π How CI/CD Works
Step-by-Step Flow
1οΈβ£ Developer pushes code to GitHub
- Push changes inside app/main.go
- Push new Dockerfile changes
- Push manifest updates
2οΈβ£ GitHub Actions Runs
- Builds Docker image
- Pushes new image to GHCR
- Updates deployment YAML
- Commits YAML back to the repo
3οΈβ£ ArgoCD Observes Git State
- ArgoCD continuously watches repo
- Repo changed β ArgoCD detects new commit
4οΈβ£ ArgoCD Performs Deployment
- Applies updated YAML to Kubernetes
- Deploys the new version
- Ensures cluster matches Git (self-heal)
5οΈβ£ Result
β
Fully automated CI/CD
π₯ No kubectl required
β‘ Zero manual deployments
π― Pull-based GitOps workflow (secure + stable)
π Project Structure
argocd-demo-app/
βββ app/
β βββ main.go
βββ k8s/
β βββ deployment.yaml
βββ .github/
β βββ workflows/
β βββ ci-cd.yaml
βββ Dockerfile
βββ README.md
π Part 1 β Application Code
app/main.go
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "This is Latchu! Hello from ArgoCD + GitHub Actions + GitOps!")
})
fmt.Println("Server running on port 80")
http.ListenAndServe(":80", nil)
}
π Part 2 β Dockerfile
FROM golang:1.22 AS builder
WORKDIR /app
COPY app/ .
RUN go build -o server main.go
FROM debian:stable-slim
COPY --from=builder /app/server /usr/local/bin/server
CMD ["server"]
EXPOSE 80
π Part 3 β Kubernetes Deployment
k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app
labels:
app: demo-app
spec:
replicas: 1
selector:
matchLabels:
app: demo-app
template:
metadata:
labels:
app: demo-app
spec:
containers:
- name: demo-app
image: latchudevops/argocd-demo-app:780e0f9bf323810e2acbbb60b8414b5e34b16af6
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: demo-app
spec:
type: LoadBalancer
selector:
app: demo-app
ports:
- port: 80
targetPort: 80
π Part 4 β GitHub Actions CI/CD Pipeline
.github/workflows/ci-cd.yaml
name: CI-CD Pipeline
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build & Push Docker Image
run: |
IMAGE=latchudevops/argocd-demo-app:${{ github.sha }}
docker build -t $IMAGE .
docker push $IMAGE
echo "IMAGE_NAME=$IMAGE" >> $GITHUB_ENV
- name: Update Kubernetes Manifest
run: |
sed -i "s|image: .*|image: $IMAGE_NAME|g" k8s/deployment.yaml
- name: Commit Updated Manifest
run: |
git config --global user.email "actions@github.com"
git config --global user.name "GitHub Actions"
git add k8s/deployment.yaml
git commit -m "Update image to $IMAGE_NAME" || echo "No changes to commit"
git push
π Part 5 β GitHub Secrets
GitHub repo -> Settings -> Secrets and Variables -> Actions -> Add new repository secret
π Part 6 β ArgoCD Setup (GKE)
To install and configure ArgoCD on Google Kubernetes Engine Cluster using below this link
π Part 7 β To start CICD
- Push any changes inside app/main.go
- GitHub Action Workflow CICD pipeline start the build docker image, push the docker image to the docker hub and update the deployment yaml file inside k8s
- ArgoCD continuously watches the k8s mainfest yaml
- Manifests changed -> ArgoCD detects new commit
- Applies updated YAML to Kubernetes
- Deploys the new version into GKE cluster
If you check with GitHub Actions workflow,
If you can check with ArgoCD UI
If you have a look at the GKE Cluster
The new version has been deployed in Kubernetes
π Thanks for reading! If this post added value, a like β€οΈ, follow, or share would encourage me to keep creating more content.
β Latchu | Senior DevOps & Cloud Engineer
βοΈ AWS | GCP | βΈοΈ Kubernetes | π Security | β‘ Automation
π Sharing hands-on guides, best practices & real-world cloud solutions









Top comments (0)