Build des catalogues#
Ce document décrit le workflow de génération des catalogues du projet Playlab42.
Principe "as-code"#
Les catalogues (data/*.json) sont générés à partir des manifests sources et ne doivent jamais être modifiés manuellement. Ils sont listés dans .gitignore et régénérés :
- En local lors du développement
- En CI/CD avant le déploiement
Fichiers générés#
| Fichier | Source | Script |
|---|---|---|
data/catalogue.json | tools/*.json, games/*/game.json | build-catalogue.js |
data/parcours.json | parcours/epics/*/epic.json | build-parcours.js |
data/bookmarks.json | bookmarks/*.json, manifests, metadata/bookmarks-og.json | build-bookmarks.js |
Scripts de build#
Tous les scripts sont dans scripts/ et partagent des utilitaires via scripts/lib/build-utils.js.
Commandes#
# Build complet, dans Docker (make build construit l'image)
make npm CMD="run build"
# Builds individuels
docker compose exec dev npm run build:catalogue
docker compose exec dev npm run build:parcours
docker compose exec dev npm run build:bookmarks
make npm CMD="run refresh:bookmarks" # actualisation éditoriale, réseau autorisé
Le build normal lit le snapshot OG revu, sans réseau. Le refresh explicite
respecte la TTL du cache technique (sept jours), signale les échecs et réécrit
le snapshot à relire. --skip-og omet l'enrichissement, il n'est pas un refresh.
Une nouvelle URL sans métadonnées conserve ses champs manuels avec un warning.
Ne pas modifier les catalogues générés pour corriger une métadonnée :
modifier les sources/snapshot puis reconstruire. Voir
fabrication et reprise.
Le build normal ne consulte pas les images du cache en repli. Le refresh
conserve une URL OG distante pour un nouveau téléchargement ignoré par Git,
ou l'image locale éditoriale déjà revue ; un échec conserve les métadonnées
précédentes. Le packaging refuse les images locales référencées absentes et
exclut les images non référencées du cache.
Structure des scripts#
scripts/
├── build-catalogue.js # Génère le catalogue tools/games
├── build-parcours.js # Génère le catalogue parcours
├── build-bookmarks.js # Génère le catalogue bookmarks
├── parcours-utils.js # Utilitaires spécifiques parcours
├── og-fetcher.js # Fetch métadonnées OpenGraph
└── lib/
└── build-utils.js # Utilitaires partagés
Workflow de développement#
Ajouter un outil#
- Créer
tools/mon-outil.json(manifest) - Créer
tools/mon-outil.html(contenu) - Lancer
npm run build:catalogue
Ajouter un jeu#
- Créer
games/mon-jeu/game.json(manifest) - Créer
games/mon-jeu/index.html(point d'entrée) - Lancer
npm run build:catalogue
Ajouter un parcours#
- Créer
parcours/epics/mon-parcours/epic.json(manifest) - Créer les slides dans
parcours/epics/mon-parcours/slides/ - Lancer
npm run build:parcours
Validation#
Les scripts valident les manifests au build :
- Champs requis présents
- Formats corrects (IDs en kebab-case, etc.)
- Fichiers référencés existants
En cas d'erreur, le build échoue avec un message explicite et conserve le dernier
catalogue. Un manifest d'outil simple sans son tools/[id].html est une erreur
bloquante, comme un outil complexe sans index.html ; il n'est pas ignoré même
si d'autres outils sont valides.
Les slides Markdown sont régénérées à chaque build, y compris après une modification du titre ou du template. Le marqueur de sortie distingue le HTML généré du HTML auteur ; les paires sans marqueur sont refusées. Voir le contrat des sources et la migration. La conservation du catalogue ne constitue pas une transaction de toutes les slides : certaines sorties générées peuvent avoir été actualisées avant qu'une autre entrée ne fasse échouer le build.
CI/CD#
Le workflow GitHub Actions (deploy.yml) :
- Réutilise la CI : installation, gates, build complet depuis le snapshot revu.
- Compare deux fabrications avec la même epoch et vérifie l'archive.
- Teste cette même archive dans Chromium, puis la publie sur GitHub Pages.
Les fichiers data/*.json sont générés par la CI ; la publication ne les
reconstruit pas et réutilise l'artefact testé.
Module partagé#
scripts/lib/build-utils.js fournit :
| Fonction | Description |
|---|---|
getRootDir(url) | Chemin racine du projet |
fileExistsAsync(path) | Vérifie existence fichier (async) |
fileExistsSync(path) | Vérifie existence fichier (sync) |
readJSONAsync(path) | Lit JSON (async) |
readJSONSync(path, stats) | Lit JSON (sync) |
isValidId(id) | Valide format kebab-case |
extractDomain(url) | Extrait domaine d'URL |
colors | Couleurs ANSI console |
createStats() | Crée objet stats standard |
printReport(stats) | Affiche rapport de build |