Merge "Retry queries for commits"

This commit is contained in:
Zuul 2018-11-27 22:35:27 +00:00 committed by Gerrit Code Review
commit 8a58a358d1
3 changed files with 68 additions and 1 deletions

View File

@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import github3.exceptions
import re
FAKE_BASE_URL = 'https://example.com/api/v3/'
@ -82,6 +83,9 @@ class FakeRepository(object):
self.data = data
self.name = name
# fail the next commit requests with 404
self.fail_not_found = 0
def branches(self, protected=False):
if protected:
# simulate there is no protected branch
@ -121,6 +125,25 @@ class FakeRepository(object):
commit.set_status(state, url, description, context, user)
def commit(self, sha):
if self.fail_not_found > 0:
self.fail_not_found -= 1
class Response:
status_code = 0
message = ''
def json(self):
return {
'message': self.message
}
resp = Response()
resp.status_code = 404
resp.message = 'Not Found'
raise github3.exceptions.NotFoundError(resp)
commit = self._commits.get(sha, None)
if commit is None:
commit = FakeCommit(sha)

View File

@ -1000,6 +1000,37 @@ class TestGithubDriver(ZuulTestCase):
self.assertEquals('https://github.com/org/project/pull/1',
job2_params['zuul']['items'][0]['change_url'])
@simple_layout('layouts/basic-github.yaml', driver='github')
def test_pull_commit_race(self):
"""Test graceful handling of delayed availability of commits"""
github = self.fake_github.getGithubClient('org/project')
repo = github.repo_from_project('org/project')
repo.fail_not_found = 1
A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
self.waitUntilSettled()
self.assertEqual('SUCCESS',
self.getJobFromHistory('project-test1').result)
self.assertEqual('SUCCESS',
self.getJobFromHistory('project-test2').result)
job = self.getJobFromHistory('project-test2')
zuulvars = job.parameters['zuul']
self.assertEqual(str(A.number), zuulvars['change'])
self.assertEqual(str(A.head_sha), zuulvars['patchset'])
self.assertEqual('master', zuulvars['branch'])
self.assertEqual(1, len(A.comments))
self.assertThat(
A.comments[0],
MatchesRegex(r'.*\[project-test1 \]\(.*\).*', re.DOTALL))
self.assertThat(
A.comments[0],
MatchesRegex(r'.*\[project-test2 \]\(.*\).*', re.DOTALL))
self.assertEqual(2, len(self.history))
class TestGithubUnprotectedBranches(ZuulTestCase):
config_file = 'zuul-github-driver.conf'

View File

@ -1322,11 +1322,24 @@ class GithubConnection(BaseConnection):
if not result:
raise Exception('Pull request was not merged')
def _getCommit(self, repository, sha, retries=5):
try:
return repository.commit(sha)
except github3.exceptions.NotFoundError:
self.log.warning("Commit %s of project %s returned None",
sha, repository.name)
if retries <= 0:
raise
time.sleep(1)
return self._getCommit(repository, sha, retries - 1)
def getCommitStatuses(self, project, sha):
github = self.getGithubClient(project)
owner, proj = project.split('/')
repository = github.repository(owner, proj)
commit = repository.commit(sha)
commit = self._getCommit(repository, sha, 5)
# make a list out of the statuses so that we complete our
# API transaction
statuses = [status.as_dict() for status in commit.statuses()]