Parallel Jobs with Dependencies

Structure GitHub Actions workflows with parallel and dependent jobs using the needs keyword. Covers fan-out/fan-in patterns, conditional jobs, and status checks.

Testing

Detailed Explanation

Parallel and Dependent Jobs

GitHub Actions runs jobs in parallel by default. The needs keyword creates dependencies between jobs, enabling fan-out (parallel) and fan-in (converging) patterns.

Workflow YAML

name: CI Pipeline

on:
  push:
    branches:
      - main

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

  type-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx tsc --noEmit

  build:
    needs: [lint, test, type-check]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: ./dist

  deploy:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: build-output
      - run: echo "Deploying..."

Pipeline Structure

lint ──────┐
test ──────├── build ── deploy
type-check ┘

The three check jobs (lint, test, type-check) run in parallel. The build job waits for all three to succeed. The deploy job runs only after a successful build and only on the main branch.

Key Patterns

  • Fan-out: Multiple jobs with no dependencies run simultaneously
  • Fan-in: A single job with needs: [job1, job2, job3] waits for all listed jobs
  • Conditional execution: if: github.ref == 'refs/heads/main' restricts jobs to specific branches
  • Artifact passing: upload-artifact and download-artifact transfer files between jobs

Job Status Functions

Use these in if conditions to handle failures gracefully:

  • success(): Default — runs only if all dependencies succeeded
  • failure(): Runs if any dependency failed (useful for notifications)
  • always(): Runs regardless of dependency status (useful for cleanup)
  • cancelled(): Runs only if the workflow was cancelled

Use Case

Structuring complex CI/CD pipelines with multiple independent checks that must all pass before deployment. Common in monorepos or projects with separate lint, test, and build stages that benefit from parallel execution.

Try It — GitHub Actions Workflow Builder

Open full tool