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.
Files changed (123) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +8 -9
  3. package/bin/adapter/entry-points/cli/index.js +8 -14
  4. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  5. package/bin/adapter/entry-points/cli/projectConfig.js +0 -6
  6. package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
  7. package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js +6 -12
  8. package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js.map +1 -1
  9. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +8 -10
  10. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  11. package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js +2 -1
  12. package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js.map +1 -1
  13. package/bin/adapter/entry-points/handlers/machineStatusWriter.js +23 -19
  14. package/bin/adapter/entry-points/handlers/machineStatusWriter.js.map +1 -1
  15. package/bin/adapter/entry-points/handlers/situationFileWriter.js.map +1 -1
  16. package/bin/adapter/entry-points/handlers/staleTmuxSessionCleaner.js +1 -2
  17. package/bin/adapter/entry-points/handlers/staleTmuxSessionCleaner.js.map +1 -1
  18. package/bin/adapter/repositories/LocalStorageCacheRepository.js +25 -0
  19. package/bin/adapter/repositories/LocalStorageCacheRepository.js.map +1 -1
  20. package/bin/adapter/repositories/ProcHostMetricsRepository.js +10 -5
  21. package/bin/adapter/repositories/ProcHostMetricsRepository.js.map +1 -1
  22. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +119 -59
  23. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
  24. package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +12 -3
  25. package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -1
  26. package/bin/domain/usecases/GetStoryObjectMapUseCase.js +1 -1
  27. package/bin/domain/usecases/GetStoryObjectMapUseCase.js.map +1 -1
  28. package/bin/domain/usecases/HandleScheduledEventUseCase.js +1 -8
  29. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
  30. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +2 -2
  31. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
  32. package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js +1 -1
  33. package/bin/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.js.map +1 -1
  34. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js +1 -1
  35. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js.map +1 -1
  36. package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js +1 -1
  37. package/bin/domain/usecases/SetupTowerDefenceProjectUseCase.js.map +1 -1
  38. package/bin/domain/usecases/StaleTmuxSessionKillUseCase.js +1 -1
  39. package/bin/domain/usecases/StaleTmuxSessionKillUseCase.js.map +1 -1
  40. package/bin/domain/usecases/StartPreparationUseCase.js +1 -1
  41. package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
  42. package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js +2 -2
  43. package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/adapter/entry-points/cli/index.test.ts +0 -5
  46. package/src/adapter/entry-points/cli/index.ts +16 -17
  47. package/src/adapter/entry-points/cli/projectConfig.ts +0 -8
  48. package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.test.ts +4 -25
  49. package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.ts +4 -7
  50. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +2 -25
  51. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +4 -4
  52. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.test.ts +11 -0
  53. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.ts +3 -0
  54. package/src/adapter/entry-points/handlers/machineStatusWriter.test.ts +29 -11
  55. package/src/adapter/entry-points/handlers/machineStatusWriter.ts +30 -19
  56. package/src/adapter/entry-points/handlers/situationFileWriter.test.ts +0 -5
  57. package/src/adapter/entry-points/handlers/situationFileWriter.ts +0 -1
  58. package/src/adapter/entry-points/handlers/staleTmuxSessionCleaner.test.ts +0 -5
  59. package/src/adapter/entry-points/handlers/staleTmuxSessionCleaner.ts +1 -9
  60. package/src/adapter/repositories/LocalStorageCacheRepository.test.ts +75 -0
  61. package/src/adapter/repositories/LocalStorageCacheRepository.ts +24 -0
  62. package/src/adapter/repositories/ProcHostMetricsRepository.test.ts +29 -8
  63. package/src/adapter/repositories/ProcHostMetricsRepository.ts +10 -6
  64. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +198 -47
  65. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +160 -81
  66. package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +23 -3
  67. package/src/domain/usecases/GetStoryObjectMapUseCase.test.ts +7 -12
  68. package/src/domain/usecases/GetStoryObjectMapUseCase.ts +1 -5
  69. package/src/domain/usecases/HandleScheduledEventUseCase.test.ts +8 -24
  70. package/src/domain/usecases/HandleScheduledEventUseCase.ts +6 -17
  71. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +4 -8
  72. package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.test.ts +35 -42
  73. package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.ts +1 -5
  74. package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +32 -32
  75. package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +1 -5
  76. package/src/domain/usecases/SetupTowerDefenceProjectUseCase.test.ts +17 -4
  77. package/src/domain/usecases/SetupTowerDefenceProjectUseCase.ts +1 -4
  78. package/src/domain/usecases/StaleTmuxSessionKillUseCase.test.ts +1 -7
  79. package/src/domain/usecases/StaleTmuxSessionKillUseCase.ts +1 -5
  80. package/src/domain/usecases/StartPreparationUseCase.test.ts +1 -94
  81. package/src/domain/usecases/StartPreparationUseCase.ts +2 -5
  82. package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +3 -10
  83. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.test.ts +11 -0
  84. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.ts +3 -1
  85. package/types/adapter/entry-points/cli/projectConfig.d.ts +0 -1
  86. package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
  87. package/types/adapter/entry-points/function/getStoryObjectMap.d.ts +1 -1
  88. package/types/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.d.ts +1 -1
  89. package/types/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.d.ts.map +1 -1
  90. package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts +1 -0
  91. package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts.map +1 -1
  92. package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts +1 -0
  93. package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts.map +1 -1
  94. package/types/adapter/entry-points/handlers/situationFileWriter.d.ts +0 -1
  95. package/types/adapter/entry-points/handlers/situationFileWriter.d.ts.map +1 -1
  96. package/types/adapter/entry-points/handlers/staleTmuxSessionCleaner.d.ts +0 -1
  97. package/types/adapter/entry-points/handlers/staleTmuxSessionCleaner.d.ts.map +1 -1
  98. package/types/adapter/repositories/LocalStorageCacheRepository.d.ts +2 -0
  99. package/types/adapter/repositories/LocalStorageCacheRepository.d.ts.map +1 -1
  100. package/types/adapter/repositories/ProcHostMetricsRepository.d.ts +1 -1
  101. package/types/adapter/repositories/ProcHostMetricsRepository.d.ts.map +1 -1
  102. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +22 -7
  103. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
  104. package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts +2 -1
  105. package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -1
  106. package/types/domain/usecases/GetStoryObjectMapUseCase.d.ts +0 -1
  107. package/types/domain/usecases/GetStoryObjectMapUseCase.d.ts.map +1 -1
  108. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +0 -1
  109. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
  110. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
  111. package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts +0 -1
  112. package/types/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.d.ts.map +1 -1
  113. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts +0 -1
  114. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts.map +1 -1
  115. package/types/domain/usecases/SetupTowerDefenceProjectUseCase.d.ts.map +1 -1
  116. package/types/domain/usecases/StaleTmuxSessionKillUseCase.d.ts +0 -1
  117. package/types/domain/usecases/StaleTmuxSessionKillUseCase.d.ts.map +1 -1
  118. package/types/domain/usecases/StartPreparationUseCase.d.ts +0 -1
  119. package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -1
  120. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +4 -3
  121. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
  122. package/types/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.d.ts +1 -0
  123. 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 (projectId: string): Promise<ProjectItem[]> => {
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 pass allowIssueCacheMinutes to getAllIssues', async () => {
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
- mockProjectRepository.getProject.mockResolvedValue(mockProject);
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 pass allowIssueCacheMinutes to getAllIssues', async () => {
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 { issues, cacheUsed }: { issues: Issue[]; cacheUsed: boolean } =
152
- await this.issueRepository.getAllIssues(
153
- projectId,
154
- input.allowIssueCacheMinutes,
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 = await this.issueRepository.getStoryObjectMap(
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 = await this.issueRepository.getStoryObjectMap(
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]) =>