Skip to content

Commit

Permalink
Get latest CI status of a commit filtered by branch
Browse files Browse the repository at this point in the history
Changes the CI status check to use the pipelines API, in order to filter
status by ref (branch).
  • Loading branch information
benjamb authored and JaimeLennox committed Apr 2, 2018
1 parent 98ee655 commit c5ce790
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 13 deletions.
16 changes: 13 additions & 3 deletions marge/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .interval import IntervalUnion
from .project import Project
from .user import User
from .pipeline import Pipeline


class MergeJob(object):
Expand Down Expand Up @@ -148,7 +149,7 @@ def sufficient_approvals():
approvals.reapprove()

if source_project.only_allow_merge_if_pipeline_succeeds:
self.wait_for_ci_to_pass(source_project.id, actual_sha)
self.wait_for_ci_to_pass(source_project.id, actual_sha, merge_request.source_branch)
log.info('CI passed!')
time.sleep(2)
try:
Expand Down Expand Up @@ -209,14 +210,23 @@ def sufficient_approvals():
self.wait_for_branch_to_be_merged()
updated_into_up_to_date_target_branch = True

def wait_for_ci_to_pass(self, source_project_id, commit_sha):
def wait_for_ci_to_pass(self, source_project_id, commit_sha, source_branch):
api = self._api
time_0 = datetime.utcnow()
waiting_time_in_secs = 10

log.info('Waiting for CI to pass')
while datetime.utcnow() - time_0 < self._options.ci_timeout:
ci_status = Commit.fetch_by_id(source_project_id, commit_sha, api).status
pipelines = Pipeline.pipelines_by_branch(source_project_id, source_branch, api)
current_pipeline = next(iter(pipelines), None)

if current_pipeline:
assert current_pipeline.sha == commit_sha
ci_status = current_pipeline.status
else:
log.warning('No pipeline listed for %s on branch %s', commit_sha, source_branch)
ci_status = None

if ci_status == 'success':
return

Expand Down
28 changes: 28 additions & 0 deletions marge/pipeline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from . import gitlab


GET = gitlab.GET


class Pipeline(gitlab.Resource):

@classmethod
def pipelines_by_branch(cls, project_id, branch, api):
pipelines_info = api.call(GET(
'/projects/{project_id}/pipelines'.format(project_id=project_id),
{'ref': branch, 'order_by': 'id', 'sort': 'desc'},
))

return [cls(api, pipeline_info) for pipeline_info in pipelines_info]

@property
def ref(self):
return self.info['ref']

@property
def sha(self):
return self.info['sha']

@property
def status(self):
return self.info['status']
10 changes: 10 additions & 0 deletions tests/gitlab_api_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ def add_approvals(self, info, sudo=None, from_state=None, to_state=None):
path = '/projects/{0.project_id}/merge_requests/{0.iid}/approvals'
self.add_resource(path, info, sudo, from_state, to_state)

def add_pipelines(self, project_id, info, sudo=None, from_state=None, to_state=None):
self.add_transition(
GET(
'/projects/%s/pipelines' % project_id,
args={'ref': info['ref'], 'order_by': 'id', 'sort': 'desc'},
),
Ok([info]),
sudo, from_state, to_state,
)

def expected_note(self, merge_request, note, sudo=None, from_state=None, to_state=None):
self.add_transition(
POST(
Expand Down
28 changes: 18 additions & 10 deletions tests/test_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ def _commit(commit_id, status):
}


def _pipeline(sha1, status):
return {
'id': 47,
'status': status,
'ref': 'useless_new_feature',
'sha': sha1,
}


class MockLab(object):
def __init__(self, gitlab_url=None):
self.gitlab_url = gitlab_url = gitlab_url or 'http://git.example.com'
Expand Down Expand Up @@ -70,15 +79,14 @@ def __init__(self, gitlab_url=None):

self.initial_master_sha = '505e'
self.rewritten_sha = rewritten_sha = 'af7a'
commit_after_pushing = _commit(commit_id=rewritten_sha, status='running')
api.add_transition(
GET('/projects/1234/repository/commits/%s' % rewritten_sha),
Ok(commit_after_pushing),
api.add_pipelines(
self.project_info['id'],
_pipeline(sha1=rewritten_sha, status='running'),
from_state='pushed', to_state='passed',
)
api.add_transition(
GET('/projects/1234/repository/commits/%s' % rewritten_sha),
Ok(_commit(commit_id=rewritten_sha, status='success')),
api.add_pipelines(
self.project_info['id'],
_pipeline(sha1=rewritten_sha, status='success'),
from_state=['passed', 'merged'],
)
api.add_transition(
Expand Down Expand Up @@ -210,9 +218,9 @@ def test_succeeds_second_time_if_master_moved(self, unused_time_sleep):
api, mocklab = self.api, self.mocklab
moved_master_sha = 'fafafa'
first_rewritten_sha = '1o1'
api.add_transition(
GET('/projects/1234/repository/commits/%s' % first_rewritten_sha),
Ok(_commit(commit_id=first_rewritten_sha, status='success')),
api.add_pipelines(
mocklab.project_info['id'],
_pipeline(sha1=first_rewritten_sha, status='success'),
from_state=['pushed_but_master_moved', 'merged_rejected'],
)
api.add_transition(
Expand Down
38 changes: 38 additions & 0 deletions tests/test_pipeline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from unittest.mock import Mock

from marge.gitlab import Api, GET
from marge.pipeline import Pipeline


INFO = {
"id": 47,
"status": "pending",
"ref": "new-pipeline",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a"
}


# pylint: disable=attribute-defined-outside-init
class TestPipeline(object):

def setup_method(self, _method):
self.api = Mock(Api)

def test_pipelines_by_branch(self):
api = self.api
pl1, pl2 = INFO, dict(INFO, id=48)
api.call = Mock(return_value=[pl1, pl2])

result = Pipeline.pipelines_by_branch(project_id=1234, branch=INFO['ref'], api=api)
api.call.assert_called_once_with(GET(
'/projects/1234/pipelines',
{'ref': INFO['ref'], 'order_by': 'id', 'sort': 'desc'},
))
assert [pl.info for pl in result] == [pl1, pl2]

def test_properties(self):
pipeline = Pipeline(api=self.api, info=INFO)
assert pipeline.id == 47
assert pipeline.status == "pending"
assert pipeline.ref == "new-pipeline"
assert pipeline.sha == "a91957a858320c0e17f3a0eca7cfacbff50ea29a"

0 comments on commit c5ce790

Please sign in to comment.