Objectifs d'apprentissage
À la fin de ce cours, l'apprenant peut :
- distinguer intégration continue (CI), livraison continue et déploiement continu, et situer GitHub Actions ;
- lire et écrire un workflow YAML : événements (
on), jobs, steps, runners ; - enchaîner des jobs (
needs), utiliser une matrice, un cache et des artefacts, en sachant les différencier ; - placer des gates de qualité (lint, tests) avant tout déploiement ;
- gérer secrets, variables et environnements protégés sans divulguer de secret ;
- restreindre les permissions du
GITHUB_TOKENau minimum ; - épingler les actions par SHA de commit et expliquer le risque de chaîne d'approvisionnement ;
- reconnaître l'injection de script et le danger de
pull_request_targetavec du code non fiable ; - décrire, sans l'exécuter, un déploiement vers Cloudflare Pages ;
- rappeler la règle de l'Orchestrator : toute publication passe par
/publier-pagesetgardien-confidentialite.
Prérequis
- Cours « Git » : commits, branches, dépôts distants en HTTPS ; cours « Cloudflare » pour le chapitre 11.
- Savoir lire du YAML (indentation, listes, dictionnaires) et les commandes de base d'un projet (
make test,npm test,python3 -m unittest). - Un dépôt GitHub privé de test, jetable, sans donnée réelle. Aucun exercice n'a besoin d'un secret réel ni d'un déploiement réel. Les fonctions comme les environnements protégés dépendent de l'offre GitHub (chapitre 8) : offre de Stéphane inconnue.
Parcours et chapitres
1. CI, livraison et déploiement continus
L'intégration continue vérifie automatiquement chaque changement (compilation, lint, tests) ; la livraison continue prépare en plus un livrable prêt à publier ; le déploiement continu le publie sans intervention. Ces trois définitions sont courantes dans l'industrie ; la documentation GitHub consultée ne les redéfinit pas ici (formulation : non vérifiée). Une chaîne saine place des points de contrôle : tests et lint avant le build, approbation humaine avant la production.
2. Anatomie d'un workflow
D'après la page « Workflow syntax », un workflow est un fichier YAML dans .github/workflows/. Éléments :
| Élément | Rôle |
|---|---|
name | nom affiché |
on | événements déclencheurs : push, pull_request, schedule (cron), workflow_dispatch (manuel), workflow_call (réutilisable) |
permissions | droits du GITHUB_TOKEN, au niveau du workflow ou d'un job |
env | variables d'environnement (workflow, job ou step) |
jobs.<id> | unités de travail, parallèles par défaut |
runs-on | type de runner du job |
needs | dépendance : le job attend la réussite d'un autre |
steps | étapes d'un job : uses (une action) ou run (une commande) |
if | condition d'exécution |
timeout-minutes | durée maximale du job |
concurrency | limite les exécutions simultanées d'un même groupe |
environment | environnement de déploiement (règles de protection) |
Un runner est la machine qui exécute un job : hébergé par GitHub ou auto-hébergé. Les images, tailles et quotas des runners hébergés n'ont pas été relus : non vérifié. Chaque job tourne sur un runner propre ; les fichiers ne passent d'un job à l'autre que par des artefacts (chapitre 5).
Un premier workflow, sans secret, qui ne fait que lire le code et lancer des vérifications :
name: ci
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
qualite:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@<SHA-COMPLET-40-CARACTERES> # v4
- name: Lint
run: make lint
- name: Tests
run: make testLes commandes make lint et make test sont des exemples : elles supposent un Makefile du projet. Le nom de l'image ubuntu-latest figure dans la documentation d'exemple ; l'image qu'il désigne à la date du jour n'a pas été vérifiée.
À retenir : un workflow est du code qui s'exécute avec des droits sur le dépôt. Il se relit et se revoit comme du code applicatif (chapitre 9).
3. Jobs, dépendances et gates de qualité
Les jobs s'exécutent en parallèle sauf si needs crée un ordre. Une gate est un job dont l'échec bloque la suite :
jobs:
qualite:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@<SHA-COMPLET-40-CARACTERES> # v4
- run: make lint
- run: make test
build:
needs: qualite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@<SHA-COMPLET-40-CARACTERES> # v4
- run: make buildSi qualite échoue, build n'est pas lancé. Règles de bon sens : lint et tests rapides en premier ; un déploiement dépend toujours (needs) de la réussite des tests ; une branche protégée exige que ces contrôles passent avant fusion (réglage de protection de branche : non relu). Une condition if: github.event_name == 'push' limite un job à certains événements. concurrency avec cancel-in-progress: true évite d'empiler des exécutions sur une même branche.
4. Matrice de tests
Une matrice (strategy.matrix) décline un job sur plusieurs combinaisons de valeurs ; fail-fast: true arrête les autres combinaisons dès qu'une échoue.
jobs:
tests:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
python: ["3.12", "3.13"]
steps:
- uses: actions/checkout@<SHA-COMPLET-40-CARACTERES> # v4
- run: echo "Version visée ${{ matrix.python }}"Les versions de Python de l'exemple sont illustratives ; les versions de Stéphane sont inconnues. Chaque combinaison est un job distinct, donc consomme des minutes d'exécution (quotas : non vérifiés).
5. Cache et artefacts
Deux mécanismes, deux usages (pages « Dependency caching » et « Store and share data ») :
Cache (actions/cache) | Artefact (actions/upload-artifact / download-artifact) | |
|---|---|---|
| But | accélérer en réutilisant des dépendances | transmettre un résultat entre jobs ou le conserver |
| Identification | key (512 caractères au plus), restore-keys | name, path |
| Durée | suppression après 7 jours sans accès (d'après la page) | retention-days, plafonné par le dépôt ou l'organisation |
| Portée | branche courante, par défaut, base ; branches sœurs séparées | le run du workflow |
| Taille | 10 Go par dépôt par défaut (d'après la page) | selon l'offre, non vérifiée |
- uses: actions/cache@<SHA-COMPLET-40-CARACTERES> # v4
with:
path: ~/.cache/projet-demo
key: deps-${{ hashFiles('requirements.txt') }}
restore-keys: deps-
- run: make build
- uses: actions/upload-artifact@<SHA-COMPLET-40-CARACTERES> # v4
with:
name: site-demo
path: dist
retention-days: 5Attention : ne jamais mettre un secret, un jeton ou un fichier d'identifiants dans un chemin mis en cache ou dans un artefact : d'après la page, quiconque peut lire le dépôt peut lire le cache, et un artefact se télécharge. Ne téléverser que dist, jamais le dossier racine (qui peut contenir un .env, un .git).
Une action download-artifact en version @v5 figure dans l'exemple officiel, upload-artifact en @v4 : l'écart de versions est celui de la page, pas une recommandation. Compatibilité des versions entre elles : non vérifiée.
6. Variables et secrets
Les variables (vars.NOM) servent aux valeurs non sensibles ; les secrets (secrets.NOM) aux valeurs sensibles. Ils se définissent au niveau du dépôt, de l'organisation ou d'un environnement (chapitre 8). La page « Secure use » recommande de :
- appliquer le moindre privilège à chaque identifiant ;
- ne pas utiliser de données structurées (JSON, YAML) comme secret, car le masquage des journaux repose sur une correspondance exacte ; créer un secret par valeur ;
- masquer avec
::add-mask::VALEURtoute valeur sensible qui n'est pas un secret GitHub (par exemple une valeur dérivée) ; - enregistrer les secrets générés pour qu'ils soient masqués dans les journaux.
Attention : un secret n'est jamais dans le dépôt, un fichier de workflow, un artefact, un cache ni un journal de workflow. Le masquage des journaux est un filet de sécurité, pas une garantie : une valeur transformée (encodée, découpée) peut échapper au masque. Ne pas afficher d'environnement (env, printenv), ne pas faire echo "${{ secrets.X }}".
Un secret se consomme de préférence via une variable d'environnement d'un seul step :
- name: Déployer
env:
JETON_DEPLOIEMENT: ${{ secrets.JETON_DEPLOIEMENT }}
run: ./deployer.shPour les secrets locaux de Stéphane, la règle de l'Orchestrator reste le Trousseau macOS (bin/secret) ; un secret de CI se saisit dans l'interface GitHub (« Settings », « Secrets and variables ») et n'est jamais relu après coup. Les limites de taille et le nombre de secrets : non vérifiés.
7. GITHUB_TOKEN : permissions au minimum
GITHUB_TOKEN est un jeton fourni automatiquement à chaque exécution (${{ secrets.GITHUB_TOKEN }} ou github.token). La page recommande de lui accorder « le moindre accès nécessaire » et de fixer par défaut la lecture seule sur le contenu du dépôt. On l'exprime avec permissions :
permissions:
contents: read
jobs:
commentaire:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- run: echo "Ce job peut commenter les pull requests, rien d'autre"Bonnes pratiques :
- mettre
permissions: contents: readen tête de chaque workflow ; - n'élargir qu'au niveau du job qui en a besoin ;
- régler dans les paramètres du dépôt ou de l'organisation les permissions par défaut en lecture seule (chemin exact des menus : non vérifié) ;
- si les permissions ne suffisent pas, la documentation propose une application GitHub ou un jeton personnel stocké comme secret ; préférer l'application, à droits limités (détail : non vérifié).
Que le jeton expire à la fin du job et qu'il ne puisse pas déclencher certains autres workflows est un comportement connu mais non confirmé par les pages lues ici.
8. Environnements et approbation
Un environnement (environment: production) est une cible de déploiement avec des règles de protection. D'après la page « Managing environments » : un job qui le référence doit respecter ses règles avant de s'exécuter. Règles décrites : relecteurs obligatoires (jusqu'à 6 personnes ou équipes, avec option d'empêcher l'auto-approbation), temporisation, restriction des branches ou étiquettes autorisées à déployer, règles personnalisées par application GitHub, contrôle du contournement par les administrateurs. Les secrets et variables d'environnement ne sont accessibles qu'une fois les règles satisfaites : c'est la bonne place pour les identifiants de déploiement.
deploiement:
needs: [qualite, build]
runs-on: ubuntu-latest
environment: production
permissions:
contents: read
steps:
- uses: actions/download-artifact@<SHA-COMPLET-40-CARACTERES> # v5
with:
name: site-demoAttention : d'après la page, avec GitHub Free les environnements ne se configurent que pour les dépôts publics ; les dépôts privés exigent une offre supérieure. L'offre de Stéphane est inconnue : vérifier avant de compter sur cette protection.
9. Supply chain : épingler les actions
Une action tierce est du code exécuté avec les droits du job (et avec ses secrets s'il en reçoit). Un tag comme @v4 peut être déplacé si le dépôt de l'action est compromis. La page « Secure use » indique que la meilleure protection est le fichier de verrouillage des dépendances de workflow lorsqu'il est disponible (fonction non relue), sinon d'épingler l'action sur le SHA complet d'un commit.
# Épinglé : le SHA identifie un contenu précis, le commentaire garde la lisibilité
- uses: actions/checkout@<SHA-COMPLET-40-CARACTERES> # v4Marche à suivre :
- relever le SHA complet de 40 caractères sur la page de la version choisie de l'action, dans le dépôt de l'auteur ;
- vérifier que ce SHA appartient bien au dépôt de l'action et non à un fork (point d'attention général, non confirmé par les pages lues) ;
- écrire le SHA et la version dans un commentaire ;
- activer les alertes Dependabot et la revue des dépendances pour suivre les mises à jour, et CODEOWNERS pour exiger une approbation sur les modifications de
.github/workflows/(tous cités par la page) ; - limiter les actions autorisées aux sources de confiance (réglage de dépôt ou d'organisation : non relu).
Pour repérer les actions non épinglées dans un dépôt de test :
grep -rn "uses:" .github/workflows | grep -v "@[0-9a-f]\{40\}"Bloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : Terminal, à la racine du dépôt de test ; les actions locales (
./) apparaîtront aussi et sont normales. - Droits : utilisateur normal, lecture seule.
- Effet : liste les lignes
uses:dont la référence n'est pas un SHA de 40 caractères hexadécimaux ; ne modifie rien. - Vérification : une liste vide (hors actions locales) signifie que tout est épinglé ; sinon, pas encore.
- Retour arrière : sans objet.
10. Injection de script et pull_request_target
Injection de script. Une expression ${{ … }} dans un run: est substituée avant que le shell lise la commande. Si elle contient une donnée contrôlée par un tiers (titre de pull request, nom de branche, message de commit, corps d'un ticket), elle peut devenir du code. Contre-mesure de la page « Secure use » : passer la valeur par une variable d'environnement intermédiaire, puis la lire comme variable du shell.
# À éviter : le titre est injecté dans le script
- run: echo "Titre : ${{ github.event.pull_request.title }}"
# Préférable : le titre est une donnée, pas du code
- name: Lire le titre
env:
TITRE: ${{ github.event.pull_request.title }}
run: echo "Titre : $TITRE"pull_request_target et workflow_run. D'après la page, ces déclencheurs, associés à l'extraction (checkout) d'une pull request non fiable, exposent le dépôt à des compromissions ; les workflows qui les utilisent « ne doivent pas explicitement extraire de code non fiable », y compris depuis des forks. Raison générale : ils s'exécutent dans le contexte du dépôt de base, avec ses droits et, selon la configuration, ses secrets. La page lue ne détaille pas le comportement des secrets et du GITHUB_TOKEN pour les forks : non vérifié. Règle simple : ne pas utiliser pull_request_target sauf besoin précis, et ne jamais y extraire ni exécuter le code de la pull request.
Runners auto-hébergés. « Ils ne devraient presque jamais être utilisés pour des dépôts publics », car une pull request non fiable peut compromettre la machine ; la page conseille des runners éphémères détruits après un job (JIT). Un runner auto-hébergé sur le Mac de Stéphane est donc déconseillé sans analyse préalable.
Autres précautions : traiter comme non fiable tout contenu externe lu par un workflow ; ne pas redonner de secret à un step qui exécute du code tiers ; relire toute modification d'un fichier de workflow (CODEOWNERS).
11. Déployer vers Cloudflare Pages (renvoi)
Le déploiement est traité dans le cours « Cloudflare ». D'après la page Cloudflare consultée (mise à jour affichée au 18 septembre 2026), un workflow peut construire le site puis publier le dossier de sortie avec Wrangler via une action Cloudflare : il faut deux secrets, un identifiant de compte et un jeton d'API limité à l'édition de Pages, et la commande sous-jacente est pages deploy <DOSSIER> --project-name=<NOM-PROJET>. Les noms des secrets et la version de l'action (citée @v4 dans l'exemple) sont à relire sur la page ; ce cours ne copie aucun exemple complet ni aucun identifiant.
Squelette sans valeurs réelles, à épingler et à placer derrière un environnement protégé :
deploiement:
needs: [qualite, build]
runs-on: ubuntu-latest
environment: production
permissions:
contents: read
steps:
- uses: actions/download-artifact@<SHA-COMPLET-40-CARACTERES> # v5
with:
name: site-demo
- name: Publier le dossier
uses: cloudflare/wrangler-action@<SHA-COMPLET-40-CARACTERES> # v4
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy dist --project-name=<NOM-PROJET>Les paramètres exacts de l'action (apiToken, accountId, command) sont ceux du schéma habituel de cette action ; ils n'ont pas été confirmés sur la page lue : non vérifié.
Règle de l'Orchestrator. Une page publiée est visible de tous. Toute publication passe par /publier-pages, qui lance l'agent gardien-confidentialite (bloquant) avant le push, et par cyberagent pour les secrets et accès (ADR 0001, cibles de déploiement). Une CI qui déploie automatiquement ne remplace jamais cette revue : donnée privée ou secret signifie cible local, pas de CI vers un hébergement public. MyITLibrary reste privée et n'est pas publiée.
12. Checklist d'un workflow sûr
- à faire :
permissionsen lecture seule en tête, élargie par job seulement. - à faire : Toutes les actions tierces épinglées par SHA complet, avec commentaire de version.
- à faire : Aucune donnée contrôlée par un tiers dans un
run:(variable intermédiaire). - à faire : Pas de
pull_request_targetniworkflow_runavec checkout de code non fiable. - à faire : Secrets uniquement dans les secrets GitHub (idéalement d'environnement), jamais dans cache, artefact, journal ou dépôt.
- à faire : Déploiement derrière lint et tests (
needs) et un environnement protégé. - à faire :
timeout-minutesetconcurrencyrenseignés. - à faire : Revue des modifications de
.github/workflows/(CODEOWNERS). - à faire : Dépôt et contenu passés par
/publier-pagesavant toute publication publique.
Exercices et vérifications de fin de cours
Tous dans un dépôt GitHub privé de test, sans secret réel ni déploiement réel.
- Anatomie. Annoter un workflow : événements, jobs, steps, runner, permissions ; dire ce qui s'exécute en parallèle.
- Gate. Écrire un workflow
qualitepuisbuildavecneeds, et prévoir ce qui se passe simake testéchoue. - Matrice. Ajouter une matrice de deux valeurs illustratives et compter les jobs créés.
- Cache ou artefact ? Pour quatre scénarios (dépendances, site construit, journal de test, identifiant), dire quel mécanisme choisir ou lequel est interdit.
- Permissions. Mettre
contents: readen tête, puis donnerpull-requests: writeà un seul job. - Épinglage. Passer une action de
@v4à un SHA complet (valeur à relever dans le dépôt de l'auteur), puis lancer la commande de recherche du chapitre 9. - Injection. Réécrire un
run:vulnérable avec une variable intermédiaire et expliquer pourquoi l'autre forme est dangereuse. - Pull request cible. Expliquer pourquoi
pull_request_targetavec checkout du code de la PR est un risque. - Environnement. Décrire, sans le créer, un environnement
productionavec relecteurs et branches autorisées ; dire si l'offre de Stéphane le permet pour un dépôt privé (à vérifier). - Plan de publication. Rédiger les étapes avant un déploiement vers Cloudflare Pages, de
/publier-pagesjusqu'au job de déploiement.
Critères de réussite
- Distinguer CI, livraison continue et déploiement continu.
- Citer deux points de contrôle d'un pipeline (tests et approbation d'environnement) et dire où ils se placent.
- Expliquer pourquoi un tag d'action n'est pas immuable et ce qu'apporte le SHA complet.
- Reconnaître une injection de script et la corriger.
- Dire où un secret peut vivre (secret d'environnement) et où il ne doit jamais apparaître (dépôt, cache, artefact, journal).
- Rappeler que toute publication publique passe par
/publier-pagesetgardien-confidentialite. - Citer le périmètre des sources (documentation en ligne du 2026-10-18, sans version) sans le confondre avec l'offre de Stéphane.
Points non vérifiés ou à confirmer
- Offre GitHub de Stéphane (Free, Pro, Team), minutes gratuites, stockage, quotas de cache et d'artefacts, prix : non consultés.
- Image désignée par
ubuntu-latest, types de runners hébergés, versions courantes des actions (@v4,@v5: seulement celles des exemples de la documentation), compatibilité entreupload-artifactetdownload-artifact. - Date de mise à jour des pages GitHub Docs : non relevée.
- Fichier de verrouillage des dépendances de workflow (cité par la page comme meilleure protection) : fonctionnement et disponibilité non lus.
- Comportement des secrets et du
GITHUB_TOKENpour les pull requests de forks, durée de vie du jeton, déclenchement de workflows par le jeton : non confirmés par les pages lues. - Chemin des menus de réglage (permissions par défaut, actions autorisées, protection de branche, secrets), limites des secrets : non relus.
- Paramètres exacts de l'action Cloudflare et noms des secrets : à relire sur la page Cloudflare ; versions de
wrangler: inconnues. - Définitions de CI, livraison continue et déploiement continu : usage courant, non tiré des pages lues.
- Hors périmètre : workflows réutilisables,
workflow_run, runners auto-hébergés en pratique,OIDC,GitHub Packages, images de conteneur, Dependabot en détail. - Les pages ont été lues avec un outil qui renvoie un résumé : citations en traduction libre, à reconfronter aux pages officielles avant validation.
Sources officielles
Toutes consultées le 18 octobre 2026. GitHub Actions n'a pas de numéro de version ici : la colonne indique l'état.
| Source | Version / état | Usage |
|---|---|---|
| Workflow syntax for GitHub Actions (s’ouvre dans un nouvel onglet) | état consulté le 2026-10-18 (date de page non relevée) | chapitres 2 à 4 |
| Secure use reference (s’ouvre dans un nouvel onglet) | état consulté le 2026-10-18 (date de page non relevée) | chapitres 6, 9 et 10 |
| Dependency caching reference (s’ouvre dans un nouvel onglet) | état consulté le 2026-10-18 (date de page non relevée) | chapitre 5 |
| Store and share data with workflow artifacts (s’ouvre dans un nouvel onglet) | état consulté le 2026-10-18 (date de page non relevée) | chapitre 5 |
| Automatic token authentication (GITHUB_TOKEN) (s’ouvre dans un nouvel onglet) | état consulté le 2026-10-18 (date de page non relevée) | chapitre 7 |
| Managing environments for deployment (s’ouvre dans un nouvel onglet) | état consulté le 2026-10-18 (date de page non relevée) | chapitre 8 |
| Cloudflare Pages : Direct Upload avec une CI (s’ouvre dans un nouvel onglet) | mise à jour affichée : 2026-09-18 (d'après le résumé) | chapitre 11 |
ADR 0001 de l'Orchestrator (docs/decisions/0001-cibles-de-deploiement.md) | accepté le 2026-10-16 | cibles de déploiement, garde-fous |