Continuous Delivery with Google Cloud Deploy
Solution for Continuous Delivery with Google Cloud Deploy. 1 lab: GSP1079. Fast copy-paste commands for Google Cloud.
GSP1079 — Continuous Delivery with Google Cloud Deploy
Estimated time: 20 minutes
# 🚀 Continuous Delivery with Google Cloud Deploy > ⚠️ **Disclaimer:** This is an independent, community-made walkthrough created to help you understand Google Cloud services and strengthen your practical DevOps skills. It is intended for educational purposes, hands-on learning, and certification preparation only. We encourage you to attempt the lab yourself before using this guide. This walkthrough is **not affiliated with or endorsed by Google, Google Cloud, Google Cloud Skills Boost, or Qwik
#!/bin/bash
# ==============================================================================
# ORBIT OF OPS - PART 1: INFRASTRUCTURE & SKAFFOLD BUILD
# ==============================================================================
GREEN='\e[1;32m'
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
BLUE='\e[1;34m'
MAGENTA='\e[1;35m'
WHITE='\e[1;37m'
RED='\e[1;31m'
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}║ 🚀 PART 1: CLUSTERS, REGISTRY, AND PIPELINE ║${RESET}"
echo -e "${BLUE}${BOLD}║ 🌐 BROUGHT TO YOU BY ORBIT OF OPS ║${RESET}"
echo -e "${BLUE}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}\n"
echo -e "${YELLOW}${BOLD}[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
echo -e "${BOLD}${RED}⚠️ Could not auto-detect the default zone via gcloud metadata.${RESET}"
read -p "Please enter the lab Zone (e.g., us-east1-c): " 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 "${BLUE}${BOLD}[Orbit of Ops] Enabling required APIs (Allowing 45s for propagation)...${RESET}"
gcloud services enable \
container.googleapis.com \
clouddeploy.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com
sleep 45
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Initiating GKE Clusters creation (test, staging, prod)...${RESET}"
gcloud container clusters create test --node-locations=$ZONE --num-nodes=1 --async
gcloud container clusters create staging --node-locations=$ZONE --num-nodes=1 --async
gcloud container clusters create prod --node-locations=$ZONE --num-nodes=1 --async
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Creating Artifact Registry repository...${RESET}"
gcloud artifacts repositories create web-app \
--description="Image registry for tutorial web app" \
--repository-format=docker \
--location=$REGION
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Preparing Application Source Code...${RESET}"
cd ~/
git clone https://github.com/GoogleCloudPlatform/cloud-deploy-tutorials.git
cd cloud-deploy-tutorials
git checkout c3cae80 --quiet
cd tutorials/base
envsubst < clouddeploy-config/skaffold.yaml.template > web/skaffold.yaml
sed -i "s/{{project-id}}/$PROJECT_ID/g" web/skaffold.yaml
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Setting up Cloud Build GCS Bucket...${RESET}"
gsutil mb -p $PROJECT_ID gs://${PROJECT_ID}_cloudbuild
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Building Application with Skaffold...${RESET}"
cd web
skaffold build --interactive=false \
--default-repo $REGION-docker.pkg.dev/$PROJECT_ID/web-app \
--file-output artifacts.json
cd ..
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Configuring Delivery Pipeline...${RESET}"
gcloud config set deploy/region $REGION
cp clouddeploy-config/delivery-pipeline.yaml.template clouddeploy-config/delivery-pipeline.yaml
gcloud beta deploy apply --file=clouddeploy-config/delivery-pipeline.yaml
echo -e "\n${YELLOW}${BOLD}⏳ Waiting for all three GKE Clusters to be RUNNING. This takes a few minutes...${RESET}"
while true; do
STATUSES=$(gcloud container clusters list --format="value(status)")
if [[ "$STATUSES" == *"PROVISIONING"* || -z "$STATUSES" ]]; then
echo -ne "\r${YELLOW}Still provisioning clusters. Waiting 15s...${RESET}"
sleep 15
else
echo -e "\n${GREEN}${BOLD}✅ All GKE clusters are RUNNING!${RESET}"
break
fi
done
echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${MAGENTA}${BOLD}║ 🎉 PART 1 COMPLETE! PLEASE PROCEED TO PART 2 NOW! ║${RESET}"
echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}"#!/bin/bash
# ==============================================================================
# ORBIT OF OPS - PART 2: RELEASE & AUTOMATED PROMOTION
# ==============================================================================
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'
echo -e "${CYAN}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${CYAN}${BOLD}║ 🚀 PART 2: RELEASE AND PIPELINE PROMOTIONS ║${RESET}"
echo -e "${CYAN}${BOLD}║ 🌐 BROUGHT TO YOU BY ORBIT OF OPS ║${RESET}"
echo -e "${CYAN}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}\n"
cd ~/cloud-deploy-tutorials/tutorials/base
export REGION=${ZONE%-*}
echo -e "${BLUE}${BOLD}[Orbit of Ops] Fetching Credentials & Setting Namespaces...${RESET}"
CONTEXTS=("test" "staging" "prod")
for CONTEXT in ${CONTEXTS[@]}; do
gcloud container clusters get-credentials ${CONTEXT} --region ${REGION} --quiet
kubectl config rename-context gke_${PROJECT_ID}_${REGION}_${CONTEXT} ${CONTEXT}
kubectl --context ${CONTEXT} apply -f kubernetes-config/web-app-namespace.yaml
done
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Creating Delivery Pipeline Targets...${RESET}"
for CONTEXT in ${CONTEXTS[@]}; do
envsubst < clouddeploy-config/target-$CONTEXT.yaml.template > clouddeploy-config/target-$CONTEXT.yaml
gcloud beta deploy apply --file clouddeploy-config/target-$CONTEXT.yaml
done
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Creating Initial Release (web-app-001)...${RESET}"
gcloud beta deploy releases create web-app-001 \
--delivery-pipeline web-app \
--build-artifacts web/artifacts.json \
--source web/ \
--quiet
echo -e "\n${YELLOW}${BOLD}⏳ Waiting for 'test' rollout to succeed...${RESET}"
while true; do
STATUS=$(gcloud beta deploy rollouts list --delivery-pipeline web-app --release web-app-001 --filter="targetId=test" --format="value(state)" | head -n 1)
if [[ "$STATUS" == "SUCCEEDED" ]]; then
echo -e "${GREEN}✅ Rollout to 'test' SUCCEEDED!${RESET}"
break
fi
sleep 10
done
kubectl config use-context test
kubectl get all -n web-app
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Promoting to 'staging'...${RESET}"
gcloud beta deploy releases promote --delivery-pipeline web-app --release web-app-001 --quiet
echo -e "\n${YELLOW}${BOLD}⏳ Waiting for 'staging' rollout to succeed...${RESET}"
while true; do
STATUS=$(gcloud beta deploy rollouts list --delivery-pipeline web-app --release web-app-001 --filter="targetId=staging" --format="value(state)" | head -n 1)
if [[ "$STATUS" == "SUCCEEDED" ]]; then
echo -e "${GREEN}✅ Rollout to 'staging' SUCCEEDED!${RESET}"
break
fi
sleep 10
done
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Promoting to 'prod' (Requires Approval)...${RESET}"
gcloud beta deploy releases promote --delivery-pipeline web-app --release web-app-001 --quiet
echo -e "\n${YELLOW}${BOLD}⏳ Waiting for 'prod' to reach PENDING_APPROVAL...${RESET}"
while true; do
STATUS=$(gcloud beta deploy rollouts list --delivery-pipeline web-app --release web-app-001 --filter="targetId=prod" --format="value(state)" | head -n 1)
if [[ "$STATUS" == "PENDING_APPROVAL" ]]; then
echo -e "${GREEN}✅ 'prod' is pending approval! Approving now...${RESET}"
break
fi
sleep 10
done
PROD_ROLLOUT=$(gcloud beta deploy rollouts list --delivery-pipeline web-app --release web-app-001 --filter="targetId=prod AND state=PENDING_APPROVAL" --format="value(name)" | head -n 1)
gcloud beta deploy rollouts approve "$PROD_ROLLOUT" --delivery-pipeline web-app --release web-app-001 --quiet
echo -e "\n${YELLOW}${BOLD}⏳ Waiting for 'prod' rollout to succeed...${RESET}"
while true; do
STATUS=$(gcloud beta deploy rollouts list --delivery-pipeline web-app --release web-app-001 --filter="targetId=prod" --format="value(state)" | head -n 1)
if [[ "$STATUS" == "SUCCEEDED" ]]; then
echo -e "${GREEN}✅ Rollout to 'prod' SUCCEEDED!${RESET}"
break
fi
sleep 10
done
kubectl config use-context prod
kubectl get all -n web-app
echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${MAGENTA}${BOLD}║ 🎉 AUTOMATION COMPLETED SUCCESSFULLY 🎉 ║${RESET}"
echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}"
echo -e "${WHITE}${BOLD}You can now check all your progress in the lab manual!${RESET}"