Implement manual versioned Synology deployments for S6
All checks were successful
Build, test and publish / verify (push) Successful in 6m34s
All checks were successful
Build, test and publish / verify (push) Successful in 6m34s
This commit is contained in:
@@ -2,7 +2,9 @@
|
||||
|
||||
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.
|
||||
Alleen `main` mag daarna images publiceren. Deze buildworkflow voert geen deployment uit.
|
||||
S6 voegt aparte handmatige workflows toe voor productie en rollback; zie
|
||||
[productiedeployment](production-deployment.md).
|
||||
Tagpushes en aparte pull-requestevents starten geen extra workflow. Een auteur
|
||||
kan een branchbuild bewust overslaan met een door Gitea ondersteunde markering,
|
||||
zoals `[skip ci]`; dit is expliciet toegestaan.
|
||||
|
||||
281
docs/production-deployment.md
Normal file
281
docs/production-deployment.md
Normal file
@@ -0,0 +1,281 @@
|
||||
# Productie uitrollen op de Synology (S6)
|
||||
|
||||
De buildworkflow bouwt, test en publiceert automatisch. Productie verandert
|
||||
alleen via **Actions → Deploy production → Run workflow** of **Rollback
|
||||
production**. Start beide vanaf `main`; de workflows verschijnen na de merge.
|
||||
|
||||
**Tot S16 is geïmplementeerd kan iedere deployment, retry, rollback of automatisch
|
||||
herstel alle applicatiegegevens wissen.** Informeer de launching partner vooraf.
|
||||
Een onderbroken berekening moet opnieuw worden gestart. Een herstelde
|
||||
applicatieversie herstelt geen verloren gegevens.
|
||||
|
||||
## Eenmalige DSM-inrichting
|
||||
|
||||
Gebruik je bestaande beheeraccount voor deze stappen:
|
||||
|
||||
1. Maak onder **Configuratiescherm → Gebruiker en groep → Gebruiker → Maken**
|
||||
het account `agiledancers-deploy` met een uniek sterk wachtwoord. Voeg het toe
|
||||
aan **administrators**: DSM vereist deze groep voor SSH. Het is daardoor een
|
||||
beheerder, geen beperkt bestandsaccount.
|
||||
2. Bij **Gedeelde mapmachtigingen**: `docker` op **Lezen/Schrijven**, `homes`
|
||||
ongewijzigd, overige mappen op **Geen toegang**. `git` is niet nodig: deployment
|
||||
gebruikt de Gitea-API en registry. Blokkeer `homes` niet, omdat dit ook de eigen
|
||||
thuismap kan blokkeren.
|
||||
3. De toepassingen onder **Toegangsmachtigingen toewijzen** zijn niet nodig en
|
||||
mogen op **Weigeren**. Gebruik je eigen beheeraccount voor DSM. Deployment
|
||||
gebruikt SSH-shellopdrachten, geen SFTP, rsync of bestandsdeling.
|
||||
4. Schakel onder **Gebruiker en groep → Geavanceerd** de
|
||||
**gebruikersbasismapservice** in als deze uitstaat.
|
||||
5. Schakel **Terminal en SNMP → Terminal → SSH-service inschakelen** in. De
|
||||
maintainer heeft SSH-poort **22** bevestigd. Beperk toegang tot mini-pc/LAN/VPN;
|
||||
configureer geen internet-portforwarding.
|
||||
6. Controleer dat Container Manager/Docker draait, dat Docker Compose **v2**,
|
||||
`curl`, `timeout` met `-k` en `sh` beschikbaar zijn. Op de NAS is geen Java,
|
||||
Python of Git nodig. Controleer het Docker-pad, doorgaans `/usr/local/bin/docker`.
|
||||
|
||||
Map- en toepassingsrechten vormen geen beveiligde isolatie voor een account met
|
||||
beheerder-/Dockerrechten. De runner voert ook vertrouwde repositorycode uit.
|
||||
Geef alleen vertrouwde beheerders schrijftoegang tot workflows en credentials.
|
||||
|
||||
Bronnen: [SSH op DSM](https://kb.synology.com/en-au/DSM/help/DSM/AdminCenter/system_terminal),
|
||||
[sleutelaanmelding en basismappen](https://kb.synology.com/en-us/DSM/tutorial/How_to_log_in_to_DSM_with_key_pairs_as_admin_or_root_permission_via_SSH_on_computers),
|
||||
[maprechten](https://kb.synology.com/nl-nl/DSM/help/DSM/AdminCenter/file_share_privilege?version=7).
|
||||
|
||||
## SSH-sleutel en hostkey
|
||||
|
||||
Maak op de mini-pc een aparte sleutel buiten de repository. De lege passphrase
|
||||
maakt niet-interactieve uitvoering mogelijk; behandel de private sleutel als secret.
|
||||
|
||||
```sh
|
||||
ssh-keygen -t ed25519 -f "$HOME/.config/agiledancers-runner/s6-deploy-key" -N '' -C agiledancers-production
|
||||
ssh-copy-id -i "$HOME/.config/agiledancers-runner/s6-deploy-key.pub" -p 22 agiledancers-deploy@192.168.2.28
|
||||
```
|
||||
|
||||
Genereer niet opnieuw als de sleutel al bestaat. De implementatiesessie heeft
|
||||
deze dedicated sleutel op de mini-pc aangemaakt. De gebruiker installeert de
|
||||
publieke sleutel via een eigen interactieve terminal; deel geen wachtwoorden.
|
||||
|
||||
Controleer de serverfingerprint via een reeds vertrouwde beheerverbinding, tegen
|
||||
`/etc/ssh/ssh_host_ed25519_key.pub`. Een keyscan alleen bewijst de serveridentiteit
|
||||
niet. Bewaar de geverifieerde known_hosts-regel; bij een andere poort gebruikt
|
||||
die `[host]:poort`. De helper vereist `StrictHostKeyChecking=yes`, gebruikt alleen
|
||||
de dedicated sleutel en negeert SSH-agent en lokale SSH-configuratie.
|
||||
|
||||
Op de NAS: eigen `~/.ssh` mode `700`, `authorized_keys` mode `600`, juiste eigenaar,
|
||||
thuismap niet schrijfbaar voor andere gebruikers. De public-keyregel kan worden
|
||||
beperkt met de werkelijke vaste mini-pc-IP en zonder forwarding/TTY:
|
||||
|
||||
```text
|
||||
from="<mini-pc-LAN-IP>",no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-pty ssh-ed25519 <public-key> agiledancers-production
|
||||
```
|
||||
|
||||
Als de sleutel na `ssh-copy-id` nog wordt geweigerd door ruime DSM-basismaprechten,
|
||||
voer dan eenmaal met wachtwoordauthenticatie uit als dit account:
|
||||
|
||||
```sh
|
||||
chmod go-w "$HOME"
|
||||
chmod 700 "$HOME/.ssh"
|
||||
chmod 600 "$HOME/.ssh/authorized_keys"
|
||||
```
|
||||
|
||||
## Productiemap en Dockerrechten
|
||||
|
||||
Controleer het volume: `/volume1/docker/agiledancers-production` is een voorbeeld,
|
||||
geen vastgestelde locatie. Maak de map als deploymentaccount, mode `700`, met
|
||||
dat account als eigenaar. Houd deze stack gescheiden van Gitea en andere projecten.
|
||||
|
||||
Kopieer `deploy/production.env.example` naar `<productiemap>/production.env`, mode
|
||||
`600`. Stel de private NAS-IP, vrije frontendpoort (voorbeeld `8088`), absolute
|
||||
Docker-locatie en `DOCKER_CONFIG` in. Gebruik een eigen `docker-auth`-submap.
|
||||
Alleen de frontend bindt aan de private IPv4; de backend krijgt geen hostpoort.
|
||||
De Docker-projectnaam is vast `agiledancers-production`.
|
||||
|
||||
Als Docker sudo vereist, laat een beheerder met `visudo` een afzonderlijke
|
||||
sudoers-regel installeren en valideren, met het gecontroleerde Docker-pad:
|
||||
|
||||
```text
|
||||
agiledancers-deploy ALL=(root) NOPASSWD: /usr/local/bin/docker
|
||||
```
|
||||
|
||||
Dit staat alleen dat executable toe, maar Dockerbeheer geeft in de praktijk
|
||||
rootmogelijkheden. Gebruik geen `NOPASSWD: ALL`, wereldschrijfbare Docker-socket
|
||||
of wachtwoord in de workflow. De helper gebruikt `sudo -n`. Als Docker al direct
|
||||
toegankelijk is voor het account, stel `DOCKER_SUDO=0` in.
|
||||
|
||||
Provision apart een **pull-only** Gitea-packagecredential. Log als deploymentaccount
|
||||
op de NAS in, via de interactieve wachtwoordprompt:
|
||||
|
||||
```sh
|
||||
mkdir -p /volume1/docker/agiledancers-production/docker-auth
|
||||
chmod 700 /volume1/docker/agiledancers-production/docker-auth
|
||||
sudo -n /usr/local/bin/docker --config /volume1/docker/agiledancers-production/docker-auth login 127.0.0.1:3000 --username <pull-account>
|
||||
sudo -n /usr/local/bin/docker compose version
|
||||
sudo -n /usr/local/bin/docker info --format '{{.OSType}}/{{.Architecture}}'
|
||||
```
|
||||
|
||||
Als DSM geen `visudo` bevat, is `deploy/enable-docker.sh` het eenmalige alternatief.
|
||||
Kopieer het naar de eigen NAS-thuismap en voer het daar met sudo uit. Het maakt
|
||||
uitsluitend de bovengenoemde regel, controleert die door als deploymentaccount
|
||||
Docker te starten en verwijdert een nieuwe regel als die controle faalt. Een
|
||||
afwijkende bestaande regel wordt niet overschreven. De implementatiesessie heeft
|
||||
deze stap op de NAS uitgevoerd; Docker rapporteert `linux/x86_64`.
|
||||
|
||||
Pas paden aan voor de echte configuratie. De bevestigde NAS-Dockerdaemon staat
|
||||
HTTP-registryverkeer alleen op loopback toe. Gebruik daarom vanaf die NAS
|
||||
`127.0.0.1:3000`: dezelfde Gitea-registry en gepubliceerde SHA-images, zonder een
|
||||
daemonherstart die Gitea en Kimai zou onderbreken. De mini-pc blijft naar
|
||||
`192.168.2.28:3000` publiceren. Deploymentrecords bevatten de op de NAS bruikbare
|
||||
loopback-digestreferenties. Authenticatie-/netwerkfouten zijn deploymentfouten.
|
||||
|
||||
## Gitea-configuratie
|
||||
|
||||
Stel onder repository **Settings → Actions** in:
|
||||
|
||||
| Soort | Naam | Inhoud |
|
||||
| --- | --- | --- |
|
||||
| Variabele | `DEPLOY_HOST` | Private NAS-IP/hostnaam, passend bij known_hosts |
|
||||
| Variabele | `DEPLOY_USER` | `agiledancers-deploy` |
|
||||
| Variabele | `DEPLOY_SSH_PORT` | `22` |
|
||||
| Variabele | `DEPLOY_DIRECTORY` | Absolute productiemap |
|
||||
| Variabele | `DEPLOY_REGISTRY` | `127.0.0.1:3000`, de NAS-lokale alias van dezelfde registry |
|
||||
| Secret | `DEPLOY_SSH_KEY` | Volledige private sleutel, inclusief begin/eindregels |
|
||||
| Secret | `DEPLOY_KNOWN_HOSTS` | Onafhankelijk geverifieerde NAS-hostkey-regel |
|
||||
| Secret | `RELEASE_TOKEN` | Apart Gitea-token voor Actions lezen en Git-tags maken |
|
||||
|
||||
Het releaseaccount heeft repositorylees-/schrijfrechten en Actions-metadatatoegang
|
||||
nodig (`write:repository` op deze Gitea). Het NAS-registrycredential is apart en
|
||||
heeft alleen de noodzakelijke package-leestoegang. Hergebruik de publicatie-PAT
|
||||
niet voor deployment. Bewaar secrets buiten Git en logs.
|
||||
|
||||
De setuphelper kan deze configuratie en de productiemap zonder containerstart
|
||||
inrichten. Bewaar `admin-token`, `s6-release-token`, `s6-pull-token` en de private
|
||||
`s6-deploy-key` als owner-only bestanden (mode `600`) in
|
||||
`~/.config/agiledancers-runner/`. Gebruik de eerder vertrouwde NAS-hostkey in
|
||||
`~/.ssh/known_hosts` en voer uit:
|
||||
|
||||
```sh
|
||||
java ci/Ci.java configure-deployment
|
||||
```
|
||||
|
||||
Defaults zijn de bevestigde NAS/account/SSH-poort, repository
|
||||
`wanjakrah/agiledancers`, productiemap `/volume1/docker/agiledancers-production`,
|
||||
NAS-IP-binding `192.168.2.28` en frontendpoort `8088`. De helper controleert een
|
||||
geslaagde main-build, weigert een bezette poort bij eerste inrichting, bewaart
|
||||
bestaande productieconfiguratie en controleert de aparte registry-login voordat
|
||||
Gitea-secrets/variabelen worden gezet. Er wordt geen release/tag gemaakt en geen
|
||||
container vervangen. Variabelen met de namen uit bovenstaande tabel en
|
||||
`DEPLOY_BIND_IP`, `DEPLOY_FRONTEND_PORT`, `PULL_USER` en de credential-`*_FILE`-
|
||||
paden kunnen de defaults expliciet vervangen.
|
||||
|
||||
Bescherm release-tags `v*` in Gitea en beperk tagcreatie tot de releasebeheerder.
|
||||
De helper maakt alleen nieuwe tags; hij verplaatst of verwijdert ze nooit. Laat
|
||||
registry-cleanup de images van huidig/vorig niet verwijderen. Gebruik geen
|
||||
algemene Docker-image/volume-prune als onderhoud van deze stack.
|
||||
|
||||
## Nieuwe release, retry en rollback
|
||||
|
||||
1. Merge naar `main` en wacht op een geslaagde **Build, test and publish** voor
|
||||
die SHA, inclusief imagepublicatie.
|
||||
2. Open **Deploy production → Run workflow**, branch `main`, mode `new`, keuze
|
||||
`patch`, `minor` of `major`. Laat het versieveld leeg. De eerste release is
|
||||
`v1.0.0`; daarna telt de hoogste bestaande release-tag, inclusief mislukte
|
||||
deployments. Minor/major zetten de lagere componenten op nul.
|
||||
3. De workflow toont versie/SHA. De immutable annotated Git-tag wordt na
|
||||
imagevoorbereiding, vóór vervanging gemaakt en blijft bij falen bestaan.
|
||||
Een tag bewijst geen succesvolle productiedeployment.
|
||||
4. Gebruik mode `retry` met een bestaande tag om dezelfde SHA/versie opnieuw uit
|
||||
te rollen. De incrementkeuze wordt genegeerd: Gitea toont alle velden, ook
|
||||
wanneer ze voor de gekozen mode niet relevant zijn. Een retry mag afwijken
|
||||
van huidig main, maar geen nieuwere succesvolle release verdringen.
|
||||
5. **Rollback production → Run workflow → main** herstelt de vorige succesvolle
|
||||
release zonder versie/tag. Na succes wisselen huidig/vorig om; nogmaals
|
||||
rollback kan dus terugschakelen. De hoogste succesvolle versie blijft bewaard.
|
||||
|
||||
De NAS-lock omvat alle modes en versieallocatie. Een gelijktijdige run faalt
|
||||
zichtbaar. Gitea 1.25 negeert workflow-`concurrency`; de serverlock is leidend.
|
||||
Main wordt direct vóór vervanging opnieuw gecontroleerd. Zodra vervanging start,
|
||||
wordt de gepinde versie afgemaakt of hersteld. Branchbuilds rollen niets uit.
|
||||
|
||||
## Checks en operationele state
|
||||
|
||||
De helper haalt beide SHA-images terug, controleert revisie/platform en legt
|
||||
registry-digests vast. Compose gebruikt die digests, nooit de bewegende main-tag.
|
||||
De recovery-images worden eveneens vooraf gecontroleerd. Binnen vijf minuten
|
||||
moeten backend-readiness, frontendpagina, GET `/api/dance-schools` via de
|
||||
gepubliceerde frontendpoort en containeridentiteit slagen. Deze checks schrijven
|
||||
geen gebruikersdata. De frontend herstart ook om de nieuwe backend-IP te resolven.
|
||||
|
||||
De productiemap bevat:
|
||||
|
||||
- `state.json`: atomisch geschreven huidig/vorig en hoogste succesvolle versie.
|
||||
Redeployment van dezelfde versie behoudt de afzonderlijke rollbackversie.
|
||||
- `releases/<attempt>/`: behouden Compose- en digest-/versieconfiguratie.
|
||||
- `pending.json`: kandidaat en vorige state, vóór iedere vervanging geschreven.
|
||||
- `deploy.lock/owner`: unieke run/poging; `operation/` markeert een actieve
|
||||
vervanging op de NAS.
|
||||
- `history/`: pogingjournalen en uitkomsten; niet opruimen tijdens een release.
|
||||
|
||||
Een ongezonde kandidaat herstelt automatisch de vorige succesvolle release en
|
||||
blijft een mislukte workflow. Bij de eerste release zonder voorganger, mislukt
|
||||
herstel, runner/SSH-onderbreking of onduidelijke statecommit blijven journal en
|
||||
lock staan. Nieuwe runs weigeren dan wijzigingen. Remote opdrachten hebben ook
|
||||
op de NAS een timeout; herstel overlapt geen nog actieve vervanging. Geen
|
||||
eindeloze herstelpogingen.
|
||||
|
||||
Download artifact `deployment-<run>-<attempt>` of `rollback-<run>-<attempt>` voor
|
||||
log, uitkomst, versie/SHA/digests en beschikbare foutdiagnostiek. Retentie is
|
||||
veertien dagen; serverinstellingen mogen dit niet inkorten. Log geen environment,
|
||||
Docker-authconfig of volledige container-inspect met eventuele secrets.
|
||||
|
||||
## Handmatig herstel
|
||||
|
||||
Gebruik een vertrouwde beheerverbinding. Verwijder nooit alleen de lock om een
|
||||
nieuwe release door te drukken.
|
||||
|
||||
1. Annuleer de betrokken Gitea-run. Controleer op de NAS dat geen SSH-deployment,
|
||||
timeout, Compose-vervanging of herstel van deze poging meer actief is. Onderzoek
|
||||
`deploy.lock/operation`; wacht op de timeout of beëindig alleen de geverifieerde
|
||||
vastgelopen deploymentprocessen.
|
||||
2. Bewaar state, pending journal, history en containerlogs. Vergelijk de kandidaat,
|
||||
de `before`-state en werkelijke images. De statecommit kan al zijn uitgevoerd
|
||||
terwijl de runner geen antwoord ontving.
|
||||
3. Behoud een aantoonbaar gezonde kandidaat met overeenkomende state. Anders:
|
||||
herstel `before.current` uit het journal met de behouden Compose-/env-bestanden,
|
||||
dezelfde projectnaam en digest-images. Start geen tweede stack.
|
||||
4. Voer dezelfde checks uit. Vanaf de checkout op de mini-pc kun je het echte
|
||||
controlescript uitvoeren met bestaande lockowner en gekozen release-directory:
|
||||
|
||||
```sh
|
||||
ssh -i <private-key-path> -p <ssh-port> <deploy-user>@<nas> \
|
||||
'timeout -k 5 300 sh -s -- apply <production-directory> <lock-owner> <release-directory-id>' < deploy/remote.sh
|
||||
```
|
||||
|
||||
Gebruik de eerder gepinde hostkey en gecontroleerde waarden uit het journal.
|
||||
Verwijder een achtergebleven lege `operation/` alleen als stap 1 heeft bewezen
|
||||
dat de oude operatie gestopt is.
|
||||
5. Bij herstel van de oude release: herstel ook de volledige `before`-state
|
||||
atomisch, inclusief high-watermark en rollbackdoel. Bij een mislukte eerste
|
||||
release: stop de defecte stack en behoud de lege succesvolle state. Verwijder
|
||||
geen volumes of release-tags.
|
||||
6. Noteer het herstel in history, archiveer het opgeloste journal en verwijder
|
||||
daarna pas de lockowner en lege lockdirectory. Start vervolgens een retry.
|
||||
Laat de blokkade staan als gezondheid of state onduidelijk is.
|
||||
|
||||
## Na S16 en lokale verificatie
|
||||
|
||||
S16 blokkeert S6 niet. Zodra S16 is ingevoerd, moeten database/volumes buiten de
|
||||
vervangbare containers blijven en saved data zowel deployment als rollback
|
||||
overleven. De gewone procedure vereist dan databasecompatibiliteit met de vorige
|
||||
applicatieversie. Plan incompatibele migraties apart: imageherstel maakt geen
|
||||
migratie ongedaan. Backup/restore blijven S17-werk.
|
||||
|
||||
```sh
|
||||
java ci/Ci.java test
|
||||
java ci/Ci.java release-test
|
||||
sh -n deploy/remote.sh
|
||||
mvn -N -Dformat.mode=check exec:exec@format
|
||||
```
|
||||
|
||||
De buildworkflow voert beide Java-testsuites uit vóór publicatie. Release-tests
|
||||
wijzigen geen productie, registry of tags. Leg echte NAS-/Gitea-bewijzen vast in
|
||||
`docs/s6-validation.md`; configuratie en lokale tests alleen voltooien S6 niet.
|
||||
107
docs/s6-validation.md
Normal file
107
docs/s6-validation.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# S6 implementation and operational evidence
|
||||
|
||||
Status: IN_PROGRESS. Repository implementation and local validation do not yet
|
||||
establish an operational Synology deployment. No production release tags have
|
||||
been created by this implementation session.
|
||||
|
||||
## Confirmed environment
|
||||
|
||||
- Work is on `feature/S6_deployment`.
|
||||
- Read-only authenticated inspection of the installed Gitea confirmed run fields
|
||||
`path=build.yaml@refs/heads/main`, `status=completed`, `conclusion=success`,
|
||||
`event=push`, `head_branch=main` and `head_sha`.
|
||||
- No remote Git tags existed at the time of that read-only inspection.
|
||||
- The maintainer created the dedicated DSM account `agiledancers-deploy` and
|
||||
confirmed SSH port 22. A separate Ed25519 deployment key was generated outside
|
||||
Git on the mini-pc and installed on the NAS.
|
||||
|
||||
Subsequent live checks confirmed key-based access after removing group/other
|
||||
write permissions from the account home. The maintainer installed the dedicated
|
||||
Docker sudo rule using `deploy/enable-docker.sh`; a subsequent noninteractive
|
||||
check reports `linux/x86_64`. NAS model is **DS224+**, Compose is
|
||||
**v2.20.1-6047-g6817716**, `timeout -k` and `curl` are available, and port **8088**
|
||||
was free. The daemon allows HTTP registry access only through `127.0.0.0/8`.
|
||||
Deployment therefore uses the NAS-local `127.0.0.1:3000` alias of the same Gitea
|
||||
registry, without restarting Gitea/Kimai or changing the shared Docker daemon.
|
||||
|
||||
## NAS setup and real image preparation
|
||||
|
||||
`java ci/Ci.java configure-deployment` succeeded using separate owner-only local
|
||||
pull/release tokens. It provisioned `/volume1/docker/agiledancers-production`,
|
||||
the private IP/port configuration and registry pull login, verified the real NAS
|
||||
preflight, and stored the three deployment secrets and five variables in Gitea.
|
||||
No secret values are recorded here.
|
||||
|
||||
A real preparation probe exercised the production coordinator/API/SSH adapter
|
||||
and NAS script, stopping explicitly at the tag-creation boundary. It retrieved
|
||||
both images for verified main commit
|
||||
`b1544357bf6ea5e1607e1de1fa4872b9510690a8` (Gitea API build run ID **35**), verified
|
||||
revision/platform labels, selected registry digests and passed Compose v2.20
|
||||
configuration validation. It released the deployment lock without creating a
|
||||
Git tag, pending journal, successful release state or application containers.
|
||||
The displayed candidate `v1.0.0` was not allocated as a release.
|
||||
|
||||
| Component | Retrieved digest (NAS registry alias `127.0.0.1:3000/wanjakrah/`) |
|
||||
| --- | --- |
|
||||
| Backend | `sha256:d46af705c527a8eaa506407206cfce927edbc4b774951cf13da8702b5cb8c56d` |
|
||||
| Frontend | `sha256:d6c09ad839b929591878195c7403cbf0bbf24ac6e8d335ef90d72b7982c4ba31` |
|
||||
|
||||
Local probe evidence: `ci/artifacts/deployment/setup.log`, `nas-image-probe.log`
|
||||
and `nas-image-probe.json` (ignored by Git). Retained configuration on the NAS:
|
||||
`releases/image-probe-bbb2a980-e624-4331-adb6-b8fffd51fa5d/`. This is preparation
|
||||
evidence, not a successful production release or Gitea dispatch run.
|
||||
|
||||
## Local checks
|
||||
|
||||
- `java ci/Ci.java test`: **17 passed**, including publication gates and process
|
||||
deadlines.
|
||||
- `java ci/Ci.java release-test`: **32 passed**, including all version increments,
|
||||
input/main/manual gates, verified-build provenance, digest preparation failures,
|
||||
duplicate/stale release rejection, retry, version high-watermark after rollback,
|
||||
automatic recovery, failed recovery/first release, ambiguous state commits,
|
||||
lock contention, annotated-tag identity and registry aliases.
|
||||
- Seven of those release tests execute the actual POSIX NAS script against
|
||||
disposable command adapters, covering image/platform checks, published endpoint
|
||||
requests, retained-configuration mismatch, bounded readiness failure, overlapping
|
||||
replacement fencing and atomic state/journal handling. These are simulated
|
||||
failure-path tests, separate from the real NAS preparation probe above.
|
||||
- `sh -n` passed separately for `deploy/remote.sh`, `deploy/provision.sh` and
|
||||
`deploy/enable-docker.sh`.
|
||||
- `mvn -N -Dformat.mode=check exec:exec@format`: passed with no differences.
|
||||
- All workflow YAML parsed; assertions confirmed automatic builds, manual-only
|
||||
release/rollback triggers and the patch/minor/major form choices.
|
||||
- `docker compose -f deploy/compose.yaml config --quiet` passed with representative
|
||||
digest references; real NAS Compose validation passed during preparation too.
|
||||
- `git diff --check`: passed.
|
||||
|
||||
Backend/frontend application code is unchanged. A full Gitea feature/main build
|
||||
and dispatched production/recovery evidence remain to be collected after review.
|
||||
|
||||
## Required operational acceptance
|
||||
|
||||
- [x] Record NAS model/platform, Docker/Compose versions, private endpoint and
|
||||
production directory (no secret values).
|
||||
- [x] Verify pinned SSH hostkey, key-only automation and separate registry pull
|
||||
credential. Release-token read access is verified; actual tag-writing
|
||||
acceptance awaits the first release.
|
||||
- [ ] Verify release-tag creation/protection with the dedicated token.
|
||||
- [ ] Merge workflows through the protected-branch process and identify the
|
||||
successful main build/publication run and SHA.
|
||||
- [ ] Demonstrate release form, first release tag and real Synology access;
|
||||
record workflow URL, version, SHA and both deployed digests.
|
||||
- [ ] Demonstrate rejected unverified/missing-image release and branch exclusion
|
||||
without modifying production.
|
||||
- [ ] Demonstrate duplicate/stale/concurrent release protection, retained tags
|
||||
after failure and exact-SHA retry without another version.
|
||||
- [ ] Demonstrate failed candidate recovery while the workflow reports failure,
|
||||
with downloadable diagnostics.
|
||||
- [ ] Demonstrate manual rollback without a new version and retained image pairs.
|
||||
- [ ] Exercise first-release/recovery failure and interruption/manual recovery
|
||||
using isolated acceptance resources where appropriate.
|
||||
- [ ] Confirm fourteen-day artifact retention.
|
||||
- [ ] Confirm operator communication of the accepted pre-S16 data-loss policy.
|
||||
- [ ] Once S16 applies, verify data preservation and migration compatibility
|
||||
during deployment and rollback (conditional on S16 implementation).
|
||||
|
||||
Identify isolated acceptance resources explicitly. Simulated tests are not real
|
||||
production evidence.
|
||||
Reference in New Issue
Block a user