This directory holds the pipeline. It is also where the CI/CD to-do list lives — if you want a check to exist one day, write it under Backlog rather than leaving it in a chat log.
For how the pipeline works — the trust model, the jobs, which digest to pin in
platform/ — see docs/ci.md. This file is the map and the
backlog, not a second copy of that explanation.
Note: a root
README.mdexists, so GitHub uses that as the repository front page and this file stays an ordinary document.
| Path | Purpose |
|---|---|
workflows/ci.yml |
The whole pipeline: validate on every PR, publish on a push to main |
actions/ci-container/ |
Makes the CI container available to a job — pulled on trusted runs, loaded from an artifact on PRs |
dependabot.yml |
Keeps the pinned action SHAs, base-image digests and dependencies moving |
The workflow knows how to move things around. It never knows how to check
them. Every check runs as a task inside the container built from
.devcontainer/Dockerfile — the same container we
develop in.
So when you pick up something from the backlog below, the shape of the work is almost always:
- Add or change a task in
Taskfile.yaml(or a component Taskfile). Run it locally until it does what you want. - Only then add a step to
ci.ymlthat runs that task inside the CI container.
If you find yourself writing the logic of a check in YAML, that is the signal to stop and put it in a task instead. The payoff is that a red job reproduces locally with the command printed in its own log.
Roughly in the order they earn their keep.
trivy is already in the CI container and unused. Missing before it can gate:
- an agreed severity threshold (the reverser fails only on fixable CRITICAL, which is actionable signal rather than noise from unfixed CVEs);
- a
.trivyignore.yaml, with the gate reading it explicitly and treating a missing file as fatal — a security control must not be able to quietly stop honouring its own suppressions; - DB caching in CI. The vulnerability DB unpacks to ~1.3 GB and goes stale in 24h, which is why it is deliberately not baked into the container image.
Put the two-pass structure (report everything, then gate on a subset) in a
task scan-image, not in workflow steps.
markdownlint-cli2 and vale are in the container and inert. This repository's
existing documents have never been checked against either, so switching them on
today starts red — that is a documentation cleanup, not a CI task, and it should
be its own change. vale additionally needs a style under .vale.ini before it
does anything at all.
It is not published and not to be deployed again; it stays linted and tested only while its replacement is written. When section 7 of the plan is done and the participant-ID-token paths have taken over:
- delete the directory and its Taskfile;
- remove the
unusedwaiver in.golangci.ymlthat exists solely for its three leftover functions; - drop it from
dependabot.yml,task lint-dockerfilesand the root Taskfile.
The waiver in .golangci.yml names the condition for
lifting it: ST1013 (numeric HTTP statuses) — lift after one sweep converting
the call sites in voter/ to http.StatusX. Enabling it before that gates on
the arbitrary subset staticcheck happens to flag.
task frontend:test currently runs npm run build, which does type-check via
vue-tsc — a real check, but not a test suite. When a runner lands (Vitest), put
it in that task; CI calls task test and needs no edit.
Images are identified by commit (sha-<short>), not semver, and there is no
changelog. That is fine while the demo is the only consumer. If platform/ ever
needs to pin a release rather than a commit, the reverser's release-please
setup is the model — and that also brings a pr-title.yml conventional-commit
check as a prerequisite.
- Retry the
curltool downloads in.devcontainer/Dockerfilethe way thego installlayer now retries. A cold CI image build is ~7 minutes and any one of ~20 downloads can flake it;--retry 3 --retry-delay 2 --retry-connrefusedwould cover them cheaply. linux/arm64— add toPLATFORMSin the root Taskfile only when something actually runs on it. The demo cluster is Talos on Proxmox (amd64), and multi-arch doubles every image build.- Runtime smoke test of the published images. Both are built and pushed
without ever being started. Even
docker run --rm <image> --helpwould catch a broken entrypoint before the cluster does. - Coverage reporting. No coverage is collected or tracked for either module.