deploy-scp.yaml: download, back up the production database before touching anything, upload into a timestamped release, symlink the persistent website in, switch current and restart, verify /health with retries, prune old releases only once that check passes. No sudo, no container actions, one shared interface U5 will call next.
4.2 KiB
4.2 KiB
Code Generation Plan — U6 Deploy Workflow
Unit Context
- Unit: U6 Deploy Workflow (Pipeline-type — YAML only, no C#/frontend code)
- Component: C-11 Deploy transport workflows (
.gitea/workflows/) - Requirements: FR-02, FR-03, FR-06, FR-08, FR-20
- Depends on: U1, U2, U5 (per
unit-of-work-dependency.md) — U1/U2 are already committed (Rounds 1–2); U5 does not exist yet, but U6 only needs to expose the interface U5 will call, not the other way around, so generating U6 first is safe - Depended on by: U5 (invokes this workflow), U7, Operations
- Basis:
construction/u6-deploy-workflow/infrastructure-design/infrastructure-design.md(approved) anddeployment-architecture.md - No test project applies:
.gitea/workflows/is pipeline configuration, not an application project — there is no C# test project for it, mirroring how the Slave API has none (CLAUDE.md). Verification for this unit is YAML validity plus logical review; real execution requires the actual Pi, SSH credentials and database, which is explicitly out of scope until Operations (per U6's Definition of Done inunit-of-work.md).
Steps
-
Step 1: Generate
.gitea/workflows/deploy-scp.yaml— reusableworkflow_callworkflowon.workflow_call.inputs:artifact_name,environment,deploy_path,service_name,health_check_url(all required strings),run_db_backup(optional boolean, defaultfalse),transport(optional string, defaultscp)- Single
deployjob, plain shell steps only (D-05 — no container actions) - Step: download artifact (
actions/download-artifact) - Step: production-only DB backup —
if: ${{ inputs.run_db_backup }}, SSH into the host and invoke~/scripts/backup-slpmodularcms-db.sh(script itself is an Operations/host-setup artifact, not generated here) - Step:
sshpass+scpthe artifact into${{ inputs.deploy_path }}/releases/<timestamp>/(timestamp computed once, reused across steps via a job output — same pattern the reference project uses for theconfigjob) - Step: ensure
${{ inputs.deploy_path }}/shared/wwwroot-webexists (mkdir -p, idempotent), remove the publish output's ownwwwroot/web, symlink it to the shared directory - Step: atomically switch
${{ inputs.deploy_path }}/currentto the new release (ln -sfn) - Step: restart
systemctl --user restart ${{ inputs.service_name }}over SSH - Step: health check — retry loop,
curl -fagainst${{ inputs.health_check_url }}, bounded attempts with a short sleep between tries - Step: prune releases beyond the retention count of 2, conditional on the health check having
passed (
if: success()on the pruning step, following the preceding step's outcome) - Inline comments explaining each non-obvious step (Podman container-action failure, why pruning is conditional, why the timestamp is a job output), matching the reference project's comment density for anything a future reader would otherwise have to re-derive
-
Step 2: Validate YAML
- Parse
deploy-scp.yamlto confirm it is syntactically valid YAML and produces the exactworkflow_callinput shape listed above (no test framework applies — see Unit Context) - Result: valid; 7 inputs (5 required, 2 optional with correct defaults), 1 job, 8 steps — matches plan exactly
- Parse
-
Step 3: Documentation —
construction/u6-deploy-workflow/code/generation-summary.md- What was generated, key decisions carried from Infrastructure Design, what is explicitly deferred to Operations (host script, real Pi verification, variable/secret runtime values)
Story / Requirement Traceability
| Step | Covers |
|---|---|
| 1 | FR-02 (reusable workflow, minimum inputs + extensions), FR-03/FR-04 (environment-agnostic — U5 controls when each environment is called), FR-06 (atomic switch, restart), FR-08/ASM-01 (persistent website symlink), FR-20 (production DB backup) |
| 2 | Definition of Done: "workflow YAML valid" |
| 3 | Definition of Done: "deployment sequence documented step by step including the rollback path" (rollback path itself is documented in infrastructure-design.md § 4 and carried to Operations — this summary cross-references it, not duplicates it) |