ci: PostgreSQL 17 с ролями как в pilot, roundtrip миграций, e2e, SHA-пины
Зачем: прежний CI запускал миграции и тесты под POSTGRES_USER сервиса (суперпользователь), не проверял откат миграций, не запускал e2e на реальной БД, держал плавающие теги actions (F13) и выполнял docker build в контейнере без Docker daemon. - verify: bootstrap-админ сервиса только создаёт роли (provision-pg.mjs, пароли случайные); миграции up -> откат всех -> up -> up (no-op) ролью krona_migrator без SUPERUSER; `npm run check` с DATABASE_TEST_URL (app-роль) и DATABASE_TEST_MIGRATION_URL (очистка, см. N5); npm audit. - format: prettier вынесен в отдельную задачу — он красный по 25 файлам (F14) и не должен маскировать статус verify/e2e. - e2e: реальный сервер + PostgreSQL 17 через scripts/test/run-e2e.mjs. Выбран «храповик» known-defects.json, а не отдельная задача с continue-on-error: так CI зелёный, только если стенд работает и каждый красный сценарий — известный открытый дефект; новый красный сценарий (регрессия) или исправленный, но не вычеркнутый дефект делают задачу красной. continue-on-error скрыл бы и поломку самого стенда. - docker-build: отдельная задача на метке `docker-host` только для push, после verify; без такого раннера она ждёт в очереди, не блокируя остальные. - actions/checkout v4.4.0 и actions/setup-node v4.4.0 закреплены SHA (git ls-remote; одинаковы на github.com и code.forgejo.org). Проверено: actionlint 1.7.12 (метки docker/docker-host объявлены как self-hosted) — 0 замечаний; scripts/test/ci-local.sh повторяет шаги verify/format/e2e на локальной PostgreSQL 17.11 (Forgejo-раннер реально не запускался — не проверено).
This commit is contained in:
parent
9bdfb66a53
commit
f59be3adf9
2 changed files with 113 additions and 15 deletions
|
|
@ -3,6 +3,16 @@ on:
|
||||||
push:
|
push:
|
||||||
branches: [main, codex/bootstrap-platform-foundation]
|
branches: [main, codex/bootstrap-platform-foundation]
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
|
# Все actions закреплены полным SHA коммита (F13); SHA получены `git ls-remote`
|
||||||
|
# и совпадают на github.com и code.forgejo.org (зеркало), поэтому закрепление
|
||||||
|
# работает при любом DEFAULT_ACTIONS_URL раннера.
|
||||||
|
#
|
||||||
|
# Роли БД как в pilot, но с минимальными привилегиями: POSTGRES_USER сервиса —
|
||||||
|
# только bootstrap-админ (роль DBA/entrypoint образа), им scripts/test/provision-pg.mjs
|
||||||
|
# создаёт krona_migrator (NOSUPERUSER, владелец БД) и krona_staff_app (NOBYPASSRLS)
|
||||||
|
# со случайными паролями. Ни миграции, ни тесты, ни сервер под bootstrap-админом не работают.
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
verify:
|
verify:
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
|
@ -10,27 +20,85 @@ jobs:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:17-alpine@sha256:18cfe3ef5e6815560c98237d6216d1e5119702fb0f3894c8785dd58b8bbe5d73
|
image: postgres:17-alpine@sha256:18cfe3ef5e6815560c98237d6216d1e5119702fb0f3894c8785dd58b8bbe5d73
|
||||||
env:
|
env:
|
||||||
POSTGRES_DB: krona_staff
|
POSTGRES_DB: postgres
|
||||||
POSTGRES_USER: krona_migrator
|
POSTGRES_USER: ci_bootstrap
|
||||||
POSTGRES_PASSWORD: ci-migration-password
|
POSTGRES_PASSWORD: ci-bootstrap-only
|
||||||
ports: ['5432:5432']
|
|
||||||
options: >-
|
options: >-
|
||||||
--health-cmd "pg_isready -U krona_migrator -d krona_staff"
|
--health-cmd "pg_isready -U ci_bootstrap -d postgres"
|
||||||
--health-interval 5s
|
--health-interval 5s
|
||||||
--health-timeout 3s
|
--health-timeout 3s
|
||||||
--health-retries 20
|
--health-retries 20
|
||||||
env:
|
env:
|
||||||
DATABASE_MIGRATION_URL: postgres://krona_migrator:ci-migration-password@postgres:5432/krona_staff
|
E2E_PG_ADMIN_URL: postgres://ci_bootstrap:ci-bootstrap-only@postgres:5432/postgres
|
||||||
DATABASE_TEST_URL: postgres://krona_staff_app:ci-app-password@postgres:5432/krona_staff
|
|
||||||
POSTGRES_APP_PASSWORD: ci-app-password
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with: { node-version: 22, cache: npm }
|
with: { node-version: 22, cache: npm }
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: node scripts/create-app-role.mjs
|
- name: provision roles (migrator NOSUPERUSER, app NOBYPASSRLS)
|
||||||
- run: node scripts/migrate.mjs up
|
run: node scripts/test/provision-pg.mjs --out "$RUNNER_TEMP/db.env" --db krona_staff
|
||||||
- run: npm run check
|
- name: migrations up -> rollback all -> up -> up (no-op)
|
||||||
- run: npm run format:check
|
run: |
|
||||||
|
set -a; . "$RUNNER_TEMP/db.env"; set +a
|
||||||
|
node scripts/test/migrate-roundtrip.mjs roundtrip
|
||||||
|
- name: npm run check (tenant-isolation on real PostgreSQL as app role)
|
||||||
|
run: |
|
||||||
|
set -a; . "$RUNNER_TEMP/db.env"; set +a
|
||||||
|
unset DATABASE_URL POSTGRES_APP_PASSWORD
|
||||||
|
npm run check
|
||||||
- run: npm audit --audit-level=high
|
- run: npm audit --audit-level=high
|
||||||
- run: docker build -t krona-staff:${{ forgejo.sha }} .
|
|
||||||
|
# Отдельная задача: prettier сейчас красный по 25 файлам (F14), и это не должно
|
||||||
|
# маскировать статус verify/e2e.
|
||||||
|
format:
|
||||||
|
runs-on: docker
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||||
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
|
with: { node-version: 22, cache: npm }
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run format:check
|
||||||
|
|
||||||
|
# Приёмочные сценарии на реальном сервере и PostgreSQL 17. Красные сценарии
|
||||||
|
# известных открытых дефектов перечислены в tests/e2e/known-defects.json:
|
||||||
|
# задача зелёная, если стенд работает ([HARNESS]/[CTRL] зелёные) и каждый
|
||||||
|
# красный сценарий есть в списке; новый красный сценарий или исправленный,
|
||||||
|
# но не вычеркнутый дефект делают задачу красной.
|
||||||
|
e2e:
|
||||||
|
runs-on: docker
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:17-alpine@sha256:18cfe3ef5e6815560c98237d6216d1e5119702fb0f3894c8785dd58b8bbe5d73
|
||||||
|
env:
|
||||||
|
POSTGRES_DB: postgres
|
||||||
|
POSTGRES_USER: ci_bootstrap
|
||||||
|
POSTGRES_PASSWORD: ci-bootstrap-only
|
||||||
|
options: >-
|
||||||
|
--health-cmd "pg_isready -U ci_bootstrap -d postgres"
|
||||||
|
--health-interval 5s
|
||||||
|
--health-timeout 3s
|
||||||
|
--health-retries 20
|
||||||
|
env:
|
||||||
|
E2E_PG_ADMIN_URL: postgres://ci_bootstrap:ci-bootstrap-only@postgres:5432/postgres
|
||||||
|
E2E_MIGRATIONS: roundtrip
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||||
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
|
with: { node-version: 22, cache: npm }
|
||||||
|
- run: npm ci
|
||||||
|
- name: e2e (known-defects ratchet)
|
||||||
|
run: node scripts/test/run-e2e.mjs
|
||||||
|
- name: e2e table
|
||||||
|
if: always()
|
||||||
|
run: cat tests/e2e/evidence/e2e-table.md || true
|
||||||
|
|
||||||
|
# docker build требует Docker daemon, которого нет в контейнере метки `docker`.
|
||||||
|
# Нужен раннер с меткой `docker-host` (хост с доступом к Docker). Пока такого
|
||||||
|
# раннера нет, задача ждёт в очереди и не блокирует verify/format/e2e.
|
||||||
|
docker-build:
|
||||||
|
runs-on: docker-host
|
||||||
|
needs: [verify]
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||||
|
- run: docker build -t "krona-staff:${GITHUB_SHA}" .
|
||||||
|
|
|
||||||
30
scripts/test/ci-local.sh
Executable file
30
scripts/test/ci-local.sh
Executable file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Локальный эквивалент задач verify/format/e2e из .forgejo/workflows/ci.yml
|
||||||
|
# (без Docker: PostgreSQL 17 уже запущен, E2E_PG_ADMIN_URL указывает на bootstrap-админа).
|
||||||
|
# docker-build локально не воспроизводится: Docker в этой среде нет.
|
||||||
|
set -uo pipefail
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
: "${E2E_PG_ADMIN_URL:?E2E_PG_ADMIN_URL (bootstrap-админ PostgreSQL 17) обязателен}"
|
||||||
|
tmp="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$tmp"' EXIT
|
||||||
|
status=0
|
||||||
|
step() {
|
||||||
|
local name="$1"
|
||||||
|
shift
|
||||||
|
echo "::: [$name] $*"
|
||||||
|
if "$@"; then echo "::: [$name] OK"; else local code=$?; echo "::: [$name] FAIL exit=$code"; status=1; fi
|
||||||
|
}
|
||||||
|
with_db_env() { (set -a; . "$tmp/db.env"; set +a; unset DATABASE_URL POSTGRES_APP_PASSWORD; "$@"); }
|
||||||
|
|
||||||
|
echo "=== job verify"
|
||||||
|
step npm-ci npm ci --no-audit --no-fund
|
||||||
|
step provision node scripts/test/provision-pg.mjs --out "$tmp/db.env" --db krona_staff
|
||||||
|
step migrate-roundtrip with_db_env node scripts/test/migrate-roundtrip.mjs roundtrip
|
||||||
|
step check with_db_env npm run check
|
||||||
|
step audit npm audit --audit-level=high
|
||||||
|
echo "=== job format"
|
||||||
|
step format-check npm run format:check
|
||||||
|
echo "=== job e2e"
|
||||||
|
step e2e env E2E_MIGRATIONS=roundtrip node scripts/test/run-e2e.mjs
|
||||||
|
echo "=== итог: status=$status"
|
||||||
|
exit $status
|
||||||
Loading…
Reference in a new issue