github-issue-tower-defence-management 1.148.15 → 1.148.17

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>TDPM Console</title>
7
- <script type="module" crossorigin src="/assets/index-DY-3a7sI.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-UQt5L756.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-Dihcph6j.css">
9
9
  </head>
10
10
  <body>
@@ -1115,12 +1115,128 @@ describe('NotifyFinishedIssuePreparationUseCase', () => {
1115
1115
  expect.anything(),
1116
1116
  expect.stringContaining('PULL_REQUEST_NOT_FOUND'),
1117
1117
  );
1118
+ expect(mockIssueRepository.update).toHaveBeenCalledWith(
1119
+ expect.objectContaining({
1120
+ status: 'Awaiting Workspace',
1121
+ }),
1122
+ mockProject,
1123
+ );
1124
+ });
1125
+
1126
+ it('should return the issue to Awaiting Workspace and say why when the last report declares pullRequestRequired as false', async () => {
1127
+ const issue = createMockIssue({
1128
+ url: 'https://github.com/user/repo/issues/1',
1129
+ status: 'Preparation',
1130
+ });
1131
+
1132
+ mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
1133
+ mockIssueRepository.get.mockResolvedValue(issue);
1134
+ mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
1135
+ createMockComment({
1136
+ content:
1137
+ 'From: :robot: Test report\n```json\n{"pullRequestRequired": false, "nextStep": null}\n```',
1138
+ }),
1139
+ ]);
1140
+ mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([]);
1141
+
1142
+ await useCase.run({
1143
+ projectUrl: 'https://github.com/users/user/projects/1',
1144
+ issueUrl: 'https://github.com/user/repo/issues/1',
1145
+ thresholdForAutoReject: 3,
1146
+ workflowBlockerResolvedWebhookUrl: null,
1147
+ allowedIssueAuthors: null,
1148
+ });
1149
+
1150
+ expect(mockIssueRepository.updateStatus).toHaveBeenCalledWith(
1151
+ mockProject,
1152
+ expect.objectContaining({ url: 'https://github.com/user/repo/issues/1' }),
1153
+ 'awaiting-workspace-id',
1154
+ );
1155
+ expect(mockIssueCommentRepository.createComment).toHaveBeenCalledWith(
1156
+ expect.objectContaining({ url: 'https://github.com/user/repo/issues/1' }),
1157
+ expect.stringContaining(
1158
+ 'Auto Status Check: RETURNED_TO_AWAITING_WORKSPACE',
1159
+ ),
1160
+ );
1161
+ });
1162
+
1163
+ it('should take the Awaiting Quality Check path when the declaration arrives again after an earlier return to Awaiting Workspace', async () => {
1164
+ const issue = createMockIssue({
1165
+ url: 'https://github.com/user/repo/issues/1',
1166
+ status: 'Preparation',
1167
+ });
1168
+
1169
+ mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
1170
+ mockIssueRepository.get.mockResolvedValue(issue);
1171
+ mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
1172
+ createMockComment({
1173
+ content:
1174
+ 'Auto Status Check: RETURNED_TO_AWAITING_WORKSPACE\nThe report declared that this task needs no pull request.',
1175
+ }),
1176
+ createMockComment({
1177
+ content:
1178
+ 'From: :robot: Test report\n```json\n{"pullRequestRequired": false, "nextStep": null}\n```',
1179
+ }),
1180
+ ]);
1181
+ mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([]);
1182
+
1183
+ await useCase.run({
1184
+ projectUrl: 'https://github.com/users/user/projects/1',
1185
+ issueUrl: 'https://github.com/user/repo/issues/1',
1186
+ thresholdForAutoReject: 3,
1187
+ workflowBlockerResolvedWebhookUrl: null,
1188
+ allowedIssueAuthors: null,
1189
+ });
1190
+
1118
1191
  expect(mockIssueRepository.update).toHaveBeenCalledWith(
1119
1192
  expect.objectContaining({
1120
1193
  status: 'Awaiting Quality Check',
1121
1194
  }),
1122
1195
  mockProject,
1123
1196
  );
1197
+ expect(mockIssueCommentRepository.createComment).not.toHaveBeenCalledWith(
1198
+ expect.anything(),
1199
+ expect.stringContaining(
1200
+ 'Auto Status Check: RETURNED_TO_AWAITING_WORKSPACE',
1201
+ ),
1202
+ );
1203
+ });
1204
+
1205
+ it('should still return the issue to Awaiting Workspace when the earlier return comment came from an untrusted author', async () => {
1206
+ const issue = createMockIssue({
1207
+ url: 'https://github.com/user/repo/issues/1',
1208
+ status: 'Preparation',
1209
+ });
1210
+
1211
+ mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
1212
+ mockIssueRepository.get.mockResolvedValue(issue);
1213
+ mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
1214
+ createMockComment({
1215
+ author: 'attacker',
1216
+ content:
1217
+ 'Auto Status Check: RETURNED_TO_AWAITING_WORKSPACE\nInjected by someone who is not the agent bot.',
1218
+ }),
1219
+ createMockComment({
1220
+ author: 'trusted-bot',
1221
+ content:
1222
+ 'From: :robot: Test report\n```json\n{"pullRequestRequired": false, "nextStep": null}\n```',
1223
+ }),
1224
+ ]);
1225
+ mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([]);
1226
+
1227
+ await useCase.run({
1228
+ projectUrl: 'https://github.com/users/user/projects/1',
1229
+ issueUrl: 'https://github.com/user/repo/issues/1',
1230
+ thresholdForAutoReject: 3,
1231
+ workflowBlockerResolvedWebhookUrl: null,
1232
+ allowedIssueAuthors: ['trusted-bot'],
1233
+ });
1234
+
1235
+ expect(mockIssueRepository.updateStatus).toHaveBeenCalledWith(
1236
+ mockProject,
1237
+ expect.objectContaining({ url: 'https://github.com/user/repo/issues/1' }),
1238
+ 'awaiting-workspace-id',
1239
+ );
1124
1240
  });
1125
1241
 
1126
1242
  it('should still reject a draft PR when the last report declares pullRequestRequired as false', async () => {
@@ -37,6 +37,12 @@ export class IllegalIssueStatusError extends Error {
37
37
  type RejectedReasonType =
38
38
  'NO_REPORT_FROM_AGENT_BOT' | 'REPORT_HAS_NEXT_STEP' | PrRejectedReasonType;
39
39
 
40
+ const RETURNED_TO_AWAITING_WORKSPACE_MESSAGE_HEAD =
41
+ 'Auto Status Check: RETURNED_TO_AWAITING_WORKSPACE';
42
+
43
+ const RETURNED_TO_AWAITING_WORKSPACE_MESSAGE = `${RETURNED_TO_AWAITING_WORKSPACE_MESSAGE_HEAD}
44
+ The last report declared that this task needs no pull request, so the task returns to the workspace queue to run under the agent its label selects. A later report carrying the same declaration takes the awaiting quality check path instead of returning here again.`;
45
+
40
46
  export class NotifyFinishedIssuePreparationUseCase {
41
47
  private readonly issueRejectionEvaluator: IssueRejectionEvaluator;
42
48
  private readonly changeTargetPullRequestApprover: ChangeTargetPullRequestApprover;
@@ -234,6 +240,31 @@ export class NotifyFinishedIssuePreparationUseCase {
234
240
  return;
235
241
  }
236
242
 
243
+ if (
244
+ rejections.length <= 0 &&
245
+ isPullRequestDeclaredUnnecessary(comments, isTrustedAuthor) &&
246
+ !comments.some(
247
+ (comment) =>
248
+ isTrustedAuthor(comment.author) &&
249
+ comment.content.startsWith(
250
+ RETURNED_TO_AWAITING_WORKSPACE_MESSAGE_HEAD,
251
+ ),
252
+ )
253
+ ) {
254
+ issue.status = AWAITING_WORKSPACE_STATUS_NAME;
255
+ await this.issueRepository.update(issue, project);
256
+ await this.issueRepository.updateStatus(
257
+ project,
258
+ issue,
259
+ awaitingWorkspaceStatusOption.id,
260
+ );
261
+ await this.issueCommentRepository.createComment(
262
+ issue,
263
+ RETURNED_TO_AWAITING_WORKSPACE_MESSAGE,
264
+ );
265
+ return;
266
+ }
267
+
237
268
  if (rejections.length <= 0) {
238
269
  await this.changeTargetPullRequestApprover.approveIfConfined(
239
270
  issue.labels,
@@ -1 +1 @@
1
- {"version":3,"file":"NotifyFinishedIssuePreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAe3E,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,QAAQ,EAAE,MAAM;CAI7B;AACD,qBAAa,uBAAwB,SAAQ,KAAK;gBAE9C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,cAAc,EAAE,MAAM,GAAG,IAAI;CAOhC;AAID,qBAAa,qCAAqC;IAK9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAahC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IAIvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAtBpC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA0B;IAClE,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAAkC;gBAG/D,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EACtD,eAAe,EAAE,IAAI,CACpC,eAAe,EACb,KAAK,GACL,QAAQ,GACR,cAAc,GACd,oBAAoB,GACpB,mBAAmB,GACnB,oBAAoB,GACpB,gCAAgC,GAChC,oBAAoB,GACpB,iCAAiC,GACjC,qBAAqB,CACxB,EACgB,sBAAsB,EAAE,IAAI,CAC3C,sBAAsB,EACtB,sBAAsB,GAAG,eAAe,CACzC,EACgB,iBAAiB,EAAE,IAAI,CACtC,iBAAiB,EACjB,gBAAgB,CACjB;IAQH,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,iCAAiC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjD,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACvC,6BAA6B,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAChD,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;KACzD,KAAG,OAAO,CAAC,IAAI,CAAC,CAsMf;IAEF,OAAO,CAAC,eAAe,CAIgD;IAEvE,OAAO,CAAC,iBAAiB,CAkDvB;IAEF,OAAO,CAAC,qBAAqB,CAuB3B;IAEF,OAAO,CAAC,gCAAgC,CAoBtC;IAEF,OAAO,CAAC,uBAAuB,CAQ7B;IAEF,OAAO,CAAC,+BAA+B,CAgCrC;CACH"}
1
+ {"version":3,"file":"NotifyFinishedIssuePreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAe3E,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,QAAQ,EAAE,MAAM;CAI7B;AACD,qBAAa,uBAAwB,SAAQ,KAAK;gBAE9C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,cAAc,EAAE,MAAM,GAAG,IAAI;CAOhC;AAUD,qBAAa,qCAAqC;IAK9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAahC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IAIvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAtBpC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA0B;IAClE,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAAkC;gBAG/D,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EACtD,eAAe,EAAE,IAAI,CACpC,eAAe,EACb,KAAK,GACL,QAAQ,GACR,cAAc,GACd,oBAAoB,GACpB,mBAAmB,GACnB,oBAAoB,GACpB,gCAAgC,GAChC,oBAAoB,GACpB,iCAAiC,GACjC,qBAAqB,CACxB,EACgB,sBAAsB,EAAE,IAAI,CAC3C,sBAAsB,EACtB,sBAAsB,GAAG,eAAe,CACzC,EACgB,iBAAiB,EAAE,IAAI,CACtC,iBAAiB,EACjB,gBAAgB,CACjB;IAQH,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,iCAAiC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjD,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACvC,6BAA6B,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAChD,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;KACzD,KAAG,OAAO,CAAC,IAAI,CAAC,CA+Nf;IAEF,OAAO,CAAC,eAAe,CAIgD;IAEvE,OAAO,CAAC,iBAAiB,CAkDvB;IAEF,OAAO,CAAC,qBAAqB,CAuB3B;IAEF,OAAO,CAAC,gCAAgC,CAoBtC;IAEF,OAAO,CAAC,uBAAuB,CAQ7B;IAEF,OAAO,CAAC,+BAA+B,CAgCrC;CACH"}