actions
CI / quality (push) Waiting to run
CI / e2e-and-a11y (push) Blocked by required conditions
CI / lighthouse (push) Blocked by required conditions
CI / android-smoke (push) Waiting to run
CI / pull-request-report (push) Blocked by required conditions
Security / codeql (push) Waiting to run
Security / deps-and-secrets (push) Waiting to run

This commit is contained in:
2026-07-21 16:52:43 +02:00
parent 256599626e
commit 785e1be2aa
12 changed files with 463 additions and 0 deletions
@@ -0,0 +1,15 @@
---
name: MVP Foundation
about: Fondations monorepo et architecture feature-first
title: "[MVP] Fondations monorepo Solid + Capacitor"
labels: ["mvp", "foundation"]
assignees: []
---
## Objectif
Mettre en place la base technique feature-first et DDD simple.
## Critères d'acceptation
- [ ] Workspaces apps/packages opérationnels
- [ ] Domain immutable pour base/variant/recipe
- [ ] Scripts qualité exécutables
+16
View File
@@ -0,0 +1,16 @@
---
name: Builder Flow
about: Parcours base -> variante -> recette
title: "[MVP] Builder flow 3 étapes"
labels: ["mvp", "feature"]
assignees: []
---
## Objectif
Implémenter le wizard de construction bento.
## Critères d'acceptation
- [ ] Filtre salé/sucré base
- [ ] Variante filtrée par base
- [ ] Recette fusionnée avec ordre de priorité
- [ ] Partage + impression + quantité
@@ -0,0 +1,15 @@
---
name: Quality and Security
about: CI quality gates et audits sécurité
title: "[MVP] Quality gates + security audits"
labels: ["mvp", "quality", "security"]
assignees: []
---
## Objectif
Garantir qualité, sécurité et non-régression.
## Critères d'acceptation
- [ ] Unit/integration/e2e en CI
- [ ] SAST + dependencies + secrets scan
- [ ] Lighthouse perf/seo/a11y bloquant
@@ -0,0 +1,33 @@
---
name: Refactor Builder SOLID
about: Découpage SOLID du flux builder (BuilderFlow)
title: "[Refactor] Builder — découpage SOLID et responsabilités claires"
labels: ["refactor"]
assignees: []
---
## Contexte
La logique et lUI du parcours builder sont concentrées dans `apps/web/src/ui/BuilderFlow.tsx` (fichier très volumineux). Le domaine pur existe déjà dans `packages/features/builder/src/domain.ts`.
## Objectif
Réduire la surface « tout-en-un » du flux builder et clarifier les frontières entre UI, état du wizard, et domaine (`@ben-to/builder`).
## Pistes techniques
- Extraire par **responsabilité unique** : étapes (base / variante / recette), barre dactions, feuille recette, navigation « Continuer », synchronisation reset (`builder-reset-bus`).
- Introduire des **hooks / ports** testables (ex. `useBuilderSteps`, `useRecipeSheet`) pour isoler les effets et la lecture du catalogue.
- **DIP** : lUI consomme le domaine (`domain.ts`) et des interfaces stables pour le catalogue, sans détails de parsing dispersés.
- Conserver / étendre les tests (`*.unit.test.ts`, e2e, Gherkin `@int-builder-*`).
## Critères dacceptation
- [ ] Aucun fichier du flux builder > ~250300 lignes sans justification documentée en commentaire de module.
- [ ] Tests unitaires / intégration et e2e verts ; pas de régression sur le parcours dans `specs/features/builder.feature`.
## Références
- `apps/web/src/ui/BuilderFlow.tsx`
- `packages/features/builder/src/domain.ts`
- `specs/features/builder.feature`
@@ -0,0 +1,36 @@
---
name: Architecture sans barrels index
about: Supprimer les index.ts barrel et verrouiller par règle / CI
title: "[Archi] Supprimer les index.ts barrel et verrouiller par règle projet"
labels: ["architecture"]
assignees: []
---
## Contexte
Les packages exposent des barrels `src/index.ts` avec `export * from "..."`. Les alias Vite dans `apps/web/vite.config.ts` pointent vers ces fichiers. Ce pattern complique le suivi des imports réels et la détection de code inutilisé.
## Objectif
Supprimer les barrels `index.ts`, migrer vers des imports **explicites**, et **verrouiller** la réintroduction du pattern (règles projet + CI).
## Travail technique
1. Remplacer les alias Vite (et chemins TypeScript si besoin) par des modules canoniques nommés (ex. `@ben-to/builder/domain`, `@ben-to/recipes/catalog`) ou par des sous-chemins `package.json` **`exports`** sans fichier nommé `index.ts`.
2. Mettre à jour tous les imports (`apps/web`, `packages/**`).
3. Supprimer les anciens `**/src/index.ts` après migration.
## Règles / outillage
- Étendre `.cursor/rules/ben-to-engineering.mdc` : pas de nouveau barrel `index.ts` ; imports depuis modules nommés.
- Optionnel : ESLint `no-restricted-imports` ou script `scripts/quality/` qui échoue si un `**/src/index.ts` barrel réapparaît.
## Critères dacceptation
- [ ] Plus de `export * from` dans des `index.ts` à la racine des packages features/shared concernés.
- [ ] CI (`check:quality` ou lint) empêche la réintroduction du pattern (selon le niveau de durcissement retenu).
## Références
- `apps/web/vite.config.ts`
- `packages/features/*/src/index.ts`, `packages/shared/*/src/index.ts`
@@ -0,0 +1,38 @@
---
name: SEO recettes OG / réseaux sociaux
about: Métadonnées Open Graph et Twitter par URL /r/...
title: "[SEO] Métadonnées OG/Twitter par recette (/r/...)"
labels: ["seo"]
assignees: []
---
## Contexte
Les métadonnées Open Graph et Twitter sont définies une seule fois dans `apps/web/index.html`. Les URLs de recette `/r/...` doivent exposer **titre**, **description** et **image** adaptés au partage.
**Contrainte SPA** : modifier `<title>` ou les meta **uniquement en JavaScript après chargement** ne suffit souvent pas pour les robots daperçu (Facebook, X, LinkedIn) : ils lisent le HTML initial.
## Objectif
Pour chaque recette partageable, fournir des métadonnées correctes : `og:title`, `og:description`, `og:image`, `og:url`, `twitter:card` (idéalement `summary_large_image` si visuel adapté), éventuellement `canonical`.
## Options à trancher (documenter le choix dans README ou `docs/`)
| Approche | Effort | Aperçus réseaux |
|----------|--------|-----------------|
| Pré-rendu statique des routes `/r/*` au build (catalogue / pipeline recettes) | Moyen | Bon pour crawlers statiques |
| Middleware / route serveur (Worker, reverse proxy, petite app Node) injectant le HTML minimal avec meta | Variable | Très bon si bien déployé |
| Meta uniquement côté client (Solid) | Faible | Insuffisant pour la majorité des partages |
Données : titres localisés, description courte, images de couverture produites par le pipeline recettes.
## Critères dacceptation
- [ ] Partager une URL `/r/...` affiche un aperçu avec **titre et image recette** (validation manuelle : Meta Sharing Debugger / Twitter Card Validator ou équivalent).
- [ ] Balises OG/Twitter cohérentes (`og:type`, `og:url`, etc.).
- [ ] Documentation de la stratégie retenue (build vs serveur).
## Références
- `apps/web/index.html`
- Parcours e2e et URL partagée dans `tests/e2e/builder.e2e.ts`
+16
View File
@@ -0,0 +1,16 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 15
groups:
npm-all:
patterns:
- "*"
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
+13
View File
@@ -0,0 +1,13 @@
## Ticket
- [ ] Issue GitHub liée : #_____
- [ ] Branche nommée de façon explicite (ex. `feat/issue-___-…`)
## Vérifications
- [ ] `npm run test:ci` exécuté localement avec succès
- [ ] Impact **mobile Android** pris en compte si pertinent (Capacitor / Gradle)
## Notes pour les relecteurs
<!-- Contexte, captures, risques -->
+158
View File
@@ -0,0 +1,158 @@
name: CI
on:
pull_request:
push:
branches: [main]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run pipeline:recipes
- run: npm run check:quality
- run: npm run lint
- run: npm run typecheck
- run: npm run test:coverage
- name: Upload coverage
uses: actions/upload-artifact@v7
with:
name: coverage-summary
path: |
coverage/coverage-summary.json
coverage/lcov.info
e2e-and-a11y:
runs-on: ubuntu-latest
needs: quality
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run pipeline:recipes
- run: npx playwright install --with-deps
- run: npm run test:e2e
- name: Upload quality summaries (a11y + perf)
uses: actions/upload-artifact@v7
with:
name: quality-e2e
path: quality-out/
if-no-files-found: warn
lighthouse:
runs-on: ubuntu-latest
needs: quality
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run audit:lighthouse
# .lighthouseci est dans .gitignore : upload-artifact exclut ces fichiers → aucun artefact « lighthouse-ci ».
# Copie vers un dossier non ignoré pour forcer lupload réel des LHR.
- name: Stage LHCI reports for artifact
run: |
rm -rf __lhci_artifact__
mkdir -p __lhci_artifact__
cp -R .lighthouseci/. __lhci_artifact__/
test "$(find __lhci_artifact__ -type f | wc -l)" -gt 0 || { echo "::error::LHCI n'a produit aucun fichier"; exit 1; }
- name: Upload Lighthouse CI output
uses: actions/upload-artifact@v7
with:
name: lighthouse-ci
path: __lhci_artifact__
if-no-files-found: error
android-smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21
- name: Setup Android SDK
uses: android-actions/setup-android@v4
- run: sdkmanager "platforms;android-35" "build-tools;35.0.0"
- run: npm ci
- run: npm run pipeline:recipes
- run: npm run build:web
- run: npm run mobile:sync
- name: Gradle assembleDebug
working-directory: apps/mobile/android
run: chmod +x gradlew && ./gradlew assembleDebug --no-daemon
pull-request-report:
if: github.event_name == 'pull_request'
needs: [quality, e2e-and-a11y, lighthouse]
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- run: npm ci
- run: mkdir -p incoming
- run: npm audit --json > incoming/audit.json || true
# Même version majeure que upload-artifact (@v7) : v8 peut ne pas résoudre les artefacts v7.
- uses: actions/download-artifact@v8
with:
name: coverage-summary
path: incoming/coverage
- uses: actions/download-artifact@v8
with:
name: quality-e2e
path: incoming/e2e
- uses: actions/download-artifact@v8
with:
name: lighthouse-ci
path: incoming/lhci
- run: node scripts/ci/pr-quality-report.mjs incoming incoming/pr-body.md
- uses: actions/github-script@v9
with:
script: |
const fs = require('fs');
const marker = '<!-- ben-to-quality-report -->';
const body = marker + '\n' + fs.readFileSync('incoming/pr-body.md','utf8');
const issue_number = context.payload.pull_request.number;
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number,
per_page: 100
});
const existing = comments.find(c => c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number,
body
});
}
+22
View File
@@ -0,0 +1,22 @@
name: Dependency review
on:
pull_request:
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
# Laction officielle `dependency-review-action` suppose Dependency graph + GitHub Advanced Security
# (réglages du dépôt). Sans GHAS elle échoue toujours sur les dépôts non éligibles.
# Même garde-fou que Security / deps-and-secrets : lockfile installable + npm audit.
- run: npm ci
- run: npm audit --audit-level=high
+50
View File
@@ -0,0 +1,50 @@
name: Mobile Release
on:
push:
tags:
- "mobile-v*"
workflow_dispatch:
jobs:
android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21
- name: Setup Android SDK
uses: android-actions/setup-android@v4
- run: sdkmanager "platforms;android-35" "build-tools;35.0.0"
- run: npm ci
- run: npm run build:web
- run: npm run mobile:sync
- name: Gradle bundleDebug (sans keystore Play — artefact de validation CI)
working-directory: apps/mobile/android
run: chmod +x gradlew && ./gradlew bundleDebug --no-daemon
- uses: actions/upload-artifact@v7
with:
name: android-bundle-debug
path: apps/mobile/android/app/build/outputs/bundle/debug/*.aab
if-no-files-found: error
ios:
runs-on: macos-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run build:web
- run: npm run mobile:sync
- name: iOS — projet non versionné ou machine locale
run: |
if [ -d apps/mobile/ios/App ]; then echo "Projet iOS présent — ouvrir Xcode pour archive."; else echo "Pas de dossier ios dans ce clone — ignorer pour Android-only."; fi
+51
View File
@@ -0,0 +1,51 @@
name: Security
on:
pull_request:
push:
branches: [main]
schedule:
- cron: "0 5 * * 1"
jobs:
codeql:
# PR depuis fork : pas dupload SARIF vers le dépôt cible (permissions GitHub).
# Dépôt sans « Code scanning » activé (Settings → Code security) : lupload échoue ;
# `upload: false` garde lanalyse CodeQL sans appeler lAPI. Quand le scanning est
# activé sur le repo, retirer `upload: false` (comportement par défaut = upload).
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- uses: actions/checkout@v7
- uses: github/codeql-action/init@v4
with:
languages: javascript-typescript
- uses: github/codeql-action/analyze@v4
with:
upload: false
deps-and-secrets:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
steps:
# Historique complet : gitleaks compare github.event.before..after sur push ;
# un clone depth=1 ne contient pas le parent, doù « unknown revision ».
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 22
- run: npm ci
- run: npm run audit:deps
- name: Secret scan
# v2 — SHA épinglé (supply chain) ; tag : https://github.com/gitleaks/gitleaks-action/releases
uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}