Merge lp:~cjwatson/launchpad/github-use-issue-number into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18927
Proposed branch: lp:~cjwatson/launchpad/github-use-issue-number
Merge into: lp:launchpad
Diff against target: 149 lines (+27/-23)
2 files modified
lib/lp/bugs/externalbugtracker/github.py (+4/-4)
lib/lp/bugs/externalbugtracker/tests/test_github.py (+23/-19)
To merge this branch: bzr merge lp:~cjwatson/launchpad/github-use-issue-number
Reviewer Review Type Date Requested Status
Tom Wardill (community) Approve
Launchpad code reviewers Pending
Review via email: mp+366083@code.launchpad.net

Commit message

Expect the upstream bug ID in the "number" field of GitHub issue objects, not the "id" field.

Description of the change

I'm not sure how this ever worked. Possibly GitHub changed the semantics of the "id" field? It seems to now be a fairly arbitrary integer that we shouldn't be using for anything meaningful on our end, much like the distinction between "id" and "iid" in GitLab:

  $ curl -s https://api.github.com/repos/calamares/calamares/issues?state=all | jq -c '.[:3] | .[] | {url, id, number}'
  {"url":"https://api.github.com/repos/calamares/calamares/issues/1123","id":433299827,"number":1123}
  {"url":"https://api.github.com/repos/calamares/calamares/issues/1122","id":433268843,"number":1122}
  {"url":"https://api.github.com/repos/calamares/calamares/issues/1121","id":433115193,"number":1121}

https://developer.github.com/v3/issues/ documents the number field, albeit only in its example responses.

To post a comment you must log in.
Revision history for this message
Tom Wardill (twom) wrote :

Change lgtm. Wonder if the id field is now a global ID, rather than a repo specific id?

review: Approve
Revision history for this message
Colin Watson (cjwatson) wrote :

Yeah, it seems to be exactly that. Just confusing that this didn't come up before.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/externalbugtracker/github.py'
2--- lib/lp/bugs/externalbugtracker/github.py 2018-07-13 12:48:19 +0000
3+++ lib/lp/bugs/externalbugtracker/github.py 2019-04-15 23:23:49 +0000
4@@ -1,4 +1,4 @@
5-# Copyright 2016-2018 Canonical Ltd. This software is licensed under the
6+# Copyright 2016-2019 Canonical Ltd. This software is licensed under the
7 # GNU Affero General Public License version 3 (see the file LICENSE).
8
9 """GitHub ExternalBugTracker utility."""
10@@ -183,10 +183,10 @@
11 for remote_bug in self._getCollection(page):
12 # We're only interested in the bug if it's one of the ones in
13 # bug_ids.
14- if remote_bug["id"] not in bug_ids:
15+ if remote_bug["number"] not in bug_ids:
16 continue
17- bugs[remote_bug["id"]] = remote_bug
18- self.cached_bugs[remote_bug["id"]] = remote_bug
19+ bugs[remote_bug["number"]] = remote_bug
20+ self.cached_bugs[remote_bug["number"]] = remote_bug
21 return bugs
22
23 def getRemoteImportance(self, bug_id):
24
25=== modified file 'lib/lp/bugs/externalbugtracker/tests/test_github.py'
26--- lib/lp/bugs/externalbugtracker/tests/test_github.py 2018-06-22 21:10:36 +0000
27+++ lib/lp/bugs/externalbugtracker/tests/test_github.py 2019-04-15 23:23:49 +0000
28@@ -1,4 +1,4 @@
29-# Copyright 2016-2018 Canonical Ltd. This software is licensed under the
30+# Copyright 2016-2019 Canonical Ltd. This software is licensed under the
31 # GNU Affero General Public License version 3 (see the file LICENSE).
32
33 """Tests for the GitHub Issues BugTracker."""
34@@ -138,12 +138,14 @@
35 super(TestGitHub, self).setUp()
36 self.addCleanup(getUtility(IGitHubRateLimit).clearCache)
37 self.sample_bugs = [
38- {"id": 1, "state": "open", "labels": []},
39- {"id": 2, "state": "open", "labels": [{"name": "feature"}]},
40- {"id": 3, "state": "open",
41+ {"id": 101, "number": 1, "state": "open", "labels": []},
42+ {"id": 102, "number": 2, "state": "open",
43+ "labels": [{"name": "feature"}]},
44+ {"id": 103, "number": 3, "state": "open",
45 "labels": [{"name": "feature"}, {"name": "ui"}]},
46- {"id": 4, "state": "closed", "labels": []},
47- {"id": 5, "state": "closed", "labels": [{"name": "feature"}]},
48+ {"id": 104, "number": 4, "state": "closed", "labels": []},
49+ {"id": 105, "number": 5, "state": "closed",
50+ "labels": [{"name": "feature"}]},
51 ]
52
53 def test_implements_interface(self):
54@@ -220,7 +222,7 @@
55 self._addIssuesResponse()
56 tracker = GitHub("https://github.com/user/repository/issues")
57 self.assertEqual(
58- {bug["id"]: bug for bug in self.sample_bugs[:2]},
59+ {bug["number"]: bug for bug in self.sample_bugs[:2]},
60 tracker.getRemoteBugBatch(["1", "2"]))
61 self.assertEqual(
62 "https://api.github.com/repos/user/repository/issues?state=all",
63@@ -233,7 +235,7 @@
64 tracker = GitHub("https://github.com/user/repository/issues")
65 since = datetime(2015, 1, 1, 12, 0, 0, tzinfo=pytz.UTC)
66 self.assertEqual(
67- {bug["id"]: bug for bug in self.sample_bugs[:2]},
68+ {bug["number"]: bug for bug in self.sample_bugs[:2]},
69 tracker.getRemoteBugBatch(["1", "2"], last_accessed=since))
70 self.assertEqual(
71 "https://api.github.com/repos/user/repository/issues?"
72@@ -246,10 +248,10 @@
73 self._addIssuesResponse()
74 tracker = GitHub("https://github.com/user/repository/issues")
75 tracker.initializeRemoteBugDB(
76- [str(bug["id"]) for bug in self.sample_bugs])
77+ [str(bug["number"]) for bug in self.sample_bugs])
78 responses.reset()
79 self.assertEqual(
80- {bug["id"]: bug for bug in self.sample_bugs[:2]},
81+ {bug["number"]: bug for bug in self.sample_bugs[:2]},
82 tracker.getRemoteBugBatch(["1", "2"]))
83 self.assertEqual(0, len(responses.calls))
84
85@@ -278,9 +280,9 @@
86 callback=issues_callback, content_type="application/json")
87 tracker = GitHub("https://github.com/user/repository/issues")
88 self.assertEqual(
89- {bug["id"]: bug for bug in self.sample_bugs},
90+ {bug["number"]: bug for bug in self.sample_bugs},
91 tracker.getRemoteBugBatch(
92- [str(bug["id"]) for bug in self.sample_bugs]))
93+ [str(bug["number"]) for bug in self.sample_bugs]))
94 expected_urls = [
95 "https://api.github.com/rate_limit",
96 "https://api.github.com/repos/user/repository/issues?state=all",
97@@ -293,9 +295,9 @@
98 @responses.activate
99 def test_status_open(self):
100 self.sample_bugs = [
101- {"id": 1, "state": "open", "labels": []},
102+ {"id": 101, "number": 1, "state": "open", "labels": []},
103 # Labels do not affect status, even if names collide.
104- {"id": 2, "state": "open",
105+ {"id": 102, "number": 2, "state": "open",
106 "labels": [{"name": "feature"}, {"name": "closed"}]},
107 ]
108 _add_rate_limit_response("api.github.com")
109@@ -314,9 +316,9 @@
110 @responses.activate
111 def test_status_closed(self):
112 self.sample_bugs = [
113- {"id": 1, "state": "closed", "labels": []},
114+ {"id": 101, "number": 1, "state": "closed", "labels": []},
115 # Labels do not affect status, even if names collide.
116- {"id": 2, "state": "closed",
117+ {"id": 102, "number": 2, "state": "closed",
118 "labels": [{"name": "feature"}, {"name": "open"}]},
119 ]
120 _add_rate_limit_response("api.github.com")
121@@ -339,7 +341,9 @@
122
123 @responses.activate
124 def test_process_one(self):
125- remote_bug = {"id": 1234, "state": "open", "labels": []}
126+ remote_bug = {
127+ "id": 12345, "number": 1234, "state": "open", "labels": [],
128+ }
129 _add_rate_limit_response("api.github.com")
130 responses.add(
131 "GET", "https://api.github.com/repos/user/repository/issues/1234",
132@@ -371,7 +375,7 @@
133 @responses.activate
134 def test_process_many(self):
135 remote_bugs = [
136- {"id": bug_id,
137+ {"id": bug_id + 1, "number": bug_id,
138 "state": "open" if (bug_id % 2) == 0 else "closed",
139 "labels": []}
140 for bug_id in range(1000, 1010)]
141@@ -385,7 +389,7 @@
142 bugtrackertype=BugTrackerType.GITHUB)
143 for remote_bug in remote_bugs:
144 bug.addWatch(
145- bug_tracker, str(remote_bug["id"]),
146+ bug_tracker, str(remote_bug["number"]),
147 getUtility(ILaunchpadCelebrities).janitor)
148 transaction.commit()
149 logger = BufferLogger()