github-issue-tower-defence-management 1.146.10 → 1.146.11
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 +7 -0
- package/bin/adapter/entry-points/console/consoleOperationApi.js +38 -1
- package/bin/adapter/entry-points/console/consoleOperationApi.js.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/{index-CPY6wV8C.js → index-D868xHqH.js} +1 -1
- package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/consoleOperationApi.test.ts +86 -0
- package/src/adapter/entry-points/console/consoleOperationApi.ts +51 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOperations.test.ts +3 -2
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOperations.ts +2 -1
- package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.ts +1 -0
- package/src/adapter/entry-points/console/ui-dist/assets/{index-CPY6wV8C.js → index-D868xHqH.js} +1 -1
- package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/types/adapter/entry-points/console/consoleOperationApi.d.ts +1 -0
- package/types/adapter/entry-points/console/consoleOperationApi.d.ts.map +1 -1
|
@@ -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-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-D868xHqH.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-CKX2ny-z.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -229,6 +229,92 @@ describe('consoleOperationApi', () => {
|
|
|
229
229
|
expectRecordedAcrossTabs('PVTI_c');
|
|
230
230
|
});
|
|
231
231
|
|
|
232
|
+
it('marks a pull request unnecessary by closing it, labelling the item chore and moving it to Awaiting workspace', async () => {
|
|
233
|
+
issueRepository.getIssueByUrl.mockResolvedValue({
|
|
234
|
+
...issue,
|
|
235
|
+
url: 'https://github.com/o/r/issues/7',
|
|
236
|
+
org: 'o',
|
|
237
|
+
repo: 'r',
|
|
238
|
+
number: 7,
|
|
239
|
+
labels: ['bug'],
|
|
240
|
+
});
|
|
241
|
+
const response = await handleReview(context, {
|
|
242
|
+
pjcode: 'acme',
|
|
243
|
+
action: 'unnecessary',
|
|
244
|
+
prUrl: 'https://github.com/o/r/pull/1',
|
|
245
|
+
issueUrl: 'https://github.com/o/r/issues/7',
|
|
246
|
+
projectItemId: 'PVTI_unnecessary',
|
|
247
|
+
commentBody: 'This pull request is unnecessary.',
|
|
248
|
+
});
|
|
249
|
+
expect(response.statusCode).toBe(200);
|
|
250
|
+
expect(issueRepository.closePullRequest).toHaveBeenCalledWith(
|
|
251
|
+
'https://github.com/o/r/pull/1',
|
|
252
|
+
);
|
|
253
|
+
expect(issueRepository.createCommentByUrl).toHaveBeenCalledWith(
|
|
254
|
+
'https://github.com/o/r/pull/1',
|
|
255
|
+
'This pull request is unnecessary.',
|
|
256
|
+
);
|
|
257
|
+
expect(issueRepository.updateLabels).toHaveBeenCalledWith(
|
|
258
|
+
expect.objectContaining({ url: 'https://github.com/o/r/issues/7' }),
|
|
259
|
+
['bug', 'chore'],
|
|
260
|
+
);
|
|
261
|
+
expect(issueRepository.updateStatus).toHaveBeenCalledWith(
|
|
262
|
+
project,
|
|
263
|
+
expect.objectContaining({ itemId: 'PVTI_unnecessary' }),
|
|
264
|
+
'status_aw',
|
|
265
|
+
);
|
|
266
|
+
expectRecordedAcrossTabs('PVTI_unnecessary');
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it('keeps the chore label once when the unnecessary item already carries it', async () => {
|
|
270
|
+
issueRepository.getIssueByUrl.mockResolvedValue({
|
|
271
|
+
...issue,
|
|
272
|
+
url: 'https://github.com/o/r/issues/8',
|
|
273
|
+
org: 'o',
|
|
274
|
+
repo: 'r',
|
|
275
|
+
number: 8,
|
|
276
|
+
labels: ['chore'],
|
|
277
|
+
});
|
|
278
|
+
const response = await handleReview(context, {
|
|
279
|
+
pjcode: 'acme',
|
|
280
|
+
action: 'unnecessary',
|
|
281
|
+
prUrl: 'https://github.com/o/r/pull/2',
|
|
282
|
+
issueUrl: 'https://github.com/o/r/issues/8',
|
|
283
|
+
projectItemId: 'PVTI_unnecessary_dup',
|
|
284
|
+
});
|
|
285
|
+
expect(response.statusCode).toBe(200);
|
|
286
|
+
expect(issueRepository.updateLabels).not.toHaveBeenCalled();
|
|
287
|
+
expect(issueRepository.updateStatus).toHaveBeenCalledWith(
|
|
288
|
+
project,
|
|
289
|
+
expect.objectContaining({ itemId: 'PVTI_unnecessary_dup' }),
|
|
290
|
+
'status_aw',
|
|
291
|
+
);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('rejects an unnecessary action without an issueUrl', async () => {
|
|
295
|
+
const response = await handleReview(context, {
|
|
296
|
+
pjcode: 'acme',
|
|
297
|
+
action: 'unnecessary',
|
|
298
|
+
prUrl: 'https://github.com/o/r/pull/1',
|
|
299
|
+
projectItemId: 'PVTI_unnecessary_missing',
|
|
300
|
+
});
|
|
301
|
+
expect(response.statusCode).toBe(400);
|
|
302
|
+
expect(issueRepository.closePullRequest).not.toHaveBeenCalled();
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('leaves labels and status untouched for the plain close action', async () => {
|
|
306
|
+
const response = await handleReview(context, {
|
|
307
|
+
pjcode: 'acme',
|
|
308
|
+
action: 'close',
|
|
309
|
+
prUrl: 'https://github.com/o/r/pull/1',
|
|
310
|
+
projectItemId: 'PVTI_plain_close',
|
|
311
|
+
commentBody: 'closing',
|
|
312
|
+
});
|
|
313
|
+
expect(response.statusCode).toBe(200);
|
|
314
|
+
expect(issueRepository.updateLabels).not.toHaveBeenCalled();
|
|
315
|
+
expect(issueRepository.updateStatus).not.toHaveBeenCalled();
|
|
316
|
+
});
|
|
317
|
+
|
|
232
318
|
it('rejects an unknown review action', async () => {
|
|
233
319
|
const response = await handleReview(context, {
|
|
234
320
|
pjcode: 'acme',
|
|
@@ -10,6 +10,7 @@ import { findConsoleItemUrl } from './consoleItemUrlLookup';
|
|
|
10
10
|
|
|
11
11
|
export const AWAITING_WORKSPACE_STATUS_NAME = 'awaiting workspace';
|
|
12
12
|
export const IN_TMUX_BY_HUMAN_STATUS_NAME = 'in tmux by human';
|
|
13
|
+
export const CHORE_LABEL_NAME = 'chore';
|
|
13
14
|
|
|
14
15
|
export type ConsoleProjectBinding = {
|
|
15
16
|
pjcode: string;
|
|
@@ -192,6 +193,24 @@ const updateStatusByName = async (
|
|
|
192
193
|
return null;
|
|
193
194
|
};
|
|
194
195
|
|
|
196
|
+
const addChoreLabel = async (
|
|
197
|
+
issueRepository: IssueRepository,
|
|
198
|
+
issueUrl: string,
|
|
199
|
+
): Promise<ConsoleOperationResponse | null> => {
|
|
200
|
+
const issue = await issueRepository.getIssueByUrl(issueUrl);
|
|
201
|
+
if (issue === null) {
|
|
202
|
+
return badGateway(`issue "${issueUrl}" could not be loaded`);
|
|
203
|
+
}
|
|
204
|
+
if (issue.labels.includes(CHORE_LABEL_NAME)) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
await issueRepository.updateLabels(issue, [
|
|
208
|
+
...issue.labels,
|
|
209
|
+
CHORE_LABEL_NAME,
|
|
210
|
+
]);
|
|
211
|
+
return null;
|
|
212
|
+
};
|
|
213
|
+
|
|
195
214
|
export const handleReview = async (
|
|
196
215
|
context: ConsoleOperationContext,
|
|
197
216
|
body: Record<string, unknown>,
|
|
@@ -230,6 +249,38 @@ export const handleReview = async (
|
|
|
230
249
|
}
|
|
231
250
|
const { project, pjcode } = binding;
|
|
232
251
|
|
|
252
|
+
if (action === 'unnecessary') {
|
|
253
|
+
const issueUrl = body.issueUrl;
|
|
254
|
+
if (!isNonEmptyString(issueUrl)) {
|
|
255
|
+
return badRequest('issueUrl is required for unnecessary');
|
|
256
|
+
}
|
|
257
|
+
await context.resolveIssueRepository(prUrl).closePullRequest(prUrl);
|
|
258
|
+
if (isNonEmptyString(body.commentBody)) {
|
|
259
|
+
await context
|
|
260
|
+
.resolveIssueRepository(prUrl)
|
|
261
|
+
.createCommentByUrl(prUrl, body.commentBody);
|
|
262
|
+
}
|
|
263
|
+
const labelFailure = await addChoreLabel(
|
|
264
|
+
context.resolveIssueRepository(issueUrl),
|
|
265
|
+
issueUrl,
|
|
266
|
+
);
|
|
267
|
+
if (labelFailure !== null) {
|
|
268
|
+
return labelFailure;
|
|
269
|
+
}
|
|
270
|
+
const failure = await updateStatusByName(
|
|
271
|
+
context.resolveIssueRepository(issueUrl),
|
|
272
|
+
project,
|
|
273
|
+
issueUrl,
|
|
274
|
+
projectItemId,
|
|
275
|
+
AWAITING_WORKSPACE_STATUS_NAME,
|
|
276
|
+
);
|
|
277
|
+
if (failure !== null) {
|
|
278
|
+
return failure;
|
|
279
|
+
}
|
|
280
|
+
recordDone(context, pjcode, projectItemId);
|
|
281
|
+
return ok();
|
|
282
|
+
}
|
|
283
|
+
|
|
233
284
|
if (action === 'approve') {
|
|
234
285
|
await context.resolveIssueRepository(prUrl).approvePullRequest(prUrl);
|
|
235
286
|
const failure = await updateStatusByName(
|
package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOperations.test.ts
CHANGED
|
@@ -72,7 +72,7 @@ describe('useConsoleOperations', () => {
|
|
|
72
72
|
});
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
it('posts an unnecessary review
|
|
75
|
+
it('posts an unnecessary review carrying the item url so the server can label it chore', async () => {
|
|
76
76
|
const fetchMock = captureFetch();
|
|
77
77
|
const { result } = setup();
|
|
78
78
|
await act(async () => {
|
|
@@ -83,7 +83,8 @@ describe('useConsoleOperations', () => {
|
|
|
83
83
|
);
|
|
84
84
|
});
|
|
85
85
|
expect(lastBody(fetchMock)).toMatchObject({
|
|
86
|
-
action: '
|
|
86
|
+
action: 'unnecessary',
|
|
87
|
+
issueUrl: prItem.url,
|
|
87
88
|
commentBody: 'This pull request is unnecessary.',
|
|
88
89
|
});
|
|
89
90
|
});
|