github-issue-tower-defence-management 1.47.0 → 1.49.0
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 +19 -0
- package/README.md +6 -25
- package/bin/adapter/entry-points/cli/index.js +2 -55
- package/bin/adapter/entry-points/cli/index.js.map +1 -1
- package/bin/adapter/entry-points/cli/projectConfig.js +0 -15
- package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +12 -53
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/repositories/GraphqlProjectRepository.js +37 -0
- package/bin/adapter/repositories/GraphqlProjectRepository.js.map +1 -1
- package/bin/domain/entities/WorkflowStatus.js +56 -0
- package/bin/domain/entities/WorkflowStatus.js.map +1 -0
- package/bin/domain/usecases/AnalyzeStoriesUseCase.js +2 -1
- package/bin/domain/usecases/AnalyzeStoriesUseCase.js.map +1 -1
- package/bin/domain/usecases/ChangeStatusByStoryColorUseCase.js +5 -4
- package/bin/domain/usecases/ChangeStatusByStoryColorUseCase.js.map +1 -1
- package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js +2 -1
- package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js.map +1 -1
- package/bin/domain/usecases/CreateEstimationIssueUseCase.js +2 -1
- package/bin/domain/usecases/CreateEstimationIssueUseCase.js.map +1 -1
- package/bin/domain/usecases/CreateNewStoryByLabelUseCase.js.map +1 -1
- package/bin/domain/usecases/HandleScheduledEventUseCase.js +9 -17
- package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +13 -15
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
- package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js +4 -5
- package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js.map +1 -1
- package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js +49 -0
- package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js.map +1 -0
- package/bin/domain/usecases/StartPreparationUseCase.js +7 -8
- package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
- package/bin/domain/usecases/UpdateIssueStatusByLabelUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/cli/index.test.ts +8 -212
- package/src/adapter/entry-points/cli/index.ts +6 -88
- package/src/adapter/entry-points/cli/projectConfig.ts +0 -33
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +5 -17
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +16 -32
- package/src/adapter/repositories/GraphqlProjectRepository.ts +55 -1
- package/src/domain/entities/WorkflowStatus.ts +60 -0
- package/src/domain/usecases/AnalyzeStoriesUseCase.ts +2 -2
- package/src/domain/usecases/ChangeStatusByStoryColorUseCase.test.ts +0 -5
- package/src/domain/usecases/ChangeStatusByStoryColorUseCase.ts +5 -5
- package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.test.ts +2 -13
- package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.ts +2 -2
- package/src/domain/usecases/CreateEstimationIssueUseCase.ts +2 -2
- package/src/domain/usecases/CreateNewStoryByLabelUseCase.test.ts +0 -4
- package/src/domain/usecases/CreateNewStoryByLabelUseCase.ts +0 -1
- package/src/domain/usecases/HandleScheduledEventUseCase.test.ts +4 -41
- package/src/domain/usecases/HandleScheduledEventUseCase.ts +9 -27
- package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +0 -202
- package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +18 -31
- package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +13 -101
- package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +10 -10
- package/src/domain/usecases/SetupTowerDefenceProjectUseCase.test.ts +266 -0
- package/src/domain/usecases/SetupTowerDefenceProjectUseCase.ts +73 -0
- package/src/domain/usecases/StartPreparationUseCase.test.ts +1 -151
- package/src/domain/usecases/StartPreparationUseCase.ts +11 -20
- package/src/domain/usecases/UpdateIssueStatusByLabelUseCase.test.ts +2 -47
- package/src/domain/usecases/UpdateIssueStatusByLabelUseCase.ts +1 -5
- package/src/domain/usecases/adapter-interfaces/ProjectRepository.ts +6 -1
- package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
- package/types/adapter/entry-points/cli/projectConfig.d.ts +0 -3
- package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/repositories/GraphqlProjectRepository.d.ts +4 -1
- package/types/adapter/repositories/GraphqlProjectRepository.d.ts.map +1 -1
- package/types/domain/entities/WorkflowStatus.d.ts +17 -0
- package/types/domain/entities/WorkflowStatus.d.ts.map +1 -0
- package/types/domain/usecases/AnalyzeStoriesUseCase.d.ts +0 -1
- package/types/domain/usecases/AnalyzeStoriesUseCase.d.ts.map +1 -1
- package/types/domain/usecases/ChangeStatusByStoryColorUseCase.d.ts +0 -1
- package/types/domain/usecases/ChangeStatusByStoryColorUseCase.d.ts.map +1 -1
- package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts +0 -1
- package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts.map +1 -1
- package/types/domain/usecases/CreateEstimationIssueUseCase.d.ts +0 -1
- package/types/domain/usecases/CreateEstimationIssueUseCase.d.ts.map +1 -1
- package/types/domain/usecases/CreateNewStoryByLabelUseCase.d.ts +0 -1
- package/types/domain/usecases/CreateNewStoryByLabelUseCase.d.ts.map +1 -1
- package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +3 -8
- package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts +1 -4
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts +0 -3
- package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/SetupTowerDefenceProjectUseCase.d.ts +10 -0
- package/types/domain/usecases/SetupTowerDefenceProjectUseCase.d.ts.map +1 -0
- package/types/domain/usecases/StartPreparationUseCase.d.ts +1 -3
- package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/UpdateIssueStatusByLabelUseCase.d.ts +0 -1
- package/types/domain/usecases/UpdateIssueStatusByLabelUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts +3 -1
- package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts.map +1 -1
|
@@ -30,12 +30,9 @@ import { OauthAPIProxyClaudeRepository } from '../../repositories/OauthAPIProxyC
|
|
|
30
30
|
import { GitHubIssueCommentRepository } from '../../repositories/GitHubIssueCommentRepository';
|
|
31
31
|
import { FetchWebhookRepository } from '../../repositories/FetchWebhookRepository';
|
|
32
32
|
import { RevertOrphanedPreparationUseCase } from '../../../domain/usecases/RevertOrphanedPreparationUseCase';
|
|
33
|
-
import { Project } from '../../../domain/entities/Project';
|
|
34
33
|
|
|
35
34
|
type StartDaemonOptions = {
|
|
36
35
|
projectUrl?: string;
|
|
37
|
-
awaitingWorkspaceStatus?: string;
|
|
38
|
-
preparationStatus?: string;
|
|
39
36
|
defaultAgentName?: string;
|
|
40
37
|
defaultLlmModelName?: string;
|
|
41
38
|
defaultLlmAgentName?: string;
|
|
@@ -50,9 +47,6 @@ type StartDaemonOptions = {
|
|
|
50
47
|
type NotifyFinishedOptions = {
|
|
51
48
|
issueUrl: string;
|
|
52
49
|
projectUrl?: string;
|
|
53
|
-
preparationStatus?: string;
|
|
54
|
-
awaitingWorkspaceStatus?: string;
|
|
55
|
-
awaitingQualityCheckStatus?: string;
|
|
56
50
|
thresholdForAutoReject?: string;
|
|
57
51
|
workflowBlockerResolvedWebhookUrl?: string;
|
|
58
52
|
configFilePath: string;
|
|
@@ -114,11 +108,6 @@ program
|
|
|
114
108
|
'Path to config file for tower defence management',
|
|
115
109
|
)
|
|
116
110
|
.option('--projectUrl <url>', 'GitHub project URL')
|
|
117
|
-
.option(
|
|
118
|
-
'--awaitingWorkspaceStatus <status>',
|
|
119
|
-
'Status for issues awaiting workspace',
|
|
120
|
-
)
|
|
121
|
-
.option('--preparationStatus <status>', 'Status for issues in preparation')
|
|
122
111
|
.option('--defaultAgentName <name>', 'Default agent name')
|
|
123
112
|
.option('--defaultLlmModelName <name>', 'Default LLM model name')
|
|
124
113
|
.option('--defaultLlmAgentName <name>', 'Default LLM agent name')
|
|
@@ -153,8 +142,6 @@ program
|
|
|
153
142
|
|
|
154
143
|
const cliOverrides: ConfigFile = {
|
|
155
144
|
projectUrl: options.projectUrl,
|
|
156
|
-
awaitingWorkspaceStatus: options.awaitingWorkspaceStatus,
|
|
157
|
-
preparationStatus: options.preparationStatus,
|
|
158
145
|
defaultAgentName: options.defaultAgentName,
|
|
159
146
|
defaultLlmModelName: options.defaultLlmModelName,
|
|
160
147
|
defaultLlmAgentName: options.defaultLlmAgentName,
|
|
@@ -189,8 +176,6 @@ program
|
|
|
189
176
|
);
|
|
190
177
|
|
|
191
178
|
const projectUrl = config.projectUrl;
|
|
192
|
-
const awaitingWorkspaceStatus = config.awaitingWorkspaceStatus;
|
|
193
|
-
const preparationStatus = config.preparationStatus;
|
|
194
179
|
const defaultAgentName = config.defaultAgentName;
|
|
195
180
|
|
|
196
181
|
if (!projectUrl) {
|
|
@@ -199,18 +184,6 @@ program
|
|
|
199
184
|
);
|
|
200
185
|
process.exit(1);
|
|
201
186
|
}
|
|
202
|
-
if (!awaitingWorkspaceStatus) {
|
|
203
|
-
console.error(
|
|
204
|
-
'awaitingWorkspaceStatus is required. Provide via --awaitingWorkspaceStatus, config file, or project README.',
|
|
205
|
-
);
|
|
206
|
-
process.exit(1);
|
|
207
|
-
}
|
|
208
|
-
if (!preparationStatus) {
|
|
209
|
-
console.error(
|
|
210
|
-
'preparationStatus is required. Provide via --preparationStatus, config file, or project README.',
|
|
211
|
-
);
|
|
212
|
-
process.exit(1);
|
|
213
|
-
}
|
|
214
187
|
if (!defaultAgentName) {
|
|
215
188
|
console.error(
|
|
216
189
|
'defaultAgentName is required. Provide via --defaultAgentName, config file, or project README.',
|
|
@@ -253,16 +226,9 @@ program
|
|
|
253
226
|
cachePath,
|
|
254
227
|
token,
|
|
255
228
|
);
|
|
256
|
-
const projectRepository =
|
|
257
|
-
...
|
|
258
|
-
|
|
259
|
-
prepareStatus: async (
|
|
260
|
-
_name: string,
|
|
261
|
-
project: Project,
|
|
262
|
-
): Promise<Project> => {
|
|
263
|
-
return project;
|
|
264
|
-
},
|
|
265
|
-
};
|
|
229
|
+
const projectRepository = new GraphqlProjectRepository(
|
|
230
|
+
...githubRepositoryParams,
|
|
231
|
+
);
|
|
266
232
|
const apiV3IssueRepository = new ApiV3IssueRepository(
|
|
267
233
|
...githubRepositoryParams,
|
|
268
234
|
);
|
|
@@ -296,9 +262,6 @@ program
|
|
|
296
262
|
);
|
|
297
263
|
await revertUseCase.run({
|
|
298
264
|
projectUrl,
|
|
299
|
-
preparationStatus,
|
|
300
|
-
awaitingWorkspaceStatus,
|
|
301
|
-
awaitingQualityCheckStatus: config.awaitingQualityCheckStatus,
|
|
302
265
|
allowIssueCacheMinutes,
|
|
303
266
|
preparationProcessCheckCommand,
|
|
304
267
|
awLogDirectoryPath: config.awLogDirectoryPath,
|
|
@@ -328,8 +291,6 @@ program
|
|
|
328
291
|
|
|
329
292
|
await useCase.run({
|
|
330
293
|
projectUrl,
|
|
331
|
-
awaitingWorkspaceStatus,
|
|
332
|
-
preparationStatus,
|
|
333
294
|
defaultAgentName,
|
|
334
295
|
defaultLlmModelName: config.defaultLlmModelName ?? null,
|
|
335
296
|
defaultLlmAgentName: config.defaultLlmAgentName ?? null,
|
|
@@ -352,15 +313,6 @@ program
|
|
|
352
313
|
)
|
|
353
314
|
.requiredOption('--issueUrl <url>', 'GitHub issue URL')
|
|
354
315
|
.option('--projectUrl <url>', 'GitHub project URL')
|
|
355
|
-
.option('--preparationStatus <status>', 'Status for issues in preparation')
|
|
356
|
-
.option(
|
|
357
|
-
'--awaitingWorkspaceStatus <status>',
|
|
358
|
-
'Status for issues awaiting workspace',
|
|
359
|
-
)
|
|
360
|
-
.option(
|
|
361
|
-
'--awaitingQualityCheckStatus <status>',
|
|
362
|
-
'Status for issues awaiting quality check',
|
|
363
|
-
)
|
|
364
316
|
.option(
|
|
365
317
|
'--thresholdForAutoReject <count>',
|
|
366
318
|
'Threshold for auto-escalation after consecutive rejections (default: 3)',
|
|
@@ -380,9 +332,6 @@ program
|
|
|
380
332
|
|
|
381
333
|
const cliOverrides: ConfigFile = {
|
|
382
334
|
projectUrl: options.projectUrl,
|
|
383
|
-
preparationStatus: options.preparationStatus,
|
|
384
|
-
awaitingWorkspaceStatus: options.awaitingWorkspaceStatus,
|
|
385
|
-
awaitingQualityCheckStatus: options.awaitingQualityCheckStatus,
|
|
386
335
|
thresholdForAutoReject: options.thresholdForAutoReject
|
|
387
336
|
? Number(options.thresholdForAutoReject)
|
|
388
337
|
: undefined,
|
|
@@ -408,9 +357,6 @@ program
|
|
|
408
357
|
);
|
|
409
358
|
|
|
410
359
|
const projectUrl = config.projectUrl;
|
|
411
|
-
const preparationStatus = config.preparationStatus;
|
|
412
|
-
const awaitingWorkspaceStatus = config.awaitingWorkspaceStatus;
|
|
413
|
-
const awaitingQualityCheckStatus = config.awaitingQualityCheckStatus;
|
|
414
360
|
|
|
415
361
|
if (!projectUrl) {
|
|
416
362
|
console.error(
|
|
@@ -418,24 +364,6 @@ program
|
|
|
418
364
|
);
|
|
419
365
|
process.exit(1);
|
|
420
366
|
}
|
|
421
|
-
if (!preparationStatus) {
|
|
422
|
-
console.error(
|
|
423
|
-
'preparationStatus is required. Provide via --preparationStatus, config file, or project README.',
|
|
424
|
-
);
|
|
425
|
-
process.exit(1);
|
|
426
|
-
}
|
|
427
|
-
if (!awaitingWorkspaceStatus) {
|
|
428
|
-
console.error(
|
|
429
|
-
'awaitingWorkspaceStatus is required. Provide via --awaitingWorkspaceStatus, config file, or project README.',
|
|
430
|
-
);
|
|
431
|
-
process.exit(1);
|
|
432
|
-
}
|
|
433
|
-
if (!awaitingQualityCheckStatus) {
|
|
434
|
-
console.error(
|
|
435
|
-
'awaitingQualityCheckStatus is required. Provide via --awaitingQualityCheckStatus, config file, or project README.',
|
|
436
|
-
);
|
|
437
|
-
process.exit(1);
|
|
438
|
-
}
|
|
439
367
|
|
|
440
368
|
let thresholdForAutoReject = 3;
|
|
441
369
|
const rawThreshold = config.thresholdForAutoReject;
|
|
@@ -469,16 +397,9 @@ program
|
|
|
469
397
|
cachePath,
|
|
470
398
|
token,
|
|
471
399
|
);
|
|
472
|
-
const projectRepository =
|
|
473
|
-
...
|
|
474
|
-
|
|
475
|
-
prepareStatus: async (
|
|
476
|
-
_name: string,
|
|
477
|
-
project: Project,
|
|
478
|
-
): Promise<Project> => {
|
|
479
|
-
return project;
|
|
480
|
-
},
|
|
481
|
-
};
|
|
400
|
+
const projectRepository = new GraphqlProjectRepository(
|
|
401
|
+
...githubRepositoryParams,
|
|
402
|
+
);
|
|
482
403
|
const apiV3IssueRepository = new ApiV3IssueRepository(
|
|
483
404
|
...githubRepositoryParams,
|
|
484
405
|
);
|
|
@@ -508,9 +429,6 @@ program
|
|
|
508
429
|
await useCase.run({
|
|
509
430
|
projectUrl,
|
|
510
431
|
issueUrl: options.issueUrl,
|
|
511
|
-
preparationStatus,
|
|
512
|
-
awaitingWorkspaceStatus,
|
|
513
|
-
awaitingQualityCheckStatus,
|
|
514
432
|
thresholdForAutoReject,
|
|
515
433
|
workflowBlockerResolvedWebhookUrl,
|
|
516
434
|
});
|
|
@@ -3,8 +3,6 @@ import * as fs from 'fs';
|
|
|
3
3
|
|
|
4
4
|
export type ConfigFile = {
|
|
5
5
|
projectUrl?: string;
|
|
6
|
-
awaitingWorkspaceStatus?: string;
|
|
7
|
-
preparationStatus?: string;
|
|
8
6
|
defaultAgentName?: string;
|
|
9
7
|
defaultLlmModelName?: string;
|
|
10
8
|
defaultLlmAgentName?: string;
|
|
@@ -12,7 +10,6 @@ export type ConfigFile = {
|
|
|
12
10
|
allowIssueCacheMinutes?: number;
|
|
13
11
|
utilizationPercentageThreshold?: number;
|
|
14
12
|
allowedIssueAuthors?: string;
|
|
15
|
-
awaitingQualityCheckStatus?: string;
|
|
16
13
|
thresholdForAutoReject?: number;
|
|
17
14
|
workflowBlockerResolvedWebhookUrl?: string;
|
|
18
15
|
projectName?: string;
|
|
@@ -68,11 +65,6 @@ export const loadConfigFile = (configFilePath: string): ConfigFile => {
|
|
|
68
65
|
}
|
|
69
66
|
return {
|
|
70
67
|
projectUrl: getStringValue(parsed, 'projectUrl'),
|
|
71
|
-
awaitingWorkspaceStatus: getStringValue(
|
|
72
|
-
parsed,
|
|
73
|
-
'awaitingWorkspaceStatus',
|
|
74
|
-
),
|
|
75
|
-
preparationStatus: getStringValue(parsed, 'preparationStatus'),
|
|
76
68
|
defaultAgentName: getStringValue(parsed, 'defaultAgentName'),
|
|
77
69
|
defaultLlmModelName: getStringValue(parsed, 'defaultLlmModelName'),
|
|
78
70
|
defaultLlmAgentName: getStringValue(parsed, 'defaultLlmAgentName'),
|
|
@@ -86,10 +78,6 @@ export const loadConfigFile = (configFilePath: string): ConfigFile => {
|
|
|
86
78
|
'utilizationPercentageThreshold',
|
|
87
79
|
),
|
|
88
80
|
allowedIssueAuthors: getStringValue(parsed, 'allowedIssueAuthors'),
|
|
89
|
-
awaitingQualityCheckStatus: getStringValue(
|
|
90
|
-
parsed,
|
|
91
|
-
'awaitingQualityCheckStatus',
|
|
92
|
-
),
|
|
93
81
|
thresholdForAutoReject: getNumberValue(parsed, 'thresholdForAutoReject'),
|
|
94
82
|
workflowBlockerResolvedWebhookUrl: getStringValue(
|
|
95
83
|
parsed,
|
|
@@ -133,11 +121,6 @@ export const parseProjectReadmeConfig = (readme: string): ConfigFile => {
|
|
|
133
121
|
return {};
|
|
134
122
|
}
|
|
135
123
|
return {
|
|
136
|
-
awaitingWorkspaceStatus: getStringValue(
|
|
137
|
-
parsed,
|
|
138
|
-
'awaitingWorkspaceStatus',
|
|
139
|
-
),
|
|
140
|
-
preparationStatus: getStringValue(parsed, 'preparationStatus'),
|
|
141
124
|
defaultAgentName: getStringValue(parsed, 'defaultAgentName'),
|
|
142
125
|
defaultLlmModelName: getStringValue(parsed, 'defaultLlmModelName'),
|
|
143
126
|
defaultLlmAgentName: getStringValue(parsed, 'defaultLlmAgentName'),
|
|
@@ -151,10 +134,6 @@ export const parseProjectReadmeConfig = (readme: string): ConfigFile => {
|
|
|
151
134
|
'utilizationPercentageThreshold',
|
|
152
135
|
),
|
|
153
136
|
allowedIssueAuthors: getStringValue(parsed, 'allowedIssueAuthors'),
|
|
154
|
-
awaitingQualityCheckStatus: getStringValue(
|
|
155
|
-
parsed,
|
|
156
|
-
'awaitingQualityCheckStatus',
|
|
157
|
-
),
|
|
158
137
|
thresholdForAutoReject: getNumberValue(parsed, 'thresholdForAutoReject'),
|
|
159
138
|
workflowBlockerResolvedWebhookUrl: getStringValue(
|
|
160
139
|
parsed,
|
|
@@ -183,14 +162,6 @@ export const mergeConfigs = (
|
|
|
183
162
|
readmeOverrides: ConfigFile,
|
|
184
163
|
): ConfigFile => ({
|
|
185
164
|
projectUrl: cliOverrides.projectUrl ?? configFile.projectUrl,
|
|
186
|
-
awaitingWorkspaceStatus:
|
|
187
|
-
readmeOverrides.awaitingWorkspaceStatus ??
|
|
188
|
-
cliOverrides.awaitingWorkspaceStatus ??
|
|
189
|
-
configFile.awaitingWorkspaceStatus,
|
|
190
|
-
preparationStatus:
|
|
191
|
-
readmeOverrides.preparationStatus ??
|
|
192
|
-
cliOverrides.preparationStatus ??
|
|
193
|
-
configFile.preparationStatus,
|
|
194
165
|
defaultAgentName:
|
|
195
166
|
readmeOverrides.defaultAgentName ??
|
|
196
167
|
cliOverrides.defaultAgentName ??
|
|
@@ -219,10 +190,6 @@ export const mergeConfigs = (
|
|
|
219
190
|
readmeOverrides.allowedIssueAuthors ??
|
|
220
191
|
cliOverrides.allowedIssueAuthors ??
|
|
221
192
|
configFile.allowedIssueAuthors,
|
|
222
|
-
awaitingQualityCheckStatus:
|
|
223
|
-
readmeOverrides.awaitingQualityCheckStatus ??
|
|
224
|
-
cliOverrides.awaitingQualityCheckStatus ??
|
|
225
|
-
configFile.awaitingQualityCheckStatus,
|
|
226
193
|
thresholdForAutoReject:
|
|
227
194
|
readmeOverrides.thresholdForAutoReject ??
|
|
228
195
|
cliOverrides.thresholdForAutoReject ??
|
|
@@ -141,8 +141,6 @@ const validConfig = {
|
|
|
141
141
|
projectUrl: 'https://github.com/users/TestOrg/projects/1',
|
|
142
142
|
manager: 'TestManager',
|
|
143
143
|
urlOfStoryView: 'https://github.com/users/TestOrg/projects/1/views/1',
|
|
144
|
-
disabledStatus: 'Icebox',
|
|
145
|
-
defaultStatus: 'Unread',
|
|
146
144
|
disabled: false,
|
|
147
145
|
allowIssueCacheMinutes: 1,
|
|
148
146
|
workingReport: {
|
|
@@ -267,17 +265,12 @@ describe('HandleScheduledEventUseCaseHandler', () => {
|
|
|
267
265
|
...validConfig,
|
|
268
266
|
allowIssueCacheMinutes: 5,
|
|
269
267
|
startPreparation: {
|
|
270
|
-
awaitingWorkspaceStatus: 'Awaiting',
|
|
271
|
-
preparationStatus: 'Preparing',
|
|
272
268
|
defaultAgentName: 'agent1',
|
|
273
269
|
configFilePath: './config.yml',
|
|
274
270
|
maximumPreparingIssuesCount: 10,
|
|
275
271
|
utilizationPercentageThreshold: 97,
|
|
276
272
|
},
|
|
277
273
|
notifyFinishedPreparation: {
|
|
278
|
-
preparationStatus: 'Preparing',
|
|
279
|
-
awaitingWorkspaceStatus: 'Awaiting',
|
|
280
|
-
awaitingQualityCheckStatus: 'Awaiting QC',
|
|
281
274
|
thresholdForAutoReject: 30,
|
|
282
275
|
workflowBlockerResolvedWebhookUrl: null,
|
|
283
276
|
},
|
|
@@ -298,10 +291,12 @@ describe('HandleScheduledEventUseCaseHandler', () => {
|
|
|
298
291
|
expect(firstCallArg.config.allowIssueCacheMinutes).toBe(5);
|
|
299
292
|
expect(firstCallArg.config.thresholdForAutoReject).toBe(30);
|
|
300
293
|
expect(firstCallArg.statusNames.awaitingQualityCheckStatus).toBe(
|
|
301
|
-
'Awaiting
|
|
294
|
+
'Awaiting Quality Check',
|
|
295
|
+
);
|
|
296
|
+
expect(firstCallArg.statusNames.preparationStatus).toBe('Preparation');
|
|
297
|
+
expect(firstCallArg.statusNames.awaitingWorkspaceStatus).toBe(
|
|
298
|
+
'Awaiting Workspace',
|
|
302
299
|
);
|
|
303
|
-
expect(firstCallArg.statusNames.preparationStatus).toBe('Preparing');
|
|
304
|
-
expect(firstCallArg.statusNames.awaitingWorkspaceStatus).toBe('Awaiting');
|
|
305
300
|
});
|
|
306
301
|
|
|
307
302
|
it('should write situation file with numeric defaults when optional fields are absent', async () => {
|
|
@@ -329,8 +324,6 @@ describe('HandleScheduledEventUseCaseHandler', () => {
|
|
|
329
324
|
...validConfig,
|
|
330
325
|
allowIssueCacheMinutes: 5,
|
|
331
326
|
startPreparation: {
|
|
332
|
-
awaitingWorkspaceStatus: 'Awaiting workspace',
|
|
333
|
-
preparationStatus: 'Preparation',
|
|
334
327
|
defaultAgentName: 'yaml-agent',
|
|
335
328
|
configFilePath: '/path/to/config.yml',
|
|
336
329
|
maximumPreparingIssuesCount: 10,
|
|
@@ -342,8 +335,6 @@ describe('HandleScheduledEventUseCaseHandler', () => {
|
|
|
342
335
|
const readmeContent = `<details>
|
|
343
336
|
<summary>config</summary>
|
|
344
337
|
maximumPreparingIssuesCount: 0
|
|
345
|
-
awaitingWorkspaceStatus: README Awaiting
|
|
346
|
-
preparationStatus: README Preparation
|
|
347
338
|
defaultAgentName: readme-agent
|
|
348
339
|
utilizationPercentageThreshold: 80
|
|
349
340
|
</details>`;
|
|
@@ -358,8 +349,6 @@ utilizationPercentageThreshold: 80
|
|
|
358
349
|
expect(capturedRunInputs[0][0]).toMatchObject({
|
|
359
350
|
startPreparation: {
|
|
360
351
|
maximumPreparingIssuesCount: 0,
|
|
361
|
-
awaitingWorkspaceStatus: 'README Awaiting',
|
|
362
|
-
preparationStatus: 'README Preparation',
|
|
363
352
|
defaultAgentName: 'readme-agent',
|
|
364
353
|
utilizationPercentageThreshold: 80,
|
|
365
354
|
},
|
|
@@ -419,7 +408,6 @@ allowedIssueAuthors: 'user1, user2, user3'
|
|
|
419
408
|
allowIssueCacheMinutes: 5,
|
|
420
409
|
startPreparation: {
|
|
421
410
|
maximumPreparingIssuesCount: 10,
|
|
422
|
-
awaitingWorkspaceStatus: 'Awaiting workspace',
|
|
423
411
|
defaultAgentName: 'yaml-agent',
|
|
424
412
|
},
|
|
425
413
|
});
|
|
@@ -30,7 +30,6 @@ import { ConvertCheckboxToIssueInStoryIssueUseCase } from '../../../domain/useca
|
|
|
30
30
|
import { ChangeStatusByStoryColorUseCase } from '../../../domain/usecases/ChangeStatusByStoryColorUseCase';
|
|
31
31
|
import { SetNoStoryIssueToStoryUseCase } from '../../../domain/usecases/SetNoStoryIssueToStoryUseCase';
|
|
32
32
|
import { CreateNewStoryByLabelUseCase } from '../../../domain/usecases/CreateNewStoryByLabelUseCase';
|
|
33
|
-
import { ProjectRepository } from '../../../domain/usecases/adapter-interfaces/ProjectRepository';
|
|
34
33
|
import { AssignNoAssigneeIssueToManagerUseCase } from '../../../domain/usecases/AssignNoAssigneeIssueToManagerUseCase';
|
|
35
34
|
import { UpdateIssueStatusByLabelUseCase } from '../../../domain/usecases/UpdateIssueStatusByLabelUseCase';
|
|
36
35
|
import { StartPreparationUseCase } from '../../../domain/usecases/StartPreparationUseCase';
|
|
@@ -40,6 +39,12 @@ import { NotifyFinishedIssuePreparationUseCase } from '../../../domain/usecases/
|
|
|
40
39
|
import { RevertOrphanedPreparationUseCase } from '../../../domain/usecases/RevertOrphanedPreparationUseCase';
|
|
41
40
|
import { GitHubIssueCommentRepository } from '../../repositories/GitHubIssueCommentRepository';
|
|
42
41
|
import { FetchWebhookRepository } from '../../repositories/FetchWebhookRepository';
|
|
42
|
+
import { SetupTowerDefenceProjectUseCase } from '../../../domain/usecases/SetupTowerDefenceProjectUseCase';
|
|
43
|
+
import {
|
|
44
|
+
AWAITING_QUALITY_CHECK_STATUS_NAME,
|
|
45
|
+
AWAITING_WORKSPACE_STATUS_NAME,
|
|
46
|
+
PREPARATION_STATUS_NAME,
|
|
47
|
+
} from '../../../domain/entities/WorkflowStatus';
|
|
43
48
|
|
|
44
49
|
export class HandleScheduledEventUseCaseHandler {
|
|
45
50
|
handle = async (
|
|
@@ -97,12 +102,6 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
97
102
|
startPreparation: input.startPreparation
|
|
98
103
|
? {
|
|
99
104
|
...input.startPreparation,
|
|
100
|
-
awaitingWorkspaceStatus:
|
|
101
|
-
readmeConfig.awaitingWorkspaceStatus ??
|
|
102
|
-
input.startPreparation.awaitingWorkspaceStatus,
|
|
103
|
-
preparationStatus:
|
|
104
|
-
readmeConfig.preparationStatus ??
|
|
105
|
-
input.startPreparation.preparationStatus,
|
|
106
105
|
defaultAgentName:
|
|
107
106
|
readmeConfig.defaultAgentName ??
|
|
108
107
|
input.startPreparation.defaultAgentName,
|
|
@@ -135,15 +134,6 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
135
134
|
notifyFinishedPreparation: input.notifyFinishedPreparation
|
|
136
135
|
? {
|
|
137
136
|
...input.notifyFinishedPreparation,
|
|
138
|
-
awaitingWorkspaceStatus:
|
|
139
|
-
readmeConfig.awaitingWorkspaceStatus ??
|
|
140
|
-
input.notifyFinishedPreparation.awaitingWorkspaceStatus,
|
|
141
|
-
preparationStatus:
|
|
142
|
-
readmeConfig.preparationStatus ??
|
|
143
|
-
input.notifyFinishedPreparation.preparationStatus,
|
|
144
|
-
awaitingQualityCheckStatus:
|
|
145
|
-
readmeConfig.awaitingQualityCheckStatus ??
|
|
146
|
-
input.notifyFinishedPreparation.awaitingQualityCheckStatus,
|
|
147
137
|
thresholdForAutoReject:
|
|
148
138
|
readmeConfig.thresholdForAutoReject ??
|
|
149
139
|
input.notifyFinishedPreparation.thresholdForAutoReject,
|
|
@@ -175,15 +165,9 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
175
165
|
input.credentials.bot.github.password,
|
|
176
166
|
input.credentials.bot.github.authenticatorKey,
|
|
177
167
|
];
|
|
178
|
-
const projectRepository
|
|
179
|
-
...
|
|
180
|
-
|
|
181
|
-
_name: string,
|
|
182
|
-
project: Project,
|
|
183
|
-
): Promise<Project> => {
|
|
184
|
-
return project;
|
|
185
|
-
},
|
|
186
|
-
};
|
|
168
|
+
const projectRepository = new GraphqlProjectRepository(
|
|
169
|
+
...githubRepositoryParams,
|
|
170
|
+
);
|
|
187
171
|
const apiV3IssueRepository = new ApiV3IssueRepository(
|
|
188
172
|
...githubRepositoryParams,
|
|
189
173
|
);
|
|
@@ -200,6 +184,9 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
200
184
|
localStorageCacheRepository,
|
|
201
185
|
...githubRepositoryParams,
|
|
202
186
|
);
|
|
187
|
+
const setupTowerDefenceProjectUseCase = new SetupTowerDefenceProjectUseCase(
|
|
188
|
+
projectRepository,
|
|
189
|
+
);
|
|
203
190
|
const actionAnnouncement = new ActionAnnouncementUseCase(issueRepository);
|
|
204
191
|
const setWorkflowManagementIssueToStoryUseCase =
|
|
205
192
|
new SetWorkflowManagementIssueToStoryUseCase(issueRepository);
|
|
@@ -268,6 +255,7 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
268
255
|
);
|
|
269
256
|
|
|
270
257
|
const handleScheduledEventUseCase = new HandleScheduledEventUseCase(
|
|
258
|
+
setupTowerDefenceProjectUseCase,
|
|
271
259
|
actionAnnouncement,
|
|
272
260
|
setWorkflowManagementIssueToStoryUseCase,
|
|
273
261
|
clearPastNextActionUseCase,
|
|
@@ -297,13 +285,9 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
297
285
|
projectId: result.project.id,
|
|
298
286
|
issues: result.issues,
|
|
299
287
|
statusNames: {
|
|
300
|
-
awaitingQualityCheckStatus:
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
preparationStatus:
|
|
304
|
-
mergedInput.startPreparation?.preparationStatus ?? null,
|
|
305
|
-
awaitingWorkspaceStatus:
|
|
306
|
-
mergedInput.startPreparation?.awaitingWorkspaceStatus ?? null,
|
|
288
|
+
awaitingQualityCheckStatus: AWAITING_QUALITY_CHECK_STATUS_NAME,
|
|
289
|
+
preparationStatus: PREPARATION_STATUS_NAME,
|
|
290
|
+
awaitingWorkspaceStatus: AWAITING_WORKSPACE_STATUS_NAME,
|
|
307
291
|
},
|
|
308
292
|
config: {
|
|
309
293
|
maximumPreparingIssuesCount:
|
|
@@ -9,7 +9,11 @@ export class GraphqlProjectRepository
|
|
|
9
9
|
implements
|
|
10
10
|
Pick<
|
|
11
11
|
ProjectRepository,
|
|
12
|
-
|
|
12
|
+
| 'getProject'
|
|
13
|
+
| 'findProjectIdByUrl'
|
|
14
|
+
| 'getByUrl'
|
|
15
|
+
| 'updateStoryList'
|
|
16
|
+
| 'updateStatusList'
|
|
13
17
|
>
|
|
14
18
|
{
|
|
15
19
|
extractProjectFromUrl = (
|
|
@@ -362,4 +366,54 @@ export class GraphqlProjectRepository
|
|
|
362
366
|
}>();
|
|
363
367
|
return response.data.updateProjectV2Field.projectV2Field.options;
|
|
364
368
|
};
|
|
369
|
+
updateStatusList = async (
|
|
370
|
+
project: Project,
|
|
371
|
+
newStatusList: (Omit<FieldOption, 'id'> & {
|
|
372
|
+
id: FieldOption['id'] | null;
|
|
373
|
+
})[],
|
|
374
|
+
): Promise<FieldOption[]> => {
|
|
375
|
+
const mutation = `mutation UpdateStatusOptions($fieldId: ID!, $options: [ProjectV2SingleSelectFieldOptionInput!]!) {
|
|
376
|
+
updateProjectV2Field(input: {
|
|
377
|
+
fieldId: $fieldId
|
|
378
|
+
singleSelectOptions: $options
|
|
379
|
+
}) {
|
|
380
|
+
projectV2Field {
|
|
381
|
+
... on ProjectV2SingleSelectField {
|
|
382
|
+
options {
|
|
383
|
+
id
|
|
384
|
+
name
|
|
385
|
+
color
|
|
386
|
+
description
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}`;
|
|
392
|
+
const variables = {
|
|
393
|
+
fieldId: project.status.fieldId,
|
|
394
|
+
options: newStatusList.map(({ id, name, color, description }) => ({
|
|
395
|
+
...(id !== null ? { id } : {}),
|
|
396
|
+
name,
|
|
397
|
+
color,
|
|
398
|
+
description,
|
|
399
|
+
})),
|
|
400
|
+
};
|
|
401
|
+
const response = await ky
|
|
402
|
+
.post('https://api.github.com/graphql', {
|
|
403
|
+
json: { query: mutation, variables },
|
|
404
|
+
headers: {
|
|
405
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
406
|
+
},
|
|
407
|
+
})
|
|
408
|
+
.json<{
|
|
409
|
+
data: {
|
|
410
|
+
updateProjectV2Field: {
|
|
411
|
+
projectV2Field: {
|
|
412
|
+
options: FieldOption[];
|
|
413
|
+
};
|
|
414
|
+
};
|
|
415
|
+
};
|
|
416
|
+
}>();
|
|
417
|
+
return response.data.updateProjectV2Field.projectV2Field.options;
|
|
418
|
+
};
|
|
365
419
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { FieldOption } from './Project';
|
|
2
|
+
|
|
3
|
+
export const DEFAULT_STATUS_NAME = 'Unread';
|
|
4
|
+
export const AWAITING_TASK_BREAKDOWN_STATUS_NAME = 'Awaiting Task Breakdown';
|
|
5
|
+
export const AWAITING_WORKSPACE_STATUS_NAME = 'Awaiting Workspace';
|
|
6
|
+
export const PREPARATION_STATUS_NAME = 'Preparation';
|
|
7
|
+
export const AWAITING_QUALITY_CHECK_STATUS_NAME = 'Awaiting Quality Check';
|
|
8
|
+
export const TODO_STATUS_NAME = 'Todo';
|
|
9
|
+
export const PC_TODO_STATUS_NAME = 'PC Todo';
|
|
10
|
+
export const IN_TMUX_STATUS_NAME = 'In Tmux';
|
|
11
|
+
export const DONE_STATUS_NAME = 'Done';
|
|
12
|
+
export const ICEBOX_STATUS_NAME = 'Icebox';
|
|
13
|
+
|
|
14
|
+
export type WorkflowStatusDefinition = {
|
|
15
|
+
name: string;
|
|
16
|
+
color: FieldOption['color'];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const REQUIRED_WORKFLOW_STATUSES: WorkflowStatusDefinition[] = [
|
|
20
|
+
{
|
|
21
|
+
name: DEFAULT_STATUS_NAME,
|
|
22
|
+
color: 'ORANGE',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: AWAITING_TASK_BREAKDOWN_STATUS_NAME,
|
|
26
|
+
color: 'ORANGE',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: AWAITING_WORKSPACE_STATUS_NAME,
|
|
30
|
+
color: 'BLUE',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: PREPARATION_STATUS_NAME,
|
|
34
|
+
color: 'YELLOW',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: AWAITING_QUALITY_CHECK_STATUS_NAME,
|
|
38
|
+
color: 'GREEN',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: TODO_STATUS_NAME,
|
|
42
|
+
color: 'PINK',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: PC_TODO_STATUS_NAME,
|
|
46
|
+
color: 'PINK',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: IN_TMUX_STATUS_NAME,
|
|
50
|
+
color: 'RED',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: DONE_STATUS_NAME,
|
|
54
|
+
color: 'PURPLE',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: ICEBOX_STATUS_NAME,
|
|
58
|
+
color: 'GRAY',
|
|
59
|
+
},
|
|
60
|
+
];
|
|
@@ -5,6 +5,7 @@ import { Member } from '../entities/Member';
|
|
|
5
5
|
import { DateRepository } from './adapter-interfaces/DateRepository';
|
|
6
6
|
import { StoryObjectMap } from '../entities/StoryObjectMap';
|
|
7
7
|
import { encodeForURI } from './utils';
|
|
8
|
+
import { ICEBOX_STATUS_NAME } from '../entities/WorkflowStatus';
|
|
8
9
|
|
|
9
10
|
export class AnalyzeStoriesUseCase {
|
|
10
11
|
constructor(
|
|
@@ -21,7 +22,6 @@ export class AnalyzeStoriesUseCase {
|
|
|
21
22
|
org: string;
|
|
22
23
|
repo: string;
|
|
23
24
|
urlOfStoryView: string;
|
|
24
|
-
disabledStatus: string;
|
|
25
25
|
storyObjectMap: StoryObjectMap;
|
|
26
26
|
members: Member['name'][];
|
|
27
27
|
}): Promise<void> => {
|
|
@@ -66,7 +66,7 @@ export class AnalyzeStoriesUseCase {
|
|
|
66
66
|
...story,
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
if (storyIssue.status ===
|
|
69
|
+
if (storyIssue.status === ICEBOX_STATUS_NAME) {
|
|
70
70
|
phases.get('others')?.push(storyIssueObject);
|
|
71
71
|
} else if (storyIssue.labels.includes('story:phase:finished-qa')) {
|
|
72
72
|
phases.get('story:phase:finished-qa')?.push(storyIssueObject);
|
|
@@ -118,7 +118,6 @@ describe('ChangeStatusByStoryColorUseCase', () => {
|
|
|
118
118
|
cacheUsed: false,
|
|
119
119
|
org: 'testOrg',
|
|
120
120
|
repo: 'testRepo',
|
|
121
|
-
disabledStatus: 'Icebox',
|
|
122
121
|
storyObjectMap: basicStoryObjectMap,
|
|
123
122
|
},
|
|
124
123
|
expectedCalls: {
|
|
@@ -133,7 +132,6 @@ describe('ChangeStatusByStoryColorUseCase', () => {
|
|
|
133
132
|
cacheUsed: true,
|
|
134
133
|
org: 'testOrg',
|
|
135
134
|
repo: 'testRepo',
|
|
136
|
-
disabledStatus: 'Icebox',
|
|
137
135
|
storyObjectMap: basicStoryObjectMap,
|
|
138
136
|
},
|
|
139
137
|
expectedCalls: {
|
|
@@ -148,7 +146,6 @@ describe('ChangeStatusByStoryColorUseCase', () => {
|
|
|
148
146
|
cacheUsed: false,
|
|
149
147
|
org: 'testOrg',
|
|
150
148
|
repo: 'testRepo',
|
|
151
|
-
disabledStatus: 'Icebox',
|
|
152
149
|
storyObjectMap: new Map([
|
|
153
150
|
[
|
|
154
151
|
'Story 1',
|
|
@@ -180,7 +177,6 @@ describe('ChangeStatusByStoryColorUseCase', () => {
|
|
|
180
177
|
cacheUsed: false,
|
|
181
178
|
org: 'testOrg',
|
|
182
179
|
repo: 'testRepo',
|
|
183
|
-
disabledStatus: 'Icebox',
|
|
184
180
|
storyObjectMap: new Map([
|
|
185
181
|
[
|
|
186
182
|
'Story 1',
|
|
@@ -245,7 +241,6 @@ describe('ChangeStatusByStoryColorUseCase', () => {
|
|
|
245
241
|
cacheUsed: false,
|
|
246
242
|
org: 'testOrg',
|
|
247
243
|
repo: 'testRepo',
|
|
248
|
-
disabledStatus: 'Icebox',
|
|
249
244
|
storyObjectMap: basicStoryObjectMap,
|
|
250
245
|
}),
|
|
251
246
|
).rejects.toThrow('First status is not found');
|