Feature Specification: Execution of Deployment Jobs
Created: 2026-09-23
Status: Implemented
Input: Reconstructed from the code of api/ at 0bf4ecd36, api/specification.md, pull requests #1184 and #1678, and the design notes of the maintainers.
User Scenarios & Testing (mandatory)
User Story 1 - Run a deployment program of core as a job (Priority: P1)
For each build, api runs a deployment program of core with the configuration of the build. With a job runner (Windmill), it submits a job. Without one, it runs a local subprocess. api gives the program the environment that core declares for it, and nothing else from the caller.
Why this priority: this is how a configuration becomes a deployment.
Independent Test: a VM test of a full deployment: the job deploys the configuration and the build succeeds.
Acceptance Scenarios:
- Given a job runner, When a build starts, Then
apisubmits a job and stores its job identifier. - Given no job runner, When a build starts, Then
apiruns the program as a local subprocess. - Given a program that fails, When the job ends, Then the build fails and the log shows the error.
User Story 2 - Keep deployments apart (Priority: P1)
Each deployment has its own namespace for names and its own state address in the state backend. api derives them from the deployment, so two deployments cannot change the resources of each other.
Independent Test: unit tests and a check of the job environment: the state address of a job is scoped to its deployment.
Acceptance Scenarios:
- Given a state backend, When a job starts, Then its state address is the base address plus the namespace of the deployment.
User Story 3 - Stream progress to clients (Priority: P2)
api forwards the events of a running job to the events service, on the channel of the deployment and of the build.
Acceptance Scenarios:
- Given a running job, When the job writes progress, Then the subscribed clients get the events.
Edge Cases
apirestarts while a local subprocess runs: the build is marked failed at the next start. A job of the job runner continues, because the job runner owns it.- The deployment attribute does not exist in the source, or the eval of the deployment refuses the configuration: the submit fails before a job starts.
Requirements (mandatory)
Functional Requirements
- FR-001:
apiMUST run deployment programs only through the public outputs ofcore(deployment attributes and the environment keys that each declares). - FR-002:
apiMUST pass to a job only the variables thatcoredeclares, plus the variables of Nix and OpenTofu that the program needs. - FR-003:
apiMUST scope the names and the state address of each job to its deployment. - FR-004:
apiMUST work with and without a job runner. - FR-005:
apiand the jobs MUST use one shared runner fornixsubprocesses.coreholds it, and the package ofapiincludes it.
Key Entities
- Deploy configuration: the provider setting that names the deployment root, attribute, executable and limits.
- Job: one run of a deployment program for one build.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: A VM test of a full deployment passes with the job runner.
- SC-002: No job gets a variable that
coredoes not declare, other than the Nix and OpenTofu variables.
Assumptions
- The job runner and the state backend are services of the provider.
apigets their addresses as configuration. apihas no default deployment program. The provider configures the program, and theapiREADME documents the configuration of the fediversity hosting provider.
Known Deviations
None.