Skip to content

infra: build, test and publish the dashboard image - #30

Merged
AbdikhaniAbdirashid merged 1 commit into
mainfrom
infra/dashboard-in-pipeline
Nov 3, 2026
Merged

AbdikhaniAbdirashid merged 1 commit into
mainfrom
infra/dashboard-in-pipeline

Conversation

@AbdikhaniAbdirashid

Copy link
Copy Markdown
Collaborator

Two jobs, so the dashboard gets the same lane in the pipeline the API already has:

dashboard-test ──► dashboard-image ──┐
api-test ──────────► api-image ──────┤──► deploy
deploy-script-test ──────────────────┘

dashboard-test runs the 35 Playwright tests that until now only ever ran on my laptop.
dashboard-image builds relay-dashboard, smoke-tests it, and pushes it on main only.
deploy waits for both image jobs: every image a commit's manifests ask for has to be on
GHCR before the server is told to pull them.

Why the smoke test checks two things, not one

A status check on /index.html looks sufficient and is not. nginx.conf hands every
unknown path to index.html (it has to, or /deliveries would 404 on reload), so that
request answers 200 almost no matter what is in the image.

I built a deliberately broken image — the real one with assets/ deleted — to see which
check catches it:

/index.html                 → 200   passes
/assets/index-BimGaWWm.js   → 404   fails

location /assets/ has try_files $uri =404 and no fallback, so the bundle that
index.html names is the request that proves the build is really inside the image. The
step reads that path out of index.html rather than hardcoding it, because the filename
is content-hashed and changes on every build.

Run against the real image the step exits 0; against the broken one it exits 1 with
::error::/assets/index-BimGaWWm.js answered 404: the build is not in the image.

Details worth a second look

  • cache-from: type=gha,scope=dashboard. The scope defaults to buildkit for
    everyone, and Docker's docs are explicit: build two images without it and each
    overwrites the other's cache. The API keeps the default, so the two no longer collide.
    Naming the API's scope api would be tidier but means touching your job, so I left it.
  • npm ci, Node from dashboard/.nvmrc. The dashboard is npm and Node 24, not Bun.
    npm install would be free to resolve versions package-lock.json never pinned.
  • npx playwright install --with-deps chromium. The runner has no browser. Without
    this line the job fails on its first run with "browser not found".
  • curl -fs, not -fsS, inside the wait loop. A refused connection while nginx
    starts is expected, and printing it would make a green run look broken.
  • Comparing %{http_code} by hand. curl -s exits 0 on a 404, so set -e does not
    catch it.

One request, and one ordering note

Please add dashboard-test as a required check on main. A green job stops nobody from
merging; only branch protection does, and only you can change it.

The comment in dashboard-test names decision 0005, which is still open as #23. Merging
that first keeps the reference from dangling.

How it was checked

  • npm ci, npm run lint, npm run build, npm run test:e2e locally: 35 passed in 19.5 s.
  • The image built and served: /index.html 200, /deliveries 200 (fallback), uid 101.
  • The smoke step extracted straight out of this YAML and run against both a good and a
    broken image, with the results above.
  • pipeline.yml parses, and deploy really lists all three jobs in needs.

Not in this PR

  • k8s/app/dashboard.yaml — infra: add the dashboard manifests for cdn.myrelay.tech #24, which goes out of draft once this is merged and the first
    relay-dashboard image is on GHCR.
  • Uploading the Playwright HTML report and traces as artifacts on failure. The github
    reporter annotates failing tests on the PR, which is enough until a red test is hard to read.

@devinder-dev devinder-dev left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. I checked it against the CI run and the files, not only the description:

  • Run on 7813a72: dashboard-test ran all 35 Playwright tests (35 passed, 24.9 s), and dashboard-image printed the image serves /index.html and /assets/index-BimGaWWm.js.
  • The new setup-node pin 949feb2 is the v7.1.0 tag. The other pins are the same as in the API jobs.
  • Asking for the bundle is the right check: location / falls back to index.html, location /assets/ has no fallback.
  • scope=dashboard keeps the two build caches apart, and deploy now waits for both images.

Small things, none of them blocking (fine as a follow-up):

  1. GitHub runs bash -eo pipefail. If index.html names no bundle, grep exits 1 inside asset=$(…) and the step stops right there, so ::error::index.html names no built bundle never prints. The job still fails; only the message is lost. Ending the pipeline with || true lets your own check run.
  2. The comment at the top of pipeline.yml still says every PR tests "the API"; it could mention the dashboard now.
  3. On a smoke failure, docker logs smoke-dash would show why nginx didn't start.

After the merge, relay-dashboard needs to be made public (decision 0004) and pulled once anonymously before #24 uses it.

@AbdikhaniAbdirashid
AbdikhaniAbdirashid merged commit c145056 into main Nov 3, 2026
6 checks passed
@AbdikhaniAbdirashid
AbdikhaniAbdirashid deleted the infra/dashboard-in-pipeline branch November 3, 2026 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants