60 Commits
Author SHA1 Message Date
Donkie bb0bcc1b5f Run CI on bot PRs and merge Weblate PRs weekly
Dependabot and Weblate branches are excluded from push runs, and the
root jobs skipped same-repo pull_request runs, so their PRs got no
checks and stayed blocked. Let those PRs run the pull_request suite.

Weblate PRs are now merged by a Monday schedule instead of as soon as
each sync goes green, to cut down the merge commits on master.
2026-10-11 10:24:34 +02:00
Donkie 022285d64d Add Argos visual snapshots of client_v2 pages to CI
A screenshots Playwright project seeds a fixed dataset on the fresh CI
database and captures the main pages in light/dark at desktop and phone
widths. The Argos reporter uploads them from CI and posts the diff against
master on the PR. Fork PRs upload tokenless.

Also scope the transparency spec's swatch locator to the inspector header,
it picked the first list row once other spools sorted ahead of its own.
2026-10-10 09:35:51 +02:00
Donkie aae2b4df56 ci: skip the duplicate pull_request run for same-repo branches
Now that every branch builds on push, opening a PR from one ran the whole
workflow twice for the same commit.

Concurrency cannot dedupe these: push and pull_request carry different refs, and
forcing them into one group only races them, killing whichever run started
first. That is the wrong outcome roughly half the time, since publish-images
runs on push and not on pull_request, so the branch image would vanish.

Guard the three jobs that have no `needs` instead. A skipped dependency skips its
dependents, so this cascades to all twelve. Forks are unaffected: a fork's push
fires no event in this repo, so its pull_request run is the only one there is.
2026-09-27 08:32:44 +02:00
Donkie e1ad9feb30 ci: build every branch and publish it to GHCR under the branch name
Branch pushes matched no trigger, so an unmerged fix could not be handed to a
bug reporter as an image. Push now covers all branches except weblate (constant
locale-only commits) and dependabot (arrives as PRs anyway).

publish-images was already gated only on "not a pull request", so it picks
branch pushes up for free; it just had no tag to publish them under. Adding
type=ref,event=branch to the GHCR metadata gives one, skipping master since that
is already :edge. Docker Hub deliberately keeps only edge and tagged releases,
so users browsing it do not see half-finished branches.

Concurrency now cancels superseded runs on any ref except master and tags, which
publish images and must not be interrupted mid-manifest.

Note: once a branch has an open PR, push and pull_request both fire and it runs
twice.
2026-09-27 08:32:44 +02:00
Donkie a353983f85 Speed up armv7 image builds on layer-cache misses
Persist uv's cache of source-built wheels (asyncpg, greenlet, psycopg2,
cffi, ...) across CI runs via actions/cache + buildkit-cache-dance, so a
lockfile or base-image change no longer recompiles everything under QEMU
(~11 min -> ~3 min). Move the greenlet patchelf step into the cached
dependency layer so source-only builds skip an apt-get under QEMU, and
drop python3-dev, which only pulled in Debian's unrelated python3.11.
2026-09-25 16:04:21 +02:00
Donkie ff7170f0f7 Build on Node 24, which is not end-of-life
Every workflow pinned node-version '20'. Node 20 reached end-of-life on
2026-04-30, so for three months CI has been building the artifacts that
go into released images on a runtime that no longer gets security fixes.
Vite 8 also floors at ^20.19, which setup-node's '20' happens to satisfy
today only because it resolves to the latest 20.x -- a floor we were
clearing by accident is not one worth keeping.

24 rather than 22: it is Active LTS until 2026-10-20 and supported
through 2028-04-30, so this pin outlives the 22 line by a year. Node 26
does not ship until October.

The legacy client declared engines "20.x", which would have made every
npm ci in that package print EBADENGINE against the new runner. It is
widened to the floor of the Vite 7 it already runs on, so it now
describes what the package actually supports instead of naming a single
line.

Verified locally on Node 24.13.0: lefthook ci green, both clients
install clean and build, client_v2's unit tests and the
tests_frontend_v2 Playwright suite pass. tests_frontend needs the built
image so it is left to CI; its only dependency declares node >=18.

The setup-node pin itself is untouched and still on v4.0.3, whose action
runtime is the other deprecated Node 20 in the logs -- GitHub already
force-runs it on 24. That is an action upgrade, and a separate change.
2026-07-31 09:00:16 +02:00
Donkie 4ab99768ae Abort last workflow run for PRs when new push 2026-07-30 21:48:55 +02:00
Donkie 9bdf4d1a5e Install client_v2 deps in the style job
lefthook's ci hook grew a client_v2 group, but the style job only ran
npm ci in client/, so all three of its jobs died at exit 127 on missing
./node_modules/.bin binaries -- eslint, prettier and svelte-kit. The
hook is invoked from the repo root and the paths are hardcoded (for
Windows' sake), so nothing resolved them from client/'s tree. That has
been failing every run since the group was added, on a branch where
client_v2 is the client that ships, so its lint, format and type checks
were the ones not running.

client_v2/docs is gitignored scratch space that prettier still walked,
which fails the hook locally on files CI never sees; the ignore files
now agree.

Claude-Session: https://claude.ai/code/session_01UB5KocsTBm9GL5x3Uuup5F
2026-07-30 21:29:07 +02:00
Donkie 59672ecb30 Merge master into feature/v2-client
Brings the branch up to 0.25.0 and picks up cosign image signing, the
armv7/arm64 smoke tests, the armv7 greenlet/libstdc++ fix, the
PUID/PGID and Kubernetes SPOOLMAN_PORT entrypoint guards, and the
externaldb unwritable-path fix.

The only conflict was publish-images' needs list, where both sides had
added a job: test-frontend-v2 here, test-multiarch-smoke on master.
Resolved as the union, so nothing publishes until every test job has
passed. The rest of the graph is unchanged, and the new smoke tests
inherit client_v2 coverage for free -- build-arm64 and build-armv7
already download the client_v2 artifact, so booting those images to
/health now also proves the default client is present in them.

Claude-Session: https://claude.ai/code/session_01UB5KocsTBm9GL5x3Uuup5F
2026-07-30 21:02:14 +02:00
Donkie 17f8b9fee1 client_v2: add Playwright frontend integration tests
Mirrors tests_frontend, but drives the Svelte client instead of the legacy
React one: same production image, same PostgreSQL-backed compose stack, same
"only the first navigation uses a URL" discipline.

- smoke.spec.ts clicks through every top-bar tab, asserting each route's title
  and the app shell, with no browser console errors; a second test proves the
  library reached the API rather than falling into its offline state.
- crud.spec.ts walks the first-use happy path. client_v2 folds the legacy
  client's three create forms into one "Add spools" modal, so a manufacturer,
  a filament and a spool are created by a single submit, then verified back in
  the library list and on the locations page.

Two client_v2-specific helpers earn their keep: the top bar renders its nav
twice (desktop + mobile, one hidden by CSS) so nav locators need narrowing to
the visible one, and NumberInput's accessible name picks up its stepper and
help buttons, so numeric fields are found via their form item instead of
getByLabel.

The suite publishes on host port 8001 so it can run alongside the legacy one.
CI gains a test-frontend-v2 job cloned from test-frontend, gating
publish-images alongside it.

Also fixes tests_frontend/run.py: it only built client/dist, but the Dockerfile
copies client_v2/build unconditionally, so the image could not be built from a
clean checkout.
2026-07-29 19:08:12 +02:00
Donkie a0987e063e Add smoke tests in CI for armv7/arm64 targets 2026-07-21 22:16:00 +02:00
Aleksei Sviridkin fc606ec8fc ci: sign the released images with cosign (#963)
Published images carry no signature, so there is no way for a user to verify
that the image they pull was built by this workflow from this repository.

Sign them keyless, using the Github OIDC token, so verification needs no key
material on either side. The manifest is signed by digest rather than by tag:
every tag produced for a release points at the same digest, and the same
digest is valid in both registries the build pushes to, so signing each tag
would only repeat the same signature.

Verify with:

    cosign verify ghcr.io/donkie/spoolman:<version> \
      --certificate-identity-regexp '^https://github\.com/Donkie/Spoolman/\.github/workflows/ci\.yml@refs/' \
      --certificate-oidc-issuer https://token.actions.githubusercontent.com

Assisted-By: Claude <noreply@anthropic.com>

Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-07-21 22:07:57 +02:00
Donkie 638466bc70 Bake client_v2 into the image and serve it by default
Build the new Svelte client (client_v2) in CI, bake it into the Docker
image alongside the legacy React client, and serve it by default. Set
SPOOLMAN_LEGACY_CLIENT=TRUE to fall back to the old client.

SinglePageApplication is generalized to serve either client: the React
client keeps its index.html + base-path rewriting, while the Svelte
client uses a 200.html SPA fallback, serves prerendered per-route pages,
and serves relative-path assets verbatim. The tweaked-HTML store is moved
off self.html, which StaticFiles uses as its HTML-mode flag.

The Playwright frontend suite targets the React DOM, so it's pinned to
the legacy client via SPOOLMAN_LEGACY_CLIENT for now.

Claude-Session: https://claude.ai/code/session_01VQQtwPBPiMCoZCpBbbqS64
2026-07-18 23:05:00 +02:00
Donkie d9fd44eab9 Add Playwright frontend integration tests; fix broken SPA static serving
Add a browser-driven integration suite (tests_frontend/) that runs against
the real production image + PostgreSQL and drives the UI with Playwright:
a smoke test that navigates every page via the sidebar with no console
errors, and a CRUD test that creates a vendor -> filament -> spool entirely
through the UI. Wired up as `poe itest-frontend` and a new `test-frontend`
CI job (reusing the image built for the backend tests, gating releases).

Navigation goes through real UI buttons (language-independent link targets)
and the app language is forced to English so label matchers are stable
regardless of the runner's browser locale.

This immediately caught a real regression: Starlette 1.3.1 (pulled by a
recent dep bump) removed the `method` kwarg from FileResponse, so
SinglePageApplication 500'd on every static asset and the whole UI was dead.
Drop the removed kwarg — Starlette now derives HEAD handling from the scope.

Claude-Session: https://claude.ai/code/session_01BQjJiwEbu6bHbeDjPPDm3V
2026-07-07 09:12:42 +02:00
Donkie 8a29ce063a Update ci.yml 2026-01-18 17:30:55 +01:00
Donkie fa6343c368 Fix artifact job 2026-01-18 17:11:54 +01:00
Donkie 1cd8c7a962 Added ci job to produce artifact package for all builds 2026-01-18 17:05:00 +01:00
Donkie b361aee956 CI fixes 2026-01-18 16:55:31 +01:00
Donkie 7b7d73224d Set github ci permissions 2025-06-08 12:23:37 +02:00
Donkie 11a74e2197 Use env for ci ghcr_image since vars is not accessible in PRs 2025-04-12 19:42:53 +02:00
Donkie ec5173067e Add push to dockerhub 2025-03-19 19:05:17 +01:00
Donkie 590b0df191 Fixed release zip missing dot-files 2024-09-23 19:26:29 +02:00
Donkie 909d8c38bd Test stage now only downloads the relevant images 2024-09-08 22:17:46 +02:00
Donkie 13a038cb3e Updated all action versions 2024-09-08 13:29:27 +02:00
Donkie b70cfb0e79 Bump artifact action versions 2024-09-07 19:54:01 +02:00
Donkie 694e4b9f61 Update compose-action to try fix CI issue 2024-08-05 19:35:17 +02:00
Donkie 4f49481475 Update PDM lockfile
This updates all dependencies, as well as makes it compatible with latest PDM which now complains about the cross_platform strategy choice, we instead use inherit_metadata now.
2024-08-05 19:15:34 +02:00
Donkie b6b6fcf6bd Remove .venv in CI build job 2024-02-01 20:04:00 +01:00
Donkie f7c9c44ea7 Write build info earlier when we still have git 2024-01-25 22:58:25 +01:00
Donkie 721733551f Fix git commit in ci.yml 2024-01-25 22:54:26 +01:00
Donkie b40da6e2ee Updated commit and build date capturing
It's now written to a build.txt file instead of using environment variables internally. Standalone installs now has this properly as well.
2024-01-25 22:03:18 +01:00
Donkie 1479e13d94 Some script permission fixes 2024-01-25 20:49:16 +01:00
Donkie 2786eff3da Fixed release publishing happening outside tag push 2024-01-25 20:21:42 +01:00
Donkie 44d3ed72b0 CI job now builds a requirement.txt into the spoolman.zip 2024-01-25 20:11:12 +01:00
Donkie d424383ebb Fixed CI zip not including dot-files 2023-12-29 20:18:45 +01:00
Donkie dc84c8cd08 Moved to tmp dir instead 2023-12-29 12:42:05 +01:00
Donkie dec34df6bd Fixed some release publish issues 2023-12-29 12:33:51 +01:00
Donkie 96f1c86616 Update ci.yml 2023-12-29 12:13:21 +01:00
Donkie 57ea0f5af9 Combine release workflow into CI 2023-12-29 11:18:25 +01:00
Donkie 86af6434a9 Fixed CI name collision with built docker images 2023-12-28 11:43:16 +01:00
Donkie 75a8128f19 New CI step to produce a full Spoolman build zip 2023-12-28 11:23:34 +01:00
Donkie b66a2c5242 Removed unnecessary zip in ci client build 2023-12-17 23:01:25 +01:00
Donkie 60b67ee758 Dockerfile no longer builds client
This proved to be extremely slow on emulated hardware to build e.g. the linux/arm/v7 image.
Since the built client is architecture agnostic, it's instead now built on the native hardware and inserted into the docker image.
2023-12-17 22:53:17 +01:00
Donkie 1a3efd9ea9 Added git commit and build date env and API 2023-09-17 10:51:28 +02:00
Donkie a1a4ad6b45 Revert "Add git hash to version for master builds"
This reverts commit af1f3b45c5.
2023-09-17 09:43:25 +02:00
Donkie af1f3b45c5 Add git hash to version for master builds 2023-09-16 20:06:14 +02:00
Donkie 89c588aaaf Revert "Remove style check"
This reverts commit 6f47fe0eaa.
2023-09-03 21:01:08 +02:00
Donkie 6f47fe0eaa Remove style check 2023-08-28 21:24:55 +02:00
Donkie 992c3220c7 Pre-commit update 2023-08-28 21:17:27 +02:00
Donkie c3779c4d2c Only release if style passes 2023-08-28 20:47:42 +02:00