diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 424a3d2..8f9052e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,6 +68,11 @@ jobs: # runner checkout per run, so there's no bigregister.db (WP-22, gitignored) # left over from a prior run to leak state in; the backend creates + migrates # an empty one on this boot, same as a fresh clone always has. + # Playwright's `webServer` (playwright.config.ts) starts BOTH the backend and + # `ng serve`, waits for them, runs the suite, and tears them down — all in the + # one `npm run e2e` process. Do NOT background them as separate steps: a `&` + # process from one Actions step is dead by the next step, so `wait-on` hung + # forever (the 2-hour e2e hang). runs-on: ubuntu-latest timeout-minutes: 15 steps: @@ -81,9 +86,6 @@ jobs: dotnet-version: 10.0.x - run: npm ci - run: npx playwright install --with-deps chromium - - run: dotnet run --project backend/src/BigRegister.Api --urls http://localhost:5000 & - - run: npx ng serve --proxy-config proxy.conf.json & - - run: npx wait-on http://localhost:5000/swagger http://localhost:4200 - run: npm run e2e codeql: diff --git a/playwright.config.ts b/playwright.config.ts index ef1f86c..0106bc7 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -15,15 +15,26 @@ export default defineConfig({ trace: 'on-first-retry', }, projects: [{ name: 'chromium', use: { browserName: 'chromium' } }], - // CI starts `ng serve` + the backend as separate job steps (both need to be up - // before the suite runs); locally, boot `npm start` automatically so `npm run e2e` - // works standalone — the backend still needs `dotnet run` running separately. - webServer: process.env['CI'] - ? undefined - : { - command: 'npm start', - url: baseURL, - reuseExistingServer: true, - timeout: 120_000, - }, + // Playwright owns both servers' lifecycle — start, wait-for-ready, tear down — in the + // one `npm run e2e` process, so `npm run e2e` is self-contained locally AND in CI. + // Do NOT background them as separate CI steps: a process started with `&` in one + // Actions `run:` step is killed when that step's shell exits, so a later `wait-on` + // step hangs forever on servers that are already gone (the 2-hour e2e hang). + // `reuseExistingServer` locally lets you run against an already-running app (incl. the + // docker stack on 4200/5000); CI always starts fresh. Backend gets a longer timeout — + // `dotnet run` cold-restores+builds before it listens. + webServer: [ + { + command: 'dotnet run --project backend/src/BigRegister.Api --urls http://localhost:5000', + url: 'http://localhost:5000/swagger', + reuseExistingServer: !process.env['CI'], + timeout: 180_000, + }, + { + command: 'npm start', + url: baseURL, + reuseExistingServer: !process.env['CI'], + timeout: 120_000, + }, + ], }); diff --git a/scripts/ci-local.sh b/scripts/ci-local.sh index e9527bf..b93d09f 100755 --- a/scripts/ci-local.sh +++ b/scripts/ci-local.sh @@ -25,6 +25,7 @@ if [[ "${1:-}" == "--full" ]]; then fi printf '\n\033[1;32m✔ local CI passed\033[0m\n' -printf 'Note: the e2e job is not run here — it needs the backend + ng serve up. Run:\n' -printf ' (backend) dotnet run --project backend/src/BigRegister.Api --urls http://localhost:5000 &\n' -printf ' (frontend) npx ng serve & then npm run e2e\n' +printf 'Note: the e2e job is not chained here (it is slow). Run it standalone with:\n' +printf ' npm run e2e\n' +printf 'Playwright starts the backend + ng serve itself (playwright.config.ts webServer),\n' +printf 'reusing an already-running app on 4200/5000 if present.\n'