1. Matrix builds

La stratégie matrix permet de tester votre code sur plusieurs OS/versions en parallèle avec un seul workflow. Chaque combinaison de valeurs crée un job distinct.

Matrix sur plusieurs versions Node.js

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]   # 3 jobs en parallèle
      fail-fast: false              # Ne pas annuler si 1 fail
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      - run: npm ci && npm test

Matrix multi-dimensionnelle (OS × version)

strategy:
  matrix:
    os: [ubuntu-latest, windows-latest, macos-latest]
    node: [18, 20]               # 3 × 2 = 6 jobs
  exclude:                         # Exclure une combinaison
    - os: windows-latest
      node: 18

runs-on: ${{ matrix.os }}
steps:
  - uses: actions/setup-node@v4
    with:
      node-version: ${{ matrix.node }}
fail-fast: false est recommandé en matrix : si Node 18 échoue, les tests sur Node 20 et 22 continuent — vous voyez tous les problèmes d'un coup.

2. Environments

Les environments GitHub permettent de protéger les déploiements. Un environment peut exiger des approbations manuelles avant qu'un job s'exécute.

Configurer un environment

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production               # Nom de l'environment
      url: ${{ steps.deploy.outputs.url }}
    steps:
      - name: Deploy
        id: deploy
        run: echo "Deploying to production..."

Protection rules (Settings → Environments)

  • Required reviewers : liste des personnes qui doivent approuver
  • Wait timer : délai d'attente avant exécution (ex: 5 min)
  • Deployment branches : restreindre aux branches protégées
  • Environment secrets : secrets spécifiques à cet environment
Les environment secrets écrasent les dépôt-secrets du même nom. Utile pour avoir des tokens différents entre staging et production.

3. Secrets management

GitHub offre 3 niveaux de secrets, du plus spécifique au plus large :

NiveauPortéeOù configurer
Repository secretUn seul dépôtSettings → Secrets → Actions
Environment secretUn seul environmentSettings → Environments
Organisation secretTous les dépôts de l'orgOrg Settings → Secrets

Utiliser un secret dans un workflow

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Deploy with token
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
          SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
        run: |
          echo "Token length: ${#DEPLOY_TOKEN}"  # Ne jamais afficher la valeur !
          ./scripts/deploy.sh

Bonnes pratiques secrets

  • Ne jamais echo $SECRET dans un step (apparaît dans les logs)
  • Utiliser GITHUB_TOKEN quand possible (token automatique)
  • Faire tourner (rotate) les secrets régulièrement
  • Utiliser des tokens à portée minimale (least privilege)

4. Déploiement

GitHub Actions supporte plusieurs stratégies de déploiement selon la cible.

GitHub Pages

name: Deploy Pages
on:
  push:
    branches: [main]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build
      - uses: actions/upload-pages-artifact@v3
        with:
          path: dist/

  deploy:
    needs: build
    environment:
      name: github-pages
      url: ${{ steps.dep.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - id: dep
        uses: actions/deploy-pages@v4

Déploiement conditionnel

- name: Deploy to production
  if: github.ref == 'refs/heads/main' && github.event_name == 'push'
  env:
    VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
  run: npx vercel --prod --token $VERCEL_TOKEN

5. Cache & Artifacts

Le cache accélère les workflows en réutilisant des données entre runs. Les artifacts partagent des fichiers entre jobs d'un même run.

actions/cache@v4 — Cache explicite

- name: Cache node_modules
  uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-      # Fallback si key exacte non trouvée

Upload + Download artifacts (entre jobs)

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: npm run build
      - uses: actions/upload-artifact@v4  # Sauvegarder
        with:
          name: dist-files
          path: dist/

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4  # Récupérer
        with:
          name: dist-files
          path: ./dist
      - run: ./deploy.sh ./dist
Cache vs Artifact : Le cache persiste entre les runs (utile pour les dépendances). Les artifacts existent pendant un seul run et sont partagés entre jobs. Durée par défaut : 90 jours pour le cache, configurable pour les artifacts.

6. Réutilisation

GitHub Actions permet de factoriser les workflows pour éviter la duplication (principe DRY).

Reusable Workflows

Un workflow appelable depuis d'autres workflows via on: workflow_call:.

# .github/workflows/reusable-test.yml
on:
  workflow_call:                  # Rend le workflow appelable
    inputs:
      node-version:
        required: true
        type: string
    secrets:
      SOME_SECRET:
        required: false
    outputs:
      result:
        description: 'Test result'
        value: ${{ jobs.test.outputs.result }}

jobs:
  test:
    runs-on: ubuntu-latest
    outputs:
      result: ${{ steps.run.outputs.result }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci && npm test
# Appelant : .github/workflows/ci.yml
jobs:
  call-test:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '20'
    secrets: inherit              # Transmettre tous les secrets

Composite Actions

Regrouper plusieurs steps dans une action composite réutilisable via action.yml.

# .github/actions/setup-and-test/action.yml
name: 'Setup and Test'
description: 'Install deps and run tests'
inputs:
  node-version:
    required: true
runs:
  using: 'composite'
  steps:
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
    - run: npm ci
      shell: bash
    - run: npm test
      shell: bash
→ Passer aux exercices O07