Record S6 production and NAS recovery acceptance [skip ci]
This commit is contained in:
@@ -90,6 +90,28 @@ 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.
|
Alleen de frontend bindt aan de private IPv4; de backend krijgt geen hostpoort.
|
||||||
De Docker-projectnaam is vast `agiledancers-production`.
|
De Docker-projectnaam is vast `agiledancers-production`.
|
||||||
|
|
||||||
|
### DSM-firewall
|
||||||
|
|
||||||
|
De bevestigde productieomgeving gebruikt frontendpoort **8088** op
|
||||||
|
`192.168.2.28` en Docker-subnet **172.18.0.0/16**. Maak in
|
||||||
|
**Configuratiescherm → Beveiliging → Firewall → Regels bewerken** toestaan-regels
|
||||||
|
op **Alle interfaces**, boven eventuele weigerregels:
|
||||||
|
|
||||||
|
| Poort | Protocol | Bron | Actie |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 8088 | TCP | `192.168.2.0`, masker `255.255.255.0` | Toestaan |
|
||||||
|
| 8080 | TCP | `172.18.0.0`, masker `255.255.0.0` | Toestaan |
|
||||||
|
|
||||||
|
De eerste regel geeft LAN-clients toegang; de tweede laat de frontend de backend
|
||||||
|
bereiken. Voeg voor bestaande VPN-clients zo nodig hun eigen bron-subnet toe
|
||||||
|
aan de frontendregel. Er wordt geen backendpoort op de NAS gepubliceerd en de
|
||||||
|
firewall blijft aan. Controleer bij het opnieuw aanmaken van het Docker-netwerk
|
||||||
|
het werkelijke subnet met `docker network inspect` en pas de regel aan als dat
|
||||||
|
subnet wijzigt. Gewone deployments vervangen containers en behouden het netwerk.
|
||||||
|
|
||||||
|
De tijdelijke S6-acceptatieregel voor `172.20.0.0/16` mag na de geïsoleerde tests
|
||||||
|
weg; dat testnetwerk en de testcontainers zijn opgeruimd.
|
||||||
|
|
||||||
Als Docker sudo vereist, laat een beheerder met `visudo` een afzonderlijke
|
Als Docker sudo vereist, laat een beheerder met `visudo` een afzonderlijke
|
||||||
sudoers-regel installeren en valideren, met het gecontroleerde Docker-pad:
|
sudoers-regel installeren en valideren, met het gecontroleerde Docker-pad:
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# S6 implementation and operational evidence
|
# S6 implementation and operational evidence
|
||||||
|
|
||||||
Status: IN_PROGRESS. Repository implementation and local validation do not yet
|
Status: IN_REVIEW. Production `v1.0.0` is running on the Synology at
|
||||||
establish an operational Synology deployment. No production release tags have
|
<http://192.168.2.28:8088>. Main publication, the real Gitea deployment and the
|
||||||
been created by this implementation session.
|
isolated NAS recovery/rollback acceptance checks passed. The evidence below
|
||||||
|
distinguishes real production actions from deliberately isolated fault tests.
|
||||||
|
|
||||||
## Confirmed environment
|
## Confirmed environment
|
||||||
|
|
||||||
@@ -88,9 +89,129 @@ Image publication is skipped for the feature branch.
|
|||||||
The subsequent evidence-only commit intentionally uses the accepted `[skip ci]`
|
The subsequent evidence-only commit intentionally uses the accepted `[skip ci]`
|
||||||
marker; implementation code is unchanged from this successful run.
|
marker; implementation code is unchanged from this successful run.
|
||||||
|
|
||||||
Main build/publication and dispatched production/recovery evidence remain to be
|
Implementation [PR #12](http://192.168.2.28:3000/wanjakrah/agiledancers/pulls/12)
|
||||||
collected after review and the protected merge. Review PR:
|
was reviewed and merged through the protected main branch. Production and
|
||||||
[S6 #12](http://192.168.2.28:3000/wanjakrah/agiledancers/pulls/12).
|
post-merge acceptance evidence follow.
|
||||||
|
|
||||||
|
## Production deployment and native workflow guards
|
||||||
|
|
||||||
|
The main SHA is `b0d6592761cf3ceab6e1ffbf9ca50548584a0096`.
|
||||||
|
|
||||||
|
| Evidence | Gitea run | Result |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Main build/test/publication | [#37](http://192.168.2.28:3000/wanjakrah/agiledancers/actions/runs/37), API ID 38 | Success |
|
||||||
|
| First manual `new` / `patch` release | [#38](http://192.168.2.28:3000/wanjakrah/agiledancers/actions/runs/38), API ID 39 | Success; production `v1.0.0` |
|
||||||
|
| Deliberate duplicate new release for the same SHA | [#39](http://192.168.2.28:3000/wanjakrah/agiledancers/actions/runs/39), API ID 40 | Expected rejection, production unchanged |
|
||||||
|
| Manual deployment from a temporary validation branch | [#40](http://192.168.2.28:3000/wanjakrah/agiledancers/actions/runs/40), API ID 41 | Expected skip, production unchanged |
|
||||||
|
|
||||||
|
The original feature branch had been deleted after merge; its attempted dispatch
|
||||||
|
returned 404 and is not counted as branch-guard evidence. The actual skipped run
|
||||||
|
used `validation/s6-deploy-guard`, based on the existing documentation-only
|
||||||
|
`60496de` commit. That temporary branch was removed after verification.
|
||||||
|
|
||||||
|
The real annotated Git tag `v1.0.0` has tag-object SHA
|
||||||
|
`0b8df86a9de1729395baad35584e4accead29c44` and points directly to the main SHA above.
|
||||||
|
Gitea tag protection rule ID **1**, pattern `v*`, allows only `wanjakrah` (the
|
||||||
|
account owning the dedicated release token) to create/delete release tags.
|
||||||
|
The helper never moves or deletes them; this does not remove the trusted
|
||||||
|
maintainer's administrative ability to manage tags.
|
||||||
|
|
||||||
|
Production image digests, using the NAS-local `127.0.0.1:3000/wanjakrah/` registry:
|
||||||
|
|
||||||
|
| Component | Deployed digest |
|
||||||
|
| --- | --- |
|
||||||
|
| Backend | `sha256:1d6f5e35bb58341bfa7b6ed0b88e5bdebced60666ca289d5511613f35d9ee92e` |
|
||||||
|
| Frontend | `sha256:843a1ffcdbe708573ca55f51a04adee0d158f255f067225a20c6d41b382ce295` |
|
||||||
|
|
||||||
|
Both running containers report `v1.0.0` and the selected main SHA. Backend
|
||||||
|
readiness, frontend and proxied API checks passed in the workflow. A subsequent
|
||||||
|
read-only GET from the mini-pc to `http://192.168.2.28:8088/api/dance-schools`
|
||||||
|
returned HTTP success and `[]`. The successful state is recorded under
|
||||||
|
`releases/release-39-3b481acf-396d-41d6-96a6-6b7ef8710f18/`, with no pending
|
||||||
|
journal or deployment lock. As this is the first production release, its previous
|
||||||
|
successful production release is correctly `null`.
|
||||||
|
|
||||||
|
### Firewall and diagnostics
|
||||||
|
|
||||||
|
The initial readiness wait exposed an active DSM firewall blocking frontend-to-
|
||||||
|
backend traffic. The maintainer added these **All interfaces** allow rules above
|
||||||
|
deny rules: TCP **8088** from `192.168.2.0/24`, and TCP **8080** from the actual
|
||||||
|
production Docker subnet **172.18.0.0/16**. The same first deployment then passed;
|
||||||
|
there was no extra production version or forced bypass of readiness checks.
|
||||||
|
|
||||||
|
Downloaded and opened the actual workflow diagnostic ZIPs:
|
||||||
|
|
||||||
|
- `deployment-39-20261103135841995564629`: two files; recorded outcome `success`.
|
||||||
|
- `deployment-40-20261103141439174434089`: two files; recorded outcome `rejected`.
|
||||||
|
|
||||||
|
Both workflows request fourteen-day artifact retention, within the previously
|
||||||
|
confirmed server retention limits. The ZIPs and run-view metadata are retained
|
||||||
|
locally in `ci/artifacts/deployment/live-workflows/`. The older Gitea artifact
|
||||||
|
list API limitation documented under S4 was avoided by downloading the actual
|
||||||
|
run-page artifact archives.
|
||||||
|
|
||||||
|
## Isolated real NAS failure and rollback acceptance
|
||||||
|
|
||||||
|
**Twelve checks passed against real NAS Docker containers**, using the production
|
||||||
|
`Release` coordinator and remote shell script. They used only project
|
||||||
|
`agiledancers-s6-acceptance`, loopback endpoint `127.0.0.1:18089` and network
|
||||||
|
`172.20.0.0/16`. State/configuration was isolated under
|
||||||
|
`/volume1/docker/agiledancers-s6-acceptance`, with `-first` and `-recovery` sibling
|
||||||
|
directories for first-release and failed-recovery cases.
|
||||||
|
|
||||||
|
The adapter changed only the project/network/configuration namespace and injected
|
||||||
|
controlled faults. **Release tags and main-head selections in this test adapter
|
||||||
|
were virtual**: no additional real Git tags were created. Build verification and
|
||||||
|
image pulls used real Gitea/registry responses for verified main SHAs `b1544357...`
|
||||||
|
and `b0d65927...`. The missing-image case also used verified main SHA `c965f9b4...`.
|
||||||
|
Fault cases used a ten-second readiness window and healthy cases sixty seconds;
|
||||||
|
the production workflow retains its normal five-minute replacement bound.
|
||||||
|
|
||||||
|
1. A healthy initial isolated release passed the real container/readiness checks.
|
||||||
|
2. A distinct candidate whose backend deliberately exited with status 23 failed;
|
||||||
|
the real previous image pair was restored, the attempt remained failed, and
|
||||||
|
its virtual version remained allocated.
|
||||||
|
3. Retrying the same version/SHA with a healthy configuration succeeded without
|
||||||
|
allocating another version.
|
||||||
|
4. Manual rollback restored the distinct previous SHA without another version;
|
||||||
|
a second rollback restored the newer successful release.
|
||||||
|
5. Retry of an older version after rollback was rejected by the high-watermark.
|
||||||
|
6. A real missing registry image was rejected before version allocation or
|
||||||
|
replacement.
|
||||||
|
7. An unverified SHA was rejected using real Gitea build metadata.
|
||||||
|
8. Duplicate and stale releases were rejected while running containers stayed
|
||||||
|
unchanged.
|
||||||
|
9. A competing NAS lock owner excluded a second release attempt.
|
||||||
|
10. An injected lost state-commit response retained the real pending journal and
|
||||||
|
lock, blocked the next attempt and was resolved with explicit manual recovery.
|
||||||
|
11. A real failed first release retained its journal/lock; manual stop/archive
|
||||||
|
recovery left no fabricated successful state.
|
||||||
|
12. Both a candidate and its recovery configuration were deliberately broken;
|
||||||
|
automatic recovery failed visibly and retained its journal/lock. Repairing
|
||||||
|
the retained previous configuration and following manual recovery restored
|
||||||
|
the recorded previous SHA.
|
||||||
|
|
||||||
|
Raw program, logs and `results.json` are retained in
|
||||||
|
`ci/artifacts/deployment/nas-acceptance/`. The test stack's containers and Docker
|
||||||
|
network were removed. Test state/history remains for inspection. Final independent
|
||||||
|
verification confirmed that production still ran the original `v1.0.0` SHA,
|
||||||
|
without a pending journal or lock, and that no acceptance containers/network
|
||||||
|
remained. The maintainer was told the temporary firewall rule for `172.20.0.0/16`
|
||||||
|
can be removed; the two production rules must remain.
|
||||||
|
|
||||||
|
These isolated tests prove the NAS replacement/recovery behavior, not a second
|
||||||
|
successful production release. Native Gitea rollback against a populated
|
||||||
|
production predecessor can be exercised after a normal subsequent release;
|
||||||
|
the same coordinator's actual distinct-version rollback is demonstrated above.
|
||||||
|
|
||||||
|
## Data boundary
|
||||||
|
|
||||||
|
The maintainer explicitly accepted redeployment data loss for the launching-
|
||||||
|
partner phase until S16 and confirmed the operator-communication policy during
|
||||||
|
refinement. The workflow and runbook display that limitation. No messages were
|
||||||
|
sent to the partner on the maintainer's behalf. S16 is not implemented, so saved-
|
||||||
|
data preservation and migration compatibility remain conditional S16 acceptance,
|
||||||
|
not a durability claim for this release.
|
||||||
|
|
||||||
## Required operational acceptance
|
## Required operational acceptance
|
||||||
|
|
||||||
@@ -99,24 +220,25 @@ collected after review and the protected merge. Review PR:
|
|||||||
- [x] Verify pinned SSH hostkey, key-only automation and separate registry pull
|
- [x] Verify pinned SSH hostkey, key-only automation and separate registry pull
|
||||||
credential. Release-token read access is verified; actual tag-writing
|
credential. Release-token read access is verified; actual tag-writing
|
||||||
acceptance awaits the first release.
|
acceptance awaits the first release.
|
||||||
- [ ] Verify release-tag creation/protection with the dedicated token.
|
- [x] Verify release-tag creation/protection with the dedicated token.
|
||||||
- [ ] Merge workflows through the protected-branch process and identify the
|
- [x] Merge workflows through the protected-branch process and identify the
|
||||||
successful main build/publication run and SHA.
|
successful main build/publication run and SHA.
|
||||||
- [ ] Demonstrate release form, first release tag and real Synology access;
|
- [x] Demonstrate release form, first release tag and real Synology access;
|
||||||
record workflow URL, version, SHA and both deployed digests.
|
record workflow URL, version, SHA and both deployed digests.
|
||||||
- [ ] Demonstrate rejected unverified/missing-image release and branch exclusion
|
- [x] Demonstrate rejected unverified/missing-image release and branch exclusion
|
||||||
without modifying production.
|
without modifying production.
|
||||||
- [ ] Demonstrate duplicate/stale/concurrent release protection, retained tags
|
- [x] Demonstrate duplicate/stale/concurrent release protection, retained versions
|
||||||
after failure and exact-SHA retry without another version.
|
after failure and exact-SHA retry without another version.
|
||||||
- [ ] Demonstrate failed candidate recovery while the workflow reports failure,
|
- [x] Demonstrate failed candidate recovery while the coordinator reports failure,
|
||||||
with downloadable diagnostics.
|
with downloadable diagnostics.
|
||||||
- [ ] Demonstrate manual rollback without a new version and retained image pairs.
|
- [x] Demonstrate manual rollback without a new version and retained image pairs.
|
||||||
- [ ] Exercise first-release/recovery failure and interruption/manual recovery
|
- [x] Exercise first-release/recovery failure and interruption/manual recovery
|
||||||
using isolated acceptance resources where appropriate.
|
using isolated acceptance resources where appropriate.
|
||||||
- [ ] Confirm fourteen-day artifact retention.
|
- [x] Confirm fourteen-day artifact retention configuration and artifact downloads.
|
||||||
- [ ] Confirm operator communication of the accepted pre-S16 data-loss policy.
|
- [x] Confirm the maintainer's accepted pre-S16 data-loss/communication policy.
|
||||||
- [ ] Once S16 applies, verify data preservation and migration compatibility
|
- [ ] Once S16 applies, verify data preservation and migration compatibility
|
||||||
during deployment and rollback (conditional on S16 implementation).
|
during deployment and rollback (deferred until S16 implementation, not a
|
||||||
|
blocker for the explicitly accepted pre-S16 release).
|
||||||
|
|
||||||
Identify isolated acceptance resources explicitly. Simulated tests are not real
|
Identify isolated acceptance resources explicitly. Simulated tests are not real
|
||||||
production evidence.
|
production evidence.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# S6 — Manual versioned production deployment through Gitea
|
# S6 — Manual versioned production deployment through Gitea
|
||||||
|
|
||||||
Status: IN_PROGRESS
|
Status: IN_REVIEW
|
||||||
|
|
||||||
Agreed after the grill-me interview; shared understanding confirmed.
|
Agreed after the grill-me interview; shared understanding confirmed.
|
||||||
|
|
||||||
@@ -141,44 +141,48 @@ does not restore lost data.
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] Successful main builds still automatically verify and publish matching SHA
|
- [x] Successful main builds still automatically verify and publish matching SHA
|
||||||
images; publishing does not automatically change production.
|
images; publishing does not automatically change production.
|
||||||
- [ ] Gitea's manual workflow form provides new/retry mode and the appropriate
|
- [x] Gitea's manual workflow form provides new/retry mode and the appropriate
|
||||||
release-type or existing-tag inputs; invalid combinations fail clearly.
|
release-type or existing-tag inputs; invalid combinations fail clearly.
|
||||||
- [ ] The first release and subsequent patch/minor/major releases allocate the
|
- [x] The first release and subsequent patch/minor/major releases allocate the
|
||||||
agreed versions and immutable annotated remote Git tags on verified SHAs.
|
agreed versions and immutable annotated remote Git tags on verified SHAs.
|
||||||
- [ ] Duplicate new releases, tag conflicts, concurrent attempts, stale main
|
- [x] Duplicate new releases, tag conflicts, concurrent attempts, stale main
|
||||||
snapshots and older pending deployments cannot overwrite release identity
|
snapshots and older pending deployments cannot overwrite release identity
|
||||||
or replace a newer successful release.
|
or replace a newer successful release.
|
||||||
- [ ] An unverified release or missing image is rejected before production changes;
|
- [x] An unverified release or missing image is rejected before production changes;
|
||||||
branch builds cannot deploy production.
|
branch builds cannot deploy production.
|
||||||
- [ ] A real Synology deployment serves the frontend and proxied API over the
|
- [x] A real Synology deployment serves the frontend and proxied API over the
|
||||||
private endpoint, with both containers running the selected image pair.
|
private endpoint, with both containers running the selected image pair.
|
||||||
- [ ] Readiness, frontend, proxied read-only API and image-identity checks establish
|
- [x] Readiness, frontend, proxied read-only API and image-identity checks establish
|
||||||
success within five minutes or trigger recovery.
|
success within five minutes or trigger recovery.
|
||||||
- [ ] A deliberately failed release restores the previous successful version,
|
- [x] A deliberately failed release restores the previous successful version,
|
||||||
while the workflow reports failure. Failed first deployment and failed
|
while the workflow reports failure. Failed first deployment and failed
|
||||||
recovery produce actionable diagnostics and manual recovery instructions.
|
recovery produce actionable diagnostics and manual recovery instructions.
|
||||||
- [ ] A failed release can be retried with its existing tag/SHA without allocating
|
- [x] A failed release can be retried with its existing tag/SHA without allocating
|
||||||
another version or superseding a newer successful release.
|
another version or superseding a newer successful release.
|
||||||
- [ ] Manual rollback demonstrably restores the previous successful release with
|
- [x] Manual rollback demonstrably restores the previous successful release with
|
||||||
no new version, and required retained images are available.
|
no new version, and required retained images are available.
|
||||||
- [ ] The temporary pre-S16 data-loss policy is visible in workflow documentation
|
- [x] The temporary pre-S16 data-loss policy is visible in workflow documentation
|
||||||
and the runbook. Once S16 applies, demonstrate saved data surviving both
|
and the runbook. Once S16 applies, demonstrate saved data surviving both
|
||||||
deployment and rollback, including the migration compatibility requirement.
|
deployment and rollback, including the migration compatibility requirement.
|
||||||
- [ ] Server setup and operational recovery documentation are usable; diagnostics
|
The latter is conditional S16 acceptance and is not applicable yet.
|
||||||
|
- [x] Server setup and operational recovery documentation are usable; diagnostics
|
||||||
and release outcomes are retained for fourteen days without secrets.
|
and release outcomes are retained for fourteen days without secrets.
|
||||||
|
|
||||||
## Implementation handoff
|
## Implementation and evidence
|
||||||
|
|
||||||
This specification records the confirmed design. Implementing workflows, release
|
This specification records the confirmed design. The evidence combines automated
|
||||||
automation, Compose configuration, Synology provisioning and collecting actual
|
behavior tests, real Gitea production release/guard runs and isolated real NAS
|
||||||
deployment/recovery evidence are subsequent work. Configuration alone does not
|
fault tests. Their distinct scopes and the virtual-tag boundary of the isolated
|
||||||
|
tests are documented in `docs/s6-validation.md`. Configuration alone does not
|
||||||
complete S6.
|
complete S6.
|
||||||
|
|
||||||
Implementation is in progress on `feature/S6_deployment`: workflows, Compose,
|
Implementation PR #12 is merged. Production `v1.0.0` runs at
|
||||||
release/retry/rollback helpers, failure-path tests and provisioning/runbook are
|
`http://192.168.2.28:8088` following a successful main build and real manual Gitea
|
||||||
provided. The dedicated NAS account, registry login and Gitea deployment secrets
|
deployment. Native duplicate/branch guards and downloadable artifacts were
|
||||||
are provisioned. Real image preparation passed without a release or container
|
verified. Twelve isolated real NAS checks cover recovery, retry, distinct-version
|
||||||
replacement. See `docs/s6-validation.md`; workflow execution and production
|
rollback, failure guards and manual recovery; they use separate state/containers
|
||||||
deployment/recovery evidence remain required after the protected main merge.
|
and virtual test tags, without changing production. The test resources have been
|
||||||
|
removed. See `docs/s6-validation.md` for run links, digests, evidence boundaries
|
||||||
|
and the conditional S16 data-persistence acceptance. S6 is ready for review.
|
||||||
Reference in New Issue
Block a user