Окружение
- JDK 21 (артефакты — байт-код Java 17; движок политик — Java 8)
- Node.js 22 и pnpm 8.10.2
- Docker (интеграционные тесты баз данных, нагрузочные бенчмарки и образы)
- Python 3.12 (скрипты CI)
Основные команды
./mvnw verify # 构建并测试全部 Java 模块(含控制台)
./mvnw verify -DskipFrontend # 跳过控制台构建
bash script/ci/web.sh test # 控制台单元测试
bash script/ci/web.sh e2e # 控制台浏览器测试(模拟后端)
bash script/ci/e2e_fullstack.sh # 打包、启动真实服务并运行全栈测试
bash script/ci/db_integration.sh postgres:17 # 在指定数据库上运行集成测试
bash script/ci/perf_benchmark.sh smoke # 小规模性能基准Для разработки консоли запускайте pnpm dev в core/grantforge-web; Vite проксирует /api и другие запросы на сервер localhost:9999.
Запуск из IDE
Запускайте org.devlive.grantforge.server.GrantForge (модуль grantforge-server) напрямую; по умолчанию он использует базу данных H2. Сервер автоматически загружает модули плагинов, собранные в каталоге plugins/ репозитория (см. Плагины и типы сервисов); перед первым использованием модуля плагина выполните один раз ./mvnw -pl plugins/grantforge-plugin-hdfs -am install -DskipTests, чтобы скопировать его зависимости.
Стандарты кодирования
- Бэкенд: Error Prone + NullAway (по умолчанию non-null, там, где значение может отсутствовать, — JSpecify
@Nullable), Checkstyle, PMD, SpotBugs; ArchUnit охраняет общие соглашения (никаких инъекций в поля, нативного SQL, сущностей в API, вызововOptional.get()и т. д.). - Фронтенд: строгий режим TypeScript, ESLint без предупреждений; все тексты проходят через i18n, ключи должны быть литералами, а наборы ключей для китайского и английского языков совпадают.
- Каждый исходный файл содержит заголовок лицензии MIT; каждому классу из основного исходного кода должен соответствовать тестовый класс (исключения перечислены в
script/ci/test_mapping_exclusions.txt). - Пороги покрытия задаются для каждого модуля (
script/ci/coverage_thresholds.txt). - Миграции баз данных — это YAML Liquibase: один файл на изменение, только добавление (существующие файлы никогда не изменяются); типы задаются перекрёстными для всех СУБД свойствами, такими как
${text}. - Сообщения коммитов следуют Conventional Commits, тема не длиннее 72 символов.
CI
| Задача | Что делает |
|---|---|
| Чистота репозитория | Заголовки лицензий, запрещённые пути, сопоставление тестов, i18n, манифест разрешений, форматирование файлов, проверка скриптов и workflow |
| Сообщения коммитов | Формат сообщений коммитов |
| Юнит-тесты CI-скриптов | Тесты самих скриптов CI |
| Java 21 (тесты и статический анализ) | Шлюз: сборка и юнит-тесты всех Java-модулей, покрытие, NullAway, Checkstyle, SpotBugs, PMD, проверка версий байт-кода |
| Java 17 / 25 / latest | Те же юнит-тесты на остальных поддерживаемых JDK |
| Фронтенд | Соответствие типов API контракту, проверка типов и сборка, ESLint, юнит-тесты, браузерные тесты |
| JavaScript SDK | Проверка типов, сборка, ESLint, юнит-тесты |
| Базы данных | Миграции и интеграционные тесты на H2, PostgreSQL 14/17, MySQL 8.0/8.4, MariaDB 10.11/11.4, Oracle 23 и SQL Server 2022 |
| Совместимость API плагинов | Сравнение контракта плагинов с предыдущим релизом |
| Сквозная приёмка | Упаковка, запуск сервера и браузерные сквозные тесты на PostgreSQL |
| Документация | Проверки, тесты и сборка сайта документации |
Каждая задача запускается, только если изменение затрагивает её область (script/ci/changed_areas.py): изменение документации не собирает Java, изменение консоли не запускает тесты баз данных. Задачи баз данных, API плагинов и full-stack ждут шлюза Java 21 и не повторяют то, что он уже проверил: без юнит-тестов, JaCoCo, enforcer и Error Prone (GRANTFORGE_CHECKED=1, script/ci/maven.sh). Для защиты ветки достаточно одной проверки CI result. Ночной процесс запускает наборы Testcontainers, smoke-тест образа и тест производительности для того, что изменилось за последние сутки, а по воскресеньям — всё; тег релиза получает собственный полный прогон CI, который релиз ждёт вместо повторного тестирования, а релиз, прерванный на полпути, завершается повторным запуском. Процессы безопасности сканируют зависимости и секреты.
Релизы
Версии имеют вид year.minor.patch (например 2026.0.0), кандидаты в релиз получают суффикс -rc.N. Версии во всех pom-файлах, npm-пакетах, appVersion Helm-чарта, боковой панели консоли и README должны совпадать; CI проверяет их скриптом check_versions.py.
Релиз из ветки dev выполняется одной командой:
bash script/release/tag.sh 2026.1.0 --dry-run # 只检查并预览发布说明,不做任何修改
bash script/release/tag.sh 2026.1.0 --next 2026.2.0 # 设置版本、打标签 v2026.1.0 并推送,再把 dev 切到下一个版本Скрипт требует чистое рабочее дерево, локальную ветку, не отстающую от удалённой, и несуществующий тег; после подтверждения он создаёт коммит chore(release): prepare <version>, навешивает аннотированный тег и отправляет его. Тег запускает release.yml:
script/ci/release.shсобирает дистрибутив, SBOM CycloneDX, содержащий только зависимости релиза, иSHA256SUMS;- мультиархитектурные образы отправляются в
ghcr.io/devlive-community/grantforge; - артефакты Maven (включая исходный код и Javadoc) публикуются в GitHub Packages; если репозиторий настроен через
CENTRAL_USERNAME,CENTRAL_PASSWORD(токен Central Portal),GPG_PRIVATE_KEYиGPG_PASSPHRASE, они подписываются и публикуются в Maven Central; - создаётся GitHub Release, в описании которого перечислены все коммиты с предыдущего релиза (
v*или числовый тег, например1.0.6), сгруппированные по возможностям, исправлениям, производительности и т. д., со ссылками на коммиты.
Кандидаты в релиз помечаются как pre-release и не обновляют тег latest образов. Локально профиль central по умолчанию ничего не публикует (central.skip=true); только релизный workflow явно передаёт -Dcentral.skip=false.
Перед созданием тега напишите журнал выпуска docs/content/<язык>/changelog/<версия>.md на каждом языке и добавьте его в docs/lib/navigation.ts; без него tag.sh отказывается выпускать релиз (кроме кандидатов). npm-пакет публикуется через trusted publishing: npm сверяет OIDC-токен уровня задания с издателем, настроенным для пакета, секрет NPM_TOKEN не нужен. Релиз сначала публикует заменяемое (GitHub Packages, образ), затем Maven Central и npm, и последним — релиз на GitHub; прерванный на полпути релиз завершается повторным запуском процесса, который пропускает уже опубликованное.
Манифест разрешений
Страницы, кнопки консоли и используемые ими API объявлены в core/grantforge-web/src/permissions/. check_permission_manifest.py гарантирует, что каждый объявленный API существует, а каждый эндпоинт, требующий разрешений, покрыт какой-либо кнопкой или страницей (исключения для прямых вызовов перечислены в script/ci/permission_direct_apis.txt).
Документация
Этот сайт расположен в docs/ и использует статический экспорт Next.js с Tailwind CSS:
cd docs
pnpm install
pnpm dev # http://localhost:3100
pnpm check # 页面、链接与图片检查
pnpm build # 输出到 docs/outСтраницы — это Markdown в docs/content/, а навигация определена в docs/lib/navigation.ts. Справочник API и коды ошибок генерируются при сборке из контракта и исходного кода. Скриншоты создаёт script/docs/screenshots.sh, который запускает реальный сервер, наполняет его тестовыми данными и управляет Playwright.
