5.7 KiB
Build contract — Phase 2
Из корня проекта, с Node.js 22+ и npm:
npm ci --ignore-scripts
scripts/spike-tools.sh
./mcpack build
Дополнительные параметры:
./mcpack build --config platform/config.yaml
./mcpack build --release
--config выбирает YAML manifest; относительные пути pack/output внутри
него считаются от корня репозитория. По умолчанию build разрешает dirty
worktree и записывает это в manifest. --release требует чистого worktree.
Команды не делают commit/tag/deploy и не запускают Minecraft.
Имя, версия, Minecraft и loader читаются из TOML packwiz. Полный релиз
создаётся в <output>/<name>-<version>/ и содержит:
<name>-<version>.mrpack
server/compose.yaml
server/.env.example
server/config/
server/README.md
manifest.json
SHA256SUMS
Релиз той же версии не перезаписывается. Для изменённого source нужно выбрать новую версию pack, явно выполнить packwiz refresh, затем build. Для локального эксперимента с прежней версией можно выбрать другой output directory через отдельный config. Не изменять опубликованный release directory вручную.
Pipeline
- Parse/validate YAML и TOML: обязательные поля, индексы/hash, explicit side, дубликаты mod targets/project IDs, пути, подтверждённый loader/image.
- Проверить SHA256 packwiz/Compose по lock и Git state/известные secret paths.
- Получить lock конкретной версии и временный каталог в output directory.
- Скопировать pack; выполнить packwiz refresh/export. Любое изменение metadata после refresh останавливает build, исходники не исправляются.
- Проверить экспорт, сформировать серверные файлы и выполнить Compose config.
- Записать manifest, покрыть SHA256SUMS все release files кроме SHA256SUMS; проверить checksums и неизменность build inputs.
- Атомарно переименовать готовый временный релиз; убрать временные файлы/lock.
При обычной ошибке partial release не остаётся. После принудительного убийства
процесса может остаться .build-*.lock/временный каталог: удалять их только
убедившись, что соответствующий build уже не работает.
Детерминированными являются имя и размещение артефактов. Побайтовая воспроизводимость ZIP не обещается: packwiz может включать timestamps.
Server payload
Compose образ закреплён literal digest из toolchain lock. Memory/port defaults
берутся из platform config; local env может переопределять их при запуске.
Runtime и release подключаются через абсолютные MC_ROOT и MC_RELEASE_DIR.
Release не зависит от checkout или его .tools/. Используется стабильное
Compose project name minecraft-lab-spike, как в текущем локальном runtime.
server/config/ включается в релиз и монтируется как /config: его файлы
имеют приоритет над соответствующими pack defaults. Локальный исходный
Compose spike по-прежнему включает этот слой только явным override.
Server properties генерируются environment, отдельного source-файла нет.
.env, активный локальный compose override, SSH target и platform YAML
не копируются в release. Публичный .env.example имеет EULA=FALSE.
Проверка известных secret filenames не является универсальным secret scanner.
Manifest v1
pack: name/version, Minecraft, loader ID/version.git: commit и dirty flag; generated output исключается из dirty check.tools: packwiz commit/hash, Compose version/hash, Node version/npm lock hash.server: image, подтверждённая Java major, defaults и project name.source_files: относительные пути inputs и SHA256, без содержимого config.managed_files.client/server: runtime paths, owner (pack/server), hashes и политика replace; server override помечает заменённого владельца.runtime_policy: неизвестные файлы preserve, defaultconfigs seed-only.release_files: hashes payload без manifest и SHA256SUMS, чтобы избежать циклического хеширования. SHA256SUMS дополнительно покрывает manifest.
Ownership описывает контракт для будущего deploy; Phase 2 сама ничего
не удаляет из runtime. Совместимость Java проверяется по записи Phase 0
в platform/compatibility.json, а не новым запуском Docker при каждом build.
Новая комбинация требует отдельного spike и записи результата.