github-issue-tower-defence-management 1.194.2 → 1.196.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/.github/workflows/codeql.yml +2 -2
- package/CHANGELOG.md +19 -0
- package/README.md +2 -2
- package/bin/adapter/entry-points/cli/fleetConfig.js +2 -0
- package/bin/adapter/entry-points/cli/fleetConfig.js.map +1 -1
- package/bin/adapter/entry-points/handlers/OauthTokenSelectHandler.js +1 -1
- package/bin/adapter/entry-points/handlers/OauthTokenSelectHandler.js.map +1 -1
- package/bin/domain/usecases/LiveSessionOauthTokenSelectUseCase.js +17 -2
- package/bin/domain/usecases/LiveSessionOauthTokenSelectUseCase.js.map +1 -1
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +36 -0
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
- package/bin/domain/usecases/OauthTokenSelectUseCase.js +18 -10
- package/bin/domain/usecases/OauthTokenSelectUseCase.js.map +1 -1
- package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js +23 -3
- package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js.map +1 -1
- package/package.json +2 -2
- package/src/adapter/entry-points/cli/fleetConfig.test.ts +33 -1
- package/src/adapter/entry-points/cli/fleetConfig.ts +16 -0
- package/src/adapter/entry-points/handlers/OauthTokenSelectHandler.test.ts +78 -0
- package/src/adapter/entry-points/handlers/OauthTokenSelectHandler.ts +2 -0
- package/src/domain/usecases/LiveSessionOauthTokenSelectUseCase.test.ts +137 -17
- package/src/domain/usecases/LiveSessionOauthTokenSelectUseCase.ts +30 -2
- package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +346 -0
- package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +64 -0
- package/src/domain/usecases/OauthTokenSelectUseCase.test.ts +99 -0
- package/src/domain/usecases/OauthTokenSelectUseCase.ts +30 -5
- package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +400 -1
- package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +44 -3
- package/types/adapter/entry-points/cli/fleetConfig.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/OauthTokenSelectHandler.d.ts.map +1 -1
- package/types/domain/usecases/LiveSessionOauthTokenSelectUseCase.d.ts +3 -0
- package/types/domain/usecases/LiveSessionOauthTokenSelectUseCase.d.ts.map +1 -1
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts +1 -0
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/OauthTokenSelectUseCase.d.ts +7 -1
- package/types/domain/usecases/OauthTokenSelectUseCase.d.ts.map +1 -1
- package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts +1 -0
- package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts.map +1 -1
|
@@ -816,7 +816,7 @@ describe('RevertOrphanedPreparationUseCase', () => {
|
|
|
816
816
|
);
|
|
817
817
|
});
|
|
818
818
|
|
|
819
|
-
it('should advance orphaned issue with non-developer agent field to Awaiting Quality Check when no
|
|
819
|
+
it('should advance orphaned issue with non-developer agent field to Awaiting Quality Check when no linked PRs exist', async () => {
|
|
820
820
|
const stuckIssue = createMockIssue({
|
|
821
821
|
url: 'https://github.com/user/repo/issues/10',
|
|
822
822
|
status: 'Preparation',
|
|
@@ -2133,6 +2133,405 @@ describe('RevertOrphanedPreparationUseCase', () => {
|
|
|
2133
2133
|
});
|
|
2134
2134
|
});
|
|
2135
2135
|
|
|
2136
|
+
describe('non-developer agent CI failure reassignment', () => {
|
|
2137
|
+
const makeProjectWithDeveloper = (developerName = 'developer') => {
|
|
2138
|
+
const project = createMockProject();
|
|
2139
|
+
project.agent = {
|
|
2140
|
+
name: 'Agent',
|
|
2141
|
+
fieldId: 'agent-field-id',
|
|
2142
|
+
options: [
|
|
2143
|
+
{
|
|
2144
|
+
id: 'opt-developer',
|
|
2145
|
+
name: developerName,
|
|
2146
|
+
color: 'GRAY',
|
|
2147
|
+
description: '',
|
|
2148
|
+
},
|
|
2149
|
+
],
|
|
2150
|
+
};
|
|
2151
|
+
return project;
|
|
2152
|
+
};
|
|
2153
|
+
|
|
2154
|
+
it('should return to Awaiting Workspace and reassign to developer when chore agent has exactly one linked PR with failing CI', async () => {
|
|
2155
|
+
const projectWithDeveloper = makeProjectWithDeveloper();
|
|
2156
|
+
mockProjectRepository.findProjectIdByUrl.mockResolvedValue('project-1');
|
|
2157
|
+
mockProjectRepository.getProject.mockResolvedValue(projectWithDeveloper);
|
|
2158
|
+
mockProjectRepository.getByUrl.mockResolvedValue(projectWithDeveloper);
|
|
2159
|
+
const stuckIssue = createMockIssue({
|
|
2160
|
+
url: 'https://github.com/user/repo/issues/10',
|
|
2161
|
+
status: 'Preparation',
|
|
2162
|
+
labels: [],
|
|
2163
|
+
agent: 'chore',
|
|
2164
|
+
});
|
|
2165
|
+
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
2166
|
+
project: projectWithDeveloper,
|
|
2167
|
+
issues: [stuckIssue],
|
|
2168
|
+
cacheUsed: false,
|
|
2169
|
+
});
|
|
2170
|
+
mockIssueRepository.get.mockImplementation(async (issueUrl: string) =>
|
|
2171
|
+
createMockIssue({
|
|
2172
|
+
url: issueUrl,
|
|
2173
|
+
status: 'Preparation',
|
|
2174
|
+
agent: 'chore',
|
|
2175
|
+
}),
|
|
2176
|
+
);
|
|
2177
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2178
|
+
stdout: '',
|
|
2179
|
+
stderr: '',
|
|
2180
|
+
exitCode: 1,
|
|
2181
|
+
});
|
|
2182
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2183
|
+
{
|
|
2184
|
+
author: 'bot',
|
|
2185
|
+
content: 'From: :robot: agent report',
|
|
2186
|
+
createdAt: new Date(),
|
|
2187
|
+
},
|
|
2188
|
+
]);
|
|
2189
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([
|
|
2190
|
+
{
|
|
2191
|
+
...createPassingPr(),
|
|
2192
|
+
url: 'https://github.com/user/repo/pull/99',
|
|
2193
|
+
isPassedAllCiJob: false,
|
|
2194
|
+
isCiStateSuccess: false,
|
|
2195
|
+
},
|
|
2196
|
+
]);
|
|
2197
|
+
|
|
2198
|
+
await useCase.run({
|
|
2199
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2200
|
+
preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
|
|
2201
|
+
thresholdForAutoReject: 3,
|
|
2202
|
+
});
|
|
2203
|
+
|
|
2204
|
+
expect(mockIssueRepository.setIssueAgentField.mock.calls).toEqual([
|
|
2205
|
+
[stuckIssue.url, projectWithDeveloper, 'opt-developer'],
|
|
2206
|
+
]);
|
|
2207
|
+
expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
|
|
2208
|
+
expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('1');
|
|
2209
|
+
expect(mockIssueCommentRepository.createComment.mock.calls).toHaveLength(
|
|
2210
|
+
1,
|
|
2211
|
+
);
|
|
2212
|
+
expect(
|
|
2213
|
+
mockIssueCommentRepository.createComment.mock.calls[0][1],
|
|
2214
|
+
).toContain('ANY_CI_JOB_FAILED_OR_IN_PROGRESS');
|
|
2215
|
+
expect(
|
|
2216
|
+
mockIssueCommentRepository.createComment.mock.calls[0][1],
|
|
2217
|
+
).toContain('https://github.com/user/repo/pull/99');
|
|
2218
|
+
});
|
|
2219
|
+
|
|
2220
|
+
it('should advance to Awaiting Quality Check when chore agent has exactly one linked PR where all CI passes', async () => {
|
|
2221
|
+
const stuckIssue = createMockIssue({
|
|
2222
|
+
url: 'https://github.com/user/repo/issues/10',
|
|
2223
|
+
status: 'Preparation',
|
|
2224
|
+
labels: [],
|
|
2225
|
+
agent: 'chore',
|
|
2226
|
+
});
|
|
2227
|
+
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
2228
|
+
project: mockProject,
|
|
2229
|
+
issues: [stuckIssue],
|
|
2230
|
+
cacheUsed: false,
|
|
2231
|
+
});
|
|
2232
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2233
|
+
stdout: '',
|
|
2234
|
+
stderr: '',
|
|
2235
|
+
exitCode: 1,
|
|
2236
|
+
});
|
|
2237
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2238
|
+
{
|
|
2239
|
+
author: 'bot',
|
|
2240
|
+
content: 'From: :robot: agent report',
|
|
2241
|
+
createdAt: new Date(),
|
|
2242
|
+
},
|
|
2243
|
+
]);
|
|
2244
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([
|
|
2245
|
+
createPassingPr(),
|
|
2246
|
+
]);
|
|
2247
|
+
|
|
2248
|
+
await useCase.run({
|
|
2249
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2250
|
+
preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
|
|
2251
|
+
thresholdForAutoReject: 3,
|
|
2252
|
+
});
|
|
2253
|
+
|
|
2254
|
+
expect(mockIssueRepository.setIssueAgentField.mock.calls).toHaveLength(0);
|
|
2255
|
+
expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
|
|
2256
|
+
expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('4');
|
|
2257
|
+
});
|
|
2258
|
+
|
|
2259
|
+
it('should advance to Awaiting Quality Check when chore agent has no linked PRs', async () => {
|
|
2260
|
+
const stuckIssue = createMockIssue({
|
|
2261
|
+
url: 'https://github.com/user/repo/issues/10',
|
|
2262
|
+
status: 'Preparation',
|
|
2263
|
+
labels: [],
|
|
2264
|
+
agent: 'chore',
|
|
2265
|
+
});
|
|
2266
|
+
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
2267
|
+
project: mockProject,
|
|
2268
|
+
issues: [stuckIssue],
|
|
2269
|
+
cacheUsed: false,
|
|
2270
|
+
});
|
|
2271
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2272
|
+
stdout: '',
|
|
2273
|
+
stderr: '',
|
|
2274
|
+
exitCode: 1,
|
|
2275
|
+
});
|
|
2276
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2277
|
+
{
|
|
2278
|
+
author: 'bot',
|
|
2279
|
+
content: 'From: :robot: agent report',
|
|
2280
|
+
createdAt: new Date(),
|
|
2281
|
+
},
|
|
2282
|
+
]);
|
|
2283
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([]);
|
|
2284
|
+
|
|
2285
|
+
await useCase.run({
|
|
2286
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2287
|
+
preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
|
|
2288
|
+
thresholdForAutoReject: 3,
|
|
2289
|
+
});
|
|
2290
|
+
|
|
2291
|
+
expect(mockIssueRepository.setIssueAgentField.mock.calls).toHaveLength(0);
|
|
2292
|
+
expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
|
|
2293
|
+
expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('4');
|
|
2294
|
+
});
|
|
2295
|
+
|
|
2296
|
+
it('should not trigger the new path when developer agent has a failing CI PR', async () => {
|
|
2297
|
+
const stuckIssue = createMockIssue({
|
|
2298
|
+
url: 'https://github.com/user/repo/issues/10',
|
|
2299
|
+
status: 'Preparation',
|
|
2300
|
+
labels: ['llm-agent:developer'],
|
|
2301
|
+
agent: 'developer',
|
|
2302
|
+
});
|
|
2303
|
+
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
2304
|
+
project: mockProject,
|
|
2305
|
+
issues: [stuckIssue],
|
|
2306
|
+
cacheUsed: false,
|
|
2307
|
+
});
|
|
2308
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2309
|
+
stdout: '',
|
|
2310
|
+
stderr: '',
|
|
2311
|
+
exitCode: 1,
|
|
2312
|
+
});
|
|
2313
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2314
|
+
{
|
|
2315
|
+
author: 'bot',
|
|
2316
|
+
content: 'From: :robot: agent report',
|
|
2317
|
+
createdAt: new Date(),
|
|
2318
|
+
},
|
|
2319
|
+
]);
|
|
2320
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([
|
|
2321
|
+
{
|
|
2322
|
+
...createPassingPr(),
|
|
2323
|
+
isPassedAllCiJob: false,
|
|
2324
|
+
isCiStateSuccess: false,
|
|
2325
|
+
},
|
|
2326
|
+
]);
|
|
2327
|
+
|
|
2328
|
+
await useCase.run({
|
|
2329
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2330
|
+
preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
|
|
2331
|
+
thresholdForAutoReject: 3,
|
|
2332
|
+
});
|
|
2333
|
+
|
|
2334
|
+
expect(mockIssueRepository.setIssueAgentField.mock.calls).toHaveLength(0);
|
|
2335
|
+
expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
|
|
2336
|
+
expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('1');
|
|
2337
|
+
});
|
|
2338
|
+
|
|
2339
|
+
it('should not trigger the new path when agent is pr-reviewer and PR has failing CI', async () => {
|
|
2340
|
+
const stuckIssue = createMockIssue({
|
|
2341
|
+
url: 'https://github.com/user/repo/issues/10',
|
|
2342
|
+
status: 'Preparation',
|
|
2343
|
+
labels: [],
|
|
2344
|
+
agent: 'pr-reviewer',
|
|
2345
|
+
});
|
|
2346
|
+
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
2347
|
+
project: mockProject,
|
|
2348
|
+
issues: [stuckIssue],
|
|
2349
|
+
cacheUsed: false,
|
|
2350
|
+
});
|
|
2351
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2352
|
+
stdout: '',
|
|
2353
|
+
stderr: '',
|
|
2354
|
+
exitCode: 1,
|
|
2355
|
+
});
|
|
2356
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2357
|
+
{
|
|
2358
|
+
author: 'bot',
|
|
2359
|
+
content: 'From: :robot: agent report',
|
|
2360
|
+
createdAt: new Date(),
|
|
2361
|
+
},
|
|
2362
|
+
]);
|
|
2363
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([
|
|
2364
|
+
{
|
|
2365
|
+
...createPassingPr(),
|
|
2366
|
+
isPassedAllCiJob: false,
|
|
2367
|
+
isCiStateSuccess: false,
|
|
2368
|
+
},
|
|
2369
|
+
]);
|
|
2370
|
+
|
|
2371
|
+
await useCase.run({
|
|
2372
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2373
|
+
preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
|
|
2374
|
+
thresholdForAutoReject: 3,
|
|
2375
|
+
});
|
|
2376
|
+
|
|
2377
|
+
expect(mockIssueRepository.setIssueAgentField.mock.calls).toHaveLength(0);
|
|
2378
|
+
expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
|
|
2379
|
+
expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('4');
|
|
2380
|
+
});
|
|
2381
|
+
|
|
2382
|
+
it('should not trigger the new path when agent is null and PR has failing CI', async () => {
|
|
2383
|
+
const stuckIssue = createMockIssue({
|
|
2384
|
+
url: 'https://github.com/user/repo/issues/10',
|
|
2385
|
+
status: 'Preparation',
|
|
2386
|
+
labels: [],
|
|
2387
|
+
agent: null,
|
|
2388
|
+
});
|
|
2389
|
+
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
2390
|
+
project: mockProject,
|
|
2391
|
+
issues: [stuckIssue],
|
|
2392
|
+
cacheUsed: false,
|
|
2393
|
+
});
|
|
2394
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2395
|
+
stdout: '',
|
|
2396
|
+
stderr: '',
|
|
2397
|
+
exitCode: 1,
|
|
2398
|
+
});
|
|
2399
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2400
|
+
{
|
|
2401
|
+
author: 'bot',
|
|
2402
|
+
content: 'From: :robot: agent report',
|
|
2403
|
+
createdAt: new Date(),
|
|
2404
|
+
},
|
|
2405
|
+
]);
|
|
2406
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([
|
|
2407
|
+
{
|
|
2408
|
+
...createPassingPr(),
|
|
2409
|
+
isPassedAllCiJob: false,
|
|
2410
|
+
isCiStateSuccess: false,
|
|
2411
|
+
},
|
|
2412
|
+
]);
|
|
2413
|
+
|
|
2414
|
+
await useCase.run({
|
|
2415
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2416
|
+
preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
|
|
2417
|
+
thresholdForAutoReject: 3,
|
|
2418
|
+
});
|
|
2419
|
+
|
|
2420
|
+
expect(mockIssueRepository.setIssueAgentField.mock.calls).toHaveLength(0);
|
|
2421
|
+
expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
|
|
2422
|
+
expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('1');
|
|
2423
|
+
});
|
|
2424
|
+
|
|
2425
|
+
it('should not trigger the new path when chore agent has two linked PRs both with failing CI', async () => {
|
|
2426
|
+
const stuckIssue = createMockIssue({
|
|
2427
|
+
url: 'https://github.com/user/repo/issues/10',
|
|
2428
|
+
status: 'Preparation',
|
|
2429
|
+
labels: [],
|
|
2430
|
+
agent: 'chore',
|
|
2431
|
+
});
|
|
2432
|
+
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
2433
|
+
project: mockProject,
|
|
2434
|
+
issues: [stuckIssue],
|
|
2435
|
+
cacheUsed: false,
|
|
2436
|
+
});
|
|
2437
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2438
|
+
stdout: '',
|
|
2439
|
+
stderr: '',
|
|
2440
|
+
exitCode: 1,
|
|
2441
|
+
});
|
|
2442
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2443
|
+
{
|
|
2444
|
+
author: 'bot',
|
|
2445
|
+
content: 'From: :robot: agent report',
|
|
2446
|
+
createdAt: new Date(),
|
|
2447
|
+
},
|
|
2448
|
+
]);
|
|
2449
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([
|
|
2450
|
+
{
|
|
2451
|
+
...createPassingPr(),
|
|
2452
|
+
url: 'https://github.com/user/repo/pull/99',
|
|
2453
|
+
isPassedAllCiJob: false,
|
|
2454
|
+
},
|
|
2455
|
+
{
|
|
2456
|
+
...createPassingPr(),
|
|
2457
|
+
url: 'https://github.com/user/repo/pull/100',
|
|
2458
|
+
isPassedAllCiJob: false,
|
|
2459
|
+
},
|
|
2460
|
+
]);
|
|
2461
|
+
|
|
2462
|
+
await useCase.run({
|
|
2463
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2464
|
+
preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
|
|
2465
|
+
thresholdForAutoReject: 3,
|
|
2466
|
+
});
|
|
2467
|
+
|
|
2468
|
+
expect(mockIssueRepository.setIssueAgentField.mock.calls).toHaveLength(0);
|
|
2469
|
+
expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(1);
|
|
2470
|
+
expect(mockIssueRepository.updateStatus.mock.calls[0][2]).toBe('4');
|
|
2471
|
+
});
|
|
2472
|
+
|
|
2473
|
+
it('should reassign to the configured developerAgentName when chore agent has a failing CI PR', async () => {
|
|
2474
|
+
const projectWithCustomDeveloper =
|
|
2475
|
+
makeProjectWithDeveloper('custom-developer');
|
|
2476
|
+
mockProjectRepository.findProjectIdByUrl.mockResolvedValue('project-1');
|
|
2477
|
+
mockProjectRepository.getProject.mockResolvedValue(
|
|
2478
|
+
projectWithCustomDeveloper,
|
|
2479
|
+
);
|
|
2480
|
+
mockProjectRepository.getByUrl.mockResolvedValue(
|
|
2481
|
+
projectWithCustomDeveloper,
|
|
2482
|
+
);
|
|
2483
|
+
const stuckIssue = createMockIssue({
|
|
2484
|
+
url: 'https://github.com/user/repo/issues/10',
|
|
2485
|
+
status: 'Preparation',
|
|
2486
|
+
labels: [],
|
|
2487
|
+
agent: 'chore',
|
|
2488
|
+
});
|
|
2489
|
+
mockIssueRepository.getAllIssues.mockResolvedValue({
|
|
2490
|
+
project: projectWithCustomDeveloper,
|
|
2491
|
+
issues: [stuckIssue],
|
|
2492
|
+
cacheUsed: false,
|
|
2493
|
+
});
|
|
2494
|
+
mockIssueRepository.get.mockImplementation(async (issueUrl: string) =>
|
|
2495
|
+
createMockIssue({
|
|
2496
|
+
url: issueUrl,
|
|
2497
|
+
status: 'Preparation',
|
|
2498
|
+
agent: 'chore',
|
|
2499
|
+
}),
|
|
2500
|
+
);
|
|
2501
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2502
|
+
stdout: '',
|
|
2503
|
+
stderr: '',
|
|
2504
|
+
exitCode: 1,
|
|
2505
|
+
});
|
|
2506
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2507
|
+
{
|
|
2508
|
+
author: 'bot',
|
|
2509
|
+
content: 'From: :robot: agent report',
|
|
2510
|
+
createdAt: new Date(),
|
|
2511
|
+
},
|
|
2512
|
+
]);
|
|
2513
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([
|
|
2514
|
+
{
|
|
2515
|
+
...createPassingPr(),
|
|
2516
|
+
url: 'https://github.com/user/repo/pull/99',
|
|
2517
|
+
isPassedAllCiJob: false,
|
|
2518
|
+
isCiStateSuccess: false,
|
|
2519
|
+
},
|
|
2520
|
+
]);
|
|
2521
|
+
|
|
2522
|
+
await useCase.run({
|
|
2523
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2524
|
+
preparationProcessCheckCommand: 'pgrep -fa "claude-agent.*{URL}"',
|
|
2525
|
+
thresholdForAutoReject: 3,
|
|
2526
|
+
developerAgentName: 'custom-developer',
|
|
2527
|
+
});
|
|
2528
|
+
|
|
2529
|
+
expect(mockIssueRepository.setIssueAgentField.mock.calls).toEqual([
|
|
2530
|
+
[stuckIssue.url, projectWithCustomDeveloper, 'opt-developer'],
|
|
2531
|
+
]);
|
|
2532
|
+
});
|
|
2533
|
+
});
|
|
2534
|
+
|
|
2136
2535
|
it('should revert orphaned issue to Awaiting Workspace and not throw when getCommentsFromIssue returns 404', async () => {
|
|
2137
2536
|
const stuckIssue = createMockIssue({
|
|
2138
2537
|
url: 'https://github.com/user/repo/issues/10',
|
|
@@ -44,7 +44,8 @@ type OrphanedPreparationOutcome =
|
|
|
44
44
|
| 'advanceToQualityCheck'
|
|
45
45
|
| 'returnToLabelSelectedAgent'
|
|
46
46
|
| 'returnToOwnerApprovalCycle'
|
|
47
|
-
| 'reject'
|
|
47
|
+
| 'reject'
|
|
48
|
+
| 'reassignToDeveloper';
|
|
48
49
|
|
|
49
50
|
export class RevertOrphanedPreparationUseCase {
|
|
50
51
|
constructor(
|
|
@@ -84,6 +85,7 @@ export class RevertOrphanedPreparationUseCase {
|
|
|
84
85
|
labelsNotRequiringPullRequest?: string[] | null;
|
|
85
86
|
allowedIssueAuthors?: string[] | null;
|
|
86
87
|
ownerApprovalTimeoutCycles?: number | null;
|
|
88
|
+
developerAgentName?: string | null;
|
|
87
89
|
}): Promise<void> => {
|
|
88
90
|
const projectId = await this.projectRepository.findProjectIdByUrl(
|
|
89
91
|
params.projectUrl,
|
|
@@ -129,10 +131,11 @@ export class RevertOrphanedPreparationUseCase {
|
|
|
129
131
|
if (!isOrphaned) {
|
|
130
132
|
continue;
|
|
131
133
|
}
|
|
132
|
-
const { outcome, comments } = await this.evaluateOutcome(
|
|
134
|
+
const { outcome, comments, ciFailingPrUrl } = await this.evaluateOutcome(
|
|
133
135
|
issue,
|
|
134
136
|
resolveLabelsNotRequiringPullRequest(params),
|
|
135
137
|
params.allowedIssueAuthors,
|
|
138
|
+
params.developerAgentName,
|
|
136
139
|
);
|
|
137
140
|
const isStillInPreparation = await this.isStillInPreparation(
|
|
138
141
|
issue,
|
|
@@ -242,6 +245,32 @@ export class RevertOrphanedPreparationUseCase {
|
|
|
242
245
|
}
|
|
243
246
|
continue;
|
|
244
247
|
}
|
|
248
|
+
if (outcome === 'reassignToDeveloper' && ciFailingPrUrl) {
|
|
249
|
+
const effectiveDeveloperAgentName =
|
|
250
|
+
params.developerAgentName ?? 'developer';
|
|
251
|
+
const agentOptionId = await ensureAgentOptionAndGetId(
|
|
252
|
+
this.projectRepository,
|
|
253
|
+
project,
|
|
254
|
+
effectiveDeveloperAgentName,
|
|
255
|
+
);
|
|
256
|
+
if (agentOptionId !== null) {
|
|
257
|
+
await this.issueRepository.setIssueAgentField(
|
|
258
|
+
issue.url,
|
|
259
|
+
project,
|
|
260
|
+
agentOptionId,
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
await this.issueRepository.updateStatus(
|
|
264
|
+
project,
|
|
265
|
+
issue,
|
|
266
|
+
awaitingWorkspaceStatusOption.id,
|
|
267
|
+
);
|
|
268
|
+
await this.issueCommentRepository.createComment(
|
|
269
|
+
issue,
|
|
270
|
+
`Auto Status Check: REJECTED\n- ANY_CI_JOB_FAILED_OR_IN_PROGRESS: ${ciFailingPrUrl}`,
|
|
271
|
+
);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
245
274
|
if (outcome === 'returnToLabelSelectedAgent') {
|
|
246
275
|
await this.issueRepository.updateStatus(
|
|
247
276
|
project,
|
|
@@ -340,9 +369,11 @@ export class RevertOrphanedPreparationUseCase {
|
|
|
340
369
|
issue: Issue,
|
|
341
370
|
labelsNotRequiringPullRequest: string[],
|
|
342
371
|
allowedIssueAuthors: string[] | null | undefined,
|
|
372
|
+
developerAgentName?: string | null,
|
|
343
373
|
): Promise<{
|
|
344
374
|
outcome: OrphanedPreparationOutcome;
|
|
345
375
|
comments: Comment[];
|
|
376
|
+
ciFailingPrUrl?: string;
|
|
346
377
|
}> => {
|
|
347
378
|
if (issue.isClosed) {
|
|
348
379
|
return { outcome: 'advanceToQualityCheck', comments: [] };
|
|
@@ -404,8 +435,9 @@ export class RevertOrphanedPreparationUseCase {
|
|
|
404
435
|
const categoryLabels = issue.labels.filter((label) =>
|
|
405
436
|
label.startsWith('category:'),
|
|
406
437
|
);
|
|
438
|
+
const effectiveDeveloperName = developerAgentName ?? 'developer';
|
|
407
439
|
const isNonDeveloperAgent =
|
|
408
|
-
issue.agent != null && issue.agent !==
|
|
440
|
+
issue.agent != null && issue.agent !== effectiveDeveloperName;
|
|
409
441
|
const hasLabelNotRequiringPullRequest = issue.labels.some((label) =>
|
|
410
442
|
labelsNotRequiringPullRequest.includes(label),
|
|
411
443
|
);
|
|
@@ -420,6 +452,15 @@ export class RevertOrphanedPreparationUseCase {
|
|
|
420
452
|
if (prsToCheck.some((pr) => pr.isConflicted)) {
|
|
421
453
|
return { outcome: 'reject', comments };
|
|
422
454
|
}
|
|
455
|
+
if (isNonDeveloperAgent && issue.agent !== 'pr-reviewer') {
|
|
456
|
+
if (prsToCheck.length === 1 && !prsToCheck[0].isPassedAllCiJob) {
|
|
457
|
+
return {
|
|
458
|
+
outcome: 'reassignToDeveloper',
|
|
459
|
+
comments,
|
|
460
|
+
ciFailingPrUrl: prsToCheck[0].url,
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
}
|
|
423
464
|
return { outcome: 'advanceToQualityCheck', comments };
|
|
424
465
|
}
|
|
425
466
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fleetConfig.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/fleetConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,sCAAsC,EACvC,MAAM,6DAA6D,CAAC;AAErE,eAAO,MAAM,2CAA2C,sBAAsB,CAAC;AAE/E,eAAO,MAAM,8CAA8C,mCACzB,CAAC;AAEnC,eAAO,MAAM,0BAA0B,GACrC,UAAU,MAAM,GAAG,IAAI,KACtB,MAAM,GAAG,IAUX,CAAC;AAwDF,eAAO,MAAM,0CAA0C,GACrD,qBAAqB,MAAM,GAAG,IAAI,KACjC,
|
|
1
|
+
{"version":3,"file":"fleetConfig.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/fleetConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,sCAAsC,EACvC,MAAM,6DAA6D,CAAC;AAErE,eAAO,MAAM,2CAA2C,sBAAsB,CAAC;AAE/E,eAAO,MAAM,8CAA8C,mCACzB,CAAC;AAEnC,eAAO,MAAM,0BAA0B,GACrC,UAAU,MAAM,GAAG,IAAI,KACtB,MAAM,GAAG,IAUX,CAAC;AAwDF,eAAO,MAAM,0CAA0C,GACrD,qBAAqB,MAAM,GAAG,IAAI,KACjC,sCA0CF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OauthTokenSelectHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/OauthTokenSelectHandler.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"OauthTokenSelectHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/OauthTokenSelectHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,uBAAuB,EACvB,KAAK,eAAe,EACrB,MAAM,kDAAkD,CAAC;AAQ1D,MAAM,MAAM,4BAA4B,GAAG;IACzC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAKF,eAAO,MAAM,wBAAwB,GACnC,cAAc,MAAM,GAAG,IAAI,KAC1B,MAAM,GAAG,IASX,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,mBAAmB,MAAM,GAAG,IAAI,KAC/B,MASF,CAAC;AAEF,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,GAAE,uBAAuD,EAChE,MAAM,GAAE,eAA6B;IAGxD,MAAM,GACJ,OAAO,4BAA4B,KAClC,6BAA6B,CAiE9B;IAEF,OAAO,CAAC,iBAAiB,CAuBvB;CACH"}
|
|
@@ -3,6 +3,8 @@ import { type OauthTokenCandidate, OauthTokenSelectUseCase } from './OauthTokenS
|
|
|
3
3
|
export type LiveSessionOauthTokenSelectionSettings = {
|
|
4
4
|
maxConcurrentSessionCount: number;
|
|
5
5
|
fullSpeedFiveHourFreeRatio: number;
|
|
6
|
+
minFiveHourFreeRatio: number;
|
|
7
|
+
minSevenDayFreeRatio: number;
|
|
6
8
|
};
|
|
7
9
|
export declare const DEFAULT_LIVE_SESSION_OAUTH_TOKEN_SELECTION_SETTINGS: LiveSessionOauthTokenSelectionSettings;
|
|
8
10
|
export declare const liveSessionConcurrentLimitOf: (fiveHourFreeRatio: number, selectionWeight: number, settings: LiveSessionOauthTokenSelectionSettings) => number;
|
|
@@ -26,6 +28,7 @@ export declare class LiveSessionOauthTokenSelectUseCase {
|
|
|
26
28
|
private readonly rateLimitSelectUseCase;
|
|
27
29
|
constructor(rateLimitSelectUseCase?: OauthTokenSelectUseCase);
|
|
28
30
|
run: (candidates: OauthTokenCandidate[], liveSessions: ClaudeLiveSession[], nowEpochSeconds: number, settings: LiveSessionOauthTokenSelectionSettings) => LiveSessionOauthTokenSelectResult;
|
|
31
|
+
private liveSessionExclusionReason;
|
|
29
32
|
private preferred;
|
|
30
33
|
private liveSessionCountByToken;
|
|
31
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveSessionOauthTokenSelectUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/LiveSessionOauthTokenSelectUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AAC1F,OAAO,EACL,KAAK,mBAAmB,EACxB,uBAAuB,EAExB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,sCAAsC,GAAG;IACnD,yBAAyB,EAAE,MAAM,CAAC;IAClC,0BAA0B,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"LiveSessionOauthTokenSelectUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/LiveSessionOauthTokenSelectUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AAC1F,OAAO,EACL,KAAK,mBAAmB,EACxB,uBAAuB,EAExB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,sCAAsC,GAAG;IACnD,yBAAyB,EAAE,MAAM,CAAC;IAClC,0BAA0B,EAAE,MAAM,CAAC;IACnC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,mDAAmD,EAAE,sCAM/D,CAAC;AAEJ,eAAO,MAAM,4BAA4B,GACvC,mBAAmB,MAAM,EACzB,iBAAiB,MAAM,EACvB,UAAU,sCAAsC,KAC/C,MAaF,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAAG;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,sBAAsB,EAAE,OAAO,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,qCAAqC,EAAE,CAAC;CAClD,CAAC;AAEF,qBAAa,kCAAkC;IAE3C,OAAO,CAAC,QAAQ,CAAC,sBAAsB;gBAAtB,sBAAsB,GAAE,uBAAuD;IAGlG,GAAG,GACD,YAAY,mBAAmB,EAAE,EACjC,cAAc,iBAAiB,EAAE,EACjC,iBAAiB,MAAM,EACvB,UAAU,sCAAsC,KAC/C,iCAAiC,CAsDlC;IAEF,OAAO,CAAC,0BAA0B,CAgBhC;IAEF,OAAO,CAAC,SAAS,CAgBf;IAEF,OAAO,CAAC,uBAAuB,CAe7B;CACH"}
|
|
@@ -42,6 +42,7 @@ export declare class NotifyFinishedIssuePreparationUseCase {
|
|
|
42
42
|
private collectRejections;
|
|
43
43
|
private reportBodyHasNextStep;
|
|
44
44
|
private setDependedIssueUrlForAllOpenPRs;
|
|
45
|
+
private resolveLinkedPrWithCiFailure;
|
|
45
46
|
private resolveOpenPrsForPrItem;
|
|
46
47
|
private sendWorkflowBlockerNotification;
|
|
47
48
|
private resolveConsoleTargetTab;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotifyFinishedIssuePreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AA4CnF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,QAAQ,EAAE,MAAM;CAI7B;AACD,qBAAa,uBAAwB,SAAQ,KAAK;gBAE9C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,cAAc,EAAE,MAAM,GAAG,IAAI;CAOhC;AAID,qBAAa,qCAAqC;IAK9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAIlC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAmBhC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IAIvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAIlC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IAnCzC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA0B;IAClE,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAAkC;gBAG/D,iBAAiB,EAAE,IAAI,CACtC,iBAAiB,EACjB,UAAU,GAAG,iBAAiB,GAAG,aAAa,CAC/C,EACgB,eAAe,EAAE,IAAI,CACpC,eAAe,EACb,KAAK,GACL,QAAQ,GACR,cAAc,GACd,cAAc,GACd,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,oBAAoB,GACpB,gCAAgC,GAChC,oBAAoB,GACpB,iCAAiC,GACjC,qBAAqB,GACrB,oBAAoB,GACpB,aAAa,GACb,gBAAgB,GAChB,sBAAsB,CACzB,EACgB,sBAAsB,EAAE,IAAI,CAC3C,sBAAsB,EACtB,sBAAsB,GAAG,eAAe,CACzC,EACgB,iBAAiB,EAAE,IAAI,CACtC,iBAAiB,EACjB,gBAAgB,CACjB,EACgB,qBAAqB,CAAC,GAAE,qBAAqB,GAAG,IAAI,aAAA;IAQvE,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,iCAAiC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjD,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACvC,6BAA6B,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAChD,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;QACxD,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,gBAAgB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QAClC,0BAA0B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5C,KAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"NotifyFinishedIssuePreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,14 +29,20 @@ export type OauthTokenSelectResult = {
|
|
|
29
29
|
selected: OauthTokenCandidate | null;
|
|
30
30
|
metrics: OauthTokenCandidateMetrics[];
|
|
31
31
|
};
|
|
32
|
+
export type OauthTokenSelectionThresholds = {
|
|
33
|
+
fiveHourMinFreeRatio: number;
|
|
34
|
+
sevenDayMinFreeRatio: number;
|
|
35
|
+
};
|
|
32
36
|
export declare const FIVE_HOUR_MIN_FREE_RATIO = 0.25;
|
|
33
37
|
export declare const SEVEN_DAY_MIN_FREE_RATIO = 0.03;
|
|
38
|
+
export declare const DEFAULT_OAUTH_TOKEN_SELECTION_THRESHOLDS: OauthTokenSelectionThresholds;
|
|
39
|
+
export declare const CL_SCRIPT_OAUTH_TOKEN_SELECTION_THRESHOLDS: OauthTokenSelectionThresholds;
|
|
34
40
|
export declare const SEVEN_DAY_WINDOW_HOURS = 168;
|
|
35
41
|
export declare const MIN_HOURS_TO_RESET = 1;
|
|
36
42
|
export declare const sevenDayUrgencyFactor: (sevenDayFreeRatio: number, sevenDayEndEpoch: number, nowEpochSeconds: number) => number;
|
|
37
43
|
export declare const selectWeightedCandidate: <Entry>(eligible: Entry[], weightOf: (entry: Entry) => number, deterministicBest: Entry, random: SelectionRandom) => Entry;
|
|
38
44
|
export declare class OauthTokenSelectUseCase {
|
|
39
|
-
run: (candidates: OauthTokenCandidate[], nowEpochSeconds: number, random?: SelectionRandom) => OauthTokenSelectResult;
|
|
45
|
+
run: (candidates: OauthTokenCandidate[], nowEpochSeconds: number, random?: SelectionRandom, thresholds?: OauthTokenSelectionThresholds) => OauthTokenSelectResult;
|
|
40
46
|
private evaluate;
|
|
41
47
|
private exclusionReason;
|
|
42
48
|
private fiveHourFreeRatio;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OauthTokenSelectUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/OauthTokenSelectUseCase.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG;IACrC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC1C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC;AAE3C,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,iBAAiB,GAAI,WAAW,mBAAmB,KAAG,MAGlE,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,0BAA0B,EAAE,CAAC;CACvC,CAAC;AAKF,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAGpC,eAAO,MAAM,qBAAqB,GAChC,mBAAmB,MAAM,EACzB,kBAAkB,MAAM,EACxB,iBAAiB,MAAM,KACtB,MAMF,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,KAAK,EAC3C,UAAU,KAAK,EAAE,EACjB,UAAU,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,EAClC,mBAAmB,KAAK,EACxB,QAAQ,eAAe,KACtB,KAkBF,CAAC;AAEF,qBAAa,uBAAuB;IAClC,GAAG,GACD,YAAY,mBAAmB,EAAE,EACjC,iBAAiB,MAAM,EACvB,SAAQ,eAA6B,
|
|
1
|
+
{"version":3,"file":"OauthTokenSelectUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/OauthTokenSelectUseCase.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG;IACrC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC1C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC;AAE3C,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,iBAAiB,GAAI,WAAW,mBAAmB,KAAG,MAGlE,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,0BAA0B,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAKF,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C,eAAO,MAAM,wCAAwC,EAAE,6BAIpD,CAAC;AAEJ,eAAO,MAAM,0CAA0C,EAAE,6BAItD,CAAC;AAEJ,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAGpC,eAAO,MAAM,qBAAqB,GAChC,mBAAmB,MAAM,EACzB,kBAAkB,MAAM,EACxB,iBAAiB,MAAM,KACtB,MAMF,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,KAAK,EAC3C,UAAU,KAAK,EAAE,EACjB,UAAU,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,EAClC,mBAAmB,KAAK,EACxB,QAAQ,eAAe,KACtB,KAkBF,CAAC;AAEF,qBAAa,uBAAuB;IAClC,GAAG,GACD,YAAY,mBAAmB,EAAE,EACjC,iBAAiB,MAAM,EACvB,SAAQ,eAA6B,EACrC,aAAY,6BAAwE,KACnF,sBAAsB,CA4CvB;IAEF,OAAO,CAAC,QAAQ,CAmCd;IAEF,OAAO,CAAC,eAAe,CAwBrB;IAEF,OAAO,CAAC,iBAAiB,CAWvB;IAEF,OAAO,CAAC,iBAAiB,CAWvB;IAEF,OAAO,CAAC,gBAAgB,CActB;IAEF,OAAO,CAAC,aAAa,CAGwC;IAE7D,OAAO,CAAC,wBAAwB,CAG9B;IAEF,OAAO,CAAC,SAAS,CAAsD;CACxE"}
|
|
@@ -20,6 +20,7 @@ export declare class RevertOrphanedPreparationUseCase {
|
|
|
20
20
|
labelsNotRequiringPullRequest?: string[] | null;
|
|
21
21
|
allowedIssueAuthors?: string[] | null;
|
|
22
22
|
ownerApprovalTimeoutCycles?: number | null;
|
|
23
|
+
developerAgentName?: string | null;
|
|
23
24
|
}) => Promise<void>;
|
|
24
25
|
private isStillInPreparation;
|
|
25
26
|
private evaluateOutcome;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RevertOrphanedPreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/RevertOrphanedPreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAEhB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"RevertOrphanedPreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/RevertOrphanedPreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAEhB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AA2C7E,qBAAa,gCAAgC;IAEzC,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAC9B,iBAAiB,EACf,oBAAoB,GACpB,YAAY,GACZ,aAAa,GACb,UAAU,GACV,iBAAiB,CACpB;IACD,QAAQ,CAAC,eAAe,EAAE,IAAI,CAC5B,eAAe,EACb,cAAc,GACd,cAAc,GACd,oBAAoB,GACpB,oBAAoB,GACpB,KAAK,GACL,oBAAoB,CACvB;IACD,QAAQ,CAAC,sBAAsB,EAAE,IAAI,CACnC,sBAAsB,EACtB,sBAAsB,GAAG,eAAe,CACzC;IACD,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB;gBArBtC,iBAAiB,EAAE,IAAI,CAC9B,iBAAiB,EACf,oBAAoB,GACpB,YAAY,GACZ,aAAa,GACb,UAAU,GACV,iBAAiB,CACpB,EACQ,eAAe,EAAE,IAAI,CAC5B,eAAe,EACb,cAAc,GACd,cAAc,GACd,oBAAoB,GACpB,oBAAoB,GACpB,KAAK,GACL,oBAAoB,CACvB,EACQ,sBAAsB,EAAE,IAAI,CACnC,sBAAsB,EACtB,sBAAsB,GAAG,eAAe,CACzC,EACQ,kBAAkB,EAAE,kBAAkB;IAGjD,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,8BAA8B,EAAE,MAAM,CAAC;QACvC,sBAAsB,EAAE,MAAM,CAAC;QAC/B,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;QACpC,0BAA0B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3C,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACvC,6BAA6B,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAChD,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,0BAA0B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3C,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACpC,KAAG,OAAO,CAAC,IAAI,CAAC,CA8Pf;IAEF,OAAO,CAAC,oBAAoB,CAqB1B;IAEF,OAAO,CAAC,eAAe,CAoHrB;IAEF,OAAO,CAAC,uBAAuB,CAQ7B;IAEF,OAAO,CAAC,qBAAqB,CAyB3B;IAEF,OAAO,CAAC,eAAe,CA6BrB;IAEF,OAAO,CAAC,YAAY,CA+BlB;CACH"}
|