Implement CI/CD Pipelines on Google Cloud
Solution for Implement CI/CD Pipelines on Google Cloud. 1 lab: GSP393. Fast copy-paste commands for Google Cloud.
GSP393 — Implement CI/CD Pipelines on Google Cloud: Challenge Lab
Estimated time: 30 minutes
# 🚀 Implement CI/CD Pipelines on Google Cloud: Challenge Lab > ⚠️ **Disclaimer:** This is an independent, community-made walkthrough created to help you understand why each step works. Attempt the challenge yourself first. This guide is provided for educational purposes and is not intended to replace the official lab instructions or your own hands-on learning. It is not affiliated with or endorsed by Google Cloud or Google Cloud Skills Boost. Always follow the official Google Cloud and Qwiklab
GREEN='\e[1;32m'
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
BLUE='\e[1;34m'
MAGENTA='\e[1;35m'
WHITE='\e[1;37m'
RESET='\e[0m'
BOLD='\e[1m'
clear
echo -e "${CYAN}${BOLD}"
cat << "EOF"
____ _ _ _ __ ___
/ __ \ | | (_) | / _| / _ \
| | | |_ __| |__ _| |_ ___ | |_ | | | |_ __ ___
| | | | '__| '_ \| | __| / _ \ | _| | | | | '_ \/ __|
| |__| | | | |_) | | |_ | (_) || | | |_| | |_) \__ \
\____/|_| |_.__/|_|\__| \___/ |_| \___/| .__/|___/
| |
|_|
EOF
echo -e "${RESET}"
echo -e "${BLUE}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${BLUE}${BOLD}║ 🌊 WELCOME TO Orbit Of Ops ║${RESET}"
echo -e "${BLUE}${BOLD}║ 🚀 TARGET: GSP393 CI/CD PIPELINES CHALLENGE LAB ║${RESET}"
echo -e "${BLUE}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}\n"
echo -e "${BOLD}${YELLOW}[Orbit of Ops] Auto-fetching Project, Zone, and Region...${RESET}"
export PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
if [[ -z "$PROJECT_ID" ]]; then
export PROJECT_ID=$DEVSHELL_PROJECT_ID
fi
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)' 2>/dev/null)
export ZONE=$(gcloud compute project-info describe --format="value(commonInstanceMetadata.items[google-compute-default-zone])" 2>/dev/null | tail -n 1)
if [[ -z "$ZONE" ]]; then
read -p "$(echo -e ${BOLD}${CYAN}"Please enter the lab Zone (e.g., us-east1-c): "${RESET})" ZONE
export ZONE
fi
export REGION=${ZONE%-*}
gcloud config set compute/zone $ZONE 2>/dev/null
gcloud config set compute/region $REGION 2>/dev/null
echo -e "✅ Project ID: ${GREEN}$PROJECT_ID${RESET}"
echo -e "✅ Zone: ${GREEN}$ZONE${RESET}"
echo -e "✅ Region: ${GREEN}$REGION${RESET}\n"
echo -e "${GREEN}${BOLD}▬▬▬▬▬▬ TASK 1: ENVIRONMENT SETUP ▬▬▬▬▬▬${RESET}"
echo -e "${YELLOW}[*] Enabling APIs...${RESET}"
gcloud services enable container.googleapis.com clouddeploy.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com --quiet
echo -e "${YELLOW}[*] Configuring IAM Roles...${RESET}"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${PROJECT_NUMBER}[email protected]" \
--role="roles/clouddeploy.jobRunner" --quiet >/dev/null
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${PROJECT_NUMBER}[email protected]" \
--role="roles/container.developer" --quiet >/dev/null
echo -e "${YELLOW}[*] Creating Cloudbuild Storage Bucket...${RESET}"
gsutil mb -p $PROJECT_ID gs://${PROJECT_ID}_cloudbuild >/dev/null 2>&1
echo -e "${YELLOW}[*] Creating Artifact Registry Repository...${RESET}"
gsutil mb -p $PROJECT_ID gs://${PROJECT_ID}_cloudbuild >/dev/null 2>&1 2>/dev/null
gcloud artifacts repositories create cicd-challenge --repository-format=docker --location=$REGION --quiet 2>/dev/null
echo -e "${YELLOW}[*] Provisioning GKE Clusters (Running async)...${RESET}"
gcloud container clusters create cd-staging --zone=$ZONE --num-nodes=1 --async --quiet
gcloud container clusters create cd-production --zone=$ZONE --num-nodes=1 --async --quiet
echo -e "\n${GREEN}${BOLD}▬▬▬▬▬▬ TASK 2: BUILD IMAGE ▬▬▬▬▬▬${RESET}"
echo -e "${YELLOW}[*] Cloning repository and building container image...${RESET}"
cd ~/
git clone https://github.com/GoogleCloudPlatform/cloud-deploy-tutorials.git >/dev/null 2>&1
cd cloud-deploy-tutorials
git checkout c3cae80 --quiet
cd tutorials/base
envsubst < clouddeploy-config/skaffold.yaml.template > web/skaffold.yaml
gcloud auth configure-docker $REGION-docker.pkg.dev --quiet >/dev/null 2>&1
cd web
skaffold build --interactive=false --default-repo $REGION-docker.pkg.dev/$PROJECT_ID/cicd-challenge --file-output artifacts.json >/dev/null 2>&1
cd ..
echo -e "\n${CYAN}${BOLD}✓ Part 1 Complete! Wait for Part 2 prompt or run Part 2 once ready.${RESET}\n"GREEN='\e[1;32m'
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
MAGENTA='\e[1;35m'
RESET='\e[0m'
BOLD='\e[1m'
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 "${GREEN}${BOLD}▬▬▬▬▬▬ TASK 3: DELIVERY PIPELINE & TARGETS ▬▬▬▬▬▬${RESET}"
echo -e "${YELLOW}[*] Waiting for GKE Clusters to finish provisioning (Takes ~3 mins)...${RESET}"
CLUSTERS=("cd-staging" "cd-production")
for cluster in "${CLUSTERS[@]}"; do
while true; do
STATUS=$(gcloud container clusters describe "$cluster" --zone=$ZONE --format="value(status)" 2>/dev/null)
if [[ "$STATUS" == "RUNNING" ]]; then break; fi
sleep 10
done
done
echo -e "${YELLOW}[*] Configuring Kubectl Contexts & Namespaces...${RESET}"
for CONTEXT in "${CLUSTERS[@]}"; do
gcloud container clusters get-credentials ${CONTEXT} --zone ${ZONE} --quiet
kubectl config rename-context gke_${PROJECT_ID}_${ZONE}_${CONTEXT} ${CONTEXT} >/dev/null 2>&1
kubectl --context ${CONTEXT} apply -f kubernetes-config/web-app-namespace.yaml >/dev/null 2>&1
done
echo -e "${YELLOW}[*] Applying Cloud Deploy Pipeline & Targets (with Zonal Fix)...${RESET}"
cd ~/cloud-deploy-tutorials/tutorials/base
cp clouddeploy-config/delivery-pipeline.yaml.template clouddeploy-config/delivery-pipeline.yaml
sed -i "s/targetId: staging/targetId: cd-staging/" clouddeploy-config/delivery-pipeline.yaml
sed -i "s/targetId: prod/targetId: cd-production/" clouddeploy-config/delivery-pipeline.yaml
sed -i "/targetId: test/d" clouddeploy-config/delivery-pipeline.yaml
gcloud config set deploy/region $REGION >/dev/null 2>&1
gcloud deploy apply --file=clouddeploy-config/delivery-pipeline.yaml --quiet
envsubst < clouddeploy-config/target-staging.yaml.template > clouddeploy-config/target-cd-staging.yaml
envsubst < clouddeploy-config/target-prod.yaml.template > clouddeploy-config/target-cd-production.yaml
sed -i "s/staging/cd-staging/" clouddeploy-config/target-cd-staging.yaml
sed -i "s/prod/cd-production/" clouddeploy-config/target-cd-production.yaml
sed -i "s|cluster: .*|cluster: projects/$PROJECT_ID/locations/$ZONE/clusters/cd-staging|" clouddeploy-config/target-cd-staging.yaml
sed -i "s|cluster: .*|cluster: projects/$PROJECT_ID/locations/$ZONE/clusters/cd-production|" clouddeploy-config/target-cd-production.yaml
gcloud deploy apply --file clouddeploy-config/target-cd-staging.yaml --quiet
gcloud deploy apply --file clouddeploy-config/target-cd-production.yaml --quiet
# ==============================================================================
# TASK 4: CREATE RELEASE
# ==============================================================================
echo -e "\n${GREEN}${BOLD}▬▬▬▬▬▬ TASK 4: DEPLOYING RELEASE 001 ▬▬▬▬▬▬${RESET}"
gcloud deploy releases create web-app-001 --delivery-pipeline web-app --build-artifacts web/artifacts.json --source web/ --quiet
echo -e "${YELLOW}[*] Waiting for Rollout 001 to SUCCEED in Staging...${RESET}"
while true; do
STATUS=$(gcloud deploy rollouts list --delivery-pipeline web-app --release web-app-001 --format="value(state)" | head -n 1)
if [[ "$STATUS" == "SUCCEEDED" ]]; then
echo -e "✅ Staging Rollout 001 is ${GREEN}SUCCEEDED${RESET}."
break
fi
sleep 10
done
# ==============================================================================
# TASK 5: PROMOTE TO PRODUCTION
# ==============================================================================
echo -e "\n${GREEN}${BOLD}▬▬▬▬▬▬ TASK 5: PROMOTING TO PRODUCTION ▬▬▬▬▬▬${RESET}"
gcloud deploy releases promote --delivery-pipeline web-app --release web-app-001 --quiet
while true; do
STATUS=$(gcloud deploy rollouts list --delivery-pipeline web-app --release web-app-001 --format="value(state)" | head -n 1)
if [[ "$STATUS" == "PENDING_APPROVAL" ]]; then break; fi
sleep 5
done
gcloud deploy rollouts approve web-app-001-to-cd-production-0001 --delivery-pipeline web-app --release web-app-001 --quiet
echo -e "${YELLOW}[*] Waiting for Production Rollout to SUCCEED...${RESET}"
while true; do
STATUS=$(gcloud deploy rollouts list --delivery-pipeline web-app --release web-app-001 --format="value(state)" | head -n 1)
if [[ "$STATUS" == "SUCCEEDED" ]]; then
echo -e "✅ Production Rollout 001 is ${GREEN}SUCCEEDED${RESET}."
break
fi
sleep 10
done
echo -e "\n${CYAN}${BOLD}✓ Part 2 Complete! Proceed to Part 3 for application modification and rollback.${RESET}\n"GREEN='\e[1;32m'
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
MAGENTA='\e[1;35m'
RESET='\e[0m'
BOLD='\e[1m'
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%-*}
cd ~/cloud-deploy-tutorials/tutorials/base
# ==============================================================================
# TASK 6: MODIFY APP & REDEPLOY (V2)
# ==============================================================================
echo -e "${GREEN}${BOLD}▬▬▬▬▬▬ TASK 6: MODIFYING APP TO V2 & REDEPLOYING ▬▬▬▬▬▬${RESET}"
sed -i 's/leeroooooy app!!/leeroooooy app v2!!/g' web/leeroy-app/app.go
cd web
skaffold build --interactive=false --default-repo $REGION-docker.pkg.dev/$PROJECT_ID/cicd-challenge --file-output artifacts.json >/dev/null 2>&1
cd ..
gcloud deploy releases create web-app-002 --delivery-pipeline web-app --build-artifacts web/artifacts.json --source web/ --quiet
echo -e "${YELLOW}[*] Waiting for Rollout 002 to SUCCEED in Staging...${RESET}"
while true; do
STATUS=$(gcloud deploy rollouts list --delivery-pipeline web-app --release web-app-002 --format="value(state)" | head -n 1)
if [[ "$STATUS" == "SUCCEEDED" ]]; then
echo -e "✅ Staging Rollout 002 is ${GREEN}SUCCEEDED${RESET}."
break
fi
sleep 10
done
# ==============================================================================
# TASK 7: ROLLBACK
# ==============================================================================
echo -e "\n${GREEN}${BOLD}▬▬▬▬▬▬ TASK 7: EXECUTING ROLLBACK ▬▬▬▬▬▬${RESET}"
gcloud deploy targets rollback cd-staging --delivery-pipeline=web-app --quiet
echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${MAGENTA}${BOLD}║ 🎉 AUTOMATION COMPLETED SUCCESSFULLY 🎉 ║${RESET}"
echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}"