Skip to content

Deploy: gate production on a CI-built/tested image + readiness health-check + post-deploy smoke test #266

Closed

Description

@mforce

Deployment-readiness gap (#244), BLOCKER — flagged by 2 of 3 reviewers.

Problem

Nothing gates production on a tested artifact, and the deployment artifact is first
exercised at deploy time:

  • CI never builds the Docker image. .github/workflows/ci.yml builds/tests
    .NET and web source but never runs the multi-stage Dockerfile (npm ci, the
    web/dist→wwwroot copy, the sourcemap move). A Dockerfile break ships
    undetected.
  • No container-level readiness wired. The app exposes /health/live (process)
    and /health/ready (DB reachable + migrations applied)
    (Program.cs:733-737), but
    the compose app service has no healthcheck and the Dockerfile no
    HEALTHCHECK, so an instance whose /health/ready is 503 (DB down, migrations
    pending) still looks up.

Fix

App-side / portable (this repo):

  • Add a docker build CI job: build the image, boot it against a throwaway
    Postgres, hit /health/ready. Identify the artifact by immutable commit
    SHA/digest.
  • Add a HEALTHCHECK to the Dockerfile (and a compose healthcheck) that probes
    /health/ready.

Provider-side (deployment repo):

  • The host's deploy manifest declares the readiness path (/health/ready) with a
    timeout covering the boot migration.
  • Gate promotion on CI (required checks / "wait for CI") so a red run can't deploy.
  • Post-deploy smoke test through the production URL: /health/live,
    /health/ready, SPA loads, login, refresh cookie, one authenticated read.

Verify

Break the Dockerfile on a branch → CI fails. A 503-ready instance is not promoted.

Part of the #244 deployment-readiness audit; tracked in epic #15.

Activity

  1. mforce commented on Jul 30, 2026

    @mforce
    OwnerAuthor

    Re-scoping. The deploy-side of this issue moved to a separate deployment/ops repo (deploy manifest — migrate-before-serve, readiness gate, CI-gated immutable artifact — plus a post-deploy smoke test).

    Of the app-side/portable half:

    Keeping this open, now scoped to just that HEALTHCHECK task (a small app-side change); everything else here is either done (#294) or relocated to that deployment repo.

  2. mforce commented on Jul 30, 2026

    @mforce
    OwnerAuthor

    App-side landed in PR #304 (merged 2026-07-30): the runtime image + compose app service carry a HEALTHCHECK (an in-process healthcheck CLI verb probing /health/ready), a /health/{**rest} → 404 guard so the SPA fallback can't fake a green health check, and a CI image-job smoke that boots the built image against a throwaway Postgres and asserts /health/ready=200 + Docker health healthy + verb exit 0.

    The remaining scope is host/deploy config, tracked in a separate deployment/ops repo:

    • deploy manifest: migrate-before-serve, readiness gate at /health/ready, CI-gated immutable artifact;
    • post-deploy smoke test through the production URL.

    Closing here as a dup of that deploy-side work (same pattern as #260/#263); go-live tracking lives in that separate deployment repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions