When visual tests fail on a PR:
- Writes diff images (base64 data URIs) to the job summary for inline viewing
- Posts a PR comment listing failing tests with a link to the job summary
- Uploads .vitest-attachments/ as an artifact (include-hidden-files: true)
The job now has pull-requests: write permission for posting the comment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When visual tests fail on a PR, upload each diff PNG to GitHub's CDN
via the issue assets endpoint and post a comment with the images
embedded inline. Also fixes the artifact upload path to point at
.vitest-attachments/ where the actual/diff files live.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Runs Vitest browser visual regression tests (drawElevationChart) on every
PR and push to main. Uses the same Playwright/Chromium cache as the e2e job.
On first run (no committed snapshots yet) the tests create the snapshots and
pass. On subsequent runs they compare against committed snapshots and fail on
visual regression. Failed runs upload a visual-snapshots-diff artifact so the
diff is visible in the Actions UI.
To update snapshots after an intentional visual change:
Actions → "Update visual snapshots" → Run workflow (or add the
`update-snapshots` label to the PR).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces two E2E=true-gated test endpoints:
- POST /api/e2e/seed — creates a test user + bare route, returns routeId + JWT
- GET /api/e2e/route/:id — returns { hasGeom } for post-callback assertions
Three new integration tests:
- valid GPX via callback stores geometry (hasGeom = true)
- invalid GPX (< 2 track points) returns 400, geometry not stored
- missing token returns 401
CI: E2E=true added to the "Run E2E tests" step so the seed endpoints
are enabled when react-router-serve runs during the Playwright job.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds @fission-ai/openspec ^1.3.1 as a root devDependency so local and CI
run the same lockfile-pinned version, and dependabot can bump it. CI now
runs `pnpm openspec validate --all --strict` instead of npx.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The npm package `openspec` is an unrelated 0.0.0 placeholder; the real
CLI ships as `@fission-ai/openspec`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a fast standalone job that runs `openspec validate --all --strict`
via npx, gating PRs on spec/change well-formedness.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a script that verifies every packages/*/package.json is listed in
all app Dockerfiles. Catches the recurring issue where adding a new
workspace package breaks production because the Dockerfile deps stage
doesn't know about it.
Also fixes two pre-existing missing packages in the planner Dockerfile
(api, map-core) caught by the new check.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gitleaks requires a license key for org repos. Skip the step (not the
job) for dependabot[bot] so the Security Scan job still passes as a
required status check. pnpm audit still runs for all PRs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The upstream gitleaks/gitleaks-action@v2 errors on merge_group events.
Use our fork which includes https://github.com/gitleaks/gitleaks-action/pull/186.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The automerge GitHub Action (pascalgn/automerge-action) is removed in
favor of GitHub's built-in merge queue, which is now enabled on the
main branch ruleset.
- Delete automerge.yml workflow
- Add merge_group trigger to CI so it runs on queue candidates
- Remove workflow_run trigger for Automerge from CD
- Update CLAUDE.md to document gh pr merge --merge-queue
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gitleaks needs explicit contents:read and pull-requests:read permissions
to scan dependabot PR commits. Without them, the GitHub API returns 403.
Ref: https://github.com/gitleaks/gitleaks/issues/1343#issuecomment-2690243151
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Client: VITE_SENTRY_ENVIRONMENT=ci baked in during CI build, disables
Sentry and sets 0 sample rates. Server: checks process.env.CI to
disable and tag as "ci" environment.
Production remains enabled with "production" environment tag.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In CI, Playwright now starts apps with production commands (react-router-
serve, node --experimental-strip-types) instead of dev servers. This
catches runtime issues like missing exports and import resolution errors
before deploy. Locally, dev servers are still used for fast iteration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Playwright JSON has file → describe → specs nesting.
Use stats.expected/unexpected for counts, iterate nested suites.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Generates a markdown summary table in GitHub Actions showing
passed/failed tests with timing per test. Uses the JSON reporter
to output results, then a Node script to format as markdown
and append to $GITHUB_STEP_SUMMARY.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pg_isready reports true before PostGIS extension is initialized.
Added a second wait loop that queries PostGIS_Version() to ensure
the extension is fully loaded before running drizzle-kit push.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace service container with manual docker run + cached image tar.
Service containers pull the image before steps run (uncacheable).
Manual approach: cache the image as a tar, load on cache hit.
PostGIS image is ~400MB — first run pulls and saves, subsequent
runs load from cache in ~2s instead of ~19s.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Playwright browser download (25s) is now cached by pnpm-lock hash.
On cache hit, only install system deps (fast). On miss, full install.
Current E2E timings (first run):
- Postgres container: 19s
- BRouter JAR: cached
- Berlin segment: 6s (will be cached next run)
- Playwright install: 25s → cached after first run
- BRouter startup: 9s
- Tests: 27s
Expected after caching: ~60s total (down from ~107s).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI now runs the full stack for E2E tests:
- PostgreSQL as a service container + schema push via drizzle
- BRouter JAR + Berlin segment (E10_N50) with caching
- Both cached across runs (BRouter JAR + segment)
Removed all skip/workaround logic from tests — all 20 E2E tests
now run in CI with real services.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Integration test DB check now hits Planner API (not Journal)
so it correctly skips when no PostgreSQL in CI
- Playwright uploads HTML report artifact on all runs (not just failures)
- Install Chromium with --with-deps for CI compatibility
- Report retained for 30 days
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Actions runtime and project node-version both set to 24.
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 opts in early.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI pipeline with parallel jobs for fast feedback:
- typecheck, lint, unit tests, build run in parallel
- e2e tests run after build
- Playwright artifacts uploaded on failure
ESLint wired into both apps with sensible defaults:
- underscore-prefixed unused vars allowed
- root package.json marked as type: module
Architecture updated: Caddy as reverse proxy with auto HTTPS.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>