Example #1
0
def add_pull_request():
    is_authorized = validate_hmac_signature(
        request.data, request.headers.get('X_HUB_SIGNATURE'))

    if not is_authorized:
        return 'Invalid Authorization Signature.', 401

    db = g.db
    models = g.models
    schema = {
        '$schema': 'http://json-schema.org/schema#',
        'title': 'Pull Request Event',
        'type': 'object',
        'properties': {
            'pull_request': {
                'type': 'object',
            },
        },
        'required': ['pull_request'],
    }
    data = request.get_json(force=True)
    validate(data, schema)

    pr = add_pr_to_session(data['pull_request'], db, models)

    route_response = update_github_comment(pr)
    db.session.commit()
    return route_response
Example #2
0
def update_test_mirror():
    db = g.db
    models = g.models
    schema = None

    if request.method == 'DELETE':
        schema = {
            '$schema': 'http://json-schema.org/schema#',
            'title': 'PR Mirrored Event',
            'type': 'object',
            'properties': {
                'issue_number': {
                    'type': 'integer'
                },
            },
            'required': ['issue_number', 'url'],
        }
    else:
        schema = {
            '$schema': 'http://json-schema.org/schema#',
            'title': 'PR Mirrored Event',
            'type': 'object',
            'properties': {
                'issue_number': {
                    'type': 'integer'
                },
                'url': {
                    'type': 'string'
                }
            },
            'required': ['issue_number', 'url'],
        }

    data = request.get_json(force=True)
    validate(data, schema)

    pr = models.get(db.session,
                    models.PullRequest,
                    number=data['issue_number'])

    if not pr:
        return 'Pull request data for this mirror does not exist in the database.', 422

    pr.mirror = pr.mirror or models.TestMirror()
    pr.mirror.url = data['url'] if request.method == 'POST' else None

    route_response = update_github_comment(pr)
    db.session.commit()
    return route_response
Example #3
0
def add_stability_check():
    db = g.db
    models = g.models
    schema = {
        'type': 'object',
        'properties': {
            'pull': {
                'type': 'object',
                'properties': {
                    'number': {
                        'type': 'integer'
                    },
                    'sha': {
                        'type': 'string'
                    },
                },
                'required': ['number', 'sha'],
            },
            'job': {
                'type': 'object',
                'properties': {
                    'id': {
                        'type': 'integer'
                    },
                    'number': {
                        'type': 'string'
                    },
                    'allow_failure': {
                        'type': 'boolean'
                    },
                    'status': {
                        'type':
                        'string',
                        'enum': [
                            'created', 'queued', 'started', 'passed', 'failed',
                            'errored', 'finished'
                        ]
                    },
                },
                'required': [
                    'id',
                    'number',
                    'allow_failure',
                    'status',
                ],
            },
            'build': {
                'type': 'object',
                'properties': {
                    'id': {
                        'type': 'integer'
                    },
                    'number': {
                        'type': 'string'
                    },
                },
                'required': [
                    'id',
                    'number',
                ],
            },
            'product': {
                'type': 'string',
                'maxLength': 255,
            },
            'iterations': {
                'type': 'integer'
            },
            'message': {
                'type': 'string'
            },
            'results': {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'properties': {
                        'result': {
                            'type': 'object',
                            'properties': {
                                'status': {
                                    'type': 'object',
                                    'patternProperties': {
                                        '^(?:pass|fail|ok|timeout|error|notrun|crash)$':
                                        {
                                            'type': 'integer'
                                        },
                                    },
                                },
                                'subtests': {
                                    'type': 'array',
                                    'items': {
                                        'type': 'object',
                                        'properties': {
                                            'result': {
                                                'type': 'object',
                                                'properties': {
                                                    'status': {
                                                        'type': 'object',
                                                        'patternProperties': {
                                                            '^(?:pass|fail|ok|timeout|error|notrun|crash)$':
                                                            {
                                                                'type':
                                                                'integer'
                                                            },
                                                        },
                                                    },
                                                    'messages': {
                                                        'type': 'array',
                                                        'items': {
                                                            'type': 'string'
                                                        },
                                                    },
                                                },
                                                'required':
                                                ['status', 'messages'],
                                            },
                                            'test': {
                                                'type': 'string',
                                            },
                                        },
                                        'required': ['result', 'test'],
                                    },
                                },
                            },
                            'required': ['status'],
                        },
                        'test': {
                            'type': 'string',
                        },
                    },
                    'required': ['test', 'result'],
                },
            },
        },
        'required':
        ['pull', 'job', 'build', 'product', 'iterations', 'results']
    }

    data = request.get_json(force=True)
    validate(data, schema)

    pr_number = data['pull']['number']

    pr = models.get(
        db.session,
        models.PullRequest,
        number=pr_number,
    )

    if not pr:
        github = GitHub()
        pr_data = github.get_pr(pr_number)
        pr = add_pr_to_session(pr_data, db, models)

    build, _ = models.get_or_create(db.session,
                                    models.Build,
                                    id=data['build']['id'])
    build.number = int(data['build']['number'])
    build.pull_request = pr
    build.head_sha = data['pull']['sha']
    build.status = build.status or models.BuildStatus.from_string('pending')

    product_name = normalize_product_name(data['product'])
    product, _ = models.get_or_create(db.session,
                                      models.Product,
                                      name=product_name)

    job, _ = models.get_or_create(db.session, models.Job, id=data['job']['id'])
    job.number = data['job']['number']
    job.allow_failure = data['job']['allow_failure']
    job.build = build
    job.product = product
    job.message = data.get('message', None)
    job.state = models.JobStatus.from_string(data['job']['status'])

    for test_data in data.get('results', []):
        test, _ = models.get_or_create(db.session,
                                       models.Test,
                                       id=test_data['test'])

        test_result, _ = models.get_or_create(
            db.session,
            models.JobResult,
            test_id=test.id,
            job_id=job.id,
        )
        test_result.iterations = data['iterations']
        test_result.consistent = True

        for status_name, count in test_data['result']['status'].items():
            status, _ = models.get_or_create(
                db.session,
                models.StabilityStatus,
                job_id=job.id,
                test_id=test.id,
                status=models.TestStatus.from_string(status_name))
            status.count = count
            if (count < data['iterations']):
                test_result.consistent = False

        for subtest_data in test_data['result'].get('subtests', []):
            subtest, _ = models.get_or_create(db.session,
                                              models.Test,
                                              id=subtest_data['test'])
            subtest.parent = test

            subtest_result, _ = models.get_or_create(
                db.session,
                models.JobResult,
                test_id=subtest.id,
                job_id=job.id,
            )
            subtest_result.iterations = data['iterations']
            subtest_result.messages = json.dumps(
                subtest_data['result']['messages'])
            subtest_result.consistent = True

            for subtest_status_name, count in subtest_data['result'][
                    'status'].items():
                subtest_status, _ = models.get_or_create(
                    db.session,
                    models.StabilityStatus,
                    job_id=job.id,
                    test_id=subtest.id,
                    status=models.TestStatus.from_string(subtest_status_name))
                subtest_status.count = count
                if (count < data['iterations']):
                    subtest_result.consistent = False
                    test_result.consistent = False

    route_response = update_github_comment(pr)
    db.session.commit()
    return route_response
Example #4
0
def add_build():
    db = g.db
    models = g.models
    schema = {
        '$schema':
        'http://json-schema.org/schema#',
        'title':
        'Travis Build Event',
        'type':
        'object',
        'definitions': {
            'date_time': {
                'type': 'string',
                'format': 'date-time',
            },
        },
        'properties': {
            'id': {
                'type': 'integer'
            },
            'number': {
                'type': 'string'
            },
            'head_commit': {
                'type': 'string'
            },
            'base_commit': {
                'type': 'string'
            },
            'pull_request': {
                'type': 'boolean'
            },
            'pull_request_number': {
                'oneOf': [
                    {
                        'type': 'integer'
                    },
                    {
                        'type': 'null'
                    },
                ]
            },
            'status_message': {
                'enum': [
                    'Pending', 'Passed', 'Fixed', 'Broken', 'Failed',
                    'Still Failing', 'Canceled', 'Errored'
                ],
            },
            'started_at': {
                '$ref': '#/definitions/date_time'
            },
            'finished_at': {
                '$ref': '#/definitions/date_time'
            },
            'repository': {
                'type': 'object',
                'properties': {
                    'name': {
                        'type': 'string'
                    },
                    'owner_name': {
                        'type': 'string'
                    },
                },
                'required': ['name', 'owner_name'],
            },
            'matrix': {
                'type': 'array',
                'items': {
                    'type':
                    'object',
                    'properties': {
                        'id': {
                            'type': 'integer'
                        },
                        'number': {
                            'type': 'string'
                        },
                        'state': {
                            'type':
                            'string',
                            'enum': [
                                'created', 'queued', 'started', 'passed',
                                'failed', 'errored', 'finished'
                            ]
                        },
                        'started_at': {
                            'oneOf': [
                                {
                                    '$ref': '#/definitions/date_time'
                                },
                                {
                                    'type': 'null'
                                },
                            ]
                        },
                        'finished_at': {
                            'oneOf': [
                                {
                                    '$ref': '#/definitions/date_time'
                                },
                                {
                                    'type': 'null'
                                },
                            ]
                        },
                        'allow_failure': {
                            'type': 'boolean'
                        },
                        'config': {
                            'type': 'object'
                        },
                    },
                    'required': [
                        'id', 'number', 'state', 'started_at', 'config',
                        'allow_failure'
                    ]
                }
            }
        },
        'required': [
            'id', 'number', 'head_commit', 'base_commit', 'pull_request',
            'pull_request_number', 'status', 'repository'
        ],
    }

    travis = Travis()

    # The payload comes in the request, but we need to make sure it is
    # really signed by Travis CI. If not, respond to this request with
    # an error.
    resp = validate(json.loads(request.form['payload']), schema)

    verified_payload = travis.get_verified_payload(
        request.form['payload'], request.headers['SIGNATURE'])
    error = verified_payload.get('error')
    if error:
        return error.get('message'), error.get('code')

    # Ensure only builds for this repository can post here.
    repository = verified_payload.get("repository")
    owner_name = repository.get("owner_name")
    repo_name = repository.get("name")
    if owner_name != ORG or repo_name != REPO:
        return "Forbidden: Repository Mismatch. Build for %s/%s attempting to comment on %s/%s" % (
            owner_name, repo_name, ORG, REPO), 403

    pr_number = verified_payload['pull_request_number']

    pr = models.get(
        db.session,
        models.PullRequest,
        number=pr_number,
    )

    if not pr:
        github = GitHub()
        pr_data = github.get_pr(pr_number)
        pr = add_pr_to_session(pr_data, db, models)

    head_commit, _ = models.get_or_create(db.session,
                                          models.Commit,
                                          sha=verified_payload['head_commit'])

    base_commit, _ = models.get_or_create(db.session,
                                          models.Commit,
                                          sha=verified_payload['base_commit'])

    build, _ = models.get_or_create(db.session,
                                    models.Build,
                                    id=verified_payload['id'])
    build.number = int(verified_payload['number'])
    build.pull_request = pr
    build.head_commit = head_commit
    build.base_commit = base_commit
    build.status = models.BuildStatus.from_string(
        verified_payload['status_message'])
    if verified_payload['started_at']:
        build.started_at = datetime.strptime(verified_payload['started_at'],
                                             DATETIME_FORMAT)

    if verified_payload['finished_at']:
        build.finished_at = datetime.strptime(verified_payload['finished_at'],
                                              DATETIME_FORMAT)

    for job_data in verified_payload['matrix']:
        add_job_to_session(job_data, build, db, models)

    route_response = update_github_comment(pr)
    db.session.commit()
    return route_response