Environnement
- JDK 21 (les artefacts sont en bytecode Java 17 ; le moteur de politiques est en Java 8)
- Node.js 22 et pnpm 8.10.2
- Docker (tests d’intégration en base de données, benchmarks de performance et images)
- Python 3.12 (scripts d’intégration continue)
Commandes courantes
./mvnw verify # construit et teste tous les modules Java (console comprise)
./mvnw verify -DskipFrontend # ignore la construction de la console
bash script/ci/web.sh test # tests unitaires de la console
bash script/ci/web.sh e2e # tests navigateur de la console (backend simulé)
bash script/ci/e2e_fullstack.sh # empaquette, démarre un vrai service et exécute les tests full-stack
bash script/ci/db_integration.sh postgres:17 # exécute les tests d’intégration sur la base de données indiquée
bash script/ci/perf_benchmark.sh smoke # benchmark de performance à petite échellePour développer la console, exécutez pnpm dev (dans core/grantforge-web) ; Vite relaie les requêtes comme /api vers le service à l’écoute sur localhost:9999.
Lancement depuis l’IDE
Exécutez directement org.devlive.grantforge.server.GrantForge (module grantforge-server) ; la base H2 est utilisée par défaut. Le serveur charge automatiquement les modules de plug-ins construits présents dans le dossier plugins/ du dépôt (voir Plug-ins et types de service) ; avant la première utilisation d’un module de plug-in, exécutez une fois ./mvnw -pl plugins/grantforge-plugin-hdfs -am install -DskipTests pour en copier les dépendances.
Conventions de code
- Backend : Error Prone + NullAway (non-nul par défaut, avec JSpecify
@Nullableaux endroits nullables), Checkstyle, PMD, SpotBugs ; ArchUnit protège les conventions communes (pas d’injection par champ, pas de SQL natif, les entités n’apparaissent pas dans l’API,Optional.get()interdit, etc.). - Frontend : mode strict de TypeScript, ESLint sans aucun avertissement ; tous les textes passent par l’i18n, les clés doivent être des littéraux et les clés chinoises et anglaises sont parfaitement identiques.
- Chaque fichier source porte un en-tête de licence MIT ; chaque classe principale du code doit avoir une classe de test correspondante (les exceptions sont déclarées dans
script/ci/test_mapping_exclusions.txt). - Les seuils de couverture sont définis par module (
script/ci/coverage_thresholds.txt). - Les migrations de base de données sont en YAML Liquibase, un fichier par changement, uniquement en ajout et jamais en modification ; les types utilisent des propriétés transverses comme
${text}. - Les messages de commit suivent Conventional Commits, et le titre ne dépasse pas 72 caractères.
Intégration continue
| Tâche | Contenu |
|---|---|
| Repository hygiene | en-têtes de licence, chemins interdits, correspondance des tests, i18n, manifeste des autorisations, formats de fichiers, vérifications des scripts et des workflows |
| Commit messages | format des messages de commit |
| CI script unit tests | tests des scripts d’intégration continue eux-mêmes |
| Java 21 (tests et analyse statique) | La barrière : construction et tests unitaires de tous les modules Java, couverture, NullAway, Checkstyle, SpotBugs, PMD, vérification de la version du bytecode |
| Java 17 / 25 / latest | les mêmes tests unitaires sur les autres JDK pris en charge |
| Frontend | cohérence des types d’API avec le contrat, vérification des types et build, ESLint, tests unitaires, tests navigateur |
| JavaScript SDK | vérification des types, build, ESLint, tests unitaires |
| Database | migrations et tests d’intégration sur H2, PostgreSQL 14/17, MySQL 8.0/8.4, MariaDB 10.11/11.4, Oracle 23 et SQL Server 2022 |
| Plugin API compatibility | comparaison du contrat des plug-ins avec la version publiée précédente |
| Full-stack acceptance | empaquetage sur PostgreSQL, démarrage du service et exécution des tests navigateur full-stack |
| Docs | vérification, tests et construction du site de documentation |
Chaque job ne s’exécute que si le changement touche son domaine (script/ci/changed_areas.py) : une modification de la documentation ne construit pas de Java, une modification de la console ne lance pas les tests de bases de données. Les jobs bases de données, API des plug-ins et full-stack attendent la barrière Java 21 et ne répètent pas ce qu’elle a vérifié : ni tests unitaires, ni JaCoCo, ni enforcer, ni Error Prone (GRANTFORGE_CHECKED=1, script/ci/maven.sh). La protection de branche n’a besoin que du contrôle CI result. Le workflow nocturne exécute les suites Testcontainers, le test de fumée de l’image et le benchmark de performance pour ce qui a changé la veille, et tous le dimanche ; une étiquette de publication obtient sa propre exécution complète de la CI, que la publication attend au lieu de tester à nouveau, et une publication interrompue à mi-chemin s’achève en la relançant. Les workflows de sécurité analysent les dépendances et les clés.
Publication
Le numéro de version est de la forme année.mineure.correctif (par exemple 2026.0.0), et les versions candidates reçoivent le suffixe -rc.N. La version doit être identique dans tous les pom, les paquets npm, l’appVersion du Helm Chart, la barre latérale de la console et le README ; l’intégration continue le vérifie avec check_versions.py.
La publication se fait depuis la branche dev avec une seule commande :
bash script/release/tag.sh 2026.1.0 --dry-run # vérifie seulement et prévisualise les notes de version, sans aucune modification
bash script/release/tag.sh 2026.1.0 --next 2026.2.0 # définit la version, crée et pousse le tag v2026.1.0, puis fait repartir dev sur la version suivanteLe script exige un espace de travail propre, une branche locale qui n’est pas en retard sur le dépôt distant et l’absence du tag ; après confirmation, il valide le commit chore(release): prepare <version>, crée un tag annoté et le pousse. Le tag déclenche release.yml :
script/ci/release.shconstruit la version publiée, un SBOM CycloneDX ne contenant que les dépendances de publication etSHA256SUMS;- les images multi-architectures sont poussées vers
ghcr.io/devlive-community/grantforge; - les artefacts Maven (paquet de sources et Javadoc compris) sont publiés sur GitHub Packages ; lorsque le dépôt définit
CENTRAL_USERNAME,CENTRAL_PASSWORD(jeton du Central Portal),GPG_PRIVATE_KEYetGPG_PASSPHRASE, ils sont signés puis publiés sur Maven Central ; - une GitHub Release est créée, dont le corps reprend tous les commits depuis la version publiée précédente (
v*ou un tag numérique comme1.0.6), regroupés par nouvelles fonctionnalités, corrections de bugs, performances, etc., avec des liens vers les commits.
Les versions candidates sont marquées comme pré-publication et ne mettent pas à jour le tag latest des images. En local, l’activation du profil central ne publie rien par défaut (central.skip=true) ; seule la transmission explicite de -Dcentral.skip=false par le workflow de publication le fait.
Avant d’étiqueter, rédigez le journal de version docs/content/<langue>/changelog/<version>.md dans chaque langue et ajoutez-le à docs/lib/navigation.ts ; sans lui, tag.sh refuse la publication (sauf pour les versions candidates). Le paquet npm est publié via le trusted publishing : npm vérifie un jeton OIDC propre au job contre l'éditeur configuré pour le paquet, aucun secret NPM_TOKEN n'est nécessaire. La publication diffuse d’abord ce qui peut être remplacé (GitHub Packages, l’image), puis Maven Central et npm, et la release GitHub en dernier ; une publication interrompue à mi-chemin s’achève en relançant le workflow, qui ignore ce qui est déjà publié.
Manifeste des autorisations
Les pages et les boutons de la console, ainsi que les API dont elles ont besoin, sont déclarés dans core/grantforge-web/src/permissions/. check_permission_manifest.py garantit que chaque API déclarée existe et que chaque interface exigeant des autorisations est couverte par un bouton ou une page (les exceptions des appels directs sont déclarées dans script/ci/permission_direct_apis.txt).
Documentation
Ce site se trouve dans docs/ et utilise l’export statique de Next.js avec Tailwind CSS :
cd docs
pnpm install
pnpm dev # http://localhost:3100
pnpm check # vérification des pages, des liens et des images
pnpm build # sortie vers docs/outLes pages sont du Markdown situé sous docs/content/, et la navigation se trouve dans docs/lib/navigation.ts. La référence de l’API et les codes d’erreur sont générés à la construction à partir du contrat et du code source. Les captures d’écran sont produites par script/docs/screenshots.sh, qui démarre un vrai service, écrit des données d’exemple, puis fait appel à Playwright.
