def start_ci(): """ Function that track the event occuring at the repository Events that are tracked: Push: Run the tests and update last commit Pull Request: If it is a pr, run the tests Issues: Update the status of recoded issues """ if request.method != 'POST': return 'OK' else: abort_code = 418 event = request.headers.get('X-GitHub-Event') if event == "ping": return json.dumps({'msg': 'Hi!'}) x_hub_signature = request.headers.get('X-Hub-Signature') if not is_valid_signature(x_hub_signature, request.data, g.github['ci_key']): g.log.warning('CI signature failed: %s' % x_hub_signature) abort(abort_code) payload = request.get_json() if payload is None: g.log.warning('CI payload is empty: %s' % payload) abort(abort_code) gh = GitHub(access_token=g.github['bot_token']) repository = gh.repos(g.github['repository_owner'])( g.github['repository']) if event == "push": # If it's a push, and the 'after' hash is available, then it's # a commit, so run the tests if 'after' in payload: commit = payload['after'] gh_commit = repository.statuses(commit) # Update the db to the new last commit ref = repository.git().refs('heads/master').get() last_commit = GeneralData.query.filter( GeneralData.key == 'last_commit').first() for platform in TestPlatform.values(): commit_name = 'fetch_commit_' + platform fetch_commit = GeneralData.query.filter( GeneralData.key == commit_name).first() if fetch_commit is None: prev_commit = GeneralData(commit_name, last_commit.value) g.db.add(prev_commit) last_commit.value = ref['object']['sha'] g.db.commit() queue_test(g.db, repository, gh_commit, commit, TestType.commit) else: g.log.warning('Unknown push type! Dumping payload for ' 'analysis') g.log.debug(payload) elif event == "pull_request": # If it's a PR, run the tests if payload['action'] == 'opened': try: commit = payload['pull_request']['head']['sha'] except KeyError: g.log.critical( "Didn't find a SHA value for a newly opened PR!") g.log.debug(payload) commit = '' elif payload['action'] == 'closed': g.log.debug('PR was closed, no after hash available') commit = '' else: try: commit = payload['after'] except KeyError: g.log.critical("Didn't find the after SHA for the " "updated commit!") g.log.debug(payload) commit = '' pr_nr = payload['pull_request']['number'] gh_commit = repository.statuses(commit) if payload['action'] == 'opened': # Run initial tests queue_test(g.db, repository, gh_commit, commit, TestType.pull_request, pr_nr=pr_nr) elif payload['action'] == 'synchronize': # Run/queue a new test set queue_test(g.db, repository, gh_commit, commit, TestType.pull_request, pr_nr=pr_nr) elif payload['action'] == 'closed': # Cancel running queue tests = Test.query.filter(Test.pr_nr == pr_nr).all() for test in tests: # Add canceled status only if the test hasn't started yet if len(test.progress) > 0: continue progress = TestProgress(test.id, TestStatus.canceled, "PR closed", datetime.datetime.now()) g.db.add(progress) repository.statuses(test.commit).post( state=Status.FAILURE, description="Tests canceled", context="CI - %s" % test.platform.value, target_url=url_for('test.by_id', test_id=test.id, _external=True)) elif payload['action'] == 'reopened': # Run tests again queue_test(g.db, repository, gh_commit, commit, TestType.pull_request) elif event == "issues": issue_data = payload['issue'] issue = Issue.query.filter( Issue.issue_id == issue_data['number']).first() if issue is not None: issue.title = issue_data['title'] issue.status = issue_data['state'] g.db.commit() else: # Unknown type g.log.warning('CI unrecognized event: %s' % event) return json.dumps({'msg': 'EOL'})
def start_ci(): """ Gets called when the webhook on GitHub is triggered. Reaction to the next events need to be processed (after verification): - Ping (for fun) - Push - Pull Request - Issues """ if request.method != 'POST': return 'OK' else: abort_code = 418 event = request.headers.get('X-GitHub-Event') if event == "ping": return json.dumps({'msg': 'Hi!'}) x_hub_signature = request.headers.get('X-Hub-Signature') if not is_valid_signature(x_hub_signature, request.data, g.github['ci_key']): g.log.warning( 'CI signature failed: {sig}'.format(sig=x_hub_signature)) abort(abort_code) payload = request.get_json() if payload is None: g.log.warning( 'CI payload is empty: {payload}'.format(payload=payload)) abort(abort_code) gh = GitHub(access_token=g.github['bot_token']) repository = gh.repos(g.github['repository_owner'])( g.github['repository']) if event == "push": # If it's a push, and the 'after' hash is available, then it's a commit, so run the tests if 'after' in payload: commit = payload['after'] gh_commit = repository.statuses(commit) # Update the db to the new last commit ref = repository.git().refs('heads/master').get() last_commit = GeneralData.query.filter( GeneralData.key == 'last_commit').first() for platform in TestPlatform.values(): commit_name = 'fetch_commit_' + platform fetch_commit = GeneralData.query.filter( GeneralData.key == commit_name).first() if fetch_commit is None: prev_commit = GeneralData(commit_name, last_commit.value) g.db.add(prev_commit) last_commit.value = ref['object']['sha'] g.db.commit() queue_test(g.db, gh_commit, commit, TestType.commit) else: g.log.warning( 'Unknown push type! Dumping payload for analysis') g.log.debug(payload) elif event == "pull_request": # If it's a valid PR, run the tests commit = '' gh_commit = None pr_nr = payload['pull_request']['number'] if payload['action'] in ['opened', 'synchronize', 'reopened']: try: commit = payload['pull_request']['head']['sha'] gh_commit = repository.statuses(commit) except KeyError: g.log.critical( "Didn't find a SHA value for a newly opened PR!") g.log.debug(payload) # Check if user blacklisted user_id = payload['pull_request']['user']['id'] if BlockedUsers.query.filter( BlockedUsers.userID == user_id).first() is not None: g.log.critical("User Blacklisted") gh_commit.post( state=Status.ERROR, description= "CI start aborted. You may be blocked from accessing this functionality", target_url=url_for('home.index', _external=True)) return 'ERROR' queue_test(g.db, gh_commit, commit, TestType.pull_request, pr_nr=pr_nr) elif payload['action'] == 'closed': g.log.debug('PR was closed, no after hash available') # Cancel running queue tests = Test.query.filter(Test.pr_nr == pr_nr).all() for test in tests: # Add canceled status only if the test hasn't started yet if len(test.progress) > 0: continue progress = TestProgress(test.id, TestStatus.canceled, "PR closed", datetime.datetime.now()) g.db.add(progress) repository.statuses(test.commit).post( state=Status.FAILURE, description="Tests canceled", context="CI - {name}".format(name=test.platform.value), target_url=url_for('test.by_id', test_id=test.id, _external=True)) elif event == "issues": issue_data = payload['issue'] issue = Issue.query.filter( Issue.issue_id == issue_data['number']).first() if issue is not None: issue.title = issue_data['title'] issue.status = issue_data['state'] g.db.commit() else: # Unknown type g.log.warning('CI unrecognized event: {event}'.format(event=event)) return json.dumps({'msg': 'EOL'})
def start_ci(): if request.method != 'POST': return 'OK' else: abort_code = 418 event = request.headers.get('X-GitHub-Event') if event == "ping": return json.dumps({'msg': 'Hi!'}) x_hub_signature = request.headers.get('X-Hub-Signature') if not is_valid_signature(x_hub_signature, request.data, g.github['ci_key']): g.log.warning('CI signature failed: %s' % x_hub_signature) abort(abort_code) payload = request.get_json() if payload is None: g.log.warning('CI payload is empty: %s' % payload) abort(abort_code) gh = GitHub(access_token=g.github['bot_token']) if event == "push": # If it's a push, run the tests commit = payload['after'] gh_commit = gh.repos(g.github['repository_owner'])( g.github['repository']).statuses(commit) queue_test(g.db, gh_commit, commit, TestType.commit) # Update the db to the new last commit ref = gh.repos(g.github['repository_owner'])( g.github['repository']).git().refs('heads/master').get() last_commit = GeneralData.query.filter(GeneralData.key == 'last_commit').first() last_commit.value = ref['object']['sha'] g.db.commit() elif event == "pull_request": # If it's a PR, run the tests if payload['action'] == 'opened': try: commit = payload['pull_request']['head']['sha'] except KeyError: g.log.critical( "Didn't find a SHA value for a newly opened PR!") g.log.debug(payload) commit = '' elif payload['action'] == 'closed': g.log.debug('PR was closed, no after hash available') commit = '' else: try: commit = payload['after'] except KeyError: g.log.critical("Didn't find the after SHA for the " "updated commit!") g.log.debug(payload) commit = '' pr_nr = payload['pull_request']['number'] gh_commit = gh.repos(g.github['repository_owner'])( g.github['repository']).statuses(commit) if payload['action'] == 'opened': # Run initial tests queue_test(g.db, gh_commit, commit, TestType.pull_request, pr_nr=pr_nr) elif payload['action'] == 'synchronize': # Run/queue a new test set queue_test(g.db, gh_commit, commit, TestType.pull_request, pr_nr=pr_nr) elif payload['action'] == 'closed': # Cancel running queue tests = Test.query.filter(Test.pr_nr == pr_nr).all() for test in tests: # Add canceled status only if the test hasn't started yet if len(test.progress) > 0: continue progress = TestProgress(test.id, TestStatus.canceled, "PR closed", datetime.datetime.now()) g.db.add(progress) gh.repos(g.github['repository_owner'])( g.github['repository']).statuses(test.commit).post( state=Status.FAILURE, description="Tests canceled", context="CI - %s" % test.platform.value, target_url=url_for( 'test.by_id', test_id=test.id, _external=True)) elif payload['action'] == 'reopened': # Run tests again queue_test(g.db, gh_commit, commit, TestType.pull_request) else: # Unknown type g.log.warning('CI unrecognized event: %s' % event) return json.dumps({'msg': 'EOL'})