Skip to content

Latest commit

 

History

History
2022 lines (1577 loc) · 47 KB

File metadata and controls

2022 lines (1577 loc) · 47 KB

🔝 Retour au Sommaire

18.9.1 GitHub Actions Windows/Ubuntu

Introduction à l'Intégration Continue avec GitHub Actions

Qu'est-ce que GitHub Actions ?

GitHub Actions est un service d'intégration continue et de déploiement continu (CI/CD) intégré directement à GitHub. Il permet d'automatiser des tâches comme :

  • Compiler votre code automatiquement à chaque modification
  • Exécuter les tests pour vérifier que rien n'est cassé
  • Vérifier la qualité du code (linting, analyse statique)
  • Déployer l'application automatiquement sur les serveurs
  • Générer des rapports de couverture de code
  • Créer des releases et des packages

Pourquoi utiliser GitHub Actions pour FreePascal ?

Avantages :

Gratuit pour les projets open source (et généreux pour les projets privés)
Intégré à GitHub : pas besoin de service externe
Multi-plateforme : teste facilement sur Windows, Linux et macOS
Parallélisation : teste sur plusieurs OS simultanément
Automatisation complète : moins d'erreurs humaines
Historique des builds : trace de toutes les compilations

Cas d'usage typiques :

  1. Développeur solo : vérifier que le code compile sur les deux OS
  2. Équipe : s'assurer qu'un commit ne casse pas le build
  3. Projet open source : garantir la qualité avant d'accepter une Pull Request
  4. Production : déployer automatiquement après validation

Concepts de Base

Anatomie d'un Workflow GitHub Actions

Un workflow GitHub Actions est défini dans un fichier YAML situé dans .github/workflows/.

Structure de base :

name: Nom du Workflow          # Nom affiché dans l'interface  
on: [push, pull_request]       # Quand le workflow se déclenche  
jobs:                          # Liste des tâches à exécuter
  build:                       # Nom du job
    runs-on: ubuntu-latest     # Sur quel OS exécuter
    steps:                     # Liste des étapes
      - name: Première étape   # Nom de l'étape
        run: echo "Hello"      # Commande à exécuter

Éléments Clés

1. Déclencheurs (Triggers)

Les événements qui lancent le workflow :

# Déclencher sur push
on: push

# Déclencher sur plusieurs événements
on: [push, pull_request]

# Déclencher sur des branches spécifiques
on:
  push:
    branches:
      - main
      - develop
  pull_request:
    branches:
      - main

2. Jobs

Unités de travail qui s'exécutent (par défaut en parallèle) :

jobs:
  build-windows:
    runs-on: windows-latest
    steps:
      - name: Compilation Windows
        run: fpc MonProgramme.pas

  build-linux:
    runs-on: ubuntu-latest
    steps:
      - name: Compilation Linux
        run: fpc MonProgramme.pas

Ces deux jobs s'exécutent en parallèle sur deux machines virtuelles différentes.

3. Steps (Étapes)

Actions individuelles dans un job :

steps:
  - name: Récupérer le code
    uses: actions/checkout@v3

  - name: Installer FreePascal
    run: sudo apt install fpc

  - name: Compiler
    run: fpc MonProgramme.pas

4. Runners (Machines d'Exécution)

OS disponibles :

  • ubuntu-latest (Ubuntu 22.04)
  • ubuntu-20.04 (version spécifique)
  • windows-latest (Windows Server 2022)
  • windows-2019 (version spécifique)
  • macos-latest (macOS 12+)

Installation de FreePascal dans GitHub Actions

Sur Ubuntu

jobs:
  build-ubuntu:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout du code
        uses: actions/checkout@v3

      - name: Installer FreePascal
        run: |
          sudo apt-get update
          sudo apt-get install -y fpc

      - name: Vérifier l'installation
        run: fpc -iV

Explication :

  • sudo apt-get update : met à jour la liste des packages
  • sudo apt-get install -y fpc : installe FreePascal (l'option -y évite la confirmation)
  • fpc -iV : affiche la version installée

Sur Windows

jobs:
  build-windows:
    runs-on: windows-latest
    steps:
      - name: Checkout du code
        uses: actions/checkout@v3

      - name: Installer FreePascal avec Chocolatey
        run: choco install freepascal -y

      - name: Vérifier l'installation
        run: fpc -iV

Explication :

  • choco install freepascal -y : utilise Chocolatey (gestionnaire de packages Windows)
  • L'option -y accepte automatiquement les confirmations

Installation de Lazarus (si nécessaire)

Ubuntu

- name: Installer Lazarus
  run: |
    sudo apt-get install -y lazarus lcl

Windows

- name: Installer Lazarus
  run: choco install lazarus -y

Premier Workflow Complet : Build Multi-Plateforme

Créer le Fichier de Workflow

Emplacement : .github/workflows/build.yml

name: Build FreePascal Multi-Plateforme

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

jobs:
  # Job 1: Compilation sur Ubuntu
  build-ubuntu:
    runs-on: ubuntu-latest

    steps:
    - name: Récupération du code source
      uses: actions/checkout@v3

    - name: Installation de FreePascal
      run: |
        sudo apt-get update
        sudo apt-get install -y fpc

    - name: Affichage de la version FPC
      run: fpc -iV

    - name: Compilation du projet
      run: |
        cd src
        fpc -O2 -gl MonProgramme.pas

    - name: Vérification de l'exécutable
      run: |
        test -f src/MonProgramme
        echo "✅ Compilation Ubuntu réussie"

  # Job 2: Compilation sur Windows
  build-windows:
    runs-on: windows-latest

    steps:
    - name: Récupération du code source
      uses: actions/checkout@v3

    - name: Installation de FreePascal
      run: choco install freepascal -y

    - name: Affichage de la version FPC
      run: fpc -iV

    - name: Compilation du projet
      run: |
        cd src
        fpc -O2 -gl MonProgramme.pas

    - name: Vérification de l'exécutable
      run: |
        if (Test-Path src\MonProgramme.exe) {
          Write-Host "✅ Compilation Windows réussie"
        } else {
          Write-Error "❌ Exécutable non trouvé"
          exit 1
        }
      shell: pwsh

Comprendre ce Workflow

Déclencheurs :

  • S'exécute sur chaque push vers les branches main ou develop
  • S'exécute sur chaque pull_request vers main

Deux jobs en parallèle :

  1. build-ubuntu : compile sur Ubuntu
  2. build-windows : compile sur Windows

Étapes communes :

  1. Récupère le code avec actions/checkout@v3
  2. Installe FreePascal (différemment selon l'OS)
  3. Affiche la version pour vérification
  4. Compile le projet
  5. Vérifie que l'exécutable existe

Workflow Avancé : Tests Automatiques

Avec FPCUnit

name: Tests FPCUnit

on: [push, pull_request]

jobs:
  test-ubuntu:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Installation FPC et FPCUnit
      run: |
        sudo apt-get update
        sudo apt-get install -y fpc fpcunit

    - name: Compilation des tests
      run: |
        cd tests
        fpc -Fu../src -gl TestsSuite.pas

    - name: Exécution des tests
      run: |
        cd tests
        ./TestsSuite --format=plain

    - name: Vérification du résultat
      run: |
        if [ $? -eq 0 ]; then
          echo "✅ Tous les tests passent"
        else
          echo "❌ Des tests ont échoué"
          exit 1
        fi

  test-windows:
    runs-on: windows-latest

    steps:
    - uses: actions/checkout@v3

    - name: Installation FPC
      run: choco install freepascal -y

    - name: Compilation des tests
      run: |
        cd tests
        fpc -Fu..\src -gl TestsSuite.pas

    - name: Exécution des tests
      run: |
        cd tests
        .\TestsSuite.exe --format=plain

    - name: Vérification du résultat
      shell: pwsh
      run: |
        if ($LASTEXITCODE -eq 0) {
          Write-Host "✅ Tous les tests passent"
        } else {
          Write-Error "❌ Des tests ont échoué"
          exit 1
        }

Matrice de Build : Tester Plusieurs Configurations

Concept de Matrice

Une matrice permet de tester automatiquement plusieurs combinaisons de paramètres (OS, versions, options).

Exemple : Plusieurs Versions de FreePascal

name: Matrice Multi-Versions

on: [push, pull_request]

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
        fpc-version: ['3.2.0', '3.2.2']

    runs-on: ${{ matrix.os }}

    steps:
    - uses: actions/checkout@v3

    - name: Installation FPC ${{ matrix.fpc-version }} sur ${{ matrix.os }}
      if: runner.os == 'Linux'
      run: |
        # Script d'installation selon la version
        echo "Installation de FPC ${{ matrix.fpc-version }}"
        sudo apt-get update
        sudo apt-get install -y fpc

    - name: Installation FPC ${{ matrix.fpc-version }} sur ${{ matrix.os }}
      if: runner.os == 'Windows'
      run: choco install freepascal -y

    - name: Compilation
      run: fpc -O2 MonProgramme.pas

Résultat : Ce workflow crée 4 jobs automatiquement :

  1. Ubuntu + FPC 3.2.0
  2. Ubuntu + FPC 3.2.2
  3. Windows + FPC 3.2.0
  4. Windows + FPC 3.2.2

Matrice avec Exclusions

strategy:
  matrix:
    os: [ubuntu-latest, windows-latest, macos-latest]
    fpc-version: ['3.2.0', '3.2.2']
    exclude:
      # Exclure macOS + FPC 3.2.0 (non supporté)
      - os: macos-latest
        fpc-version: '3.2.0'

Gestion des Artefacts (Artifacts)

Qu'est-ce qu'un Artefact ?

Un artefact est un fichier généré par votre workflow (exécutable, rapport, logs) que vous pouvez télécharger ou réutiliser.

Sauvegarder les Exécutables

name: Build et Sauvegarde des Exécutables

on: [push]

jobs:
  build-and-upload:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]

    runs-on: ${{ matrix.os }}

    steps:
    - uses: actions/checkout@v3

    - name: Installer FPC
      run: |
        if [ "$RUNNER_OS" == "Linux" ]; then
          sudo apt-get update && sudo apt-get install -y fpc
        elif [ "$RUNNER_OS" == "Windows" ]; then
          choco install freepascal -y
        fi
      shell: bash

    - name: Compiler
      run: fpc -O2 MonProgramme.pas

    - name: Upload de l'exécutable Ubuntu
      if: runner.os == 'Linux'
      uses: actions/upload-artifact@v3
      with:
        name: MonProgramme-Linux
        path: MonProgramme

    - name: Upload de l'exécutable Windows
      if: runner.os == 'Windows'
      uses: actions/upload-artifact@v3
      with:
        name: MonProgramme-Windows
        path: MonProgramme.exe

Résultat : Après le build, vous pouvez télécharger MonProgramme-Linux et MonProgramme-Windows depuis l'interface GitHub Actions.

Télécharger un Artefact dans un Autre Job

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Compiler
        run: fpc MonProgramme.pas
      - name: Upload
        uses: actions/upload-artifact@v3
        with:
          name: executable
          path: MonProgramme

  test:
    needs: build  # Attend que 'build' soit terminé
    runs-on: ubuntu-latest
    steps:
      - name: Télécharger l'exécutable
        uses: actions/download-artifact@v3
        with:
          name: executable

      - name: Rendre exécutable
        run: chmod +x MonProgramme

      - name: Exécuter les tests
        run: ./MonProgramme --run-tests

Workflows Conditionnels

Exécuter Seulement sur Certaines Branches

name: Deploy Production

on:
  push:
    branches:
      - main  # Seulement sur la branche main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Déploiement
        run: echo "Déploiement en production"

Conditions au Niveau des Steps

steps:
  - name: Étape qui s'exécute seulement sur Linux
    if: runner.os == 'Linux'
    run: echo "Je suis sur Linux"

  - name: Étape qui s'exécute seulement sur Windows
    if: runner.os == 'Windows'
    run: echo "Je suis sur Windows"

  - name: Étape qui s'exécute seulement sur la branche main
    if: github.ref == 'refs/heads/main'
    run: echo "Je suis sur main"

  - name: Étape qui s'exécute seulement sur les tags
    if: startsWith(github.ref, 'refs/tags/')
    run: echo "C'est un tag de version"

Exécuter sur Pull Request Uniquement

name: Validation PR

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Vérifier le code
        run: |
          fpc -gl -Ci src/*.pas
          echo "✅ Code valide"

Cache pour Accélérer les Builds

Mise en Cache des Dépendances

Le cache permet de réutiliser des fichiers entre les exécutions pour gagner du temps.

name: Build avec Cache

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Cache des packages FPC
      uses: actions/cache@v3
      with:
        path: |
          ~/.fpc
          /usr/lib/fpc
        key: ${{ runner.os }}-fpc-${{ hashFiles('**/fpc.cfg') }}
        restore-keys: |
          ${{ runner.os }}-fpc-

    - name: Installer FPC
      run: sudo apt-get install -y fpc

    - name: Compiler
      run: fpc -O2 MonProgramme.pas

Avantages :

  • Premier build : installe FPC normalement (~2 minutes)
  • Builds suivants : utilise le cache (~10 secondes)

Variables d'Environnement et Secrets

Variables d'Environnement

jobs:
  build:
    runs-on: ubuntu-latest

    env:
      FPC_VERSION: 3.2.2
      BUILD_CONFIG: Release

    steps:
    - name: Utiliser les variables
      run: |
        echo "Version FPC: $FPC_VERSION"
        echo "Configuration: $BUILD_CONFIG"
        fpc -O2 -dRELEASE MonProgramme.pas

Secrets (Données Sensibles)

Pour stocker des mots de passe, clés API, etc.

1. Ajouter un secret dans GitHub :

  • Allez dans Settings → Secrets and variables → Actions
  • Cliquez sur New repository secret
  • Nom : DEPLOY_TOKEN, Valeur : votre_token_secret

2. Utiliser le secret dans le workflow :

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Déployer avec token
      run: |
        echo "Déploiement avec token sécurisé"
        curl -H "Authorization: Bearer ${{ secrets.DEPLOY_TOKEN }}" \
             https://api.example.com/deploy

Important : Les secrets ne sont JAMAIS affichés dans les logs !


Workflow Complet : Pipeline CI/CD Professionnel

Structure du Projet

mon-projet/
├── .github/
│   └── workflows/
│       └── ci-cd.yml
├── src/
│   └── MonProgramme.pas
├── tests/
│   └── TestsSuite.pas
└── README.md

Fichier ci-cd.yml Complet

name: Pipeline CI/CD FreePascal

on:
  push:
    branches: [ main, develop ]
    tags:
      - 'v*'
  pull_request:
    branches: [ main ]

env:
  FPC_VERSION: 3.2.2

jobs:
  # Job 1: Vérification du code
  lint:
    name: Analyse statique du code
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Installer FPC
        run: |
          sudo apt-get update
          sudo apt-get install -y fpc

      - name: Vérifier la syntaxe
        run: |
          find src -name "*.pas" -exec fpc -S {} \;

  # Job 2: Build multi-plateforme
  build:
    name: Compilation ${{ matrix.os }}
    needs: lint
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest]
        include:
          - os: ubuntu-latest
            executable: MonProgramme
          - os: windows-latest
            executable: MonProgramme.exe

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v3

      - name: Installer FPC (Linux)
        if: runner.os == 'Linux'
        run: |
          sudo apt-get update
          sudo apt-get install -y fpc

      - name: Installer FPC (Windows)
        if: runner.os == 'Windows'
        run: choco install freepascal -y

      - name: Compiler le projet
        run: |
          cd src
          fpc -O2 -gl -Ci MonProgramme.pas

      - name: Upload de l'exécutable
        uses: actions/upload-artifact@v3
        with:
          name: MonProgramme-${{ runner.os }}
          path: src/${{ matrix.executable }}

  # Job 3: Tests automatiques
  test:
    name: Tests ${{ matrix.os }}
    needs: build
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v3

      - name: Télécharger l'exécutable
        uses: actions/download-artifact@v3
        with:
          name: MonProgramme-${{ runner.os }}
          path: ./bin

      - name: Rendre exécutable (Linux)
        if: runner.os == 'Linux'
        run: chmod +x bin/MonProgramme

      - name: Installer FPC
        run: |
          if [ "$RUNNER_OS" == "Linux" ]; then
            sudo apt-get update && sudo apt-get install -y fpc fpcunit
          elif [ "$RUNNER_OS" == "Windows" ]; then
            choco install freepascal -y
          fi
        shell: bash

      - name: Compiler les tests
        run: |
          cd tests
          fpc -Fu../src -gl TestsSuite.pas

      - name: Exécuter les tests
        run: |
          cd tests
          if [ "$RUNNER_OS" == "Linux" ]; then
            ./TestsSuite --format=plain
          else
            ./TestsSuite.exe --format=plain
          fi
        shell: bash

  # Job 4: Release automatique (seulement sur tags)
  release:
    name: Créer une Release
    if: startsWith(github.ref, 'refs/tags/v')
    needs: [build, test]
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Télécharger tous les artefacts
        uses: actions/download-artifact@v3

      - name: Créer l'archive Linux
        run: |
          cd MonProgramme-Linux
          tar -czf ../MonProgramme-Linux-${{ github.ref_name }}.tar.gz *

      - name: Créer l'archive Windows
        run: |
          cd MonProgramme-Windows
          zip -r ../MonProgramme-Windows-${{ github.ref_name }}.zip *

      - name: Créer la Release GitHub
        uses: softprops/action-gh-release@v1
        with:
          files: |
            MonProgramme-Linux-${{ github.ref_name }}.tar.gz
            MonProgramme-Windows-${{ github.ref_name }}.zip
          draft: false
          prerelease: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Fonctionnalités de ce Pipeline

1. Analyse statique (lint)

  • Vérifie la syntaxe de tous les fichiers .pas
  • S'exécute en premier pour détecter rapidement les erreurs

2. Compilation multi-plateforme (build)

  • Compile sur Ubuntu et Windows en parallèle
  • Sauvegarde les exécutables comme artefacts
  • Utilise une matrice pour éviter la duplication

3. Tests automatiques (test)

  • Télécharge les exécutables compilés
  • Compile et exécute la suite de tests FPCUnit
  • Valide sur les deux plateformes

4. Release automatique (release)

  • S'exécute seulement quand vous créez un tag (ex: v1.0.0)
  • Crée des archives .tar.gz et .zip
  • Publie automatiquement une Release GitHub avec les binaires

Badge de Statut dans le README

Ajoutez un badge pour montrer l'état de votre build :

# Mon Projet FreePascal

![Build Status](https://github.com/username/repo/workflows/CI-CD/badge.svg)

Le badge affichera :

  • ✅ Vert si le build passe
  • ❌ Rouge si le build échoue
  • 🟡 Jaune si le build est en cours

Débogage des Workflows

Afficher des Informations de Debug

steps:
  - name: Debug - Informations système
    run: |
      echo "OS: $RUNNER_OS"
      echo "Architecture: $RUNNER_ARCH"
      echo "Workspace: $GITHUB_WORKSPACE"
      echo "Branch: $GITHUB_REF"
      echo "Commit: $GITHUB_SHA"

  - name: Debug - Lister les fichiers
    run: |
      ls -la
      pwd

Activer le Mode Debug

Dans GitHub :

  1. Allez dans Settings → Secrets and variables → Actions
  2. Ajoutez deux secrets :
    • ACTIONS_RUNNER_DEBUG = true
    • ACTIONS_STEP_DEBUG = true

Les logs afficheront beaucoup plus de détails.

Tester Localement avec act

act permet d'exécuter GitHub Actions localement :

# Installation (Linux)
curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash

# Exécuter le workflow localement
act -j build

Bonnes Pratiques

1. Nommer Clairement les Jobs et Steps

Mauvais :

steps:
  - name: Step 1
    run: fpc test.pas

Bon :

steps:
  - name: Compilation des tests unitaires
    run: fpc -Fu../src tests/TestsSuite.pas

2. Utiliser fail-fast Intelligemment

strategy:
  fail-fast: false  # Continue même si un job échoue
  matrix:
    os: [ubuntu-latest, windows-latest]

Sans fail-fast: false, si Windows échoue, Ubuntu est annulé automatiquement.

3. Séparer Build et Test

jobs:
  build:
    # Compile le code

  test:
    needs: build  # Attend la fin du build
    # Exécute les tests

Avantage : en cas d'échec de compilation, les tests ne s'exécutent pas inutilement.

4. Versionner les Actions

Bon :

- uses: actions/checkout@v3  # Version fixe

Risqué :

- uses: actions/checkout@main  # Peut changer sans prévenir

5. Nettoyer les Artefacts

Les artefacts consomment de l'espace de stockage :

- name: Upload de l'exécutable
  uses: actions/upload-artifact@v3
  with:
    name: executable
    path: MonProgramme
    retention-days: 7  # Supprimer après 7 jours

6. Utiliser des Scripts pour le Code Complexe

Au lieu de mettre beaucoup de lignes run:, créez un script :

scripts/build.sh :

#!/bin/bash
set -e

echo "Compilation en cours..."  
cd src  
fpc -O2 -gl MonProgramme.pas  
echo "✅ Compilation réussie"

Workflow :

steps:
  - name: Compiler
    run: bash scripts/build.sh

Limites et Quotas

Limites Gratuites (par mois)

Type de Compte Minutes Gratuites Espace Artefacts
Public (open source) Illimité 500 MB
Privé (Free) 2000 minutes 500 MB
Privé (Pro) 3000 minutes 1 GB
Privé (Team) 3000 minutes 2 GB

Multiplicateurs par OS

OS Multiplicateur
Linux 1x
Windows 2x
macOS 10x

Exemple : Un build de 10 minutes sur Windows compte comme 20 minutes.

Optimiser la Consommation

  1. Utiliser le cache pour réduire les temps de build
  2. Privilégier Linux quand c'est possible
  3. Paralléliser intelligemment sans abus
  4. Nettoyer les artefacts régulièrement

Cas d'Usage Avancés

Build Conditionnel selon le Message de Commit

jobs:
  build:
    if: "!contains(github.event.head_commit.message, '[skip ci]')"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build
        run: fpc MonProgramme.pas

Si votre commit contient [skip ci], le build est ignoré.

Notifications Slack/Discord

jobs:
  notify:
    runs-on: ubuntu-latest
    if: always()  # S'exécute même si les autres jobs échouent
    needs: [build, test]
    steps:
      - name: Notifier sur Discord
        if: failure()
        run: |
          curl -X POST ${{ secrets.DISCORD_WEBHOOK }} \
            -H "Content-Type: application/json" \
            -d '{"content":"❌ Build échoué pour ${{ github.repository }}"}'

      - name: Notifier sur Slack
        if: success()
        run: |
          curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
            -H "Content-Type: application/json" \
            -d '{
              "text": "✅ Build réussi pour ${{ github.repository }}",
              "attachments": [{
                "color": "good",
                "fields": [{
                  "title": "Branche",
                  "value": "${{ github.ref_name }}",
                  "short": true
                }, {
                  "title": "Commit",
                  "value": "${{ github.sha }}",
                  "short": true
                }]
              }]
            }'

Configuration :

  1. Créez un webhook dans Discord/Slack
  2. Ajoutez-le comme secret : DISCORD_WEBHOOK ou SLACK_WEBHOOK
  3. Le workflow envoie automatiquement des notifications

Déploiement Automatique

Déploiement sur un Serveur Linux via SSH

name: Déploiement Production

on:
  push:
    branches:
      - main
    tags:
      - 'v*'

jobs:
  deploy:
    name: Déployer sur serveur Linux
    runs-on: ubuntu-latest

    steps:
      - name: Checkout du code
        uses: actions/checkout@v3

      - name: Installer FreePascal
        run: |
          sudo apt-get update
          sudo apt-get install -y fpc

      - name: Compiler pour production
        run: |
          cd src
          fpc -O3 -XXs -CX MonProgramme.pas

      - name: Créer l'archive de déploiement
        run: |
          mkdir -p deploy
          cp src/MonProgramme deploy/
          cp -r config deploy/
          tar -czf deploy.tar.gz deploy/

      - name: Déployer via SSH
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.DEPLOY_HOST }}
          username: ${{ secrets.DEPLOY_USER }}
          key: ${{ secrets.DEPLOY_SSH_KEY }}
          source: "deploy.tar.gz"
          target: "/tmp/"

      - name: Extraire et redémarrer le service
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.DEPLOY_HOST }}
          username: ${{ secrets.DEPLOY_USER }}
          key: ${{ secrets.DEPLOY_SSH_KEY }}
          script: |
            cd /opt/monapp
            sudo systemctl stop monapp
            tar -xzf /tmp/deploy.tar.gz
            cp -r deploy/* .
            sudo systemctl start monapp
            sudo systemctl status monapp
            rm -rf /tmp/deploy.tar.gz deploy/

Secrets nécessaires :

  • DEPLOY_HOST : IP ou nom d'hôte du serveur
  • DEPLOY_USER : Nom d'utilisateur SSH
  • DEPLOY_SSH_KEY : Clé privée SSH (format PEM)

Déploiement sur un Serveur Windows

jobs:
  deploy-windows:
    name: Déployer sur serveur Windows
    runs-on: windows-latest

    steps:
      - uses: actions/checkout@v3

      - name: Compiler
        run: |
          choco install freepascal -y
          cd src
          fpc -O3 MonProgramme.pas

      - name: Copier vers le serveur
        run: |
          # Utiliser WinSCP ou PowerShell Remoting
          $secPassword = ConvertTo-SecureString "${{ secrets.DEPLOY_PASSWORD }}" -AsPlainText -Force
          $credential = New-Object System.Management.Automation.PSCredential("${{ secrets.DEPLOY_USER }}", $secPassword)

          $session = New-PSSession -ComputerName ${{ secrets.DEPLOY_HOST }} -Credential $credential

          Copy-Item -Path "src\MonProgramme.exe" `
                    -Destination "C:\Apps\MonApp\" `
                    -ToSession $session

          Invoke-Command -Session $session -ScriptBlock {
            Stop-Service -Name "MonAppService"
            Start-Service -Name "MonAppService"
          }

          Remove-PSSession $session
        shell: pwsh

Déploiement Docker Multi-Plateforme

Créer et Publier des Images Docker

name: Docker Build et Push

on:
  push:
    branches: [ main ]
    tags: [ 'v*' ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-docker:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Login vers GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}

      - name: Build et Push image Docker
        uses: docker/build-push-action@v4
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Dockerfile FreePascal :

# Dockerfile
FROM ubuntu:22.04 as builder

# Installer FreePascal
RUN apt-get update && \
    apt-get install -y fpc && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /build

# Copier le code source
COPY src/ ./src/

# Compiler
RUN cd src && fpc -O3 -XXs MonProgramme.pas

# Image finale légère
FROM ubuntu:22.04

RUN apt-get update && \
    apt-get install -y ca-certificates && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Copier l'exécutable compilé
COPY --from=builder /build/src/MonProgramme .

# Copier les fichiers de configuration
COPY config/ ./config/

# Exposition du port (si applicable)
EXPOSE 8080

# Commande de démarrage
CMD ["./MonProgramme"]

Tests de Performance Automatisés

Benchmark et Mesure de Performance

name: Tests de Performance

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

jobs:
  benchmark:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Installer FreePascal
        run: |
          sudo apt-get update
          sudo apt-get install -y fpc

      - name: Compiler avec optimisations
        run: |
          cd src
          fpc -O3 -Xs MonProgramme.pas

      - name: Exécuter les benchmarks
        run: |
          ./src/MonProgramme --benchmark > benchmark_results.txt
          cat benchmark_results.txt

      - name: Analyser les résultats
        run: |
          # Extraire le temps d'exécution
          TIME=$(grep "Temps total:" benchmark_results.txt | awk '{print $3}')
          echo "Temps d'exécution: $TIME secondes"

          # Comparer avec la baseline
          BASELINE=10.0
          if (( $(echo "$TIME > $BASELINE" | bc -l) )); then
            echo "⚠️ Performance dégradée: $TIME s (baseline: $BASELINE s)"
            exit 1
          else
            echo "✅ Performance acceptable: $TIME s"
          fi

      - name: Upload des résultats
        uses: actions/upload-artifact@v3
        with:
          name: benchmark-results
          path: benchmark_results.txt

      - name: Commenter la PR avec les résultats
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v6
        with:
          script: |
            const fs = require('fs');
            const results = fs.readFileSync('benchmark_results.txt', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## 📊 Résultats des Benchmarks\n\`\`\`\n${results}\n\`\`\``
            });

Analyse de Sécurité et Qualité du Code

Scanner de Vulnérabilités

name: Analyse de Sécurité

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  schedule:
    # Scan hebdomadaire le lundi à 9h
    - cron: '0 9 * * 1'

jobs:
  security-scan:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Scanner les dépendances
        run: |
          # Rechercher les bibliothèques connues avec vulnérabilités
          echo "Analyse des dépendances..."
          find . -name "*.pas" -exec grep -l "uses.*SysUtils" {} \;

      - name: Analyser le code pour les patterns dangereux
        run: |
          echo "Recherche de patterns de code dangereux..."

          # Rechercher les commandes shell potentiellement dangereuses
          if grep -r "ShellExecute\|Exec\|System(" src/; then
            echo "⚠️ Commandes shell détectées - vérifier la sécurité"
          fi

          # Rechercher les allocations mémoire non libérées
          if grep -r "GetMem\|New(" src/ | grep -v "FreeMem\|Dispose"; then
            echo "⚠️ Allocations mémoire potentiellement non libérées"
          fi

      - name: Vérifier les permissions de fichiers
        run: |
          # S'assurer qu'aucun fichier exécutable n'est commité par erreur
          find . -type f -perm /111 ! -name "*.sh" | grep -v ".git" || true

Analyse de la Complexité du Code

jobs:
  code-quality:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Installer les outils d'analyse
        run: |
          sudo apt-get update
          sudo apt-get install -y fpc cloc

      - name: Statistiques du code
        run: |
          echo "## 📊 Statistiques du Code" > code_stats.md
          echo "" >> code_stats.md
          cloc src/ --md >> code_stats.md
          cat code_stats.md

      - name: Analyser la complexité
        run: |
          # Compter les fonctions longues (>100 lignes)
          echo "Recherche de fonctions trop longues..."
          for file in src/*.pas; do
            awk '/^(function|procedure)/{start=NR} /^end;/{
              if (NR-start > 100)
                print FILENAME ":" start " - Fonction trop longue (" NR-start " lignes)"
            }' "$file"
          done

      - name: Vérifier les standards de code
        run: |
          # Vérifier l'indentation
          echo "Vérification de l'indentation..."
          find src/ -name "*.pas" -exec grep -n "^[^ ]" {} + | grep -v "^[^:]*:[0-9]*:(uses\|type\|var\|const\|begin\|end)" || true

      - name: Commenter la PR
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v6
        with:
          script: |
            const fs = require('fs');
            const stats = fs.readFileSync('code_stats.md', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: stats
            });

Documentation Automatique

Générer et Publier la Documentation

name: Documentation

on:
  push:
    branches: [ main ]

jobs:
  generate-docs:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Installer PasDoc
        run: |
          sudo apt-get update
          sudo apt-get install -y pasdoc

      - name: Générer la documentation
        run: |
          mkdir -p docs/api
          pasdoc \
            --source src/ \
            --output docs/api/ \
            --format html \
            --title "Documentation API - Mon Projet" \
            --introduction README.md

      - name: Créer l'index de documentation
        run: |
          cat > docs/index.html << 'EOF'
          <!DOCTYPE html>
          <html>
          <head>
            <title>Documentation - Mon Projet FreePascal</title>
            <meta charset="UTF-8">
            <style>
              body { font-family: Arial, sans-serif; margin: 40px; }
              h1 { color: #333; }
              .link-box {
                background: #f5f5f5;
                padding: 20px;
                margin: 10px 0;
                border-radius: 5px;
              }
            </style>
          </head>
          <body>
            <h1>📚 Documentation - Mon Projet FreePascal</h1>
            <div class="link-box">
              <h2>🔗 Liens Utiles</h2>
              <ul>
                <li><a href="api/">Documentation API</a></li>
                <li><a href="https://github.com/${{ github.repository }}">Code Source</a></li>
                <li><a href="https://github.com/${{ github.repository }}/releases">Releases</a></li>
              </ul>
            </div>
          </body>
          </html>
          EOF

      - name: Déployer sur GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs
          publish_branch: gh-pages

Configuration GitHub Pages :

  1. Allez dans Settings → Pages
  2. Source : Deploy from a branch
  3. Branch : gh-pages / root
  4. Votre documentation sera accessible à https://username.github.io/repo/

Gestion des Versions Automatique

Semantic Versioning et Changelog

name: Release Automatique

on:
  push:
    branches: [ main ]

jobs:
  release:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0  # Récupère tout l'historique git

      - name: Analyser les commits
        id: semantic
        uses: paulhatch/semantic-version@v5.0.2
        with:
          tag_prefix: "v"
          major_pattern: "(BREAKING CHANGE|MAJOR)"
          minor_pattern: "(feat|FEATURE)"
          patch_pattern: "(fix|bugfix|patch)"
          format: "${major}.${minor}.${patch}"

      - name: Générer le changelog
        id: changelog
        run: |
          PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")

          if [ -z "$PREVIOUS_TAG" ]; then
            COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges)
          else
            COMMITS=$(git log ${PREVIOUS_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges)
          fi

          echo "CHANGELOG<<EOF" >> $GITHUB_OUTPUT
          echo "## Version ${{ steps.semantic.outputs.version }}" >> $GITHUB_OUTPUT
          echo "" >> $GITHUB_OUTPUT
          echo "### Changements :" >> $GITHUB_OUTPUT
          echo "$COMMITS" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Compiler les binaires
        run: |
          sudo apt-get update && sudo apt-get install -y fpc
          cd src
          fpc -O3 MonProgramme.pas

      - name: Créer le tag
        run: |
          git config user.name "GitHub Actions"
          git config user.email "actions@github.com"
          git tag -a "v${{ steps.semantic.outputs.version }}" -m "Release v${{ steps.semantic.outputs.version }}"
          git push origin "v${{ steps.semantic.outputs.version }}"

      - name: Créer la Release GitHub
        uses: softprops/action-gh-release@v1
        with:
          tag_name: v${{ steps.semantic.outputs.version }}
          name: Release v${{ steps.semantic.outputs.version }}
          body: ${{ steps.changelog.outputs.CHANGELOG }}
          draft: false
          prerelease: false
          files: |
            src/MonProgramme
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Convention de commits pour semantic versioning :

feat: Nouvelle fonctionnalité       → Version mineure (1.0.0 → 1.1.0)  
fix: Correction de bug               → Version patch (1.0.0 → 1.0.1)  
BREAKING CHANGE: Changement majeur   → Version majeure (1.0.0 → 2.0.0)

Workflows Réutilisables

Créer un Workflow Réutilisable

Fichier .github/workflows/build-reusable.yml :

name: Build Réutilisable

on:
  workflow_call:
    inputs:
      os:
        required: true
        type: string
      fpc-version:
        required: false
        type: string
        default: 'latest'
      build-config:
        required: false
        type: string
        default: 'Release'
    outputs:
      artifact-name:
        description: "Nom de l'artefact créé"
        value: ${{ jobs.build.outputs.artifact }}

jobs:
  build:
    runs-on: ${{ inputs.os }}
    outputs:
      artifact: ${{ steps.upload.outputs.artifact-name }}

    steps:
      - uses: actions/checkout@v3

      - name: Installer FPC (${{ inputs.os }})
        run: |
          if [ "$RUNNER_OS" == "Linux" ]; then
            sudo apt-get update && sudo apt-get install -y fpc
          elif [ "$RUNNER_OS" == "Windows" ]; then
            choco install freepascal -y
          fi
        shell: bash

      - name: Compiler (${{ inputs.build-config }})
        run: |
          cd src
          if [ "${{ inputs.build-config }}" == "Release" ]; then
            fpc -O3 -XXs MonProgramme.pas
          else
            fpc -g -gl MonProgramme.pas
          fi
        shell: bash

      - name: Upload artefact
        id: upload
        uses: actions/upload-artifact@v3
        with:
          name: MonProgramme-${{ runner.os }}-${{ inputs.build-config }}
          path: src/MonProgramme*

Utiliser le Workflow Réutilisable

Fichier .github/workflows/main.yml :

name: Pipeline Principal

on: [push, pull_request]

jobs:
  build-linux-debug:
    uses: ./.github/workflows/build-reusable.yml
    with:
      os: ubuntu-latest
      build-config: Debug

  build-linux-release:
    uses: ./.github/workflows/build-reusable.yml
    with:
      os: ubuntu-latest
      build-config: Release

  build-windows-release:
    uses: ./.github/workflows/build-reusable.yml
    with:
      os: windows-latest
      build-config: Release

Avantages :

  • ✅ Évite la duplication de code
  • ✅ Maintenance centralisée
  • ✅ Réutilisable dans plusieurs workflows

Stratégies de Tests Avancées

Tests Paramétrés avec Matrice Dynamique

name: Tests Paramétrés

on: [push, pull_request]

jobs:
  prepare-matrix:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}

    steps:
      - uses: actions/checkout@v3

      - name: Générer la matrice de test
        id: set-matrix
        run: |
          # Lire les configurations depuis un fichier JSON
          MATRIX=$(cat .github/test-matrix.json | jq -c .)
          echo "matrix=$MATRIX" >> $GITHUB_OUTPUT

  test:
    needs: prepare-matrix
    strategy:
      matrix: ${{ fromJson(needs.prepare-matrix.outputs.matrix) }}

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v3

      - name: Test ${{ matrix.test-name }}
        run: |
          echo "Exécution du test: ${{ matrix.test-name }}"
          echo "Paramètres: ${{ matrix.params }}"

Fichier .github/test-matrix.json :

{
  "include": [
    {
      "os": "ubuntu-latest",
      "test-name": "Performance Tests",
      "params": "--benchmark"
    },
    {
      "os": "ubuntu-latest",
      "test-name": "Integration Tests",
      "params": "--integration"
    },
    {
      "os": "windows-latest",
      "test-name": "UI Tests",
      "params": "--ui-tests"
    }
  ]
}

Gestion des Erreurs et Retry

Réessayer en Cas d'Échec

jobs:
  build-with-retry:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Compiler avec retry
        uses: nick-invision/retry@v2
        with:
          timeout_minutes: 10
          max_attempts: 3
          retry_wait_seconds: 30
          command: |
            sudo apt-get update
            sudo apt-get install -y fpc
            cd src
            fpc -O2 MonProgramme.pas

      - name: Tests avec retry
        uses: nick-invision/retry@v2
        with:
          timeout_minutes: 5
          max_attempts: 2
          command: |
            ./tests/run_tests.sh

Continue-on-error pour les Jobs Optionnels

jobs:
  mandatory-build:
    runs-on: ubuntu-latest
    steps:
      - name: Build principal
        run: fpc MonProgramme.pas

  optional-benchmark:
    runs-on: ubuntu-latest
    continue-on-error: true  # N'arrête pas le workflow si ce job échoue
    steps:
      - name: Benchmark
        run: ./benchmark.sh

  deployment:
    needs: mandatory-build  # N'attend PAS optional-benchmark
    runs-on: ubuntu-latest
    steps:
      - name: Déployer
        run: ./deploy.sh

Workflows Composites

Créer une Action Composite Réutilisable

Fichier .github/actions/setup-fpc/action.yml :

name: 'Setup FreePascal'  
description: 'Installe FreePascal avec cache'

inputs:
  version:
    description: 'Version de FPC à installer'
    required: false
    default: 'latest'
  cache:
    description: 'Activer le cache'
    required: false
    default: 'true'

outputs:
  fpc-version:
    description: 'Version de FPC installée'
    value: ${{ steps.get-version.outputs.version }}

runs:
  using: 'composite'
  steps:
    - name: Cache FPC
      if: inputs.cache == 'true'
      uses: actions/cache@v3
      with:
        path: |
          ~/.fpc
          /usr/lib/fpc
        key: ${{ runner.os }}-fpc-${{ inputs.version }}

    - name: Installer FPC (Linux)
      if: runner.os == 'Linux'
      run: sudo apt-get update && sudo apt-get install -y fpc
      shell: bash

    - name: Installer FPC (Windows)
      if: runner.os == 'Windows'
      run: choco install freepascal -y
      shell: pwsh

    - name: Obtenir la version
      id: get-version
      run: echo "version=$(fpc -iV)" >> $GITHUB_OUTPUT
      shell: bash

Utiliser l'Action Composite

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup FreePascal
        uses: ./.github/actions/setup-fpc
        with:
          version: 'latest'
          cache: 'true'

      - name: Compiler
        run: fpc MonProgramme.pas

Conclusion et Bonnes Pratiques Finales

Checklist pour un Workflow de Qualité

Organisation

  • Noms de workflows explicites
  • Jobs bien séparés (build/test/deploy)
  • Commentaires dans les fichiers YAML complexes

Performance

  • Cache activé pour les dépendances
  • Parallélisation des jobs indépendants
  • Artefacts nettoyés automatiquement

Sécurité

  • Secrets utilisés pour les données sensibles
  • Pas de secrets dans les logs
  • Permissions minimales pour les tokens

Qualité

  • Tests automatiques à chaque commit
  • Couverture de code mesurée
  • Déploiement uniquement après validation

Maintenance

  • Versions fixées pour les actions (@v3 au lieu de @main)
  • Documentation du workflow
  • Notifications configurées

Ressources Utiles

Documentation officielle :

Actions populaires pour FreePascal :

  • actions/checkout@v3 - Récupérer le code
  • actions/upload-artifact@v3 - Sauvegarder les artefacts
  • actions/cache@v3 - Mise en cache
  • softprops/action-gh-release@v1 - Créer des releases

Exemple de Projet Complet

Pour un projet FreePascal professionnel, voici une structure recommandée :

.github/
├── workflows/
│   ├── ci.yml              # Build et tests continus
│   ├── release.yml         # Création de releases
│   ├── documentation.yml   # Génération de docs
│   └── security.yml        # Scans de sécurité
├── actions/
│   └── setup-fpc/          # Action composite réutilisable
│       └── action.yml
└── test-matrix.json        # Configuration des tests

src/  
tests/  
docs/  
scripts/

Avec GitHub Actions, vous automatisez complètement votre workflow de développement FreePascal, du commit au déploiement, sur Windows et Ubuntu en parallèle ! 🚀

⏭️ GitLab CI avec runners multi-OS