github-issue-tower-defence-management 1.120.0 → 1.122.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 +14 -0
- package/README.md +8 -9
- package/bin/adapter/entry-points/cli/index.js +8 -14
- package/bin/adapter/entry-points/cli/index.js.map +1 -1
- package/bin/adapter/entry-points/cli/projectConfig.js +0 -6
- package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
- package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js +6 -12
- package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +8 -10
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js +2 -1
- package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js.map +1 -1
- package/bin/adapter/entry-points/handlers/machineStatusWriter.js +23 -19
- package/bin/adapter/entry-points/handlers/machineStatusWriter.js.map +1 -1
- package/bin/adapter/entry-points/handlers/situationFileWriter.js.map +1 -1
- package/bin/adapter/entry-points/handlers/staleTmuxSessionCleaner.js +1 -2
- package/bin/adapter/entry-points/handlers/staleTmuxSessionCleaner.js.map +1 -1
- package/bin/adapter/repositories/LocalStorageCacheRepository.js +25 -0
- package/bin/adapter/repositories/LocalStorageCacheRepository.js.map +1 -1
- package/bin/adapter/repositories/ProcHostMetricsRepository.js +10 -5
- package/bin/adapter/repositories/ProcHostMetricsRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +119 -59
- package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +12 -3
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -1
- package/bin/domain/usecases/GetStoryObjectMapUseCase.js +1 -1
- package/bin/domain/usecases/GetStoryObjectMapUseCase.js.map +1 -1
- package/bin/domain/usecases/HandleScheduledEventUseCase.js +1 -8
- package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +2 -2
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
- package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js +1 -1
- package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js.map +1 -1
- package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js +1 -1
- package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js.map +1 -1
- package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js +1 -1
- package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js.map +1 -1
- package/bin/domain/usecases/StaleTmuxSessionKillUseCase.js +1 -1
- package/bin/domain/usecases/StaleTmuxSessionKillUseCase.js.map +1 -1
- package/bin/domain/usecases/StartPreparationUseCase.js +1 -1
- package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
- package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js +2 -2
- package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/cli/index.test.ts +0 -5
- package/src/adapter/entry-points/cli/index.ts +16 -17
- package/src/adapter/entry-points/cli/projectConfig.ts +0 -8
- package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.test.ts +4 -25
- package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.ts +4 -7
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +2 -25
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +4 -4
- package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.test.ts +11 -0
- package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.ts +3 -0
- package/src/adapter/entry-points/handlers/machineStatusWriter.test.ts +29 -11
- package/src/adapter/entry-points/handlers/machineStatusWriter.ts +30 -19
- package/src/adapter/entry-points/handlers/situationFileWriter.test.ts +0 -5
- package/src/adapter/entry-points/handlers/situationFileWriter.ts +0 -1
- package/src/adapter/entry-points/handlers/staleTmuxSessionCleaner.test.ts +0 -5
- package/src/adapter/entry-points/handlers/staleTmuxSessionCleaner.ts +1 -9
- package/src/adapter/repositories/LocalStorageCacheRepository.test.ts +75 -0
- package/src/adapter/repositories/LocalStorageCacheRepository.ts +24 -0
- package/src/adapter/repositories/ProcHostMetricsRepository.test.ts +29 -8
- package/src/adapter/repositories/ProcHostMetricsRepository.ts +10 -6
- package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +198 -47
- package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +160 -81
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +23 -3
- package/src/domain/usecases/GetStoryObjectMapUseCase.test.ts +7 -12
- package/src/domain/usecases/GetStoryObjectMapUseCase.ts +1 -5
- package/src/domain/usecases/HandleScheduledEventUseCase.test.ts +8 -24
- package/src/domain/usecases/HandleScheduledEventUseCase.ts +6 -17
- package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +4 -8
- package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.test.ts +35 -42
- package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.ts +1 -5
- package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +32 -32
- package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +1 -5
- package/src/domain/usecases/SetupTowerDefenceProjectUseCase.test.ts +17 -4
- package/src/domain/usecases/SetupTowerDefenceProjectUseCase.ts +1 -4
- package/src/domain/usecases/StaleTmuxSessionKillUseCase.test.ts +1 -7
- package/src/domain/usecases/StaleTmuxSessionKillUseCase.ts +1 -5
- package/src/domain/usecases/StartPreparationUseCase.test.ts +1 -94
- package/src/domain/usecases/StartPreparationUseCase.ts +2 -5
- package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +3 -10
- package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.test.ts +11 -0
- package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.ts +3 -1
- package/types/adapter/entry-points/cli/projectConfig.d.ts +0 -1
- package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
- package/types/adapter/entry-points/function/getStoryObjectMap.d.ts +1 -1
- package/types/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.d.ts +1 -1
- package/types/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts +1 -0
- package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts +1 -0
- package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/situationFileWriter.d.ts +0 -1
- package/types/adapter/entry-points/handlers/situationFileWriter.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/staleTmuxSessionCleaner.d.ts +0 -1
- package/types/adapter/entry-points/handlers/staleTmuxSessionCleaner.d.ts.map +1 -1
- package/types/adapter/repositories/LocalStorageCacheRepository.d.ts +2 -0
- package/types/adapter/repositories/LocalStorageCacheRepository.d.ts.map +1 -1
- package/types/adapter/repositories/ProcHostMetricsRepository.d.ts +1 -1
- package/types/adapter/repositories/ProcHostMetricsRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +22 -7
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts +2 -1
- package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -1
- package/types/domain/usecases/GetStoryObjectMapUseCase.d.ts +0 -1
- package/types/domain/usecases/GetStoryObjectMapUseCase.d.ts.map +1 -1
- package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +0 -1
- package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts +0 -1
- package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts.map +1 -1
- package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts +0 -1
- package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/SetupTowerDefenceProjectUseCase.d.ts.map +1 -1
- package/types/domain/usecases/StaleTmuxSessionKillUseCase.d.ts +0 -1
- package/types/domain/usecases/StaleTmuxSessionKillUseCase.d.ts.map +1 -1
- package/types/domain/usecases/StartPreparationUseCase.d.ts +0 -1
- package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +4 -3
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
- package/types/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.d.ts +1 -0
- package/types/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.d.ts.map +1 -1
|
@@ -13,6 +13,7 @@ export type ProjectItem = {
|
|
|
13
13
|
labels: string[];
|
|
14
14
|
assignees: string[];
|
|
15
15
|
createdAt: string;
|
|
16
|
+
updatedAt: string;
|
|
16
17
|
author: string;
|
|
17
18
|
closingIssueReferenceUrls: string[];
|
|
18
19
|
customFields: {
|
|
@@ -196,12 +197,15 @@ export class GraphqlProjectItemRepository extends BaseGitHubRepository {
|
|
|
196
197
|
return undefined;
|
|
197
198
|
}
|
|
198
199
|
};
|
|
199
|
-
fetchProjectItems = async (
|
|
200
|
+
fetchProjectItems = async (
|
|
201
|
+
projectId: string,
|
|
202
|
+
query?: string,
|
|
203
|
+
): Promise<ProjectItem[]> => {
|
|
200
204
|
const graphqlQueryString = `
|
|
201
|
-
query GetProjectItems($projectId: ID!, $after: String, $first: Int
|
|
205
|
+
query GetProjectItems($projectId: ID!, $after: String, $first: Int!, $query: String) {
|
|
202
206
|
node(id: $projectId) {
|
|
203
207
|
... on ProjectV2 {
|
|
204
|
-
items(first: $first, after: $after) {
|
|
208
|
+
items(first: $first, after: $after, query: $query) {
|
|
205
209
|
totalCount
|
|
206
210
|
pageInfo {
|
|
207
211
|
endCursor
|
|
@@ -261,6 +265,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
|
|
|
261
265
|
state
|
|
262
266
|
url
|
|
263
267
|
createdAt
|
|
268
|
+
updatedAt
|
|
264
269
|
author {
|
|
265
270
|
login
|
|
266
271
|
}
|
|
@@ -284,6 +289,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
|
|
|
284
289
|
state
|
|
285
290
|
url
|
|
286
291
|
createdAt
|
|
292
|
+
updatedAt
|
|
287
293
|
author {
|
|
288
294
|
login
|
|
289
295
|
}
|
|
@@ -345,6 +351,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
|
|
|
345
351
|
state: string;
|
|
346
352
|
url: string;
|
|
347
353
|
createdAt: string;
|
|
354
|
+
updatedAt: string;
|
|
348
355
|
author: { login: string } | null;
|
|
349
356
|
labels: { nodes: { name: string }[] };
|
|
350
357
|
assignees: { nodes: { login: string }[] };
|
|
@@ -360,6 +367,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
|
|
|
360
367
|
projectId: projectId,
|
|
361
368
|
after: after,
|
|
362
369
|
first: first,
|
|
370
|
+
query: query ?? null,
|
|
363
371
|
},
|
|
364
372
|
};
|
|
365
373
|
const response = await callWithRateLimitRetry(() =>
|
|
@@ -399,6 +407,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
|
|
|
399
407
|
state: string;
|
|
400
408
|
url: string;
|
|
401
409
|
createdAt: string;
|
|
410
|
+
updatedAt: string;
|
|
402
411
|
author: { login: string } | null;
|
|
403
412
|
labels: { nodes: { name: string }[] };
|
|
404
413
|
assignees: { nodes: { login: string }[] };
|
|
@@ -456,6 +465,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
|
|
|
456
465
|
state: string;
|
|
457
466
|
url: string;
|
|
458
467
|
createdAt: string;
|
|
468
|
+
updatedAt: string;
|
|
459
469
|
author: { login: string } | null;
|
|
460
470
|
labels: { nodes: { name: string }[] };
|
|
461
471
|
assignees: { nodes: { login: string }[] };
|
|
@@ -534,6 +544,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
|
|
|
534
544
|
state: string;
|
|
535
545
|
url: string;
|
|
536
546
|
createdAt: string;
|
|
547
|
+
updatedAt: string;
|
|
537
548
|
author: { login: string } | null;
|
|
538
549
|
labels: { nodes: { name: string }[] };
|
|
539
550
|
assignees: { nodes: { login: string }[] };
|
|
@@ -555,6 +566,10 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
|
|
|
555
566
|
labels: item.content.labels?.nodes?.map((l) => l.name) || [],
|
|
556
567
|
assignees: item.content.assignees?.nodes?.map((a) => a.login) || [],
|
|
557
568
|
createdAt: item.content.createdAt || new Date().toISOString(),
|
|
569
|
+
updatedAt:
|
|
570
|
+
item.content.updatedAt ||
|
|
571
|
+
item.content.createdAt ||
|
|
572
|
+
new Date().toISOString(),
|
|
558
573
|
author: item.content.author?.login || '',
|
|
559
574
|
closingIssueReferenceUrls:
|
|
560
575
|
item.content.closingIssuesReferences?.nodes
|
|
@@ -782,6 +797,7 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
|
|
|
782
797
|
url
|
|
783
798
|
body
|
|
784
799
|
createdAt
|
|
800
|
+
updatedAt
|
|
785
801
|
author {
|
|
786
802
|
login
|
|
787
803
|
}
|
|
@@ -859,6 +875,7 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
|
|
|
859
875
|
url
|
|
860
876
|
body
|
|
861
877
|
createdAt
|
|
878
|
+
updatedAt
|
|
862
879
|
author {
|
|
863
880
|
login
|
|
864
881
|
}
|
|
@@ -951,6 +968,7 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
|
|
|
951
968
|
url: string;
|
|
952
969
|
body: string;
|
|
953
970
|
createdAt: string;
|
|
971
|
+
updatedAt: string;
|
|
954
972
|
author: { login: string } | null;
|
|
955
973
|
labels: { nodes: { name: string }[] };
|
|
956
974
|
assignees: { nodes: { login: string }[] };
|
|
@@ -1029,6 +1047,8 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
|
|
|
1029
1047
|
labels: content.labels?.nodes?.map((l) => l.name) || [],
|
|
1030
1048
|
assignees: content.assignees?.nodes?.map((a) => a.login) || [],
|
|
1031
1049
|
createdAt: content.createdAt || new Date().toISOString(),
|
|
1050
|
+
updatedAt:
|
|
1051
|
+
content.updatedAt || content.createdAt || new Date().toISOString(),
|
|
1032
1052
|
author: content.author?.login || '',
|
|
1033
1053
|
closingIssueReferenceUrls:
|
|
1034
1054
|
content.closingIssuesReferences?.nodes
|
|
@@ -87,14 +87,12 @@ describe('GetStoryObjectMapUseCase', () => {
|
|
|
87
87
|
await expect(
|
|
88
88
|
useCase.run({
|
|
89
89
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
90
|
-
allowIssueCacheMinutes: 60,
|
|
91
90
|
}),
|
|
92
91
|
).rejects.toThrow(ProjectNotFoundError);
|
|
93
92
|
|
|
94
93
|
await expect(
|
|
95
94
|
useCase.run({
|
|
96
95
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
97
|
-
allowIssueCacheMinutes: 60,
|
|
98
96
|
}),
|
|
99
97
|
).rejects.toThrow(
|
|
100
98
|
'Project not found. projectUrl: https://github.com/orgs/test/projects/1',
|
|
@@ -108,14 +106,12 @@ describe('GetStoryObjectMapUseCase', () => {
|
|
|
108
106
|
await expect(
|
|
109
107
|
useCase.run({
|
|
110
108
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
111
|
-
allowIssueCacheMinutes: 60,
|
|
112
109
|
}),
|
|
113
110
|
).rejects.toThrow(ProjectNotFoundError);
|
|
114
111
|
|
|
115
112
|
await expect(
|
|
116
113
|
useCase.run({
|
|
117
114
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
118
|
-
allowIssueCacheMinutes: 60,
|
|
119
115
|
}),
|
|
120
116
|
).rejects.toThrow(
|
|
121
117
|
'Project not found. projectId: project-1 projectUrl: https://github.com/orgs/test/projects/1',
|
|
@@ -126,13 +122,13 @@ describe('GetStoryObjectMapUseCase', () => {
|
|
|
126
122
|
mockProjectRepository.findProjectIdByUrl.mockResolvedValue('project-1');
|
|
127
123
|
mockProjectRepository.getProject.mockResolvedValue(basicProject);
|
|
128
124
|
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
125
|
+
project: mock<Project>(),
|
|
129
126
|
issues: [],
|
|
130
127
|
cacheUsed: false,
|
|
131
128
|
});
|
|
132
129
|
|
|
133
130
|
const result = await useCase.run({
|
|
134
131
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
135
|
-
allowIssueCacheMinutes: 60,
|
|
136
132
|
});
|
|
137
133
|
|
|
138
134
|
expect(result.project).toBe(basicProject);
|
|
@@ -141,22 +137,21 @@ describe('GetStoryObjectMapUseCase', () => {
|
|
|
141
137
|
expect(result.storyObjectMap).toBeInstanceOf(Map);
|
|
142
138
|
});
|
|
143
139
|
|
|
144
|
-
it('should
|
|
140
|
+
it('should call getAllIssues with the resolved project id', async () => {
|
|
145
141
|
mockProjectRepository.findProjectIdByUrl.mockResolvedValue('project-1');
|
|
146
142
|
mockProjectRepository.getProject.mockResolvedValue(basicProject);
|
|
147
143
|
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
144
|
+
project: mock<Project>(),
|
|
148
145
|
issues: [],
|
|
149
146
|
cacheUsed: true,
|
|
150
147
|
});
|
|
151
148
|
|
|
152
149
|
const result = await useCase.run({
|
|
153
150
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
154
|
-
allowIssueCacheMinutes: 120,
|
|
155
151
|
});
|
|
156
152
|
|
|
157
153
|
expect(mockIssueRepository.getAllIssues).toHaveBeenCalledWith(
|
|
158
154
|
'project-1',
|
|
159
|
-
120,
|
|
160
155
|
);
|
|
161
156
|
expect(result.cacheUsed).toBe(true);
|
|
162
157
|
});
|
|
@@ -181,13 +176,13 @@ describe('GetStoryObjectMapUseCase', () => {
|
|
|
181
176
|
mockProjectRepository.findProjectIdByUrl.mockResolvedValue('project-1');
|
|
182
177
|
mockProjectRepository.getProject.mockResolvedValue(basicProject);
|
|
183
178
|
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
179
|
+
project: mock<Project>(),
|
|
184
180
|
issues: [issue1, issue2, issue3],
|
|
185
181
|
cacheUsed: false,
|
|
186
182
|
});
|
|
187
183
|
|
|
188
184
|
const result = await useCase.run({
|
|
189
185
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
190
|
-
allowIssueCacheMinutes: 60,
|
|
191
186
|
});
|
|
192
187
|
|
|
193
188
|
const story1Object = result.storyObjectMap.get('Story 1');
|
|
@@ -209,13 +204,13 @@ describe('GetStoryObjectMapUseCase', () => {
|
|
|
209
204
|
mockProjectRepository.findProjectIdByUrl.mockResolvedValue('project-1');
|
|
210
205
|
mockProjectRepository.getProject.mockResolvedValue(basicProject);
|
|
211
206
|
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
207
|
+
project: mock<Project>(),
|
|
212
208
|
issues: [storyIssue],
|
|
213
209
|
cacheUsed: false,
|
|
214
210
|
});
|
|
215
211
|
|
|
216
212
|
const result = await useCase.run({
|
|
217
213
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
218
|
-
allowIssueCacheMinutes: 60,
|
|
219
214
|
});
|
|
220
215
|
|
|
221
216
|
const story1Object = result.storyObjectMap.get('Story 1');
|
|
@@ -232,13 +227,13 @@ describe('GetStoryObjectMapUseCase', () => {
|
|
|
232
227
|
mockProjectRepository.findProjectIdByUrl.mockResolvedValue('project-1');
|
|
233
228
|
mockProjectRepository.getProject.mockResolvedValue(basicProject);
|
|
234
229
|
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
230
|
+
project: mock<Project>(),
|
|
235
231
|
issues: [issue],
|
|
236
232
|
cacheUsed: false,
|
|
237
233
|
});
|
|
238
234
|
|
|
239
235
|
const result = await useCase.run({
|
|
240
236
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
241
|
-
allowIssueCacheMinutes: 60,
|
|
242
237
|
});
|
|
243
238
|
|
|
244
239
|
const story1Object = result.storyObjectMap.get('Story 1');
|
|
@@ -254,13 +249,13 @@ describe('GetStoryObjectMapUseCase', () => {
|
|
|
254
249
|
mockProjectRepository.findProjectIdByUrl.mockResolvedValue('project-1');
|
|
255
250
|
mockProjectRepository.getProject.mockResolvedValue(projectWithoutStory);
|
|
256
251
|
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
252
|
+
project: mock<Project>(),
|
|
257
253
|
issues: [],
|
|
258
254
|
cacheUsed: false,
|
|
259
255
|
});
|
|
260
256
|
|
|
261
257
|
const result = await useCase.run({
|
|
262
258
|
projectUrl: 'https://github.com/orgs/test/projects/1',
|
|
263
|
-
allowIssueCacheMinutes: 60,
|
|
264
259
|
});
|
|
265
260
|
|
|
266
261
|
expect(result.storyObjectMap.size).toBe(0);
|
|
@@ -22,7 +22,6 @@ export class GetStoryObjectMapUseCase {
|
|
|
22
22
|
|
|
23
23
|
run = async (input: {
|
|
24
24
|
projectUrl: string;
|
|
25
|
-
allowIssueCacheMinutes: number;
|
|
26
25
|
}): Promise<{
|
|
27
26
|
project: Project;
|
|
28
27
|
issues: Issue[];
|
|
@@ -44,10 +43,7 @@ export class GetStoryObjectMapUseCase {
|
|
|
44
43
|
);
|
|
45
44
|
}
|
|
46
45
|
const { issues, cacheUsed }: { issues: Issue[]; cacheUsed: boolean } =
|
|
47
|
-
await this.issueRepository.getAllIssues(
|
|
48
|
-
projectId,
|
|
49
|
-
input.allowIssueCacheMinutes,
|
|
50
|
-
);
|
|
46
|
+
await this.issueRepository.getAllIssues(projectId);
|
|
51
47
|
const storyObjectMap: StoryObjectMap = this.createStoryObjectMap({
|
|
52
48
|
project,
|
|
53
49
|
issues,
|
|
@@ -160,6 +160,7 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
160
160
|
);
|
|
161
161
|
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
162
162
|
issues: [],
|
|
163
|
+
project: mock<Project>(),
|
|
163
164
|
cacheUsed: false,
|
|
164
165
|
});
|
|
165
166
|
mockSpreadsheetRepository.getSheet.mockResolvedValue([
|
|
@@ -184,7 +185,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
184
185
|
},
|
|
185
186
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
186
187
|
disabled: false,
|
|
187
|
-
allowIssueCacheMinutes: 60,
|
|
188
188
|
};
|
|
189
189
|
|
|
190
190
|
const mockProject = mock<Project>();
|
|
@@ -206,11 +206,14 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
206
206
|
},
|
|
207
207
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
208
208
|
disabled: false,
|
|
209
|
-
allowIssueCacheMinutes: 60,
|
|
210
209
|
};
|
|
211
210
|
|
|
212
211
|
const mockProject = mock<Project>();
|
|
213
|
-
|
|
212
|
+
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
213
|
+
issues: [],
|
|
214
|
+
project: mockProject,
|
|
215
|
+
cacheUsed: false,
|
|
216
|
+
});
|
|
214
217
|
await useCase.run(input);
|
|
215
218
|
expect(mockUpdateIssueStatusByLabelUseCase.run).toHaveBeenCalledWith({
|
|
216
219
|
project: mockProject,
|
|
@@ -231,7 +234,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
231
234
|
},
|
|
232
235
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
233
236
|
disabled: true,
|
|
234
|
-
allowIssueCacheMinutes: 60,
|
|
235
237
|
};
|
|
236
238
|
|
|
237
239
|
const result = await useCase.run(input);
|
|
@@ -254,7 +256,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
254
256
|
},
|
|
255
257
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
256
258
|
disabled: false,
|
|
257
|
-
allowIssueCacheMinutes: 60,
|
|
258
259
|
};
|
|
259
260
|
|
|
260
261
|
const mockProject = mock<Project>();
|
|
@@ -264,7 +265,7 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
264
265
|
expect(mockProjectRepository.findProjectIdByUrl).toHaveBeenCalled();
|
|
265
266
|
});
|
|
266
267
|
|
|
267
|
-
it('should
|
|
268
|
+
it('should call getAllIssues with the resolved project id', async () => {
|
|
268
269
|
const input = {
|
|
269
270
|
projectName: 'test-project',
|
|
270
271
|
org: 'test-org',
|
|
@@ -277,15 +278,11 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
277
278
|
},
|
|
278
279
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
279
280
|
disabled: false,
|
|
280
|
-
allowIssueCacheMinutes: 120,
|
|
281
281
|
};
|
|
282
282
|
|
|
283
|
-
const mockProject = mock<Project>();
|
|
284
|
-
mockProjectRepository.getProject.mockResolvedValue(mockProject);
|
|
285
283
|
await useCase.run(input);
|
|
286
284
|
expect(mockIssueRepository.getAllIssues).toHaveBeenCalledWith(
|
|
287
285
|
'project-1',
|
|
288
|
-
120,
|
|
289
286
|
);
|
|
290
287
|
});
|
|
291
288
|
|
|
@@ -304,7 +301,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
304
301
|
disabledStatus: 'disabled',
|
|
305
302
|
defaultStatus: null,
|
|
306
303
|
disabled: false,
|
|
307
|
-
allowIssueCacheMinutes: 60,
|
|
308
304
|
startPreparation: {
|
|
309
305
|
awaitingWorkspaceStatus: 'Awaiting Workspace',
|
|
310
306
|
preparationStatus: 'Preparation',
|
|
@@ -339,7 +335,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
339
335
|
},
|
|
340
336
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
341
337
|
disabled: false,
|
|
342
|
-
allowIssueCacheMinutes: 60,
|
|
343
338
|
};
|
|
344
339
|
|
|
345
340
|
mockProjectRepository.getProject.mockResolvedValue(mock<Project>());
|
|
@@ -350,7 +345,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
350
345
|
).toHaveBeenCalledWith(
|
|
351
346
|
expect.objectContaining({
|
|
352
347
|
projectUrl: 'https://github.com/test-org/test-project',
|
|
353
|
-
allowIssueCacheMinutes: 60,
|
|
354
348
|
}),
|
|
355
349
|
);
|
|
356
350
|
});
|
|
@@ -368,7 +362,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
368
362
|
},
|
|
369
363
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
370
364
|
disabled: false,
|
|
371
|
-
allowIssueCacheMinutes: 60,
|
|
372
365
|
};
|
|
373
366
|
|
|
374
367
|
mockProjectRepository.getProject.mockResolvedValue(mock<Project>());
|
|
@@ -392,7 +385,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
392
385
|
},
|
|
393
386
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
394
387
|
disabled: false,
|
|
395
|
-
allowIssueCacheMinutes: 60,
|
|
396
388
|
allowedIssueAuthors: ['top-level-author'],
|
|
397
389
|
};
|
|
398
390
|
|
|
@@ -421,7 +413,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
421
413
|
},
|
|
422
414
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
423
415
|
disabled: false,
|
|
424
|
-
allowIssueCacheMinutes: 60,
|
|
425
416
|
allowedIssueAuthors: ['top-level-author'],
|
|
426
417
|
startPreparation: {
|
|
427
418
|
defaultAgentName: 'agent1',
|
|
@@ -464,7 +455,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
464
455
|
},
|
|
465
456
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
466
457
|
disabled: false,
|
|
467
|
-
allowIssueCacheMinutes: 60,
|
|
468
458
|
startPreparation: {
|
|
469
459
|
defaultAgentName: 'agent1',
|
|
470
460
|
configFilePath: '/path/to/config.yml',
|
|
@@ -510,7 +500,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
510
500
|
},
|
|
511
501
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
512
502
|
disabled: false,
|
|
513
|
-
allowIssueCacheMinutes: 60,
|
|
514
503
|
startPreparation: {
|
|
515
504
|
defaultAgentName: 'aw',
|
|
516
505
|
configFilePath: '/path/to/config.yml',
|
|
@@ -540,7 +529,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
540
529
|
},
|
|
541
530
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
542
531
|
disabled: false,
|
|
543
|
-
allowIssueCacheMinutes: 60,
|
|
544
532
|
};
|
|
545
533
|
|
|
546
534
|
mockProjectRepository.getProject.mockResolvedValue(mock<Project>());
|
|
@@ -562,7 +550,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
562
550
|
},
|
|
563
551
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
564
552
|
disabled: false,
|
|
565
|
-
allowIssueCacheMinutes: 60,
|
|
566
553
|
};
|
|
567
554
|
|
|
568
555
|
const storyProject: Project = {
|
|
@@ -612,6 +599,7 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
612
599
|
mockProjectRepository.getProject.mockResolvedValue(storyProject);
|
|
613
600
|
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
614
601
|
issues: [],
|
|
602
|
+
project: storyProject,
|
|
615
603
|
cacheUsed: false,
|
|
616
604
|
});
|
|
617
605
|
mockIssueRepository.createNewIssue.mockResolvedValue(99);
|
|
@@ -705,7 +693,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
705
693
|
},
|
|
706
694
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
707
695
|
disabled: false,
|
|
708
|
-
allowIssueCacheMinutes: 10,
|
|
709
696
|
startPreparation: {
|
|
710
697
|
defaultAgentName: 'test-agent',
|
|
711
698
|
configFilePath: '/path/to/config.yml',
|
|
@@ -865,7 +852,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
865
852
|
},
|
|
866
853
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
867
854
|
disabled: false,
|
|
868
|
-
allowIssueCacheMinutes: 60,
|
|
869
855
|
};
|
|
870
856
|
|
|
871
857
|
beforeEach(() => {
|
|
@@ -1033,7 +1019,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
1033
1019
|
},
|
|
1034
1020
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
1035
1021
|
disabled: false,
|
|
1036
|
-
allowIssueCacheMinutes: 60,
|
|
1037
1022
|
};
|
|
1038
1023
|
|
|
1039
1024
|
it('should create an error issue and rethrow when spreadsheet read fails in findTargetDateAndUpdateLastExecutionDateTime', async () => {
|
|
@@ -1098,7 +1083,6 @@ describe('HandleScheduledEventUseCase', () => {
|
|
|
1098
1083
|
},
|
|
1099
1084
|
urlOfStoryView: 'https://github.com/test-org/test-project/issues',
|
|
1100
1085
|
disabled: false,
|
|
1101
|
-
allowIssueCacheMinutes: 60,
|
|
1102
1086
|
};
|
|
1103
1087
|
|
|
1104
1088
|
it('should not crash and should skip the LastExecutionDateTime write when lastExecutionDateTime is within 60 seconds of now', async () => {
|
|
@@ -95,7 +95,6 @@ export class HandleScheduledEventUseCase {
|
|
|
95
95
|
};
|
|
96
96
|
urlOfStoryView: string;
|
|
97
97
|
disabled: boolean;
|
|
98
|
-
allowIssueCacheMinutes: number;
|
|
99
98
|
labelsAsLlmAgentName?: string[] | null;
|
|
100
99
|
changeTargetPathAliases?: Record<string, string> | null;
|
|
101
100
|
allowedIssueAuthors?: string[] | null;
|
|
@@ -139,20 +138,13 @@ export class HandleScheduledEventUseCase {
|
|
|
139
138
|
`Project not found. projectUrl: ${input.projectUrl}`,
|
|
140
139
|
);
|
|
141
140
|
}
|
|
142
|
-
const project = await this.projectRepository.getProject(projectId);
|
|
143
|
-
if (!project) {
|
|
144
|
-
throw new ProjectNotFoundError(
|
|
145
|
-
`Project not found. projectId: ${
|
|
146
|
-
projectId
|
|
147
|
-
} projectUrl: ${input.projectUrl}`,
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
141
|
const now: Date = await this.dateRepository.now();
|
|
151
|
-
const {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
142
|
+
const {
|
|
143
|
+
issues,
|
|
144
|
+
project,
|
|
145
|
+
cacheUsed,
|
|
146
|
+
}: { issues: Issue[]; project: Project; cacheUsed: boolean } =
|
|
147
|
+
await this.issueRepository.getAllIssues(projectId);
|
|
156
148
|
const storyIssues: StoryObjectMap = await this.storyIssues({
|
|
157
149
|
project,
|
|
158
150
|
issues,
|
|
@@ -329,7 +321,6 @@ ${JSON.stringify(e)}
|
|
|
329
321
|
});
|
|
330
322
|
await this.revertNotReadyReviewQueueIssueUseCase.run({
|
|
331
323
|
projectUrl: input.projectUrl,
|
|
332
|
-
allowIssueCacheMinutes: input.allowIssueCacheMinutes,
|
|
333
324
|
labelsAsLlmAgentName,
|
|
334
325
|
changeTargetPathAliases: input.changeTargetPathAliases,
|
|
335
326
|
allowedIssueAuthors,
|
|
@@ -351,7 +342,6 @@ ${JSON.stringify(e)}
|
|
|
351
342
|
if (input.startPreparation.preparationProcessCheckCommand) {
|
|
352
343
|
await this.revertOrphanedPreparationUseCase.run({
|
|
353
344
|
projectUrl: input.projectUrl,
|
|
354
|
-
allowIssueCacheMinutes: input.allowIssueCacheMinutes,
|
|
355
345
|
preparationProcessCheckCommand:
|
|
356
346
|
input.startPreparation.preparationProcessCheckCommand,
|
|
357
347
|
thresholdForAutoReject: input.thresholdForAutoReject ?? 3,
|
|
@@ -377,7 +367,6 @@ ${JSON.stringify(e)}
|
|
|
377
367
|
input.startPreparation.utilizationPercentageThreshold ?? 90,
|
|
378
368
|
allowedIssueAuthors,
|
|
379
369
|
codexHomeCandidates: input.startPreparation.codexHomeCandidates ?? null,
|
|
380
|
-
allowIssueCacheMinutes: input.allowIssueCacheMinutes,
|
|
381
370
|
labelsAsLlmAgentName,
|
|
382
371
|
});
|
|
383
372
|
return { rotationOrder: preparationResult.rotationOrder };
|
|
@@ -124,10 +124,8 @@ export class NotifyFinishedIssuePreparationUseCase {
|
|
|
124
124
|
|
|
125
125
|
if (issue.dependedIssueUrls.length === 0) {
|
|
126
126
|
try {
|
|
127
|
-
const storyObjectMap =
|
|
128
|
-
project
|
|
129
|
-
0,
|
|
130
|
-
);
|
|
127
|
+
const storyObjectMap =
|
|
128
|
+
await this.issueRepository.getStoryObjectMap(project);
|
|
131
129
|
for (const storyObject of storyObjectMap.values()) {
|
|
132
130
|
const towerDefenceIssue = storyObject.issues.find(
|
|
133
131
|
(i) => i.url === issue.url,
|
|
@@ -387,10 +385,8 @@ export class NotifyFinishedIssuePreparationUseCase {
|
|
|
387
385
|
}
|
|
388
386
|
|
|
389
387
|
try {
|
|
390
|
-
const storyObjectMap =
|
|
391
|
-
project
|
|
392
|
-
0,
|
|
393
|
-
);
|
|
388
|
+
const storyObjectMap =
|
|
389
|
+
await this.issueRepository.getStoryObjectMap(project);
|
|
394
390
|
|
|
395
391
|
const isWorkflowBlocker = Array.from(storyObjectMap.entries()).some(
|
|
396
392
|
([storyName, storyObject]) =>
|