github-issue-tower-defence-management 1.153.4 → 1.153.6
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/issue/ApiV3CheerioRestIssueRepository.js +161 -0
- package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
- package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js +3 -2
- package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js.map +1 -1
- package/bin/domain/usecases/IssueRejectionEvaluator.js +28 -11
- package/bin/domain/usecases/IssueRejectionEvaluator.js.map +1 -1
- package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js +15 -3
- package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +11 -0
- package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +194 -0
- package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +252 -0
- package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.test.ts +55 -0
- package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.ts +5 -4
- package/src/domain/usecases/IssueRejectionEvaluator.ts +49 -15
- package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.test.ts +154 -0
- package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.ts +33 -5
- package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +3 -0
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +3 -0
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
- package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts.map +1 -1
- package/types/domain/usecases/IssueRejectionEvaluator.d.ts +6 -1
- package/types/domain/usecases/IssueRejectionEvaluator.d.ts.map +1 -1
- package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts +1 -1
- package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +1 -0
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IssueRejectionEvaluator.js","sourceRoot":"","sources":["../../../src/domain/usecases/IssueRejectionEvaluator.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"IssueRejectionEvaluator.js","sourceRoot":"","sources":["../../../src/domain/usecases/IssueRejectionEvaluator.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,6 +39,18 @@ class RevertNotReadyReviewQueueIssueUseCase {
|
|
|
39
39
|
const { issues } = await this.issueRepository.getAllIssues(projectId);
|
|
40
40
|
const awaitingQualityCheckIssues = issues.filter((issue) => issue.status === WorkflowStatus_1.AWAITING_QUALITY_CHECK_STATUS_NAME);
|
|
41
41
|
const relatedOpenPrUrlsByIssueUrl = this.buildRelatedOpenPrUrlsByIssueUrl(issues);
|
|
42
|
+
const unreadPullRequests = issues.filter((issue) => issue.status === WorkflowStatus_1.DEFAULT_STATUS_NAME && issue.isPr);
|
|
43
|
+
const labelsNotRequiringPullRequest = (0, resolveLabelsNotRequiringPullRequest_1.resolveLabelsNotRequiringPullRequest)(params);
|
|
44
|
+
const willBeEvaluated = (item) => (0, isAuthorAuthorizedForAutoStatusCheck_1.isAuthorAuthorizedForAutoStatusCheck)(item.author, allowedIssueAuthors) &&
|
|
45
|
+
this.issueRejectionEvaluator.requiresPullRequestEvaluation(item, labelsNotRequiringPullRequest);
|
|
46
|
+
const resolvedOpenPrByUrl = await this.issueRepository.getOpenPullRequests(Array.from(new Set([
|
|
47
|
+
...awaitingQualityCheckIssues
|
|
48
|
+
.filter(willBeEvaluated)
|
|
49
|
+
.flatMap((issue) => relatedOpenPrUrlsByIssueUrl.get(issue.url) ?? []),
|
|
50
|
+
...unreadPullRequests
|
|
51
|
+
.filter(willBeEvaluated)
|
|
52
|
+
.map((pullRequest) => pullRequest.url),
|
|
53
|
+
])));
|
|
42
54
|
for (const issue of awaitingQualityCheckIssues) {
|
|
43
55
|
const hasLlmAgentLabel = issue.labels.some((l) => l === 'llm-agent' || l.startsWith('llm-agent:'));
|
|
44
56
|
if (hasLlmAgentLabel) {
|
|
@@ -48,8 +60,9 @@ class RevertNotReadyReviewQueueIssueUseCase {
|
|
|
48
60
|
continue;
|
|
49
61
|
}
|
|
50
62
|
try {
|
|
51
|
-
const { rejections, approvedPrUrl } = await this.issueRejectionEvaluator.evaluate(issue,
|
|
63
|
+
const { rejections, approvedPrUrl } = await this.issueRejectionEvaluator.evaluate(issue, labelsNotRequiringPullRequest, {
|
|
52
64
|
relatedOpenPrUrls: relatedOpenPrUrlsByIssueUrl.get(issue.url) ?? null,
|
|
65
|
+
resolvedOpenPrByUrl,
|
|
53
66
|
});
|
|
54
67
|
if (rejections.length === 1 &&
|
|
55
68
|
rejections[0].type === 'PULL_REQUEST_NOT_FOUND' &&
|
|
@@ -84,7 +97,6 @@ class RevertNotReadyReviewQueueIssueUseCase {
|
|
|
84
97
|
}
|
|
85
98
|
}
|
|
86
99
|
const projectStory = project.story;
|
|
87
|
-
const unreadPullRequests = issues.filter((issue) => issue.status === WorkflowStatus_1.DEFAULT_STATUS_NAME && issue.isPr);
|
|
88
100
|
for (const pullRequest of unreadPullRequests) {
|
|
89
101
|
const hasLlmAgentLabel = pullRequest.labels.some((l) => l === 'llm-agent' || l.startsWith('llm-agent:'));
|
|
90
102
|
if (hasLlmAgentLabel) {
|
|
@@ -94,7 +106,7 @@ class RevertNotReadyReviewQueueIssueUseCase {
|
|
|
94
106
|
continue;
|
|
95
107
|
}
|
|
96
108
|
try {
|
|
97
|
-
const { rejections } = await this.issueRejectionEvaluator.evaluate(pullRequest,
|
|
109
|
+
const { rejections } = await this.issueRejectionEvaluator.evaluate(pullRequest, labelsNotRequiringPullRequest, { resolvedOpenPrByUrl });
|
|
98
110
|
if (rejections.length > 0) {
|
|
99
111
|
if (!pullRequest.assignees.includes(params.manager)) {
|
|
100
112
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RevertNotReadyReviewQueueIssueUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.ts"],"names":[],"mappings":";;;AAIA,uEAAoE;AACpE,uFAAoF;AACpF,iGAA8F;AAC9F,yFAAsF;AACtF,iGAA8F;AAC9F,+DAIoC;AAEpC,qEAAqE;AACrE,8EAA8E;AAC9E,0EAA0E;AAC1E,6EAA6E;AAC7E,kDAAkD;AAClD,MAAM,0BAA0B,GAAG,CAAC,KAAc,EAAW,EAAE;IAC7D,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,KAAc,EAAW,EAAE,CACjD,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC;AAE1D,MAAa,qCAAqC;IAIhD,YACmB,iBAGhB,EACgB,
|
|
1
|
+
{"version":3,"file":"RevertNotReadyReviewQueueIssueUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.ts"],"names":[],"mappings":";;;AAIA,uEAAoE;AACpE,uFAAoF;AACpF,iGAA8F;AAC9F,yFAAsF;AACtF,iGAA8F;AAC9F,+DAIoC;AAEpC,qEAAqE;AACrE,8EAA8E;AAC9E,0EAA0E;AAC1E,6EAA6E;AAC7E,kDAAkD;AAClD,MAAM,0BAA0B,GAAG,CAAC,KAAc,EAAW,EAAE;IAC7D,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,KAAc,EAAW,EAAE,CACjD,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC;AAE1D,MAAa,qCAAqC;IAIhD,YACmB,iBAGhB,EACgB,eAWhB,EACgB,sBAGhB;QAnBgB,sBAAiB,GAAjB,iBAAiB,CAGjC;QACgB,oBAAe,GAAf,eAAe,CAW/B;QACgB,2BAAsB,GAAtB,sBAAsB,CAGtC;QAQH,QAAG,GAAG,KAAK,EAAE,MAOZ,EAAiB,EAAE;YAClB,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,IAAI,IAAI,CAAC;YAC/D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,kBAAkB,CAC/D,MAAM,CAAC,UAAU,CAClB,CAAC;YACF,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,kCAAkC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;YACzE,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YACnE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CACb,iCAAiC,SAAS,gBAAgB,MAAM,CAAC,UAAU,EAAE,CAC9E,CAAC;YACJ,CAAC;YAED,MAAM,6BAA6B,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAChE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,+CAA8B,CACjD,CAAC;YACF,IAAI,CAAC,6BAA6B,EAAE,CAAC;gBACnC,OAAO;YACT,CAAC;YAED,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YAEtE,MAAM,0BAA0B,GAAG,MAAM,CAAC,MAAM,CAC9C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,mDAAkC,CAC/D,CAAC;YAEF,MAAM,2BAA2B,GAC/B,IAAI,CAAC,gCAAgC,CAAC,MAAM,CAAC,CAAC;YAEhD,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CACtC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,oCAAmB,IAAI,KAAK,CAAC,IAAI,CAC9D,CAAC;YAEF,MAAM,6BAA6B,GACjC,IAAA,2EAAoC,EAAC,MAAM,CAAC,CAAC;YAC/C,MAAM,eAAe,GAAG,CAAC,IAAW,EAAW,EAAE,CAC/C,IAAA,2EAAoC,EAAC,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC;gBACtE,IAAI,CAAC,uBAAuB,CAAC,6BAA6B,CACxD,IAAI,EACJ,6BAA6B,CAC9B,CAAC;YAEJ,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,mBAAmB,CACxE,KAAK,CAAC,IAAI,CACR,IAAI,GAAG,CAAC;gBACN,GAAG,0BAA0B;qBAC1B,MAAM,CAAC,eAAe,CAAC;qBACvB,OAAO,CACN,CAAC,KAAK,EAAE,EAAE,CAAC,2BAA2B,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAC5D;gBACH,GAAG,kBAAkB;qBAClB,MAAM,CAAC,eAAe,CAAC;qBACvB,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC;aACzC,CAAC,CACH,CACF,CAAC;YAEF,KAAK,MAAM,KAAK,IAAI,0BAA0B,EAAE,CAAC;gBAC/C,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CACxC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,WAAW,IAAI,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CACvD,CAAC;gBACF,IAAI,gBAAgB,EAAE,CAAC;oBACrB,SAAS;gBACX,CAAC;gBAED,IACE,CAAC,IAAA,2EAAoC,EAAC,KAAK,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACxE,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,IAAI,CAAC;oBACH,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,GACjC,MAAM,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CACzC,KAAK,EACL,6BAA6B,EAC7B;wBACE,iBAAiB,EACf,2BAA2B,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI;wBACpD,mBAAmB;qBACpB,CACF,CAAC;oBACJ,IACE,UAAU,CAAC,MAAM,KAAK,CAAC;wBACvB,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,wBAAwB;wBAC/C,IAAA,mEAAgC,EAC9B,MAAM,IAAI,CAAC,sBAAsB,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAC7D,CAAC,MAAM,EAAE,EAAE,CACT,IAAA,2EAAoC,EAAC,MAAM,EAAE,mBAAmB,CAAC,CACpE,EACD,CAAC;wBACD,SAAS;oBACX,CAAC;oBACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC1B,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;4BAC9C,SAAS;wBACX,CAAC;wBACD,IAAI,CAAC;4BACH,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,CACrC,OAAO,EACP,KAAK,EACL,6BAA6B,CAAC,EAAE,CACjC,CAAC;wBACJ,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,IAAI,0BAA0B,CAAC,KAAK,CAAC,EAAE,CAAC;gCACtC,OAAO,CAAC,IAAI,CACV,qHAAqH,KAAK,CAAC,GAAG,EAAE,CACjI,CAAC;gCACF,SAAS;4BACX,CAAC;4BACD,MAAM,KAAK,CAAC;wBACd,CAAC;wBACD,MAAM,IAAI,CAAC,sBAAsB,CAAC,aAAa,CAC7C,KAAK,EACL,gCAAgC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpF,CAAC;wBACF,SAAS;oBACX,CAAC;oBAED,MAAM,IAAI,CAAC,+BAA+B,CAAC,iBAAiB,CAC1D,KAAK,CAAC,MAAM,EACZ,aAAa,EACb,MAAM,CAAC,uBAAuB,CAC/B,CAAC;gBACJ,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC1B,OAAO,CAAC,IAAI,CACV,sGAAsG,KAAK,CAAC,GAAG,WAAW,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACnL,CAAC;wBACF,SAAS;oBACX,CAAC;oBACD,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YAED,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;YAEnC,KAAK,MAAM,WAAW,IAAI,kBAAkB,EAAE,CAAC;gBAC7C,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAC9C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,WAAW,IAAI,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CACvD,CAAC;gBACF,IAAI,gBAAgB,EAAE,CAAC;oBACrB,SAAS;gBACX,CAAC;gBAED,IACE,CAAC,IAAA,2EAAoC,EACnC,WAAW,CAAC,MAAM,EAClB,mBAAmB,CACpB,EACD,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,IAAI,CAAC;oBACH,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAChE,WAAW,EACX,6BAA6B,EAC7B,EAAE,mBAAmB,EAAE,CACxB,CAAC;oBACF,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC1B,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;4BACpD,SAAS;wBACX,CAAC;wBACD,IAAI,CAAC;4BACH,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,CACrC,OAAO,EACP,WAAW,EACX,6BAA6B,CAAC,EAAE,CACjC,CAAC;wBACJ,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,IAAI,0BAA0B,CAAC,KAAK,CAAC,EAAE,CAAC;gCACtC,OAAO,CAAC,IAAI,CACV,kHAAkH,WAAW,CAAC,GAAG,EAAE,CACpI,CAAC;gCACF,SAAS;4BACX,CAAC;4BACD,MAAM,KAAK,CAAC;wBACd,CAAC;wBACD,IAAI,YAAY,EAAE,CAAC;4BACjB,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CACpC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,EACnC,WAAW,EACX,YAAY,CAAC,uBAAuB,CAAC,EAAE,CACxC,CAAC;wBACJ,CAAC;wBACD,MAAM,IAAI,CAAC,sBAAsB,CAAC,aAAa,CAC7C,WAAW,EACX,gCAAgC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpF,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC1B,OAAO,CAAC,IAAI,CACV,0GAA0G,WAAW,CAAC,GAAG,WAAW,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC7L,CAAC;wBACF,SAAS;oBACX,CAAC;oBACD,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,+EAA+E;QAC/E,uEAAuE;QACvE,+EAA+E;QAC/E,2EAA2E;QAC3E,kEAAkE;QAClE,2EAA2E;QACnE,qCAAgC,GAAG,CACzC,MAAe,EACQ,EAAE;YACzB,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAuB,CAAC;YAC5D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBAClC,SAAS;gBACX,CAAC;gBACD,KAAK,MAAM,kBAAkB,IAAI,KAAK,CAAC,yBAAyB,EAAE,CAAC;oBACjE,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;oBAC9D,IAAI,QAAQ,EAAE,CAAC;wBACb,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC1B,CAAC;yBAAM,CAAC;wBACN,oBAAoB,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACrE,CAAC;gBACH,CAAC;YACH,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;YAC3C,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,oBAAoB,EAAE,CAAC;gBACtD,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC3C,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;QAtPA,IAAI,CAAC,uBAAuB,GAAG,IAAI,iDAAuB,CAAC,eAAe,CAAC,CAAC;QAC5E,IAAI,CAAC,+BAA+B,GAAG,IAAI,iEAA+B,CACxE,eAAe,CAChB,CAAC;IACJ,CAAC;CAmPF;AAjRD,sFAiRC"}
|
package/package.json
CHANGED
|
@@ -426,6 +426,17 @@ const createStubIssueRepository = (
|
|
|
426
426
|
url === CONSOLE_E2E_AWAITING_QUALITY_CHECK_PR_URL
|
|
427
427
|
? awaitingQualityCheckPullRequest
|
|
428
428
|
: null,
|
|
429
|
+
getOpenPullRequests: async (
|
|
430
|
+
urls: string[],
|
|
431
|
+
): Promise<Map<string, RelatedPullRequest | null>> =>
|
|
432
|
+
new Map(
|
|
433
|
+
urls.map((url) => [
|
|
434
|
+
url,
|
|
435
|
+
url === CONSOLE_E2E_AWAITING_QUALITY_CHECK_PR_URL
|
|
436
|
+
? awaitingQualityCheckPullRequest
|
|
437
|
+
: null,
|
|
438
|
+
]),
|
|
439
|
+
),
|
|
429
440
|
getPullRequestChangedFilePaths: async (): Promise<string[]> => [],
|
|
430
441
|
approvePullRequest: async (): Promise<void> => undefined,
|
|
431
442
|
requestChangesWithInlineComment: async (
|
|
@@ -2339,6 +2339,9 @@ describe('ApiV3CheerioRestIssueRepository', () => {
|
|
|
2339
2339
|
prNumber: number;
|
|
2340
2340
|
reviewThreadsAfter: string | null;
|
|
2341
2341
|
}) => Response | object;
|
|
2342
|
+
slimPullRequestBatch?: (
|
|
2343
|
+
variables: Record<string, unknown>,
|
|
2344
|
+
) => Response | object;
|
|
2342
2345
|
branchRules?: (url: string) => Response | object;
|
|
2343
2346
|
branchDetail?: (url: string) => Response | object;
|
|
2344
2347
|
checkRuns?: (url: string) => Response | object;
|
|
@@ -2363,6 +2366,7 @@ describe('ApiV3CheerioRestIssueRepository', () => {
|
|
|
2363
2366
|
prNumber: number;
|
|
2364
2367
|
reviewThreadsAfter: string | null;
|
|
2365
2368
|
};
|
|
2369
|
+
rawVariables: Record<string, unknown>;
|
|
2366
2370
|
};
|
|
2367
2371
|
|
|
2368
2372
|
const parseGraphqlRequestBody = (init?: RequestInit): GraphqlRequestBody => {
|
|
@@ -2401,6 +2405,7 @@ describe('ApiV3CheerioRestIssueRepository', () => {
|
|
|
2401
2405
|
return {
|
|
2402
2406
|
query: parsed.query,
|
|
2403
2407
|
variables: { owner, repo, prNumber, reviewThreadsAfter },
|
|
2408
|
+
rawVariables: Object.fromEntries(Object.entries(variables)),
|
|
2404
2409
|
};
|
|
2405
2410
|
};
|
|
2406
2411
|
|
|
@@ -2421,6 +2426,12 @@ describe('ApiV3CheerioRestIssueRepository', () => {
|
|
|
2421
2426
|
) {
|
|
2422
2427
|
return toResponse(routes.mergeability());
|
|
2423
2428
|
}
|
|
2429
|
+
if (
|
|
2430
|
+
body.query.includes('PullRequestSlimStatusBatch') &&
|
|
2431
|
+
routes.slimPullRequestBatch
|
|
2432
|
+
) {
|
|
2433
|
+
return toResponse(routes.slimPullRequestBatch(body.rawVariables));
|
|
2434
|
+
}
|
|
2424
2435
|
if (body.query.includes('headRefOid') && routes.slimPullRequest) {
|
|
2425
2436
|
return toResponse(routes.slimPullRequest(body.variables));
|
|
2426
2437
|
}
|
|
@@ -2472,6 +2483,14 @@ describe('ApiV3CheerioRestIssueRepository', () => {
|
|
|
2472
2483
|
body.includes('mergeStateStatus'),
|
|
2473
2484
|
);
|
|
2474
2485
|
|
|
2486
|
+
const countSlimPullRequestBatchQueries = (fetchSpy: FetchSpy): number =>
|
|
2487
|
+
countCallsMatching(
|
|
2488
|
+
fetchSpy,
|
|
2489
|
+
(url, body) =>
|
|
2490
|
+
url === 'https://api.github.com/graphql' &&
|
|
2491
|
+
body.includes('PullRequestSlimStatusBatch'),
|
|
2492
|
+
);
|
|
2493
|
+
|
|
2475
2494
|
const buildSlimPullRequestResponse = (
|
|
2476
2495
|
overrides: {
|
|
2477
2496
|
url?: string;
|
|
@@ -2508,6 +2527,181 @@ describe('ApiV3CheerioRestIssueRepository', () => {
|
|
|
2508
2527
|
},
|
|
2509
2528
|
});
|
|
2510
2529
|
|
|
2530
|
+
const buildSlimPullRequestNode = (
|
|
2531
|
+
overrides: Parameters<typeof buildSlimPullRequestResponse>[0] = {},
|
|
2532
|
+
) => buildSlimPullRequestResponse(overrides).data.repository.pullRequest;
|
|
2533
|
+
|
|
2534
|
+
describe('getOpenPullRequests batched resolution', () => {
|
|
2535
|
+
afterEach(() => {
|
|
2536
|
+
jest.restoreAllMocks();
|
|
2537
|
+
});
|
|
2538
|
+
|
|
2539
|
+
const prUrlOf = (prNumber: number): string =>
|
|
2540
|
+
`https://github.com/HiromiShikata/test-repository/pull/${prNumber}`;
|
|
2541
|
+
|
|
2542
|
+
it('resolves every pull request state in one GraphQL request', async () => {
|
|
2543
|
+
const prNumbers = [31, 32, 33];
|
|
2544
|
+
const capturedVariables: Record<string, unknown>[] = [];
|
|
2545
|
+
const fetchSpy = mockFetchRoutes({
|
|
2546
|
+
slimPullRequestBatch: (variables) => {
|
|
2547
|
+
capturedVariables.push(variables);
|
|
2548
|
+
return {
|
|
2549
|
+
data: Object.fromEntries(
|
|
2550
|
+
prNumbers.map((prNumber, index) => [
|
|
2551
|
+
`pullRequest${index}`,
|
|
2552
|
+
{
|
|
2553
|
+
pullRequest: buildSlimPullRequestNode({
|
|
2554
|
+
url: prUrlOf(prNumber),
|
|
2555
|
+
headRefName: `feature-${prNumber}`,
|
|
2556
|
+
}),
|
|
2557
|
+
},
|
|
2558
|
+
]),
|
|
2559
|
+
),
|
|
2560
|
+
};
|
|
2561
|
+
},
|
|
2562
|
+
checkRuns: () => ({
|
|
2563
|
+
total_count: 1,
|
|
2564
|
+
check_runs: [{ id: 1, name: 'ci', conclusion: 'success' }],
|
|
2565
|
+
}),
|
|
2566
|
+
});
|
|
2567
|
+
|
|
2568
|
+
const { repository } = createApiV3CheerioRestIssueRepository();
|
|
2569
|
+
const resolved = await repository.getOpenPullRequests(
|
|
2570
|
+
prNumbers.map(prUrlOf),
|
|
2571
|
+
);
|
|
2572
|
+
|
|
2573
|
+
expect(countSlimPullRequestBatchQueries(fetchSpy)).toBe(1);
|
|
2574
|
+
expect(capturedVariables).toHaveLength(1);
|
|
2575
|
+
expect(capturedVariables[0].prNumber0).toBe(31);
|
|
2576
|
+
expect(capturedVariables[0].prNumber2).toBe(33);
|
|
2577
|
+
expect(Array.from(resolved.keys())).toEqual(prNumbers.map(prUrlOf));
|
|
2578
|
+
for (const prNumber of prNumbers) {
|
|
2579
|
+
expect(resolved.get(prUrlOf(prNumber))?.branchName).toBe(
|
|
2580
|
+
`feature-${prNumber}`,
|
|
2581
|
+
);
|
|
2582
|
+
}
|
|
2583
|
+
});
|
|
2584
|
+
|
|
2585
|
+
it('resolves a pull request the batch reports as not found to an absent pull request', async () => {
|
|
2586
|
+
mockFetchRoutes({
|
|
2587
|
+
slimPullRequestBatch: () => ({
|
|
2588
|
+
data: { pullRequest0: null },
|
|
2589
|
+
errors: [
|
|
2590
|
+
{
|
|
2591
|
+
message: 'Could not resolve to a PullRequest',
|
|
2592
|
+
type: 'NOT_FOUND',
|
|
2593
|
+
path: ['pullRequest0', 'pullRequest'],
|
|
2594
|
+
},
|
|
2595
|
+
],
|
|
2596
|
+
}),
|
|
2597
|
+
});
|
|
2598
|
+
|
|
2599
|
+
const { repository } = createApiV3CheerioRestIssueRepository();
|
|
2600
|
+
const resolved = await repository.getOpenPullRequests([prUrlOf(31)]);
|
|
2601
|
+
|
|
2602
|
+
expect(resolved.has(prUrlOf(31))).toBe(true);
|
|
2603
|
+
expect(resolved.get(prUrlOf(31))).toBeNull();
|
|
2604
|
+
});
|
|
2605
|
+
|
|
2606
|
+
it('omits a pull request whose alias failed for a reason other than not found so an unknown state is not read as absent', async () => {
|
|
2607
|
+
mockFetchRoutes({
|
|
2608
|
+
slimPullRequestBatch: () => ({
|
|
2609
|
+
data: { pullRequest0: null },
|
|
2610
|
+
errors: [
|
|
2611
|
+
{
|
|
2612
|
+
message: 'Something went wrong while executing your query',
|
|
2613
|
+
type: 'SERVICE_UNAVAILABLE',
|
|
2614
|
+
path: ['pullRequest0', 'pullRequest'],
|
|
2615
|
+
},
|
|
2616
|
+
],
|
|
2617
|
+
}),
|
|
2618
|
+
});
|
|
2619
|
+
|
|
2620
|
+
const { repository } = createApiV3CheerioRestIssueRepository();
|
|
2621
|
+
const resolved = await repository.getOpenPullRequests([prUrlOf(31)]);
|
|
2622
|
+
|
|
2623
|
+
expect(resolved.has(prUrlOf(31))).toBe(false);
|
|
2624
|
+
});
|
|
2625
|
+
|
|
2626
|
+
it('omits a pull request whose review threads do not fit one page so it is resolved by the paginating path', async () => {
|
|
2627
|
+
mockFetchRoutes({
|
|
2628
|
+
slimPullRequestBatch: () => ({
|
|
2629
|
+
data: {
|
|
2630
|
+
pullRequest0: {
|
|
2631
|
+
pullRequest: buildSlimPullRequestNode({
|
|
2632
|
+
reviewThreads: {
|
|
2633
|
+
pageInfo: { endCursor: 'cursor-1', hasNextPage: true },
|
|
2634
|
+
nodes: [{ isResolved: true }],
|
|
2635
|
+
},
|
|
2636
|
+
}),
|
|
2637
|
+
},
|
|
2638
|
+
},
|
|
2639
|
+
}),
|
|
2640
|
+
});
|
|
2641
|
+
|
|
2642
|
+
const { repository } = createApiV3CheerioRestIssueRepository();
|
|
2643
|
+
const resolved = await repository.getOpenPullRequests([prUrlOf(31)]);
|
|
2644
|
+
|
|
2645
|
+
expect(resolved.has(prUrlOf(31))).toBe(false);
|
|
2646
|
+
});
|
|
2647
|
+
|
|
2648
|
+
it('leaves every url of a failed batch unresolved so the caller falls back to the single query', async () => {
|
|
2649
|
+
mockFetchRoutes({
|
|
2650
|
+
slimPullRequestBatch: () => ({
|
|
2651
|
+
data: null,
|
|
2652
|
+
errors: [
|
|
2653
|
+
{ message: 'Something went wrong while executing your query' },
|
|
2654
|
+
],
|
|
2655
|
+
}),
|
|
2656
|
+
});
|
|
2657
|
+
|
|
2658
|
+
const { repository } = createApiV3CheerioRestIssueRepository();
|
|
2659
|
+
const resolved = await repository.getOpenPullRequests([
|
|
2660
|
+
prUrlOf(31),
|
|
2661
|
+
prUrlOf(32),
|
|
2662
|
+
]);
|
|
2663
|
+
|
|
2664
|
+
expect(resolved.size).toBe(0);
|
|
2665
|
+
});
|
|
2666
|
+
|
|
2667
|
+
it('resolves an issue url to an absent pull request without issuing any request', async () => {
|
|
2668
|
+
const fetchSpy = mockFetchRoutes({});
|
|
2669
|
+
const issueUrl =
|
|
2670
|
+
'https://github.com/HiromiShikata/test-repository/issues/31';
|
|
2671
|
+
|
|
2672
|
+
const { repository } = createApiV3CheerioRestIssueRepository();
|
|
2673
|
+
const resolved = await repository.getOpenPullRequests([issueUrl]);
|
|
2674
|
+
|
|
2675
|
+
expect(resolved.get(issueUrl)).toBeNull();
|
|
2676
|
+
expect(fetchSpy).not.toHaveBeenCalled();
|
|
2677
|
+
});
|
|
2678
|
+
|
|
2679
|
+
it('splits more pull requests than one batch holds into separate GraphQL requests', async () => {
|
|
2680
|
+
const prNumbers = Array.from({ length: 101 }, (_, index) => 1000 + index);
|
|
2681
|
+
const fetchSpy = mockFetchRoutes({
|
|
2682
|
+
slimPullRequestBatch: (variables) => ({
|
|
2683
|
+
data: Object.fromEntries(
|
|
2684
|
+
Object.keys(variables)
|
|
2685
|
+
.filter((name) => name.startsWith('prNumber'))
|
|
2686
|
+
.map((name) => [
|
|
2687
|
+
`pullRequest${name.slice('prNumber'.length)}`,
|
|
2688
|
+
{ pullRequest: buildSlimPullRequestNode() },
|
|
2689
|
+
]),
|
|
2690
|
+
),
|
|
2691
|
+
}),
|
|
2692
|
+
checkRuns: () => ({ total_count: 0, check_runs: [] }),
|
|
2693
|
+
});
|
|
2694
|
+
|
|
2695
|
+
const { repository } = createApiV3CheerioRestIssueRepository();
|
|
2696
|
+
const resolved = await repository.getOpenPullRequests(
|
|
2697
|
+
prNumbers.map(prUrlOf),
|
|
2698
|
+
);
|
|
2699
|
+
|
|
2700
|
+
expect(countSlimPullRequestBatchQueries(fetchSpy)).toBe(2);
|
|
2701
|
+
expect(resolved.size).toBe(prNumbers.length);
|
|
2702
|
+
});
|
|
2703
|
+
});
|
|
2704
|
+
|
|
2511
2705
|
describe('getOpenPullRequest CI state computation', () => {
|
|
2512
2706
|
afterEach(() => {
|
|
2513
2707
|
jest.restoreAllMocks();
|
|
@@ -108,6 +108,43 @@ type PrStatusComputationData = {
|
|
|
108
108
|
}>;
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
+
// One GraphQL query carrying this many aliased pull requests costs the same
|
|
112
|
+
// single rate-limit point as a query carrying one, measured against the live
|
|
113
|
+
// API by reading the rateLimit cost field it returns.
|
|
114
|
+
const SLIM_PULL_REQUEST_BATCH_SIZE = 100;
|
|
115
|
+
const SLIM_PULL_REQUEST_REVIEW_THREADS_PAGE_SIZE = 100;
|
|
116
|
+
|
|
117
|
+
type SlimPullRequestNodeResponse = {
|
|
118
|
+
url: string;
|
|
119
|
+
state: string;
|
|
120
|
+
isDraft?: boolean;
|
|
121
|
+
headRefName?: string;
|
|
122
|
+
baseRefName?: string;
|
|
123
|
+
mergeable?: string;
|
|
124
|
+
headRefOid?: string;
|
|
125
|
+
reviewThreads?: {
|
|
126
|
+
pageInfo: {
|
|
127
|
+
endCursor: string | null;
|
|
128
|
+
hasNextPage: boolean;
|
|
129
|
+
};
|
|
130
|
+
nodes: Array<{
|
|
131
|
+
isResolved: boolean;
|
|
132
|
+
}>;
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
type SlimPullRequestBatchResponse = {
|
|
137
|
+
data?: Record<
|
|
138
|
+
string,
|
|
139
|
+
{ pullRequest?: SlimPullRequestNodeResponse | null } | null
|
|
140
|
+
> | null;
|
|
141
|
+
errors?: Array<{
|
|
142
|
+
message: string;
|
|
143
|
+
type?: string;
|
|
144
|
+
path?: Array<string | number>;
|
|
145
|
+
}>;
|
|
146
|
+
};
|
|
147
|
+
|
|
111
148
|
type SlimPullRequestResponse = {
|
|
112
149
|
data?: {
|
|
113
150
|
repository?: {
|
|
@@ -206,6 +243,13 @@ function isSlimPullRequestResponse(
|
|
|
206
243
|
return true;
|
|
207
244
|
}
|
|
208
245
|
|
|
246
|
+
function isSlimPullRequestBatchResponse(
|
|
247
|
+
value: unknown,
|
|
248
|
+
): value is SlimPullRequestBatchResponse {
|
|
249
|
+
if (typeof value !== 'object' || value === null) return false;
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
|
|
209
253
|
function isBranchRulesResponse(
|
|
210
254
|
value: unknown,
|
|
211
255
|
): value is BranchRulesResponseItem[] {
|
|
@@ -1691,6 +1735,214 @@ export class ApiV3CheerioRestIssueRepository
|
|
|
1691
1735
|
return this.buildRelatedPullRequestFromSlim(owner, repo, slimPullRequest);
|
|
1692
1736
|
};
|
|
1693
1737
|
|
|
1738
|
+
// Resolves many pull requests with one GraphQL query per hundred instead of
|
|
1739
|
+
// one query per pull request. A URL this cannot settle is left out of the
|
|
1740
|
+
// returned map rather than mapped to null, so the caller falls back to
|
|
1741
|
+
// getOpenPullRequest for it and an unknown state is never mistaken for an
|
|
1742
|
+
// absent pull request.
|
|
1743
|
+
getOpenPullRequests = async (
|
|
1744
|
+
prUrls: string[],
|
|
1745
|
+
): Promise<Map<string, RelatedPullRequest | null>> => {
|
|
1746
|
+
const resolved = new Map<string, RelatedPullRequest | null>();
|
|
1747
|
+
const parsedByUrl = new Map<
|
|
1748
|
+
string,
|
|
1749
|
+
{ owner: string; repo: string; prNumber: number }
|
|
1750
|
+
>();
|
|
1751
|
+
for (const prUrl of Array.from(new Set(prUrls))) {
|
|
1752
|
+
const parsedUrl = this.parseIssueUrl(prUrl);
|
|
1753
|
+
if (!parsedUrl.isPr) {
|
|
1754
|
+
resolved.set(prUrl, null);
|
|
1755
|
+
continue;
|
|
1756
|
+
}
|
|
1757
|
+
parsedByUrl.set(prUrl, {
|
|
1758
|
+
owner: parsedUrl.owner,
|
|
1759
|
+
repo: parsedUrl.repo,
|
|
1760
|
+
prNumber: parsedUrl.issueNumber,
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
const urlsToFetch = Array.from(parsedByUrl.keys());
|
|
1765
|
+
for (
|
|
1766
|
+
let start = 0;
|
|
1767
|
+
start < urlsToFetch.length;
|
|
1768
|
+
start += SLIM_PULL_REQUEST_BATCH_SIZE
|
|
1769
|
+
) {
|
|
1770
|
+
const batchUrls = urlsToFetch.slice(
|
|
1771
|
+
start,
|
|
1772
|
+
start + SLIM_PULL_REQUEST_BATCH_SIZE,
|
|
1773
|
+
);
|
|
1774
|
+
let slimByUrl: Map<string, SlimPullRequest | null>;
|
|
1775
|
+
try {
|
|
1776
|
+
slimByUrl = await this.fetchSlimPullRequestsInOneQuery(
|
|
1777
|
+
batchUrls.map((prUrl) => ({
|
|
1778
|
+
prUrl,
|
|
1779
|
+
...this.requireParsedPullRequest(parsedByUrl, prUrl),
|
|
1780
|
+
})),
|
|
1781
|
+
);
|
|
1782
|
+
} catch (error) {
|
|
1783
|
+
console.warn(
|
|
1784
|
+
`ApiV3CheerioRestIssueRepository: batched pull request status query failed, leaving ${batchUrls.length} pull request(s) to per-request resolution. error: ${error instanceof Error ? error.message : String(error)}`,
|
|
1785
|
+
);
|
|
1786
|
+
continue;
|
|
1787
|
+
}
|
|
1788
|
+
for (const prUrl of batchUrls) {
|
|
1789
|
+
if (!slimByUrl.has(prUrl)) {
|
|
1790
|
+
continue;
|
|
1791
|
+
}
|
|
1792
|
+
const slimPullRequest = slimByUrl.get(prUrl) ?? null;
|
|
1793
|
+
if (!slimPullRequest || slimPullRequest.state !== 'OPEN') {
|
|
1794
|
+
resolved.set(prUrl, null);
|
|
1795
|
+
continue;
|
|
1796
|
+
}
|
|
1797
|
+
const parsed = this.requireParsedPullRequest(parsedByUrl, prUrl);
|
|
1798
|
+
try {
|
|
1799
|
+
resolved.set(
|
|
1800
|
+
prUrl,
|
|
1801
|
+
await this.buildRelatedPullRequestFromSlim(
|
|
1802
|
+
parsed.owner,
|
|
1803
|
+
parsed.repo,
|
|
1804
|
+
slimPullRequest,
|
|
1805
|
+
),
|
|
1806
|
+
);
|
|
1807
|
+
} catch (error) {
|
|
1808
|
+
console.warn(
|
|
1809
|
+
`ApiV3CheerioRestIssueRepository: building the pull request status failed, leaving it to per-request resolution. prUrl: ${prUrl} error: ${error instanceof Error ? error.message : String(error)}`,
|
|
1810
|
+
);
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
return resolved;
|
|
1815
|
+
};
|
|
1816
|
+
|
|
1817
|
+
private requireParsedPullRequest = (
|
|
1818
|
+
parsedByUrl: Map<string, { owner: string; repo: string; prNumber: number }>,
|
|
1819
|
+
prUrl: string,
|
|
1820
|
+
): { owner: string; repo: string; prNumber: number } => {
|
|
1821
|
+
const parsed = parsedByUrl.get(prUrl);
|
|
1822
|
+
if (!parsed) {
|
|
1823
|
+
throw new Error(`Pull request URL was not parsed: ${prUrl}`);
|
|
1824
|
+
}
|
|
1825
|
+
return parsed;
|
|
1826
|
+
};
|
|
1827
|
+
|
|
1828
|
+
// A pull request whose review threads do not fit the first page is omitted
|
|
1829
|
+
// from the returned map, so the caller resolves it through the paginating
|
|
1830
|
+
// single-pull-request path and the resolved-thread state stays complete.
|
|
1831
|
+
private fetchSlimPullRequestsInOneQuery = async (
|
|
1832
|
+
references: {
|
|
1833
|
+
prUrl: string;
|
|
1834
|
+
owner: string;
|
|
1835
|
+
repo: string;
|
|
1836
|
+
prNumber: number;
|
|
1837
|
+
}[],
|
|
1838
|
+
): Promise<Map<string, SlimPullRequest | null>> => {
|
|
1839
|
+
const aliasOf = (index: number): string => `pullRequest${index}`;
|
|
1840
|
+
const variableDeclarations = references
|
|
1841
|
+
.map(
|
|
1842
|
+
(_, index) =>
|
|
1843
|
+
`$owner${index}: String!, $repo${index}: String!, $prNumber${index}: Int!`,
|
|
1844
|
+
)
|
|
1845
|
+
.join(', ');
|
|
1846
|
+
const selections = references
|
|
1847
|
+
.map(
|
|
1848
|
+
(
|
|
1849
|
+
_,
|
|
1850
|
+
index,
|
|
1851
|
+
) => ` ${aliasOf(index)}: repository(owner: $owner${index}, name: $repo${index}) {
|
|
1852
|
+
pullRequest(number: $prNumber${index}) {
|
|
1853
|
+
url
|
|
1854
|
+
state
|
|
1855
|
+
isDraft
|
|
1856
|
+
headRefName
|
|
1857
|
+
baseRefName
|
|
1858
|
+
mergeable
|
|
1859
|
+
headRefOid
|
|
1860
|
+
reviewThreads(first: ${SLIM_PULL_REQUEST_REVIEW_THREADS_PAGE_SIZE}) {
|
|
1861
|
+
pageInfo {
|
|
1862
|
+
endCursor
|
|
1863
|
+
hasNextPage
|
|
1864
|
+
}
|
|
1865
|
+
nodes {
|
|
1866
|
+
isResolved
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
}`,
|
|
1871
|
+
)
|
|
1872
|
+
.join('\n');
|
|
1873
|
+
const query = `query PullRequestSlimStatusBatch(${variableDeclarations}) {\n${selections}\n}`;
|
|
1874
|
+
const variables: Record<string, string | number> = {};
|
|
1875
|
+
references.forEach((reference, index) => {
|
|
1876
|
+
variables[`owner${index}`] = reference.owner;
|
|
1877
|
+
variables[`repo${index}`] = reference.repo;
|
|
1878
|
+
variables[`prNumber${index}`] = reference.prNumber;
|
|
1879
|
+
});
|
|
1880
|
+
|
|
1881
|
+
const response = await this.fetchWithRateLimitRetry(() =>
|
|
1882
|
+
fetchGithubGraphql({ ghToken: this.ghToken, query, variables }),
|
|
1883
|
+
);
|
|
1884
|
+
if (!response.ok) {
|
|
1885
|
+
throw new Error(
|
|
1886
|
+
`Failed to fetch pull requests from GitHub GraphQL API: HTTP ${response.status}`,
|
|
1887
|
+
);
|
|
1888
|
+
}
|
|
1889
|
+
const responseData: unknown = await response.json();
|
|
1890
|
+
if (!isSlimPullRequestBatchResponse(responseData)) {
|
|
1891
|
+
throw new Error('Unexpected response shape when fetching pull requests');
|
|
1892
|
+
}
|
|
1893
|
+
const errors = responseData.errors || [];
|
|
1894
|
+
const notFoundAliases = new Set(
|
|
1895
|
+
errors
|
|
1896
|
+
.filter((error) => error.type === 'NOT_FOUND')
|
|
1897
|
+
.map((error) => String(error.path?.[0] ?? '')),
|
|
1898
|
+
);
|
|
1899
|
+
const otherErrorAliases = new Set(
|
|
1900
|
+
errors
|
|
1901
|
+
.filter((error) => error.type !== 'NOT_FOUND')
|
|
1902
|
+
.map((error) => String(error.path?.[0] ?? '')),
|
|
1903
|
+
);
|
|
1904
|
+
if (!responseData.data) {
|
|
1905
|
+
throw new Error(`GraphQL errors: ${JSON.stringify(errors)}`);
|
|
1906
|
+
}
|
|
1907
|
+
const unattributedError = errors.some(
|
|
1908
|
+
(error) => error.type !== 'NOT_FOUND' && !error.path,
|
|
1909
|
+
);
|
|
1910
|
+
if (unattributedError) {
|
|
1911
|
+
throw new Error(`GraphQL errors: ${JSON.stringify(errors)}`);
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
const slimByUrl = new Map<string, SlimPullRequest | null>();
|
|
1915
|
+
references.forEach((reference, index) => {
|
|
1916
|
+
const alias = aliasOf(index);
|
|
1917
|
+
if (otherErrorAliases.has(alias)) {
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
const node = responseData.data?.[alias]?.pullRequest ?? null;
|
|
1921
|
+
if (!node) {
|
|
1922
|
+
if (notFoundAliases.has(alias) || !errors.length) {
|
|
1923
|
+
slimByUrl.set(reference.prUrl, null);
|
|
1924
|
+
}
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
if (node.reviewThreads?.pageInfo.hasNextPage === true) {
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
slimByUrl.set(reference.prUrl, {
|
|
1931
|
+
url: node.url,
|
|
1932
|
+
state: node.state,
|
|
1933
|
+
isDraft: node.isDraft,
|
|
1934
|
+
headRefName: node.headRefName,
|
|
1935
|
+
baseRefName: node.baseRefName,
|
|
1936
|
+
mergeable: node.mergeable,
|
|
1937
|
+
headRefOid: node.headRefOid,
|
|
1938
|
+
reviewThreads: (node.reviewThreads?.nodes || []).map((thread) => ({
|
|
1939
|
+
isResolved: thread.isResolved,
|
|
1940
|
+
})),
|
|
1941
|
+
});
|
|
1942
|
+
});
|
|
1943
|
+
return slimByUrl;
|
|
1944
|
+
};
|
|
1945
|
+
|
|
1694
1946
|
closePullRequest = async (prUrl: string): Promise<void> => {
|
|
1695
1947
|
const { owner, repo, issueNumber: prNumber } = this.parseIssueUrl(prUrl);
|
|
1696
1948
|
const response = await this.fetchWithRateLimitRetry(() =>
|