diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e49df83 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,76 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + name: build + vitest + playwright smoke + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 11 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + cache-dependency-path: | + web/pnpm-lock.yaml + e2e/pnpm-lock.yaml + + # Cache the ~50MB CCP SDE zip across runs. scripts/build-sde.ts + # already self-invalidates after 7 days, so the same key is safe to + # keep — a stale entry will just trigger one re-download. + - name: Cache SDE zip + uses: actions/cache@v4 + with: + path: web/scripts/cache + key: freightdesk-sde-zip-v1 + + - name: Install web deps + working-directory: web + run: pnpm install --frozen-lockfile + + - name: Install e2e deps + working-directory: e2e + run: pnpm install --frozen-lockfile + + # `pnpm build` chains: build:sde → build:services → tsc -b → vite build. + # This is also our typecheck gate. + - name: Build web (SDE + services + tsc + vite) + working-directory: web + run: pnpm build + + - name: Run vitest + working-directory: web + run: pnpm test + + - name: Install Playwright Chromium + working-directory: e2e + run: pnpm exec playwright install --with-deps chromium + + - name: Run Playwright smoke + working-directory: e2e + run: pnpm exec playwright test + + - name: Upload Playwright report on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: playwright-report + path: | + e2e/playwright-report + e2e/test-results + retention-days: 7 diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts index 3803b84..9daf9f7 100644 --- a/e2e/playwright.config.ts +++ b/e2e/playwright.config.ts @@ -1,16 +1,20 @@ +import { existsSync } from "node:fs"; import { defineConfig, devices } from "@playwright/test"; +// On synicloud's Ubuntu host we use the snap-packaged Chromium; on macOS dev +// boxes and GitHub Actions runners we let Playwright's bundled Chromium win. +const SNAP_CHROMIUM = "/snap/bin/chromium"; +const useSnapChromium = process.platform === "linux" && existsSync(SNAP_CHROMIUM); + export default defineConfig({ testDir: ".", fullyParallel: false, retries: 0, use: { baseURL: process.env.E2E_BASE_URL ?? "http://localhost:4173", - launchOptions: { - ...(process.platform === "linux" - ? { executablePath: "/snap/bin/chromium", args: ["--no-sandbox", "--disable-setuid-sandbox"] } - : {}), - }, + launchOptions: useSnapChromium + ? { executablePath: SNAP_CHROMIUM, args: ["--no-sandbox", "--disable-setuid-sandbox"] } + : {}, }, projects: [{ name: "chromium", use: devices["Desktop Chrome"] }], webServer: process.env.E2E_BASE_URL