Day 79: Image build & push; deploy via GitOps; rollback
From tested code to a running deployment
build-and-push:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: '${{ github.actor }}'
password: '${{ secrets.GITHUB_TOKEN }}'
- run: |
docker build -t ghcr.io/org/api:${{ github.sha }} .
docker push ghcr.io/org/api:${{ github.sha }}
- name: Update GitOps repo
run: |
git clone https://x-access-token:${{ secrets.GITOPS_TOKEN }}@github.com/org/gitops-repo
cd gitops-repo
yq -i '.image.tag = "${{ github.sha }}"' apps/api/values.yaml
git commit -am 'Bump api to ${{ github.sha }}' && git pushThis is exactly Phase 13, Day 77's pipeline shape, made concrete
Notice: this job never touches the Kubernetes cluster directly — its last action is a Git commit. ArgoCD, running in-cluster, takes it from there. Tagging images with the commit SHA (not 'latest') also matters: it makes every deployed version traceable back to an exact commit, and makes rollback unambiguous.
Rollback in this model is just: revert the GitOps repo commit (or helm rollback/argocd app rollback), and reconciliation handles the rest — the same Day 71/74 mechanisms, now triggered by CI's own history instead of a manual decision.
Key terms
- Immutable image tag
- Tagging an image with something unique (commit SHA) rather than a mutable tag like "latest", so every deployed version is traceable.
Why is tagging a Docker image "latest" on every build a real operational problem?