Skip to main content

Jobs and steps


Table of contents

  1. Execution architecture
  2. Job configuration
  3. Dependencies between jobs
  4. Step configuration
  5. Sharing data
  6. Practical exercises


1 - Execution architecture

Execution flow

Characteristics

ElementEnvironmentExecution
WorkflowRepositoryTriggered by an event
JobDedicated runnerParallel by default
StepSame runnerSequential

Isolation

jobs:
job1:
runs-on: ubuntu-latest # Runner A
steps:
- run: echo $HOME # /home/runner

job2:
runs-on: ubuntu-latest # Runner B (différent!)
steps:
- run: echo $HOME # /home/runner (autre machine)
Important

Each job runs on a different runner. Files are not shared between jobs.

🔝 Back to table of contents



2 - Job configuration

Complete structure

jobs:
build:
name: Build Application # Nom affiché
runs-on: ubuntu-latest # Runner

timeout-minutes: 30 # Timeout

permissions: # Permissions GITHUB_TOKEN
contents: read
packages: write

env: # Variables d'environnement
NODE_ENV: production

defaults: # Défauts pour les steps
run:
shell: bash
working-directory: ./src

steps:
- uses: actions/checkout@v4

Permissions

jobs:
build:
permissions:
contents: read # Lecture du repo
packages: write # Écriture packages
issues: write # Écriture issues
pull-requests: write # Écriture PR
id-token: write # OIDC token
PermissionUsage
contentsRead/write the repo
packagesGitHub Packages
issuesIssues and comments
pull-requestsPRs and reviews
id-tokenOIDC (cloud auth)

Concurrency

jobs:
deploy:
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: true

runs-on: ubuntu-latest
steps:
- run: ./deploy.sh

Environment

jobs:
deploy:
environment:
name: production
url: https://myapp.com

runs-on: ubuntu-latest
steps:
- run: echo "Deploying to production"

🔝 Back to table of contents



3 - Dependencies between jobs

needs

jobs:
build:
runs-on: ubuntu-latest
steps:
- run: npm run build

test:
needs: build # Attend que build soit terminé
runs-on: ubuntu-latest
steps:
- run: npm test

deploy:
needs: [build, test] # Attend build ET test
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh

Visualization

Conditions on needs

jobs:
build:
runs-on: ubuntu-latest
steps:
- run: npm run build

notify-success:
needs: build
if: success() # Seulement si build réussi
runs-on: ubuntu-latest
steps:
- run: echo "Build succeeded!"

notify-failure:
needs: build
if: failure() # Seulement si build échoué
runs-on: ubuntu-latest
steps:
- run: echo "Build failed!"

cleanup:
needs: build
if: always() # Toujours exécuté
runs-on: ubuntu-latest
steps:
- run: echo "Cleaning up..."

Outputs between jobs

jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- id: version
run: echo "version=1.0.${{ github.run_number }}" >> $GITHUB_OUTPUT

deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Deploying version ${{ needs.build.outputs.version }}"

🔝 Back to table of contents



4 - Step configuration

Types of steps

steps:
# Action depuis le Marketplace
- uses: actions/checkout@v4

# Action avec paramètres
- uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'

# Commande shell
- run: npm install

# Commande multi-lignes
- run: |
npm install
npm run build
npm test

# Action locale
- uses: ./.github/actions/my-action

Step options

steps:
- name: Install dependencies # Nom affiché
id: install # ID pour référencer
if: success() # Condition
continue-on-error: true # Ne pas échouer le job
timeout-minutes: 10 # Timeout
env: # Variables d'environnement
NODE_ENV: production
working-directory: ./app # Répertoire de travail
shell: bash # Shell à utiliser
run: npm install

Available shells

ShellOSCommand
bashLinux, macOSbash --noprofile --norc
shLinux, macOSsh -e
pwshAllPowerShell Core
powershellWindowsPowerShell Desktop
cmdWindowscmd /D /E:ON
pythonAllPython script
steps:
- name: Bash script
shell: bash
run: echo "Hello from bash"

- name: PowerShell script
shell: pwsh
run: Write-Host "Hello from PowerShell"

- name: Python script
shell: python
run: |
import os
print(f"Hello from Python on {os.name}")

🔝 Back to table of contents



5 - Sharing data

Between steps (same job)

jobs:
build:
runs-on: ubuntu-latest
steps:
# Méthode 1: Fichiers
- name: Create file
run: echo "data" > myfile.txt

- name: Read file
run: cat myfile.txt

# Méthode 2: Outputs
- name: Set output
id: step1
run: echo "result=success" >> $GITHUB_OUTPUT

- name: Use output
run: echo "${{ steps.step1.outputs.result }}"

# Méthode 3: Environment
- name: Set env
run: echo "MY_VAR=value" >> $GITHUB_ENV

- name: Use env
run: echo "$MY_VAR"

Between jobs (artifacts)

jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "content" > artifact.txt

- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: artifact.txt

test:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: my-artifact

- run: cat artifact.txt

Between jobs (outputs)

jobs:
job1:
runs-on: ubuntu-latest
outputs:
data: ${{ steps.generate.outputs.data }}
steps:
- id: generate
run: echo "data=hello" >> $GITHUB_OUTPUT

job2:
needs: job1
runs-on: ubuntu-latest
steps:
- run: echo "${{ needs.job1.outputs.data }}"

🔝 Back to table of contents



6 - Practical exercises

Exercise 1: Sequential pipeline

Create a build → test → deploy pipeline:

Solution
name: Pipeline

on: push

jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "Building..."

test:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Testing..."

deploy:
needs: test
runs-on: ubuntu-latest
steps:
- run: echo "Deploying..."

Exercise 2: Sharing outputs

Pass a version between two jobs:

Solution
name: Version

on: push

jobs:
generate:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.ver.outputs.version }}
steps:
- id: ver
run: echo "version=1.0.0" >> $GITHUB_OUTPUT

use:
needs: generate
runs-on: ubuntu-latest
steps:
- run: echo "Version is ${{ needs.generate.outputs.version }}"

Quiz

Q1. How do you make a job wait for two other jobs?

Answer

needs: [job1, job2]

Q2. What is the difference between jobs and steps for sharing files?

Answer

Steps share the same filesystem, jobs require artifacts.

🔝 Back to table of contents



Key takeaways

  • Jobs run in parallel by default
  • needs to create dependencies
  • Steps run sequentially within a job
  • $GITHUB_OUTPUT for step outputs
  • Artifacts to share between jobs
  • continue-on-error: true to ignore failures
  • timeout-minutes to limit execution

🔝 Back to table of contents


← Previous chapter | Next chapter: Marketplace actions →