Browse Source

Merge "Retry queries for commits"

tags/3.3.1
Zuul 5 months ago
parent
commit
8a58a358d1
3 changed files with 68 additions and 1 deletions
  1. 23
    0
      tests/fakegithub.py
  2. 31
    0
      tests/unit/test_github_driver.py
  3. 14
    1
      zuul/driver/github/githubconnection.py

+ 23
- 0
tests/fakegithub.py View File

@@ -14,6 +14,7 @@
14 14
 # License for the specific language governing permissions and limitations
15 15
 # under the License.
16 16
 
17
+import github3.exceptions
17 18
 import re
18 19
 
19 20
 FAKE_BASE_URL = 'https://example.com/api/v3/'
@@ -82,6 +83,9 @@ class FakeRepository(object):
82 83
         self.data = data
83 84
         self.name = name
84 85
 
86
+        # fail the next commit requests with 404
87
+        self.fail_not_found = 0
88
+
85 89
     def branches(self, protected=False):
86 90
         if protected:
87 91
             # simulate there is no protected branch
@@ -121,6 +125,25 @@ class FakeRepository(object):
121 125
         commit.set_status(state, url, description, context, user)
122 126
 
123 127
     def commit(self, sha):
128
+
129
+        if self.fail_not_found > 0:
130
+            self.fail_not_found -= 1
131
+
132
+            class Response:
133
+                status_code = 0
134
+                message = ''
135
+
136
+                def json(self):
137
+                    return {
138
+                        'message': self.message
139
+                    }
140
+
141
+            resp = Response()
142
+            resp.status_code = 404
143
+            resp.message = 'Not Found'
144
+
145
+            raise github3.exceptions.NotFoundError(resp)
146
+
124 147
         commit = self._commits.get(sha, None)
125 148
         if commit is None:
126 149
             commit = FakeCommit(sha)

+ 31
- 0
tests/unit/test_github_driver.py View File

@@ -1000,6 +1000,37 @@ class TestGithubDriver(ZuulTestCase):
1000 1000
         self.assertEquals('https://github.com/org/project/pull/1',
1001 1001
                           job2_params['zuul']['items'][0]['change_url'])
1002 1002
 
1003
+    @simple_layout('layouts/basic-github.yaml', driver='github')
1004
+    def test_pull_commit_race(self):
1005
+        """Test graceful handling of delayed availability of commits"""
1006
+
1007
+        github = self.fake_github.getGithubClient('org/project')
1008
+        repo = github.repo_from_project('org/project')
1009
+        repo.fail_not_found = 1
1010
+
1011
+        A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
1012
+        self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
1013
+        self.waitUntilSettled()
1014
+
1015
+        self.assertEqual('SUCCESS',
1016
+                         self.getJobFromHistory('project-test1').result)
1017
+        self.assertEqual('SUCCESS',
1018
+                         self.getJobFromHistory('project-test2').result)
1019
+
1020
+        job = self.getJobFromHistory('project-test2')
1021
+        zuulvars = job.parameters['zuul']
1022
+        self.assertEqual(str(A.number), zuulvars['change'])
1023
+        self.assertEqual(str(A.head_sha), zuulvars['patchset'])
1024
+        self.assertEqual('master', zuulvars['branch'])
1025
+        self.assertEqual(1, len(A.comments))
1026
+        self.assertThat(
1027
+            A.comments[0],
1028
+            MatchesRegex(r'.*\[project-test1 \]\(.*\).*', re.DOTALL))
1029
+        self.assertThat(
1030
+            A.comments[0],
1031
+            MatchesRegex(r'.*\[project-test2 \]\(.*\).*', re.DOTALL))
1032
+        self.assertEqual(2, len(self.history))
1033
+
1003 1034
 
1004 1035
 class TestGithubUnprotectedBranches(ZuulTestCase):
1005 1036
     config_file = 'zuul-github-driver.conf'

+ 14
- 1
zuul/driver/github/githubconnection.py View File

@@ -1322,11 +1322,24 @@ class GithubConnection(BaseConnection):
1322 1322
         if not result:
1323 1323
             raise Exception('Pull request was not merged')
1324 1324
 
1325
+    def _getCommit(self, repository, sha, retries=5):
1326
+        try:
1327
+            return repository.commit(sha)
1328
+        except github3.exceptions.NotFoundError:
1329
+            self.log.warning("Commit %s of project %s returned None",
1330
+                             sha, repository.name)
1331
+            if retries <= 0:
1332
+                raise
1333
+            time.sleep(1)
1334
+            return self._getCommit(repository, sha, retries - 1)
1335
+
1325 1336
     def getCommitStatuses(self, project, sha):
1326 1337
         github = self.getGithubClient(project)
1327 1338
         owner, proj = project.split('/')
1328 1339
         repository = github.repository(owner, proj)
1329
-        commit = repository.commit(sha)
1340
+
1341
+        commit = self._getCommit(repository, sha, 5)
1342
+
1330 1343
         # make a list out of the statuses so that we complete our
1331 1344
         # API transaction
1332 1345
         statuses = [status.as_dict() for status in commit.statuses()]

Loading…
Cancel
Save