build: versions.env как единый контракт продукта, платформы и toolchain
Версии были размазаны: PACKAGE_VERSION в build.sh, схема конфигурации в profile.ts и в hy2xs.env, версии toolchain в deps.sh, Debian 13 в нескольких местах. Расхождение уже перестало быть теоретическим - пакет 1.0.0 сообщал "HY2XS admin version v0.0.22". Введён корневой versions.env: версия продукта, линия релиза, схема конфигурации, целевая платформа, версии и контрольные суммы Go/Bun/Node/pnpm, политика выбора Hysteria. Чего в нём нет намеренно: 1. Прикладных зависимостей - у них есть pnpm-lock.yaml, bun.lock, go.sum. Второй слой неизбежно разъедется с настоящим графом. 2. Конкретной версии Hysteria - здесь только политика HYSTERIA_CHANNEL, результат резолва живёт в hysteria-lock.env. Пин версии здесь вернул бы ручное обновление. Подход - проверка, а не генерация. profile.ts, hy2xs.env и packageManager в двух package.json остаются обычными файлами, чтобы bun test, tsc и go test работали из чистого чекаута до сборки. Новый шаг verify_versions_contract роняет сборку до создания tarball при расхождении. Контракт оркестратора сверяется не grep'ом по исходникам, а выводом print-contract.ts: это доказывает, что в бинарь попало то же значение. Версия админки перестала быть константой и приезжает через ldflags; собранный бинарь проверяется запуском hy2xs-admin version. Контрольные суммы toolchain больше не передаются через окружение. Для Bun зафиксированы обе суммы: артефакт выбирается по наличию AVX2, поэтому одной архитектурно недостаточно. Production-сборка снова запускается одной командой.
This commit is contained in:
@@ -3,6 +3,7 @@ set -euo pipefail
|
||||
|
||||
require_repo_layout() {
|
||||
[ -f "LICENSE" ] || fail "missing LICENSE"
|
||||
[ -f "versions.env" ] || fail "missing versions.env (product/platform/toolchain contract)"
|
||||
[ -d "orchestrator/src" ] || fail "missing orchestrator/src"
|
||||
[ -f "orchestrator/package.json" ] || fail "missing orchestrator/package.json"
|
||||
[ -f "orchestrator/bun.lock" ] || fail "missing orchestrator/bun.lock"
|
||||
@@ -58,6 +59,25 @@ verify_archive() {
|
||||
printf '%s\n' "$listing" | grep -q '^hy2xs-install/metadata/hysteria.url$' || fail "archive missing pinned Hysteria artifact url"
|
||||
printf '%s\n' "$listing" | grep -q '^hy2xs-install/metadata/hysteria.sha256$' || fail "archive missing pinned Hysteria sha256"
|
||||
printf '%s\n' "$listing" | grep -q '^hy2xs-install/metadata/hysteria.resolution$' || fail "archive missing Hysteria resolution marker"
|
||||
printf '%s\n' "$listing" | grep -q '^hy2xs-install/metadata/package.release_line$' || fail "archive missing product release line"
|
||||
printf '%s\n' "$listing" | grep -q '^hy2xs-install/metadata/package.config_schema_version$' || fail "archive missing packaged config schema version"
|
||||
|
||||
# Двухфазный контракт установки проверяется структурно: read-only preflight
|
||||
# обязан стоять раньше первой мутации, иначе ошибочный запуск поверх
|
||||
# работающего сервера снова начнёт его ломать.
|
||||
local packaged_installer preflight_line first_mutation_line
|
||||
packaged_installer="$(tar -xOzf "$archive" hy2xs-install/install.sh)"
|
||||
printf '%s\n' "$packaged_installer" | grep -q 'preflight-install' \
|
||||
|| fail "packaged install.sh does not run the read-only preflight"
|
||||
|
||||
preflight_line="$(printf '%s\n' "$packaged_installer" | grep -n 'preflight-install --package-dir' | head -n1 | cut -d: -f1)"
|
||||
first_mutation_line="$(printf '%s\n' "$packaged_installer" \
|
||||
| grep -nE '^[[:space:]]*(install -d|install -m|ln -sf|rm -rf|cp -a)' | head -n1 | cut -d: -f1)"
|
||||
|
||||
[ -n "$preflight_line" ] || fail "packaged install.sh: could not locate the preflight invocation"
|
||||
[ -n "$first_mutation_line" ] || fail "packaged install.sh: could not locate the mutation phase"
|
||||
[ "$preflight_line" -lt "$first_mutation_line" ] \
|
||||
|| fail "packaged install.sh mutates the host (line $first_mutation_line) before the clean-host preflight (line $preflight_line)"
|
||||
|
||||
local license_text
|
||||
license_text="$(tar -xOzf "$archive" hy2xs-install/LICENSE)"
|
||||
@@ -118,6 +138,26 @@ verify_archive() {
|
||||
printf '%s\n' "$meta" | grep -q '^build_profile=production$' || fail "metadata missing build_profile=production"
|
||||
printf '%s\n' "$meta" | grep -q '^license=AGPL-3.0-only$' || fail "metadata missing license=AGPL-3.0-only"
|
||||
|
||||
# Поколение продукта обязано доехать до пакета: install-state строится из
|
||||
# него, а reconfigure/repair по нему отличают v1 от чужой установки.
|
||||
printf '%s\n' "$meta" | grep -q "^version=${HY2XS_VERSION}$" \
|
||||
|| fail "metadata version disagrees with versions.env HY2XS_VERSION=${HY2XS_VERSION}"
|
||||
printf '%s\n' "$meta" | grep -q "^release_line=${HY2XS_RELEASE_LINE}$" \
|
||||
|| fail "metadata release_line disagrees with versions.env HY2XS_RELEASE_LINE=${HY2XS_RELEASE_LINE}"
|
||||
printf '%s\n' "$meta" | grep -q "^config_schema_version=${HY2XS_CONFIG_SCHEMA_VERSION}$" \
|
||||
|| fail "metadata config_schema_version disagrees with versions.env"
|
||||
printf '%s\n' "$meta" | grep -q "^target_version=${HY2XS_TARGET_OS_VERSION}$" \
|
||||
|| fail "metadata target_version disagrees with versions.env"
|
||||
printf '%s\n' "$meta" | grep -q "^target_arch=${HY2XS_TARGET_ARCH}$" \
|
||||
|| fail "metadata target_arch disagrees with versions.env"
|
||||
|
||||
local packaged_schema
|
||||
packaged_schema="$(grep -E '^HY2XS_CONFIG_SCHEMA_VERSION=' "$tmp/hy2xs-install/config/hy2xs.env" | head -n1 | cut -d= -f2-)"
|
||||
[ "$packaged_schema" = "$HY2XS_CONFIG_SCHEMA_VERSION" ] \
|
||||
|| fail "packaged hy2xs.env declares schema $packaged_schema, versions.env declares $HY2XS_CONFIG_SCHEMA_VERSION"
|
||||
|
||||
verify_admin_version_contract "$tmp/hy2xs-install/ui/hy2xs-admin/hy2xs-admin"
|
||||
|
||||
if declare -F run_fix20_acceptance_subset >/dev/null 2>&1; then
|
||||
run_fix20_acceptance_subset "$tmp/hy2xs-install"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user