0%
Tutoriel 10 sur 10
100% terminé

GitHub Actions et CI/CD

Configurez des workflows d'intégration et de déploiement continus directement dans vos dépôts GitHub.

GitHub Actions et CI/CD

GitHub Actions révolutionne l’automatisation du développement logiciel en intégrant directement CI/CD dans vos dépôts. Ce tutoriel vous apprendra à créer des workflows puissants pour automatiser tests, builds et déploiements.

Introduction à GitHub Actions

Qu’est-ce que GitHub Actions ?

GitHub Actions est une plateforme d’automatisation qui permet de :

  • Exécuter des workflows sur des événements Git
  • Automatiser les tests et la validation
  • Déployer automatiquement vos applications
  • Gérer les releases et notifications
graph LR
    A[Push/PR] --> B[GitHub Actions]
    B --> C[Tests]
    B --> D[Build]
    B --> E[Deploy]
    C --> F[Notifications]
    D --> F
    E --> F

Concepts clés

Workflow : Processus automatisé défini en YAML Job : Ensemble d’étapes exécutées sur un runner Step : Action individuelle dans un job Action : Composant réutilisable Runner : Machine virtuelle qui exécute les jobs

Structure d’un workflow

Fichier de base

# .github/workflows/ci.yml
name: CI Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          
      - name: Install dependencies
        run: npm ci
        
      - name: Run tests
        run: npm test

Déclencheurs (Triggers)

# Événements Git
on:
  push:
    branches: [main]
    tags: ['v*']
  pull_request:
    branches: [main]
  release:
    types: [published]

# Événements programmés
on:
  schedule:
    - cron: '0 2 * * 1'  # Tous les lundis à 2h

# Déclenchement manuel
on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to deploy'
        required: true
        default: 'staging'

Workflows essentiels

CI basique pour Node.js

# .github/workflows/node-ci.yml
name: Node.js CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [16, 18, 20]
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
          
      - name: Install dependencies
        run: npm ci
        
      - name: Run linter
        run: npm run lint
        
      - name: Run tests
        run: npm test
        
      - name: Run build
        run: npm run build
        
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info

CI pour Python

# .github/workflows/python-ci.yml
name: Python CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        python-version: [3.8, 3.9, '3.10', 3.11]
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
          
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install -r requirements-dev.txt
          
      - name: Lint with flake8
        run: |
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
          flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127
          
      - name: Test with pytest
        run: |
          pytest --cov=./ --cov-report=xml
          
      - name: Upload coverage
        uses: codecov/codecov-action@v3

Déploiement automatique

# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          
      - name: Install and build
        run: |
          npm ci
          npm run build
          
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.ORG_ID }}
          vercel-project-id: ${{ secrets.PROJECT_ID }}
          vercel-args: '--prod'

Actions avancées

Matrice de tests

jobs:
  test:
    runs-on: ${{ matrix.os }}
    
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [16, 18, 20]
        include:
          - os: ubuntu-latest
            node-version: 20
            coverage: true
        exclude:
          - os: windows-latest
            node-version: 16
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          
      - name: Run tests
        run: npm test
        
      - name: Upload coverage
        if: matrix.coverage
        uses: codecov/codecov-action@v3

Conditions et expressions

jobs:
  deploy:
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    runs-on: ubuntu-latest
    
    steps:
      - name: Deploy to staging
        if: contains(github.event.head_commit.message, '[staging]')
        run: echo "Deploying to staging"
        
      - name: Deploy to production
        if: startsWith(github.ref, 'refs/tags/v')
        run: echo "Deploying to production"
        
      - name: Notify on failure
        if: failure()
        uses: 8398a7/action-slack@v3
        with:
          status: failure
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Artifacts et cache

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-
            
      - name: Install and build
        run: |
          npm ci
          npm run build
          
      - name: Upload build artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build-files
          path: dist/
          
  deploy:
    needs: build
    runs-on: ubuntu-latest
    
    steps:
      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-files
          path: dist/
          
      - name: Deploy
        run: echo "Deploying files from dist/"

Sécurité et secrets

Gestion des secrets

# Configuration des secrets dans GitHub
# Settings > Secrets and variables > Actions

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: Deploy to AWS
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        run: |
          aws s3 sync ./dist s3://my-bucket

Environnements protégés

jobs:
  deploy-production:
    runs-on: ubuntu-latest
    environment: production
    
    steps:
      - name: Deploy to production
        run: echo "Deploying to production environment"

Permissions GITHUB_TOKEN

name: Secure Workflow

on: [push]

permissions:
  contents: read
  issues: write
  pull-requests: write

jobs:
  security-scan:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Run security scan
        uses: github/super-linter@v4
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Actions personnalisées

Action JavaScript

// .github/actions/hello-world/index.js
const core = require('@actions/core');
const github = require('@actions/github');

try {
  const nameToGreet = core.getInput('who-to-greet');
  console.log(`Hello ${nameToGreet}!`);
  
  const time = (new Date()).toTimeString();
  core.setOutput("time", time);
  
  const payload = JSON.stringify(github.context.payload, undefined, 2);
  console.log(`The event payload: ${payload}`);
} catch (error) {
  core.setFailed(error.message);
}
# .github/actions/hello-world/action.yml
name: 'Hello World'
description: 'Greet someone and record the time'

inputs:
  who-to-greet:
    description: 'Who to greet'
    required: true
    default: 'World'

outputs:
  time:
    description: 'The time we greeted you'

runs:
  using: 'node20'
  main: 'index.js'

Utilisation de l’action

jobs:
  hello_world_job:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Hello world action step
        uses: ./.github/actions/hello-world
        id: hello
        with:
          who-to-greet: 'GitHub Actions'
          
      - name: Get the output time
        run: echo "The time was ${{ steps.hello.outputs.time }}"

Workflows complexes

Pipeline multi-environnements

# .github/workflows/multi-env-deploy.yml
name: Multi-Environment Deploy

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        run: npm test
  
  deploy-staging:
    needs: test
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    environment: staging
    
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to staging
        run: echo "Deploying to staging"
        
  deploy-production:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to production
        run: echo "Deploying to production"
        
  notify:
    needs: [deploy-staging, deploy-production]
    if: always()
    runs-on: ubuntu-latest
    
    steps:
      - name: Notify team
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Release automatique

# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          
      - name: Install dependencies
        run: npm ci
        
      - name: Build
        run: npm run build
        
      - name: Generate changelog
        id: changelog
        uses: metcalfc/changelog-generator@v4.0.1
        with:
          myToken: ${{ secrets.GITHUB_TOKEN }}
          
      - name: Create Release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ github.ref }}
          body: ${{ steps.changelog.outputs.changelog }}
          draft: false
          prerelease: false
          
      - name: Upload Release Asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./dist/app.zip
          asset_name: app.zip
          asset_content_type: application/zip

Exercices pratiques

Exercice 1 : CI basique

# .github/workflows/basic-ci.yml
name: Basic CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          
      - name: Install dependencies
        run: |
          echo '{"name": "test-app", "scripts": {"test": "echo \"Tests passed!\""}}' > package.json
          npm install
          
      - name: Run tests
        run: npm test
        
      - name: Success message
        run: echo "✅ All tests passed!"

Exercice 2 : Déploiement conditionnel

# .github/workflows/conditional-deploy.yml
name: Conditional Deploy

on:
  push:
    branches: [main, staging]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy to staging
        if: github.ref == 'refs/heads/staging'
        run: |
          echo "🚀 Deploying to staging environment"
          echo "Environment: staging"
          
      - name: Deploy to production
        if: github.ref == 'refs/heads/main'
        run: |
          echo "🚀 Deploying to production environment"
          echo "Environment: production"
          
      - name: Notify deployment
        run: |
          echo "📧 Sending notification"
          echo "Deployment completed for branch: ${{ github.ref_name }}"

Exercice 3 : Workflow avec artifacts

# .github/workflows/artifacts-demo.yml
name: Artifacts Demo

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Create build artifacts
        run: |
          mkdir -p dist
          echo "Built application v1.0.0" > dist/app.txt
          echo "Build timestamp: $(date)" > dist/build-info.txt
          
      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build-artifacts
          path: dist/
          
  test:
    needs: build
    runs-on: ubuntu-latest
    
    steps:
      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-artifacts
          path: ./downloaded/
          
      - name: Test artifacts
        run: |
          echo "📦 Testing downloaded artifacts:"
          ls -la ./downloaded/
          cat ./downloaded/app.txt
          cat ./downloaded/build-info.txt

Monitoring et debugging

Logs et debugging

jobs:
  debug:
    runs-on: ubuntu-latest
    
    steps:
      - name: Debug information
        run: |
          echo "🔍 Debug Information:"
          echo "Runner OS: ${{ runner.os }}"
          echo "GitHub Actor: ${{ github.actor }}"
          echo "Repository: ${{ github.repository }}"
          echo "Branch: ${{ github.ref_name }}"
          echo "Commit SHA: ${{ github.sha }}"
          
      - name: Enable debug logging
        run: echo "::debug::This is a debug message"
        
      - name: Set environment variable
        run: echo "CUSTOM_VAR=hello-world" >> $GITHUB_ENV
        
      - name: Use environment variable
        run: echo "Custom variable: $CUSTOM_VAR"

Notifications

jobs:
  notify:
    runs-on: ubuntu-latest
    if: always()
    
    steps:
      - name: Slack notification
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          channel: '#deployments'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}
          
      - name: Email notification
        uses: dawidd6/action-send-mail@v3
        with:
          server_address: smtp.gmail.com
          server_port: 465
          username: ${{ secrets.MAIL_USERNAME }}
          password: ${{ secrets.MAIL_PASSWORD }}
          subject: "Build ${{ job.status }}"
          body: "Build completed with status: ${{ job.status }}"
          to: team@company.com

Bonnes pratiques

Organisation des workflows

.github/
├── workflows/
│   ├── ci.yml              # Tests et validation
│   ├── deploy-staging.yml  # Déploiement staging
│   ├── deploy-prod.yml     # Déploiement production
│   ├── release.yml         # Gestion des releases
│   └── security.yml        # Scans de sécurité
├── actions/
│   └── custom-action/      # Actions personnalisées
└── ISSUE_TEMPLATE/         # Templates d'issues

Optimisation des performances

jobs:
  optimized:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      # Cache des dépendances
      - name: Cache Node modules
        uses: actions/cache@v3
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          
      # Parallélisation
      - name: Install dependencies
        run: npm ci --prefer-offline --no-audit
        
      # Éviter les étapes inutiles
      - name: Run tests
        if: github.event_name == 'pull_request'
        run: npm test

Sécurité

# Permissions minimales
permissions:
  contents: read
  
jobs:
  secure:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      # Scan de sécurité
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          
      # Validation des secrets
      - name: Check for secrets
        uses: trufflesecurity/trufflehog@main
        with:
          path: ./

Ressources supplémentaires

Actions populaires

  • actions/checkout : Récupérer le code
  • actions/setup-node : Configurer Node.js
  • actions/cache : Cache des dépendances
  • docker/build-push-action : Build et push Docker
  • peaceiris/actions-gh-pages : Déploiement GitHub Pages

Marketplace

Documentation

Conclusion

GitHub Actions transforme votre dépôt en une plateforme DevOps complète. En maîtrisant ces concepts, vous pouvez automatiser l’ensemble de votre pipeline de développement, de l’intégration continue au déploiement en production.

Félicitations ! Vous avez terminé ce cours complet sur Git et GitHub. Vous disposez maintenant de toutes les compétences nécessaires pour gérer efficacement vos projets avec Git, collaborer sur GitHub et automatiser vos workflows de développement.


Temps de lecture estimé : 40 minutes
Niveau : Avancé
Étape précédente : Git sous-modules et sous-arbres
🎉 Cours terminé ! Vous maîtrisez maintenant Git et GitHub !