ci(web): Phase P6 — vite build + headless E2E gate on every trunk merge (#1445) (#1454)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
This commit was merged in pull request #1454.
This commit is contained in:
@@ -254,6 +254,23 @@ steps:
|
||||
depends_on:
|
||||
- typecheck
|
||||
|
||||
# Canonical verify:release stage `build` (#1445, P6): every PR proves the
|
||||
# full workspace build — including the SPA `vite build` — before merge,
|
||||
# instead of leaving build breakage to surface post-merge in publish.yml's
|
||||
# verify step. Same canonical command the publish pipeline's build step runs.
|
||||
build:
|
||||
image: *node_image
|
||||
commands:
|
||||
- *enable_pnpm
|
||||
- pnpm build
|
||||
depends_on:
|
||||
# after test, not typecheck: turbo gives `test` a ^build dependency, so
|
||||
# running this step concurrently with test would put two independent
|
||||
# turbo builds on the same shared-workspace dist/ and turbo cache with
|
||||
# no cross-process locking — the same serialization invariant
|
||||
# publish.yml documents for #1411.
|
||||
- test
|
||||
|
||||
services:
|
||||
ci-postgres:
|
||||
image: pgvector/pgvector:pg17
|
||||
|
||||
@@ -407,6 +407,96 @@ steps:
|
||||
- build
|
||||
- verify
|
||||
|
||||
# #1445 (P6): headless Playwright E2E gate on every trunk merge. Boots the
|
||||
# real gateway on the embedded PGlite path (no DATABASE_URL, no services)
|
||||
# serving the built SPA bundle via WEB_DIST_DIR — the exact serving path the
|
||||
# gateway image ships (docker/gateway.Dockerfile sets WEB_DIST_DIR to the
|
||||
# baked bundle), which keeps #1407's parity guarantee: the image build steps
|
||||
# below depend on this gate, so a bundle that fails E2E never publishes.
|
||||
#
|
||||
# Image pinned to the @playwright/test version in pnpm-lock.yaml so the
|
||||
# image's bundled browsers match the workspace driver exactly (bump the two
|
||||
# together). The step installs no workspace packages (corepack does fetch
|
||||
# the pinned pnpm itself): it reuses the workspace node_modules
|
||||
# from `install` and the dist outputs from `build` — the gateway's runtime
|
||||
# dependency path is pure JS/WASM (PGlite is WASM, postgres-js is pure JS),
|
||||
# so the alpine-installed modules run unchanged under this glibc image.
|
||||
# depends_on publish-next-npm per the #1411 serialization invariant: this
|
||||
# step reads the workspace and must never run inside the manifest-transform
|
||||
# window.
|
||||
e2e:
|
||||
image: mcr.microsoft.com/playwright:v1.58.2-noble
|
||||
environment:
|
||||
GATEWAY_PORT: '14242'
|
||||
PLAYWRIGHT_BASE_URL: http://localhost:14242
|
||||
# The database is seeded by Playwright's globalSetup in this step, so
|
||||
# login failures are real failures: without this flag the suite's
|
||||
# skip-when-login-fails guards (a live-environment affordance) could
|
||||
# skip every authenticated spec and go green while proving nothing.
|
||||
E2E_REQUIRE_SEEDED_AUTH: '1'
|
||||
commands:
|
||||
- corepack enable
|
||||
- |
|
||||
# Throwaway signing secret for this step's ephemeral embedded database
|
||||
# (the gateway refuses to boot without one). Generated per run so no
|
||||
# usable literal lives in the tree.
|
||||
export BETTER_AUTH_SECRET="$(head -c 32 /dev/urandom | base64)"
|
||||
export WEB_DIST_DIR="$(pwd)/apps/web/dist"
|
||||
if [ ! -f "$WEB_DIST_DIR/index.html" ]; then
|
||||
echo "[e2e] FATAL: $WEB_DIST_DIR/index.html missing — did the build step run?" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Boot the gateway from the built dist, cwd- AND HOME-isolated: the
|
||||
# local-tier PGlite database lives under $HOME/.config/mosaic/gateway/
|
||||
# (database.module.ts), not under cwd, so HOME must point at the
|
||||
# throwaway dir too or the run would share a database with anything
|
||||
# else in the container's home.
|
||||
GATEWAY_RUN_DIR="$(mktemp -d /tmp/e2e-gateway.XXXXXX)"
|
||||
(cd "$GATEWAY_RUN_DIR" && export HOME="$GATEWAY_RUN_DIR" && exec node "$OLDPWD/apps/gateway/dist/main.js") > /tmp/gateway.log 2>&1 &
|
||||
GATEWAY_PID=$!
|
||||
ready=0
|
||||
for i in $(seq 1 90); do
|
||||
if node -e "fetch('http://localhost:' + process.env.GATEWAY_PORT + '/health', { signal: AbortSignal.timeout(2000) }).then((r) => process.exit(r.ok ? 0 : 1), () => process.exit(1))"; then
|
||||
ready=1
|
||||
break
|
||||
fi
|
||||
if ! kill -0 "$GATEWAY_PID" 2>/dev/null; then
|
||||
echo "[e2e] FATAL: gateway process exited during startup" >&2
|
||||
cat /tmp/gateway.log >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "[e2e] waiting for gateway ($i/90)..."
|
||||
sleep 1
|
||||
done
|
||||
if [ "$ready" -ne 1 ]; then
|
||||
echo "[e2e] FATAL: gateway did not become ready in 90s" >&2
|
||||
cat /tmp/gateway.log >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "[e2e] gateway ready; running Playwright suite"
|
||||
set +e
|
||||
pnpm --filter @mosaicstack/web exec playwright test
|
||||
E2E_EXIT=$?
|
||||
set -e
|
||||
kill "$GATEWAY_PID" 2>/dev/null || true
|
||||
if [ "$E2E_EXIT" -ne 0 ]; then
|
||||
echo "[e2e] FATAL: Playwright suite failed (exit $E2E_EXIT); gateway log follows" >&2
|
||||
tail -100 /tmp/gateway.log >&2
|
||||
echo "[e2e] browser-side traces/screenshots are under apps/web/test-results/ in the step workspace (not persisted past the pod)" >&2
|
||||
fi
|
||||
exit "$E2E_EXIT"
|
||||
# Same filter as the image builds it gates: a merge that publishes no
|
||||
# image (docs-only on main) pays no browser suite, and a skipped e2e does
|
||||
# not block anything (skipped-dependency semantics, same as
|
||||
# publish-next-npm on tag events).
|
||||
when: *image_build_when
|
||||
depends_on:
|
||||
- build
|
||||
- verify
|
||||
# #1411: never read the workspace inside publish-next-npm's
|
||||
# manifest-transform window.
|
||||
- publish-next-npm
|
||||
|
||||
# TODO: Uncomment when ready to publish to npmjs.org
|
||||
# publish-npmjs:
|
||||
# image: *node_image
|
||||
@@ -466,6 +556,8 @@ steps:
|
||||
# ERR_PNPM_OUTDATED_LOCKFILE despite a clean restore. This edge is the
|
||||
# serialization invariant; add it to every new workspace consumer.
|
||||
- publish-next-npm
|
||||
# #1445 (P6): a bundle that fails the E2E gate never publishes an image.
|
||||
- e2e
|
||||
|
||||
build-appservice:
|
||||
image: gcr.io/kaniko-project/executor:debug
|
||||
@@ -510,3 +602,5 @@ steps:
|
||||
# ERR_PNPM_OUTDATED_LOCKFILE despite a clean restore. This edge is the
|
||||
# serialization invariant; add it to every new workspace consumer.
|
||||
- publish-next-npm
|
||||
# #1445 (P6): a bundle that fails the E2E gate never publishes an image.
|
||||
- e2e
|
||||
|
||||
Reference in New Issue
Block a user