@shipfox/api-workflows 13.1.0 → 15.0.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 (94) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +61 -0
  3. package/README.md +12 -5
  4. package/dist/core/checkout.d.ts +4 -2
  5. package/dist/core/checkout.d.ts.map +1 -1
  6. package/dist/core/checkout.js +7 -2
  7. package/dist/core/checkout.js.map +1 -1
  8. package/dist/core/entities/job.d.ts +1 -1
  9. package/dist/core/entities/job.d.ts.map +1 -1
  10. package/dist/core/entities/job.js.map +1 -1
  11. package/dist/core/entities/workflow-run.d.ts +25 -6
  12. package/dist/core/entities/workflow-run.d.ts.map +1 -1
  13. package/dist/core/entities/workflow-run.js.map +1 -1
  14. package/dist/core/index.d.ts +2 -2
  15. package/dist/core/index.d.ts.map +1 -1
  16. package/dist/core/index.js +1 -1
  17. package/dist/core/index.js.map +1 -1
  18. package/dist/core/run-workflow.d.ts +26 -1
  19. package/dist/core/run-workflow.d.ts.map +1 -1
  20. package/dist/core/run-workflow.js +27 -1
  21. package/dist/core/run-workflow.js.map +1 -1
  22. package/dist/db/db.d.ts +72 -0
  23. package/dist/db/db.d.ts.map +1 -1
  24. package/dist/db/schema/workflow-runs.d.ts +45 -1
  25. package/dist/db/schema/workflow-runs.d.ts.map +1 -1
  26. package/dist/db/schema/workflow-runs.js +42 -1
  27. package/dist/db/schema/workflow-runs.js.map +1 -1
  28. package/dist/db/workflow-runs/jobs.d.ts +3 -1
  29. package/dist/db/workflow-runs/jobs.d.ts.map +1 -1
  30. package/dist/db/workflow-runs/jobs.js +12 -3
  31. package/dist/db/workflow-runs/jobs.js.map +1 -1
  32. package/dist/db/workflow-runs/queries.d.ts +3 -2
  33. package/dist/db/workflow-runs/queries.d.ts.map +1 -1
  34. package/dist/db/workflow-runs/queries.js +3 -0
  35. package/dist/db/workflow-runs/queries.js.map +1 -1
  36. package/dist/db/workflow-runs/run-create.d.ts +4 -1
  37. package/dist/db/workflow-runs/run-create.d.ts.map +1 -1
  38. package/dist/db/workflow-runs/run-create.js +14 -1
  39. package/dist/db/workflow-runs/run-create.js.map +1 -1
  40. package/dist/presentation/dto/workflow-run.d.ts.map +1 -1
  41. package/dist/presentation/dto/workflow-run.js +14 -0
  42. package/dist/presentation/dto/workflow-run.js.map +1 -1
  43. package/dist/presentation/inter-module.d.ts +1 -0
  44. package/dist/presentation/inter-module.d.ts.map +1 -1
  45. package/dist/presentation/inter-module.js +41 -4
  46. package/dist/presentation/inter-module.js.map +1 -1
  47. package/dist/presentation/routes/checkout-token.d.ts.map +1 -1
  48. package/dist/presentation/routes/checkout-token.js +2 -1
  49. package/dist/presentation/routes/checkout-token.js.map +1 -1
  50. package/dist/presentation/routes/get-run-aggregates.d.ts.map +1 -1
  51. package/dist/presentation/routes/get-run-aggregates.js +2 -1
  52. package/dist/presentation/routes/get-run-aggregates.js.map +1 -1
  53. package/dist/presentation/routes/leased-step.d.ts +3 -1
  54. package/dist/presentation/routes/leased-step.d.ts.map +1 -1
  55. package/dist/presentation/routes/leased-step.js +2 -1
  56. package/dist/presentation/routes/leased-step.js.map +1 -1
  57. package/dist/presentation/routes/list-runs.d.ts.map +1 -1
  58. package/dist/presentation/routes/list-runs.js +2 -1
  59. package/dist/presentation/routes/list-runs.js.map +1 -1
  60. package/dist/presentation/routes/project-access.d.ts +1 -0
  61. package/dist/presentation/routes/project-access.d.ts.map +1 -1
  62. package/dist/tsconfig.test.tsbuildinfo +1 -1
  63. package/drizzle/0004_dev_run_origin.sql +12 -0
  64. package/drizzle/meta/0004_snapshot.json +1773 -0
  65. package/drizzle/meta/_journal.json +7 -0
  66. package/package.json +16 -16
  67. package/src/core/checkout.test.ts +198 -1
  68. package/src/core/checkout.ts +18 -5
  69. package/src/core/entities/job.ts +1 -1
  70. package/src/core/entities/workflow-run.ts +26 -6
  71. package/src/core/index.ts +2 -2
  72. package/src/core/job-transition/decide-job-activation.test.ts +2 -0
  73. package/src/core/run-workflow.test.ts +151 -3
  74. package/src/core/run-workflow.ts +59 -3
  75. package/src/core/workflow-run-creation.test.ts +2 -0
  76. package/src/db/job-listeners.test.ts +17 -0
  77. package/src/db/schema/workflow-runs.ts +58 -0
  78. package/src/db/workflow-runs/jobs.ts +17 -3
  79. package/src/db/workflow-runs/queries.ts +6 -1
  80. package/src/db/workflow-runs/run-create.test.ts +87 -0
  81. package/src/db/workflow-runs/run-create.ts +23 -1
  82. package/src/presentation/dto/workflow-run.ts +23 -1
  83. package/src/presentation/inter-module.test.ts +131 -1
  84. package/src/presentation/inter-module.ts +48 -3
  85. package/src/presentation/routes/checkout-token.test.ts +45 -0
  86. package/src/presentation/routes/checkout-token.ts +2 -1
  87. package/src/presentation/routes/get-run-aggregates.test.ts +56 -0
  88. package/src/presentation/routes/get-run-aggregates.ts +2 -0
  89. package/src/presentation/routes/get-step-secrets.test.ts +1 -0
  90. package/src/presentation/routes/leased-step.ts +7 -1
  91. package/src/presentation/routes/list-runs.test.ts +152 -0
  92. package/src/presentation/routes/list-runs.ts +2 -0
  93. package/test/factories/workflow-run.ts +2 -0
  94. package/tsconfig.build.tsbuildinfo +1 -1
@@ -29,6 +29,13 @@
29
29
  "when": 1786266649202,
30
30
  "tag": "0003_output_invalid_reason",
31
31
  "breakpoints": true
32
+ },
33
+ {
34
+ "idx": 4,
35
+ "version": "7",
36
+ "when": 1787477580166,
37
+ "tag": "0004_dev_run_origin",
38
+ "breakpoints": true
32
39
  }
33
40
  ]
34
41
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-workflows",
3
3
  "license": "MIT",
4
- "version": "13.1.0",
4
+ "version": "15.0.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
@@ -23,30 +23,30 @@
23
23
  "drizzle-orm": "^0.45.2",
24
24
  "js-yaml": "^4.1.0",
25
25
  "zod": "^4.4.3",
26
- "@shipfox/api-auth-context": "12.2.0",
27
- "@shipfox/api-auth-dto": "12.0.0",
28
- "@shipfox/api-agent-dto": "13.1.0",
26
+ "@shipfox/api-auth-context": "15.0.0",
27
+ "@shipfox/api-auth-dto": "15.0.0",
28
+ "@shipfox/api-agent-dto": "15.0.0",
29
29
  "@shipfox/annotations-dto": "12.3.0",
30
- "@shipfox/api-definitions-dto": "12.3.0",
31
- "@shipfox/api-projects-dto": "12.2.0",
32
- "@shipfox/api-integration-core-dto": "12.2.0",
33
- "@shipfox/api-runners-dto": "13.0.0",
30
+ "@shipfox/api-definitions-dto": "15.0.0",
31
+ "@shipfox/api-projects-dto": "15.0.0",
32
+ "@shipfox/api-integration-core-dto": "15.0.0",
33
+ "@shipfox/api-runners-dto": "14.0.0",
34
34
  "@shipfox/api-secrets-dto": "12.0.0",
35
- "@shipfox/api-workflows-dto": "13.1.0",
36
- "@shipfox/api-workspaces-dto": "12.0.0",
35
+ "@shipfox/api-workflows-dto": "15.0.0",
36
+ "@shipfox/api-workspaces-dto": "15.0.0",
37
37
  "@shipfox/config": "1.2.4",
38
38
  "@shipfox/inter-module": "0.2.3",
39
- "@shipfox/expression": "2.2.0",
39
+ "@shipfox/expression": "2.3.0",
40
40
  "@shipfox/node-drizzle": "0.3.5",
41
41
  "@shipfox/node-error-monitoring": "0.3.0",
42
- "@shipfox/node-fastify": "0.4.2",
43
- "@shipfox/node-module": "1.0.6",
44
- "@shipfox/node-opentelemetry": "0.6.4",
42
+ "@shipfox/node-fastify": "0.4.3",
43
+ "@shipfox/node-module": "1.0.7",
44
+ "@shipfox/node-opentelemetry": "0.6.5",
45
45
  "@shipfox/node-outbox": "0.2.6",
46
46
  "@shipfox/node-postgres": "0.5.0",
47
- "@shipfox/node-temporal": "0.4.5",
47
+ "@shipfox/node-temporal": "0.4.6",
48
48
  "@shipfox/runner-labels": "0.2.0",
49
- "@shipfox/workflow-document": "3.0.1"
49
+ "@shipfox/workflow-document": "3.2.0"
50
50
  },
51
51
  "imports": {
52
52
  "#*": "./dist/*"
@@ -3,9 +3,24 @@ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module'
3
3
  import {projectFactory} from '#test/factories/project.js';
4
4
  import {createStepCheckoutSpec} from './checkout.js';
5
5
  import type {Step} from './entities/step.js';
6
- import type {WorkflowRunTriggerReference} from './entities/workflow-run.js';
6
+ import type {WorkflowRunDevSource, WorkflowRunTriggerReference} from './entities/workflow-run.js';
7
7
  import {CheckoutConfigInvalidError, CheckoutIntentUnresolvedError} from './errors.js';
8
8
 
9
+ const syncedRun = {origin: 'synced', devSource: null} as const;
10
+
11
+ function devRun(commit: string): {origin: 'dev'; devSource: WorkflowRunDevSource} {
12
+ return {
13
+ origin: 'dev',
14
+ devSource: {
15
+ ref: 'fix-triage-prompt',
16
+ commit,
17
+ configPath: '.shipfox/workflows/triage-sentry.yml',
18
+ initiatedByUserId: crypto.randomUUID(),
19
+ replayOfEventId: null,
20
+ },
21
+ };
22
+ }
23
+
9
24
  const getProjectById = vi.fn();
10
25
  const resolveCheckoutTarget = vi.fn();
11
26
  const projects = {
@@ -46,6 +61,7 @@ describe('createStepCheckoutSpec', () => {
46
61
  });
47
62
 
48
63
  const result = await createStepCheckoutSpec({
64
+ run: syncedRun,
49
65
  step,
50
66
  workspaceId: project.workspaceId,
51
67
  projectId: project.id,
@@ -96,6 +112,7 @@ describe('createStepCheckoutSpec', () => {
96
112
  });
97
113
 
98
114
  const result = await createStepCheckoutSpec({
115
+ run: syncedRun,
99
116
  step,
100
117
  workspaceId: project.workspaceId,
101
118
  projectId: project.id,
@@ -134,6 +151,7 @@ describe('createStepCheckoutSpec', () => {
134
151
  });
135
152
 
136
153
  await createStepCheckoutSpec({
154
+ run: syncedRun,
137
155
  step,
138
156
  workspaceId: project.workspaceId,
139
157
  projectId: project.id,
@@ -167,6 +185,7 @@ describe('createStepCheckoutSpec', () => {
167
185
  });
168
186
 
169
187
  await createStepCheckoutSpec({
188
+ run: syncedRun,
170
189
  step,
171
190
  workspaceId: project.workspaceId,
172
191
  projectId: project.id,
@@ -200,6 +219,7 @@ describe('createStepCheckoutSpec', () => {
200
219
  });
201
220
 
202
221
  await createStepCheckoutSpec({
222
+ run: syncedRun,
203
223
  step,
204
224
  workspaceId: project.workspaceId,
205
225
  projectId: project.id,
@@ -216,6 +236,41 @@ describe('createStepCheckoutSpec', () => {
216
236
  });
217
237
  });
218
238
 
239
+ it('falls through to the dev commit when a same-project trigger has no commit', async () => {
240
+ const project = projectFactory.build();
241
+ const devCommit = 'b'.repeat(40);
242
+ const triggerReference = {...triggerReferenceFor(project.id), commit: null};
243
+ const step = checkoutStep({permissions: {contents: 'read'}});
244
+ getProjectById.mockResolvedValue({project});
245
+ resolveCheckoutTarget.mockResolvedValue({
246
+ projectId: project.id,
247
+ connectionId: project.sourceConnectionId,
248
+ externalRepositoryId: project.sourceExternalRepositoryId,
249
+ });
250
+ createCheckoutSpec.mockResolvedValue({
251
+ repositoryUrl: 'https://github.com/acme/repo.git',
252
+ ref: devCommit,
253
+ });
254
+
255
+ await createStepCheckoutSpec({
256
+ run: devRun(devCommit),
257
+ step,
258
+ workspaceId: project.workspaceId,
259
+ projectId: project.id,
260
+ triggerReference,
261
+ integrations: integrations as IntegrationsModuleClient,
262
+ projects: projects as ProjectsModuleClient,
263
+ });
264
+
265
+ expect(createCheckoutSpec).toHaveBeenCalledWith({
266
+ workspaceId: project.workspaceId,
267
+ connectionId: project.sourceConnectionId,
268
+ externalRepositoryId: project.sourceExternalRepositoryId,
269
+ ref: devCommit,
270
+ permissions: {contents: 'read'},
271
+ });
272
+ });
273
+
219
274
  it('keeps the provider default ref for a cross-repository target', async () => {
220
275
  const project = projectFactory.build();
221
276
  const targetProjectId = crypto.randomUUID();
@@ -232,6 +287,142 @@ describe('createStepCheckoutSpec', () => {
232
287
  });
233
288
 
234
289
  await createStepCheckoutSpec({
290
+ run: syncedRun,
291
+ step,
292
+ workspaceId: project.workspaceId,
293
+ projectId: project.id,
294
+ triggerReference: triggerReferenceFor(project.id),
295
+ integrations: integrations as IntegrationsModuleClient,
296
+ projects: projects as ProjectsModuleClient,
297
+ });
298
+
299
+ expect(createCheckoutSpec).toHaveBeenCalledWith({
300
+ workspaceId: project.workspaceId,
301
+ connectionId: expect.any(String),
302
+ externalRepositoryId: 'github:412',
303
+ permissions: {contents: 'read'},
304
+ });
305
+ });
306
+
307
+ it('checks out the dev commit for a dev run without a trigger reference', async () => {
308
+ const project = projectFactory.build();
309
+ const devCommit = 'b'.repeat(40);
310
+ const step = checkoutStep({permissions: {contents: 'read'}});
311
+ getProjectById.mockResolvedValue({project});
312
+ resolveCheckoutTarget.mockResolvedValue({
313
+ projectId: project.id,
314
+ connectionId: project.sourceConnectionId,
315
+ externalRepositoryId: project.sourceExternalRepositoryId,
316
+ });
317
+ createCheckoutSpec.mockResolvedValue({
318
+ repositoryUrl: 'https://github.com/acme/repo.git',
319
+ ref: devCommit,
320
+ });
321
+
322
+ await createStepCheckoutSpec({
323
+ run: devRun(devCommit),
324
+ step,
325
+ workspaceId: project.workspaceId,
326
+ projectId: project.id,
327
+ integrations: integrations as IntegrationsModuleClient,
328
+ projects: projects as ProjectsModuleClient,
329
+ });
330
+
331
+ expect(createCheckoutSpec).toHaveBeenCalledWith({
332
+ workspaceId: project.workspaceId,
333
+ connectionId: project.sourceConnectionId,
334
+ externalRepositoryId: project.sourceExternalRepositoryId,
335
+ ref: devCommit,
336
+ permissions: {contents: 'read'},
337
+ });
338
+ });
339
+
340
+ it('prefers the event commit over the dev commit on a dev replay of a same-project push', async () => {
341
+ const project = projectFactory.build();
342
+ const eventCommit = 'c'.repeat(40);
343
+ const triggerReference = {...triggerReferenceFor(project.id), commit: eventCommit};
344
+ const step = checkoutStep({permissions: {contents: 'read'}});
345
+ getProjectById.mockResolvedValue({project});
346
+ resolveCheckoutTarget.mockResolvedValue({
347
+ projectId: project.id,
348
+ connectionId: project.sourceConnectionId,
349
+ externalRepositoryId: project.sourceExternalRepositoryId,
350
+ });
351
+ createCheckoutSpec.mockResolvedValue({
352
+ repositoryUrl: 'https://github.com/acme/repo.git',
353
+ ref: eventCommit,
354
+ });
355
+
356
+ await createStepCheckoutSpec({
357
+ run: devRun('b'.repeat(40)),
358
+ step,
359
+ workspaceId: project.workspaceId,
360
+ projectId: project.id,
361
+ triggerReference,
362
+ integrations: integrations as IntegrationsModuleClient,
363
+ projects: projects as ProjectsModuleClient,
364
+ });
365
+
366
+ expect(createCheckoutSpec).toHaveBeenCalledWith({
367
+ workspaceId: project.workspaceId,
368
+ connectionId: project.sourceConnectionId,
369
+ externalRepositoryId: project.sourceExternalRepositoryId,
370
+ ref: eventCommit,
371
+ permissions: {contents: 'read'},
372
+ });
373
+ });
374
+
375
+ it('preserves an explicit ref on a dev run', async () => {
376
+ const project = projectFactory.build();
377
+ const explicitRef = 'refs/heads/feature/checkout';
378
+ const step = checkoutStep({ref: explicitRef, permissions: {contents: 'read'}});
379
+ getProjectById.mockResolvedValue({project});
380
+ resolveCheckoutTarget.mockResolvedValue({
381
+ projectId: project.id,
382
+ connectionId: project.sourceConnectionId,
383
+ externalRepositoryId: project.sourceExternalRepositoryId,
384
+ });
385
+ createCheckoutSpec.mockResolvedValue({
386
+ repositoryUrl: 'https://github.com/acme/repo.git',
387
+ ref: explicitRef,
388
+ });
389
+
390
+ await createStepCheckoutSpec({
391
+ run: devRun('b'.repeat(40)),
392
+ step,
393
+ workspaceId: project.workspaceId,
394
+ projectId: project.id,
395
+ triggerReference: triggerReferenceFor(project.id),
396
+ integrations: integrations as IntegrationsModuleClient,
397
+ projects: projects as ProjectsModuleClient,
398
+ });
399
+
400
+ expect(createCheckoutSpec).toHaveBeenCalledWith({
401
+ workspaceId: project.workspaceId,
402
+ connectionId: project.sourceConnectionId,
403
+ externalRepositoryId: project.sourceExternalRepositoryId,
404
+ ref: explicitRef,
405
+ permissions: {contents: 'read'},
406
+ });
407
+ });
408
+
409
+ it('keeps the provider default ref for a cross-project target in a dev run', async () => {
410
+ const project = projectFactory.build();
411
+ const targetProjectId = crypto.randomUUID();
412
+ const step = checkoutStep({project: targetProjectId});
413
+ getProjectById.mockResolvedValue({project});
414
+ resolveCheckoutTarget.mockResolvedValue({
415
+ projectId: targetProjectId,
416
+ connectionId: crypto.randomUUID(),
417
+ externalRepositoryId: 'github:412',
418
+ });
419
+ createCheckoutSpec.mockResolvedValue({
420
+ repositoryUrl: 'https://github.com/acme/target.git',
421
+ ref: 'main',
422
+ });
423
+
424
+ await createStepCheckoutSpec({
425
+ run: devRun('b'.repeat(40)),
235
426
  step,
236
427
  workspaceId: project.workspaceId,
237
428
  projectId: project.id,
@@ -263,6 +454,7 @@ describe('createStepCheckoutSpec', () => {
263
454
  });
264
455
 
265
456
  await createStepCheckoutSpec({
457
+ run: syncedRun,
266
458
  step,
267
459
  workspaceId: project.workspaceId,
268
460
  projectId: project.id,
@@ -294,6 +486,7 @@ describe('createStepCheckoutSpec', () => {
294
486
  });
295
487
 
296
488
  await createStepCheckoutSpec({
489
+ run: syncedRun,
297
490
  step,
298
491
  workspaceId: project.workspaceId,
299
492
  projectId: project.id,
@@ -330,6 +523,7 @@ describe('createStepCheckoutSpec', () => {
330
523
  });
331
524
 
332
525
  await createStepCheckoutSpec({
526
+ run: syncedRun,
333
527
  step,
334
528
  workspaceId: project.workspaceId,
335
529
  projectId: project.id,
@@ -350,6 +544,7 @@ describe('createStepCheckoutSpec', () => {
350
544
  {connection: 'github'},
351
545
  ])('rejects invalid checkout target shape: %j', async (checkout) => {
352
546
  const act = createStepCheckoutSpec({
547
+ run: syncedRun,
353
548
  step: checkoutStep(checkout),
354
549
  workspaceId: crypto.randomUUID(),
355
550
  projectId: crypto.randomUUID(),
@@ -368,6 +563,7 @@ describe('createStepCheckoutSpec', () => {
368
563
  getProjectById.mockResolvedValue({project: null});
369
564
 
370
565
  const act = createStepCheckoutSpec({
566
+ run: syncedRun,
371
567
  step: checkoutStep({}),
372
568
  workspaceId: crypto.randomUUID(),
373
569
  projectId,
@@ -387,6 +583,7 @@ describe('createStepCheckoutSpec', () => {
387
583
  resolveConnection.mockResolvedValue(null);
388
584
 
389
585
  const act = createStepCheckoutSpec({
586
+ run: syncedRun,
390
587
  step,
391
588
  workspaceId: project.workspaceId,
392
589
  projectId: project.id,
@@ -3,7 +3,10 @@ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module'
3
3
  import {checkoutTargetValidationIssues} from '@shipfox/workflow-document';
4
4
  import {z} from 'zod';
5
5
  import type {Step} from '#core/entities/step.js';
6
- import type {WorkflowRunTriggerReference} from '#core/entities/workflow-run.js';
6
+ import type {
7
+ WorkflowRunOriginState,
8
+ WorkflowRunTriggerReference,
9
+ } from '#core/entities/workflow-run.js';
7
10
  import {CheckoutConfigInvalidError, CheckoutIntentUnresolvedError} from './errors.js';
8
11
 
9
12
  const checkoutConfigSchema = z
@@ -39,6 +42,7 @@ export async function createStepCheckoutSpec({
39
42
  workspaceId,
40
43
  projectId,
41
44
  triggerReference,
45
+ run,
42
46
  integrations,
43
47
  projects,
44
48
  }: {
@@ -46,6 +50,8 @@ export async function createStepCheckoutSpec({
46
50
  workspaceId: string;
47
51
  projectId: string;
48
52
  triggerReference?: WorkflowRunTriggerReference | null | undefined;
53
+ /** The run's origin state; a dev run checks out its dev commit by default. */
54
+ run: WorkflowRunOriginState;
49
55
  integrations: IntegrationsModuleClient;
50
56
  projects: ProjectsModuleClient;
51
57
  }): Promise<{
@@ -79,11 +85,18 @@ export async function createStepCheckoutSpec({
79
85
  },
80
86
  target,
81
87
  });
82
- const ref =
83
- checkout.ref ??
84
- (triggerReference?.project?.id === resolvedTarget.projectId
88
+ // Explicit step refs win, followed by same-project event commits (including
89
+ // replays), then the pinned dev commit for the run's own project. Other targets
90
+ // intentionally use the provider default branch.
91
+ const triggerCommitRef =
92
+ triggerReference?.project?.id === resolvedTarget.projectId
85
93
  ? (triggerReference.commit ?? undefined)
86
- : undefined);
94
+ : undefined;
95
+ const devCommitRef =
96
+ run.origin === 'dev' && resolvedTarget.projectId === projectId
97
+ ? run.devSource.commit
98
+ : undefined;
99
+ const ref = checkout.ref ?? triggerCommitRef ?? devCommitRef;
87
100
  const response = await integrations.createCheckoutSpec({
88
101
  workspaceId,
89
102
  connectionId: resolvedTarget.connectionId,
@@ -69,7 +69,7 @@ export interface Job {
69
69
 
70
70
  export interface JobListeningTrigger {
71
71
  readonly source: string;
72
- readonly event: string;
72
+ readonly event?: string;
73
73
  readonly inputs?: Readonly<Record<string, unknown>>;
74
74
  readonly filter?: string;
75
75
  }
@@ -5,6 +5,24 @@ import type {WorkflowRunAttempt} from './workflow-run-attempt.js';
5
5
 
6
6
  export type WorkflowRunStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled';
7
7
 
8
+ export type WorkflowRunOrigin = 'synced' | 'dev';
9
+
10
+ /**
11
+ * Why a dev run was created: the ref and pinned commit the definition came from, the
12
+ * file that ran, the user who started it, and the journaled event it replays when any.
13
+ */
14
+ export interface WorkflowRunDevSource {
15
+ ref: string;
16
+ commit: string;
17
+ configPath: string;
18
+ initiatedByUserId: string;
19
+ replayOfEventId: string | null;
20
+ }
21
+
22
+ export type WorkflowRunOriginState =
23
+ | {origin: 'synced'; devSource: null}
24
+ | {origin: 'dev'; devSource: WorkflowRunDevSource};
25
+
8
26
  export type TerminalWorkflowRunStatus = Extract<
9
27
  WorkflowRunStatus,
10
28
  'succeeded' | 'failed' | 'cancelled'
@@ -40,14 +58,16 @@ export type TriggerPayload =
40
58
  source: 'manual';
41
59
  provider?: 'manual' | undefined;
42
60
  event: 'fire';
43
- subscriptionId: string;
61
+ // A dev trigger has no subscription row, so the id is optional here.
62
+ subscriptionId?: string | undefined;
44
63
  userId: string;
45
64
  }
46
65
  | {
47
66
  source: 'cron';
48
67
  provider?: 'cron' | undefined;
49
68
  event: 'tick';
50
- scheduleId: string;
69
+ // A dev trigger has no schedule row, so the id is optional here.
70
+ scheduleId?: string | undefined;
51
71
  }
52
72
  // Integration sources (github, gitlab, sentry, …) flow through opaquely: the
53
73
  // run records what fired it and carries the raw event payload, without the
@@ -60,7 +80,7 @@ export type TriggerPayload =
60
80
  data: unknown;
61
81
  };
62
82
 
63
- export interface WorkflowRun {
83
+ export type WorkflowRun = WorkflowRunOriginState & {
64
84
  id: string;
65
85
  workspaceId: string;
66
86
  projectId: string;
@@ -89,7 +109,7 @@ export interface WorkflowRun {
89
109
  updatedAt: Date;
90
110
  startedAt: Date | null;
91
111
  finishedAt: Date | null;
92
- }
112
+ };
93
113
 
94
114
  export interface StepDetail extends Step {
95
115
  attempts: StepAttempt[];
@@ -103,11 +123,11 @@ export interface WorkflowJobDetail extends Job {
103
123
  jobExecutions: JobExecutionDetail[];
104
124
  }
105
125
 
106
- export interface WorkflowRunDetail extends WorkflowRun {
126
+ export type WorkflowRunDetail = WorkflowRun & {
107
127
  runAttempt: WorkflowRunAttempt;
108
128
  latestAttempt: number;
109
129
  jobs: WorkflowJobDetail[];
110
130
  /** Whether any job execution of this attempt reached its runner, decided here so the detail
111
131
  * and the list cannot answer it differently. */
112
132
  hasStartedJobExecution: boolean;
113
- }
133
+ };
package/src/core/index.ts CHANGED
@@ -35,8 +35,8 @@ export {
35
35
  deriveJobSuccess,
36
36
  type JobActivationDecision,
37
37
  } from './job-transition/index.js';
38
- export type {RunWorkflowParams} from './run-workflow.js';
39
- export {runWorkflow} from './run-workflow.js';
38
+ export type {RunDevWorkflowParams, RunWorkflowParams} from './run-workflow.js';
39
+ export {runDevWorkflow, runWorkflow} from './run-workflow.js';
40
40
  export {
41
41
  type MaterializedWorkflowJob,
42
42
  type MaterializedWorkflowStep,
@@ -121,6 +121,8 @@ function workflowRun(): WorkflowRun {
121
121
  workflowName: 'Run',
122
122
  nameOverride: null,
123
123
  status: 'pending',
124
+ origin: 'synced',
125
+ devSource: null,
124
126
  currentAttempt: 1,
125
127
  triggerProvider: null,
126
128
  triggerSource: 'manual',