def refresh_statuses(pulls_by_target): for pulls in pulls_by_target.values(): for gh_pr in pulls: statuses = get_repo(gh_pr.target_ref.repo.qname, 'commits/' + gh_pr.source.sha + '/statuses', status_code=200) prs.refresh_from_github_build_status( gh_pr, build_state_from_gh_json(statuses))
def refresh_reviews(pulls_by_target): for (_, pulls) in pulls_by_target.items(): for gh_pr in pulls: reviews = get_repo(gh_pr.target_ref.repo.qname, 'pulls/' + gh_pr.number + '/reviews', status_code=200) state = overall_review_state(reviews)['state'] prs.review(gh_pr, state)
def refresh_reviews(pulls_by_target): for (_, pulls) in pulls_by_target.items(): for gh_pr in pulls: reviews = get_repo( gh_pr.target_ref.repo.qname, 'pulls/' + gh_pr.number + '/reviews', status_code=200) state = overall_review_state(reviews)['state'] prs.review(gh_pr, state)
def poll_github_until_merged(pr_number, delay_in_seconds=DELAY_IN_SECONDS, max_polls=MAX_POLLS): r, status_code = get_repo( FQ_REPO, f'pulls/{pr_number}/merge', # 204 NO CONTENT means merged, 404 means not merged status_code=[204, 404], json_response=False, token=oauth_tokens['user1']) polls = 0 while status_code != 204 and polls < max_polls: time.sleep(delay_in_seconds) polls = polls + 1 _, status_code = get_repo( FQ_REPO, f'pulls/{pr_number}/merge', # 204 NO CONTENT means merged, 404 means not merged status_code=[204, 404], json_response=False, token=oauth_tokens['user1']) assert polls < max_polls, f'{polls} {max_polls}' assert status_code == 204
def get_reviews(repo, pr_number): return get_repo(repo.qname, 'pulls/' + pr_number + '/reviews', status_code=200)
def test_merges_approved_pr(tmpdir): BRANCH_NAME = 'test_merges_approved_pr' pr_number = None try: status = ci_get('/status', status_code=200) assert '_watched_targets' in status assert status['_watched_targets'] == [[{ 'repo': { 'name': REPO_NAME, 'owner': 'hail-ci-test' }, 'name': 'master' }, True]] os.chdir(tmpdir) call( [ 'git', 'clone', f'https://{oauth_tokens["user1"]}@github.com/hail-ci-test/{REPO_NAME}.git' ], # do not leak the token stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) os.chdir(REPO_NAME) call([ 'git', 'config', 'user.email', '*****@*****.**' ]) call(['git', 'config', 'user.name', 'ci-automated-tests']) call(['git', 'remote', '-v']) call(['git', 'checkout', '-b', BRANCH_NAME]) call(['git', 'commit', '--allow-empty', '-m', 'foo']) call(['git', 'push', 'origin', BRANCH_NAME]) source_sha = rev_parse(BRANCH_NAME) gh_pr = post_repo(FQ_REPO, 'pulls', json={ "title": "foo", "head": BRANCH_NAME, "base": "master" }, status_code=201) pr_number = str(gh_pr['number']) post_repo(FQ_REPO, f'pulls/{pr_number}/reviews', json={ "commit_id": source_sha, "event": "APPROVE" }, status_code=200, token=oauth_tokens['user2']) get_repo(FQ_REPO, f'pulls/{pr_number}/reviews', status_code=200, token=oauth_tokens['user1']) time.sleep(7) poll_github_until_merged(pr_number) call(['git', 'fetch', 'origin']) merged_sha = rev_parse('origin/master') # deploy job takes some time time.sleep(7) deploy_artifact = run( ['gsutil', 'cat', f'gs://hail-ci-test/{merged_sha}'], stdout=subprocess.PIPE, check=True) deploy_artifact = deploy_artifact.stdout.decode('utf-8').strip() assert f'commit {merged_sha}' in deploy_artifact finally: call(['git', 'push', 'origin', ':' + BRANCH_NAME]) if pr_number is not None: patch_repo(FQ_REPO, f'pulls/{pr_number}', json={"state": "closed"}, status_code=200)
def test_merges_approved_pr(tmpdir): BRANCH_NAME = 'test_merges_approved_pr' pr_number = None try: status = ci_get('/status', status_code=200) assert '_watched_targets' in status assert status['_watched_targets'] == [[{ 'repo': { 'name': REPO_NAME, 'owner': 'hail-ci-test'}, 'name': 'master'}, True]] os.chdir(tmpdir) call(['git', 'clone', f'https://{oauth_tokens["user1"]}@github.com/hail-ci-test/{REPO_NAME}.git'], # do not leak the token stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) os.chdir(REPO_NAME) call(['git', 'config', 'user.email', '*****@*****.**']) call(['git', 'config', 'user.name', 'ci-automated-tests']) call(['git', 'remote', '-v']) call(['git', 'checkout', '-b', BRANCH_NAME]) call(['git', 'commit', '--allow-empty', '-m', 'foo']) call(['git', 'push', 'origin', BRANCH_NAME]) source_sha = rev_parse(BRANCH_NAME) gh_pr = post_repo( FQ_REPO, 'pulls', json={ "title": "foo", "head": BRANCH_NAME, "base": "master" }, status_code=201) pr_number = str(gh_pr['number']) post_repo( FQ_REPO, f'pulls/{pr_number}/reviews', json={ "commit_id": source_sha, "event": "APPROVE" }, status_code=200, token=oauth_tokens['user2']) get_repo( FQ_REPO, f'pulls/{pr_number}/reviews', status_code=200, token=oauth_tokens['user1']) time.sleep(7) poll_github_until_merged(pr_number) call(['git', 'fetch', 'origin']) merged_sha = rev_parse('origin/master') # deploy job takes some time time.sleep(7) deploy_artifact = run(['gsutil', 'cat', f'gs://hail-ci-test/{merged_sha}'], stdout=subprocess.PIPE, check=True) deploy_artifact = deploy_artifact.stdout.decode('utf-8').strip() assert f'commit {merged_sha}' in deploy_artifact finally: call(['git', 'push', 'origin', ':' + BRANCH_NAME]) if pr_number is not None: patch_repo( FQ_REPO, f'pulls/{pr_number}', json={"state": "closed"}, status_code=200)
def test_merges_approved_pr(self): BRANCH_NAME = 'test_merges_approved_pr' with tempfile.TemporaryDirectory() as d: pr_number = None try: status = ci_get('/status', status_code=200) self.assertIn('_watched_targets', status) assert status['_watched_targets'] == [[{ 'repo': { 'name': self.repo_name, 'owner': 'hail-ci-test'}, 'name': 'master'}, True]] os.chdir(d) call(['git', 'clone', f'[email protected]:hail-ci-test/{self.repo_name}.git']) os.chdir(self.repo_name) call(['git', 'remote', '-v']) call(['git', 'checkout', '-b', BRANCH_NAME]) call(['git', 'commit', '--allow-empty', '-m', 'foo']) call(['git', 'push', 'origin', BRANCH_NAME]) source_sha = self.rev_parse(BRANCH_NAME) gh_pr = post_repo( self.fq_repo, 'pulls', json={ "title": "foo", "head": BRANCH_NAME, "base": "master" }, status_code=201) pr_number = str(gh_pr['number']) post_repo( self.fq_repo, f'pulls/{pr_number}/reviews', json={ "commit_id": source_sha, "event": "APPROVE" }, status_code=200, token=oauth_tokens['user2']) get_repo( self.fq_repo, f'pulls/{pr_number}/reviews', status_code=200, token=oauth_tokens['user1']) time.sleep(7) self.poll_github_until_merged(pr_number) call(['git', 'fetch', 'origin']) merged_sha = self.rev_parse('origin/master') # deploy job takes some time time.sleep(7) deploy_artifact = run(['gsutil', 'cat', f'gs://hail-ci-test/{merged_sha}'], stdout=subprocess.PIPE, check=True) deploy_artifact = deploy_artifact.stdout.decode('utf-8').strip() assert f'commit {merged_sha}' in deploy_artifact finally: call(['git', 'push', 'origin', ':' + BRANCH_NAME]) if pr_number is not None: patch_repo( self.fq_repo, f'pulls/{pr_number}', json={"state": "closed"}, status_code=200)
def get_reviews(repo, pr_number): return get_repo( repo.qname, 'pulls/' + pr_number + '/reviews', status_code=200)
def latest_sha_for_ref(ref): d = get_repo(ref.repo.qname, f'git/refs/heads/{ref.name}', status_code=200) assert 'object' in d, d assert 'sha' in d['object'], d return d['object']['sha']
def open_pulls(target_repo): return get_repo(target_repo.qname, 'pulls?state=open', status_code=200)