Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,40 @@ jobs:
- run: npm run test:run
- run: npm run migrate:smoke
- run: npm run build
- run: docker build --target runner .
- run: docker build --target runner -t auth-runner:ci .
- run: docker build --target worker .
# The image that ships is the one under test: nonce CSP, HSTS, the
# standalone server and migrate-on-boot only exist in production mode.
# --network host lets the container reach the service containers on
# localhost and lets Playwright reach it on 127.0.0.1:3000. The
# Turnstile pair is Cloudflare's documented always-pass test keypair.
- name: Boot the runner image
run: |
docker run -d --name auth-runner --network host \
-e DATABASE_URL -e REDIS_URL -e OIDC_PRIVATE_KEY_PEM -e OIDC_KEY_ID \
-e AUTH_BASE_URL=http://127.0.0.1:3000 \
-e OAUTH_CSRF_SECRET=ci-oauth-csrf-secret \
-e TELEGRAM_BOT_WEBHOOK_SECRET=ci-telegram-webhook-secret \
-e TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA \
-e TURNSTILE_SITE_KEY=1x00000000000000000000AA \
auth-runner:ci
- run: npx playwright install --with-deps chromium
- name: Wait for the runner to be ready
run: |
for i in $(seq 1 45); do
if curl -fsS http://127.0.0.1:3000/api/health/ready; then exit 0; fi
sleep 2
done
echo "runner image did not become ready" >&2
docker logs auth-runner
exit 1
- run: npm run test:e2e
env:
PLAYWRIGHT_BASE_URL: http://127.0.0.1:3000
- if: failure()
run: docker logs auth-runner
- if: always()
run: docker rm -f auth-runner

sdk:
runs-on: ubuntu-latest
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,14 @@ With `REDIS_URL` set, rate-limit counters live in Redis and are shared across
test files within one run, so a test that exercises a rate-limited path must
use keys unique to itself.

CI (`.github/workflows/security.yml`) runs the unit and integration suites,
the Playwright end-to-end scenarios against Postgres and Redis services, `npm audit`,
`npm run test:e2e` starts the dev server on port 3100 by itself. Set
`PLAYWRIGHT_BASE_URL` to point the suite at an already-running server
instead (CI sets it to the booted production image).

CI (`.github/workflows/security.yml`) runs the unit and integration suites
against Postgres and Redis services, boots the production runner image
against the same services and runs the Playwright end-to-end scenarios
against it, and runs `npm audit`,
the migration smoke test, the production build, and both Docker image builds
on every push. The `sdk` job separately builds and type-checks the Node SDK.

Expand Down
27 changes: 14 additions & 13 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { defineConfig, devices } from "@playwright/test";

// CI points PLAYWRIGHT_BASE_URL at the booted production image and manages
// that process itself; locally the dev server on 3100 is started (or reused).
const baseURL = process.env.PLAYWRIGHT_BASE_URL || "http://127.0.0.1:3100";

export default defineConfig({
testDir: "./tests/e2e",
timeout: 30_000,
use: {
baseURL: "http://127.0.0.1:3100",
baseURL,
trace: "on-first-retry",
},
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
webServer: {
command: "npm run dev -- -H 127.0.0.1 -p 3100",
url: "http://127.0.0.1:3100/login",
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }],
webServer: process.env.PLAYWRIGHT_BASE_URL
? undefined
: {
command: "npm run dev -- -H 127.0.0.1 -p 3100",
url: "http://127.0.0.1:3100/login",
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
});