Commit graph

16 commits

Author SHA1 Message Date
3532e4d486 Add account settings dropdown and verified email change flow.
All checks were successful
CI / Lint, type check, unit tests, coverage (pull_request) Successful in 2m9s
CI / E2E browser tests (pull_request) Successful in 1m55s
Replace the header "Byt lösenord" link with an Inställningar menu for
changing email or password. Email changes are two-step: request with
password, confirmation link to the new address, then password again on
confirm so a wrong inbox cannot take over the account.

- Backend: EmailChangeService, V10 email_change_tokens, confirm API
- Frontend: ChangeEmailPage, ConfirmEmailChangePage, header dropdown
- E2E: account-settings round-trips, Mailpit verification, wrong-password guard
- Flyway: V9 restore for dev DBs, CI migration checks, V10 for email tokens

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 14:33:06 +02:00
13974e26f7 ci: fix coverage summary table — remove Status column and trailing empty cell
All checks were successful
CI / Lint, type check, unit tests, coverage (push) Successful in 1m53s
CI / E2E browser tests (push) Successful in 44s
The 4-column table had a trailing empty column on the right because
the Status column was removed but the right border was still placed
after it. This created a visual glitch in the Forgejo log viewer.

- Convert to a clean 3-column table: Layer | Lines | Branch
- Remove emojis from table cells (they're double-width and break alignment)
- Add a plain-text pass/fail line below the table instead
- Use consistent 7-char padding for all percentage values so % signs align

Result: coverage summary renders cleanly in the CI job log.
2026-05-19 20:40:26 +02:00
5705b17c4b ci: add coverage summary printed to job log
All checks were successful
CI / Lint, type check, unit tests, coverage (push) Successful in 2m6s
CI / E2E browser tests (push) Successful in 44s
Adds a step after backend coverage that parses the JaCoCo XML report
and prints a formatted table showing line and branch coverage with
pass/fail status against thresholds (70% lines, 60% branches).

The frontend coverage is already visible from Vitest's built-in text
reporter which prints during npm run test:coverage.

Both HTML reports remain downloadable as artifacts (backend-coverage
and frontend-coverage ZIPs).

Result: coverage numbers are visible at a glance in the CI job log
without needing to download and unzip artifacts.
2026-05-19 20:30:19 +02:00
4a48dccd91 ci: downgrade upload-artifact to v3 for Forgejo compatibility
All checks were successful
CI / Lint, type check, unit tests, coverage (push) Successful in 2m3s
CI / E2E browser tests (push) Successful in 44s
actions/upload-artifact@v4 requires GHES features not available in
self-hosted Forgejo, causing artifact upload failures with:
GHESNotSupportedError: upload-artifact@v4+ are not supported on GHES.

- Downgrade both coverage upload steps from v4 to v3
- v3 uses a compatible upload mechanism that works on Forgejo

Keeps the artifact upload functionality so coverage HTML reports remain
downloadable from the workflow run page.
2026-05-19 20:16:26 +02:00
3e014b90ae ci: remove redundant test steps and add coverage artifact uploads
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Failing after 1m57s
CI / E2E browser tests (push) Successful in 45s
The lint-and-test job was running tests twice:
- 'Backend unit tests' ran tests without coverage
- 'Backend coverage' ran the same tests again with JaCoCo
- 'Frontend unit tests' ran tests without coverage
- 'Frontend coverage' ran the same tests again with v8 coverage

This wasted ~2x test time for no benefit since coverage steps already
run all tests.

- Remove 'Backend unit tests' and 'Frontend unit tests' steps
- Keep only coverage steps (jacocoTestCoverageVerification and test:coverage)
- Add artifact upload steps for both coverage HTML reports:
  - backend-coverage: backend/build/reports/jacoco/test/html/
  - frontend-coverage: frontend/coverage/
  - 7-day retention to avoid storage bloat

Result: lint-and-test job runs faster (no duplicate test runs) and
produces downloadable HTML coverage reports visible in the Forgejo
Actions UI.
2026-05-19 20:12:35 +02:00
df7cf9f020 ci: remove npm cache from setup-node to speed up lint-and-test job
All checks were successful
CI / Lint, type check, unit tests, coverage (push) Successful in 1m56s
CI / E2E browser tests (push) Successful in 45s
The Forgejo runner uses catthehacker/ubuntu:act-latest which does not have
a real GitHub Actions cache backend. actions/setup-node@v4 with cache: npm
spends ~4m44s trying to restore a non-existent cache during setup, and then
~4m40s in the post-job hook trying to save the cache during 'Complete job'.

- Remove cache: npm and cache-dependency-path from setup-node step
- npm ci without cache is fast enough for this project size (~10-20s)

Expected result: lint-and-test job drops from ~11m to ~2m total.
2026-05-19 20:02:38 +02:00
5abb5bc2e9 fix: use host Docker socket with isolated E2E network
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Successful in 11m41s
CI / E2E browser tests (push) Failing after 45s
The per-job DinD approach failed because Forgejo Runner's service container
DNS resolution does not work when the runner itself uses DinD
(container.docker_host: tcp://dind:2375). The job container could not resolve
the 'dind' service hostname, causing docker compose to fail immediately.

New approach:

- Runner now uses container.docker_host: 'automount' which mounts the host
  Docker socket into job containers. The runner runs as root (user: 0:0)
  to access /var/run/docker.sock.

- E2E job no longer uses a 'dind' service. docker compose runs directly
  against the host Docker daemon inside the job container.

- docker-compose.e2e.yml gets a custom 'e2e' bridge network. All E2E
  containers (postgres, backend, frontend, playwright) attach only to this
  network, isolating them from other host containers (Nextcloud, Jellyfin,
  etc.). They can still reach the internet for vehicle lookup and npm.

Tradeoff: job containers can see other containers via docker ps, but they
are on an isolated network. For a single-user home server, this is the
simplest reliable configuration.
2026-05-19 18:17:01 +02:00
1f1016a775 feat: add isolated E2E browser test pipeline for Forgejo Actions
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Successful in 1m53s
CI / E2E browser tests (push) Failing after 11s
Implement per-job Docker-in-Docker (DinD) for E2E tests, giving each
job a completely isolated Docker daemon and network. This prevents
leakage to the host Docker or other containers.

The previous E2E approach failed because:
1. The Forgejo runner's container.docker_host was not set, causing
   the runner itself to try unix:///var/run/docker.sock and crash-loop.
2. The host DinD daemon had isolated networking — job containers
   running docker compose could not resolve 'dind' hostname or access
   host filesystem bind mounts (e.g. .:/app).

New approach — zero bind mounts, all COPY-based images:

- docker/backend.e2e.Dockerfile: multi-stage build from repo root.
  Copies gradlew + settings.gradle + backend/build.gradle to download
  dependencies in a cacheable layer, then copies backend/src and builds
  the bootJar. Runs the JAR directly on startup.

- docker/frontend.e2e.Dockerfile: multi-stage Node build → nginx.
  Reuses existing docker/nginx.conf for /api proxy to backend service.
  No volume mounts, fully self-contained.

- docker/playwright.e2e.Dockerfile: extends official Playwright image.
  Installs deps from package-lock.json, copies e2e tests + config.

- docker-compose.e2e.yml: zero bind mounts. Services depend on each
  other in order: postgres (healthy) → backend → frontend → playwright.
  Playwright waits for backend and frontend via curl loops before
  running tests.

- .forgejo/workflows/ci.yml: E2E job adds a 'dind' service container
  (docker:28-dind, privileged, no TLS). The job sets DOCKER_HOST to
  tcp://dind:2375 so the docker CLI inside the job talks to the
  per-job DinD daemon. The compose file is docker-compose.e2e.yml.

- Runner fix on tocke: added container.docker_host: 'tcp://dind:2375'
  to runner-config.yaml so the runner's own Docker client connects to
  the host DinD container, stopping the crash loop.

Key properties:
- Network isolation: each E2E job gets its own DinD with its own
  container network. No host container visibility.
- No bind mount leakage: all images use COPY instead of volume mounts.
  The per-job DinD has its own filesystem and can't see host paths.
- Deterministic: builds start from clean state every time. Image cache
  exists only within the per-job DinD lifetime.
- Lint-and-test job is untouched and remains green.
2026-05-19 18:07:12 +02:00
8e3632f05f fix: remove DOCKER_HOST from E2E job, now uses host docker socket
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Successful in 1m54s
CI / E2E browser tests (push) Failing after 1s
2026-05-19 17:05:24 +02:00
10cc12154e fix: split coverage into separate backend and frontend steps
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Failing after 18s
CI / E2E browser tests (push) Failing after 0s
- Backend coverage runs from repo root where gradlew lives
- Frontend coverage runs from frontend/ with working-directory
- No cd tricks that break relative paths
2026-05-19 16:49:50 +02:00
e4cfb873f0 fix: run backend coverage from repo root, not frontend dir
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Failing after 1m41s
CI / E2E browser tests (push) Failing after 2s
- Remove working-directory: frontend from coverage step
- cd back to repo root for ./gradlew command, then cd frontend for npm
- Gradle wrapper lives at repo root, not in frontend/
2026-05-19 16:41:30 +02:00
b41124b141 fix: use git init + fetch checkout to handle non-empty workspace
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Failing after 1m38s
CI / E2E browser tests (push) Failing after 2s
- Replace git clone . with git init + git fetch + git checkout FETCH_HEAD
  Runner pre-creates workspace directory, so git clone . fails
- Use GITHUB_SHA to fetch exact commit, matching original checkout behavior
- Add DOCKER_HOST=tcp://dind:2375 to E2E job step env
2026-05-19 16:32:47 +02:00
076fe1b299 fix: replace actions/checkout with direct git clone to preserve /git/ subpath
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Failing after 1m43s
CI / E2E browser tests (push) Failing after 2s
- Replace actions/checkout@v4 with git clone in both jobs
- Clone URL: https://x-access-token:${FORGEJO_TOKEN}@srvr.nu/git/jocke/bilhej.git
- The checkout action constructed https://srvr.nu/jocke/bilhej/ dropping the /git/ subpath
- FORGEJO_TOKEN is automatically injected by Forgejo at runtime
- Remove ineffective GITHUB_SERVER_URL env var
2026-05-19 16:24:48 +02:00
3cc0cb88d2 fix: use GITHUB_SERVER_URL so checkout resolves Forgejo subpath
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Failing after 43s
CI / E2E browser tests (push) Failing after 34s
- Rename FORGEJO_SERVER_URL to GITHUB_SERVER_URL
- The actions/checkout action reads GITHUB_SERVER_URL to construct the
  clone URL. The runner was cloning https://srvr.nu/jocke/bilhej/ instead
  of https://srvr.nu/git/jocke/bilhej/ because the /git/ subpath was lost
2026-05-19 16:16:41 +02:00
0be3bc473d fix: use github.com source for setup-java and set Forgejo server URL
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Failing after 1m10s
CI / E2E browser tests (push) Failing after 35s
- Change actions/setup-java@v4 to https://github.com/actions/setup-java@v4
  (not mirrored on code.forgejo.org)
- Add FORGEJO_SERVER_URL env var set to https://srvr.nu/git
  (runner checkout was missing /git/ subpath prefix)
2026-05-19 16:07:28 +02:00
8892e0402b ci: add Forgejo lint, test, coverage and E2E workflow
Some checks failed
CI / Lint, type check, unit tests, coverage (push) Failing after 33s
CI / E2E browser tests (push) Failing after 26s
- Add .forgejo/workflows/ci.yml triggering on push/PR to master and develop
- Job lint-and-test: ESLint, vue-tsc type check, Vitest, JUnit, coverage
- Job e2e: Docker compose CI stack with Postgres, backend, frontend, Playwright
- Backend tests use H2 in-memory, no Postgres needed for unit tests
- E2E reuses existing docker-compose.ci.yml orchestration
- Strep env vars use fake test values since Stripe integration is deferred
2026-05-19 15:37:08 +02:00