Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXLVII · Pipeline DependenciesDeclaration

needs and depends-on — declaring edges between jobs

Intermediate⏱ ~20 mingit

What you'll learn

  • Declare an edge in GitHub Actions with `needs:` and in GitLab CI with `needs:`
  • Distinguish a single-element list from a multi-element list and predict the scheduler behaviour
  • Recognise that the default semantics is "wait for successful completion"
  • Use `needs:` with `outputs:` to express a typed data contract between jobs

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

The needs: clause declares an edge in the pipeline DAG. The current job waits for every job listed in needs: to complete before starting. The list can be a single job or many.

needs in GitHub Actions

jobs:
  build:
    runs-on: ubuntu-latest
  test:
    runs-on: ubuntu-latest
    needs: build
  package:
    runs-on: ubuntu-latest
    needs: [build, test]
  deploy:
    runs-on: ubuntu-latest
    needs: package

A single predecessor can be a bare string or a one-element list; equivalent. Multiple predecessors must be a list. Default is to wait for successful completion.

needs in GitLab CI

package:
  stage: package
  needs: [unit, integration]
  script: make package

package:
  stage: package
  needs:
    - job: unit
      artifacts: true
    - job: integration
      artifacts: true
  script: make package

The first is a simple list; the second couples needs: with the artifact download.

Single versus multiple predecessors

A list of one means “wait for this job”. A list of many means “wait for all of these jobs”. The scheduler starts the current job when every predecessor has completed.

grep -B 1 'needs:' .github/workflows/ci.yml

Implicit completion states

The default waits for successful completion only. States: success, always, failure, cancelled. GitHub Actions uses if: always(); GitLab CI uses when: on_success / when: always.

Production discipline

  1. Declare needs: explicitly; absent is immediate.
  2. Use bare-string form for a single predecessor.
  3. Audit needs: for cycles.

Cross-course references

  • Ansible for Production Sysadmins - Part XXXVII uses the same pattern in AWX workflows.
  • Linux for Production Sysadmins - Part XXX uses the same edge for systemd Requires=.

Quiz

Knowledge check · 4 questions

  1. Q1. Job D has `needs: [A, B, C]`. What must be true before D starts?

  2. Q2. By default, a job with `needs: [predecessor]` waits for the predecessor to succeed; if the predecessor fails, the dependent job is skipped.

  3. Q3. In GitHub Actions, name the two equivalent ways to declare a single predecessor and explain why the artifact must be downloaded separately from `needs:`.

  4. Q4. Diagnose why a deploy runs without the package it is supposed to deploy.

    Team K: `build`, `package`, `deploy` jobs. `deploy` has no `needs:` but runs `actions/download-artifact` to fetch the package from `package`. Pipeline is green but deploy sometimes installs stale or missing package.

Passing score: 75%. Answers are checked in this browser.