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
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
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
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