@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
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import {requireLeasedJobContext} from '@shipfox/api-auth-context';
|
|
2
1
|
import {
|
|
3
2
|
type IntegrationsModuleClient,
|
|
4
3
|
integrationsInterModuleContract,
|
|
5
4
|
} from '@shipfox/api-integration-core-dto/inter-module';
|
|
6
|
-
import
|
|
5
|
+
import {
|
|
6
|
+
type ProjectsModuleClient,
|
|
7
|
+
projectsInterModuleContract,
|
|
8
|
+
} from '@shipfox/api-projects-dto/inter-module';
|
|
7
9
|
import type {RunnersInterModuleClient} from '@shipfox/api-runners-dto/inter-module';
|
|
8
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
checkoutTokenParamsSchema,
|
|
12
|
+
checkoutTokenQuerySchema,
|
|
13
|
+
checkoutTokenResponseSchema,
|
|
14
|
+
} from '@shipfox/api-workflows-dto';
|
|
9
15
|
import {isInterModuleKnownError} from '@shipfox/inter-module';
|
|
10
16
|
import {ClientError, defineRoute} from '@shipfox/node-fastify';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
CheckoutIntentUnresolvedError,
|
|
14
|
-
JobNotFoundError,
|
|
15
|
-
WorkflowRunNotFoundError,
|
|
16
|
-
} from '#core/errors.js';
|
|
17
|
+
import {createStepCheckoutSpec} from '#core/checkout.js';
|
|
18
|
+
import {CheckoutConfigInvalidError, CheckoutIntentUnresolvedError} from '#core/errors.js';
|
|
17
19
|
import {toCheckoutTokenDto} from '#presentation/dto/checkout-token.js';
|
|
20
|
+
import {loadRunningLeasedStep} from './leased-step.js';
|
|
18
21
|
|
|
19
22
|
export function createCheckoutTokenRoute(clients: {
|
|
20
23
|
runners: RunnersInterModuleClient;
|
|
@@ -23,10 +26,14 @@ export function createCheckoutTokenRoute(clients: {
|
|
|
23
26
|
}) {
|
|
24
27
|
return defineRoute({
|
|
25
28
|
method: 'POST',
|
|
26
|
-
path: '/checkout-token',
|
|
29
|
+
path: '/steps/:stepId/checkout-token',
|
|
27
30
|
description:
|
|
28
|
-
"Exchanges the runner's
|
|
29
|
-
schema: {
|
|
31
|
+
"Exchanges the runner's lease for short-lived checkout credentials for the currently running checkout step. The step id and attempt are checked against the lease and the server-frozen step config supplies the target, ref, permissions, and fetch depth.",
|
|
32
|
+
schema: {
|
|
33
|
+
params: checkoutTokenParamsSchema,
|
|
34
|
+
querystring: checkoutTokenQuerySchema,
|
|
35
|
+
response: {200: checkoutTokenResponseSchema},
|
|
36
|
+
},
|
|
30
37
|
errorHandler: (error) => {
|
|
31
38
|
const known = isInterModuleKnownError(
|
|
32
39
|
integrationsInterModuleContract.methods.createCheckoutSpec,
|
|
@@ -34,12 +41,24 @@ export function createCheckoutTokenRoute(clients: {
|
|
|
34
41
|
)
|
|
35
42
|
? error
|
|
36
43
|
: undefined;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
44
|
+
const targetError = isInterModuleKnownError(
|
|
45
|
+
projectsInterModuleContract.methods.resolveCheckoutTarget,
|
|
46
|
+
error,
|
|
47
|
+
)
|
|
48
|
+
? error
|
|
49
|
+
: undefined;
|
|
41
50
|
if (error instanceof CheckoutIntentUnresolvedError)
|
|
42
51
|
throw new ClientError(error.message, 'checkout-unavailable', {status: 404});
|
|
52
|
+
if (error instanceof CheckoutConfigInvalidError)
|
|
53
|
+
throw new ClientError('Checkout configuration is invalid', 'checkout-config-invalid', {
|
|
54
|
+
status: 409,
|
|
55
|
+
});
|
|
56
|
+
if (targetError?.code === 'checkout-repository-not-authorized')
|
|
57
|
+
throw new ClientError(
|
|
58
|
+
'Checkout repository is not authorized for this workspace',
|
|
59
|
+
'checkout-repository-not-authorized',
|
|
60
|
+
{status: 404},
|
|
61
|
+
);
|
|
43
62
|
if (known?.code === 'connection-not-found')
|
|
44
63
|
throw new ClientError(
|
|
45
64
|
'Integration connection not found',
|
|
@@ -101,21 +120,32 @@ export function createCheckoutTokenRoute(clients: {
|
|
|
101
120
|
throw error;
|
|
102
121
|
},
|
|
103
122
|
handler: async (request, reply) => {
|
|
104
|
-
const
|
|
105
|
-
const {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
123
|
+
const {stepId} = request.params;
|
|
124
|
+
const {attempt} = request.query;
|
|
125
|
+
const {step, workspaceId, projectId, triggerReference} = await loadRunningLeasedStep({
|
|
126
|
+
runners: clients.runners,
|
|
127
|
+
request,
|
|
128
|
+
stepId,
|
|
129
|
+
attempt,
|
|
109
130
|
});
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
131
|
+
|
|
132
|
+
if (step.type !== 'setup' && step.type !== 'checkout') {
|
|
133
|
+
throw new ClientError('Step is not a checkout step', 'step-not-checkout', {status: 409});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const checkout = await createStepCheckoutSpec({
|
|
137
|
+
step,
|
|
138
|
+
workspaceId,
|
|
139
|
+
projectId,
|
|
140
|
+
triggerReference,
|
|
114
141
|
integrations: clients.integrations,
|
|
115
142
|
projects: clients.projects,
|
|
116
143
|
});
|
|
117
144
|
reply.header('cache-control', 'no-store');
|
|
118
|
-
return toCheckoutTokenDto(checkout.spec, {
|
|
145
|
+
return toCheckoutTokenDto(checkout.spec, {
|
|
146
|
+
fetchDepth: checkout.fetchDepth,
|
|
147
|
+
persist: checkout.persistCredentials,
|
|
148
|
+
});
|
|
119
149
|
},
|
|
120
150
|
});
|
|
121
151
|
}
|
|
@@ -117,6 +117,8 @@ describe('GET /api/workflows/runs/:id', () => {
|
|
|
117
117
|
expect(res.statusCode).toBe(200);
|
|
118
118
|
const body = res.json();
|
|
119
119
|
expect(body.id).toBe(run.id);
|
|
120
|
+
expect(body).toMatchObject({name: 'Test', workflow_name: 'Test'});
|
|
121
|
+
expect(body.number).toBe(run.number);
|
|
120
122
|
expect(body.source_snapshot).toBeNull();
|
|
121
123
|
expect(body.jobs).toHaveLength(1);
|
|
122
124
|
expect(body.jobs[0].key).toBe('build');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {closeApp, createApp, type FastifyInstance} from '@shipfox/node-fastify';
|
|
2
2
|
import {createCapturingLogger} from '@shipfox/node-log/test';
|
|
3
|
+
import {agentThinkingSchema} from '@shipfox/workflow-document';
|
|
3
4
|
import {eq} from 'drizzle-orm';
|
|
4
5
|
import type {StepStatus} from '#core/entities/step.js';
|
|
5
6
|
import {db} from '#db/db.js';
|
|
@@ -205,7 +206,11 @@ describe('GET /runs/jobs/current/steps/:stepId/secrets', () => {
|
|
|
205
206
|
|
|
206
207
|
const scope = await getJobScope(job.id);
|
|
207
208
|
|
|
208
|
-
expect(scope).toEqual({
|
|
209
|
+
expect(scope).toEqual({
|
|
210
|
+
workspaceId: run.workspaceId,
|
|
211
|
+
projectId: run.projectId,
|
|
212
|
+
triggerReference: null,
|
|
213
|
+
});
|
|
209
214
|
});
|
|
210
215
|
});
|
|
211
216
|
|
|
@@ -256,7 +261,7 @@ async function createStep(params: {
|
|
|
256
261
|
harness: defaults.harness ?? 'pi',
|
|
257
262
|
provider: defaults.provider ?? 'anthropic',
|
|
258
263
|
model: defaults.model ?? 'claude-opus-4-8',
|
|
259
|
-
thinking: defaults.thinking ?? 'high',
|
|
264
|
+
thinking: agentThinkingSchema.safeParse(defaults.thinking).data ?? 'high',
|
|
260
265
|
}),
|
|
261
266
|
triggerPayload: {
|
|
262
267
|
source: 'manual',
|
|
@@ -2,6 +2,7 @@ import {type LeasedJobContext, requireLeasedJobContext} from '@shipfox/api-auth-
|
|
|
2
2
|
import type {RunnersInterModuleClient} from '@shipfox/api-runners-dto/inter-module';
|
|
3
3
|
import {ClientError} from '@shipfox/node-fastify';
|
|
4
4
|
import type {Step} from '#core/entities/step.js';
|
|
5
|
+
import type {WorkflowRunTriggerReference} from '#core/entities/workflow-run.js';
|
|
5
6
|
import {getJobScope, getStepByIdForJobExecution} from '#db/index.js';
|
|
6
7
|
|
|
7
8
|
export interface LoadedRunningLeasedStep {
|
|
@@ -9,6 +10,7 @@ export interface LoadedRunningLeasedStep {
|
|
|
9
10
|
step: Step;
|
|
10
11
|
workspaceId: string;
|
|
11
12
|
projectId: string;
|
|
13
|
+
triggerReference: WorkflowRunTriggerReference | null;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export async function loadRunningLeasedStep(params: {
|
|
@@ -51,5 +53,11 @@ export async function loadRunningLeasedStep(params: {
|
|
|
51
53
|
throw new ClientError('Step is not running', 'step-not-running', {status: 409});
|
|
52
54
|
}
|
|
53
55
|
|
|
54
|
-
return {
|
|
56
|
+
return {
|
|
57
|
+
leasedJob,
|
|
58
|
+
step,
|
|
59
|
+
workspaceId: scope.workspaceId,
|
|
60
|
+
projectId: scope.projectId,
|
|
61
|
+
triggerReference: scope.triggerReference,
|
|
62
|
+
};
|
|
55
63
|
}
|
|
@@ -96,6 +96,7 @@ describe('GET /api/workflows/runs', () => {
|
|
|
96
96
|
expect(body.runs).toHaveLength(2);
|
|
97
97
|
expect(body.runs[0].project_id).toBe(projectId);
|
|
98
98
|
expect(body.runs[0].name).toBeDefined();
|
|
99
|
+
expect(body.runs[0].workflow_name).toBeDefined();
|
|
99
100
|
expect(body.runs[0].trigger_source).toBe('manual');
|
|
100
101
|
// The runs list carries run-level timing (null until the run starts).
|
|
101
102
|
expect(body.runs[0]).toMatchObject({started_at: null, finished_at: null});
|
|
@@ -103,6 +104,62 @@ describe('GET /api/workflows/runs', () => {
|
|
|
103
104
|
expect(body.filtered_total_count).toBe(2);
|
|
104
105
|
});
|
|
105
106
|
|
|
107
|
+
test('carries the current attempt jobs in graph order so a row can draw its status strip', async () => {
|
|
108
|
+
await createWorkflowRun({
|
|
109
|
+
workspaceId,
|
|
110
|
+
projectId,
|
|
111
|
+
definitionId: crypto.randomUUID(),
|
|
112
|
+
name: 'Pipeline',
|
|
113
|
+
model: workflowModel({
|
|
114
|
+
name: 'Pipeline',
|
|
115
|
+
jobs: {
|
|
116
|
+
build: {steps: [{run: 'echo build'}]},
|
|
117
|
+
test: {needs: 'build', steps: [{run: 'echo test'}]},
|
|
118
|
+
deploy: {needs: 'test', steps: [{run: 'echo deploy'}]},
|
|
119
|
+
},
|
|
120
|
+
}),
|
|
121
|
+
triggerPayload: {
|
|
122
|
+
source: 'manual',
|
|
123
|
+
event: 'fire',
|
|
124
|
+
subscriptionId: crypto.randomUUID(),
|
|
125
|
+
userId: crypto.randomUUID(),
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const res = await app.inject({
|
|
130
|
+
method: 'GET',
|
|
131
|
+
url: `/api/workflows/runs?project_id=${projectId}`,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(res.statusCode).toBe(200);
|
|
135
|
+
const [run] = res.json().runs;
|
|
136
|
+
expect(run.jobs.map((job: {key: string}) => job.key)).toEqual(['build', 'test', 'deploy']);
|
|
137
|
+
expect(run.jobs[0]).toMatchObject({status: 'pending', position: 0});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('reports a null trigger reference for a run no source-control event produced', async () => {
|
|
141
|
+
await createWorkflowRun({
|
|
142
|
+
workspaceId,
|
|
143
|
+
projectId,
|
|
144
|
+
definitionId: crypto.randomUUID(),
|
|
145
|
+
name: 'Manual',
|
|
146
|
+
model: workflowModel({name: 'Manual'}),
|
|
147
|
+
triggerPayload: {
|
|
148
|
+
source: 'manual',
|
|
149
|
+
event: 'fire',
|
|
150
|
+
subscriptionId: crypto.randomUUID(),
|
|
151
|
+
userId: crypto.randomUUID(),
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const res = await app.inject({
|
|
156
|
+
method: 'GET',
|
|
157
|
+
url: `/api/workflows/runs?project_id=${projectId}`,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
expect(res.json().runs[0].trigger_reference).toBeNull();
|
|
161
|
+
});
|
|
162
|
+
|
|
106
163
|
test('returns empty array for project with no runs', async () => {
|
|
107
164
|
const res = await app.inject({
|
|
108
165
|
method: 'GET',
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
import {decodeTimestampIdCursor, encodeTimestampIdCursor} from '@shipfox/node-drizzle';
|
|
7
7
|
import {ClientError, defineRoute} from '@shipfox/node-fastify';
|
|
8
8
|
import {logger} from '@shipfox/node-opentelemetry';
|
|
9
|
-
import {listWorkflowRuns} from '#db/index.js';
|
|
10
|
-
import {
|
|
9
|
+
import {listWorkflowRunJobSummaries, listWorkflowRuns} from '#db/index.js';
|
|
10
|
+
import {toRunListItemDto} from '#presentation/dto/index.js';
|
|
11
11
|
import {requireProjectAccess} from './project-access.js';
|
|
12
12
|
|
|
13
13
|
export function listRunsRoute(projects: ProjectsModuleClient) {
|
|
@@ -54,6 +54,11 @@ export function listRunsRoute(projects: ProjectsModuleClient) {
|
|
|
54
54
|
filters,
|
|
55
55
|
includeTotal: !decodedCursor,
|
|
56
56
|
});
|
|
57
|
+
// Paired with the attempt this read returned, so a re-run landing mid-request cannot
|
|
58
|
+
// pair one attempt's metadata with another's jobs.
|
|
59
|
+
const jobsByRun = await listWorkflowRunJobSummaries(
|
|
60
|
+
result.runs.map((run) => ({id: run.id, currentAttempt: run.currentAttempt})),
|
|
61
|
+
);
|
|
57
62
|
|
|
58
63
|
logger().info(
|
|
59
64
|
{
|
|
@@ -71,7 +76,7 @@ export function listRunsRoute(projects: ProjectsModuleClient) {
|
|
|
71
76
|
);
|
|
72
77
|
|
|
73
78
|
return {
|
|
74
|
-
runs: result.runs.map((run) =>
|
|
79
|
+
runs: result.runs.map((run) => toRunListItemDto(run, jobsByRun.get(run.id))),
|
|
75
80
|
next_cursor: result.nextCursor ? encodeTimestampIdCursor(result.nextCursor) : null,
|
|
76
81
|
filtered_total_count: result.filteredTotalCount,
|
|
77
82
|
};
|
|
@@ -215,6 +215,31 @@ describe('POST /runs/jobs/current/steps/:stepId/report', () => {
|
|
|
215
215
|
expect(attempt?.exitCode).toBe(0);
|
|
216
216
|
});
|
|
217
217
|
|
|
218
|
+
test('persists dedicated checkout details alongside user output', async () => {
|
|
219
|
+
const {jobId, steps} = await arrangeJobWithSteps(1);
|
|
220
|
+
const token = await mintActiveLeaseToken({jobId});
|
|
221
|
+
await nextStepForJob(jobId);
|
|
222
|
+
const checkout = {
|
|
223
|
+
repository: 'https://github.com/acme/api.git',
|
|
224
|
+
ref: 'refs/pull/412/head',
|
|
225
|
+
commit: '9f2c000000000000000000000000000000000000',
|
|
226
|
+
path: '/runner/workspace/job-1',
|
|
227
|
+
};
|
|
228
|
+
const res = await app.inject({
|
|
229
|
+
method: 'POST',
|
|
230
|
+
url: reportUrl(steps[0]?.id as string),
|
|
231
|
+
headers: {authorization: `Bearer ${token}`},
|
|
232
|
+
payload: reportPayload({
|
|
233
|
+
status: 'succeeded',
|
|
234
|
+
output: {artifact: 'dist/app.tgz', checkout: 'user-value'},
|
|
235
|
+
checkout,
|
|
236
|
+
exit_code: 0,
|
|
237
|
+
}),
|
|
238
|
+
});
|
|
239
|
+
expect(res.statusCode).toBe(200);
|
|
240
|
+
const [attempt] = await getStepAttempts(jobId);
|
|
241
|
+
expect(attempt?.output).toEqual({artifact: 'dist/app.tgz', checkout});
|
|
242
|
+
});
|
|
218
243
|
test('rejects a failed report without an error', async () => {
|
|
219
244
|
const {jobId, steps} = await arrangeJobWithSteps(1);
|
|
220
245
|
const token = await mintActiveLeaseToken({jobId});
|
|
@@ -12,7 +12,7 @@ export function createReportStepRoute(runners: RunnersInterModuleClient) {
|
|
|
12
12
|
method: 'POST',
|
|
13
13
|
path: '/steps/:stepId/report',
|
|
14
14
|
description:
|
|
15
|
-
'Reports whether a step succeeded or failed. The job is identified by the access token. Reporting the same step more than once is safe: once a step has finished, later reports for it are ignored. The runner does not call a separate job-completion endpoint
|
|
15
|
+
'Reports whether a step succeeded or failed. The job is identified by the access token. Reporting the same step more than once is safe: once a step has finished, later reports for it are ignored. The runner does not call a separate job-completion endpoint: finalization is driven server-side from the recorded step results, and the `cancel` flag tells the runner to stop once the job has finished without full success.',
|
|
16
16
|
schema: {
|
|
17
17
|
params: z.object({stepId: z.string().uuid()}),
|
|
18
18
|
body: reportStepBodySchema,
|
|
@@ -45,12 +45,20 @@ export function createReportStepRoute(runners: RunnersInterModuleClient) {
|
|
|
45
45
|
throw new ClientError('Job lease is no longer active', 'lease-not-active', {status: 404});
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
// Checkout is a reserved system field on the report wire contract. Keep
|
|
49
|
+
// it out of the runner's user output merge until this persistence
|
|
50
|
+
// boundary, where the system value has explicit precedence.
|
|
51
|
+
const output =
|
|
52
|
+
request.body.checkout === undefined
|
|
53
|
+
? (request.body.output ?? null)
|
|
54
|
+
: {...(request.body.output ?? {}), checkout: request.body.checkout};
|
|
55
|
+
|
|
48
56
|
const outcome = await recordStepResult({
|
|
49
57
|
jobExecutionId: leasedJob.jobExecutionId,
|
|
50
58
|
stepId,
|
|
51
59
|
status: request.body.status,
|
|
52
60
|
error: fromStepErrorDto(request.body.error),
|
|
53
|
-
output
|
|
61
|
+
output,
|
|
54
62
|
response: request.body.response ?? null,
|
|
55
63
|
exitCode: request.body.exit_code ?? request.body.error?.exit_code ?? null,
|
|
56
64
|
logOutcome: request.body.log_outcome,
|
|
@@ -7,7 +7,7 @@ import {isWorkflowNotFound} from '#temporal/workflow-not-found.js';
|
|
|
7
7
|
// Per-step execution finishes a job inside recordStepResult (no runner /complete
|
|
8
8
|
// call), which enqueues WORKFLOWS_JOB_STEPS_SETTLED in the same transaction. The
|
|
9
9
|
// persisted per-step projection is already terminal, so the workflow only flips
|
|
10
|
-
// the job status
|
|
10
|
+
// the job status: no steps are carried.
|
|
11
11
|
export async function onJobStepsSettled(payload: WorkflowsJobStepsSettledEventDto): Promise<void> {
|
|
12
12
|
logger().info(
|
|
13
13
|
{
|
|
@@ -2,7 +2,20 @@ import {getJobExecutionsByJobId, getJobsByWorkflowRunId} from '#db/index.js';
|
|
|
2
2
|
import {workflowRunFactory} from '#test/index.js';
|
|
3
3
|
import {onRunnerJobClaimed} from './on-runner-job-claimed.js';
|
|
4
4
|
|
|
5
|
+
const signalMock = vi.fn();
|
|
6
|
+
const getHandleMock = vi.fn(() => ({signal: signalMock}));
|
|
7
|
+
|
|
8
|
+
vi.mock('@shipfox/node-temporal', () => ({
|
|
9
|
+
temporalClient: () => ({workflow: {getHandle: getHandleMock}}),
|
|
10
|
+
}));
|
|
11
|
+
|
|
5
12
|
describe('onRunnerJobClaimed', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
getHandleMock.mockClear();
|
|
15
|
+
signalMock.mockReset();
|
|
16
|
+
signalMock.mockResolvedValue(undefined);
|
|
17
|
+
});
|
|
18
|
+
|
|
6
19
|
it('stamps started_at on the job execution from the claim event payload', async () => {
|
|
7
20
|
const run = await workflowRunFactory.create();
|
|
8
21
|
const job = (await getJobsByWorkflowRunId(run.id))[0];
|
|
@@ -23,6 +36,11 @@ describe('onRunnerJobClaimed', () => {
|
|
|
23
36
|
|
|
24
37
|
const after = (await getJobExecutionsByJobId(job.id))[0];
|
|
25
38
|
expect(after?.startedAt?.getTime()).toBe(claimedAt.getTime());
|
|
39
|
+
expect(getHandleMock).toHaveBeenCalledWith(`job:${job.id}`);
|
|
40
|
+
expect(signalMock).toHaveBeenCalledWith('job-claimed', {
|
|
41
|
+
jobExecutionId: jobExecution.id,
|
|
42
|
+
claimedAt: claimedAt.toISOString(),
|
|
43
|
+
});
|
|
26
44
|
});
|
|
27
45
|
|
|
28
46
|
it('is idempotent: a redelivered event keeps the first started_at (coalesce)', async () => {
|
|
@@ -54,4 +72,35 @@ describe('onRunnerJobClaimed', () => {
|
|
|
54
72
|
const after = (await getJobExecutionsByJobId(job.id))[0];
|
|
55
73
|
expect(after?.startedAt?.getTime()).toBe(first.getTime());
|
|
56
74
|
});
|
|
75
|
+
|
|
76
|
+
it('discards a claim signal when the job workflow already terminated', async () => {
|
|
77
|
+
const notFound = new Error('gone');
|
|
78
|
+
notFound.name = 'WorkflowNotFoundError';
|
|
79
|
+
signalMock.mockRejectedValueOnce(notFound);
|
|
80
|
+
|
|
81
|
+
await expect(
|
|
82
|
+
onRunnerJobClaimed({
|
|
83
|
+
workflowRunId: crypto.randomUUID(),
|
|
84
|
+
workflowRunAttemptId: crypto.randomUUID(),
|
|
85
|
+
jobId: crypto.randomUUID(),
|
|
86
|
+
jobExecutionId: crypto.randomUUID(),
|
|
87
|
+
claimedAt: '2026-06-22T10:05:00.000Z',
|
|
88
|
+
}),
|
|
89
|
+
).resolves.toBeUndefined();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('rethrows a transient Temporal signal failure for subscriber retry', async () => {
|
|
93
|
+
const failure = new Error('temporal unavailable');
|
|
94
|
+
signalMock.mockRejectedValueOnce(failure);
|
|
95
|
+
|
|
96
|
+
await expect(
|
|
97
|
+
onRunnerJobClaimed({
|
|
98
|
+
workflowRunId: crypto.randomUUID(),
|
|
99
|
+
workflowRunAttemptId: crypto.randomUUID(),
|
|
100
|
+
jobId: crypto.randomUUID(),
|
|
101
|
+
jobExecutionId: crypto.randomUUID(),
|
|
102
|
+
claimedAt: '2026-06-22T10:05:00.000Z',
|
|
103
|
+
}),
|
|
104
|
+
).rejects.toBe(failure);
|
|
105
|
+
});
|
|
57
106
|
});
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type {RunnerJobClaimedEvent} from '@shipfox/api-runners-dto';
|
|
2
2
|
import {logger} from '@shipfox/node-opentelemetry';
|
|
3
|
+
import {temporalClient} from '@shipfox/node-temporal';
|
|
3
4
|
import {recordJobExecutionStartedAt} from '#db/index.js';
|
|
5
|
+
import {JOB_CLAIMED_SIGNAL} from '#temporal/constants.js';
|
|
6
|
+
import {isWorkflowNotFound} from '#temporal/workflow-not-found.js';
|
|
4
7
|
|
|
5
8
|
// Anticorruption layer: the runner reports a `claimed` fact in its own lease-broker
|
|
6
9
|
// language; the run lifecycle treats the claim as the job's start, so we project it onto
|
|
@@ -20,4 +23,23 @@ export async function onRunnerJobClaimed(payload: RunnerJobClaimedEvent): Promis
|
|
|
20
23
|
jobExecutionId: payload.jobExecutionId,
|
|
21
24
|
startedAt: new Date(payload.claimedAt),
|
|
22
25
|
});
|
|
26
|
+
|
|
27
|
+
const handle = temporalClient().workflow.getHandle(`job:${payload.jobId}`);
|
|
28
|
+
try {
|
|
29
|
+
await handle.signal(JOB_CLAIMED_SIGNAL, {
|
|
30
|
+
jobExecutionId: payload.jobExecutionId,
|
|
31
|
+
claimedAt: payload.claimedAt,
|
|
32
|
+
});
|
|
33
|
+
} catch (err) {
|
|
34
|
+
// A terminal execution can race the claim outbox delivery. Its persisted status is
|
|
35
|
+
// authoritative, so discard the signal if Temporal has already closed the workflow.
|
|
36
|
+
if (isWorkflowNotFound(err)) {
|
|
37
|
+
logger().debug(
|
|
38
|
+
{jobId: payload.jobId, jobExecutionId: payload.jobExecutionId},
|
|
39
|
+
'Job workflow already terminated; claim event discarded',
|
|
40
|
+
);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
23
45
|
}
|
|
@@ -287,6 +287,7 @@ export function createDrainListenerEventsActivity(clients: {
|
|
|
287
287
|
agent: AgentInterModuleClient;
|
|
288
288
|
integrations?: IntegrationsModuleClient | undefined;
|
|
289
289
|
projects?: ProjectsModuleClient | undefined;
|
|
290
|
+
secrets: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'>;
|
|
290
291
|
}) {
|
|
291
292
|
return async function drainListenerEventsActivity(params: {
|
|
292
293
|
jobId: string;
|
|
@@ -2,5 +2,6 @@ export const WORKFLOWS_TASK_QUEUE = 'workflows-orchestrator';
|
|
|
2
2
|
export const RUN_CANCEL_SIGNAL = 'run-cancel';
|
|
3
3
|
export const JOB_FINISHED_SIGNAL = 'job-finished';
|
|
4
4
|
export const JOB_LEASE_EXPIRED_SIGNAL = 'job-lease-expired';
|
|
5
|
+
export const JOB_CLAIMED_SIGNAL = 'job-claimed';
|
|
5
6
|
export const LISTENER_EVENTS_AVAILABLE_SIGNAL = 'events-available';
|
|
6
7
|
export const LISTENER_RESOLVE_SIGNAL = 'resolve';
|
package/src/temporal/index.ts
CHANGED