Repository navigation
feat: let a relaunch from failed nodes overwrite the workflow variables - #1050
Conversation
Relaunching from the failed node carries everything the original run used, variables included. That is usually what you want, but not when a node that finished successfully left a wrong value behind: the same value comes back on every relaunch and the workflow cannot get past it without starting over. Workflow job templates gain allow_overwrite_flow_vars_on_relaunch, off by default. With it on, POST to a workflow job's relaunch endpoint accepts extra_vars alongside nodes=failed, and those variables are merged over the ones copied from the original run: a key that is sent replaces its value, a key that is not is left alone, and a key the run never had is added. Workflow variables outrank the artifacts a parent node published, so this is also how a bad set_stats value gets corrected. The flag lives on WorkflowJobOptions, so the job records the setting it was launched with and the relaunch endpoint reads it off the run rather than off a template that may have changed since. Variables are only accepted together with nodes=failed, since a plain relaunch has the launch prompts for this. Answers the survey defines are validated as they are on launch, and password answers are stored encrypted, with $encrypted$ meaning "keep what the run used". In the UI the relaunch dropdown gains a second from-failed entry when the template allows it. It opens the run's variables in an editor, so the value to correct is there to edit, and relaunches with whatever is left in the box.
302fd1e to
6f8f752
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Non-mapping inputs and password-placeholder handling have correctness gaps that can accept invalid payloads or silently discard legitimate values.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 4
Open (5)
What changed in this PR
Adds opt-in variable overrides when relaunching workflow jobs from failed nodes.
Changes:
- Adds persisted template/job configuration and API merge validation.
- Adds UI configuration, variable editor, and relaunch action.
- Adds backend/UI tests, API types, documentation, and translations.
| File | Description |
|---|---|
ascender/ui/src/util/jobs.ts |
Detects overwrite capability. |
ascender/ui/src/types/api.generated.ts |
Adds generated API fields. |
ascender/ui/src/screens/Template/WorkflowJobTemplateEdit/WorkflowJobTemplateEdit.test.tsx |
Updates form expectations. |
ascender/ui/src/screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.tsx |
Displays the enabled option. |
ascender/ui/src/screens/Template/shared/WorkflowJobTemplateForm.tsx |
Adds the configuration checkbox. |
ascender/ui/src/screens/Template/shared/WorkflowJobTemplate.helptext.tsx |
Adds checkbox guidance. |
ascender/ui/src/screens/Job/WorkflowOutput/WorkflowOutputToolbar.tsx |
Enables variable relaunch from output. |
ascender/ui/src/locales/zh/messages.po |
Updates Chinese message catalog. |
ascender/ui/src/locales/es/messages.po |
Updates Spanish message catalog. |
ascender/ui/src/locales/en/messages.po |
Updates English message catalog. |
ascender/ui/src/components/LaunchButton/WorkflowRelaunchVariablesModal.tsx |
Adds the variable editor modal. |
ascender/ui/src/components/LaunchButton/WorkflowRelaunchVariablesModal.test.tsx |
Tests modal behavior. |
ascender/ui/src/components/LaunchButton/WorkflowReLaunchDropDown.tsx |
Adds variable-aware relaunch choices. |
ascender/ui/src/components/LaunchButton/WorkflowReLaunchDropDown.test.tsx |
Tests dropdown behavior. |
ascender/ui/src/components/JobList/JobListItem.tsx |
Enables the action in job lists. |
ascender/main/tests/functional/models/test_workflow.py |
Tests model copying and merging. |
ascender/main/tests/functional/api/test_workflow_job.py |
Tests API validation and encryption. |
ascender/main/models/workflow.py |
Implements persistence, validation, and merging. |
ascender/main/migrations/0220_workflow_allow_overwrite_flow_vars_on_relaunch.py |
Adds template and job fields. |
ascender/api/views/workflow.py |
Accepts relaunch variable overrides. |
ascender/api/templates/api/workflow_job_relaunch.md |
Documents relaunch parameters. |
ascender/api/serializers/workflow.py |
Exposes the new setting. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Copilot review of ctrliq#1050. A payload that is not a mapping but is falsy — `[]`, `false`, `null` — was turned into `{}` before it ever reached the parser, so the endpoint answered 201 and ignored it. The parser sees whatever was sent now, and only an absent field means "no variables". `$encrypted$` was treated as "keep the stored value" for every key, so it skipped survey validation on a text or multiple-choice answer, and a plain variable whose value happens to be that string was silently dropped instead of set. It now means that for survey passwords only, both the ones the run recorded and the ones the template asks for today, in case the survey changed since the run. Anywhere else it is refused as a reserved word, which is what a launch does with it. The variables editor handed a parsed sequence straight to the relaunch, which the API then refused with the modal already closed. It says so inline instead, with the document still open. The relaunch endpoint documentation said the setting is read from the workflow job template; it is read from the run, which copies it at launch. Spelled that out, along with what happens to runs started before the template was changed. Also: the new dropdown entry opens a modal, so it closes the menu behind it, and a test covers that an overwritten variable reaches the node that runs again and outranks what a parent node published with set_stats.
|
Everything is working as expected. There is one thing I did notice though. If you have a WF that you send |
A plain relaunch rebuilds the job from its launch config rather than from its extra_vars. The overrides only went into extra_vars, so relaunching the run that got color: blue brought back the original color: red. Write them into the launch config as well.
|
Good catch, A plain relaunch rebuilds the job from its launch config, not from its extra_vars, and the overrides were only going into extra_vars. |
Keeping the overrides in the launch config made a later relaunch by anyone but a superuser fail with "prompts no longer accepted" whenever the template does not prompt for variables, which is the usual case for this option. While the template still allows the overwrite, those variables are not prompts it stopped accepting: whoever can relaunch could send them anyway.


What this is for
Relaunch from the failed node (#406) carries the whole original run forward, variables included. That is normally what you want, but it falls down in one case we keep hitting: a node that finished successfully left a wrong value behind. The workflow stops downstream, and every relaunch from the failed node feeds it the same wrong value again. The only way out today is launching the whole workflow from scratch, which is exactly what relaunch-from-failed exists to avoid.
The setting
Workflow job templates get
allow_overwrite_flow_vars_on_relaunch, off by default. It is opt-in per template, the same trust boundary asask_variables_on_launch: whoever administers the template decides whether people with execute permission may hand variables to a relaunch.With it on:
The variables are merged over the ones copied from the original run. A key that is sent replaces its value, a key that is not is left alone, and a key the run never had is added. That last part matters: workflow
extra_varsoutrank the artifacts a parent node published withset_stats, so this is also how a bad artifact value gets corrected without re-running the node that produced it.The flag lives on
WorkflowJobOptions, so it is copied to the job at launch likeallow_simultaneousis, and the relaunch endpoint reads it off the run rather than off a template that may have been edited since. A run started before the setting was turned on keeps the answer it was launched with.Variables are only accepted together with
nodes=failed. A plain relaunch already has the launch prompts for this, and from-failed is the one path with no other way in.Answers the survey defines are validated the same way a launch validates them, so a relaunch cannot slip an invalid choice past the survey. Password answers are stored encrypted exactly as a launch stores them, and
$encrypted$means "keep the value the run used".In the UI
The relaunch dropdown gains a second from-failed entry when the template allows it:
It opens the variables of the run being relaunched in an editor, so the value that has to change is right there to edit, and relaunches with whatever is left in the box. The template form gets the checkbox, under Options next to Concurrent Jobs, and the template detail lists it.
Tests
Backend: the merge (replace, keep, add), the two refusals (no flag, no
nodes=failed), a payload that is not a mapping, survey validation of an overwritten answer, survey passwords kept and replaced, and that launching carries the flag from the template to the job.UI: the entry is hidden unless the template allows it, the modal opens on the run's variables and relaunches with them, an empty run, variables that are not a mapping, and cancelling.
Migration 0220 adds the field to both tables.
makemigrations --checkis clean.Note on CI
Rebased onto main now that #1049 has landed, so the checks that were red for every branch opened after the Pendo removal are green again here.
api.generated.tscarries only the six entries for the new field: the file was regenerated, and everything the generator produced beyond those entries was left out, so nothing unrelated rides along.