Skip to main content

Order jobs with dependencies

Dependencies control when each job runs: a job waits until everything it depends on is satisfied. Use them to sequence work (run B after A succeeds), coordinate shared limits, or run recovery steps when something fails.

What this solves

Jobs that only run on a timer either start before the data they need is ready, or plough ahead after an upstream step has failed, producing wrong results that no one catches until much later.

Dependency types​

TypeA job waits until…
JobA predecessor job behaves as you require — set by its Condition and Type (below), optionally from another day.
ThresholdA named threshold compares as you require against a value — pick the comparison as well as the number.
ResourceEnough of a named resource is free (the job reserves it).
ExpressionA custom expression renders True — see Gate a job on an expression.

Condition and Type​

A job dependency has two settings that work together:

  • Condition — which result satisfies it: Finished OK, Failed, or Any.
  • Type — what happens when the predecessor isn't scheduled for the day:
    • Requires (the default) — the job waits. Use it when the predecessor must run.
    • After — the job proceeds without it. Use it for "run after this if it runs" ordering.

When the predecessor is scheduled, both Types wait for it to reach the Condition. The difference only shows when the predecessor is absent that day.

"Isn't scheduled" covers three cases, and the dependency card names them: the predecessor's frequency didn't fire for the date, the predecessor's Disabled switch is on, or it isn't defined in the workflow. A Requires dependency on any of them waits until an Operator adds that predecessor to the run.

Add a dependency​

To add a dependency to a job, complete the following steps:

  1. In the job editor, open the Dependencies tab.
  2. Add a dependency and choose its type (job, threshold, resource, or expression).
  3. For a job dependency:
    • Choose the predecessor's Workflow — the current workflow or another one — then its Job Name.
    • Set the Condition (Finished OK, Failed, or Any).
    • Set the Type (Requires or After).
    • Set a Days Offset if it depends on another day's run: 0 is the same day, −1 the previous day, +1 the next day.
  4. For a threshold dependency, choose the threshold, the comparison — equal to, not equal to, less than, greater than, or either of the "or equal to" forms — and the value. For a resource dependency, choose the resource and the amount required.
  5. For an expression dependency, write the expression — see below.
  6. Select Save & Close.

A job can't depend on itself on the same day. Depending on the same job in the same workflow at offset 0 is rejected on save. A non-zero offset is fine — it points at that job's own previous or next day's run.

Getting to the other workflow from the canvas

A dependency on a job in another workflow draws its own card on the Design canvas — the job name on the first line, the workflow it lives in on the second — with an edge into the job that waits on it. Select that card to open the other workflow in a new tab, so you can check the predecessor without going back to the workflow list. Enter or Space does the same when the card has focus.

The card is display-only otherwise: edit the dependency on the Dependencies tab. If the cards get in the way, turn External Jobs off under Card Filters in the sidebar. See A cross-workflow predecessor on the Design canvas.

Gate a job on an expression​

An expression dependency holds the job until your expression renders True. The job waits at Waiting on expression, and the platform re-asks about once a second until it does.

Expression dependencies only started working in this release

A job authored with one used to wait there forever — and because a workflow can't close while a job is still waiting, it held the whole run open, with nothing saying why. If you have a job in that state, or gave up on this dependency type in the past, it works now.

Three rules decide whether your expression does what you meant:

  • Only True or False answers the gate (case doesn't matter). A number does not: an expression that renders 1 does not open the gate, it puts the job on hold. Write a comparison — [[= [[OI.BatchReady]] == "Y" ]] — so it renders True.
  • A job's expressions are joined with && and read as one expression. Parenthesize any half that contains ||, or better, put the whole condition in a single expression dependency.
  • An expression that can't be evaluated holds the job, with the reason recorded against it — there is no quiet fallback, because text that happened to read True would open the gate. A misspelled property name is enough to trigger this, so check the names before you rely on it.
Don't gate a job on its estimated run time

JI.$EST RUN TIME reads nothing on a job the build produced, so an expression using it holds the job until someone sets Estimated Run Time on that job instance by hand. Other job facts are available; see Which run facts an expression can read.

If a job is on hold with a reason naming your expression, fix the expression and release the job. See Expression dependencies for the full set of outcomes.

What counts as success, failure, or any​

For a job dependency, each Condition maps to more than one outcome:

ConditionThe predecessor is satisfied when it…
successFinished OK, including when it was marked finished OK, fixed, or skipped.
failureFailed, including a marked-failed, an initialization error, or a job flagged under review.
anyReached either a success or a failure result (above). It does not mean "any outcome."

A cancelled or missed job never releases its dependents. If a predecessor is cancelled or misses its start time, it never produced a result, so a dependent (even one set to any) keeps waiting. That's intended. If you see a job stuck waiting on a predecessor that was cancelled or missed, clear it from Processes with Force Start or Skip, or fix the upstream job.

Good to know
  • A job runs only when all its dependencies are satisfied.
  • Depending on failure or any is a valid pattern. For example, a cleanup job runs only when its predecessor fails.
  • If a job waits on a day the predecessor isn't scheduled, its Type is Requires. Switch it to After when the predecessor is optional.
  • A resource dependency makes a job wait for capacity, so use it to keep too many jobs from running at once against a shared system.
Dependencies stay inside one schedule instance

If the workflow builds as several named schedule instances — one run per branch, say — a dependency between two of its jobs is scoped to the instance it is running in. BRANCH1's job waits on BRANCH1's predecessor, not on BRANCH2's, so you author the sequence once and every branch gets its own copy of it.

If two branches genuinely contend for one shared system, that's what a Resource dependency is for — resources span instances.

Renaming a job your other workflows depend on

A dependency remembers which job it points at, not just the name — so renaming a job does not break the workflows that depend on it.

There is one step to finish, though: the dependent workflow's own copy of the name is brought up to date the next time that workflow is saved. So after renaming a job that other workflows depend on, open each of those workflows, save it, and create a new version. Until you do, the version they build from still names the job as it used to be called.

Two related points while you are in there:

  • Editing the predecessor name on a dependency card no longer re-points it. The remembered identity wins. To aim a dependency at a different job, re-pick the predecessor rather than retyping its name.
  • A conflict authored against a name prefix is the exception — a prefix matches a set of jobs, so there is no single job to remember. Those keep working by name alone.
A job cannot wait on itself on the same day

Pointing a job at itself with a day offset of 0 is flagged on the dependency card as you author it, and the save is blocked — you will see it immediately rather than when you try to save. A self-reference at a non-zero offset is legitimate: it points at the job’s own run on another date.

Related topics