Skip to content

Commit

Permalink
Merge branch 'feature/RELENG-4453/check-github-ci' into q/3.6
Browse files Browse the repository at this point in the history
  • Loading branch information
bert-e committed May 18, 2021
2 parents 708fa13 + 498a4a6 commit 7a3755d
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 5 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Change Log
All notable changes to this project will be documented in this file.

## [3.6.0] - 2021-04-27
# Added
- Support GitHub Action CI thanks to a new build key config `github_actions`



## [3.5.0] - 2021-04-27
# Added
- Add "pr_author_options" option to config, which add bypass to a specifique user
Expand Down
82 changes: 82 additions & 0 deletions bert_e/git_host/github/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,12 @@ def get_commit_status(self, ref):
combined = AggregatedStatus.get(self.client,
owner=self.owner,
repo=self.slug, ref=ref)

actions = AggregatedCheckSuites.get(self.client,
owner=self.owner,
repo=self.slug, ref=ref)
combined.status[actions.key] = actions

except HTTPError as err:
if err.response.status_code == 404:
return None
Expand Down Expand Up @@ -501,6 +507,82 @@ def __str__(self) -> str:
return self.state


class AggregatedCheckRuns(base.AbstractGitHostObject):
"""
The Endpoint to have access infos about github actions runs
"""
GET_URL = '/repos/{owner}/{repo}/commits/{ref}/check-runs'
SCHEMA = schema.AggregateCheckRuns

@property
def html_url(self):
if self.data['total_count']:
return self.data['check_runs'][0]['html_url']
return ''


class AggregatedCheckSuites(base.AbstractGitHostObject,
base.AbstractBuildStatus):
"""
The Endpoint to have access infos about github actions suites
"""
GET_URL = '/repos/{owner}/{repo}/commits/{ref}/check-suites'
SCHEMA = schema.AggregateCheckSuites

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._check_suites = [elem for elem in self.data['check_suites']]

@classmethod
def get(cls, client, url=None, params={}, headers={}, **kwargs):
res = super(AggregatedCheckSuites, cls)\
.get(client, url, params, headers, **kwargs)

html_url = AggregatedCheckRuns\
.get(client, url, params, headers, **kwargs).html_url
res.data['html_url'] = html_url
return res

@property
def url(self):
return self.data['html_url']

@property
def state(self):
queued = any(
elem['status'] == 'queued' for elem in self._check_suites
)
all_complete = all(
elem['status'] == 'completed' for elem in self._check_suites
)
all_success = all(
elem['conclusion'] == 'success' for elem in self._check_suites
)
if self._check_suites.__len__() > 0 and queued:
return 'NOTSTARTED'
elif self._check_suites.__len__() > 0 and not all_complete:
return 'INPROGRESS'
elif self._check_suites.__len__() > 0 and all_complete and all_success:
return 'SUCCESSFUL'
else:
return 'FAILED'

@property
def description(self) -> str:
return 'github actions CI'

@property
def key(self) -> str:
return 'github_actions'

@property
def commit(self):
if self._check_suites.__len__() > 0:
return self._check_suites[0]["head_sha"]
else:
return None


class PullRequest(base.AbstractGitHostObject, base.AbstractPullRequest):
LIST_URL = '/repos/{owner}/{repo}/pulls'
GET_URL = '/repos/{owner}/{repo}/pulls/{number}'
Expand Down
25 changes: 25 additions & 0 deletions bert_e/git_host/github/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,31 @@ class Branch(Schema):
repo = fields.Nested(Repo)


class CheckSuites(Schema):
id = fields.Integer()
head_sha = fields.Str()
status = fields.Str()
conclusion = fields.Str(allow_none=True)


class AggregateCheckSuites(Schema):
total_count = fields.Integer()
check_suites = fields.Nested(CheckSuites, many=True)


class CheckRuns(Schema):
id = fields.Integer()
head_sha = fields.Str()
status = fields.Str()
conclusion = fields.Str(allow_none=True)
html_url = fields.Url()


class AggregateCheckRuns(Schema):
total_count = fields.Integer()
check_runs = fields.Nested(CheckRuns, many=True)


class PullRequest(Schema):
number = fields.Int(required=True)
url = fields.Url()
Expand Down
3 changes: 3 additions & 0 deletions bert_e/tests/assets/workflow-error.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: basic tests

on:
11 changes: 11 additions & 0 deletions bert_e/tests/assets/workflow-fail.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: basic tests

on: push

jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- run: exit 1
20 changes: 20 additions & 0 deletions bert_e/tests/assets/workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: basic tests

on: push

jobs:
first:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- run: exit 0

second:
needs:
- first
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- run: exit 0
138 changes: 133 additions & 5 deletions bert_e/tests/test_bert_e.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import argparse
import logging
import os.path
import re
import sys
import time
Expand Down Expand Up @@ -157,13 +158,20 @@ def create_branch(repo, name, from_branch=None, file_=False, do_push=True):
add_file_to_branch(repo, name, file_, do_push)


def add_file_to_branch(repo, branch_name, file_name, do_push=True):
repo.cmd('git checkout ' + branch_name)
def add_file_to_branch(repo, branch_name, file_name, do_push=True, folder='.'):
if file_name is True:
file_name = 'file_created_on_' + branch_name.replace('/', '_')
repo.cmd('echo %s > %s' % (branch_name, file_name))
repo.cmd('git add ' + file_name)
repo.cmd('git commit -m "adds %s file on %s"' % (file_name, branch_name))

file_path = os.path.dirname(os.path.abspath(__file__))

repo.cmd(f'git checkout {branch_name}')
repo.cmd(f'mkdir -p {folder}')
if os.path.isfile(f'{file_path}/assets/{file_name}'):
repo.cmd(f'cp {file_path}/assets/{file_name} {folder}/{file_name}')
else:
repo.cmd(f'echo {branch_name} > {file_name}')
repo.cmd(f'git add {folder}/{file_name}')
repo.cmd(f'git commit -m "adds %s file on %s"' % (file_name, branch_name))
if do_push:
repo.cmd('git pull || exit 0')
repo.cmd('git push --set-upstream origin ' + branch_name)
Expand Down Expand Up @@ -3187,6 +3195,126 @@ def test_source_branch_history_changed(self):
options=self.bypass_all_but(['bypass_build_status']),
backtrace=True)

def test_github_actions_result_error(self):
if self.args.git_host != 'github':
self.skipTest("GitHub Actions is only supported with GitHub")

settings = """
repository_owner: {owner}
repository_slug: {slug}
repository_host: {host}
robot: {robot}
robot_email: nobody@nowhere.com
pull_request_base_url: https://bitbucket.org/{owner}/{slug}/bar/pull-requests/{{pr_id}}
commit_base_url: https://bitbucket.org/{owner}/{slug}/commits/{{commit_id}}
build_key: github_actions
always_create_integration_pull_requests: False
""" # noqa
pr = self.create_pr('bugfix/TEST-00001', 'development/4.3')
add_file_to_branch(self.gitrepo,
'bugfix/TEST-00001',
'workflow-error.yml',
do_push=True,
folder='.github/workflows')
add_file_to_branch(self.gitrepo,
'bugfix/TEST-00001',
'workflow.yml',
do_push=True,
folder='.github/workflows')

for index in range(0, 60):
try:
with self.assertRaises(exns.BuildFailed):
self.handle(
pr.id, settings=settings,
options=self.bypass_all_but(['bypass_build_status']),
backtrace=True)
except Exception:
if index == 59:
raise exns.BuildFailed()
time.sleep(2)
else:
break

def test_github_actions_result_fail(self):
"""
To check the return of github action we are adding one workflow
that will succeed and an other with a failure.
We should have an build status error at the end.
"""
if self.args.git_host != 'github':
self.skipTest("GitHub Actions is only supported with GitHub")

settings = """
repository_owner: {owner}
repository_slug: {slug}
repository_host: {host}
robot: {robot}
robot_email: nobody@nowhere.com
pull_request_base_url: https://bitbucket.org/{owner}/{slug}/bar/pull-requests/{{pr_id}}
commit_base_url: https://bitbucket.org/{owner}/{slug}/commits/{{commit_id}}
build_key: github_actions
always_create_integration_pull_requests: False
""" # noqa
pr = self.create_pr('bugfix/TEST-00001', 'development/4.3')
add_file_to_branch(self.gitrepo,
'bugfix/TEST-00001',
'workflow-fail.yml',
do_push=True,
folder='.github/workflows')

for index in range(0, 60):
try:
with self.assertRaises(exns.BuildFailed):
self.handle(
pr.id, settings=settings,
options=self.bypass_all_but(['bypass_build_status']),
backtrace=True)

except Exception:
if index == 59:
raise exns.BuildFailed()
time.sleep(4)
else:
break

def test_github_actions_result(self):
if self.args.git_host != 'github':
self.skipTest("GitHub Actions is only supported with GitHub")

settings = """
repository_owner: {owner}
repository_slug: {slug}
repository_host: {host}
robot: {robot}
robot_email: nobody@nowhere.com
pull_request_base_url: https://bitbucket.org/{owner}/{slug}/bar/pull-requests/{{pr_id}}
commit_base_url: https://bitbucket.org/{owner}/{slug}/commits/{{commit_id}}
build_key: github_actions
always_create_integration_pull_requests: False
""" # noqa
pr = self.create_pr('bugfix/TEST-00001', 'development/4.3')
add_file_to_branch(self.gitrepo,
'bugfix/TEST-00001',
'workflow.yml',
do_push=True,
folder='.github/workflows')

for index in range(0, 60):
try:
with self.assertRaises(exns.SuccessMessage):
self.handle(
pr.id, settings=settings,
options=self.bypass_all_but(['bypass_build_status']),
backtrace=True)

except Exception:
if index == 59:
raise exns.BuildFailed()
time.sleep(2)
else:
break

def test_source_branch_commit_added_and_target_updated(self):
pr = self.create_pr('bugfix/TEST-00001', 'development/4.3')
pr2 = self.create_pr('bugfix/TEST-00002', 'development/4.3')
Expand Down
1 change: 1 addition & 0 deletions settings.sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ commit_base_url: https://bitbucket.org/foo/bar/commits/{commit_id}

# build_key [OPTIONAL]:
# The label of the key to look for in githost commit statuses.
# The key "github_actions" can be set to check github actions status instead of external app checks
#
# default value: pre-merge
#
Expand Down

0 comments on commit 7a3755d

Please sign in to comment.