приложение собрано каркасом и вшито в бинарник

- заведён каталог web/ — Vue 3, роутер пятой версии, сборка Vite; собранное
  вшивается через go:embed и раздаётся корневым маршрутом: разметка на
  неизвестном пути вне корней сервиса, отказ контракта внутри корня
- перечень корней сервиса стал единой точкой и порождает регистрацию маршрутов,
  а не описывает её; журнал раздачи пишет исход и длину пути, но не сам путь
- шаг front зовёт Node контейнером docker — Biome, юнит-тесты Vue и сборка
  входят в гейт, а в Dockerfile появилась ступень приложения
This commit is contained in:
av
2026-08-15 18:51:05 +03:00
parent c6ffda9aac
commit 663021f712
46 changed files with 5958 additions and 43 deletions
+76
View File
@@ -24,6 +24,9 @@ tasks:
gate:
desc: 'Все проверки разом. База диффа: task gate BASE=<rev>'
cmds:
# Приложение собирается первым: вшивание требует готового каталога, и
# `go build` без него соберёт бинарник со вчерашней сборкой.
- task: front
- go build ./...
- go vet ./...
- |
@@ -122,6 +125,79 @@ tasks:
fi
done
front:
desc: 'Приложение: зависимости, проверки, сборка'
vars:
# Образ берётся из Dockerfile: там он объявлен ступенью сборки. Второй дом
# версии сборочного окружения разошёлся бы с первым молча, а своего шага
# сверки у него, в отличие от версий Go, нет.
NODE_IMAGE:
sh: grep -oP '^FROM \K\S*node:\S*' Dockerfile | head -1
# Кэш установщика лежит вне дерева проекта: внутри контейнера он не пережил
# бы прогон, и каждый набор проверок тянул бы зависимости заново.
NPM_CACHE: '{{.NPM_CACHE | default "/tmp/transcriber-npm-cache"}}'
cmds:
# Node на машину не ставится — он зовётся контейнером, тем же образом,
# каким собирается ступень образа. Требованием к машине остаётся docker.
- |
set -eu
if ! command -v docker >/dev/null 2>&1; then
echo "docker не найден в PATH"
echo "приложение собирается контейнером: https://docs.docker.com/engine/install/"
exit 3
fi
if [ -z "{{.NODE_IMAGE}}" ]; then
echo "в Dockerfile не нашлось ступени с образом node"
exit 3
fi
mkdir -p "{{.NPM_CACHE}}"
run() {
docker run --rm \
-u "$(id -u):$(id -g)" \
-e npm_config_cache=/npmcache \
-v "{{.NPM_CACHE}}:/npmcache" \
-v "$PWD/web:/web" \
-w /web \
"{{.NODE_IMAGE}}" \
sh -c "$1"
}
# Зависимости ставятся из файла замка командой, которая его не правит:
# иначе набор проверок пачкал бы рабочее дерево, а собранное им
# расходилось бы с собранным в образе.
#
# Сперва — установка из кэша, без единого обращения наружу: кэш лежит
# вне дерева проекта и переживает прогоны, поэтому обычный случай сети
# не требует вовсе.
if ! run 'npm ci --offline' >/dev/null 2>&1; then
# Кэша не хватило — значит нужна сеть, и её наличие проверяется одним
# коротким обращением. Без этой проверки установщик уходит в повторы с
# нарастающей паузой и **висит на каждом пакете**: гейт, который висит,
# хуже красного — он не даёт ни исхода, ни причины.
if ! run 'npm ping --fetch-timeout=15000 --fetch-retries=0' >/dev/null 2>&1; then
echo "реестр пакетов недоступен"
echo "шагу нужна сеть: он ставит зависимости приложения и тянет образ"
exit 3
fi
# Сеть здесь уже заведомо есть — проба реестра прошла. Значит всякий
# отказ установки это отказ проекта: замок разошёлся с package.json,
# пакет снят из реестра, сломался его postinstall. По словарю кодов
# это дрейф, а не окружение: код 3 отправил бы человека чинить docker
# и сеть вместо `git diff web/package-lock.json`.
if ! run 'npm ci'; then
echo "зависимости приложения не установились, а реестр доступен"
echo "смотри расхождение web/package-lock.json с web/package.json"
exit 1
fi
fi
run 'npm run check && npm run test && npm run build'
shell:
desc: 'shellcheck на скрипты оболочки'
cmds: