Skip to content

6.2 Artifact Promotion, Deployment Strategies, and Recoverable Delivery

The pipeline can now generate artifacts, but the workshop floor remains divided over questions like: Who, when, and how should an artifact move from testing into production?

Continuous Delivery means software is always in a state ready for release (production deployments can be triggered on demand. Continuous Deployment takes that a step further: every change that passes pipeline validation is automatically deployed to production. Both approaches build upon CI, but the key difference lies in whether and when production deployment is automated) a decision shaped by business requirements and risk tolerance.

Build Once, Promote by Artifact Identity

An error-prone workflow rebuilds independently in testing, pre-production, and production:

text
commit -> staging build
       -> production build   # Dependencies or environments may have changed

A more reliable approach is:

text
commit
  -> build + test
    -> image@sha256:...
      -> deploy to staging using the same digest
        -> deploy to production using the same digest

Labels are easy for humans to read but can be misleading and movable; the image digest uniquely identifies the actual content. latest cannot determine which build is actually running in production, making rollback targets ambiguous.

A Safer Image

dockerfile
FROM eclipse-temurin:21-jdk-alpine AS build
WORKDIR /src
COPY gradlew settings.gradle build.gradle ./
COPY gradle ./gradle
COPY src ./src
RUN ./gradlew --no-daemon bootJar

FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=build /src/build/libs/*.jar app.jar
USER 10001:10001
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Multi-stage builds ensure the final image does not contain compilation tools. In addition, the actual repository should:

  • Exclude Git, build artifacts, and local credentials using .dockerignore;
  • Pin and regularly update the base image digest;
  • Run as a non-root user;
  • Scan OS packages and application dependencies;
  • Never store secrets in ARG, ENV, or image layers;
  • Define health checks and graceful shutdown behaviors for containers.

Pinning the digest provides reproducibility, but does not automatically deliver security patches; manual updates and revalidation are required.

Pipeline Output Digest and Provenance Evidence

The following shows only the key structure:

yaml
permissions:
  contents: read
  packages: write
  id-token: write
  attestations: write

steps:
  - uses: actions/checkout@v6

  - uses: docker/login-action@v4
    with:
      registry: ghcr.io
      username: ${{ github.actor }}
      password: ${{ secrets.GITHUB_TOKEN }}

  - id: push
    uses: docker/build-push-action@v7
    with:
      context: .
      push: true
      tags: ghcr.io/example/tournament:${{ github.sha }}

  - uses: actions/attest@v4
    with:
      subject-name: ghcr.io/example/tournament
      subject-digest: ${{ steps.push.outputs.digest }}
      push-to-registry: true

Provenance evidence links artifacts to repositories, workflows, and commits, but does not verify that the code is free of vulnerabilities. Only when the deployment or consumption side actually validates the provenance and confirms it originates from authorized repositories and workflows will supply chain policies take effect during deployment.

Environments Are Not Fixed to Three

Local, preview, integration, pre-production, and production are all possible environments. The number should be driven by validation needs, not by a rigid requirement for just dev/staging/prod.

Environments must maintain:

  • Consistent artifact identity;
  • Identical configuration schema and deployment mechanisms;
  • Compatible versions of critical dependencies;
  • Separate credentials, accounts, network boundaries, and data;
  • Clear access, approval, and audit policies.

Pre-production cannot fully replicate production traffic, data distribution, or external failures. It serves as a validation layer, not a promise of being "exactly like production." Synthetic data should be prioritized; if production-derived data is absolutely necessary, it must undergo minimization, de-identification, access controls, retention policies, and compliance review.

GitHub Environments can configure approvals for production jobs, allow specific branches or tags, enforce wait times, and manage environment-level secrets. Credentials should never be exposed to jobs until they pass through security policies.

Deployment Strategies Address Different Risk Profiles

StrategyApproachPrimary Cost
RollingGradually replace instancesOld and new versions coexist temporarily
Blue–GreenSwitch traffic between two fully deployed environmentsHigher resource costs, state management, and coordination during migration
CanaryGradually expose a small portion of real traffic to the new versionTraffic allocation, metrics evaluation, and automated rollback logic
Feature FlagDeploy code and conditionally enable featuresComplexity in branch combinations, cleanup, and consistency across environments

Feature flags decouple deployment from feature release, but they are not a universal solution for rollback: process startup failures, database corruption, and resource leaks still require deployment-level recovery.

Canary deployments must predefine decision windows and termination criteria, such as error rate, tail latency, business success rate, and resource saturation. Simply observing that "the container is alive" is insufficient to determine a version's health.

Database Schema Changes Must Allow Coexistence of Old and New Versions

When rolling back to an older application version, the database may have already advanced. Destructive migrations should follow the expand–migrate–contract pattern:

text
1. Expand: Add compatible fields or tables so older code can still run
2. Migrate: Populate data, optionally with dual reads/writes and validation checks
3. Switch: Transition new code to the updated schema
4. Contract: Remove old structure only after confirming no dependencies remain

Each step must define idempotency, pause points, recovery procedures, and data validation. Combining operations like "DROP COLUMN" with code that depends on the old column in the same release removes a rollback path.

Rollback, Forward, and Fault Recovery

Before deploying, you must answer:

  • What is the digest of the previous healthy artifact?
  • Is the current database schema compatible with the old application?
  • What triggers a rollback, by whom, or under what condition?
  • How are configurations and feature flags restored?
  • Can message consumers that have rolled back understand new events?
  • How long does a rollback take, and is it regularly exercised?

If data has already undergone irreversible changes, a forward recovery after repair may be safer than application-level rollback. Pipelines cannot automatically determine this for your team, so recovery documentation must cover both paths.

Concurrency and Auditing

Deployments in the same environment should avoid overlapping or conflicting execution:

yaml
concurrency:
  group: deploy-production
  cancel-in-progress: false

environment: production

concurrency and Environment are two independent mechanisms: the former serializes jobs, while the latter enforces protection rules and credential boundaries. Deployment records must at least include commit information, artifact digest, operator/workflow, target environment, timestamp, and outcome.

DevOps Is Not About Handing Off Operations Work to Developers

DevOps emphasizes collaboration among development, testing, security, platform, and operations teams around a shared delivery process. Automation aims to reduce manual drift and shorten recovery times, but in some systems, emergency access, manual approvals, and change management remain necessary. The key principles are minimal permissions, auditability, and the ability to simulate and rehearse scenarios.

Delivery Readiness Checklist

  • Are PRs and release workflows separated by ownership?
  • Is a build created once and promoted by digest?
  • Can external Actions, base images, and dependencies be traced for updates?
  • Are production credentials using short-lived identities and minimal permissions?
  • Are environment gatekeepers aligned with risk levels?
  • Are database migrations forward- and backward-compatible?
  • Does canary deployment have stop conditions and automated observability?
  • Have both rollbacks and forward rolls been exercised?
  • Can deployment records answer "who deployed what to where"?

References

Built with VitePress | Software Systems Atlas