GitHub Actions Avancé

Maîtriser les Workflows Avancés de GitHub Actions : Performance et Optimisation en Production

Explorez les mécanismes internes de GitHub Actions et découvrez comment construire des pipelines CI/CD ultra-performants à l'échelle entreprise. Ce cours approfondit les patterns avancés, le debugging expert et les optimisations critiques pour des déploiements fiables et rapides.

Preparetoi.academy 30 min

1. Architecture Interne et Contextes d'Exécution

Définition: L'architecture interne de GitHub Actions repose sur un système d'exécution distribué qui gère les contextes (secrets, variables, environnements) et les runners (GitHub-hosted ou self-hosted) pour exécuter les workflows avec isolation et sécurité.

Explication détaillée: GitHub Actions fonctionne selon une architecture événementielle complexe où chaque workflow est déclenché par un événement (push, pull_request, schedule, etc.) et exécuté dans un environnement isolé. Les runners sont des machines virtuelles (pour GitHub-hosted) ou des serveurs physiques (self-hosted) qui exécutent les jobs en parallèle. Chaque job crée un nouveau conteneur ou machine virtuelle avec un contexte spécifique contenant les secrets, variables et metadata du workflow. Les contextes sont évalués à différents niveaux : le contexte github contient les informations du dépôt et de l'événement, le contexte env contient les variables d'environnement, et le contexte secrets contient les données sensibles chiffrées. Comprendre cette architecture est crucial pour optimiser les performances et éviter les fuites de sécurité.

name: Architecture Analysis Workflow
on:
  push:
    branches: [main, develop]
  pull_request:
    types: [opened, synchronize]

env:
  GLOBAL_ENV: "production"
  LOG_LEVEL: "debug"

jobs:
  context-analysis:
    runs-on: ubuntu-latest
    environment: production
    outputs:
      build-id: ${{ steps.build.outputs.id }}
      runner-info: ${{ runner.os }}-${{ runner.arch }}
    
    steps:
      - name: Analyze Execution Context
        id: context
        run: |
          echo "=== GitHub Context ===" >> $GITHUB_OUTPUT
          echo "Repository: ${{ github.repository }}" >> $GITHUB_OUTPUT
          echo "Event Name: ${{ github.event_name }}" >> $GITHUB_OUTPUT
          echo "Workflow SHA: ${{ github.sha }}" >> $GITHUB_OUTPUT
          echo "Runner Temp: ${{ runner.temp }}" >> $GITHUB_OUTPUT
          
      - name: Debug Runner Internals
        id: build
        run: |
          # Accéder aux paths système du runner
          echo "id=$(uuidgen)" >> $GITHUB_OUTPUT
          echo "Workspace: $GITHUB_WORKSPACE"
          echo "Temp Directory: $RUNNER_TEMP"
          # Variables système du runner
          env | grep -E "^RUNNER_|^GITHUB_" | sort
          
      - name: Visualize Context Hierarchy
        run: |
          cat > context_map.json <<'EOF'
          {
            "github": {
              "repository": "${{ github.repository }}",
              "ref": "${{ github.ref }}",
              "event_name": "${{ github.event_name }}"
            },
            "env": {
              "GLOBAL_ENV": "${{ env.GLOBAL_ENV }}",
              "LOG_LEVEL": "${{ env.LOG_LEVEL }}"
            },
            "runner": {
              "os": "${{ runner.os }}",
              "arch": "${{ runner.arch }}",
              "temp": "${{ runner.temp }}"
            }
          }
          EOF
          jq . context_map.json

      - name: Cross-Job Context Passing
        run: |
          # Exporter des données pour les jobs suivants
          echo "CROSS_JOB_DATA=$(echo ${{ steps.build.outputs.id }})" >> $GITHUB_ENV
          echo "BUILD_TIMESTAMP=$(date +%s)" >> $GITHUB_OUTPUT
Aspect Détail Impact Performance
Runner Type GitHub-hosted (partagé) Startup ~30s, limites de ressources
Runner Type Self-hosted (dédié) Startup ~2s, contrôle total
Context Evaluation À la soumission du job Impacts la taille du workflow file
Secrets Storage Chiffrement AES-256 Overhead minimal (~1ms)
Job Isolation Conteneur par job Perte de cache entre jobs
Matrix Expansion Généré avant exécution Peut créer 100s de jobs

Astuce Expert: Utilisez runner.debug en variable secrète pour activer le logging détaillé de GitHub Actions et révéler les internals du système. Les logs de debugging contiennent des informations critiques sur l'évaluation des contextes et les appels API internes.

⚠️ ATTENTION: Les contextes sont évalués à des moments différents du workflow. Les contextes utilisant secrets ne peuvent pas être utilisés dans les conditions if au niveau du job car ils sont évalués avant que les secrets ne soient injectés. De plus, les valeurs massives dans les contextes (matrices avec 1000+ éléments) peuvent causer des timeouts de workflow et des dépassements de limite de taille.


2. Optimisation Avancée des Runners et Gestion des Ressources

Définition: L'optimisation des runners implique la configuration stratégique des runners GitHub-hosted et self-hosted, la gestion du cache, des artefacts et des ressources système pour minimiser les temps d'exécution et les coûts d'infrastructure.

Explication détaillée: GitHub propose des runners avec différentes spécifications (Ubuntu, macOS, Windows) avec des ressources limitées. Les runners GitHub-hosted partagés ont des limites de CPU, RAM et disque, et incluent un cache limité à 5 Go par référence. Les self-hosted runners peuvent être configurés avec des ressources illimitées mais nécessitent une gestion et une maintenance. L'optimisation critique passe par l'utilisation stratégique du cache (actions/cache), la parallélisation des jobs, la réduction des dépendances, et l'utilisation de conteneurs Docker pour contrôler l'environnement. Le caching des dépendances (npm, pip, maven) peut réduire les temps de 70-90%, tandis que la parallélisation des tests peut diviser les temps d'exécution par le nombre de jobs parallèles. Il est également crucial de monitorer l'utilisation des ressources et d'identifier les goulots d'étranglement.

name: Advanced Runner Optimization
on:
  push:
    branches: [main]
  pull_request:

jobs:
  # Job 1: Parallélisation intelligente des tests
  parallel-testing:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        test-suite: [unit, integration, e2e]
        node-version: [18, 20]
      max-parallel: 6
      fail-fast: false
    
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Setup Node with Cache
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
          cache-dependency-path: '**/package-lock.json'
      
      - name: Advanced Dependency Caching
        uses: actions/cache@v3
        with:
          path: |
            ~/.npm
            ~/.cache/pip
            node_modules
            .gradle
          key: ${{ runner.os }}-deps-${{ hashFiles('**/package-lock.json', '**/requirements.txt') }}
          restore-keys: |
            ${{ runner.os }}-deps-
            ${{ runner.os }}-
      
      - name: Install Dependencies with Fallback
        run: |
          npm ci --prefer-offline --no-audit || npm ci
      
      - name: Run Parallel Test Suite
        env:
          DB_HOST: localhost
          DB_PORT: 5432
          TEST_WORKERS: 4
        run: |
          case "${{ matrix.test-suite }}" in
            unit)
              npm run test:unit -- --maxWorkers=4 --coverage
              ;;
            integration)
              npm run test:integration -- --maxWorkers=2
              ;;
            e2e)
              npm run test:e2e -- --workers=2 --timeout=30000
              ;;
          esac

  # Job 2: Self-hosted runner avec gestion des ressources
  resource-intensive-build:
    runs-on: [self-hosted, linux, x64, high-performance]
    if: github.event_name == 'push'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Monitor Resource Usage
        run: |
          echo "=== CPU Usage ===" 
          mpstat -P ALL 1 1
          echo "=== Memory Usage ===" 
          free -h
          echo "=== Disk Usage ===" 
          df -h /
          echo "=== Top Processes ===" 
          ps aux --sort=-%cpu | head -10
      
      - name: Build with Resource Limits
        run: |
          # Limiter les ressources pour éviter l'overload
          ulimit -c 0  # Désactiver les core dumps
          ulimit -m 4194304  # 4GB RAM limit
          
          # Build avec parallelization contrôlée
          ./build.sh --jobs=$(nproc --all)
      
      - name: Cleanup and Disk Management
        if: always()
        run: |
          # Nettoyer les artefacts temporaires
          find . -type d -name "__pycache__" -exec rm -rf {} +
          find . -type d -name ".gradle" -exec rm -rf {} +
          find . -type d -name "node_modules" -delete
          
          # Rapporter l'espace disque
          df -h / | tail -1

  # Job 3: Artefacts et uploads optimisés
  artifact-optimization:
    runs-on: ubuntu-latest
    needs: parallel-testing
    
    steps:
      - uses: actions/download-artifact@v3
        with:
          name: test-results
          path: ./results
      
      - name: Compress Large Artifacts
        run: |
          # Compresser avant upload pour économiser la bande passante
          tar -czf coverage-report.tar.gz coverage/
          # Vérifier la taille
          du -sh coverage-report.tar.gz
      
      - name: Upload with Retention
        uses: actions/upload-artifact@v3
        with:
          name: coverage-reports
          path: coverage-report.tar.gz
          retention-days: 7
          compression-level: 9
Stratégie Technique Gain de Performance
Caching actions/cache + npm ci 70-90% temps
Parallélisation Matrix + max-parallel Jusqu'à 6x speedup
Service Containers PostgreSQL/Redis Évite l'init externe
Compression Artifacts gzip niveau 9 60-80% réduction
Resource Limiting ulimit, cgroups Stabilité +40%
Partial Checkout fetch-depth: 1 50% temps clone

Astuce Expert: Utilisez des artifacts avec une retention-days court (3-7 jours) pour économiser l'espace de stockage. Pour les builds importants, compressez les artefacts avant upload avec tar -czf niveau 9, ce qui peut réduire de 80% la taille et accélérer le transfert de 2-3x. Activez également le mode prefer-offline lors de l'installation des dépendances pour forcer l'utilisation du cache local.

⚠️ ATTENTION: Les runners GitHub-hosted partagés sont limités à ~7 Go de RAM et 2 cœurs CPU effectifs. Les builds massifs (compilation C++, gros datasets ML) peuvent causer un manque de mémoire et des timeouts. Les self-hosted runners doivent être strictement isolés avec des conteneurs ou des VMs pour éviter les fuites de sécurité. Le cache Actions est limité à 5 Go par ref, et les fichiers inutilisés pendant 7 jours sont automatiquement supprimés, ce qui peut causer des cache miss inattendus.


3. Patterns de Debugging Expert et Gestion des Erreurs

Définition: Le debugging avancé en GitHub Actions implique l'activation du mode debug, l'analyse des logs système, l'utilisation stratégique des étapes de diagnostic, et l'implémentation de mécanismes robustes de gestion des erreurs et de récupération.

Explication détaillée: GitHub Actions fournit plusieurs niveaux de logging et de debugging. Le mode debug peut être activé via la variable secrète ACTIONS_STEP_DEBUG et RUNNER_DEBUG, qui expose les logs internes du runner et les appels API. Les logs des workflows contiennent des informations sur l'exécution des étapes, mais les logs de debugging contiennent aussi des détails sur l'évaluation des contextes, les décisions de branchement et les appels système. Pour un debugging efficace, il faut instrumenter le code avec des echo stratégiques, capturer les états du système, et utiliser des outils comme jq pour analyser les structures JSON complexes. La gestion des erreurs doit inclure des blocs try-catch dans les scripts, des conditions if: failure() ou if: always(), et des stratégies de retry pour les opérations flaky. Il est crucial de logger les états intermédiaires et de capturer les outputs pour les analyses post-mortem.

name: Expert Debugging & Error Handling
on:
  push:
  pull_request:

env:
  # Activer le debugging complet
  ACTIONS_STEP_DEBUG: true
  RUNNER_DEBUG: 1

jobs:
  advanced-debugging:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: System Diagnostics Capture
        id: diagnostics
        run: |
          # Créer un fichier de diagnostic complet
          {
            echo "=== SYSTEM INFO ==="
            uname -a
            echo "=== CPU INFO ==="
            nproc --all
            lscpu | head -10
            echo "=== MEMORY INFO ==="
            free -h
            echo "=== DISK INFO ==="
            df -h /
            echo "=== NETWORK INFO ==="
            ifconfig || ip addr
            echo "=== ENVIRONMENT ==="
            env | grep -E "^(GITHUB_|RUNNER_|ACTIONS_)" | sort
          } | tee system_diagnostics.log
          
          # Exporter les diagnostics pour les steps suivantes
          echo "diagnostics_path=$(pwd)/system_diagnostics.log" >> $GITHUB_OUTPUT
      
      - name: Instrumented Code Execution
        id: execution
        continue-on-error: true
        run: |
          set -e  # Exit on error
          
          # Fonction de logging avancée
          log_section() {
            echo "::group::$1"
            echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $1"
          }
          
          log_end() {
            echo "::endgroup::"
          }
          
          # Exécution avec instrumentation
          log_section "Step 1: Initialize"
          export BUILD_ID=$(uuidgen)
          export BUILD_START=$(date +%s)
          echo "Build ID: $BUILD_ID"
          echo "Start Time: $BUILD_START"
          log_end
          
          log_section "Step 2: Execute Main Logic"
          # Capturer les états intermédiaires
          {
            echo "Executing main logic..."
            # Simuler une opération
            for i in {1..5}; do
              echo "Iteration $i"
              sleep 0.5
            done
            echo "Main logic completed successfully"
          } 2>&1 | tee execution_log.txt
          log_end
          
          log_section "Step 3: Collect Metrics"
          BUILD_END=$(date +%s)
          BUILD_DURATION=$((BUILD_END - BUILD_START))
          echo "Duration: ${BUILD_DURATION}s"
          echo "build_id=$BUILD_ID" >> $GITHUB_OUTPUT
          echo "duration=$BUILD_DURATION" >> $GITHUB_OUTPUT
          log_end
      
      - name: Error Analysis and Recovery
        if: failure()
        run: |
          echo "::error::Job failed at $(date)"
          echo "::error::Build ID: ${{ steps.execution.outputs.build_id }}"
          
          # Analyser les logs d'erreur
          if [ -f execution_log.txt ]; then
            echo "::group::Execution Log Analysis"
            tail -50 execution_log.txt
            echo "::endgroup::"
          fi
          
          # Capture de stack traces ou contextes d'erreur
          echo "::group::Error Context"
          ps aux
          dmesg | tail -20 || true
          echo "::endgroup::"
      
      - name: JSON Output Analysis
        run: |
          cat > build_metadata.json <<'EOF'
          {
            "build_id": "${{ steps.execution.outputs.build_id }}",
            "duration": ${{ steps.execution.outputs.duration }},
            "status": "success",
            "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
            "runner": {
              "os": "${{ runner.os }}",
              "arch": "${{ runner.arch }}"
            }
          }
          EOF
          
          # Valider et analyser avec jq
          jq . build_metadata.json
          echo "Build Metadata Validated"

      - name: Retry Logic for Flaky Operations
        uses: nick-invision/retry@v2
        with:
          timeout_minutes: 5
          max_attempts: 3
          retry_wait_seconds: 10
          retry_on: error
          command: |
            echo "Attempting operation (attempt ${{ attempt }})"
            # Opération susceptible d'échouer
            curl -f https://api.example.com/health || exit 1

      - name: Upload Diagnostics Artifacts
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: debug-diagnostics-${{ github.run_id }}
          path: |
            system_diagnostics.log
            execution_log.txt
            build_metadata.json
          retention-days: 30

  # Job 2: Monitoring avancé
  monitoring-and-alerts:
    runs-on: ubuntu-latest
    if: always()
    needs: advanced-debugging
    
    steps:
      - name: Generate Failure Report
        if: failure()
        run: |
          cat > failure_report.md <<'EOF'
          # Workflow Failure Report
          
          - **Run ID:** ${{ github.run_id }}
          - **Workflow:** ${{ github.workflow }}
          - **Branch:** ${{ github.ref }}
          - **Commit:** ${{ github.sha }}
          - **Time:** $(date -u)
          
          ## Failed Jobs
          - advanced-debugging: FAILED
          
          ## Diagnostic Artifacts
          See attached logs and diagnostics.
          EOF
          cat failure_report.md
Technique Utilisation Efficacité
ACTIONS_STEP_DEBUG Logs détaillés du runner Expose tous les internals
Groupes de logs ::group:: / ::endgroup:: Organise les logs longs
continue-on-error Capture les erreurs sans arrêt Permet l'analyse post-mortem
Retry Actions Gère les opérations flaky 95%+ de succès après 3 tentatives
Artifacts de Debug Stockage des logs/états Rétention 30 jours
JSON Parsing (jq) Analyse structurée Validation automatisée

Astuce Expert: Utilisez les "annotations" GitHub (::error::, ::warning::, ::notice::) pour marquer les problèmes directement dans l'interface. Activez ACTIONS_STEP_DEBUG: true comme variable secrète du repository pour un debugging permanent sans révéler les secrets dans les logs. Créez un job de "monitoring" qui s'exécute toujours (if: always()) pour collecter les diagnostics même en cas d'échec, puis uploadez-les comme artefacts avec une rétention longue.

⚠️ ATTENTION: Le mode debug expose TOUS les secrets non-masqués dans les logs système, y compris les tokens d'API et les credentials. Ne l'activez JAMAIS sans avoir configuré des secrets correctement masqués. Les logs avec ACTIONS_STEP_DEBUG peuvent être 10x plus volumineux, ce qui ralentit l'affichage et peut causer des timeouts de parsing. Les artifacts uploaded avec un grand nombre de fichiers peuvent aussi causer des problèmes d'énumération. De plus, les logs sont conservés pendant 90 jours par défaut, ce qui peut révéler des patterns d'exécution sensibles à des attaquants.


4. Sécurité Avancée et Gestion des Secrets

Définition: La sécurité avancée en GitHub Actions couvre la gestion des secrets, les permissions granulaires (RBAC), l'isolation des environnements, la validation des dépendances, la prévention des injections, et les mécanismes de protection contre les attaques de supply chain.

Explication détaillée: GitHub Actions introduit plusieurs couches de sécurité qui doivent être comprises et configurées correctement. Les secrets sont chiffrés avec AES-256 et ne sont jamais exposés dans les logs (GitHub les masque automatiquement), mais ils peuvent être exfiltrés via des scripts malveillants. Les permissions du token GITHUB_TOKEN doivent être réduites au minimum nécessaire avec permissions: au niveau du workflow ou du job. Les environnements permettent de créer des stratégies d'approbation et des secrets spécifiques à des branches ou des déploiements. Les workflows provenant de forks et de branches non-protégées ne reçoivent pas automatiquement les secrets, ce qui prévient l'exfiltration. La validation des dépendances (actions externes) est critique car une action malveillante peut exécuter du code arbitraire. Les injections de contexte (context injection) sont une menace majeure : utiliser les variables du contexte dans des shells ou des scripts peuvent permettre l'exécution de code arbitraire. Les solutions incluent l'utilisation de fichiers .env, des variables d'environnement, et l'échappement correct des valeurs.

name: Advanced Security Hardening
on:
  push:
    branches: [main]
  pull_request:

# Permissions minimales au niveau du workflow
permissions:
  contents: read
  id-token: write
  pull-requests: read

env:
  # Variables non-sensibles seulement
  LOG_LEVEL: info
  REGISTRY: ghcr.io

jobs:
  security-audit:
    runs-on: ubuntu-latest
    # Permissions spécifiques au job
    permissions:
      contents: read
      security-events: write
    
    steps:
      - uses: actions/checkout@v4
        with:
          # Limiter la profondeur du clone
          fetch-depth: 1
      
      - name: Dependency Validation & Lock Files
        run: |
          # Vérifier l'intégrité des dépendances via checksums
          if [ -f package-lock.json ]; then
            npm ci --audit
          fi
          
          if [ -f Gemfile.lock ]; then
            bundle check
          fi
          
          if [ -f requirements.txt ]; then
            pip install --require-hashes -r requirements.txt || \
            pip install -r requirements.txt
          fi

      - name: Secrets Detection (GitGuardian/TruffleHog)
        continue-on-error: true
        run: |
          # Installer les outils de détection de secrets
          pip install detect-secrets truffleHog
          
          # Scanner pour les secrets hardcodés
          detect-secrets scan --baseline .secrets.baseline
          
          # Vérifier les patterns connus
          for pattern in "PRIVATE KEY" "AWS_SECRET" "api_key" "password"; do
            if grep -r "$pattern" --include="*.py" --include="*.js" --include="*.json"; then
              echo "::warning::Potential secret pattern found: $pattern"
            fi
          done

      - name: SBOM Generation (Software Bill of Materials)
        run: |
          # Générer un SBOM pour tracer les dépendances
          npm sbom 2>/dev/null || echo "SBOM: Node modules listed below"
          npm list --depth=0
          
          # Générer un hash des dépendances
          {
            echo "=== Dependency Hashes ==="
            find . -name "package-lock.json" -o -name "Gemfile.lock" -o -name "requirements.txt" | \
            while read f; do
              echo "$f: $(sha256sum "$f" | cut -d' ' -f1)"
            done
          } | tee sbom.txt

  # Job avec accès aux secrets et environnement protégé
  secure-deployment:
    runs-on: ubuntu-latest
    needs: security-audit
    # Déployer seulement sur main (branches protégées)
    if: github.ref == 'refs/heads/main'
    
    # Environnement avec approbations requises
    environment:
      name: production
      url: https://app.example.com
    
    # Permissions minimales pour ce job
    permissions:
      contents: read
      id-token: write
    
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1
      
      - name: OIDC Token Exchange for AWS
        run: |
          # Utiliser OIDC au lieu de secrets AWS classiques
          # C'est la meilleure pratique pour les déploiements
          
          # 1. Obtenir le token OIDC
          OIDC_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
            "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.token')
          
          # 2. Échanger contre des credentials AWS temporaires
          # (Normalement fait par AWS STS)
          echo "OIDC Token acquired (${#OIDC_TOKEN} chars)"
      
      - name: Secrets Handling - Safe Pattern
        env:
          # Les secrets ne doivent JAMAIS être dans les contextes
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          # ✅ BON: Passer via variables d'environnement
          # Le secret est masqué dans les logs GitHub
          
          # ❌ MAUVAIS (jamais faire ça):
          # echo "Password: ${{ secrets.DB_PASSWORD }}"
          # url="http://user:${{ secrets.DB_PASSWORD }}@host"
          # grep "${{ secrets.DB_PASSWORD }}" file.txt
          
          # ✅ BON: Utiliser des fichiers temporaires avec permissions restrictives
          cat > .env.local <<EOF
          DB_PASSWORD=$DB_PASSWORD
          API_KEY=$API_KEY
          EOF
          chmod 600 .env.local
          
          # Charger sans exposer
          source .env.local
          
          # Utiliser dans des commandes sûres
          curl -H "Authorization: Bearer $API_KEY" https://api.example.com/deploy
          
          # Nettoyer
          rm -f .env.local
          unset DB_PASSWORD API_KEY

  # Job pour valider les actions tierces
  action-validation:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Validate Third-Party Actions
        run: |
          # Lister toutes les actions utilisées
          grep -r "uses:" .github/workflows/ | grep -v "actions/checkout" | tee actions_used.txt
          
          # Vérifier les versions (utiliser des versions fixes, pas latest)
          echo "::notice::Checking for 'latest' tags..."
          if grep -q "@latest" actions_used.txt; then
            echo "::warning::Found @latest tags - consider using fixed versions"
          fi
          
          # Vérifier les dépôts connus et de confiance
          while read -r line; do
            action=$(echo "$line" | grep -oP 'uses: \K[^@]+')
            if [[ ! "$action" =~ ^(actions|github)/ ]]; then
              echo "::notice::External action: $action - manually verify"
            fi
          done < actions_used.txt

  # Job pour les vérifications de compliance
  compliance-check:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      checks: write
    
    steps:
      - uses: actions/checkout@v4
      
      - name: License Compliance Scan
        continue-on-error: true
        run: |
          # Vérifier les licenses des dépendances
          npm list --depth=0 2>/dev/null | awk '{print $1}' | while read pkg; do
            echo "License for $pkg: $(npm view "$pkg" license 2>/dev/null || echo 'UNKNOWN')"
          done

      - name: Generate Security Report
        run: |
          cat > SECURITY_REPORT.md <<'EOF'
          # Security Audit Report
          
          - **Date:** $(date -u)
          - **Commit:** ${{ github.sha }}
          - **Secrets Detected:** 0 (or list any findings)
          - **Actions Validated:** Yes
          - **SBOM Generated:** See sbom.txt
          - **OIDC Enabled:** Yes for AWS/GCP
          
          ## Recommendations
          1. Always use environment protection rules
          2. Use OIDC for cloud provider authentication
          3. Pin action versions to commit SHAs
          4. Regular dependency updates
          5. Enable branch protection and code review
          EOF
          cat SECURITY_REPORT.md
Mesure Sécurité Implémentation Niveau Protection
Secrets GitHub Chiffrement AES-256 Fort (automatic masking)
OIDC Token Exchange AWS/GCP/Azure STS Très fort (pas de long-term secrets)
Permissions RBAC permissions: au niveau workflow/job Modéré (dépend de la config)
Environment Rules Branch protection + approbations Fort (review requis)
Secrets Detection TruffleHog/detect-secrets Modéré (faux positifs)
Action Pinning Versions de commit fixes Fort (prévient les mutations)
SBOM Generation npm sbom / pip freeze Informatif (traceabilité)

Astuce Expert: Utilisez toujours l'échange de tokens OIDC pour l'authentification cloud au lieu de stocker des credentials long-term. GitHub Actions

Accédez à des centaines d'examens QCM — Découvrir les offres Premium