@shipfox/api-workflows 11.0.0 → 12.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.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +100 -0
- package/README.md +75 -0
- package/dist/core/agent-defaults.d.ts +2 -1
- package/dist/core/agent-defaults.d.ts.map +1 -1
- package/dist/core/agent-defaults.js.map +1 -1
- package/dist/core/checkout.d.ts +7 -21
- package/dist/core/checkout.d.ts.map +1 -1
- package/dist/core/checkout.js +122 -41
- package/dist/core/checkout.js.map +1 -1
- package/dist/core/entities/job-execution.d.ts +8 -0
- package/dist/core/entities/job-execution.d.ts.map +1 -1
- package/dist/core/entities/job-execution.js +13 -1
- package/dist/core/entities/job-execution.js.map +1 -1
- package/dist/core/entities/job-listener-event.d.ts +2 -0
- package/dist/core/entities/job-listener-event.d.ts.map +1 -1
- package/dist/core/entities/job-listener-event.js.map +1 -1
- package/dist/core/entities/step.d.ts +13 -3
- package/dist/core/entities/step.d.ts.map +1 -1
- package/dist/core/entities/step.js +6 -0
- package/dist/core/entities/step.js.map +1 -1
- package/dist/core/entities/workflow-run-attempt.d.ts +1 -0
- package/dist/core/entities/workflow-run-attempt.d.ts.map +1 -1
- package/dist/core/entities/workflow-run-attempt.js.map +1 -1
- package/dist/core/entities/workflow-run.d.ts +17 -0
- package/dist/core/entities/workflow-run.d.ts.map +1 -1
- package/dist/core/entities/workflow-run.js.map +1 -1
- package/dist/core/errors.d.ts +9 -2
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +10 -5
- package/dist/core/errors.js.map +1 -1
- package/dist/core/job-execution.d.ts.map +1 -1
- package/dist/core/job-execution.js +14 -8
- package/dist/core/job-execution.js.map +1 -1
- package/dist/core/job-transition/decide-job-activation.d.ts +1 -0
- package/dist/core/job-transition/decide-job-activation.d.ts.map +1 -1
- package/dist/core/job-transition/decide-job-activation.js +1 -0
- package/dist/core/job-transition/decide-job-activation.js.map +1 -1
- package/dist/core/job-transition/derive-job-success.d.ts +1 -0
- package/dist/core/job-transition/derive-job-success.d.ts.map +1 -1
- package/dist/core/job-transition/derive-job-success.js +5 -8
- package/dist/core/job-transition/derive-job-success.js.map +1 -1
- package/dist/core/listener-execution-materialization.d.ts +6 -3
- package/dist/core/listener-execution-materialization.d.ts.map +1 -1
- package/dist/core/listener-execution-materialization.js +44 -6
- package/dist/core/listener-execution-materialization.js.map +1 -1
- package/dist/core/resolve-trigger-reference.d.ts +11 -0
- package/dist/core/resolve-trigger-reference.d.ts.map +1 -0
- package/dist/core/resolve-trigger-reference.js +39 -0
- package/dist/core/resolve-trigger-reference.js.map +1 -0
- package/dist/core/run-workflow.d.ts +1 -0
- package/dist/core/run-workflow.d.ts.map +1 -1
- package/dist/core/run-workflow.js +1 -0
- package/dist/core/run-workflow.js.map +1 -1
- package/dist/core/step-config/agent.d.ts +1 -2
- package/dist/core/step-config/agent.d.ts.map +1 -1
- package/dist/core/step-config/agent.js +22 -7
- package/dist/core/step-config/agent.js.map +1 -1
- package/dist/core/step-config/assemble-run-context.d.ts +19 -8
- package/dist/core/step-config/assemble-run-context.d.ts.map +1 -1
- package/dist/core/step-config/assemble-run-context.js +51 -19
- package/dist/core/step-config/assemble-run-context.js.map +1 -1
- package/dist/core/step-config/complete-step-dispatch-config.d.ts.map +1 -1
- package/dist/core/step-config/complete-step-dispatch-config.js +72 -4
- package/dist/core/step-config/complete-step-dispatch-config.js.map +1 -1
- package/dist/core/step-config/index.d.ts +1 -0
- package/dist/core/step-config/index.d.ts.map +1 -1
- package/dist/core/step-config/index.js +1 -0
- package/dist/core/step-config/index.js.map +1 -1
- package/dist/core/step-config/materialize-job-execution-steps.d.ts +1 -1
- package/dist/core/step-config/materialize-job-execution-steps.d.ts.map +1 -1
- package/dist/core/step-config/materialize-job-execution-steps.js +49 -8
- package/dist/core/step-config/materialize-job-execution-steps.js.map +1 -1
- package/dist/core/step-config/materialize-workflow-model.d.ts +3 -3
- package/dist/core/step-config/materialize-workflow-model.d.ts.map +1 -1
- package/dist/core/step-config/materialize-workflow-model.js +9 -5
- package/dist/core/step-config/materialize-workflow-model.js.map +1 -1
- package/dist/core/step-config/resolve-job-execution-name.d.ts +3 -3
- package/dist/core/step-config/resolve-job-execution-name.d.ts.map +1 -1
- package/dist/core/step-config/resolve-job-execution-name.js +24 -13
- package/dist/core/step-config/resolve-job-execution-name.js.map +1 -1
- package/dist/core/step-config/resolve-step-config.d.ts.map +1 -1
- package/dist/core/step-config/resolve-step-config.js +174 -9
- package/dist/core/step-config/resolve-step-config.js.map +1 -1
- package/dist/core/step-config/resolve-workflow-run-name.d.ts +19 -0
- package/dist/core/step-config/resolve-workflow-run-name.d.ts.map +1 -0
- package/dist/core/step-config/resolve-workflow-run-name.js +73 -0
- package/dist/core/step-config/resolve-workflow-run-name.js.map +1 -0
- package/dist/core/step-transition/decide-step-transition.js.map +1 -1
- package/dist/core/step-transition/evaluate-gate.d.ts +2 -1
- package/dist/core/step-transition/evaluate-gate.d.ts.map +1 -1
- package/dist/core/step-transition/evaluate-gate.js +5 -3
- package/dist/core/step-transition/evaluate-gate.js.map +1 -1
- package/dist/core/workflow-run-creation.d.ts +3 -0
- package/dist/core/workflow-run-creation.d.ts.map +1 -1
- package/dist/core/workflow-run-creation.js +22 -7
- package/dist/core/workflow-run-creation.js.map +1 -1
- package/dist/db/db.d.ts +278 -10
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +2 -0
- package/dist/db/db.js.map +1 -1
- package/dist/db/index.d.ts +3 -2
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +2 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/job-listener-events.d.ts +2 -0
- package/dist/db/job-listener-events.d.ts.map +1 -1
- package/dist/db/job-listener-events.js +1 -0
- package/dist/db/job-listener-events.js.map +1 -1
- package/dist/db/job-listeners.d.ts +2 -0
- package/dist/db/job-listeners.d.ts.map +1 -1
- package/dist/db/job-listeners.js +81 -21
- package/dist/db/job-listeners.js.map +1 -1
- package/dist/db/schema/job-executions.d.ts +3 -3
- package/dist/db/schema/job-executions.d.ts.map +1 -1
- package/dist/db/schema/job-executions.js +8 -4
- package/dist/db/schema/job-executions.js.map +1 -1
- package/dist/db/schema/job-listener-events.d.ts +20 -0
- package/dist/db/schema/job-listener-events.d.ts.map +1 -1
- package/dist/db/schema/job-listener-events.js +2 -0
- package/dist/db/schema/job-listener-events.js.map +1 -1
- package/dist/db/schema/step-attempts.js +2 -2
- package/dist/db/schema/step-attempts.js.map +1 -1
- package/dist/db/schema/steps.d.ts +4 -2
- package/dist/db/schema/steps.d.ts.map +1 -1
- package/dist/db/schema/steps.js +1 -1
- package/dist/db/schema/steps.js.map +1 -1
- package/dist/db/schema/workflow-run-attempts.d.ts +21 -2
- package/dist/db/schema/workflow-run-attempts.d.ts.map +1 -1
- package/dist/db/schema/workflow-run-attempts.js +2 -0
- package/dist/db/schema/workflow-run-attempts.js.map +1 -1
- package/dist/db/schema/workflow-run-counters.d.ts +43 -0
- package/dist/db/schema/workflow-run-counters.d.ts.map +1 -0
- package/dist/db/schema/workflow-run-counters.js +10 -0
- package/dist/db/schema/workflow-run-counters.js.map +1 -0
- package/dist/db/schema/workflow-runs.d.ts +54 -1
- package/dist/db/schema/workflow-runs.d.ts.map +1 -1
- package/dist/db/schema/workflow-runs.js +10 -2
- package/dist/db/schema/workflow-runs.js.map +1 -1
- package/dist/db/workflow-runs/job-executions.d.ts.map +1 -1
- package/dist/db/workflow-runs/job-executions.js +35 -14
- package/dist/db/workflow-runs/job-executions.js.map +1 -1
- package/dist/db/workflow-runs/jobs.d.ts +2 -0
- package/dist/db/workflow-runs/jobs.d.ts.map +1 -1
- package/dist/db/workflow-runs/jobs.js +9 -5
- package/dist/db/workflow-runs/jobs.js.map +1 -1
- package/dist/db/workflow-runs/queries.d.ts +51 -0
- package/dist/db/workflow-runs/queries.d.ts.map +1 -1
- package/dist/db/workflow-runs/queries.js +82 -2
- package/dist/db/workflow-runs/queries.js.map +1 -1
- package/dist/db/workflow-runs/run-create.d.ts +1 -0
- package/dist/db/workflow-runs/run-create.d.ts.map +1 -1
- package/dist/db/workflow-runs/run-create.js +159 -32
- package/dist/db/workflow-runs/run-create.js.map +1 -1
- package/dist/db/workflow-runs/run-rerun.d.ts.map +1 -1
- package/dist/db/workflow-runs/run-rerun.js +13 -5
- package/dist/db/workflow-runs/run-rerun.js.map +1 -1
- package/dist/db/workflow-runs/shared.d.ts +1 -0
- package/dist/db/workflow-runs/shared.d.ts.map +1 -1
- package/dist/db/workflow-runs/shared.js +2 -1
- package/dist/db/workflow-runs/shared.js.map +1 -1
- package/dist/db/workflow-runs/steps.js +3 -3
- package/dist/db/workflow-runs/steps.js.map +1 -1
- package/dist/db/workflow-runs.d.ts +4 -3
- package/dist/db/workflow-runs.d.ts.map +1 -1
- package/dist/db/workflow-runs.js +3 -2
- package/dist/db/workflow-runs.js.map +1 -1
- package/dist/metrics/instance.d.ts +1 -0
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js +9 -0
- package/dist/metrics/instance.js.map +1 -1
- package/dist/presentation/dto/checkout-token.d.ts +1 -0
- package/dist/presentation/dto/checkout-token.d.ts.map +1 -1
- package/dist/presentation/dto/checkout-token.js +1 -0
- package/dist/presentation/dto/checkout-token.js.map +1 -1
- package/dist/presentation/dto/index.d.ts +1 -1
- package/dist/presentation/dto/index.d.ts.map +1 -1
- package/dist/presentation/dto/index.js +1 -1
- package/dist/presentation/dto/index.js.map +1 -1
- package/dist/presentation/dto/step.d.ts.map +1 -1
- package/dist/presentation/dto/step.js +2 -2
- package/dist/presentation/dto/step.js.map +1 -1
- package/dist/presentation/dto/workflow-run.d.ts +3 -1
- package/dist/presentation/dto/workflow-run.d.ts.map +1 -1
- package/dist/presentation/dto/workflow-run.js +34 -0
- package/dist/presentation/dto/workflow-run.js.map +1 -1
- package/dist/presentation/inter-module.d.ts.map +1 -1
- package/dist/presentation/inter-module.js +31 -3
- package/dist/presentation/inter-module.js.map +1 -1
- package/dist/presentation/routes/checkout-token.d.ts +1 -1
- package/dist/presentation/routes/checkout-token.d.ts.map +1 -1
- package/dist/presentation/routes/checkout-token.js +32 -20
- package/dist/presentation/routes/checkout-token.js.map +1 -1
- package/dist/presentation/routes/leased-step.d.ts +2 -0
- package/dist/presentation/routes/leased-step.d.ts.map +1 -1
- package/dist/presentation/routes/leased-step.js +2 -1
- package/dist/presentation/routes/leased-step.js.map +1 -1
- package/dist/presentation/routes/list-runs.d.ts.map +1 -1
- package/dist/presentation/routes/list-runs.js +9 -3
- package/dist/presentation/routes/list-runs.js.map +1 -1
- package/dist/presentation/routes/project-access.d.ts +1 -0
- package/dist/presentation/routes/project-access.d.ts.map +1 -1
- package/dist/presentation/routes/report-step.d.ts.map +1 -1
- package/dist/presentation/routes/report-step.js +9 -2
- package/dist/presentation/routes/report-step.js.map +1 -1
- package/dist/presentation/subscribers/on-job-steps-settled.js +1 -1
- package/dist/presentation/subscribers/on-job-steps-settled.js.map +1 -1
- package/dist/presentation/subscribers/on-runner-job-claimed.d.ts.map +1 -1
- package/dist/presentation/subscribers/on-runner-job-claimed.js +21 -0
- package/dist/presentation/subscribers/on-runner-job-claimed.js.map +1 -1
- package/dist/temporal/activities/index.d.ts.map +1 -1
- package/dist/temporal/activities/index.js +2 -1
- package/dist/temporal/activities/index.js.map +1 -1
- package/dist/temporal/activities/orchestration-activities.d.ts +1 -0
- package/dist/temporal/activities/orchestration-activities.d.ts.map +1 -1
- package/dist/temporal/activities/orchestration-activities.js.map +1 -1
- package/dist/temporal/constants.d.ts +1 -0
- package/dist/temporal/constants.d.ts.map +1 -1
- package/dist/temporal/constants.js +1 -0
- package/dist/temporal/constants.js.map +1 -1
- package/dist/temporal/index.d.ts +1 -1
- package/dist/temporal/index.d.ts.map +1 -1
- package/dist/temporal/index.js +1 -1
- package/dist/temporal/index.js.map +1 -1
- package/dist/temporal/workflows/index.bundle.js +82 -43
- package/dist/temporal/workflows/index.d.ts +1 -1
- package/dist/temporal/workflows/index.d.ts.map +1 -1
- package/dist/temporal/workflows/index.js +1 -1
- package/dist/temporal/workflows/index.js.map +1 -1
- package/dist/temporal/workflows/job-execution-orchestration.d.ts +5 -0
- package/dist/temporal/workflows/job-execution-orchestration.d.ts.map +1 -1
- package/dist/temporal/workflows/job-execution-orchestration.js +77 -43
- package/dist/temporal/workflows/job-execution-orchestration.js.map +1 -1
- package/dist/temporal/workflows/test-env.d.ts +5 -1
- package/dist/temporal/workflows/test-env.d.ts.map +1 -1
- package/dist/temporal/workflows/test-env.js +32 -11
- package/dist/temporal/workflows/test-env.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0000_initial.sql +14 -2
- package/drizzle/0001_windy_sunfire.sql +1 -0
- package/drizzle/meta/0000_snapshot.json +93 -1
- package/drizzle/meta/0001_snapshot.json +1711 -0
- package/drizzle/meta/_journal.json +2 -2
- package/package.json +21 -21
- package/src/core/agent-defaults.ts +2 -1
- package/src/core/checkout.test.ts +378 -67
- package/src/core/checkout.ts +142 -59
- package/src/core/entities/job-execution.test.ts +21 -0
- package/src/core/entities/job-execution.ts +24 -0
- package/src/core/entities/job-listener-event.ts +3 -0
- package/src/core/entities/step.ts +15 -3
- package/src/core/entities/workflow-run-attempt.ts +1 -0
- package/src/core/entities/workflow-run.ts +16 -0
- package/src/core/errors.ts +21 -7
- package/src/core/job-execution.ts +27 -4
- package/src/core/job-transition/decide-job-activation.test.ts +4 -0
- package/src/core/job-transition/decide-job-activation.ts +2 -0
- package/src/core/job-transition/derive-job-success.test.ts +12 -0
- package/src/core/job-transition/derive-job-success.ts +6 -9
- package/src/core/listener-execution-materialization.test.ts +2 -0
- package/src/core/listener-execution-materialization.ts +57 -11
- package/src/core/resolve-trigger-reference.test.ts +160 -0
- package/src/core/resolve-trigger-reference.ts +53 -0
- package/src/core/run-workflow.ts +2 -0
- package/src/core/step-config/agent.ts +29 -12
- package/src/core/step-config/assemble-run-context.test.ts +149 -6
- package/src/core/step-config/assemble-run-context.ts +87 -25
- package/src/core/step-config/complete-step-dispatch-config.test.ts +125 -2
- package/src/core/step-config/complete-step-dispatch-config.ts +83 -1
- package/src/core/step-config/index.ts +7 -0
- package/src/core/step-config/materialize-job-execution-steps.test.ts +250 -1
- package/src/core/step-config/materialize-job-execution-steps.ts +57 -10
- package/src/core/step-config/materialize-workflow-model.test.ts +212 -4
- package/src/core/step-config/materialize-workflow-model.ts +33 -28
- package/src/core/step-config/resolve-job-execution-name.test.ts +37 -15
- package/src/core/step-config/resolve-job-execution-name.ts +30 -15
- package/src/core/step-config/resolve-step-config.ts +175 -10
- package/src/core/step-config/resolve-workflow-run-name.test.ts +115 -0
- package/src/core/step-config/resolve-workflow-run-name.ts +108 -0
- package/src/core/step-transition/decide-step-transition.ts +2 -2
- package/src/core/step-transition/evaluate-gate.test.ts +8 -0
- package/src/core/step-transition/evaluate-gate.ts +8 -1
- package/src/core/workflow-run-creation.test.ts +7 -4
- package/src/core/workflow-run-creation.ts +13 -7
- package/src/db/db.ts +2 -0
- package/src/db/index.ts +6 -0
- package/src/db/job-listener-events.test.ts +19 -0
- package/src/db/job-listener-events.ts +3 -0
- package/src/db/job-listeners.test.ts +187 -5
- package/src/db/job-listeners.ts +122 -30
- package/src/db/schema/job-executions.ts +12 -5
- package/src/db/schema/job-listener-events.ts +3 -0
- package/src/db/schema/step-attempts.ts +2 -2
- package/src/db/schema/steps.ts +2 -1
- package/src/db/schema/workflow-run-attempts.ts +2 -0
- package/src/db/schema/workflow-run-counters.ts +13 -0
- package/src/db/schema/workflow-runs.ts +11 -2
- package/src/db/workflow-runs/job-executions.ts +37 -15
- package/src/db/workflow-runs/jobs.ts +17 -4
- package/src/db/workflow-runs/queries.test.ts +206 -0
- package/src/db/workflow-runs/queries.ts +146 -2
- package/src/db/workflow-runs/run-create.test.ts +606 -8
- package/src/db/workflow-runs/run-create.ts +185 -40
- package/src/db/workflow-runs/run-rerun.test.ts +61 -2
- package/src/db/workflow-runs/run-rerun.ts +15 -5
- package/src/db/workflow-runs/shared.ts +2 -0
- package/src/db/workflow-runs/steps.ts +3 -3
- package/src/db/workflow-runs.ts +7 -0
- package/src/metrics/instance.ts +14 -0
- package/src/presentation/dto/checkout-token.test.ts +19 -9
- package/src/presentation/dto/checkout-token.ts +2 -1
- package/src/presentation/dto/index.ts +1 -1
- package/src/presentation/dto/job.test.ts +9 -0
- package/src/presentation/dto/step.test.ts +12 -0
- package/src/presentation/dto/step.ts +5 -2
- package/src/presentation/dto/workflow-run.ts +44 -2
- package/src/presentation/inter-module.test.ts +165 -0
- package/src/presentation/inter-module.ts +38 -4
- package/src/presentation/routes/checkout-token.test.ts +357 -142
- package/src/presentation/routes/checkout-token.ts +56 -26
- package/src/presentation/routes/get-run.test.ts +2 -0
- package/src/presentation/routes/get-step-secrets.test.ts +7 -2
- package/src/presentation/routes/leased-step.ts +9 -1
- package/src/presentation/routes/list-runs.test.ts +57 -0
- package/src/presentation/routes/list-runs.ts +8 -3
- package/src/presentation/routes/report-step.test.ts +25 -0
- package/src/presentation/routes/report-step.ts +10 -2
- package/src/presentation/subscribers/on-job-steps-settled.ts +1 -1
- package/src/presentation/subscribers/on-runner-job-claimed.test.ts +49 -0
- package/src/presentation/subscribers/on-runner-job-claimed.ts +22 -0
- package/src/temporal/activities/index.ts +1 -0
- package/src/temporal/activities/orchestration-activities.ts +1 -0
- package/src/temporal/constants.ts +1 -0
- package/src/temporal/index.ts +1 -0
- package/src/temporal/workflows/index.ts +1 -0
- package/src/temporal/workflows/job-execution-orchestration.test.ts +142 -6
- package/src/temporal/workflows/job-execution-orchestration.ts +99 -50
- package/src/temporal/workflows/run-orchestration.test.ts +1 -1
- package/src/temporal/workflows/test-env.ts +50 -13
- package/test/factories/project.ts +2 -0
- package/test/factories/workflow-model.ts +80 -26
- package/test/factories/workflow-run.ts +4 -1
- package/test/fixtures/agent-inter-module.ts +2 -1
- package/test/fixtures/job-with-steps.ts +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/drizzle/0001_agent_tool_materialization.sql +0 -1
package/src/core/checkout.ts
CHANGED
|
@@ -1,58 +1,51 @@
|
|
|
1
1
|
import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto/inter-module';
|
|
2
2
|
import type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from './errors.js';
|
|
3
|
+
import {checkoutTargetValidationIssues} from '@shipfox/workflow-document';
|
|
4
|
+
import {z} from 'zod';
|
|
5
|
+
import type {Step} from '#core/entities/step.js';
|
|
6
|
+
import type {WorkflowRunTriggerReference} from '#core/entities/workflow-run.js';
|
|
7
|
+
import {CheckoutConfigInvalidError, CheckoutIntentUnresolvedError} from './errors.js';
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
9
|
+
const checkoutConfigSchema = z
|
|
10
|
+
.object({
|
|
11
|
+
project: z.string().uuid().optional(),
|
|
12
|
+
connection: z.string().min(1).optional(),
|
|
13
|
+
repository: z.string().min(1).optional(),
|
|
14
|
+
ref: z.string().min(1).optional(),
|
|
15
|
+
fetch_depth: z.number().int().nonnegative().optional(),
|
|
16
|
+
permissions: z.object({contents: z.enum(['read', 'write'])}).optional(),
|
|
17
|
+
persist_credentials: z.boolean().optional(),
|
|
18
|
+
})
|
|
19
|
+
.superRefine((checkout, context) => {
|
|
20
|
+
for (const validationIssue of checkoutTargetValidationIssues(checkout)) {
|
|
21
|
+
const message =
|
|
22
|
+
validationIssue.kind === 'project-with-connection'
|
|
23
|
+
? 'Checkout project cannot be combined with a connection.'
|
|
24
|
+
: validationIssue.kind === 'project-with-repository'
|
|
25
|
+
? 'Checkout project cannot be combined with a repository.'
|
|
26
|
+
: 'Checkout connection requires a repository.';
|
|
27
|
+
context.addIssue({
|
|
28
|
+
code: 'custom',
|
|
29
|
+
path: [validationIssue.path],
|
|
30
|
+
message,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
});
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
if (project === null) throw new CheckoutIntentUnresolvedError(run.projectId);
|
|
35
|
+
type CheckoutConfig = z.infer<typeof checkoutConfigSchema>;
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
permissions: job.checkout.permissions,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Resolves the job's checkout intent and exchanges it for a short-lived,
|
|
47
|
-
* scoped checkout spec. Omitting `ref` lets the provider use the repository's
|
|
48
|
-
* default branch while preserving the JSON-only inter-module boundary.
|
|
49
|
-
*/
|
|
50
|
-
export async function createJobCheckoutSpec({
|
|
51
|
-
jobId,
|
|
37
|
+
export async function createStepCheckoutSpec({
|
|
38
|
+
step,
|
|
39
|
+
workspaceId,
|
|
40
|
+
projectId,
|
|
41
|
+
triggerReference,
|
|
52
42
|
integrations,
|
|
53
43
|
projects,
|
|
54
44
|
}: {
|
|
55
|
-
|
|
45
|
+
step: Step;
|
|
46
|
+
workspaceId: string;
|
|
47
|
+
projectId: string;
|
|
48
|
+
triggerReference?: WorkflowRunTriggerReference | null | undefined;
|
|
56
49
|
integrations: IntegrationsModuleClient;
|
|
57
50
|
projects: ProjectsModuleClient;
|
|
58
51
|
}): Promise<{
|
|
@@ -62,29 +55,119 @@ export async function createJobCheckoutSpec({
|
|
|
62
55
|
credentials?: {username: string; token: string; expiresAt: Date};
|
|
63
56
|
gitAuthor?: {name: string; email: string};
|
|
64
57
|
};
|
|
58
|
+
fetchDepth: number;
|
|
65
59
|
persistCredentials: boolean;
|
|
66
60
|
}> {
|
|
67
|
-
const
|
|
61
|
+
const checkout = parseCheckoutConfig(step);
|
|
62
|
+
const {project: defaultProject} = await projects.getProjectById({projectId});
|
|
63
|
+
if (defaultProject === null || defaultProject === undefined) {
|
|
64
|
+
throw new CheckoutIntentUnresolvedError({kind: 'project', value: projectId});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const target = await checkoutTarget({
|
|
68
|
+
checkout,
|
|
69
|
+
defaultProjectId: projectId,
|
|
70
|
+
defaultConnectionId: defaultProject.sourceConnectionId,
|
|
71
|
+
integrations,
|
|
72
|
+
workspaceId,
|
|
73
|
+
});
|
|
74
|
+
const resolvedTarget = await projects.resolveCheckoutTarget({
|
|
75
|
+
workspaceId,
|
|
76
|
+
defaults: {
|
|
77
|
+
connectionId: defaultProject.sourceConnectionId,
|
|
78
|
+
owner: defaultOwner(defaultProject.sourceRepositoryOwner, checkout.repository),
|
|
79
|
+
},
|
|
80
|
+
target,
|
|
81
|
+
});
|
|
82
|
+
const ref =
|
|
83
|
+
checkout.ref ??
|
|
84
|
+
(triggerReference?.project?.id === resolvedTarget.projectId
|
|
85
|
+
? (triggerReference.commit ?? undefined)
|
|
86
|
+
: undefined);
|
|
68
87
|
const response = await integrations.createCheckoutSpec({
|
|
69
|
-
workspaceId
|
|
70
|
-
connectionId:
|
|
71
|
-
externalRepositoryId:
|
|
72
|
-
|
|
88
|
+
workspaceId,
|
|
89
|
+
connectionId: resolvedTarget.connectionId,
|
|
90
|
+
externalRepositoryId: resolvedTarget.externalRepositoryId,
|
|
91
|
+
...(ref === undefined ? {} : {ref}),
|
|
92
|
+
permissions: checkout.permissions ?? {contents: 'read'},
|
|
73
93
|
});
|
|
74
|
-
|
|
94
|
+
|
|
75
95
|
return {
|
|
76
96
|
spec: {
|
|
77
|
-
|
|
78
|
-
|
|
97
|
+
repositoryUrl: response.repositoryUrl,
|
|
98
|
+
ref: response.ref,
|
|
99
|
+
...(response.credentials
|
|
79
100
|
? {
|
|
80
101
|
credentials: {
|
|
81
|
-
...credentials,
|
|
82
|
-
expiresAt: new Date(credentials.expiresAt),
|
|
102
|
+
...response.credentials,
|
|
103
|
+
expiresAt: new Date(response.credentials.expiresAt),
|
|
83
104
|
},
|
|
84
105
|
}
|
|
85
106
|
: {}),
|
|
86
|
-
...(gitAuthor ? {
|
|
107
|
+
...(response.gitAuthor === undefined ? {} : {gitAuthor: response.gitAuthor}),
|
|
87
108
|
},
|
|
88
|
-
|
|
109
|
+
fetchDepth: checkout.fetch_depth ?? 1,
|
|
110
|
+
persistCredentials: checkout.persist_credentials ?? true,
|
|
89
111
|
};
|
|
90
112
|
}
|
|
113
|
+
|
|
114
|
+
function parseCheckoutConfig(step: Step): CheckoutConfig {
|
|
115
|
+
const result = checkoutConfigSchema.safeParse(step.config.checkout);
|
|
116
|
+
if (!result.success) {
|
|
117
|
+
throw new CheckoutConfigInvalidError(step.id);
|
|
118
|
+
}
|
|
119
|
+
return result.data;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function checkoutTarget(params: {
|
|
123
|
+
checkout: CheckoutConfig;
|
|
124
|
+
defaultProjectId: string;
|
|
125
|
+
defaultConnectionId: string;
|
|
126
|
+
integrations: IntegrationsModuleClient;
|
|
127
|
+
workspaceId: string;
|
|
128
|
+
}) {
|
|
129
|
+
const {checkout} = params;
|
|
130
|
+
if (checkout.project !== undefined) return {project: checkout.project};
|
|
131
|
+
if (checkout.repository !== undefined) {
|
|
132
|
+
const connection =
|
|
133
|
+
checkout.connection === undefined
|
|
134
|
+
? undefined
|
|
135
|
+
: await resolveConnectionId({
|
|
136
|
+
integrations: params.integrations,
|
|
137
|
+
workspaceId: params.workspaceId,
|
|
138
|
+
defaultConnectionId: params.defaultConnectionId,
|
|
139
|
+
slug: checkout.connection,
|
|
140
|
+
});
|
|
141
|
+
return {
|
|
142
|
+
...(connection === undefined ? {} : {connection}),
|
|
143
|
+
repository: checkout.repository,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return {project: params.defaultProjectId};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function resolveConnectionId(params: {
|
|
150
|
+
integrations: IntegrationsModuleClient;
|
|
151
|
+
workspaceId: string;
|
|
152
|
+
defaultConnectionId: string;
|
|
153
|
+
slug: string;
|
|
154
|
+
}): Promise<string> {
|
|
155
|
+
const connection = await params.integrations.resolveConnection({
|
|
156
|
+
workspaceId: params.workspaceId,
|
|
157
|
+
slug: params.slug,
|
|
158
|
+
});
|
|
159
|
+
if (connection === null) {
|
|
160
|
+
throw new CheckoutIntentUnresolvedError({kind: 'connection', value: params.slug});
|
|
161
|
+
}
|
|
162
|
+
return connection.id;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function defaultOwner(
|
|
166
|
+
projectOwner: string | null | undefined,
|
|
167
|
+
repository: string | undefined,
|
|
168
|
+
): string {
|
|
169
|
+
if (projectOwner) return projectOwner;
|
|
170
|
+
const separator = repository?.indexOf('/') ?? -1;
|
|
171
|
+
if (separator > 0 && repository !== undefined) return repository.slice(0, separator);
|
|
172
|
+
return 'unknown';
|
|
173
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {normalizeWorkflowExecutionEvent} from './job-execution.js';
|
|
2
|
+
|
|
3
|
+
describe('normalizeWorkflowExecutionEvent', () => {
|
|
4
|
+
it('fills null reference fields for legacy persisted events', () => {
|
|
5
|
+
const legacyEvent = {
|
|
6
|
+
source: 'github',
|
|
7
|
+
event: 'push',
|
|
8
|
+
delivery_id: 'delivery-1',
|
|
9
|
+
received_at: '2026-07-20T12:00:00.000Z',
|
|
10
|
+
data: {ref: 'refs/heads/main'},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
expect(normalizeWorkflowExecutionEvent(legacyEvent)).toEqual({
|
|
14
|
+
...legacyEvent,
|
|
15
|
+
project: null,
|
|
16
|
+
repository: null,
|
|
17
|
+
ref: null,
|
|
18
|
+
commit: null,
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {JobStatus, JobStatusReason} from './job.js';
|
|
2
2
|
import type {PersistedEvaluationTraceEntry} from './step.js';
|
|
3
|
+
import type {WorkflowRunTriggerReference} from './workflow-run.js';
|
|
3
4
|
|
|
4
5
|
export type JobExecutionStatus = Exclude<JobStatus, 'skipped'>;
|
|
5
6
|
|
|
@@ -8,13 +9,36 @@ export interface WorkflowExecutionEvent {
|
|
|
8
9
|
event: string;
|
|
9
10
|
delivery_id: string;
|
|
10
11
|
received_at: string;
|
|
12
|
+
project: WorkflowRunTriggerReference['project'];
|
|
13
|
+
repository: WorkflowRunTriggerReference['repository'];
|
|
14
|
+
ref: WorkflowRunTriggerReference['ref'];
|
|
15
|
+
commit: WorkflowRunTriggerReference['commit'];
|
|
11
16
|
data: unknown;
|
|
12
17
|
}
|
|
13
18
|
|
|
19
|
+
export function normalizeWorkflowExecutionEvent(
|
|
20
|
+
event: Omit<WorkflowExecutionEvent, 'project' | 'repository' | 'ref' | 'commit'> &
|
|
21
|
+
Partial<Pick<WorkflowExecutionEvent, 'project' | 'repository' | 'ref' | 'commit'>>,
|
|
22
|
+
): WorkflowExecutionEvent {
|
|
23
|
+
return {
|
|
24
|
+
source: event.source,
|
|
25
|
+
event: event.event,
|
|
26
|
+
delivery_id: event.delivery_id,
|
|
27
|
+
received_at: event.received_at,
|
|
28
|
+
project: event.project ?? null,
|
|
29
|
+
repository: event.repository ?? null,
|
|
30
|
+
ref: event.ref ?? null,
|
|
31
|
+
commit: event.commit ?? null,
|
|
32
|
+
data: event.data,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
14
36
|
export interface JobExecution {
|
|
15
37
|
id: string;
|
|
16
38
|
jobId: string;
|
|
17
39
|
sequence: number;
|
|
40
|
+
/** A dynamically resolved name; null means use the parent job's fallback. */
|
|
41
|
+
nameOverride: string | null;
|
|
18
42
|
name: string;
|
|
19
43
|
runner: string[] | null;
|
|
20
44
|
status: JobExecutionStatus;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type {WorkflowRunTriggerReference} from './workflow-run.js';
|
|
2
|
+
|
|
1
3
|
export type JobListenerEventDisposition = 'fire' | 'resolve';
|
|
2
4
|
|
|
3
5
|
export interface JobListenerEvent {
|
|
@@ -8,6 +10,7 @@ export interface JobListenerEvent {
|
|
|
8
10
|
deliveryId: string;
|
|
9
11
|
source: string;
|
|
10
12
|
event: string;
|
|
13
|
+
triggerReference: WorkflowRunTriggerReference | null;
|
|
11
14
|
payload: unknown;
|
|
12
15
|
receivedAt: Date;
|
|
13
16
|
consumedByExecutionId: string | null;
|
|
@@ -8,11 +8,15 @@ import type {
|
|
|
8
8
|
ResolvedField,
|
|
9
9
|
WorkflowExpression,
|
|
10
10
|
} from '@shipfox/expression';
|
|
11
|
-
import type {
|
|
11
|
+
import type {Harness} from '@shipfox/workflow-document';
|
|
12
12
|
import type {InterpolationUnresolvableField} from '../errors.js';
|
|
13
13
|
|
|
14
14
|
export type StepStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'skipped';
|
|
15
15
|
|
|
16
|
+
export const STEP_TYPES = ['setup', 'run', 'agent', 'checkout'] as const;
|
|
17
|
+
|
|
18
|
+
export type StepType = (typeof STEP_TYPES)[number];
|
|
19
|
+
|
|
16
20
|
export const STEP_STATUS_REASONS = [
|
|
17
21
|
'default_gate_rejected',
|
|
18
22
|
'condition_rejected',
|
|
@@ -61,14 +65,22 @@ export interface StepConfigEvaluationTraceEntry extends EvaluationTraceEntry {
|
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
export interface StepConfigDispatchPlan {
|
|
68
|
+
working_directory?: ResolvedField;
|
|
64
69
|
run?: ResolvedField;
|
|
65
70
|
env?: Readonly<Record<string, ResolvedField>>;
|
|
71
|
+
checkout?: {
|
|
72
|
+
project?: ResolvedField;
|
|
73
|
+
connection?: ResolvedField;
|
|
74
|
+
repository?: ResolvedField;
|
|
75
|
+
ref?: ResolvedField;
|
|
76
|
+
path?: ResolvedField;
|
|
77
|
+
};
|
|
66
78
|
agent?: {
|
|
67
79
|
prompt?: ResolvedField;
|
|
68
80
|
model?: ResolvedField;
|
|
69
81
|
provider?: ResolvedField;
|
|
70
82
|
harness?: Harness;
|
|
71
|
-
thinking?:
|
|
83
|
+
thinking?: ResolvedField;
|
|
72
84
|
tools?: readonly string[];
|
|
73
85
|
integrations?: readonly MaterializedAgentIntegrationConfigDto[];
|
|
74
86
|
mcpServers?: readonly AgentIntegrationMcpServerConfigDto[];
|
|
@@ -85,7 +97,7 @@ export interface Step {
|
|
|
85
97
|
status: StepStatus;
|
|
86
98
|
statusReason: StepStatusReason | null;
|
|
87
99
|
evaluationTrace: readonly PersistedEvaluationTraceEntry[] | null;
|
|
88
|
-
type:
|
|
100
|
+
type: StepType;
|
|
89
101
|
config: Record<string, unknown>;
|
|
90
102
|
condition: WorkflowExpression | null;
|
|
91
103
|
configPlan: StepConfigDispatchPlan | null;
|
|
@@ -12,6 +12,7 @@ export interface WorkflowRunAttempt {
|
|
|
12
12
|
rerunMode: RerunMode | null;
|
|
13
13
|
rerunByUserId: string | null;
|
|
14
14
|
model: WorkflowModel | null;
|
|
15
|
+
vars: Record<string, string> | null;
|
|
15
16
|
agentToolMaterialization: AgentToolMaterializationSnapshot | null;
|
|
16
17
|
version: number;
|
|
17
18
|
createdAt: Date;
|
|
@@ -22,6 +22,14 @@ export function isWorkflowRunTerminal(
|
|
|
22
22
|
return TERMINAL_WORKFLOW_RUN_STATUSES.has(status);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export interface WorkflowRunTriggerReference {
|
|
26
|
+
project: {id: string} | null;
|
|
27
|
+
repository: string | null;
|
|
28
|
+
ref: string | null;
|
|
29
|
+
commit: string | null;
|
|
30
|
+
actor: string | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
export interface WorkflowSourceSnapshot {
|
|
26
34
|
content: string;
|
|
27
35
|
format: 'yaml';
|
|
@@ -57,13 +65,21 @@ export interface WorkflowRun {
|
|
|
57
65
|
workspaceId: string;
|
|
58
66
|
projectId: string;
|
|
59
67
|
definitionId: string;
|
|
68
|
+
number: number;
|
|
69
|
+
/** Effective runtime name: the resolved override, or workflowName when absent. */
|
|
60
70
|
name: string;
|
|
71
|
+
/** Static workflow-name snapshot preserved from the definition at creation. */
|
|
72
|
+
workflowName: string;
|
|
73
|
+
/** Nullable resolved override retained for rerun fidelity. */
|
|
74
|
+
nameOverride: string | null;
|
|
61
75
|
status: WorkflowRunStatus;
|
|
62
76
|
currentAttempt: number;
|
|
63
77
|
triggerProvider: string | null;
|
|
64
78
|
triggerSource: string;
|
|
65
79
|
triggerEvent: string;
|
|
66
80
|
triggerPayload: TriggerPayload;
|
|
81
|
+
/** Provider-neutral trigger facts captured at run creation, when available. */
|
|
82
|
+
triggerReference?: WorkflowRunTriggerReference | null | undefined;
|
|
67
83
|
inputs: Record<string, unknown> | null;
|
|
68
84
|
sourceSnapshot: WorkflowSourceSnapshot | null;
|
|
69
85
|
triggerIdempotencyKey: string | null;
|
package/src/core/errors.ts
CHANGED
|
@@ -61,11 +61,19 @@ export type InterpolationUnresolvableField =
|
|
|
61
61
|
| 'agent.prompt'
|
|
62
62
|
| 'agent.model'
|
|
63
63
|
| 'agent.provider'
|
|
64
|
+
| 'agent.thinking'
|
|
64
65
|
| 'job.runner'
|
|
65
66
|
| 'job.outputs'
|
|
66
|
-
| 'job.
|
|
67
|
+
| 'job.execution_name'
|
|
68
|
+
| 'workflow.run_name'
|
|
67
69
|
| 'step.name'
|
|
68
|
-
| 'step.
|
|
70
|
+
| 'step.working_directory'
|
|
71
|
+
| 'step.feedback'
|
|
72
|
+
| 'checkout.project'
|
|
73
|
+
| 'checkout.connection'
|
|
74
|
+
| 'checkout.repository'
|
|
75
|
+
| 'checkout.ref'
|
|
76
|
+
| 'checkout.path';
|
|
69
77
|
|
|
70
78
|
export class InterpolationUnresolvableError extends Error {
|
|
71
79
|
readonly field: InterpolationUnresolvableField;
|
|
@@ -182,15 +190,21 @@ export class NoFailedJobsError extends Error {
|
|
|
182
190
|
}
|
|
183
191
|
}
|
|
184
192
|
|
|
185
|
-
// The
|
|
186
|
-
// there is nothing to check out.
|
|
193
|
+
// The checkout target cannot be resolved, so there is nothing to check out.
|
|
187
194
|
export class CheckoutIntentUnresolvedError extends Error {
|
|
188
|
-
constructor(
|
|
189
|
-
super(`Checkout intent unresolved:
|
|
195
|
+
constructor(target: {kind: 'project' | 'connection'; value: string}) {
|
|
196
|
+
super(`Checkout intent unresolved: ${target.kind} ${target.value} not found`);
|
|
190
197
|
this.name = 'CheckoutIntentUnresolvedError';
|
|
191
198
|
}
|
|
192
199
|
}
|
|
193
200
|
|
|
201
|
+
export class CheckoutConfigInvalidError extends Error {
|
|
202
|
+
constructor(readonly stepId: string) {
|
|
203
|
+
super(`Checkout config is invalid for step ${stepId}`);
|
|
204
|
+
this.name = 'CheckoutConfigInvalidError';
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
194
208
|
export class StepNotFoundError extends Error {
|
|
195
209
|
constructor(stepId: string, jobId: string) {
|
|
196
210
|
super(`Step ${stepId} not found in job ${jobId}`);
|
|
@@ -207,7 +221,7 @@ export class StepNotRunningError extends Error {
|
|
|
207
221
|
|
|
208
222
|
// A report whose attempt is ahead of the step's current attempt. The host
|
|
209
223
|
// allocates attempt numbers, so a runner can never report one it was not
|
|
210
|
-
// dispatched
|
|
224
|
+
// dispatched: this is a protocol error, not an idempotent no-op.
|
|
211
225
|
export class StepAttemptAheadError extends Error {
|
|
212
226
|
constructor(
|
|
213
227
|
readonly stepId: string,
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
getLatestJobExecutionByJobId,
|
|
16
16
|
getStepAttemptsByJobExecutionId,
|
|
17
17
|
getStepsByJobExecutionIdForUpdate,
|
|
18
|
+
getWorkflowContextForJob,
|
|
18
19
|
insertRunningStepAttempt,
|
|
19
20
|
markStepRunning,
|
|
20
21
|
markStepSkipped,
|
|
@@ -91,6 +92,7 @@ interface ResolvePendingStepParams {
|
|
|
91
92
|
readonly jobExecution: JobExecution;
|
|
92
93
|
readonly attempts: Awaited<ReturnType<typeof getStepAttemptsByJobExecutionId>>;
|
|
93
94
|
readonly jobs: Awaited<ReturnType<typeof getDirectDependencyJobContexts>>;
|
|
95
|
+
readonly vars: Record<string, string> | undefined;
|
|
94
96
|
readonly tx: Tx;
|
|
95
97
|
readonly agent?: AgentInterModuleClient | undefined;
|
|
96
98
|
}
|
|
@@ -130,8 +132,18 @@ async function nextStepForJobExecutionInTransaction(
|
|
|
130
132
|
|
|
131
133
|
const attempts = await getStepAttemptsByJobExecutionId(jobExecutionId, tx);
|
|
132
134
|
const jobs = await getDirectDependencyJobContexts(jobExecution.jobId, tx);
|
|
135
|
+
const workflowContext = await getWorkflowContextForJob(jobExecution.jobId, tx);
|
|
133
136
|
|
|
134
|
-
return resolveNextPendingStep({
|
|
137
|
+
return resolveNextPendingStep({
|
|
138
|
+
jobExecutionId,
|
|
139
|
+
steps,
|
|
140
|
+
jobExecution,
|
|
141
|
+
attempts,
|
|
142
|
+
jobs,
|
|
143
|
+
vars: workflowContext.vars ?? undefined,
|
|
144
|
+
tx,
|
|
145
|
+
agent,
|
|
146
|
+
});
|
|
135
147
|
}
|
|
136
148
|
|
|
137
149
|
async function resolveNextPendingStep({
|
|
@@ -140,6 +152,7 @@ async function resolveNextPendingStep({
|
|
|
140
152
|
jobExecution,
|
|
141
153
|
attempts,
|
|
142
154
|
jobs,
|
|
155
|
+
vars,
|
|
143
156
|
tx,
|
|
144
157
|
agent,
|
|
145
158
|
}: ResolvePendingStepParams): Promise<NextStep> {
|
|
@@ -167,6 +180,7 @@ async function resolveNextPendingStep({
|
|
|
167
180
|
targetStepId: pending.id,
|
|
168
181
|
jobExecution,
|
|
169
182
|
jobs,
|
|
183
|
+
vars,
|
|
170
184
|
});
|
|
171
185
|
const condition = evaluateStepCondition({step: pending, context});
|
|
172
186
|
if (condition.kind === 'run') {
|
|
@@ -454,11 +468,17 @@ async function recordStepResultInTransaction(
|
|
|
454
468
|
};
|
|
455
469
|
}
|
|
456
470
|
|
|
457
|
-
// Evaluate the gate (if any) at the service boundary
|
|
458
|
-
// engine runs
|
|
471
|
+
// Evaluate the gate (if any) at the service boundary. This is the only place
|
|
472
|
+
// the CEL engine runs. Pass the precomputed outcome into the pure decision.
|
|
459
473
|
const shouldEvaluateGate = outputCoercion.kind !== 'failed';
|
|
460
474
|
const gate = shouldEvaluateGate ? readStepGate(target.config) : undefined;
|
|
461
|
-
const
|
|
475
|
+
const vars =
|
|
476
|
+
gate === undefined
|
|
477
|
+
? undefined
|
|
478
|
+
: ((await getWorkflowContextForJob(jobExecution.jobId, tx)).vars ?? undefined);
|
|
479
|
+
const gateOutcome = shouldEvaluateGate
|
|
480
|
+
? evaluateGate(gate, result, vars)
|
|
481
|
+
: {kind: 'no-gate' as const};
|
|
462
482
|
const hasRestartPolicy = gate?.onFailure?.restartFrom !== undefined;
|
|
463
483
|
// The restart cap is bounded on the gating step's OWN attempts, not its
|
|
464
484
|
// current_attempt (which a rewind inflates for downstream steps).
|
|
@@ -479,6 +499,7 @@ async function recordStepResultInTransaction(
|
|
|
479
499
|
gate,
|
|
480
500
|
result,
|
|
481
501
|
definitionId: jobExecution.jobId,
|
|
502
|
+
vars,
|
|
482
503
|
});
|
|
483
504
|
|
|
484
505
|
return applyStepTransition(
|
|
@@ -548,6 +569,7 @@ function resolveRestartFeedback(params: {
|
|
|
548
569
|
gate: ReturnType<typeof readStepGate>;
|
|
549
570
|
result: ReportedStepResult;
|
|
550
571
|
definitionId: string;
|
|
572
|
+
vars?: Record<string, string> | undefined;
|
|
551
573
|
}): StepTransitionDecision {
|
|
552
574
|
if (params.decision.kind !== 'restart-job-from-step') return params.decision;
|
|
553
575
|
if (params.gate === undefined) return params.decision;
|
|
@@ -559,6 +581,7 @@ function resolveRestartFeedback(params: {
|
|
|
559
581
|
gate: params.gate,
|
|
560
582
|
result: params.result,
|
|
561
583
|
definitionId: params.definitionId,
|
|
584
|
+
vars: params.vars,
|
|
562
585
|
}),
|
|
563
586
|
};
|
|
564
587
|
} catch (error) {
|
|
@@ -113,10 +113,13 @@ function expression(source: string) {
|
|
|
113
113
|
function workflowRun(): WorkflowRun {
|
|
114
114
|
return {
|
|
115
115
|
id: crypto.randomUUID(),
|
|
116
|
+
number: 1,
|
|
116
117
|
workspaceId: crypto.randomUUID(),
|
|
117
118
|
projectId: crypto.randomUUID(),
|
|
118
119
|
definitionId: crypto.randomUUID(),
|
|
119
120
|
name: 'Run',
|
|
121
|
+
workflowName: 'Run',
|
|
122
|
+
nameOverride: null,
|
|
120
123
|
status: 'pending',
|
|
121
124
|
currentAttempt: 1,
|
|
122
125
|
triggerProvider: null,
|
|
@@ -179,6 +182,7 @@ export function jobExecution(params: Partial<JobExecution> = {}): JobExecution {
|
|
|
179
182
|
id: crypto.randomUUID(),
|
|
180
183
|
jobId: params.jobId ?? crypto.randomUUID(),
|
|
181
184
|
sequence: params.sequence ?? 1,
|
|
185
|
+
nameOverride: params.nameOverride ?? params.name ?? 'build',
|
|
182
186
|
name: params.name ?? 'build',
|
|
183
187
|
runner: null,
|
|
184
188
|
status: params.status ?? 'succeeded',
|
|
@@ -34,6 +34,7 @@ export interface DecideJobActivationInput {
|
|
|
34
34
|
job: Job;
|
|
35
35
|
condition?: WorkflowExpression | undefined;
|
|
36
36
|
dependencies: readonly JobContextInput[];
|
|
37
|
+
vars?: Record<string, string> | undefined;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export function decideJobActivation(input: DecideJobActivationInput): JobActivationDecision {
|
|
@@ -52,6 +53,7 @@ export function decideJobActivation(input: DecideJobActivationInput): JobActivat
|
|
|
52
53
|
run: input.run,
|
|
53
54
|
triggerPayload: input.run.triggerPayload,
|
|
54
55
|
inputs: input.run.inputs,
|
|
56
|
+
vars: input.vars,
|
|
55
57
|
jobs: input.dependencies,
|
|
56
58
|
});
|
|
57
59
|
const outcome = evaluatePlannedPredicateAtSite({
|
|
@@ -52,6 +52,17 @@ describe('deriveJobSuccess', () => {
|
|
|
52
52
|
expect(result).toMatchObject({status: 'succeeded', statusReason: null});
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
test('resolves vars from the run-creation snapshot', () => {
|
|
56
|
+
const result = deriveJobSuccess({
|
|
57
|
+
success: 'vars.RELEASE == "yes"',
|
|
58
|
+
executions: [jobExecution({status: 'succeeded'})],
|
|
59
|
+
jobs: [],
|
|
60
|
+
vars: {RELEASE: 'yes'},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
expect(result).toMatchObject({status: 'succeeded', statusReason: null});
|
|
64
|
+
});
|
|
65
|
+
|
|
55
66
|
test('fails closed when the success expression throws at runtime', () => {
|
|
56
67
|
const result = deriveJobSuccess({
|
|
57
68
|
success: 'executions.all(e, 1 / 0 == 0)',
|
|
@@ -116,6 +127,7 @@ function jobExecution(params: Partial<JobExecution> = {}): JobExecution {
|
|
|
116
127
|
id: crypto.randomUUID(),
|
|
117
128
|
jobId: params.jobId ?? crypto.randomUUID(),
|
|
118
129
|
sequence: params.sequence ?? 1,
|
|
130
|
+
nameOverride: params.nameOverride ?? params.name ?? 'build',
|
|
119
131
|
name: params.name ?? 'build',
|
|
120
132
|
runner: null,
|
|
121
133
|
status: params.status ?? 'succeeded',
|
|
@@ -9,8 +9,7 @@ import type {JobStatusReason} from '../entities/job.js';
|
|
|
9
9
|
import type {JobExecution} from '../entities/job-execution.js';
|
|
10
10
|
import type {PersistedEvaluationTraceEntry} from '../entities/step.js';
|
|
11
11
|
import {
|
|
12
|
-
|
|
13
|
-
assembleJobsContext,
|
|
12
|
+
assembleJobResolutionContext,
|
|
14
13
|
type JobContextInput,
|
|
15
14
|
} from '../step-config/assemble-run-context.js';
|
|
16
15
|
import type {RuntimeCompletionStatus} from '../workflow-scheduling/runtime-dag.js';
|
|
@@ -25,27 +24,25 @@ export function deriveJobSuccess(params: {
|
|
|
25
24
|
success: string | null;
|
|
26
25
|
executions: readonly JobExecution[];
|
|
27
26
|
jobs: readonly JobContextInput[];
|
|
27
|
+
vars?: Record<string, string> | undefined;
|
|
28
28
|
}): DeriveJobSuccessResult {
|
|
29
29
|
const expression = createWorkflowExpression({
|
|
30
30
|
source: params.success ?? DEFAULT_JOB_SUCCESS,
|
|
31
31
|
check: {mode: 'syntax'},
|
|
32
32
|
});
|
|
33
|
-
const context =
|
|
34
|
-
...assembleExecutionsContext(params.executions),
|
|
35
|
-
...assembleJobsContext(params.jobs),
|
|
36
|
-
};
|
|
33
|
+
const context = assembleJobResolutionContext(params);
|
|
37
34
|
const outcome = evaluatePlannedPredicateAtSite({
|
|
38
35
|
expression,
|
|
39
36
|
field: 'job.success',
|
|
40
|
-
site:
|
|
41
|
-
context,
|
|
37
|
+
site: context.site,
|
|
38
|
+
context: context.values,
|
|
42
39
|
});
|
|
43
40
|
const trace = capTraceEntries([
|
|
44
41
|
{
|
|
45
42
|
...predicateTraceEntry({
|
|
46
43
|
expression: expression.source,
|
|
47
44
|
route: outcome.route,
|
|
48
|
-
site:
|
|
45
|
+
site: context.site,
|
|
49
46
|
value: outcome.value,
|
|
50
47
|
degraded: outcome.evaluationFailed,
|
|
51
48
|
}),
|
|
@@ -21,7 +21,9 @@ describe('materializeListenerExecution', () => {
|
|
|
21
21
|
model,
|
|
22
22
|
run: {
|
|
23
23
|
id: crypto.randomUUID(),
|
|
24
|
+
number: 1,
|
|
24
25
|
name: 'Review run',
|
|
26
|
+
workflowName: 'Review run',
|
|
25
27
|
definitionId: crypto.randomUUID(),
|
|
26
28
|
projectId: crypto.randomUUID(),
|
|
27
29
|
workspaceId: crypto.randomUUID(),
|