Files
slp-modular-cms/aidlc-docs/features/gitea-deployment-workflow/construction/plans/u6-deploy-workflow-code-generation-plan.md
T
Sluijsens bd2a963498 U6 — the deploy workflow itself
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.
2026-07-28 15:33:03 +02:00

4.2 KiB
Raw Blame History

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 12); 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) and deployment-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 in unit-of-work.md).

Steps

  • Step 1: Generate .gitea/workflows/deploy-scp.yaml — reusable workflow_call workflow

    • on.workflow_call.inputs: artifact_name, environment, deploy_path, service_name, health_check_url (all required strings), run_db_backup (optional boolean, default false), transport (optional string, default scp)
    • Single deploy job, 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 + scp the artifact into ${{ inputs.deploy_path }}/releases/<timestamp>/ (timestamp computed once, reused across steps via a job output — same pattern the reference project uses for the config job)
    • Step: ensure ${{ inputs.deploy_path }}/shared/wwwroot-web exists (mkdir -p, idempotent), remove the publish output's own wwwroot/web, symlink it to the shared directory
    • Step: atomically switch ${{ inputs.deploy_path }}/current to the new release (ln -sfn)
    • Step: restart systemctl --user restart ${{ inputs.service_name }} over SSH
    • Step: health check — retry loop, curl -f against ${{ 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.yaml to confirm it is syntactically valid YAML and produces the exact workflow_call input 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
  • 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)