CI: gate builds + pushes app image to Gitea registry tagged with the commit hash
CI / full-gate (push) Successful in 2m32s
Mirror / github-mirror (push) Successful in 0s

This commit was merged in pull request #4.
This commit is contained in:
2026-07-03 16:39:57 +02:00
parent 6e60df7008
commit 50006dd1a7
3 changed files with 32 additions and 3 deletions
+12
View File
@@ -9,3 +9,15 @@ jobs:
steps:
- uses: actions/checkout@v4.2.2
- run: bash ci.sh
- name: Push app image tagged with the commit hash
env:
IMAGE: gitea.larvit.se/${{ github.repository }}:${{ github.sha }}
REGISTRY_TOKEN: ${{ secrets.DOCKER_REGISTRY_TOKEN }}
REGISTRY_USER: ${{ vars.DOCKER_REGISTRY_USER }}
run: |
printf '%s' "$REGISTRY_TOKEN" | docker login gitea.larvit.se -u "$REGISTRY_USER" --password-stdin
docker build -t "$IMAGE" .
docker push "$IMAGE"
- name: Log out of the registry
if: always()
run: docker logout gitea.larvit.se
+18 -1
View File
@@ -1173,7 +1173,7 @@ Gitea Actions (`.gitea/workflows/`) runs the pipeline; the test job runs
| Workflow | Trigger | Does |
| --- | --- | --- |
| `ci.yml` | push, any branch except `main` | the full gate (`bash ci.sh`) |
| `ci.yml` | push, any branch except `main` | the full gate (`bash ci.sh`), then build + push the app image |
| `mirror.yml` | push to `main`, or manual | force-push `main` + tags to the [GitHub mirror](https://github.com/larvit/plainpages) |
`main` is not re-tested on push — its commits are meant to arrive already green from a
@@ -1185,6 +1185,23 @@ no repo files involved): direct pushes are blocked, changes land via PR only, th
**fast-forward-only** — history stays linear and `main`'s head is the exact commit hash of
the merged branch, which is why the branch's push-triggered status carries over.
**Container images** — after a green gate, `ci.yml` builds the app image and pushes it to the
Gitea container registry as `gitea.larvit.se/larvit/plainpages:<full commit hash>`. Because
merges are fast-forward-only, the image for any `main` commit already exists — it was built
and pushed by that exact commit's branch gate; nothing is rebuilt after merge (build once,
promote by re-tagging). One-time setup: on an account with package write in the `larvit` org,
create a Gitea access token with `read:package` + `write:package`, and store the account name
as the Actions **variable** `DOCKER_REGISTRY_USER` and the token as the Actions **secret**
`DOCKER_REGISTRY_TOKEN` (a `GITEA_` prefix is rejected — reserved, like `GITHUB_`). Because
this step runs
inside the required gate, a missing/expired token (or registry outage) fails every branch's
gate and blocks **all** merges until restored — set the secrets before this lands, and use a
non-expiring token or track its expiry. Retention: hash tags
accumulate one image per gated push, so an org-level package **cleanup rule**
(org Settings → Packages, applied by Gitea's daily cleanup cron) prunes them — type
`container`, remove versions matching `^[0-9a-f]{40}$` older than 30 days, keep the 10 most
recent and anything matching `^v?\d+\.\d+\.\d+$|^latest$` (semver tags are never pruned).
**GitHub mirror** — [github.com/larvit/plainpages](https://github.com/larvit/plainpages) is a
read-only mirror; after every merge, `mirror.yml` force-pushes `main` and all tags there,
overwriting any drift (refs deleted on Gitea are not pruned). One-time setup: a dedicated
+2 -2
View File
@@ -6,9 +6,9 @@
- [x] CI/CD - Test on push to any branch except main. (`.gitea/workflows/ci.yml` runs `bash ci.sh`; the one-time act_runner setup it needs is documented in README → CI/CD.)
- [x] CI/CD - Require PR to main and don't allow merge if tests does not pass. Only allow linear history and history that leaves the last commit hash on main the exact same as on the branch we just merged in. (Gitea branch protection on main + fast-forward-only merge style, set via API; documented in README → CI/CD.)
- [x] CI/CD - Sync up to github after every successful merge to main, URL: git@github.com:larvit/plainpages.git - also note the true home top of the README. Force push to github, it should only ever be a mirror of the gitea.larvit.se repository. (`.gitea/workflows/mirror.yml` force-pushes main + tags over HTTPS with a dedicated account's PAT in the `MIRROR_GITHUB_TOKEN` secret; setup documented in README → CI/CD.)
- [ ] CI/CD - Build docker images as part of the requirements to be able to merge to main. Push them with the git commit hash as docker tag. Push to container registry at Gitea.
- [x] CI/CD - Build docker images as part of the requirements to be able to merge to main. Push them with the git commit hash as docker tag. Push to container registry at Gitea. (`ci.yml` builds + pushes `gitea.larvit.se/larvit/plainpages:<commit hash>` after a green gate — with ff-only merges that is the main commit's image; auth via the `DOCKER_REGISTRY_USER` variable + `DOCKER_REGISTRY_TOKEN` secret, retention via an org cleanup rule; documented in README → CI/CD.)
- [ ] CI/CD - Re-tag docker images from git hash to semver when a semver git tag is pushed.
- [ ] CI/CD - Require human to make docker hub account - sync docker images to docker hub after each deploy build.
- [ ] CI/CD - Sync docker images to docker hub after each re-tag to git tags.
- [ ] CI/CD - Setup renovate bot.
- [ ] Add an e2e test for the admin plugin's OAuth2-clients (Hydra) screen. The full-flow e2e suite runs without Hydra (compose.full.yml), so /admin/clients register/detail/delete is only unit-covered (src/http/app.test.ts); wire Hydra into an e2e stack and drive the screen in the browser.
- [ ] Build and publish docker image as CI/CD.