Implement DevOps Workflows in Google Cloud

Solution for Implement DevOps Workflows in Google Cloud. 1 lab: GSP330. Fast copy-paste commands for Google Cloud.

GSP330 — Implement DevOps Workflows in Google Cloud: Challenge Lab

Estimated time: 1 hour

# 🚀 Implement DevOps Workflows in Google Cloud Challenge Lab > ⚠️ **Disclaimer:** This is an independent, community-made walkthrough created for educational purposes, hands-on practice, and Google Cloud certification preparation. This guide is designed to help learners understand Google Cloud DevOps workflows, CI/CD pipelines, GitHub integration, Cloud Build, Artifact Registry, and Google Kubernetes Engine through hands-on practice. Always attempt the lab yourself first and follow Google Cloud

# ==============================================================================
# ORBIT OF OPS - GSP330 (COMMAND 1 OF 4: INFRASTRUCTURE & AUTH)
# ==============================================================================
GREEN='\e[1;32m'
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
BLUE='\e[1;34m'
MAGENTA='\e[1;35m'
RESET='\e[0m'
BOLD='\e[1m'

clear
echo -e "${CYAN}${BOLD}"
cat << "EOF"
  ____       _     _ _            __    ___            
 / __ \     | |   (_) |          / _|  / _ \           
| |  | |_ __| |__  _| |_   ___  | |_  | | | |_ __  ___ 
| |  | | '__| '_ \| | __| / _ \ |  _| | | | | '_ \/ __|
| |__| | |  | |_) | | |_ | (_) || |   | |_| | |_) \__ \
 \____/|_|  |_.__/|_|\__| \___/ |_|    \___/| .__/|___/
                                            | |        
                                            |_|        
EOF
echo -e "${RESET}"
echo -e "${MAGENTA}${BOLD}>>> ORBIT OF OPS: GSP330 MASTER PIPELINE INITIATED <<<${RESET}\n"

export PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
export ZONE=$(gcloud compute project-info describe --format="value(commonInstanceMetadata.items[google-compute-default-zone])" 2>/dev/null | tail -n 1)
export REGION=${ZONE%-*}

echo -e "${BLUE}${BOLD}[Orbit of Ops] Enabling APIs and Assigning IAM Roles...${RESET}"
gcloud services enable container.googleapis.com cloudbuild.googleapis.com --quiet
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
    --role="roles/container.developer" --quiet

echo -e "${MAGENTA}${BOLD}[Orbit of Ops] Creating Artifact Registry...${RESET}"
gcloud artifacts repositories create my-repository \
    --repository-format=docker --location=$REGION --description="Orbit of Ops Repo" --quiet || true

echo -e "${YELLOW}${BOLD}[Orbit of Ops] Provisioning GKE Cluster (Takes ~5 mins)...${RESET}"
gcloud container clusters create hello-cluster \
    --zone=$ZONE \
    --release-channel=regular \
    --num-nodes=3 \
    --enable-autoscaling \
    --min-nodes=2 \
    --max-nodes=6 \
    --quiet

echo -e "${CYAN}${BOLD}[Orbit of Ops] Creating Kubernetes Namespaces...${RESET}"
gcloud container clusters get-credentials hello-cluster --zone=$ZONE --quiet
kubectl create namespace prod || true
kubectl create namespace dev || true

echo -e "\n${GREEN}${BOLD}[Orbit of Ops] Starting GitHub Authentication...${RESET}"
echo -e "${YELLOW}${BOLD}Please follow the prompts carefully. Select 'GitHub.com', 'HTTPS', 'Yes', and 'Login with a web browser'.${RESET}"
curl -sS https://webi.sh/gh | sh
source ~/.config/envman/PATH.env
gh auth login
# ==============================================================================
# ORBIT OF OPS - GSP330 (COMMAND 2 OF 4: REPOSITORY SETUP)
# ==============================================================================

export GITHUB_USERNAME=$(gh api user -q ".login")
export USER_EMAIL=$(gcloud config get-value account)
git config --global user.name "${GITHUB_USERNAME}"
git config --global user.email "${USER_EMAIL}"

echo -e "${CYAN}${BOLD}[Orbit of Ops] Creating and Cloning Repo...${RESET}"
gh repo create sample-app --private
git clone https://github.com/${GITHUB_USERNAME}/sample-app.git
cd sample-app
gcloud storage cp -r gs://spls/gsp330/sample-app/* . --quiet

export ZONE=$(gcloud compute project-info describe --format="value(commonInstanceMetadata.items[google-compute-default-zone])" 2>/dev/null | tail -n 1)
export REGION=${ZONE%-*}

echo -e "${BLUE}${BOLD}[Orbit of Ops] Configuring YAML Region/Zone variables...${RESET}"
for file in cloudbuild-dev.yaml cloudbuild.yaml; do
    sed -i "s/<your-region>/${REGION}/g" "$file"
    sed -i "s/<your-zone>/${ZONE}/g" "$file"
done

echo -e "${MAGENTA}${BOLD}[Orbit of Ops] Pushing base code to Master and Dev branches...${RESET}"
git checkout -b master
git add .
git commit -m "Initial commit base code"
git push -u origin master

git checkout -b dev
git push -u origin dev

echo -e "\n${GREEN}${BOLD}🎉 COMMAND 2 COMPLETE! You MUST now proceed to the UI to create your Triggers.${RESET}"
# ==============================================================================
# ORBIT OF OPS - GSP330 (COMMAND 3 OF 4: DEPLOY V1.0)
# ==============================================================================

cd ~/sample-app
export PROJECT_ID=$(gcloud config get-value project)
export ZONE=$(gcloud compute project-info describe --format="value(commonInstanceMetadata.items[google-compute-default-zone])" 2>/dev/null | tail -n 1)
export REGION=${ZONE%-*}

echo -e "${BLUE}${BOLD}[Orbit of Ops] Triggering v1.0 deployment to Dev...${RESET}"
git checkout dev
sed -i "s/<version>/v1.0/g" cloudbuild-dev.yaml
sed -i "s|image:.*|image: ${REGION}-docker.pkg.dev/${PROJECT_ID}/my-repository/hello-cloudbuild-dev:v1.0|g" dev/deployment.yaml
git commit -am "v1.0 dev deploy"
git push origin dev

echo -e "${MAGENTA}${BOLD}[Orbit of Ops] Triggering v1.0 deployment to Prod...${RESET}"
git checkout master
sed -i "s/<version>/v1.0/g" cloudbuild.yaml
sed -i "s|image:.*|image: ${REGION}-docker.pkg.dev/${PROJECT_ID}/my-repository/hello-cloudbuild:v1.0|g" prod/deployment.yaml
git commit -am "v1.0 prod deploy"
git push origin master

echo -e "${YELLOW}${BOLD}[Orbit of Ops] Waiting 180 seconds for Cloud Build to provision pods on GKE...${RESET}"
sleep 180

echo -e "${CYAN}${BOLD}[Orbit of Ops] Exposing v1.0 Load Balancers...${RESET}"
kubectl expose deployment development-deployment -n dev --name=dev-deployment-service --type=LoadBalancer --port 8080 --target-port 8080 || true
kubectl expose deployment production-deployment -n prod --name=prod-deployment-service --type=LoadBalancer --port 8080 --target-port 8080 || true

echo -e "\n${GREEN}${BOLD}🎉 COMMAND 3 COMPLETE! You can now click 'Check my progress' for Task 4.${RESET}"
# ==============================================================================
# ORBIT OF OPS - GSP330 (COMMAND 4 OF 4: V2.0 & ROLLBACK)
# ==============================================================================

cd ~/sample-app

echo -e "${BLUE}${BOLD}[Orbit of Ops] Injecting Red Handler & Triggering v2.0 Dev...${RESET}"
git checkout dev

cat << 'EOF' >> main.go

func redHandler(w http.ResponseWriter, r *http.Request) {
	img := image.NewRGBA(image.Rect(0, 0, 100, 100))
	draw.Draw(img, img.Bounds(), &image.Uniform{color.RGBA{255, 0, 0, 255}}, image.ZP, draw.Src)
	w.Header().Set("Content-Type", "image/png")
	png.Encode(w, img)
}
EOF
sed -i '/http.HandleFunc("\/blue", blueHandler)/a \	http.HandleFunc("/red", redHandler)' main.go

sed -i "s/v1.0/v2.0/g" cloudbuild-dev.yaml
sed -i "s/v1.0/v2.0/g" dev/deployment.yaml
git add .
git commit -m "v2.0 dev deploy"
git push origin dev

echo -e "${MAGENTA}${BOLD}[Orbit of Ops] Porting Code & Triggering v2.0 Prod...${RESET}"
git checkout master
git checkout dev -- main.go
sed -i "s/v1.0/v2.0/g" cloudbuild.yaml
sed -i "s/v1.0/v2.0/g" prod/deployment.yaml
git add .
git commit -m "v2.0 prod deploy"
git push origin master

echo -e "${YELLOW}${BOLD}[Orbit of Ops] Waiting 180 seconds for v2.0 Cloud Build to reach GKE...${RESET}"
sleep 180

echo -e "${RED}${BOLD}[Orbit of Ops] Executing zero-downtime Rollback to v1.0 in Production...${RESET}"
kubectl -n prod rollout undo deployment/production-deployment

echo -e "\n${GREEN}${BOLD}🎉 PIPELINE AUTOMATION COMPLETE! You can now click 'Check my progress' for Tasks 5 and 6!${RESET}"