ops(web): bound immutable release history

This commit is contained in:
lingniu
2026-07-16 04:18:15 +08:00
parent 8e8f3f9f5c
commit 326d03cd6d
10 changed files with 392 additions and 3 deletions

View File

@@ -44,6 +44,16 @@ Release `web-release-smoke-20260716015150` installs `deploy/verify-web-release.s
Behavioral tests cover a valid release, a missing compatibility file, a wrong HTTP 200 response body and an unsafe manifest path. The deployed gate passed all 20 current assets and all 20 compatibility assets from `mileage-export-worker-20260716014414`; the platform service remained active and the authenticated health endpoint reported the new release. The ECS host still runs Python 3.6, so the test fixture uses a working-directory subshell instead of the newer `http.server --directory` option and now proves the same cases on both the development host and ECS. The final release is `web-release-smoke-portable-20260716015528`.
## 2026-07-16: bounded immutable release history
The initial immutable-release workflow copied every asset from the active release into the next release. Because the active release already contained its own compatibility assets, this formed a transitive chain: every deployment retained all earlier assets. The ECS host had accumulated 747 release directories occupying 12 GB, even though only the current and recent rollback revisions could serve traffic.
The production build now emits `.release-assets` itself and verifies that it lists every generated file exactly once. Release preparation keeps three explicit compatibility generations, copies only assets named by those manifests and rejects unsafe names, missing files or same-name/different-content collisions. Older tabs remain protected by the route boundary's one-shot current-version reload, while recent tabs continue loading their original hashed chunks without interruption.
`install-web-release.sh` stages an immutable directory, validates archive paths, atomically replaces the `current` symlink, restarts the service, verifies every current and compatibility asset byte-for-byte, checks the authenticated runtime release and only then prunes history to 20 releases. Any readiness, asset or health failure restores the previous symlink, release environment and service before returning an error. Tests exercise successful installation, bounded compatibility generations, unsafe input, missing assets, release pruning and a forced post-switch rollback.
This applies the same lifecycle principles as blue/green deployment: stage a separate revision, validate it, switch traffic and retain a bounded rollback history. AWS documents fast rollback by switching back to the blue environment, while Kubernetes exposes `revisionHistoryLimit` because unbounded old revisions consume control-plane resources: <https://docs.aws.amazon.com/whitepapers/latest/blue-green-deployments/introduction.html>, <https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit>.
## 2026-07-16: cancellable, off-main-thread mileage export
The full-fleet mileage export previously performed three long-running phases as one opaque foreground action: paginating vehicle identities, paginating daily mileage rows and building the ExcelJS workbook on the browser main thread. Navigating away did not cancel the export requests, and a large `writeBuffer()` could make controls and route transitions unresponsive.