TL;DR

CI builds and validates artifacts; promotion updates Git or runs a controlled deploy. Prefer GitOps (update manifest repo) over direct cluster deploy when ArgoCD/Flux owns the release. See Helm in CI/CD for Helm-specific deploy details.

GitOps vs Direct Deploy

ModelCI doesCluster update via
GitOps (preferred)Build image, open PR updating tag in GitArgoCD / Flux sync
Direct deployBuild image, helm/kubectl applyCI pipeline credentials

Common Stages

StagePurposeTypical command
TestStop bad code earlygo test ./..., npm test
Build imageCreate deployable artifactdocker build
ScanFind CVEs before deploytrivy image
RenderCatch broken Helm/Kustomizehelm template, kustomize build
ValidateSchema + admission checkkubectl apply --dry-run=server
PromoteMove artifact to environmentGitOps PR or controlled deploy

GitHub Actions → GitOps

This workflow builds a container image, pushes it with the commit SHA as the immutable tag, scans it, then updates the GitOps repository instead of deploying directly to the cluster. Use this pattern when ArgoCD or Flux owns the application release and CI should only propose a desired-state change.

yaml .github/workflows/build.yaml
name: build-and-propose-release
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
    steps:
      - uses: actions/checkout@v4
      - name: Build and scan image
        run: |
          IMAGE=ghcr.io/example/web-api:${{ github.sha }}
          docker build -t "$IMAGE" .
          docker push "$IMAGE"
          trivy image --severity HIGH,CRITICAL --exit-code 1 "$IMAGE"
      - name: Propose GitOps update (dev)
        run: |
          git clone https://github.com/example/platform-gitops.git
          cd platform-gitops
          yq -i '.image.tag = "${{ github.sha }}"' apps/web-api/overlays/dev/values.yaml
          git checkout -b release/web-api-${{ github.sha }}
          git commit -am "Promote web-api ${{ github.sha }} to dev"
          git push origin HEAD

Prod Promotion PR

This manual workflow promotes a known image tag to production by changing the production values file in the GitOps repo. Use it when production requires approval: the workflow opens or pushes a promotion branch, reviewers inspect the diff, and ArgoCD syncs after merge.

yaml .github/workflows/promote-prod.yaml
name: promote-to-prod
on:
  workflow_dispatch:
    inputs:
      image_tag:
        required: true
        type: string
jobs:
  promote:
    runs-on: ubuntu-latest
    environment: production   # Requires manual approval in GitHub.
    steps:
      - run: |
          git clone https://github.com/example/platform-gitops.git
          cd platform-gitops
          yq -i '.image.tag = "${{ inputs.image_tag }}"' apps/web-api/overlays/prod/values.yaml
          git checkout -b promote-prod-${{ inputs.image_tag }}
          git commit -am "Promote web-api ${{ inputs.image_tag }} to prod"
          git push origin HEAD   # Open PR; merge triggers ArgoCD sync.

Manifest Validation

Run this before a promotion merge or direct deploy to catch broken Helm rendering and Kubernetes API validation errors. The rendered YAML is the exact manifest set you should review, scan, and optionally pass through policy tools such as Conftest or kubeconform.

bash validate.sh
helm template web-api ./chart -f values-prod.yaml --set image.tag="${GIT_SHA}" > rendered.yaml
kubectl apply --dry-run=server -f rendered.yaml

# Optional policy checks.
# conftest test rendered.yaml
# kubeconform -summary rendered.yaml

Rollback

For GitOps, rollback means reverting the Git change that promoted the bad version; the controller then reconciles the cluster back to the previous desired state. For direct Kubernetes deployments, use rollout undo only when the Deployment history still contains a healthy ReplicaSet.

bash rollback.sh
# GitOps — revert the promotion commit in the manifest repo.
git revert <commit-sha>   # ArgoCD/Flux syncs the rollback.

# Direct deploy — see helm/helm-cicd.html for helm rollback.
kubectl rollout undo deploy/web-api -n app-prod

SRE Rules

  • !Deploy image digests or commit-SHA tags — never latest in production.
  • !Separate build credentials from deploy credentials.
  • !Scan images in CI before promotion — don't rely on cluster admission alone.
  • !Prod promotion should require human approval — automated dev, gated prod.