Umgebung
- JDK 21 (Artefakte sind Java-17-Bytecode; die Policy-Engine ist Java 8)
- Node.js 22 und pnpm 8.10.2
- Docker (Datenbank-Integrationstests, Performance-Benchmarks und Images)
- Python 3.12 (CI-Skripte)
Häufige Befehle
./mvnw verify # baut und testet alle Java-Module (einschließlich Konsole)
./mvnw verify -DskipFrontend # überspringt den Build der Konsole
bash script/ci/web.sh test # Unit-Tests der Konsole
bash script/ci/web.sh e2e # Browsertests der Konsole (simuliertes Backend)
bash script/ci/e2e_fullstack.sh # paketiert, startet einen echten Dienst und führt Full-Stack-Tests aus
bash script/ci/db_integration.sh postgres:17 # führt Integrationstests auf der angegebenen Datenbank aus
bash script/ci/perf_benchmark.sh smoke # kleinstes Performance-BenchmarkFür die Arbeit an der Konsole führe pnpm dev in core/grantforge-web aus; Vite proxyt Anfragen wie /api an den Dienst unter localhost:9999.
Start aus der IDE
Starte direkt org.devlive.grantforge.server.GrantForge (Modul grantforge-server); standardmäßig wird H2 verwendet. Der Server lädt gebaute Plug-in-Module aus plugins/ im Repository automatisch (siehe Plug-ins und Diensttypen); vor der ersten Nutzung eines Plug-in-Moduls führe einmal ./mvnw -pl plugins/grantforge-plugin-hdfs -am install -DskipTests aus, um seine Abhängigkeiten zu kopieren.
Code-Konventionen
- Backend: Error Prone + NullAway (standardmäßig non-null, an nullable Stellen JSpecify
@Nullable), Checkstyle, PMD, SpotBugs; ArchUnit sichert die gemeinsamen Konventionen (keine Field Injection, keine nativen SQL-Abfragen, Entitäten erscheinen nicht in der API, keinOptional.get()usw.). - Frontend: TypeScript Strict Mode, ESLint ohne Warnungen; alle Texte laufen über i18n, Schlüssel müssen Literale sein, und die chinesischen und englischen Schlüssel sind vollständig gleich.
- Jede Quelldatei hat einen MIT-Lizenzheader; zu jeder Hauptklasse im Code gibt es eine passende Testklasse (Ausnahmen stehen in
script/ci/test_mapping_exclusions.txt). - Die Abdeckungsschwellen sind je Modul gesetzt (
script/ci/coverage_thresholds.txt). - Datenbankmigrationen sind Liquibase-YAML, eine Datei je Änderung, nur hinzufügen und nie ändern; Typen verwenden datenbankübergreifende Eigenschaften wie
${text}. - Commit-Nachrichten folgen Conventional Commits, der Titel ist höchstens 72 Zeichen lang.
CI
| Job | Inhalt |
|---|---|
| Repository hygiene | Lizenzheader, verbotene Pfade, Test-Mapping, i18n, das Berechtigungs-Manifest, Dateiformate sowie Prüfungen von Skripten und Workflows |
| Commit messages | Format der Commit-Nachrichten |
| CI script unit tests | Tests der CI-Skripte selbst |
| Java 21 (Tests und statische Analyse) | Das Gate: Build und Unit-Tests aller Java-Module, Abdeckung, NullAway, Checkstyle, SpotBugs, PMD, Prüfung der Bytecode-Version |
| Java 17 / 25 / latest | Dieselben Unit-Tests auf den übrigen unterstützten JDKs |
| Frontend | API-Typen konsistent mit dem Vertrag, Typprüfung und Build, ESLint, Unit-Tests, Browsertests |
| JavaScript SDK | Typprüfung, Build, ESLint, Unit-Tests |
| Database | Migrationen und Integrationstests auf H2, PostgreSQL 14/17, MySQL 8.0/8.4, MariaDB 10.11/11.4, Oracle 23 und SQL Server 2022 |
| Plugin API compatibility | Vergleicht den Plug-in-Vertrag mit der vorherigen Veröffentlichung |
| Full-stack acceptance | Paketiert auf PostgreSQL, startet den Dienst und führt Full-Stack-Browsertests aus |
| Docs | Prüfungen, Tests und Build der Dokumentationsseite |
Jeder Job läuft nur, wenn die Änderung seinen Bereich berührt (script/ci/changed_areas.py): Eine Dokumentationsänderung baut kein Java, eine Konsolenänderung startet keine Datenbanktests. Die Jobs für Datenbanken, Plug-in-API und Full-Stack warten auf das Java-21-Gate und wiederholen nicht, was es geprüft hat: keine Unit-Tests, kein JaCoCo, kein Enforcer und kein Error Prone (GRANTFORGE_CHECKED=1, script/ci/maven.sh). Für den Branch-Schutz genügt die eine Prüfung CI result. Der nächtliche Workflow führt die Testcontainers-Suiten, den Image-Smoke-Test und den Performance-Benchmark für das aus, was sich am letzten Tag geändert hat, sonntags alle; ein Release-Tag bekommt einen eigenen vollständigen CI-Lauf, auf den das Release wartet, statt erneut zu testen, und ein auf halbem Weg gescheitertes Release wird durch erneutes Ausführen vollendet. Sicherheits-Workflows prüfen Abhängigkeiten und Geheimnisse.
Veröffentlichungen
Die Versionsnummer ist Jahr.Nebenversion.Revision (zum Beispiel 2026.0.0), Release-Kandidaten erhalten den Zusatz -rc.N. Die Versionen in allen poms, npm-Paketen, im appVersion des Helm Chart, in der Seitenleiste der Konsole und in der README müssen übereinstimmen; die CI prüft das mit check_versions.py.
Veröffentlichen geht vom dev-Zweig mit einem einzigen Befehl:
bash script/release/tag.sh 2026.1.0 --dry-run # prüft nur und zeigt eine Vorschau der Release-Notes, nimmt keine Änderungen vor
bash script/release/tag.sh 2026.1.0 --next 2026.2.0 # setzt die Version, erstellt das Tag v2026.1.0 und pusht, danach wechselt dev auf die nächste VersionDas Skript verlangt einen sauberen Arbeitsstand, einen lokalen Zweig, der nicht hinter dem Remote liegt, und ein nicht existierendes Tag; nach der Bestätigung committet es chore(release): prepare <Version>, erzeugt ein kommentiertes Tag und pusht. Das Tag stößt release.yml an:
script/ci/release.shbaut das Release-Paket, eine CycloneDX-SBOM nur mit Release-Abhängigkeiten undSHA256SUMS;- Multi-Architektur-Images werden nach
ghcr.io/devlive-community/grantforgegepusht; - Maven-Artefakte (einschließlich Quellpaket und Javadoc) werden in GitHub Packages veröffentlicht; sind im Repository
CENTRAL_USERNAME,CENTRAL_PASSWORD(Token des Central Portal),GPG_PRIVATE_KEYundGPG_PASSPHRASEgesetzt, werden sie signiert und nach Maven Central veröffentlicht; - Ein GitHub Release wird erzeugt, dessen Text alle Commits seit der vorherigen Veröffentlichung (
v*oder ein numerisches Tag wie1.0.6) enthält, gruppiert nach neuen Funktionen, Fehlerbehebungen, Performance usw., mit Links zu den Commits.
Release-Kandidaten werden als Vorabversion markiert und aktualisieren nicht das latest-Tag der Images. Lokal wird beim Aktivieren des central-Profils standardmäßig nichts veröffentlicht (central.skip=true); nur wenn der Release-Workflow -Dcentral.skip=false ausdrücklich übergibt, passiert es.
Schreiben Sie vor dem Taggen das Release-Log docs/content/<Sprache>/changelog/<Version>.md in jeder Sprache und tragen Sie es in docs/lib/navigation.ts ein; ohne es verweigert tag.sh das Release (Release-Kandidaten ausgenommen). Das npm-Paket wird über Trusted Publishing veröffentlicht: npm prüft ein job-spezifisches OIDC-Token gegen den für das Paket konfigurierten Publisher, ein Secret NPM_TOKEN ist nicht nötig. Das Release veröffentlicht zuerst, was sich ersetzen lässt (GitHub Packages, das Image), dann Maven Central und npm und zuletzt das GitHub-Release; ein auf halbem Weg gescheitertes Release wird durch erneutes Ausführen des Workflows vollendet, der bereits Veröffentlichtes überspringt.
Berechtigungs-Manifest
Die Seiten und Schaltflächen der Konsole und die APIs, die sie brauchen, sind in core/grantforge-web/src/permissions/ deklariert. check_permission_manifest.py stellt sicher, dass jede deklarierte API existiert und dass jede berechtigungspflichtige Schnittstelle von einer Schaltfläche oder Seite abgedeckt ist (Ausnahmen für direkte Aufrufe stehen in script/ci/permission_direct_apis.txt).
Dokumentation
Diese Seite liegt in docs/ und nutzt den statischen Export von Next.js mit Tailwind CSS:
cd docs
pnpm install
pnpm dev # http://localhost:3100
pnpm check # Prüfung von Seiten, Links und Bildern
pnpm build # Ausgabe nach docs/outDie Seiten sind Markdown unter docs/content/, die Navigation steht in docs/lib/navigation.ts. API-Referenz und Fehlercodes werden beim Bauen aus Vertrag und Quellcode erzeugt. Screenshots entstehen mit script/docs/screenshots.sh: echter Dienststart, Beispieldaten einfügen und dann Playwright.
