Skip to content

feat: let a relaunch from failed nodes overwrite the workflow variables - #1050

Merged
cigamit merged 5 commits into
ctrliq:mainfrom
fernandorocagonzalez:feat-relaunch-overwrite-flow-vars
Sep 26, 2026
Merged

cigamit merged 5 commits into
ctrliq:mainfrom
fernandorocagonzalez:feat-relaunch-overwrite-flow-vars

Conversation

@fernandorocagonzalez

@fernandorocagonzalez fernandorocagonzalez commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

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 as ask_variables_on_launch: whoever administers the template decides whether people with execute permission may hand variables to a relaunch.

With it on:

POST /api/v2/workflow_jobs/N/relaunch/
{"nodes": "failed", "extra_vars": {"target_version": "1.4.2"}}

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_vars outrank the artifacts a parent node published with set_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 like allow_simultaneous is, 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:

Relaunch from:
  First node
  Failed node
  Failed node, new variables      <- new, only 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 --check is 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.ts carries 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.

@cigamit cigamit self-assigned this Sep 22, 2026
@cigamit cigamit added the enhancement New feature or request label Sep 22, 2026
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.
@cigamit
cigamit force-pushed the feat-relaunch-overwrite-flow-vars branch from 302fd1e to 6f8f752 Compare September 22, 2026 15:28
@cigamit
cigamit requested a balanced review from Copilot September 22, 2026 15:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Medium severity · 1 Low severity

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.

Comment thread ascender/api/views/workflow.py Outdated
Comment thread ascender/main/models/workflow.py Outdated
Comment thread ascender/main/models/workflow.py Outdated
Comment thread ascender/api/templates/api/workflow_job_relaunch.md Outdated
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.
@cigamit

cigamit commented Sep 25, 2026

Copy link
Copy Markdown
Collaborator

Everything is working as expected. There is one thing I did notice though.

If you have a WF that you send
color: red
and you relaunch the WF with
color: blue
it properly runs that job with that color, but if you then click the relaunch on that WF, it sends the original
color: red

cigamit and others added 2 commits September 25, 2026 13:17
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.
@fernandorocagonzalez

Copy link
Copy Markdown
Contributor Author

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.
@cigamit
cigamit merged commit fd84087 into ctrliq:main Sep 26, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Development

Successfully merging this pull request may close these issues.

3 participants