docs: add server and CI/CD guides
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
---
|
||||
title: Déploiement continu
|
||||
description: Publier une image puis déployer une version par clé SSH.
|
||||
---
|
||||
|
||||
Le workflow de livraison s'exécute après la CI, idéalement sur un tag de version. Il publie d'abord l'image, puis déclenche une opération étroite et contrôlée sur le serveur.
|
||||
|
||||
## Préparer une commande de déploiement côté serveur
|
||||
|
||||
Le serveur peut exposer un script `/usr/local/sbin/deploy-app`, appartenant à `root`, qui n'accepte qu'un tag SemVer :
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
tag="${1:-}"
|
||||
if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Tag invalide" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
cd /srv/mon-app
|
||||
printf 'IMAGE_TAG=%s\n' "$tag" > .env.release
|
||||
|
||||
docker compose --env-file .env.release -f docker-compose.prod.yml pull
|
||||
docker compose --env-file .env.release -f docker-compose.prod.yml \
|
||||
up -d --no-build --remove-orphans
|
||||
docker compose --env-file .env.release -f docker-compose.prod.yml ps
|
||||
```
|
||||
|
||||
Configure ensuite, avec `visudo`, une règle limitée à ce script pour le compte technique. Le workflow n'a ainsi pas besoin d'un accès Docker général ni d'un mot de passe SSH.
|
||||
|
||||
## Publier dans GHCR
|
||||
|
||||
```yaml
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ["v*.*.*"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- uses: docker/metadata-action@v5
|
||||
id: meta
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}-backend
|
||||
tags: type=ref,event=tag
|
||||
|
||||
- uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./backend
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
```
|
||||
|
||||
GitHub recommande d'épingler les actions à un SHA de commit pour une chaîne d'approvisionnement plus stricte. Les tags majeurs ci-dessus gardent l'exemple lisible ; remplace-les par les SHA validés par ton équipe en production.
|
||||
|
||||
## Déployer avec une clé
|
||||
|
||||
Ajoute un second job au même workflow :
|
||||
|
||||
```yaml
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: publish
|
||||
permissions:
|
||||
contents: read
|
||||
environment:
|
||||
name: production
|
||||
url: https://app.example.com
|
||||
concurrency:
|
||||
group: production
|
||||
cancel-in-progress: false
|
||||
|
||||
steps:
|
||||
- name: Préparer SSH
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.PRODUCTION_SSH_PRIVATE_KEY }}
|
||||
SSH_KNOWN_HOSTS: ${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}
|
||||
run: |
|
||||
install -m 700 -d ~/.ssh
|
||||
printf '%s\n' "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
printf '%s\n' "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
|
||||
|
||||
- name: Déployer la version
|
||||
env:
|
||||
DEPLOY_HOST: ${{ vars.PRODUCTION_HOST }}
|
||||
DEPLOY_USER: ${{ vars.PRODUCTION_USER }}
|
||||
IMAGE_TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
[[ "$IMAGE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]
|
||||
ssh "$DEPLOY_USER@$DEPLOY_HOST" \
|
||||
"sudo /usr/local/sbin/deploy-app $IMAGE_TAG"
|
||||
```
|
||||
|
||||
## Secrets et variables attendus
|
||||
|
||||
| Nom | Type | Contenu |
|
||||
| --- | --- | --- |
|
||||
| `PRODUCTION_SSH_PRIVATE_KEY` | secret d'environnement | clé privée dédiée au déploiement |
|
||||
| `PRODUCTION_SSH_KNOWN_HOSTS` | secret d'environnement | empreinte SSH vérifiée du serveur |
|
||||
| `PRODUCTION_HOST` | variable d'environnement | nom DNS ou adresse du serveur |
|
||||
| `PRODUCTION_USER` | variable d'environnement | compte technique autorisé |
|
||||
|
||||
La clé doit être dédiée, révocable et limitée à la production. Stocke-la dans l'environnement GitHub `production`, qui peut aussi exiger une approbation et limiter les tags autorisés.
|
||||
|
||||
<Callout title="Pas de mot de passe SSH dans la CI" type="warn">
|
||||
Utilise une clé dédiée et vérifie l'empreinte de l'hôte. Ne remplace pas `known_hosts` par un `ssh-keyscan` aveugle au moment du déploiement.
|
||||
</Callout>
|
||||
|
||||
Pour aller plus loin : [publier des images Docker](https://docs.github.com/en/actions/tutorials/publish-packages/publish-docker-images) et [protéger les environnements](https://docs.github.com/en/actions/reference/workflows-and-actions/deployments-and-environments).
|
||||
@@ -0,0 +1,115 @@
|
||||
---
|
||||
title: Flux complet
|
||||
description: Relier le développement, la CI, le registry, le serveur et le rollback.
|
||||
---
|
||||
|
||||
Voici le parcours complet d'un changement jusqu'à la production.
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
|
||||
### Développer un petit changement
|
||||
|
||||
Une branche courte part de `main`. Les hooks locaux donnent un premier retour sans remplacer la CI.
|
||||
|
||||
</Step>
|
||||
<Step>
|
||||
|
||||
### Ouvrir une pull request
|
||||
|
||||
Le frontend et le backend sont vérifiés en parallèle : lint, tests et build.
|
||||
|
||||
</Step>
|
||||
<Step>
|
||||
|
||||
### Valider l'image
|
||||
|
||||
La CI construit les Dockerfiles de production et peut lancer les tests d'intégration contre la stack Compose.
|
||||
|
||||
</Step>
|
||||
<Step>
|
||||
|
||||
### Fusionner sur une branche saine
|
||||
|
||||
La fusion n'est possible que si les contrôles obligatoires et la revue ont réussi.
|
||||
|
||||
</Step>
|
||||
<Step>
|
||||
|
||||
### Créer une version
|
||||
|
||||
Un tag SemVer, par exemple `v1.4.0`, déclenche la publication d'une image portant le même tag.
|
||||
|
||||
</Step>
|
||||
<Step>
|
||||
|
||||
### Publier dans le registry
|
||||
|
||||
La CI s'authentifie avec un jeton à portée limitée, pousse l'image et conserve son digest.
|
||||
|
||||
</Step>
|
||||
<Step>
|
||||
|
||||
### Déployer sur le serveur
|
||||
|
||||
L'environnement `production` libère ses secrets après les protections éventuelles. Une clé SSH dédiée appelle le script de déploiement.
|
||||
|
||||
</Step>
|
||||
<Step>
|
||||
|
||||
### Vérifier ou restaurer
|
||||
|
||||
Healthchecks, URL publique, journaux et smoke test confirment la version. En cas d'échec, le tag précédent est redéployé.
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
```text
|
||||
branche courte
|
||||
│
|
||||
▼
|
||||
pull request ──► CI ──► revue ──► main
|
||||
│
|
||||
▼
|
||||
tag de version
|
||||
│
|
||||
build + push de l'image
|
||||
│
|
||||
▼
|
||||
registry
|
||||
│
|
||||
approbation éventuelle
|
||||
│
|
||||
▼
|
||||
serveur ──► healthcheck
|
||||
│
|
||||
si échec
|
||||
▼
|
||||
tag précédent
|
||||
```
|
||||
|
||||
## Critères de passage
|
||||
|
||||
| Passage | Condition |
|
||||
| --- | --- |
|
||||
| pull request → main | tous les contrôles et la revue réussissent |
|
||||
| main → version | la branche est livrable et le changelog est prêt |
|
||||
| version → registry | l'image est construite et identifiée sans ambiguïté |
|
||||
| registry → production | sauvegarde, accès, secrets et approbations sont prêts |
|
||||
| déploiement → terminé | healthchecks et smoke test réussissent |
|
||||
|
||||
## En cas d'incident
|
||||
|
||||
1. arrête les déploiements concurrents ;
|
||||
2. collecte le tag, l'heure, les journaux et les changements de configuration ;
|
||||
3. redéploie le dernier tag sain si l'incident vient de l'application ;
|
||||
4. restaure les données seulement si nécessaire et selon la procédure testée ;
|
||||
5. corrige par un nouveau changement versionné, sans modifier le conteneur à la main ;
|
||||
6. documente la cause et améliore le contrôle qui aurait pu la détecter.
|
||||
|
||||
<Callout title="Définition de terminé" type="success">
|
||||
La pipeline n'est complète que lorsqu'elle sait prouver quelle version tourne, détecter un échec et revenir à un état connu.
|
||||
</Callout>
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
title: Intégration continue
|
||||
description: Organiser des contrôles rapides et bloquants avec GitHub Actions.
|
||||
---
|
||||
|
||||
Un workflow GitHub Actions est un fichier YAML placé dans `.github/workflows/`. Il contient des événements déclencheurs, des jobs et des étapes exécutées par des runners.
|
||||
|
||||
## Exemple pour un monorepo
|
||||
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
backend:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: backend
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: backend/package-lock.json
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm test
|
||||
- run: npm run build
|
||||
|
||||
frontend:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontend
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm test
|
||||
- run: npm run build
|
||||
|
||||
docker-build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [backend, frontend]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- run: docker compose -f docker-compose.prod.yml build
|
||||
```
|
||||
|
||||
Le backend et le frontend s'exécutent en parallèle. `docker-build` ne démarre que si les deux ont réussi : il joue le rôle de porte de sortie.
|
||||
|
||||
<Callout title="Adapte les scripts au dépôt" type="info">
|
||||
Les commandes `lint`, `test` et `build` doivent exister dans les `package.json`. Si le projet possède un fichier de version Node, utilise `node-version-file` pour garder la CI alignée avec le développement.
|
||||
</Callout>
|
||||
|
||||
## Installer de façon reproductible
|
||||
|
||||
`npm ci` respecte le lockfile et échoue si celui-ci n'est plus cohérent avec `package.json`. Il est préférable à `npm install` dans la CI.
|
||||
|
||||
Le cache accélère le téléchargement des paquets, mais ne remplace pas `npm ci`. Les dépendances continuent d'être vérifiées à chaque run.
|
||||
|
||||
## Protéger la branche principale
|
||||
|
||||
Dans les règles de branche du dépôt :
|
||||
|
||||
1. impose une pull request avant fusion ;
|
||||
2. rends les jobs CI obligatoires ;
|
||||
3. exige que la branche soit à jour ;
|
||||
4. empêche la fusion si un job échoue ;
|
||||
5. limite les contournements administrateur.
|
||||
|
||||
## Garder la pipeline lisible
|
||||
|
||||
- donne aux jobs des noms qui indiquent leur responsabilité ;
|
||||
- parallélise les contrôles indépendants ;
|
||||
- place les tests lents après les vérifications rapides ;
|
||||
- évite de dupliquer la même logique dans plusieurs workflows ;
|
||||
- conserve les rapports de test utiles au diagnostic ;
|
||||
- épingle les actions tierces à un SHA de commit dans les dépôts sensibles.
|
||||
|
||||
## Ordre recommandé
|
||||
|
||||
```text
|
||||
format/lint → tests unitaires → build → tests d'intégration → build Docker
|
||||
```
|
||||
|
||||
La [documentation GitHub Actions](https://docs.github.com/en/actions/reference/workflows-and-actions) décrit les événements, jobs, permissions et dépendances disponibles.
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"title": "CI/CD",
|
||||
"description": "Tester, publier et déployer automatiquement",
|
||||
"pages": [
|
||||
"principes",
|
||||
"integration-continue",
|
||||
"deploiement-continu",
|
||||
"flux-complet"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: Principes de la CI/CD
|
||||
description: Comprendre la chaîne qui transforme un changement en version déployable.
|
||||
---
|
||||
|
||||
CI/CD désigne un ensemble de pratiques, pas un outil. GitHub Actions, GitLab CI ou Jenkins exécutent la chaîne, mais sa valeur vient surtout de règles simples : retours rapides, branche principale saine et livraison reproductible.
|
||||
|
||||
## CI et CD ne font pas le même travail
|
||||
|
||||
| Étape | Question | Résultat |
|
||||
| --- | --- | --- |
|
||||
| intégration continue (CI) | le changement est-il valide ? | code testé et branche principale saine |
|
||||
| livraison continue | cette version peut-elle être livrée ? | artefact versionné et prêt |
|
||||
| déploiement continu (CD) | la version doit-elle être mise en ligne ? | production mise à jour et vérifiée |
|
||||
|
||||
Une équipe peut automatiser la livraison tout en gardant une approbation manuelle avant la production. Le « D » de CD ne signifie donc pas toujours déploiement automatique.
|
||||
|
||||
## Les trois propriétés recherchées
|
||||
|
||||
### Une branche principale toujours livrable
|
||||
|
||||
Les branches restent courtes, les changements petits et les contrôles obligatoires avant fusion. Une erreur est plus simple à comprendre lorsqu'elle porte sur quelques commits.
|
||||
|
||||
### Des boucles de retour rapides
|
||||
|
||||
Lance d'abord les vérifications rapides : formatage, lint et tests unitaires. Les builds Docker et tests e2e plus coûteux viennent ensuite. Un développeur doit savoir rapidement si son changement peut avancer.
|
||||
|
||||
### Un artefact unique
|
||||
|
||||
La CI produit une image versionnée. La recette de production déploie cette même image ; elle ne reconstruit pas le projet sur le serveur.
|
||||
|
||||
```text
|
||||
commit → contrôles → image versionnée → registry → déploiement → vérification
|
||||
```
|
||||
|
||||
## Répartir les responsabilités
|
||||
|
||||
| Niveau | Exemples |
|
||||
| --- | --- |
|
||||
| poste du développeur | formatage, lint, tests ciblés, hooks Git |
|
||||
| pull request | lint complet, tests, build, revue |
|
||||
| branche principale | image candidate, scans et tests d'intégration |
|
||||
| version | publication dans le registry |
|
||||
| environnement | approbation éventuelle, déploiement, smoke test |
|
||||
|
||||
Les hooks Git améliorent le confort local, mais la CI reste la source de vérité : un hook peut être désactivé ou ne pas exister sur une autre machine.
|
||||
|
||||
## Une politique minimale efficace
|
||||
|
||||
- aucune fusion si un contrôle obligatoire échoue ;
|
||||
- aucun déploiement depuis une branche non approuvée ;
|
||||
- chaque image porte un tag immuable ;
|
||||
- les secrets sont limités à l'environnement qui en a besoin ;
|
||||
- un seul déploiement de production s'exécute à la fois ;
|
||||
- chaque mise en ligne possède une vérification et un rollback.
|
||||
|
||||
<Callout title="La confiance vient de la répétition" type="info">
|
||||
Une petite pipeline exécutée à chaque changement protège mieux qu'une longue procédure manuelle lancée seulement avant une grosse livraison.
|
||||
</Callout>
|
||||
|
||||
Reference in New Issue
Block a user