Files
minecraft-lab/docs/build.md
T
2026-10-04 00:30:09 +07:00

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

  1. Parse/validate YAML и TOML: обязательные поля, индексы/hash, explicit side, дубликаты mod targets/project IDs, пути, подтверждённый loader/image.
  2. Проверить SHA256 packwiz/Compose по lock и Git state/известные secret paths.
  3. Получить lock конкретной версии и временный каталог в output directory.
  4. Скопировать pack; выполнить packwiz refresh/export. Любое изменение metadata после refresh останавливает build, исходники не исправляются.
  5. Проверить экспорт, сформировать серверные файлы и выполнить Compose config.
  6. Записать manifest, покрыть SHA256SUMS все release files кроме SHA256SUMS; проверить checksums и неизменность build inputs.
  7. Атомарно переименовать готовый временный релиз; убрать временные файлы/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 и записи результата.