Re-run a completed workflow run
POST/api/workflow-runs/{run_id}/rerun
rerunWorkflowRun
Creates a fresh attempt of a finished (succeeded / failed / cancelled) run: a NEW run that keeps the source's `run_number`, increments `attempt`, and pins the same workflow snapshot, cause and trigger commit. Trust is inherited — a re-run of an unapproved fork PR run is held `pending_approval` again. Requires write access on the run's repo. 409 while the source run is still active.
Authentication is not described for this operation in the spec — that does not mean it is public. Check tokens and scopes.
curl
curl -X POST 'https://neosource.dev/api/workflow-runs/RUN_ID/rerun'fetch
fetch("https://neosource.dev/api/workflow-runs/RUN_ID/rerun", {
method: "POST",
});neo
neo actions rerun RUN_IDPath parameters
run_idrequired
Responses
201New attempt enqueued
application/json
403Forbidden — one of: forbidden, needs_scope
application/json
Standard errors
Bodies documented once for the whole API — see standard errors.
- 400Bad Request — one of: invalid_input
- 404Not Found — one of: not_found
- 409Conflict — one of: already_exists, conflict
- 429Rate limited — retry after the `Retry-After` header
- 500Internal server error
- 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
- 504Gateway timeout — the request exceeded the server's handling budget
Schemas
Referenced above. Listed here rather than expanded inline, so the same definition is not repeated at every level.
WorkflowRunTestFailure
One failing test out of the run's `JUnit` report.
messageThe failure/error message attribute, when present.
namerequiredTest identity: `classname::name` when the report carries a classname, else the bare testcase name.
ResolvedToolchain
What the catalog answered, and what a re-run re-materializes.
artifactrequiredtoolrequiredCanonical tool name (aliases resolve to it), or the raw name for a passthrough installable.
variantDistribution/vendor where the tool has one (`temurin`, `zulu`, …).
versionrequiredThe concrete version. **Open vocabulary, deliberately `String`** — the set of version strings is unbounded by construction, so this is the documented exception to the closed-set-DTO-enum rule.
NixStorePath
An absolute, well-formed store path — `<root>/<hash>-<name>` for SOME valid [`NixStoreRoot`] — validated on construction AND on deserialize. **The grammar is a property of the VALUE, not a step some caller remembers.** `ToolArtifact::StorePath` is deserialized straight out of `workflow_runs.toolchain_manifest` jsonb and is the agent's whole authorization surface (`ToolchainManifest::has_store_path`), so a raw `String` there would let `/etc/passwd` answer "recorded" the moment it byte-matched a recorded entry, and would leave the grammar as the daemon's job alone. Validating in `Deserialize` too is the half that matters: an invariant that holds only for freshly-built values is not an invariant, and every value on this path arrives from a database. Deliberately ROOT-INDEPENDENT: whether a path is under the root *this* process serves is [`store_path_leaf`]'s question, and that root is env-configurable. This type answers the other one — is it shaped like a store path at all. Which means the grammar alone is NOT the authorization answer, and the doc must not be read as claiming it is: `/etc` is a root [`NixStoreRoot`] admits, so `/etc/<hash>-passwd` is a well-formed value of this type. Pinning a RECORDED artifact to the real store is [`crate::model::toolchain::StorePathArtifact::new`]'s clause, one layer up, where the recording happens.