Files
satellite-provider/_docs/03_implementation/deploy_cycle4.md
T
Oleksandr Bezdieniezhnykh e31f59211d [AZ-500] Cycle 4 Step 17: retrospective + close cycle
Adds retro_2026-05-12_cycle4.md, structure_2026-05-12_cycle4.md, and
the deploy_cycle4.md report that was dropped from the Steps 12-15
sync commit. Appends 3 new lessons to LESSONS.md (12/15 ring buffer)
on transitive major-version bumps, exposed pre-existing bugs, and
single-task-cycle metric framing. State advances to cycle 5 / step 9
(awaiting next New Task invocation).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 06:14:43 +03:00

6.9 KiB

Deploy Report — Cycle 4 (AZ-500)

Date: 2026-05-12 Cycle: 4 Scope: Single-task cycle — AZ-500 .NET 8 LTS → .NET 10 migration (cross-cutting infra: every csproj, both Dockerfiles, every CI script, two docs, plus the Microsoft.OpenApi 1.x → 2.x compat refactor in Program.cs).

What is shipping

Code changes (committed to dev, pushed to origin/dev)

Commit Subject
c0f004d [AZ-500] Cycle 4 Step 9: new-task .NET 10 migration
8131363 [AZ-500] .NET 8 -> .NET 10 migration
de609cf [AZ-500] Cycle 4 implement-skill wrap-up reports
af4219f [AZ-500] Cycle 4 Steps 12-15 sync (test-spec / docs / security / perf)

All 4 commits on dev, pushed to origin/dev as of this report.

Database migration

None this cycle. AZ-500 is runtime/SDK only; the tiles table schema and all DbUp migrations are unchanged. Per AZ-500 Constraint: "Do not rename any database objects during this task."

Configuration changes (operator must verify before promoting)

Setting Was Now Source
Host SDK on every dev/CI machine .NET 8.0.x SDK installed (or rolling from .NET 10.0.x via global.json latestMinor — no, that one didn't roll because cycle-3 pin was 8.0.0/latestMinor) .NET 10.0.x SDK installed (pin is now 10.0.0/latestMinor, so any 10.0.x patch SDK satisfies — dotnet --list-sdks should show ≥ 10.0.0) AZ-500 AC-2 — global.json. Surfaced in cycle-3 perf-harness leftover (host had only 10.0.103, .NET 8 pin wouldn't roll). Now resolved at the project pin level.
Docker image tag (api service) mcr.microsoft.com/dotnet/aspnet:8.0 (floating, last resolved 8.0.25-bullseye-slim) mcr.microsoft.com/dotnet/aspnet:10.0 (floating; first build pulls latest 10.0.x patch from Microsoft) AZ-500 AC-3 — SatelliteProvider.Api/Dockerfile. CI image (mcr.microsoft.com/dotnet/sdk:10.0) similarly bumped in .woodpecker/01-test.yml + scripts/run-tests.sh.
No new env vars introduced. AZ-500 carries forward the cycle-3 env contract verbatim (JWT_SECRET ≥ 32B, JWT_ISSUER, JWT_AUDIENCE, GOOGLE_MAPS_API_KEY).

Container image

  • Source: SatelliteProvider.Api/Dockerfile multi-stage build, base mcr.microsoft.com/dotnet/aspnet:10.0 (was :8.0).
  • Verification on dev workstation (local): docker compose up -d --build → API healthy on :18980, /swagger returns 301, anonymous probe of /api/satellite/region/<id> returns 401 (expected — JWT enforcement). Verified at the start of Step 15 perf run.
  • Verification on CI: origin/dev push at af4219f triggers Woodpecker 01-test (now on mcr.microsoft.com/dotnet/sdk:10.0) → 02-build-push → registry tag dev-arm. Operator action: confirm the next CI run on dev succeeds before promoting to staging.
  • Multi-arch: mcr.microsoft.com/dotnet/sdk:10.0 and aspnet:10.0 are published as multi-arch (amd64 + arm64) by Microsoft — verified via docker manifest inspect in cycle 3 (no change in cycle 4); Risk #6 from AZ-500 spec is closed.

Verification gates passed in this cycle

Gate Result Evidence
Step 11 — Functional test suite PASS 271 unit + integration tests green; _docs/03_implementation/implementation_report_dotnet10_migration_cycle4.md
Step 12 — Test-Spec Sync PASS _docs/02_document/tests/traceability-matrix.md updated with 8 AZ-500 AC rows + .NET 10 runtime restriction supersession + Cycle-4 coverage shape note
Step 13 — Update Docs PASS 8 doc files synced + _docs/02_document/ripple_log_cycle4.md (empty import-graph ripple recorded with rationale)
Step 14 — Security Audit PASS_WITH_WARNINGS _docs/05_security/dependency_scan_cycle4.md + security_report_cycle4.md; 0 new Critical/High; cycle-3 D2 (Microsoft.NET.Test.Sdk carry-over) still open per AZ-500 scope
Step 15 — Performance Test PASS_WITH_UNVERIFIED _docs/06_metrics/perf_2026-05-12_cycle4.md; PT-01..PT-07 PASS (7.7x improvement on PT-07 warm p95); PT-08 unmeasurable (pre-existing script bug, not a .NET 10 regression)

Outstanding leftovers (NOT closed by cycle 4)

  1. _docs/_process_leftovers/2026-05-12_perf-cycle3-harness-execution.md — STAYS OPEN. Replay #3 (this cycle's Step 15 full run) appended; PT-08 still hits the same pre-existing scripts/run-performance-tests.sh:417 grep-pipefail bug. Per AZ-500 Constraint: "leftover file is deleted ONLY when the full perf script runs cleanly." Closure path is the script-fix follow-up PBI below.
ID Estimate Title Why
(TBD) 1 SP Fix scripts/run-performance-tests.sh:416-417 grep-pipefail Replace grep -o ... | wc -l with grep -c ... || true. Unblocks PT-08 + closes the cycle-3 perf-harness leftover. Trivial mechanical fix.
(TBD) 3 SP Migrate WithOpenApi(...) callsites to ASP.NET Core 10 minimal-API metadata extensions Clears 8 ASPDEPR002 deprecation warnings in Program.cs. Recorded in _docs/03_implementation/reviews/batch_01_cycle4_review.md. API still fully functional in .NET 10 (deprecated, not removed).
(TBD) 1 SP Microsoft.OpenApi 2.x nullable cleanup CS8604 warning in SatelliteProvider.Api/Swagger/ParameterDescriptionFilter.cs:25 exposed by the major bump.
(TBD) 1 SP Bump Microsoft.NET.Test.Sdk 17.8.0 → 17.13.0+ Closes cycle-3 D2 (transitive NuGet.Frameworks flag). Test-runtime exposure only; safe to land independently.
(TBD) 1 SP (recheck per cycle) Serilog.AspNetCore 8.0.3 → 10.x Currently retains 8.0.3 fallback per AZ-500 Risk #4 (no 10.x line published as of cycle 4). Re-check at every cycle start; bump as soon as a 10.x line ships. Removes the AGENTS.md/00_discovery/api_program inline-fallback notes.

Operator runbook for promoting to staging / production

  1. Wait for CI to confirm dev build at af4219f is green and the registry has the new dev-arm (and any new amd64) tag built on aspnet:10.0.
  2. Verify on a dev environment that docker pull of the new tag + docker compose up -d brings the API up healthy on the configured port; smoke-test /swagger (expect 200/301) and /api/satellite/region/<random> (expect 401, no 500).
  3. If staging/production hosts have not yet provisioned the .NET 10 SDK on the host (only relevant for non-containerised perf-harness invocations), update host provisioning to install .NET 10.0.x SDK. The deployed container itself does NOT need a host SDK — only scripts/run-performance-tests.sh does (and that script normally only runs from a developer or CI machine).
  4. No DB migration to apply. No env-var change to coordinate.
  5. Roll forward; if a regression appears, roll back to the prior dev-arm tag (the one built from commit de609cf or earlier) — same compose contract, same env vars, same DB schema.