fix(rc5): harden frontend runtime and diagnostics
This commit is contained in:
+14
-9
@@ -63,15 +63,16 @@ Windows и macOS можно использовать для редактиров
|
||||
и сверяет каждый архив с контрольной суммой из `versions.env`.
|
||||
6. Выполняет `verify_versions_contract`: рассинхрон версий роняет сборку до создания tarball.
|
||||
7. Прогоняет тесты и типы оркестратора (`bun test`, `tsc --noEmit`).
|
||||
8. Разрешает upstream-версию Hysteria, берёт ожидаемый SHA-256 из upstream `hashes.txt` и сверяет с ним скачанный артефакт.
|
||||
9. Проходит compatibility gate: реальный бинарник Hysteria должен принять канонический конфиг HY2XS.
|
||||
10. Копирует package skeleton.
|
||||
11. Собирает install-only orchestrator в standalone binary.
|
||||
12. Собирает frontend и backend HY2XS admin в Linux amd64 binary, проставляя версию админки через ldflags.
|
||||
13. Прогоняет `go vet` и `go test` для HY2XS admin (после сборки frontend, потому что `go:embed all:dist` требует готовых ассетов).
|
||||
14. Записывает metadata и checksums.
|
||||
15. Создаёт `dist/hy2xs-install-<version>.tar.gz`.
|
||||
16. Проверяет архив и прогоняет acceptance-проверки.
|
||||
8. Рано прогоняет dependency-free контракты панели.
|
||||
9. Разрешает upstream-версию Hysteria, берёт ожидаемый SHA-256 из upstream `hashes.txt` и сверяет с ним скачанный артефакт.
|
||||
10. Проходит compatibility gate: реальный бинарник Hysteria должен принять канонический конфиг HY2XS.
|
||||
11. Копирует package skeleton и собирает install-only orchestrator.
|
||||
12. Устанавливает frozen frontend lock-граф, runtime-компилирует все сообщения RU/EN реальным `vue-i18n`, проверяет типы и собирает production bundle.
|
||||
13. Собирает backend HY2XS admin в Linux amd64 binary, проставляя версию через ldflags.
|
||||
14. Прогоняет `go vet` и `go test` для HY2XS admin (после сборки frontend, потому что `go:embed all:dist` требует готовых ассетов).
|
||||
15. Проверяет зависимости через `govulncheck ./...` и `pnpm audit` по всему lock-графу.
|
||||
16. Записывает metadata и checksums.
|
||||
17. Создаёт архив и прогоняет его acceptance-проверки.
|
||||
|
||||
## Контракт версий
|
||||
|
||||
@@ -99,6 +100,10 @@ Go-коде больше нет: она уже успела разъехатьс
|
||||
только политика `HYSTERIA_CHANNEL`, результат резолва — в
|
||||
[`hysteria-lock.env`](hysteria-lock.env)).
|
||||
|
||||
Security overrides frontend находятся в `apps/frontend/pnpm-workspace.yaml`:
|
||||
это канонический файл настроек pnpm. Поле `pnpm` в `package.json` для этой цели
|
||||
не используется, потому что новые версии package manager его игнорируют.
|
||||
|
||||
## Версия Hysteria: разрешение и compatibility gate
|
||||
|
||||
Builder не хранит версию Hysteria вручную. По умолчанию он определяет последнюю стабильную версию сам и замораживает её в пакете.
|
||||
|
||||
@@ -43,9 +43,9 @@ main() {
|
||||
log_step "Checking orchestrator contracts"
|
||||
run_orchestrator_tests
|
||||
|
||||
# Контракты панели проверяются рано: они не требуют ни собранного bundle, ни
|
||||
# установленных зависимостей, и падать на них после резолва Hysteria и сборки
|
||||
# артефактов означало бы платить минутами за ошибку, видимую сразу.
|
||||
# Dependency-free контракты панели проверяются рано. Runtime-компиляция
|
||||
# словарей запускается внутри bundle_ui сразу после frozen install, потому
|
||||
# что ей нужен реальный vue-i18n из frontend lock-графа.
|
||||
log_step "Checking HY2XS admin frontend contracts"
|
||||
run_frontend_tests
|
||||
|
||||
|
||||
@@ -1345,14 +1345,20 @@ $piped_matcher"
|
||||
|| fail "acceptance: прогон тестов оркестратора не фиксируется результатом"
|
||||
grep -q 'ADMIN_TESTS_PASSED' tools/build/lib/package.sh \
|
||||
|| fail "acceptance: прогон тестов админки не фиксируется результатом"
|
||||
grep -q 'FRONTEND_CONTRACT_TESTS_PASSED' tools/build/lib/package.sh \
|
||||
|| fail "acceptance: ранние контракты панели не фиксируются результатом"
|
||||
grep -q 'FRONTEND_RUNTIME_TESTS_PASSED' tools/build/lib/package.sh \
|
||||
|| fail "acceptance: runtime-компиляция локализации не фиксируется результатом"
|
||||
grep -q 'FRONTEND_TESTS_PASSED' tools/build/lib/package.sh \
|
||||
|| fail "acceptance: прогон контрактных тестов панели не фиксируется результатом"
|
||||
|| fail "acceptance: общий результат тестов панели не фиксируется"
|
||||
"$BUN_BIN" -e '
|
||||
const source = require("node:fs").readFileSync("tools/build/lib/package.sh", "utf8");
|
||||
for (const [fn, flag] of [
|
||||
["run_orchestrator_tests()", "ORCHESTRATOR_TESTS_PASSED=\"true\""],
|
||||
["run_admin_tests()", "ADMIN_TESTS_PASSED=\"true\""],
|
||||
["run_frontend_tests()", "FRONTEND_TESTS_PASSED=\"true\""]
|
||||
["run_frontend_tests()", "FRONTEND_CONTRACT_TESTS_PASSED=\"true\""],
|
||||
["bundle_ui()", "FRONTEND_RUNTIME_TESTS_PASSED=\"true\""],
|
||||
["bundle_ui()", "FRONTEND_TESTS_PASSED=\"true\""]
|
||||
]) {
|
||||
const start = source.indexOf(fn);
|
||||
if (start < 0) throw new Error("не найдена функция " + fn);
|
||||
@@ -1366,6 +1372,19 @@ $piped_matcher"
|
||||
if (set < 0) throw new Error(fn + ": результат прогона не фиксируется");
|
||||
if (set < run) throw new Error(fn + ": результат объявляется раньше, чем получен");
|
||||
}
|
||||
|
||||
const bundleStart = source.indexOf("bundle_ui()");
|
||||
const bundleRest = source.slice(bundleStart);
|
||||
const bundleEnd = bundleRest.search(/\n\}[\r\n]/);
|
||||
const bundle = bundleEnd < 0 ? bundleRest : bundleRest.slice(0, bundleEnd);
|
||||
const install = bundle.indexOf("install --frozen-lockfile");
|
||||
const runtime = bundle.indexOf("test test/i18n-runtime.test.ts");
|
||||
const typecheck = bundle.indexOf("run typecheck");
|
||||
const build = bundle.indexOf("run build:prod");
|
||||
if (install < 0 || runtime < 0) throw new Error("runtime i18n gate не найден в bundle_ui");
|
||||
if (!(install < runtime && runtime < typecheck && typecheck < build)) {
|
||||
throw new Error("порядок frontend gate обязан быть install -> i18n runtime -> typecheck -> build");
|
||||
}
|
||||
' || fail "acceptance: утверждение о пройденных тестах обязано следовать за прогоном"
|
||||
|
||||
# Детектор гонок — часть прогона админки, а не пожелание.
|
||||
|
||||
@@ -64,7 +64,7 @@ run_orchestrator_tests() {
|
||||
}
|
||||
|
||||
run_frontend_tests() {
|
||||
# Контракты панели, которые не проверяются ни типами, ни сборкой bundle:
|
||||
# Ранние контракты панели, которые не требуют установленных зависимостей:
|
||||
# цвет иконок в спрайте, совпадение словарей локализации, соответствие кодов
|
||||
# ошибок серверным константам, единственность адреса атрибуции.
|
||||
#
|
||||
@@ -80,8 +80,8 @@ run_frontend_tests() {
|
||||
"$BUN_BIN" test tools/test/frontend-sprite.test.ts tools/test/frontend-contract.test.ts \
|
||||
|| fail "HY2XS admin frontend contract tests failed"
|
||||
|
||||
FRONTEND_TESTS_PASSED="true"
|
||||
export FRONTEND_TESTS_PASSED
|
||||
FRONTEND_CONTRACT_TESTS_PASSED="true"
|
||||
export FRONTEND_CONTRACT_TESTS_PASSED
|
||||
}
|
||||
|
||||
run_admin_tests() {
|
||||
@@ -146,6 +146,9 @@ build_orchestrator() {
|
||||
bundle_ui() {
|
||||
local ui_src="${UI_SRC:-apps}"
|
||||
|
||||
[ "${FRONTEND_CONTRACT_TESTS_PASSED:-false}" = "true" ] \
|
||||
|| fail "bundle_ui: ранние контракты панели не проверялись"
|
||||
|
||||
rm -rf "$ADMIN_BUILD_DIR"
|
||||
mkdir -p "$ADMIN_BUILD_DIR"
|
||||
|
||||
@@ -164,6 +167,12 @@ bundle_ui() {
|
||||
|
||||
"$PNPM_BIN" install --frozen-lockfile
|
||||
|
||||
# Словари являются JavaScript-объектами и компилируются vue-i18n только
|
||||
# при вызове t(). Поэтому ни vue-tsc, ни Vite не видят синтаксическую
|
||||
# ошибку сообщения. Gate использует тот же установленный runtime, обходит
|
||||
# все строки обоих языков и выполняется до typecheck и production bundle.
|
||||
"$BUN_BIN" test test/i18n-runtime.test.ts
|
||||
|
||||
# Проверка типов идёт ПЕРЕД сборкой bundle, и это обязательный шаг релиза.
|
||||
#
|
||||
# Раньше её здесь не было вовсе: `build:prod` означал
|
||||
@@ -176,7 +185,7 @@ bundle_ui() {
|
||||
# кода, который не проходит проверку типов, нет.
|
||||
"$PNPM_BIN" run typecheck
|
||||
"$PNPM_BIN" run build:prod
|
||||
)
|
||||
) || fail "HY2XS admin frontend runtime tests or bundle failed"
|
||||
|
||||
# Версия админки приходит из versions.env через ldflags: один и тот же
|
||||
# исполняемый файл обязан знать версию пакета, из которого он собран.
|
||||
@@ -196,6 +205,12 @@ bundle_ui() {
|
||||
mkdir -p "$STAGE_DIR/ui/hy2xs-admin/docs/sql"
|
||||
install -m 0644 "$ui_src/docs/sql/schema.sql" "$STAGE_DIR/ui/hy2xs-admin/docs/sql/schema.sql"
|
||||
fi
|
||||
|
||||
# Оба утверждения выставляются только после dependency-free контрактов,
|
||||
# runtime-компиляции словарей и успешной сборки production bundle.
|
||||
FRONTEND_RUNTIME_TESTS_PASSED="true"
|
||||
FRONTEND_TESTS_PASSED="true"
|
||||
export FRONTEND_RUNTIME_TESTS_PASSED FRONTEND_TESTS_PASSED
|
||||
}
|
||||
|
||||
write_metadata() {
|
||||
|
||||
Reference in New Issue
Block a user