diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 4da5bad..98853a3 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -38,8 +38,18 @@ jobs: # bun drives installs (repo ships bun.lock, no package-lock.json); pinned to the # same major as oven/bun in the Dockerfile. + # Retried: the runner's outbound network/DNS is flaky (transient EAI_AGAIN seen in CI). - name: Install bun - run: npm i -g bun@1.4.2 + run: | + set -u + ok=0 + for i in 1 2 3; do + if npm i -g bun@1.4.2; then ok=1; break; fi + echo "::warning::bun install attempt $i/3 failed (likely transient network) — retrying in 5s" >&2 + sleep 5 + done + [ "$ok" = "1" ] || { echo "::error::bun install failed after 3 attempts" >&2; exit 1; } + bun --version # Job-level dep cache via the runner's built-in cache server. continue-on-error on # both steps: an unreachable/broken cache server must never break the run. @@ -52,8 +62,17 @@ jobs: $HOME/.bun/install/cache key: ${{ runner.os }}-deps-bun-${{ hashFiles('bun.lock') }} + # Retried: the runner's outbound network/DNS is flaky (transient EAI_AGAIN seen in CI). - name: Install dependencies - run: bun install --frozen-lockfile + run: | + set -u + ok=0 + for i in 1 2 3; do + if bun install --frozen-lockfile; then ok=1; break; fi + echo "::warning::dependency install attempt $i/3 failed (likely transient network) — retrying in 5s" >&2 + sleep 5 + done + [ "$ok" = "1" ] || { echo "::error::dependency install failed after 3 attempts" >&2; exit 1; } - name: Save deps cache uses: actions/cache@v4 @@ -76,6 +95,19 @@ jobs: - name: Install browsers (local) run: npx playwright install --with-deps chromium + # Pre-build the e2e image with retries (flaky runner network); the E2E step's own + # build then becomes a fast no-op. Plain progress keeps BuildKit output visible. + - name: Build e2e image (retries) + run: | + set -u + ok=0 + for i in 1 2 3; do + if docker compose -f docker-compose.ci.yml -p flight-ci build --progress=plain; then ok=1; break; fi + echo "::warning::e2e image build attempt $i/3 failed (likely transient network) — retrying in 5s" >&2 + sleep 5 + done + [ "$ok" = "1" ] || { echo "::error::e2e image build failed after 3 attempts" >&2; exit 1; } + # E2E against an isolated stack on the shared daemon — never the production instance. # docker-compose.ci.yml joins the flight-ci-e2e network prepared above; project name # flight-ci keeps it distinct from production. E2E_DEPLOY_CMD makes the config's diff --git a/CHANGELOG.md b/CHANGELOG.md index 339c2e5..86c10e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - **@playwright/test pinned as devDependency** (`1.63.0`, matching the shared remote browser server image and the global install) so CI is self-contained; still excluded from the runtime image via .dockerignore (comment updated), prod-deps stage unaffected - `AGENTS.md`: "Change process" + "E2E tests" rewritten for the PR workflow — feature branch off master → commits with CHANGELOG entry + version bump → PR to master → CI (build→unit→e2e) green → merge → tag on master → manual production deploy via `docker compose up -d --build`; no direct pushes to master, CI never deploys - **CI build reliability + caching** (after first dind runs): the e2e image is now built with `--progress=plain` before `up -d` so BuildKit step output lands in job logs instead of being hidden by auto progress; Dockerfile bun installs use a BuildKit cache mount (`/root/.bun/install/cache`) that persists on the runner's shared daemon, and CI restores/saves node_modules + the bun cache via actions/cache around dependency install (both steps `continue-on-error` — safe while the runner's cache server is being fixed) +- **CI retry wrappers for the flaky runner network/DNS** (transient EAI_AGAIN failures seen in runs #10/#11): bun install, dependency install and the e2e image build each retry up to 3× with 5s between attempts before failing; the image is pre-built by a dedicated retried step so the E2E step's own build becomes a fast no-op - Verified: unit suite 234 green locally; e2e not run locally by design (would deploy to production) — first real pass happens in the PR's CI run ## v0.12.2 — 2026-09-18 14:06