Since there are some new features explained here, I'd like to talk about a feature that I have introduced to Ascender: relaunching a failed workflow from the failed node. The PR is now merged (#406) and will ship in the next version.
What Is Relaunch-from-Failed?
Until now, relaunching a workflow job in Ascender meant re-running the entire workflow from the very first node. Every node ran again, whether it had succeeded or not. My feature adds an option to relaunch a workflow from the point where it broke when a node fails or the workflow is canceled.
In this new option, only the unsuccessful node and everything downstream of it runs again. The nodes that already succeeded in the first run are not re-run; they're carried forward as already-complete, with their results intact.
You can trigger this from the same relaunch icon that you use today. A failed/errored/canceled workflow now offers a small menu: Relaunch from → First node / Failed node / Canceled node. "First node" is the classic full relaunch you already know; "Failed node" is the new behavior. It's available both in the Jobs list and on the workflow Output toolbar.
The Problem It Solves
Picture a workflow: build → test → deploy-east → deploy-west → notify. The build node takes 25 minutes. Everything sails through until deploy-west, which fails because a host was briefly unreachable. You fix the host and want to try again.
Today, your only option is to relaunch the whole thing, which re-runs that 25-minute build and the tests and deploy-east, all of which already succeeded. That's wasted time, and you're repeating them for no reason.
With relaunch-from-failed, you pick Failed node, and Ascender re-runs only deploy-west and notify. The build, the tests, and deploy-east are shown as already-done and carried forward. You go from a 30-minute round trip to a 2-minute one.
It also handles the more subtle case where a failure changed the path the workflow took. Say a node failed and the DAG followed its failure edge into a remediation branch. On a relaunch-from-failed, that node now succeeds, so the old failure branch is abandoned and the workflow follows the success path instead, exactly as if it had succeeded the first time. The result is a workflow that actually completes, not one stuck replaying its old wrong turn.
How It Works Under the Hood
When you relaunch from the failed node, Ascender rebuilds the workflow job but tags every node whose job succeeded in the prior run as carried forward. For that, I added two new fields on the workflow node to record this:
- prior_run_succeeded
- prior_run_elapsed
A carried-forward node spawns no job at all. The scheduler treats it as a successful parent: its success and always edges are traversed as though the job had just finished green, so the re-run picks up cleanly at the right place.
The node keeps its prior elapsed time so the UI can show what it took, and, importantly, it carries its set_stats artifacts forward into the downstream nodes' ancestor artifacts. That last part matters because a carried node has no job of its own to read stats from; without it, any set_stats a succeeded node produced would be invisible to the re-run nodes.
The DAG pruning is still fully in charge. A carried node is not exempt from "do not run": if the branch that reached it is no longer taken this time around (because a re-run parent now succeeds instead of failing), that node and its subtree are pruned just like any other unreachable node. This is what keeps the workflow from getting stuck.
Everything else about a relaunch is preserved: it reuses the same copy_unified_job path as a normal relaunch, so survey answers and passwords, credentials, limit, prompts, and extra_vars all carry over the way you'd expect. In the UI, carried nodes render green with their prior elapsed time, the running node shows a blue frame with a live timer, canceled nodes are orange, and each node's elapsed time appears the moment it finishes.
What It Does Not Do
Sliced workflow jobs can't be relaunched from failed. A sliced job isn't a workflow you authored; it's one Ascender generates for you, fanning a single job template out into one parallel slice per chunk of the inventory, with no success/failure/always edges between the slices the way a real workflow has.
The whole carry-forward-and-prune model that powers relaunch-from-failed assumes that authored DAG structure, so it simply doesn't map onto a pile of independent slices, and forcing it would produce confusing or wrong results. Rather than guess, Ascender rejects the request outright with a clear message, and you fall back to a normal relaunch.
A workflow that has nothing to re-run is rejected too. And there's an honest edge case: if a workflow failed because a reached node's job template was deleted, relaunching can't recover that, so you get a message saying so.
It's also not a substitute for fixing flapping infrastructure or non-deterministic playbooks; it re-runs from where things broke, it doesn't change why they broke. But for the everyday case of "one node failed, I fixed the cause, let me continue from there without redoing an hour of work," it's exactly the tool.