npm-cli-gh-issue-preparator 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/bin/adapter/repositories/GitHubIssueRepository.js +182 -115
- package/bin/adapter/repositories/GitHubIssueRepository.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/repositories/GitHubIssueRepository.integration.test.ts +53 -37
- package/src/adapter/repositories/GitHubIssueRepository.test.ts +40 -0
- package/src/adapter/repositories/GitHubIssueRepository.ts +219 -123
- package/types/adapter/repositories/GitHubIssueRepository.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [1.0.2](https://github.com/HiromiShikata/npm-cli-gh-issue-preparator/compare/v1.0.1...v1.0.2) (2025-12-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* failed to get all fields ([f236af7](https://github.com/HiromiShikata/npm-cli-gh-issue-preparator/commit/f236af7cab059d8b63bc81743bd59127b28933cb))
|
|
7
|
+
|
|
8
|
+
## [1.0.1](https://github.com/HiromiShikata/npm-cli-gh-issue-preparator/compare/v1.0.0...v1.0.1) (2025-12-14)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* failed to load PR and over 100 items ([dd1c216](https://github.com/HiromiShikata/npm-cli-gh-issue-preparator/commit/dd1c2164e3ed1b8dcfa1b4de75395f875a8d0de2))
|
|
14
|
+
|
|
1
15
|
# 1.0.0 (2025-12-14)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -31,10 +31,15 @@ class GitHubIssueRepository {
|
|
|
31
31
|
}
|
|
32
32
|
buildProjectItemsQuery() {
|
|
33
33
|
return `
|
|
34
|
-
query($owner: String!, $number: Int
|
|
34
|
+
query($owner: String!, $number: Int!, $after: String) {
|
|
35
35
|
organization(login: $owner) {
|
|
36
36
|
projectV2(number: $number) {
|
|
37
|
-
items(first: 100) {
|
|
37
|
+
items(first: 100, after: $after) {
|
|
38
|
+
totalCount
|
|
39
|
+
pageInfo {
|
|
40
|
+
endCursor
|
|
41
|
+
hasNextPage
|
|
42
|
+
}
|
|
38
43
|
nodes {
|
|
39
44
|
id
|
|
40
45
|
content {
|
|
@@ -48,6 +53,16 @@ class GitHubIssueRepository {
|
|
|
48
53
|
}
|
|
49
54
|
}
|
|
50
55
|
}
|
|
56
|
+
... on PullRequest {
|
|
57
|
+
url
|
|
58
|
+
title
|
|
59
|
+
number
|
|
60
|
+
labels(first: 10) {
|
|
61
|
+
nodes {
|
|
62
|
+
name
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
51
66
|
}
|
|
52
67
|
fieldValues(first: 20) {
|
|
53
68
|
nodes {
|
|
@@ -76,7 +91,12 @@ class GitHubIssueRepository {
|
|
|
76
91
|
}
|
|
77
92
|
user(login: $owner) {
|
|
78
93
|
projectV2(number: $number) {
|
|
79
|
-
items(first: 100) {
|
|
94
|
+
items(first: 100, after: $after) {
|
|
95
|
+
totalCount
|
|
96
|
+
pageInfo {
|
|
97
|
+
endCursor
|
|
98
|
+
hasNextPage
|
|
99
|
+
}
|
|
80
100
|
nodes {
|
|
81
101
|
id
|
|
82
102
|
content {
|
|
@@ -90,6 +110,16 @@ class GitHubIssueRepository {
|
|
|
90
110
|
}
|
|
91
111
|
}
|
|
92
112
|
}
|
|
113
|
+
... on PullRequest {
|
|
114
|
+
url
|
|
115
|
+
title
|
|
116
|
+
number
|
|
117
|
+
labels(first: 10) {
|
|
118
|
+
nodes {
|
|
119
|
+
name
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
93
123
|
}
|
|
94
124
|
fieldValues(first: 20) {
|
|
95
125
|
nodes {
|
|
@@ -122,10 +152,14 @@ class GitHubIssueRepository {
|
|
|
122
152
|
async getStatusOptionId(project, statusName) {
|
|
123
153
|
const { owner, projectNumber } = this.parseProjectInfo(project);
|
|
124
154
|
const query = `
|
|
125
|
-
query($owner: String!, $number: Int
|
|
155
|
+
query($owner: String!, $number: Int!, $after: String) {
|
|
126
156
|
organization(login: $owner) {
|
|
127
157
|
projectV2(number: $number) {
|
|
128
|
-
fields(first:
|
|
158
|
+
fields(first: 100, after: $after) {
|
|
159
|
+
pageInfo {
|
|
160
|
+
endCursor
|
|
161
|
+
hasNextPage
|
|
162
|
+
}
|
|
129
163
|
nodes {
|
|
130
164
|
... on ProjectV2SingleSelectField {
|
|
131
165
|
id
|
|
@@ -141,7 +175,11 @@ class GitHubIssueRepository {
|
|
|
141
175
|
}
|
|
142
176
|
user(login: $owner) {
|
|
143
177
|
projectV2(number: $number) {
|
|
144
|
-
fields(first:
|
|
178
|
+
fields(first: 100, after: $after) {
|
|
179
|
+
pageInfo {
|
|
180
|
+
endCursor
|
|
181
|
+
hasNextPage
|
|
182
|
+
}
|
|
145
183
|
nodes {
|
|
146
184
|
... on ProjectV2SingleSelectField {
|
|
147
185
|
id
|
|
@@ -157,86 +195,106 @@ class GitHubIssueRepository {
|
|
|
157
195
|
}
|
|
158
196
|
}
|
|
159
197
|
`;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
variables: {
|
|
169
|
-
owner,
|
|
170
|
-
number: projectNumber,
|
|
198
|
+
let after = null;
|
|
199
|
+
let hasNextPage = true;
|
|
200
|
+
while (hasNextPage) {
|
|
201
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
202
|
+
method: 'POST',
|
|
203
|
+
headers: {
|
|
204
|
+
Authorization: `Bearer ${this.token}`,
|
|
205
|
+
'Content-Type': 'application/json',
|
|
171
206
|
},
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
body: JSON.stringify({
|
|
208
|
+
query,
|
|
209
|
+
variables: {
|
|
210
|
+
owner,
|
|
211
|
+
number: projectNumber,
|
|
212
|
+
after,
|
|
213
|
+
},
|
|
214
|
+
}),
|
|
215
|
+
});
|
|
216
|
+
if (!response.ok) {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
const responseData = await response.json();
|
|
220
|
+
if (!isStatusFieldsResponse(responseData)) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
const result = responseData;
|
|
224
|
+
const projectData = result.data?.organization?.projectV2 || result.data?.user?.projectV2;
|
|
225
|
+
if (!projectData) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
const fields = projectData.fields.nodes;
|
|
229
|
+
const statusField = fields.find((f) => f.name === 'Status');
|
|
230
|
+
if (statusField) {
|
|
231
|
+
const option = statusField.options.find((o) => o.name === statusName);
|
|
232
|
+
if (option) {
|
|
233
|
+
return {
|
|
234
|
+
fieldId: statusField.id,
|
|
235
|
+
optionId: option.id,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
hasNextPage = projectData.fields.pageInfo.hasNextPage;
|
|
240
|
+
after = projectData.fields.pageInfo.endCursor;
|
|
192
241
|
}
|
|
193
|
-
return
|
|
194
|
-
fieldId: statusField.id,
|
|
195
|
-
optionId: option.id,
|
|
196
|
-
};
|
|
242
|
+
return null;
|
|
197
243
|
}
|
|
198
244
|
async getAllOpened(project) {
|
|
199
245
|
const { owner, projectNumber } = this.parseProjectInfo(project);
|
|
200
246
|
const query = this.buildProjectItemsQuery();
|
|
201
|
-
const response = await fetch('https://api.github.com/graphql', {
|
|
202
|
-
method: 'POST',
|
|
203
|
-
headers: {
|
|
204
|
-
Authorization: `Bearer ${this.token}`,
|
|
205
|
-
'Content-Type': 'application/json',
|
|
206
|
-
},
|
|
207
|
-
body: JSON.stringify({
|
|
208
|
-
query,
|
|
209
|
-
variables: {
|
|
210
|
-
owner,
|
|
211
|
-
number: projectNumber,
|
|
212
|
-
},
|
|
213
|
-
}),
|
|
214
|
-
});
|
|
215
|
-
if (!response.ok) {
|
|
216
|
-
const errorText = await response.text();
|
|
217
|
-
throw new Error(`GitHub API error: ${errorText}`);
|
|
218
|
-
}
|
|
219
|
-
const responseData = await response.json();
|
|
220
|
-
if (!isProjectItemsResponse(responseData)) {
|
|
221
|
-
throw new Error('Invalid API response format');
|
|
222
|
-
}
|
|
223
|
-
const result = responseData;
|
|
224
|
-
const items = result.data?.organization?.projectV2?.items.nodes ||
|
|
225
|
-
result.data?.user?.projectV2?.items.nodes ||
|
|
226
|
-
[];
|
|
227
247
|
const issues = [];
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
248
|
+
let after = null;
|
|
249
|
+
let hasNextPage = true;
|
|
250
|
+
while (hasNextPage) {
|
|
251
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
252
|
+
method: 'POST',
|
|
253
|
+
headers: {
|
|
254
|
+
Authorization: `Bearer ${this.token}`,
|
|
255
|
+
'Content-Type': 'application/json',
|
|
256
|
+
},
|
|
257
|
+
body: JSON.stringify({
|
|
258
|
+
query,
|
|
259
|
+
variables: {
|
|
260
|
+
owner,
|
|
261
|
+
number: projectNumber,
|
|
262
|
+
after,
|
|
263
|
+
},
|
|
264
|
+
}),
|
|
239
265
|
});
|
|
266
|
+
if (!response.ok) {
|
|
267
|
+
const errorText = await response.text();
|
|
268
|
+
throw new Error(`GitHub API error: ${errorText}`);
|
|
269
|
+
}
|
|
270
|
+
const responseData = await response.json();
|
|
271
|
+
if (!isProjectItemsResponse(responseData)) {
|
|
272
|
+
throw new Error('Invalid API response format');
|
|
273
|
+
}
|
|
274
|
+
const result = responseData;
|
|
275
|
+
const projectData = result.data?.organization?.projectV2 || result.data?.user?.projectV2;
|
|
276
|
+
if (!projectData) {
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
const items = projectData.items.nodes;
|
|
280
|
+
for (const item of items) {
|
|
281
|
+
if (!item.content)
|
|
282
|
+
continue;
|
|
283
|
+
const statusField = item.fieldValues?.nodes.find((fv) => fv.field?.name === 'Status');
|
|
284
|
+
const status = statusField?.name || '';
|
|
285
|
+
if (item.content.url === undefined) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
issues.push({
|
|
289
|
+
id: item.id,
|
|
290
|
+
url: item.content.url,
|
|
291
|
+
title: item.content.title,
|
|
292
|
+
labels: item.content.labels?.nodes?.map((l) => l.name) || [],
|
|
293
|
+
status,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
hasNextPage = projectData.items.pageInfo.hasNextPage;
|
|
297
|
+
after = projectData.items.pageInfo.endCursor;
|
|
240
298
|
}
|
|
241
299
|
return issues;
|
|
242
300
|
}
|
|
@@ -293,45 +351,54 @@ class GitHubIssueRepository {
|
|
|
293
351
|
async get(issueUrl, project) {
|
|
294
352
|
const { owner, projectNumber } = this.parseProjectInfo(project);
|
|
295
353
|
const query = this.buildProjectItemsQuery();
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
variables: {
|
|
305
|
-
owner,
|
|
306
|
-
number: projectNumber,
|
|
354
|
+
let after = null;
|
|
355
|
+
let hasNextPage = true;
|
|
356
|
+
while (hasNextPage) {
|
|
357
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
358
|
+
method: 'POST',
|
|
359
|
+
headers: {
|
|
360
|
+
Authorization: `Bearer ${this.token}`,
|
|
361
|
+
'Content-Type': 'application/json',
|
|
307
362
|
},
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
return
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
363
|
+
body: JSON.stringify({
|
|
364
|
+
query,
|
|
365
|
+
variables: {
|
|
366
|
+
owner,
|
|
367
|
+
number: projectNumber,
|
|
368
|
+
after,
|
|
369
|
+
},
|
|
370
|
+
}),
|
|
371
|
+
});
|
|
372
|
+
if (!response.ok) {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
const responseData = await response.json();
|
|
376
|
+
if (!isProjectItemsResponse(responseData)) {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
const result = responseData;
|
|
380
|
+
const projectData = result.data?.organization?.projectV2 || result.data?.user?.projectV2;
|
|
381
|
+
if (!projectData) {
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
const items = projectData.items.nodes;
|
|
385
|
+
for (const item of items) {
|
|
386
|
+
if (!item.content)
|
|
387
|
+
continue;
|
|
388
|
+
if (item.content.url === issueUrl) {
|
|
389
|
+
const statusField = item.fieldValues?.nodes.find((fv) => fv.field?.name === 'Status');
|
|
390
|
+
const status = statusField?.name || '';
|
|
391
|
+
return {
|
|
392
|
+
id: item.id,
|
|
393
|
+
url: item.content.url,
|
|
394
|
+
title: item.content.title,
|
|
395
|
+
labels: item.content.labels?.nodes?.map((l) => l.name) || [],
|
|
396
|
+
status,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
334
399
|
}
|
|
400
|
+
hasNextPage = projectData.items.pageInfo.hasNextPage;
|
|
401
|
+
after = projectData.items.pageInfo.endCursor;
|
|
335
402
|
}
|
|
336
403
|
return null;
|
|
337
404
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GitHubIssueRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/GitHubIssueRepository.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"GitHubIssueRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/GitHubIssueRepository.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -10,41 +10,57 @@ describe('GitHubIssueRepository Integration Test', () => {
|
|
|
10
10
|
const issueUrl =
|
|
11
11
|
'https://github.com/HiromiShikata/test-repository/issues/1552';
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
13
|
+
describe('getgetAllOpened', () => {
|
|
14
|
+
it('should get all opened issues and verify the list is not empty', async () => {
|
|
15
|
+
if (!token) {
|
|
16
|
+
throw new Error('GH_TOKEN environment variable is required');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const repository = new GitHubIssueRepository(token);
|
|
20
|
+
const projectRepository = new GitHubProjectRepository(token);
|
|
21
|
+
const project = await projectRepository.getByUrl(projectUrl);
|
|
22
|
+
|
|
23
|
+
const openedIssues = await repository.getAllOpened(project);
|
|
24
|
+
expect(openedIssues.length).toBeGreaterThan(0);
|
|
25
|
+
}, 60000);
|
|
26
|
+
});
|
|
27
|
+
describe('update', () => {
|
|
28
|
+
it('should update issue status from Awaiting workspace to Preparation and verify the change', async () => {
|
|
29
|
+
if (!token) {
|
|
30
|
+
throw new Error('GH_TOKEN environment variable is required');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const repository = new GitHubIssueRepository(token);
|
|
34
|
+
const projectRepository = new GitHubProjectRepository(token);
|
|
35
|
+
const project = await projectRepository.getByUrl(projectUrl);
|
|
36
|
+
|
|
37
|
+
const initialIssue = await repository.get(issueUrl, project);
|
|
38
|
+
expect(initialIssue).not.toBeNull();
|
|
39
|
+
if (!initialIssue) {
|
|
40
|
+
throw new Error('Failed to get initial issue');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
initialIssue.status = 'Awaiting workspace';
|
|
44
|
+
await repository.update(initialIssue, project);
|
|
45
|
+
|
|
46
|
+
const reloadedIssue = await repository.get(issueUrl, project);
|
|
47
|
+
if (!reloadedIssue) {
|
|
48
|
+
throw new Error('Failed to get reloaded issue');
|
|
49
|
+
}
|
|
50
|
+
expect(reloadedIssue.status).toBe('Awaiting workspace');
|
|
51
|
+
|
|
52
|
+
reloadedIssue.status = 'Preparation';
|
|
53
|
+
await repository.update(reloadedIssue, project);
|
|
54
|
+
|
|
55
|
+
const verifyIssue = await repository.get(issueUrl, project);
|
|
56
|
+
expect(verifyIssue).not.toBeNull();
|
|
57
|
+
if (!verifyIssue) {
|
|
58
|
+
throw new Error('Failed to get verify issue');
|
|
59
|
+
}
|
|
60
|
+
expect(verifyIssue.status).toBe('Preparation');
|
|
61
|
+
|
|
62
|
+
verifyIssue.status = 'Awaiting workspace';
|
|
63
|
+
await repository.update(verifyIssue, project);
|
|
64
|
+
}, 60000);
|
|
65
|
+
});
|
|
50
66
|
});
|
|
@@ -38,6 +38,11 @@ describe('GitHubIssueRepository', () => {
|
|
|
38
38
|
organization: {
|
|
39
39
|
projectV2: {
|
|
40
40
|
items: {
|
|
41
|
+
totalCount: 2,
|
|
42
|
+
pageInfo: {
|
|
43
|
+
endCursor: null,
|
|
44
|
+
hasNextPage: false,
|
|
45
|
+
},
|
|
41
46
|
nodes: [
|
|
42
47
|
{
|
|
43
48
|
id: 'issue-1',
|
|
@@ -149,6 +154,11 @@ describe('GitHubIssueRepository', () => {
|
|
|
149
154
|
user: {
|
|
150
155
|
projectV2: {
|
|
151
156
|
items: {
|
|
157
|
+
totalCount: 1,
|
|
158
|
+
pageInfo: {
|
|
159
|
+
endCursor: null,
|
|
160
|
+
hasNextPage: false,
|
|
161
|
+
},
|
|
152
162
|
nodes: [
|
|
153
163
|
{
|
|
154
164
|
id: 'user-issue-1',
|
|
@@ -199,6 +209,11 @@ describe('GitHubIssueRepository', () => {
|
|
|
199
209
|
organization: {
|
|
200
210
|
projectV2: {
|
|
201
211
|
items: {
|
|
212
|
+
totalCount: 2,
|
|
213
|
+
pageInfo: {
|
|
214
|
+
endCursor: null,
|
|
215
|
+
hasNextPage: false,
|
|
216
|
+
},
|
|
202
217
|
nodes: [
|
|
203
218
|
{
|
|
204
219
|
id: 'item-without-content',
|
|
@@ -263,6 +278,11 @@ describe('GitHubIssueRepository', () => {
|
|
|
263
278
|
organization: {
|
|
264
279
|
projectV2: {
|
|
265
280
|
items: {
|
|
281
|
+
totalCount: 1,
|
|
282
|
+
pageInfo: {
|
|
283
|
+
endCursor: null,
|
|
284
|
+
hasNextPage: false,
|
|
285
|
+
},
|
|
266
286
|
nodes: [
|
|
267
287
|
{
|
|
268
288
|
id: 'issue-no-status',
|
|
@@ -728,6 +748,11 @@ describe('GitHubIssueRepository', () => {
|
|
|
728
748
|
organization: {
|
|
729
749
|
projectV2: {
|
|
730
750
|
items: {
|
|
751
|
+
totalCount: 1,
|
|
752
|
+
pageInfo: {
|
|
753
|
+
endCursor: null,
|
|
754
|
+
hasNextPage: false,
|
|
755
|
+
},
|
|
731
756
|
nodes: [
|
|
732
757
|
{
|
|
733
758
|
id: 'issue-1',
|
|
@@ -805,6 +830,11 @@ describe('GitHubIssueRepository', () => {
|
|
|
805
830
|
organization: {
|
|
806
831
|
projectV2: {
|
|
807
832
|
items: {
|
|
833
|
+
totalCount: 0,
|
|
834
|
+
pageInfo: {
|
|
835
|
+
endCursor: null,
|
|
836
|
+
hasNextPage: false,
|
|
837
|
+
},
|
|
808
838
|
nodes: [],
|
|
809
839
|
},
|
|
810
840
|
},
|
|
@@ -828,6 +858,11 @@ describe('GitHubIssueRepository', () => {
|
|
|
828
858
|
user: {
|
|
829
859
|
projectV2: {
|
|
830
860
|
items: {
|
|
861
|
+
totalCount: 1,
|
|
862
|
+
pageInfo: {
|
|
863
|
+
endCursor: null,
|
|
864
|
+
hasNextPage: false,
|
|
865
|
+
},
|
|
831
866
|
nodes: [
|
|
832
867
|
{
|
|
833
868
|
id: 'issue-2',
|
|
@@ -880,6 +915,11 @@ describe('GitHubIssueRepository', () => {
|
|
|
880
915
|
organization: {
|
|
881
916
|
projectV2: {
|
|
882
917
|
items: {
|
|
918
|
+
totalCount: 1,
|
|
919
|
+
pageInfo: {
|
|
920
|
+
endCursor: null,
|
|
921
|
+
hasNextPage: false,
|
|
922
|
+
},
|
|
883
923
|
nodes: [
|
|
884
924
|
{
|
|
885
925
|
id: 'issue-3',
|
|
@@ -27,6 +27,11 @@ type ProjectItemsResponse = {
|
|
|
27
27
|
organization?: {
|
|
28
28
|
projectV2?: {
|
|
29
29
|
items: {
|
|
30
|
+
totalCount: number;
|
|
31
|
+
pageInfo: {
|
|
32
|
+
endCursor: string;
|
|
33
|
+
hasNextPage: boolean;
|
|
34
|
+
};
|
|
30
35
|
nodes: ProjectItem[];
|
|
31
36
|
};
|
|
32
37
|
};
|
|
@@ -34,6 +39,11 @@ type ProjectItemsResponse = {
|
|
|
34
39
|
user?: {
|
|
35
40
|
projectV2?: {
|
|
36
41
|
items: {
|
|
42
|
+
totalCount: number;
|
|
43
|
+
pageInfo: {
|
|
44
|
+
endCursor: string;
|
|
45
|
+
hasNextPage: boolean;
|
|
46
|
+
};
|
|
37
47
|
nodes: ProjectItem[];
|
|
38
48
|
};
|
|
39
49
|
};
|
|
@@ -67,6 +77,10 @@ type StatusFieldsResponse = {
|
|
|
67
77
|
organization?: {
|
|
68
78
|
projectV2?: {
|
|
69
79
|
fields: {
|
|
80
|
+
pageInfo: {
|
|
81
|
+
endCursor: string;
|
|
82
|
+
hasNextPage: boolean;
|
|
83
|
+
};
|
|
70
84
|
nodes: StatusField[];
|
|
71
85
|
};
|
|
72
86
|
};
|
|
@@ -74,6 +88,10 @@ type StatusFieldsResponse = {
|
|
|
74
88
|
user?: {
|
|
75
89
|
projectV2?: {
|
|
76
90
|
fields: {
|
|
91
|
+
pageInfo: {
|
|
92
|
+
endCursor: string;
|
|
93
|
+
hasNextPage: boolean;
|
|
94
|
+
};
|
|
77
95
|
nodes: StatusField[];
|
|
78
96
|
};
|
|
79
97
|
};
|
|
@@ -117,10 +135,15 @@ export class GitHubIssueRepository implements IssueRepository {
|
|
|
117
135
|
|
|
118
136
|
private buildProjectItemsQuery(): string {
|
|
119
137
|
return `
|
|
120
|
-
query($owner: String!, $number: Int
|
|
138
|
+
query($owner: String!, $number: Int!, $after: String) {
|
|
121
139
|
organization(login: $owner) {
|
|
122
140
|
projectV2(number: $number) {
|
|
123
|
-
items(first: 100) {
|
|
141
|
+
items(first: 100, after: $after) {
|
|
142
|
+
totalCount
|
|
143
|
+
pageInfo {
|
|
144
|
+
endCursor
|
|
145
|
+
hasNextPage
|
|
146
|
+
}
|
|
124
147
|
nodes {
|
|
125
148
|
id
|
|
126
149
|
content {
|
|
@@ -134,6 +157,16 @@ export class GitHubIssueRepository implements IssueRepository {
|
|
|
134
157
|
}
|
|
135
158
|
}
|
|
136
159
|
}
|
|
160
|
+
... on PullRequest {
|
|
161
|
+
url
|
|
162
|
+
title
|
|
163
|
+
number
|
|
164
|
+
labels(first: 10) {
|
|
165
|
+
nodes {
|
|
166
|
+
name
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
137
170
|
}
|
|
138
171
|
fieldValues(first: 20) {
|
|
139
172
|
nodes {
|
|
@@ -162,7 +195,12 @@ export class GitHubIssueRepository implements IssueRepository {
|
|
|
162
195
|
}
|
|
163
196
|
user(login: $owner) {
|
|
164
197
|
projectV2(number: $number) {
|
|
165
|
-
items(first: 100) {
|
|
198
|
+
items(first: 100, after: $after) {
|
|
199
|
+
totalCount
|
|
200
|
+
pageInfo {
|
|
201
|
+
endCursor
|
|
202
|
+
hasNextPage
|
|
203
|
+
}
|
|
166
204
|
nodes {
|
|
167
205
|
id
|
|
168
206
|
content {
|
|
@@ -176,6 +214,16 @@ export class GitHubIssueRepository implements IssueRepository {
|
|
|
176
214
|
}
|
|
177
215
|
}
|
|
178
216
|
}
|
|
217
|
+
... on PullRequest {
|
|
218
|
+
url
|
|
219
|
+
title
|
|
220
|
+
number
|
|
221
|
+
labels(first: 10) {
|
|
222
|
+
nodes {
|
|
223
|
+
name
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
179
227
|
}
|
|
180
228
|
fieldValues(first: 20) {
|
|
181
229
|
nodes {
|
|
@@ -213,10 +261,14 @@ export class GitHubIssueRepository implements IssueRepository {
|
|
|
213
261
|
const { owner, projectNumber } = this.parseProjectInfo(project);
|
|
214
262
|
|
|
215
263
|
const query = `
|
|
216
|
-
query($owner: String!, $number: Int
|
|
264
|
+
query($owner: String!, $number: Int!, $after: String) {
|
|
217
265
|
organization(login: $owner) {
|
|
218
266
|
projectV2(number: $number) {
|
|
219
|
-
fields(first:
|
|
267
|
+
fields(first: 100, after: $after) {
|
|
268
|
+
pageInfo {
|
|
269
|
+
endCursor
|
|
270
|
+
hasNextPage
|
|
271
|
+
}
|
|
220
272
|
nodes {
|
|
221
273
|
... on ProjectV2SingleSelectField {
|
|
222
274
|
id
|
|
@@ -232,7 +284,11 @@ export class GitHubIssueRepository implements IssueRepository {
|
|
|
232
284
|
}
|
|
233
285
|
user(login: $owner) {
|
|
234
286
|
projectV2(number: $number) {
|
|
235
|
-
fields(first:
|
|
287
|
+
fields(first: 100, after: $after) {
|
|
288
|
+
pageInfo {
|
|
289
|
+
endCursor
|
|
290
|
+
hasNextPage
|
|
291
|
+
}
|
|
236
292
|
nodes {
|
|
237
293
|
... on ProjectV2SingleSelectField {
|
|
238
294
|
id
|
|
@@ -249,50 +305,61 @@ export class GitHubIssueRepository implements IssueRepository {
|
|
|
249
305
|
}
|
|
250
306
|
`;
|
|
251
307
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
owner,
|
|
262
|
-
number: projectNumber,
|
|
308
|
+
let after: string | null = null;
|
|
309
|
+
let hasNextPage = true;
|
|
310
|
+
|
|
311
|
+
while (hasNextPage) {
|
|
312
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
313
|
+
method: 'POST',
|
|
314
|
+
headers: {
|
|
315
|
+
Authorization: `Bearer ${this.token}`,
|
|
316
|
+
'Content-Type': 'application/json',
|
|
263
317
|
},
|
|
264
|
-
|
|
265
|
-
|
|
318
|
+
body: JSON.stringify({
|
|
319
|
+
query,
|
|
320
|
+
variables: {
|
|
321
|
+
owner,
|
|
322
|
+
number: projectNumber,
|
|
323
|
+
after,
|
|
324
|
+
},
|
|
325
|
+
}),
|
|
326
|
+
});
|
|
266
327
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
328
|
+
if (!response.ok) {
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
270
331
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
332
|
+
const responseData: unknown = await response.json();
|
|
333
|
+
if (!isStatusFieldsResponse(responseData)) {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
275
336
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
result.data?.user?.projectV2?.fields.nodes ||
|
|
280
|
-
[];
|
|
337
|
+
const result: StatusFieldsResponse = responseData;
|
|
338
|
+
const projectData =
|
|
339
|
+
result.data?.organization?.projectV2 || result.data?.user?.projectV2;
|
|
281
340
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
341
|
+
if (!projectData) {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
286
344
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
345
|
+
const fields = projectData.fields.nodes;
|
|
346
|
+
|
|
347
|
+
const statusField = fields.find((f) => f.name === 'Status');
|
|
348
|
+
if (statusField) {
|
|
349
|
+
const option = statusField.options.find((o) => o.name === statusName);
|
|
350
|
+
if (option) {
|
|
351
|
+
return {
|
|
352
|
+
fieldId: statusField.id,
|
|
353
|
+
optionId: option.id,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
hasNextPage = projectData.fields.pageInfo.hasNextPage;
|
|
359
|
+
after = projectData.fields.pageInfo.endCursor;
|
|
290
360
|
}
|
|
291
361
|
|
|
292
|
-
return
|
|
293
|
-
fieldId: statusField.id,
|
|
294
|
-
optionId: option.id,
|
|
295
|
-
};
|
|
362
|
+
return null;
|
|
296
363
|
}
|
|
297
364
|
|
|
298
365
|
async getAllOpened(project: Project): Promise<Issue[]> {
|
|
@@ -300,53 +367,69 @@ export class GitHubIssueRepository implements IssueRepository {
|
|
|
300
367
|
|
|
301
368
|
const query = this.buildProjectItemsQuery();
|
|
302
369
|
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
number: projectNumber,
|
|
370
|
+
const issues: Issue[] = [];
|
|
371
|
+
let after: string | null = null;
|
|
372
|
+
let hasNextPage = true;
|
|
373
|
+
|
|
374
|
+
while (hasNextPage) {
|
|
375
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
376
|
+
method: 'POST',
|
|
377
|
+
headers: {
|
|
378
|
+
Authorization: `Bearer ${this.token}`,
|
|
379
|
+
'Content-Type': 'application/json',
|
|
314
380
|
},
|
|
315
|
-
|
|
316
|
-
|
|
381
|
+
body: JSON.stringify({
|
|
382
|
+
query,
|
|
383
|
+
variables: {
|
|
384
|
+
owner,
|
|
385
|
+
number: projectNumber,
|
|
386
|
+
after,
|
|
387
|
+
},
|
|
388
|
+
}),
|
|
389
|
+
});
|
|
317
390
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
391
|
+
if (!response.ok) {
|
|
392
|
+
const errorText = await response.text();
|
|
393
|
+
throw new Error(`GitHub API error: ${errorText}`);
|
|
394
|
+
}
|
|
322
395
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
396
|
+
const responseData: unknown = await response.json();
|
|
397
|
+
if (!isProjectItemsResponse(responseData)) {
|
|
398
|
+
throw new Error('Invalid API response format');
|
|
399
|
+
}
|
|
327
400
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
result.data?.user?.projectV2?.items.nodes ||
|
|
332
|
-
[];
|
|
401
|
+
const result: ProjectItemsResponse = responseData;
|
|
402
|
+
const projectData =
|
|
403
|
+
result.data?.organization?.projectV2 || result.data?.user?.projectV2;
|
|
333
404
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
405
|
+
if (!projectData) {
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const items = projectData.items.nodes;
|
|
410
|
+
|
|
411
|
+
for (const item of items) {
|
|
412
|
+
if (!item.content) continue;
|
|
413
|
+
|
|
414
|
+
const statusField = item.fieldValues?.nodes.find(
|
|
415
|
+
(fv) => fv.field?.name === 'Status',
|
|
416
|
+
);
|
|
417
|
+
const status = statusField?.name || '';
|
|
418
|
+
|
|
419
|
+
if (item.content.url === undefined) {
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
issues.push({
|
|
423
|
+
id: item.id,
|
|
424
|
+
url: item.content.url,
|
|
425
|
+
title: item.content.title,
|
|
426
|
+
labels: item.content.labels?.nodes?.map((l) => l.name) || [],
|
|
427
|
+
status,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
hasNextPage = projectData.items.pageInfo.hasNextPage;
|
|
432
|
+
after = projectData.items.pageInfo.endCursor;
|
|
350
433
|
}
|
|
351
434
|
|
|
352
435
|
return issues;
|
|
@@ -416,53 +499,66 @@ export class GitHubIssueRepository implements IssueRepository {
|
|
|
416
499
|
|
|
417
500
|
const query = this.buildProjectItemsQuery();
|
|
418
501
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
owner,
|
|
429
|
-
number: projectNumber,
|
|
502
|
+
let after: string | null = null;
|
|
503
|
+
let hasNextPage = true;
|
|
504
|
+
|
|
505
|
+
while (hasNextPage) {
|
|
506
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
507
|
+
method: 'POST',
|
|
508
|
+
headers: {
|
|
509
|
+
Authorization: `Bearer ${this.token}`,
|
|
510
|
+
'Content-Type': 'application/json',
|
|
430
511
|
},
|
|
431
|
-
|
|
432
|
-
|
|
512
|
+
body: JSON.stringify({
|
|
513
|
+
query,
|
|
514
|
+
variables: {
|
|
515
|
+
owner,
|
|
516
|
+
number: projectNumber,
|
|
517
|
+
after,
|
|
518
|
+
},
|
|
519
|
+
}),
|
|
520
|
+
});
|
|
433
521
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
522
|
+
if (!response.ok) {
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
437
525
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
526
|
+
const responseData: unknown = await response.json();
|
|
527
|
+
if (!isProjectItemsResponse(responseData)) {
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
442
530
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
result.data?.user?.projectV2?.items.nodes ||
|
|
447
|
-
[];
|
|
531
|
+
const result: ProjectItemsResponse = responseData;
|
|
532
|
+
const projectData =
|
|
533
|
+
result.data?.organization?.projectV2 || result.data?.user?.projectV2;
|
|
448
534
|
|
|
449
|
-
|
|
450
|
-
|
|
535
|
+
if (!projectData) {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
451
538
|
|
|
452
|
-
|
|
453
|
-
const statusField = item.fieldValues?.nodes.find(
|
|
454
|
-
(fv) => fv.field?.name === 'Status',
|
|
455
|
-
);
|
|
456
|
-
const status = statusField?.name || '';
|
|
539
|
+
const items = projectData.items.nodes;
|
|
457
540
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
541
|
+
for (const item of items) {
|
|
542
|
+
if (!item.content) continue;
|
|
543
|
+
|
|
544
|
+
if (item.content.url === issueUrl) {
|
|
545
|
+
const statusField = item.fieldValues?.nodes.find(
|
|
546
|
+
(fv) => fv.field?.name === 'Status',
|
|
547
|
+
);
|
|
548
|
+
const status = statusField?.name || '';
|
|
549
|
+
|
|
550
|
+
return {
|
|
551
|
+
id: item.id,
|
|
552
|
+
url: item.content.url,
|
|
553
|
+
title: item.content.title,
|
|
554
|
+
labels: item.content.labels?.nodes?.map((l) => l.name) || [],
|
|
555
|
+
status,
|
|
556
|
+
};
|
|
557
|
+
}
|
|
465
558
|
}
|
|
559
|
+
|
|
560
|
+
hasNextPage = projectData.items.pageInfo.hasNextPage;
|
|
561
|
+
after = projectData.items.pageInfo.endCursor;
|
|
466
562
|
}
|
|
467
563
|
|
|
468
564
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GitHubIssueRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/GitHubIssueRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,0DAA0D,CAAC;AAC3F,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"GitHubIssueRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/GitHubIssueRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,0DAA0D,CAAC;AAC3F,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAkHxD,qBAAa,qBAAsB,YAAW,eAAe;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,MAAM;IAE1C,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,sBAAsB;YAyHhB,iBAAiB;IA4GzB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAyEhD,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA2DrD,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;CAqErE"}
|