linear-github-cli 1.1.1 → 1.1.4
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/README.md +19 -0
- package/dist/commands/create-sub.js +8 -12
- package/dist/github-client.js +243 -40
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -180,6 +180,25 @@ Make sure you've set the environment variable:
|
|
|
180
180
|
export LINEAR_API_KEY="lin_api_..."
|
|
181
181
|
```
|
|
182
182
|
|
|
183
|
+
### GitHub Project date fields not being set
|
|
184
|
+
|
|
185
|
+
If start date or target date fields are not being set in GitHub Projects:
|
|
186
|
+
|
|
187
|
+
1. **Enable debug mode** to see detailed logs:
|
|
188
|
+
```bash
|
|
189
|
+
DEBUG=true lg parent
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
2. **Check the logs** for:
|
|
193
|
+
- Whether the project item was found (may require retries due to timing)
|
|
194
|
+
- Whether the date fields exist in the project
|
|
195
|
+
- Any GraphQL errors
|
|
196
|
+
|
|
197
|
+
3. **Common issues**:
|
|
198
|
+
- The issue may not be indexed in the project yet (the tool will retry automatically)
|
|
199
|
+
- The project may not have "Target" or "Start" date fields configured
|
|
200
|
+
- Network or API rate limiting issues
|
|
201
|
+
|
|
183
202
|
### "lg: command not found"
|
|
184
203
|
|
|
185
204
|
If you installed globally, make sure npm's global bin directory is in your PATH:
|
|
@@ -67,18 +67,6 @@ async function createSubIssue() {
|
|
|
67
67
|
});
|
|
68
68
|
console.log(`✅ Sub-Issue #${subIssue.number} created: ${subIssue.url}`);
|
|
69
69
|
console.log(` Parent: #${parentIssueNumber}`);
|
|
70
|
-
// Set GitHub Project date fields if dates are provided
|
|
71
|
-
if (details.dueDate || details.startDate) {
|
|
72
|
-
console.log('\n📅 Setting GitHub Project date fields...');
|
|
73
|
-
// sub-issueから直接プロジェクト情報を取得(Auto-add sub-issues to projectが有効な場合)
|
|
74
|
-
const projectName = await githubClient.getIssueProject(repo, subIssue.id);
|
|
75
|
-
if (projectName) {
|
|
76
|
-
await githubClient.setProjectDateFields(repo, projectName, subIssue.id, details.dueDate || undefined, details.startDate || undefined);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
console.log(' ⚠️ Sub-issue has no GitHub Project. Skipping date field setting.');
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
70
|
// Step 5: Wait for Linear sync, then update metadata
|
|
83
71
|
console.log('\n⏳ Waiting for Linear sync (5 seconds)...');
|
|
84
72
|
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
@@ -138,6 +126,14 @@ async function createSubIssue() {
|
|
|
138
126
|
console.log(` Due date: ${details.dueDate}`);
|
|
139
127
|
}
|
|
140
128
|
console.log(' Status: Will be updated automatically via PR integration');
|
|
129
|
+
// Set GitHub Project date fields if parent project is available and dates are provided
|
|
130
|
+
if (parentProjectName && (details.dueDate || details.startDate)) {
|
|
131
|
+
console.log('\n📅 Setting GitHub Project date fields...');
|
|
132
|
+
// Wait additional time for GitHub Actions to sync project assignment
|
|
133
|
+
console.log(' ⏳ Waiting for GitHub Actions sync (3 seconds)...');
|
|
134
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
135
|
+
await githubClient.setProjectDateFields(repo, parentProjectName, subIssue.id, details.dueDate || undefined, details.startDate || undefined);
|
|
136
|
+
}
|
|
141
137
|
}
|
|
142
138
|
else {
|
|
143
139
|
console.log('⚠️ Failed to update Linear issue metadata. You can update it manually in Linear.');
|
package/dist/github-client.js
CHANGED
|
@@ -183,6 +183,7 @@ class GitHubClientWrapper {
|
|
|
183
183
|
* Get project field ID by field name
|
|
184
184
|
*/
|
|
185
185
|
async getProjectFieldId(projectId, fieldName) {
|
|
186
|
+
const debug = process.env.DEBUG === 'true';
|
|
186
187
|
try {
|
|
187
188
|
const query = `query {
|
|
188
189
|
node(id: "${projectId}") {
|
|
@@ -198,53 +199,170 @@ class GitHubClientWrapper {
|
|
|
198
199
|
}
|
|
199
200
|
}
|
|
200
201
|
}`;
|
|
202
|
+
if (debug) {
|
|
203
|
+
console.log(` [DEBUG] Looking up field "${fieldName}" in project ${projectId}`);
|
|
204
|
+
}
|
|
201
205
|
const output = (0, child_process_1.execSync)(`gh api graphql -f query="${query.replace(/"/g, '\\"')}"`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
202
206
|
const result = JSON.parse(output);
|
|
207
|
+
if (debug) {
|
|
208
|
+
console.log(` [DEBUG] Fields query response:`, JSON.stringify(result, null, 2));
|
|
209
|
+
}
|
|
210
|
+
if (result.errors) {
|
|
211
|
+
console.error(` ⚠️ GraphQL errors when fetching fields:`, result.errors);
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
203
214
|
const fields = result.data?.node?.fields?.nodes || [];
|
|
204
215
|
const field = fields.find((f) => f.name === fieldName);
|
|
205
|
-
|
|
216
|
+
if (field) {
|
|
217
|
+
if (debug) {
|
|
218
|
+
console.log(` [DEBUG] Found field "${fieldName}" with ID: ${field.id}`);
|
|
219
|
+
}
|
|
220
|
+
return field.id;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
if (debug) {
|
|
224
|
+
const availableFields = fields.map((f) => f.name);
|
|
225
|
+
console.log(` [DEBUG] Field "${fieldName}" not found. Available fields:`, availableFields);
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
206
229
|
}
|
|
207
230
|
catch (error) {
|
|
208
|
-
|
|
231
|
+
const errorMessage = error.message || error.stderr || String(error);
|
|
232
|
+
console.error(` ⚠️ Failed to get field ID for "${fieldName}": ${errorMessage}`);
|
|
233
|
+
if (debug) {
|
|
234
|
+
console.error(` [DEBUG] Full error:`, error);
|
|
235
|
+
}
|
|
209
236
|
return null;
|
|
210
237
|
}
|
|
211
238
|
}
|
|
212
239
|
/**
|
|
213
|
-
* Get project item ID by issue ID
|
|
240
|
+
* Get project item ID by issue ID with retry and pagination support
|
|
214
241
|
*/
|
|
215
|
-
async getProjectItemId(projectId, issueId) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
242
|
+
async getProjectItemId(projectId, issueId, maxRetries = 3) {
|
|
243
|
+
const debug = process.env.DEBUG === 'true';
|
|
244
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
245
|
+
try {
|
|
246
|
+
let cursor = null;
|
|
247
|
+
let hasNextPage = true;
|
|
248
|
+
let allItems = [];
|
|
249
|
+
// Paginate through all items
|
|
250
|
+
while (hasNextPage) {
|
|
251
|
+
const query = cursor
|
|
252
|
+
? `query {
|
|
253
|
+
node(id: "${projectId}") {
|
|
254
|
+
... on ProjectV2 {
|
|
255
|
+
items(first: 100, after: "${cursor}") {
|
|
256
|
+
pageInfo {
|
|
257
|
+
hasNextPage
|
|
258
|
+
endCursor
|
|
259
|
+
}
|
|
260
|
+
nodes {
|
|
261
|
+
id
|
|
262
|
+
content {
|
|
263
|
+
... on Issue {
|
|
264
|
+
id
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
226
269
|
}
|
|
227
270
|
}
|
|
228
|
-
}
|
|
271
|
+
}`
|
|
272
|
+
: `query {
|
|
273
|
+
node(id: "${projectId}") {
|
|
274
|
+
... on ProjectV2 {
|
|
275
|
+
items(first: 100) {
|
|
276
|
+
pageInfo {
|
|
277
|
+
hasNextPage
|
|
278
|
+
endCursor
|
|
279
|
+
}
|
|
280
|
+
nodes {
|
|
281
|
+
id
|
|
282
|
+
content {
|
|
283
|
+
... on Issue {
|
|
284
|
+
id
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}`;
|
|
292
|
+
if (debug) {
|
|
293
|
+
console.log(` [DEBUG] Attempt ${attempt}/${maxRetries}: Querying project items${cursor ? ` (cursor: ${cursor})` : ''}`);
|
|
294
|
+
}
|
|
295
|
+
const output = (0, child_process_1.execSync)(`gh api graphql -f query="${query.replace(/"/g, '\\"')}"`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
296
|
+
const result = JSON.parse(output);
|
|
297
|
+
if (debug) {
|
|
298
|
+
console.log(` [DEBUG] GraphQL response:`, JSON.stringify(result, null, 2));
|
|
299
|
+
}
|
|
300
|
+
if (result.errors) {
|
|
301
|
+
console.error(` ⚠️ GraphQL errors on attempt ${attempt}:`, result.errors);
|
|
302
|
+
throw new Error(`GraphQL errors: ${JSON.stringify(result.errors)}`);
|
|
303
|
+
}
|
|
304
|
+
const itemsData = result.data?.node?.items;
|
|
305
|
+
if (!itemsData) {
|
|
306
|
+
console.error(` ⚠️ Invalid response structure on attempt ${attempt}`);
|
|
307
|
+
if (debug) {
|
|
308
|
+
console.error(` [DEBUG] Full response:`, JSON.stringify(result, null, 2));
|
|
309
|
+
}
|
|
310
|
+
throw new Error('Invalid response structure');
|
|
311
|
+
}
|
|
312
|
+
const items = itemsData.nodes || [];
|
|
313
|
+
allItems = allItems.concat(items);
|
|
314
|
+
hasNextPage = itemsData.pageInfo?.hasNextPage || false;
|
|
315
|
+
cursor = itemsData.pageInfo?.endCursor || null;
|
|
316
|
+
if (debug) {
|
|
317
|
+
console.log(` [DEBUG] Found ${items.length} items in this page (total: ${allItems.length}), hasNextPage: ${hasNextPage}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
// Search for the item with matching issue ID
|
|
321
|
+
const item = allItems.find((i) => i.content?.id === issueId);
|
|
322
|
+
if (item) {
|
|
323
|
+
if (attempt > 1) {
|
|
324
|
+
console.log(` ✅ Found project item after ${attempt} attempt(s)`);
|
|
325
|
+
}
|
|
326
|
+
if (debug) {
|
|
327
|
+
console.log(` [DEBUG] Found item ID: ${item.id} for issue ID: ${issueId}`);
|
|
328
|
+
}
|
|
329
|
+
return item.id;
|
|
330
|
+
}
|
|
331
|
+
// If not found and not last attempt, wait and retry
|
|
332
|
+
if (attempt < maxRetries) {
|
|
333
|
+
const waitTime = attempt * 1000; // 1s, 2s, 3s
|
|
334
|
+
console.log(` ⏳ Project item not found (searched ${allItems.length} items), retrying in ${waitTime}ms... (attempt ${attempt}/${maxRetries})`);
|
|
335
|
+
await new Promise(resolve => setTimeout(resolve, waitTime));
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
console.error(` ⚠️ Project item not found after ${maxRetries} attempts (searched ${allItems.length} total items)`);
|
|
339
|
+
if (debug) {
|
|
340
|
+
console.error(` [DEBUG] Issue ID being searched: ${issueId}`);
|
|
341
|
+
console.error(` [DEBUG] Available issue IDs in project:`, allItems.map((i) => i.content?.id).slice(0, 10));
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
const errorMessage = error.message || error.stderr || String(error);
|
|
347
|
+
console.error(` ⚠️ Failed to get project item ID on attempt ${attempt}/${maxRetries}:`, errorMessage);
|
|
348
|
+
if (debug) {
|
|
349
|
+
console.error(` [DEBUG] Full error:`, error);
|
|
350
|
+
}
|
|
351
|
+
// If not last attempt, wait and retry
|
|
352
|
+
if (attempt < maxRetries) {
|
|
353
|
+
const waitTime = attempt * 1000;
|
|
354
|
+
console.log(` ⏳ Retrying in ${waitTime}ms...`);
|
|
355
|
+
await new Promise(resolve => setTimeout(resolve, waitTime));
|
|
356
|
+
}
|
|
229
357
|
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}`;
|
|
233
|
-
const output = (0, child_process_1.execSync)(`gh api graphql -f query="${query.replace(/"/g, '\\"')}"`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
234
|
-
const result = JSON.parse(output);
|
|
235
|
-
const items = result.data?.node?.items?.nodes || [];
|
|
236
|
-
const item = items.find((i) => i.content?.id === issueId);
|
|
237
|
-
return item?.id || null;
|
|
238
|
-
}
|
|
239
|
-
catch (error) {
|
|
240
|
-
console.error('⚠️ Failed to get project item ID:', error);
|
|
241
|
-
return null;
|
|
242
358
|
}
|
|
359
|
+
return null;
|
|
243
360
|
}
|
|
244
361
|
/**
|
|
245
362
|
* Set date field value for a project item
|
|
246
363
|
*/
|
|
247
364
|
async setProjectItemDateField(projectId, itemId, fieldId, date) {
|
|
365
|
+
const debug = process.env.DEBUG === 'true';
|
|
248
366
|
try {
|
|
249
367
|
const mutation = `mutation {
|
|
250
368
|
updateProjectV2ItemFieldValue(
|
|
@@ -262,12 +380,35 @@ class GitHubClientWrapper {
|
|
|
262
380
|
}
|
|
263
381
|
}
|
|
264
382
|
}`;
|
|
383
|
+
if (debug) {
|
|
384
|
+
console.log(` [DEBUG] Executing mutation:`);
|
|
385
|
+
console.log(` [DEBUG] Project ID: ${projectId}`);
|
|
386
|
+
console.log(` [DEBUG] Item ID: ${itemId}`);
|
|
387
|
+
console.log(` [DEBUG] Field ID: ${fieldId}`);
|
|
388
|
+
console.log(` [DEBUG] Date: ${date}`);
|
|
389
|
+
}
|
|
265
390
|
const output = (0, child_process_1.execSync)(`gh api graphql -f query="${mutation.replace(/"/g, '\\"')}"`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
266
391
|
const result = JSON.parse(output);
|
|
267
|
-
|
|
392
|
+
if (debug) {
|
|
393
|
+
console.log(` [DEBUG] Mutation response:`, JSON.stringify(result, null, 2));
|
|
394
|
+
}
|
|
395
|
+
if (result.errors) {
|
|
396
|
+
console.error(` ⚠️ GraphQL errors:`, result.errors);
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
const success = !!result.data?.updateProjectV2ItemFieldValue?.projectV2Item;
|
|
400
|
+
if (!success && debug) {
|
|
401
|
+
console.error(` [DEBUG] Mutation returned no projectV2Item in response`);
|
|
402
|
+
}
|
|
403
|
+
return success;
|
|
268
404
|
}
|
|
269
405
|
catch (error) {
|
|
270
|
-
|
|
406
|
+
const errorMessage = error.message || error.stderr || String(error);
|
|
407
|
+
console.error(` ⚠️ Failed to set project date field: ${errorMessage}`);
|
|
408
|
+
if (debug) {
|
|
409
|
+
console.error(` [DEBUG] Full error:`, error);
|
|
410
|
+
console.error(` [DEBUG] Stack trace:`, error.stack);
|
|
411
|
+
}
|
|
271
412
|
return false;
|
|
272
413
|
}
|
|
273
414
|
}
|
|
@@ -275,70 +416,132 @@ class GitHubClientWrapper {
|
|
|
275
416
|
* Set GitHub Project date fields (Target and Start) for an issue
|
|
276
417
|
*/
|
|
277
418
|
async setProjectDateFields(repo, projectName, issueId, targetDate, startDate) {
|
|
419
|
+
const debug = process.env.DEBUG === 'true';
|
|
278
420
|
try {
|
|
421
|
+
if (debug) {
|
|
422
|
+
console.log(` [DEBUG] Setting project date fields:`);
|
|
423
|
+
console.log(` [DEBUG] Repo: ${repo}`);
|
|
424
|
+
console.log(` [DEBUG] Project: ${projectName}`);
|
|
425
|
+
console.log(` [DEBUG] Issue ID: ${issueId}`);
|
|
426
|
+
console.log(` [DEBUG] Target date: ${targetDate || 'not set'}`);
|
|
427
|
+
console.log(` [DEBUG] Start date: ${startDate || 'not set'}`);
|
|
428
|
+
}
|
|
279
429
|
// Get project node ID
|
|
430
|
+
console.log(` Looking up project "${projectName}"...`);
|
|
280
431
|
const projectId = await this.getProjectNodeId(repo, projectName);
|
|
281
432
|
if (!projectId) {
|
|
282
|
-
console.error(
|
|
433
|
+
console.error(` ⚠️ Project "${projectName}" not found`);
|
|
434
|
+
if (debug) {
|
|
435
|
+
console.error(` [DEBUG] Tried to find project in repo: ${repo}`);
|
|
436
|
+
}
|
|
283
437
|
return false;
|
|
284
438
|
}
|
|
285
|
-
|
|
439
|
+
if (debug) {
|
|
440
|
+
console.log(` [DEBUG] Found project ID: ${projectId}`);
|
|
441
|
+
}
|
|
442
|
+
// Get project item ID (with retry mechanism)
|
|
443
|
+
console.log(` Looking up issue in project...`);
|
|
286
444
|
const itemId = await this.getProjectItemId(projectId, issueId);
|
|
287
445
|
if (!itemId) {
|
|
288
|
-
console.error(
|
|
446
|
+
console.error(` ⚠️ Issue not found in project "${projectName}"`);
|
|
447
|
+
console.error(` ⚠️ This may be due to a timing issue. The issue may appear in the project shortly.`);
|
|
448
|
+
if (debug) {
|
|
449
|
+
console.error(` [DEBUG] Project ID: ${projectId}`);
|
|
450
|
+
console.error(` [DEBUG] Issue ID: ${issueId}`);
|
|
451
|
+
}
|
|
289
452
|
return false;
|
|
290
453
|
}
|
|
454
|
+
if (debug) {
|
|
455
|
+
console.log(` [DEBUG] Found project item ID: ${itemId}`);
|
|
456
|
+
}
|
|
291
457
|
let success = true;
|
|
458
|
+
const results = {};
|
|
292
459
|
// Set Target date field if provided
|
|
293
460
|
if (targetDate) {
|
|
461
|
+
console.log(` Setting Target date field...`);
|
|
294
462
|
const targetFieldId = await this.getProjectFieldId(projectId, 'Target');
|
|
295
463
|
if (targetFieldId) {
|
|
464
|
+
if (debug) {
|
|
465
|
+
console.log(` [DEBUG] Target field ID: ${targetFieldId}`);
|
|
466
|
+
}
|
|
296
467
|
const result = await this.setProjectItemDateField(projectId, itemId, targetFieldId, targetDate);
|
|
468
|
+
results.target = result;
|
|
297
469
|
if (result) {
|
|
298
470
|
console.log(` ✅ Set Target date: ${targetDate}`);
|
|
299
471
|
}
|
|
300
472
|
else {
|
|
301
|
-
console.log(` ⚠️ Failed to set Target date`);
|
|
473
|
+
console.log(` ⚠️ Failed to set Target date: ${targetDate}`);
|
|
474
|
+
if (debug) {
|
|
475
|
+
console.error(` [DEBUG] Mutation may have failed. Check GraphQL response above.`);
|
|
476
|
+
}
|
|
302
477
|
success = false;
|
|
303
478
|
}
|
|
304
479
|
}
|
|
305
480
|
else {
|
|
306
|
-
console.log(` ⚠️ Target field not found in project`);
|
|
481
|
+
console.log(` ⚠️ Target field not found in project "${projectName}"`);
|
|
482
|
+
if (debug) {
|
|
483
|
+
console.error(` [DEBUG] Make sure the project has a "Target" date field configured.`);
|
|
484
|
+
}
|
|
485
|
+
success = false;
|
|
307
486
|
}
|
|
308
487
|
}
|
|
309
488
|
// Set Start date field if provided
|
|
310
489
|
if (startDate) {
|
|
490
|
+
console.log(` Setting Start date field...`);
|
|
311
491
|
const startFieldId = await this.getProjectFieldId(projectId, 'Start');
|
|
312
492
|
if (startFieldId) {
|
|
493
|
+
if (debug) {
|
|
494
|
+
console.log(` [DEBUG] Start field ID: ${startFieldId}`);
|
|
495
|
+
}
|
|
313
496
|
const result = await this.setProjectItemDateField(projectId, itemId, startFieldId, startDate);
|
|
497
|
+
results.start = result;
|
|
314
498
|
if (result) {
|
|
315
499
|
console.log(` ✅ Set Start date: ${startDate}`);
|
|
316
500
|
}
|
|
317
501
|
else {
|
|
318
|
-
console.log(` ⚠️ Failed to set Start date`);
|
|
502
|
+
console.log(` ⚠️ Failed to set Start date: ${startDate}`);
|
|
503
|
+
if (debug) {
|
|
504
|
+
console.error(` [DEBUG] Mutation may have failed. Check GraphQL response above.`);
|
|
505
|
+
}
|
|
319
506
|
success = false;
|
|
320
507
|
}
|
|
321
508
|
}
|
|
322
509
|
else {
|
|
323
|
-
console.log(` ⚠️ Start field not found in project`);
|
|
510
|
+
console.log(` ⚠️ Start field not found in project "${projectName}"`);
|
|
511
|
+
if (debug) {
|
|
512
|
+
console.error(` [DEBUG] Make sure the project has a "Start" date field configured.`);
|
|
513
|
+
}
|
|
514
|
+
success = false;
|
|
324
515
|
}
|
|
325
516
|
}
|
|
517
|
+
// Summary
|
|
518
|
+
if (debug) {
|
|
519
|
+
console.log(` [DEBUG] Date field setting results:`, results);
|
|
520
|
+
}
|
|
521
|
+
if (!success) {
|
|
522
|
+
console.log(` ⚠️ Some date fields failed to set. Check the messages above for details.`);
|
|
523
|
+
}
|
|
326
524
|
return success;
|
|
327
525
|
}
|
|
328
526
|
catch (error) {
|
|
329
|
-
|
|
527
|
+
const errorMessage = error.message || error.stderr || String(error);
|
|
528
|
+
console.error(` ⚠️ Failed to set project date fields: ${errorMessage}`);
|
|
529
|
+
if (debug) {
|
|
530
|
+
console.error(` [DEBUG] Full error:`, error);
|
|
531
|
+
console.error(` [DEBUG] Stack trace:`, error.stack);
|
|
532
|
+
}
|
|
330
533
|
return false;
|
|
331
534
|
}
|
|
332
535
|
}
|
|
333
536
|
/**
|
|
334
|
-
* Get GitHub Project name from issue
|
|
537
|
+
* Get GitHub Project name from issue number
|
|
335
538
|
*/
|
|
336
|
-
async getIssueProject(repo,
|
|
539
|
+
async getIssueProject(repo, issueNumber) {
|
|
337
540
|
try {
|
|
338
541
|
const [owner, name] = repo.split('/');
|
|
339
542
|
const query = `query {
|
|
340
543
|
repository(owner: "${owner}", name: "${name}") {
|
|
341
|
-
issue(
|
|
544
|
+
issue(number: ${issueNumber}) {
|
|
342
545
|
projectItems(first: 10) {
|
|
343
546
|
nodes {
|
|
344
547
|
project {
|