Add Gitea build, container tests and registry publication
All checks were successful
Build, test and publish / verify (push) Successful in 1m41s

This commit is contained in:
2026-10-28 17:07:23 +01:00
parent e3e362c2ac
commit 74a5aa1237
26 changed files with 1180 additions and 12 deletions

236
docs/gitea-ci.md Normal file
View File

@@ -0,0 +1,236 @@
# Gitea build pipeline beheren
De workflow staat in `.gitea/workflows/build.yaml`. Elke branchpush bouwt en test
backend en frontend, bouwt twee images en draait Playwright tegen die containers.
Alleen `main` mag daarna images publiceren. Er vindt geen deployment plaats.
Tagpushes en aparte pull-requestevents starten geen extra workflow.
## Machines en voorwaarden
Gitea 1.25.4 en de registry staan op de bestaande Synology,
`http://192.168.2.28:3000`. De runner draait als gebruikersservice op de bestaande
Linux x86_64 mini-pc. Er is geen extra hardware nodig. De mini-pc moet aanstaan en
wakker blijven; Docker en de runner moeten draaien. Anders blijven jobs wachten.
Een host-runner voert repositorycode uit als de ontwikkelgebruiker: gebruik deze
runner alleen voor deze vertrouwde repository.
De runner heeft Git, Bash, JDK 25, Maven 3.9+, Node 22.22.3+/24.15.0+/26+, npm,
Python 3, curl, flock (util-linux), timeout (coreutils) en een werkende Docker-daemon
nodig. De huidige mini-pc heeft de ontwikkeltools en Docker Desktop al geïnstalleerd.
De workflow gebruikt één job tegelijk (`capacity: 1`), één Playwright-worker en
CPU/geheugenlimieten voor de tijdelijke applicatie- en browsercontainers.
### Doelarchitectuur eerst vaststellen
Controleer op de Synology via een bestaande beheerverbinding:
```sh
uname -m
docker info --format '{{.OSType}}/{{.Architecture}}'
```
`x86_64`/`amd64` betekent `linux/amd64`; `aarch64`/`arm64` betekent `linux/arm64`.
Leg de werkelijke uitvoer, datum en het Synology-model vast bij de oplevering en
stel repositoryvariabele `TARGET_PLATFORM` daarop in. De workflow weigert een
ontbrekende waarde en een verschil met de Docker-daemon van de runner; hij doet
dus geen stilzwijgende aanname over de NAS en gebruikt geen ongeteste emulatie.
Een mismatch vereist een geteste oplossing op de bestaande machines voordat S4
afgerond kan worden; er worden geen multi-architecture images gebouwd.
### Docker op de mini-pc
Start de al aanwezige Docker Desktop via de desktop of:
```sh
systemctl --user start docker-desktop
docker --context desktop-linux info
```
Bij Docker Desktop configureer je onder **Settings → Docker Engine** de inhoud
van `ci/runner/docker-daemon.json`, samengevoegd met bestaande instellingen.
Je kunt de instelling ook samenvoegen met behoud van bestaande instellingen en
backup via:
```sh
python3 ci/runner/configure-docker.py "$HOME/.docker/daemon.json"
```
Voor Docker Engine op Linux is dat dezelfde toevoeging aan
`/etc/docker/daemon.json` (met de daarvoor benodigde beheerrechten). Overschrijf geen andere daemoninstellingen. Pas de
wijziging toe/herstart de daemon en controleer met `docker info` dat
`192.168.2.28:3000` onder de insecure registries staat. Configureer ook andere
Docker-clients die images van deze interne HTTP-registry moeten ophalen.
Gebruik de Docker Desktop-context of zet `DOCKER_HOST` expliciet. De installer
neemt de geselecteerde socket over in de gebruikersservice. Als de socket later
wijzigt, pas dan `~/.config/agiledancers-runner/environment` aan en herstart de
runner. Bij Docker Desktop blijft de Desktop-VM eveneens nodig voor builds.
Runner en containers moeten de Synology en internetdownloads kunnen bereiken.
## Gitea-instellingen en credentials
Repository: `wanjakrah/agiledancers`, hoofdbranch: `main`.
Actions staat voor deze repository al aan. Controleer zo nodig op de Synology
`app.ini` onder `[actions]` de instelling `ENABLED = true` en de Actions-feature
onder repositoryinstellingen. Stel `SKIP_WORKFLOW_STRINGS` leeg in als ook commits met teksten als `[skip ci]`
verplicht moeten draaien, zoals de afspraak elke branchpush vereist.
Wijzig serverconfiguratie alleen indien nodig.
Stel bij repository **Settings → Actions** in:
| Soort | Naam | Waarde/doel |
| --- | --- | --- |
| Variabele | `TARGET_PLATFORM` | Vastgestelde Synology-platformwaarde |
| Secret | `REGISTRY_USER` | Gitea-gebruiker die in namespace `wanjakrah` mag publiceren |
| Secret | `REGISTRY_TOKEN` | PAT met `write:package` en `read:repository` voor imagepublicatie en controle van de huidige hoofdbranch |
Het gewone jobtoken van Gitea 1.25 biedt geen packagepublicatie; gebruik een PAT.
Gebruik een repository-runnerregistratietoken, geen instancebrede registratie.
Sla tokenwaarden buiten Git op en plaats ze niet in opdrachten, screenshots of logs.
Voor reproduceerbare configuratie bestaat `ci/configure-gitea.py`. Maak twee
bestanden buiten de repository met mode `600`: één voor een PAT met voldoende
repositorybeheerrechten (repository Actions, secrets, variabelen en runnerregistratie),
en één voor de publicatie-PAT. De beheer-PAT hoeft niet als workflowsecret te worden
bewaard. Vul die bestanden via een lokale editor of verborgen terminalinvoer.
Voer daarna uit met de werkelijke platformwaarde:
```sh
export GITEA_ADMIN_TOKEN_FILE="$HOME/.config/agiledancers-runner/admin-token"
export REGISTRY_TOKEN_FILE="$HOME/.config/agiledancers-runner/registry-token"
export REGISTRY_USER=wanjakrah
export TARGET_PLATFORM=linux/amd64 # alleen als dit op de Synology is vastgesteld
python3 ci/configure-gitea.py
```
Het script stelt de repository-instellingen in via de API en schrijft het
runnerregistratietoken naar
`~/.config/agiledancers-runner/registration-token` met mode `600`. Het toont geen
tokenwaarden. Voor handmatige inrichting kun je dat registratietoken uit de
repository-instellingen halen en in hetzelfde bestand plaatsen.
Controleer de artifactretentie op de server: een workflow vraagt veertien dagen
via `retention-days: 14`. Een kortere serverlimiet of het vroegtijdig verwijderen
van workflowruns mag die periode niet inkorten. Artifactretentie geldt voor
testdiagnostiek; gepubliceerde containerimages worden niet automatisch verwijderd.
## Runner installeren en starten
```sh
export JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64
bash ci/runner/install.sh --prepare-only
# Na Dockerconfiguratie en het opslaan van het registratietoken:
bash ci/runner/install.sh
systemctl --user status agiledancers-runner
journalctl --user -u agiledancers-runner -f
```
De installer controleert tools, installeert checksum-gecontroleerde runner
`v0.2.13`, neemt label `agiledancers-mini-pc:host` over en registreert de runner.
Configuratie en `.runner`-credentials staan in
`~/.local/share/agiledancers-runner`, de service in
`~/.config/systemd/user/agiledancers-runner.service` en de expliciete Java-, PATH-
en Docker-socketinstellingen in `~/.config/agiledancers-runner/environment`.
Een bestaande registratie wordt hergebruikt. Er worden geen secrets in de
repository geschreven. Bewaar het tokenbestand alleen zolang registratie/herstel
dat nodig heeft en behandel `.runner` als credential.
De gebruikersservice start bij een gebruikerssessie. Automatisch doorlopen zonder
inloggen vereist daarnaast een bewuste keuze voor user lingering en een Docker-
daemon die zonder desktopsessie beschikbaar is. S4 belooft geen beschikbaarheid
wanneer de mini-pc uitstaat. Herstarten/stoppen:
```sh
systemctl --user restart agiledancers-runner
systemctl --user stop agiledancers-runner
```
## Images en publicatie
| Component | Image |
| --- | --- |
| Backend | `192.168.2.28:3000/wanjakrah/agiledancers-backend` |
| Frontend | `192.168.2.28:3000/wanjakrah/agiledancers-frontend` |
De volledige commit-SHA is de versie van beide images. Een `main`-tag wijst naar
de nieuwste met succes gepubliceerde actuele hoofdbranchbuild. Gebruik voor een
exact passend paar op beide images dezelfde SHA:
```sh
# Gebruik bij private packages eerst docker login met interactieve invoer.
commit_sha=<volledige-commit-SHA>
docker pull "192.168.2.28:3000/wanjakrah/agiledancers-backend:$commit_sha"
docker pull "192.168.2.28:3000/wanjakrah/agiledancers-frontend:$commit_sha"
```
De frontend luistert op containerpoort 8080, ondersteunt SPA-routes en proxy't
`/api/` naar `BACKEND_UPSTREAM` (standaard `backend:8080`). De backend luistert op
8080. Voorbeelden voor eventueel handmatig starten staan los van de pipeline;
de pipeline start geen blijvende applicatie op de NAS.
`ci/verify.sh` maakt een succesmarker pas na alle builds en tests.
`ci/publish.sh` vereist die marker en hoofdbranchref. Onder een gedeeld `flock`
buiten de checkout worden bestaande commitimages hergebruikt en ontbrekende
images geüpload. Iedere image wordt teruggehaald, op revisielabel gecontroleerd en
met digest vastgelegd in de diagnostiek. Authenticatie- of netwerkfouten tellen
niet als een ontbrekende tag.
Pas na beide images worden `main`-tags bijgewerkt, met een actuele hoofdbranch-
controle voor iedere wijziging. De gedeelde lock voorkomt dat een oudere pipeline
een door een nieuwere pipeline bijgewerkte tag terugzet. `capacity: 1` ondersteunt
dat op de enige runner. Vertrouw niet op workflow-`concurrency`: Gitea 1.25 negeert
die instelling. De twee bewegende tags zijn geen atomisch paar.
## Diagnostiek en herstellen
Iedere workflowpoging bewaart beschikbare diagnostiek als
`diagnostics-<run-id>-<attempt>` gedurende veertien dagen: Maven-rapporten, JUnit-
rapporten van frontend/Playwright, het Playwright HTML-rapport, traces/screenshots
en containerlogs. Open de artifactdownload op de Gitea Actions-runpagina.
Build- en publicatielogs staan er eveneens in. Geen environmentdump of Docker
inspect met mogelijke credentials wordt opgenomen.
Bij mislukking blijven de oorspronkelijke exitstatus en rapporten behouden.
Een trap én een `always()`-stap verzamelen diagnostiek en verwijderen de tijdelijke
containers en het netwerk met hun unieke runnaam. Een harde machine-uitval kan
opruimen onderbreken: controleer daarna uitsluitend achtergebleven resources met
label `agiledancers.ci.run`; gebruik geen algemene Docker-prune op de ontwikkel-PC.
Herstart een mislukte run vanuit Gitea. Als slechts één commitimage gepubliceerd
was, bewaart de herhaling die en vult de ontbrekende image aan. Een fout bij
publiceren, terughalen of bijwerken van `main` laat de pipeline falen. Bestaande
commitimages worden niet overschreven. Bij een inmiddels nieuwere hoofdbranch
blijven de committags bruikbaar en worden de oude `main`-updates overgeslagen.
Lokale controle van publicatie-/foutgedrag zonder registrywijzigingen:
```sh
python3 -m unittest discover -s ci/tests -v
```
Volledige lokale verificatie met Docker en de vastgestelde platformwaarde:
```sh
export JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64
export TARGET_PLATFORM=linux/amd64 # eerst de Synology controleren
bash ci/verify.sh
```
## Operationele oplevering
Leg links/run-ID's en beide image-digests vast in `docs/s4-validation.md` voor:
1. Een geslaagde feature-branchpush, inclusief twee builds en container-E2E,
zonder imagepublicatie.
2. Een expres mislukte build/test op een tijdelijke branch die publicatie blokkeert,
met downloadbare foutdiagnostiek. Herstel die testwijziging daarna.
3. Een geslaagde hoofdbranchrun met beide teruggehaalde commitimages.
4. Een herhaling/partiële-publicatieherstel en bewijs dat bestaande committags
behouden blijven en oudere builds `main` niet terugzetten.
Zonder werkende runner, vastgestelde NAS-architectuur, registrytoegang en echte
pipelinebewijzen is S4 niet volledig opgeleverd.
Bronnen: [runner](https://docs.gitea.com/1.25/usage/actions/act-runner/),
[Gitea-verschillen](https://docs.gitea.com/1.25/usage/actions/comparison/),
[containerregistry](https://docs.gitea.com/1.25/usage/packages/container/).

75
docs/s4-validation.md Normal file
View File

@@ -0,0 +1,75 @@
# S4 verification evidence
Date: 2026-10-28. Status: repository implementation and local container verification
passed; operational Gitea acceptance remains pending. S4 is **not complete**.
## Verified locally
- Gitea reports version 1.25.4; repository `wanjakrah/agiledancers` has Actions
enabled and uses `main` as its default branch.
- Docker Desktop was started on the existing Linux x86_64 mini-PC. Its Docker
daemon reports `linux/x86_64` (`linux/amd64`). This is not evidence of the
Synology's architecture.
- `mvn clean verify` passed, including all 20 backend tests and architecture tests.
- `npm ci`, all 14 frontend unit tests with JUnit output, and the production build
passed in the full verification script.
- Both runtime images built successfully with the `prebuilt` targets. The images
package the same outputs that passed verification.
- Both existing Playwright tests passed (2/2) using the built frontend and backend
containers, the frontend `/api/` proxy and Chromium in the version-matched
Playwright container. No Angular development server was used.
- The full `ci/verify.sh` execution exited successfully; its trap removed all three
temporary test containers and the run network.
- Eleven isolated CI tests pass: failed verification removes its success marker,
feature branches do not publish, unverified commits cannot publish, reruns
preserve commit tags, partial publication is recoverable, authentication and
pull failures block publication, older commits do not move `main`, platform
mismatches fail, and daemon configuration preserves existing settings.
- Shell syntax, Python compilation, workflow YAML parsing and the changed files'
whitespace checks passed.
- Runner v0.2.13 was downloaded from the official source, SHA-256 checked, and
installed with its user-service configuration using `--prepare-only`.
The runner was subsequently registered and its user service started using the
supplied repository administration credentials.
- The internal registry was merged into Docker Desktop's daemon configuration,
preserving existing settings and a backup. Docker Desktop was restarted and
the running daemon confirmed that `192.168.2.28:3000` is an active HTTP registry.
Local outputs are in `ci/artifacts/` (ignored by Git): verify log, backend test
reports, frontend unit JUnit report, Playwright JUnit/HTML report and container
logs. These are local files, not yet artifacts uploaded by a real Gitea run.
The unit JUnit report uses a separate directory so Playwright output cleanup
cannot delete it.
The local test used working-tree changes on base commit
`e3e362c2ac30d6b365f752f3da6c8b0250c019db`, with run ID `s4local`. These local
images are test outputs, not published release images for that commit.
Local image IDs (not registry digests):
- Backend: `sha256:bd77a46e3dbdcaea9662d21c608098999fe17dfdf241cd28a24a935f47401f61`.
- Frontend: `sha256:ce8e6ab21fb8f9cbee280ac2c4d7b4ca24a30e899a457382f1e45c6baf99dfb6`.
## Remaining operational acceptance
- [x] Synology architecture confirmed by the maintainer: `x86_64`,
`linux/amd64`; repository variable `TARGET_PLATFORM=linux/amd64` configured.
- [x] Activate and verify the Docker Desktop HTTP-registry setting.
- [x] Repository `REGISTRY_USER`/`REGISTRY_TOKEN` secrets configured using the
supplied token files. Registry access is verified by actual publication below.
- [ ] Obtain a repository runner registration token and register/start the
installed mini-PC runner; verify it is online in Gitea.
- [ ] Confirm server settings permit every branchpush (including messages with
skip strings) and retain uploaded diagnostic artifacts for fourteen days.
- [ ] Real feature-branch run: record URL/run ID, successful container-E2E and
absence of publication.
- [ ] Real intentionally failing test/build run: record URL/run ID, blocked
publication and downloadable failure artifacts.
- [ ] Real main run: record URL/run ID, both full-SHA images, successful pullback,
registry digests and the two `main` aliases.
- [ ] Real rerun/partial-publication recovery and stale-main evidence: record
run IDs and unchanged existing commit digests.
The isolated publication tests provide automated control-flow coverage; they do
not substitute for real authenticated registry/Gitea acceptance runs. No application
images have been published and no application has been deployed by this work.