Google Cloud पर Rails 8: ज़ीरो से एआई तक

1. परिचय

Google Cloud पर Rails 8 की वर्कशॉप में आपका स्वागत है! इस कोडलैब में, आपको Rails 8 के मॉडर्न ऐप्लिकेशन को लोकल SQLite के सामान्य बेसलाइन से लेकर, Google Cloud पर प्रोडक्शन-ग्रेड और एंटरप्राइज़-रेडी रेफ़रंस आर्किटेक्चर तक ले जाने का तरीका बताया जाएगा.

इस वर्कशॉप में, हम सिर्फ़ किसी ऐप्लिकेशन को डिप्लॉय नहीं करते. हम क्लाउड मॉडर्नाइज़ेशन के लिए, प्रोडक्शन-ग्रेड का एक ओपिनियनटेड तरीका लागू करते हैं. लिफ़्ट-एंड-शिफ़्ट को सही तरीके से किया गया!

आपने "मेरी मशीन पर काम करता है" लोकल सेटअप (इफ़ेमरल डिस्क, एम्बेड किया गया SQLite, इन-प्रोसेस जॉब) से शुरुआत की थी. इसके बाद, आपने इसे Google Cloud पर एंटरप्राइज़-ग्रेड, बुलेटप्रूफ़ क्लाउड आर्किटेक्चर में बदल दिया:

  1. 🐘 लोकल SQLite → Cloud SQL (PostgreSQL): अब रीस्टार्ट करने पर डेटाबेस मिट नहीं जाएगा. हम मैनेज किए गए PostgreSQL पर माइग्रेट करते हैं. यह Cloud SQL Auth Proxy (एमटीएलएस, कोई सार्वजनिक आईपी नहीं) के ज़रिए सुरक्षित तरीके से कनेक्ट होता है.
  2. 🪣 इफ़ेमरल लोकल स्टोरेज → प्राइवेट GCS: सर्वरलेस डिस्क अस्थायी होती है. हम IAM signed URL (iam: true) का इस्तेमाल करके, ActiveStorage को निजी Google Cloud Storage से कनेक्ट करते हैं. इसमें न तो सार्वजनिक बकेट का इस्तेमाल किया जाता है और न ही लीक हुई कुंजियों का.
  3. 🚀 इन-प्रोसेस जॉब → मल्टी-कंटेनर Cloud Run से: हम Rails मोनोलिथ और सर्वरलेस क्लाउड के बीच पुल बनाते हैं! हम स्टैंडर्ड Docker Compose का इस्तेमाल करके, Solid Queue को Cloud Run मल्टी-कंटेनर पॉड में Puma के साथ एक डेडीकेटेड वर्कर कंटेनर के तौर पर चलाते हैं. इससे माइक्रोसेवाओं की संख्या में बढ़ोतरी नहीं होती और थ्रेड स्टार्वेशन की समस्या भी नहीं होती. DHH को इस बात पर गर्व होगा!

🍌 हम 2026 में जी रहे हैं, इसलिए हम पूरे स्टैक को Google Antigravity के साथ सुपरचार्ज करते हैं. यह सिर्फ़ एक विचार नहीं है. हमारे पास ऐसे प्रॉम्प्ट और स्किल हैं जो इस वर्कशॉप को बेहतर तरीके से पूरा करने (और इसका आनंद लेने) में आपकी मदद करेंगे!

🏛️ टारगेट रेफ़रंस आर्किटेक्चर (वैरिएंट 1: क्लीन फ़्लैट वेक्टर एंटरप्राइज़)

यहां Google Cloud का कैननिकल रेफ़रंस आर्किटेक्चर दिया गया है, जिसे आपको बनाना और डिप्लॉय करना होगा (Variant 1: Clean Flat Vector Enterprise). इसमें, हमारी प्रोडक्शन मल्टी-कंटेनर Cloud Run सेवा को मैनेज की गई Google Cloud की सभी परसिस्टेंस और एआई सेवाओं से कनेक्ट किया गया है:

पहला वैरिएंट: क्लीन फ़्लैट वेक्टर एंटरप्राइज़ — Google Cloud आर्किटेक्चर पर Rails 8

🎞️ आर्किटेक्चर का विकास: ज़ीरो से क्लाउड-नेटिव तक

हमारे स्टैक को धीरे-धीरे आधुनिक बनाया जा रहा है. इसे एक ही मशीन पर काम करने वाले बुनियादी ढांचे से, पूरी तरह से मैनेज किए जाने वाले Google Cloud ब्लूप्रिंट में बदला जा रहा है. हर वर्कशॉप के माइलस्टोन के दौरान, इस बदलाव को देखें:

वर्कशॉप के आर्किटेक्चर का विकास

आपको क्या सीखने को मिलेगा

  • Rails 8 और Google Cloud के बारे में ज़्यादा जानने के लिए, Google Antigravity के साथ पेयर-प्रोग्रामिंग कैसे करें.
  • फ़्लाइट से पहले गड़बड़ी की अपने-आप जांच करने की सुविधा (just workshop-test) का इस्तेमाल कैसे करें.
  • google प्रोवाइडर का इस्तेमाल करके, लोकल डेवलपमेंट को जारी रखते हुए, Terraform का इस्तेमाल करके, Google Cloud इन्फ़्रास्ट्रक्चर को एसिंक्रोनस तरीके से कैसे प्रोविज़न करें.
  • सुरक्षा से जुड़ी एंटी-पैटर्न को हटाने का तरीका: 0.0.0.0/0 खोलने के बजाय, निजी GCS बकेट (iam: true) और Cloud SQL Auth Proxy mTLS टनल का इस्तेमाल करें.
  • Google Cloud Secret Manager से सीधे सीक्रेट इंजेक्ट करने का तरीका.
  • Solid Queue की मदद से, एसिंक्रोनस जेन एआई बैकग्राउंड जॉब (NanoBanana कवर जनरेटर, दो भाषाओं में पॉडकास्ट सिंथेसिस) को कैसे व्यवस्थित करें.

आइए, शुरू करें!

2. सबसे पहले: ज़रूरी शर्तें, एंटीग्रैविटी सेटअप, और बिलिंग की पुष्टि

💡 स्थिति: आपको और आपकी टीम को, मिशन के लिए ज़रूरी Rails 8 ऐप्लिकेशन बनाना है. कोड को छूने या क्लाउड संसाधनों को लॉन्च करने से पहले, हमें अपनी टूल चेन बनानी होगी, Google Antigravity को कनेक्ट करना होगा, और Google Cloud क्रेडेंशियल और बिलिंग फ़ाउंडेशन की पुष्टि करनी होगी.

1. ज़रूरी शर्तों की चेकलिस्ट

शुरू करने से पहले, पक्का करें कि आपके एनवायरमेंट में ये टूल उपलब्ध हों:

  • just (1.21 और इसके बाद के वर्शन): (just --version) टास्क रनर — इस वर्कशॉप में मौजूद हर कमांड एक just रेसिपी है (इसे इंस्टॉल करने के लिए, अपने एआई हार्नेस से कहें या skills/rails8app-workshop देखें).
  • Git (2.30+): (git --version) वर्शन कंट्रोल, ब्रांचिंग, और डेटा स्टोर करने की जगह को क्लोन करने के लिए.
  • Google Cloud SDK (gcloud सीएलआई): इंस्टॉल किया गया हो और अप-टू-डेट हो.
  • Terraform सीएलआई (1.5 या इससे ऊपर का वर्शन): इन्फ़्रास्ट्रक्चर को डिक्लेरेटिव तरीके से उपलब्ध कराने के लिए.
  • docker और docker-compose: ये स्थानीय तौर पर इंस्टॉल और चालू किए गए हैं.
  • Ruby 3.4.5: (ruby -v — blog/.ruby-version ने पिन किया; अगर 3.4.5 मौजूद नहीं है, तो एआई से इसे इंस्टॉल करने के लिए कहें). Rails 8 को Gemfile में सेट किया गया है और इसे bundle install अपने-आप इंस्टॉल कर देता है.
  • Google Antigravity 2.0: यह एक ऑटोनॉमस एआई है, जो पेयर प्रोग्रामिंग में आपकी मदद करता है (Google Antigravity 2.0 डाउनलोड करें). आपको अपने निजी Gmail खाते से लॉग इन करना होगा. इसके लिए, एपीआई टोकन की ज़रूरत नहीं होगी.

2. Google Cloud Authentication, Dedicated Configuration, और ADC

हमारा सुझाव है कि इस वर्कशॉप के लिए, एक खास कॉन्फ़िगरेशन बनाएं. इससे कॉर्पोरेट, निजी या एक से ज़्यादा खातों वाले gcloud सेटअप के साथ टकराव से बचा जा सकेगा:

# 1. Create and activate dedicated workshop configuration (Fixes Issue #38)
gcloud config configurations create rails8-on-gcp-workshop --activate 2>/dev/null || \
  gcloud config configurations activate rails8-on-gcp-workshop

# 2. Authenticate your account and Application Default Credentials (ADC)
gcloud auth login $GOOGLE_CLOUD_ACCOUNT
gcloud auth application-default login

# 3. Configure active project and region
gcloud config set project $GOOGLE_CLOUD_PROJECT
gcloud config set compute/region europe-west1

💡 खास कॉन्फ़िगरेशन क्यों? gcloud config configurations create rails8-on-gcp-workshop का इस्तेमाल करने से, सभी सीएलआई सेटिंग (खाता, कोटा प्रोजेक्ट, डिफ़ॉल्ट क्षेत्र) सिर्फ़ इस वर्कशॉप के लिए अलग हो जाती हैं. सेटअप पूरा होने के बाद, gcloud config configurations activate default पर जाकर कभी भी सामान्य सेटअप पर वापस स्विच किया जा सकता है.

चालू gcloud कॉन्फ़िगरेशन

3. 🚨 GCP की बिलिंग की पुष्टि

⚠️ ध्यान दें: Google Cloud SQL और Cloud Run डिप्लॉयमेंट के लिए, लिंक किया गया चालू बिलिंग खाता या वर्कशॉप के मान्य शिक्षा क्रेडिट ज़रूरी हैं. आइए, अब पक्का करें कि आपका सेटअप सही है. इसके लिए, बिलिंग की पुष्टि करने वाली जांच करें:

gcloud beta billing projects describe $GOOGLE_CLOUD_PROJECT

पक्का करें कि billingEnabled: true वापस कर दिया गया हो. अपने सभी बिलिंग खातों की सूची भी देखी जा सकती है:

gcloud billing accounts list

पक्का करें कि इनमें से कम से कम एक डिवाइस पर OPEN: True दिख रहा हो. अगर कोई भी खाता चालू नहीं है, तो Google Cloud Console के बिलिंग पेज पर जाकर, कोई बिलिंग खाता लिंक करें या वर्कशॉप के क्रेडिट कूपन को रिडीम करें.

चालू GCP बिलिंग खाता

4. डेटा स्टोर करने की जगह को क्लोन करना और Antigravity से जोड़ना

रिपॉज़िटरी को क्लोन करें और डायरेक्ट्री डालें. ध्यान दें कि हम पूरी तरह से main पर बने रहते हैं:

git clone https://github.com/palladius/rails8-app-on-gcp.git
cd rails8-app-on-gcp

इस डायरेक्ट्री को Google Antigravity में खोलें. Antigravity, रिपॉज़िटरी की अपने-आप जांच करेगा, AGENTS.md पढ़ेगा, और आपके साथ पेयर प्रोग्रामर के तौर पर काम करेगा.

5. 🪫 अगर Antigravity के मुफ़्त क्रेडिट खत्म हो जाते हैं

⚠️ आपने अभी जो Cloud क्रेडिट रिडीम किए हैं उनसे Antigravity में क्रेडिट नहीं जुड़ेंगे. ये दोनों अलग-अलग बिलिंग प्लैटफ़ॉर्म हैं: Antigravity का कोटा Google के एआई प्लान (Google One) पर होता है, जबकि वाउचर और Cloud क्रेडिट Cloud Billing खाते पर मिलते हैं. बिलिंग खाते को अपने GCP प्रोजेक्ट से लिंक करने पर, आपको एक भी अतिरिक्त Antigravity प्रॉम्प्ट नहीं मिलेगा.

अगर एजेंट, कोटा पूरा होने का मैसेज दिखाता है, तो यहां दिए गए विकल्पों को आज़माएं. इनमें से पहले दो विकल्प मुफ़्त हैं और तुरंत काम करते हैं:

  1. मॉडल पूल स्विच करें. कोटा को मॉडल फ़ैमिली के हिसाब से ट्रैक किया जाता है. Antigravity, दो इंडिपेंडेंट पूल दिखाता है (Gemini मॉडल बनाम Claude/GPT मॉडल). Claude और GPT-OSS मॉडल, फ़्री टियर में उपलब्ध हैं. इसलिए, Gemini का पूल खत्म होने पर भी, दूसरे मॉडल का पूल अक्सर इस्तेमाल नहीं किया जाता. प्रॉम्प्ट बॉक्स के नीचे मौजूद, मॉडल चुनने वाले मेन्यू का इस्तेमाल करें.Antigravity मॉडल चुनने का विकल्प — Gemini, Claude, और GPT-OSS के पूल के बीच स्विच करें
  2. Pro के बजाय, कोई Flash मॉडल चुनें. दर की सीमाएं इस बात से जुड़ी होती हैं कि एजेंट हर अनुरोध पर कितना काम करता है. इसलिए, कम संसाधनों का इस्तेमाल करने वाला मॉडल, बचे हुए संसाधनों का इस्तेमाल ज़्यादा समय तक कर सकता है.
  3. अपने Gemini API पासकोड के साथ Antigravity CLI का इस्तेमाल करें. Bring-your-own-key की सुविधा, Antigravity IDE में काम नहीं करती. इसके बजाय, CLI का इस्तेमाल किया जा सकता है. Google AI Studio में जाकर, बिना किसी शुल्क के पासकोड बनाएं. इसके लिए, प्रोजेक्ट की ज़रूरत होती है, लेकिन बिलिंग खाते की नहीं. इसके बाद, Antigravity CLI को डाउनलोड करें और कॉन्फ़िगर करें.
  4. इंतज़ार करें या अपग्रेड करें. मुफ़्त टियर का कोटा हर हफ़्ते रीफ़्रेश होता है. गड़बड़ी के मैसेज में, रीसेट होने की तारीख दी गई होती है. डेस्कटॉप ऐप्लिकेशन में बेसलाइन बढ़ाने का सिर्फ़ एक तरीका है, Google AI Pro/Ultra. ये प्लान हर पांच घंटे में रीफ़्रेश होते हैं. साथ ही, ये प्लान, अतिरिक्त शुल्क देकर खरीदे गए एआई क्रेडिट को खर्च कर सकते हैं.
  5. यह Antigravity की वर्कशॉप है. हालांकि, ज़्यादातर एआई कोडिंग हार्नेस भी काम करने चाहिए. बस अपने हार्नेस को repo में मौजूद AGENTS.md और skills/ डायरेक्ट्री पर पॉइंट करें.

6. अपने-आप होने वाला चरण 0 का पुष्टि करने का प्रोसेस

पुष्टि करें कि आपका चरण 0 वाला एनवायरमेंट, मूल्यांकन सुइट की शर्तों का पूरी तरह से पालन करता हो:

just workshop-eval 0

✨ अद्भुत पल: Antigravity और वर्कशॉप के आकलन का इंजन, दो सेकंड से भी कम समय में आपके सीएलआई वर्शन, Ruby एनवायरमेंट, और एडीसी ऑथेंटिकेशन की पुष्टि करते हैं!

3. पहला चरण: Terraform इन्फ़्रास्ट्रक्चर को शुरू करना और प्री-फ़्लाइट डाइग्नोस्टिक्स

💡 रणनीति: Google Cloud SQL PostgreSQL जैसे मैनेज किए गए डेटाबेस को उपलब्ध होने में करीब 10 से 12 मिनट लगते हैं. हम स्थानीय तौर पर डेवलपमेंट करते समय, Terraform के ज़रिए बैकग्राउंड में अभी ही इम्यूटेबल इंफ़्रास्ट्रक्चर लॉन्च कर देते हैं, ताकि बाद में हमें इंतज़ार न करना पड़े!

1. ऑटोमेटेड प्री-फ़्लाइट डाइग्नोस्टिक्स सुइट चलाना

क्लाउड इन्फ़्रास्ट्रक्चर लॉन्च करने से पहले, प्री-फ़्लाइट टेस्ट सुइट चलाएं:

just workshop-test

यह स्क्रिप्ट (bin/workshop_diagnostics.rb):

  • यह कुकी, GOOGLE_CLOUD_ACCOUNT की पहचान से जुड़े कॉन्फ़िगरेशन की पुष्टि करती है.
  • इससे यह पुष्टि होती है कि बिलिंग चालू है और प्रोजेक्ट लिंक है.
  • यह कुकी, Vertex AI के लिए ऐप्लिकेशन के डिफ़ॉल्ट क्रेडेंशियल (एडीसी) की पुष्टि करती है.
  • यह कुकी, ActiveStorage की कैनरी सीड इमेज (blog/app/assets/images/gcs_dev_image.jpg) की पुष्टि करती है.

सिर्फ़ वर्कशॉप-टेस्ट डाइग्नोस्टिक्स आउटपुट

अगर .env मौजूद नहीं है, तो इसे दस्तावेज़ वाले टेंप्लेट से कॉपी करें:

cp .env.dist .env
# Edit .env and configure GOOGLE_CLOUD_ACCOUNT with your Google/Gmail account

💡 अहम जानकारी: अगर just workshop-test यह सूचना देता है कि आपके प्रोजेक्ट पर बिलिंग एपीआई बंद है, तो इसे तुरंत चालू करें. इसके लिए, यह तरीका अपनाएं:

gcloud services enable cloudbilling.googleapis.com

2. ⏱️ Terraform इन्फ़्रास्ट्रक्चर को एसिंक्रोनस तरीके से लॉन्च करना

एक चरण वाली Terraform रेसिपी चलाएं. इससे रिमोट बैकएंड स्टेट बकेट बन जाती है और इन्फ़्रास्ट्रक्चर डिप्लॉयमेंट ट्रिगर हो जाता है:

just terraform-apply

Terraform को शुरू किया गया

मैन्युअल तरीका (या सीधे तौर पर `iac/bin/terraform-apply.sh` चलाएं)

# Fall back to active gcloud config if environment variables are unset
GOOGLE_CLOUD_PROJECT="${GOOGLE_CLOUD_PROJECT:-$(gcloud config get-value project)}"
GOOGLE_CLOUD_REGION="${GOOGLE_CLOUD_REGION:-europe-west1}"

# Create remote state bucket idempotently
gcloud storage buckets create "gs://${GOOGLE_CLOUD_PROJECT}-tfstate" --location="$GOOGLE_CLOUD_REGION" 2>/dev/null || \
  gcloud storage buckets describe "gs://${GOOGLE_CLOUD_PROJECT}-tfstate" >/dev/null

cd iac
terraform init -backend-config="bucket=${GOOGLE_CLOUD_PROJECT}-tfstate"
terraform apply -auto-approve -var="project_id=${GOOGLE_CLOUD_PROJECT}" -var="region=${GOOGLE_CLOUD_REGION}"
cd ..

Terraform क्या-क्या उपलब्ध कराता है:

  • Google Cloud Storage बकेट: इसे निजी ऐक्सेस और IAM क्रेडेंशियल पर हस्ताक्षर करने (iam: true) की सुविधा के साथ बनाया गया है.
  • कैनरी टेस्ट इमेज: यह बकेट में gcs_dev_image.jpg अपलोड करती है, ताकि एंड-टू-एंड ब्लॉब की पुष्टि की जा सके.
  • Google Cloud SQL PostgreSQL इंस्टेंस: बैकग्राउंड में प्रोविज़निंग शुरू करता है (~10 से 12 मिनट).

Google Cloud Console में Cloud SQL PostgreSQL इंस्टेंस

💡 ध्यान दें: ऑटोमैटिक बैकअप मौजूद न होने की चेतावनी को अनदेखा किया जा सकता है. हमें इस वर्कशॉप के डेटाबेस के लिए इनकी ज़रूरत नहीं होगी. हालांकि, किसी भी प्रोडक्शन डेटाबेस के लिए, हर दिन के ऑटोमैटिक बैकअप लेना एक ज़रूरी सबसे सही तरीका है!

Terraform apply completed successfully with outputs

📝 अपने Cloud Run यूआरएल को नोट करें: Terraform apply को पूरा होना चाहिए और आपके इन्फ़्रास्ट्रक्चर के आउटपुट प्रिंट होने चाहिए. अपने cloud_run_url को लिख लें या क्लिपबोर्ड पर कॉपी कर लें. लाइव सेवा की पुष्टि करते समय, आपको इसकी ज़रूरत पड़ेगी!

3. पहले चरण की पुष्टि अपने-आप होना (ज़रूरी नहीं)

पुष्टि करें कि पहले चरण की ज़रूरी शर्तें और कॉन्फ़िगरेशन पूरे हों:

just workshop-eval 1

⏱️ ध्यान दें: इस आकलन में, लाइव क्लाउड संसाधनों की जांच की जाती है. इसे पूरा होने में कुछ मिनट लग सकते हैं. यह पूरी तरह से वैकल्पिक है. यह आपके टर्मिनल में चलता है. इसलिए, आपको इंतज़ार करने की ज़रूरत नहीं है. आप तुरंत अगले चरण पर जा सकते हैं!

4. दूसरा चरण: लोकल बेसलाइन, Mailpit, और एडमिन ऑनबोर्डिंग

हमारा शुरुआती पॉइंट, लोकल होस्ट पर चल रहा एक नया और मॉडर्न Rails 8 ब्लॉग ऐप्लिकेशन है. इसमें SQLite, Mailpit ईमेल इंटरसेप्शन, और डिस्क पर आधारित ActiveStorage का इस्तेमाल किया जाता है.

1. ऐप्लिकेशन को स्थानीय तौर पर बूट करना

📁 डायरेक्ट्री का ध्यान रखें! इस रेपो में, blog/ में Rails ऐप्लिकेशन और iac/ में Terraform मौजूद है. पहले चरण के बाद, आप रेपो रूट में पहुंच जाते हैं. इसलिए, दूसरे चरण में मौजूद हर कमांड,

blog/ — Gemfile, bin/rails, और compose.yaml सभी वहां रहते हैं. इन्हें रूट से चलाने पर, no configuration file provided: not found या Gemfile मौजूद न होने की वजह से गड़बड़ी होती है.

Rails ऐप्लिकेशन में जाएं. इसके बाद, पुष्टि करें कि आपने पिन की गई Ruby का इस्तेमाल किया है. फिर, gems इंस्टॉल करें और डेटाबेस सेट अप करें:

cd blog
ruby -v          # must print 3.4.5 — see Step 0 if it does not
bundle install
bin/rails db:setup

🧯 में लिखने की अनुमति से जुड़ी गड़बड़ी

/var/lib/gems/

या

ruby -v

shows system Ruby (e.g. 3.3.x)? Vanilla Linux सिस्टम Ruby, .ruby-version फ़ाइलों को पूरी तरह से अनदेखा करता है और पूरे सिस्टम में gems इंस्टॉल करने की कोशिश करता है! पक्का करें कि rbenv आपके चालू टर्मिनल शेल में लोड हो:

eval "$(rbenv init - bash)"   # or: eval "$(rbenv init - zsh)"
ruby -v                       # confirm it now outputs 3.4.5!

ध्यान दें: अगर आपने चरण 0 में 3.4.5 वर्शन इंस्टॉल नहीं किया है, तो rbenv install 3.4.5 चलाएं. इसके अलावा, नीचे दिए गए मोड A (Docker Compose) (just compose-up) का इस्तेमाल करें. यह पिन किए गए Ruby स्टैक को कंटेनर के अंदर पूरी तरह से चलाता है. इसके लिए, होस्ट जेम को नहीं छुआ जाता!

💡 क्या आपको इस बारे में नहीं सोचना है? just install और just compose-up, रिपो रूट से cd blog करते हैं.

2. 🌱 स्मार्ट सीड ऑटो-डिस्कवरी और एडमिन बूटस्ट्रैप (समस्या #21 और #25)

डेटाबेस सीड (db/seeds.rb) में स्मार्ट एनवायरमेंट ऑटो-डिस्कवरी की सुविधा है:

  • यह आपके चालू डेटाबेस अडैप्टर (SQLite बनाम Postgres) और स्टोरेज कॉन्फ़िगरेशन की जांच करता है.
  • यह स्टेज 0 (लोकलहोस्ट) का पता लगाता है. साथ ही, शुरुआती एडमिन उपयोगकर्ता को अपने-आप बना देता है और शिक्षा से जुड़ी पोस्ट को सीड करता है:
    • [LOCAL BASELINE] Welcome to Rails 8 on Localhost!
    • लोकल डिस्क स्टोरेज की सुविधा के बारे में बताने वाला वॉटरमार्क, जिसमें उदास इमेज (local_sad_image.png) अटैच की गई है.
  • इससे ActionMailer के ज़रिए, पासवर्ड फिर सेट करने का ईमेल अपने-आप ट्रिगर हो जाता है.

सीड की पुष्टि करें या उसे फिर से चलाएं. इससे .env से GOOGLE_CLOUD_ACCOUNT अपने-आप इस्तेमाल हो जाएगा:

bin/rails db:seed    # or from repo root: just seed

Docker Compose की मदद से, लोकल डेवलपमेंट स्टैक बूट करें:

docker compose up -d     # from blog/ — or `just compose-up` from the repo root

Docker Compose, Rails, Mailpit, और लोकल स्टैक शुरू कर रहा है

ऐप्लिकेशन, लोकल Mailpit एसएमटीपी सर्वर, और Adminer डेटाबेस व्यूअर अब अलग-अलग कंटेनर में एक साथ चल रहे हैं:

  • Rails ऐप्लिकेशन: http://localhost:3000
  • Mailpit का वेब यूज़र इंटरफ़ेस (यूआई): http://localhost:8025
  • Adminer DB UI: http://localhost:8081

🧯 पोर्ट 3000 का टकराव या

server.pid

गड़बड़ी? अगर आपने पहले नेटिव डेवलपमेंट सर्वर (bin/dev) शुरू किया था, तो उसे Ctrl+C की मदद से बंद करें. अगर Docker यह शिकायत करता है कि पोर्ट 3000 पहले से ही असाइन किया गया है या उसे कोई बचा हुआ server.pid मिलता है, तो इसे इस कमांड से हटाएं:

just compose-down
rm -f blog/tmp/pids/server.pid
just compose-up

3. Mailpit का इस्तेमाल करना और एडमिन के तौर पर लॉगिन करना

  1. Mailpit की मदद से भेजे गए ईमेल ट्रैक करना: अपने ब्राउज़र में http://localhost:8025 खोलें. स्थानीय इनबॉक्स देखें! db:seed के दौरान, ActionMailer ने एडमिन को एक ईमेल भेजा. Mailpit ने इस ईमेल को सुरक्षित तरीके से स्थानीय तौर पर कैप्चर किया. इसके लिए, बाहरी ईमेल सर्वर या क्रेडेंशियल का इस्तेमाल नहीं किया गया:

Mailpit के वेब यूज़र इंटरफ़ेस (यूआई) की इमेज, जिसमें इंटरसेप्ट किया गया पासवर्ड रीसेट करने का ईमेल दिखाया गया है 2. ब्लॉग में लॉग इन करें: अपने ब्राउज़र में http://localhost:3000 खोलें.

  • पासवर्ड सेट करने के लिए, Mailpit ईमेल में मौजूद पासवर्ड रीसेट करने के लिंक पर क्लिक करें.
  • इसके अलावा, अपने Google Cloud खाते के ईमेल पते (.env से) और डिफ़ॉल्ट सीड किए गए पासवर्ड: Ch4ng3m3!!1 का इस्तेमाल करके लॉग इन करें.
  1. विज़ुअल टेलीमेट्री बैज देखें:
    • यूज़र इंटरफ़ेस (यूआई) में, पीले रंग के एनवायरमेंट बैनर और बैज पर ध्यान दें: Notice: Ephemeral Database Active (POSTGRESQL) और [EPHEMERAL DB / STORAGE] 💾 Local.
    • पोस्ट के वॉटरमार्क पर ध्यान दें: 🏠 स्टैंप (कवर इमेज के सबसे नीचे दाएं कोने में nanobanana_stamp_local.png). इससे तुरंत यह पुष्टि हो जाती है कि आपकी ऐसेट और डेटाबेस, फ़िलहाल कुछ समय के लिए लोकल स्टोरेज से जुड़े हुए हैं.

लोकल ब्लॉग का होम पेज, जिसमें कुछ समय के लिए उपलब्ध टेलीमेट्री सूचनाएं और बैज दिख रहे हैं

💡 ज़रूरी नहीं: Rails Console Workout के बारे में खास जानकारी क्या आपको यह जानना है कि Rails, CLI से आपके सीड किए गए डेटा के साथ कैसे इंटरैक्ट करता है? इंटरैक्टिव कंसोल में ड्रॉप करें:

bin/rails console

अपने एनवायरमेंट वैरिएबल का इस्तेमाल करके, सीड किए गए एडमिन उपयोगकर्ता की डाइनैमिक तरीके से जांच करें:

user = User.find_by(email_address: ENV.fetch("GOOGLE_CLOUD_ACCOUNT"))
# Or simply grab the first user:
user = User.first
puts "Admin email: #{user.email_address} (created via: #{user.created_via})"
exit

4. दूसरे चरण की पुष्टि अपने-आप होना

अपने स्थानीय बेसलाइन और एडमिन सेटअप की पुष्टि करें:

just workshop-eval 2

just workshop-eval 2 verification output

5. समस्या: स्टेटलेस कंटेनर

Cloud Run कंटेनर, स्टेटलेस और कुछ समय के लिए होते हैं. अगर हम अपने SQLite डेटाबेस और लोकल storage/ डायरेक्ट्री को सीधे Cloud Run पर डिप्लॉय करते हैं, तो कंटेनर के शून्य पर स्केल होने या रीस्टार्ट होने पर, सभी पोस्ट और अपलोड की गई इमेज हमेशा के लिए मिट जाएंगी.

अगले चरण में, हम इस कुछ समय के लिए उपलब्ध कॉन्फ़िगरेशन को Cloud Run पर डिप्लॉय करेंगे, ताकि स्टेटलेस शॉक को सीधे तौर पर देखा जा सके!

5. तीसरा चरण: 1 — बिना किसी स्टेटस वाली शॉक स्क्रिप्ट (तीन मिनट में शुरुआती WOW!)

वेब पर कुछ भी दिखने से पहले, क्लाउड डेटाबेस के लिए 15 से 20 मिनट इंतज़ार करने के बजाय, सर्वरलेस डेवलपमेंट की आधुनिक तकनीक का इस्तेमाल करके, हम अपने सिंगल-कंटेनर Rails ऐप्लिकेशन को सीधे Google Cloud Run पर तीन मिनट से भी कम समय में डिप्लॉय कर सकते हैं!

1. टाइम-मशीन रिवाइंड

यह पक्का करने के लिए कि हमारा शुरुआती कॉन्फ़िगरेशन 100% इफ़ेमरल (स्थानीय SQLite डेटाबेस और लोकल डिस्क फ़ाइल स्टोरेज) है, Zero-Branch Time-Machine इंजन का इस्तेमाल करें:

just workshop-rewind 1

💡 अभी क्या हुआ?workshop-rewind 1 ने main ब्रांच से बाहर निकले बिना, blog/config/ पर stage-1-stateless कॉन्फ़िगरेशन ओवरले लागू किया. आपका ऐप्लिकेशन, कंटेनर डिस्क पर SQLite और लोकल फ़ाइल सिस्टम पर ActiveStorage के साथ कॉन्फ़िगर किया गया है.

2. Cloud Run पर सिंगल-कंटेनर Puma को डिप्लॉय करना

सोर्स कोड से सीधे Cloud Run पर डिप्लॉय करें. मॉडर्न Rails 8, आधिकारिक और प्रोडक्शन के लिए तैयार Dockerfile को अपने-आप जनरेट करता है. इसमें अलग-अलग लेवल के बिल्ड, jemalloc, और नॉन-रूट सुरक्षा शामिल होती है. blog/ फ़ोल्डर से डिप्लॉय करने पर, Google Cloud Build इस नेटिव Dockerfile का पता सीधे तौर पर लगाता है और मैनेज की गई सर्वरलेस सेवा उपलब्ध कराता है:

# Ensure you are inside the Rails application directory
cd blog

# Ensure default region is set
export GOOGLE_CLOUD_REGION="europe-west1"

# Deploy single-container service from source (with dummy key fallback if starting without credentials)
gcloud run deploy blog \
  --source . \
  --region $GOOGLE_CLOUD_REGION \
  --allow-unauthenticated \
  --set-env-vars GOOGLE_CLOUD_ACCOUNT=$GOOGLE_CLOUD_ACCOUNT,SECRET_KEY_BASE_DUMMY=1

आपको प्रोग्रेस आउटपुट कुछ ऐसा दिखना चाहिए:

gcloud run deploy building and deploying container

⏳ इसमें कुछ मिनट लगेंगे. इस दौरान, Cloud Build आपके कंटेनर को पैकेज करेगा और Cloud Run के वर्शन को उपलब्ध कराएगा.

🧯 समस्याएं हल करना और सामान्य चेतावनियां

PERMISSION_DENIED: Build failed because the default service account is missing required IAM permissions

? दो अलग-अलग वजहों से एक ही गड़बड़ी होती है:

  1. gcloud ने आपके लिए एक एपीआई चालू कर दिया है. अगर डिप्लॉय किए गए The following APIs are not enabled ... cloudbuild.googleapis.com और आपने Y का जवाब दिया है, तो हो सकता है कि नई अनुमतियों के लागू होने से पहले ही बिल्ड शुरू हो गया हो. gcloud के प्रॉम्प्ट में यह चेतावनी दी गई है कि "इसमें कुछ मिनट लगेंगे". एक मिनट इंतज़ार करें और ठीक उसी कमांड को फिर से चलाएं. आम तौर पर, यह काम कर जाती है. पहले चरण में terraform apply आम तौर पर इस एपीआई को आपके लिए चालू कर देता है. इसलिए, आपको प्रॉम्प्ट नहीं दिखना चाहिए.
  2. डिफ़ॉल्ट Compute SA के पास वाकई भूमिकाएं नहीं हैं. नए GCP प्रोजेक्ट में कम से कम अधिकारों का सिद्धांत लागू होता है. इससे सोर्स डिप्लॉयमेंट में समस्या आती है. इसे ठीक करने के लिए:
    just project-status   # grants storage.admin, logging.logWriter, artifactregistry.writer, cloudbuild.builds.builder
    
    just workshop-test भी अब इसकी रिपोर्ट करता है. इसलिए, अगर डिप्लॉयमेंट बार-बार फ़ेल हो रहा है, तो इसे फिर से चलाएं.

परिनियोजन के दौरान:

  1. Cloud Run, आपकी Rails कंटेनर इमेज बनाता है.
  2. यह एक सार्वजनिक और सुरक्षित टीएलएस डोमेन असाइन करता है: https://blog-[hash]-[region].a.run.app.
  3. पोर्ट 8080 पर Puma को ट्रैफ़िक रूट करना शुरू कर देता है.

3. ✨ शुरुआती शानदार पल

जनरेट किए गए Cloud Run यूआरएल को अपने ब्राउज़र में खोलें!

  1. आपका मॉडर्न Rails 8 ऐप्लिकेशन, Google Cloud पर लाइव है!
  2. अपने एडमिन क्रेडेंशियल (GOOGLE_CLOUD_ACCOUNT और APP_ADMIN_PASSWORD) का इस्तेमाल करके लॉग इन करें. अगर आपको लॉग इन बटन नहीं दिखता है, तो "नई पोस्ट" पर क्लिक करें. इसके बाद, आपको उपयोगकर्ता नाम और पासवर्ड डालने के लिए कहा जाएगा:Rails 8 का साइन इन पेज, जिसमें कुछ समय के लिए दिखने वाले टेलीमेट्री बैनर मौजूद हैं
  3. "नई पोस्ट" पर क्लिक करें. इसके बाद, "मेरी पहली Cloud Run पोस्ट" नाम का लेख लिखें, कोई तस्वीर अटैच करें, और पोस्ट बनाएं पर क्लिक करें.
  4. आपकी पोस्ट पूरी फ़ॉर्मैटिंग के साथ पब्लिश हो जाती है और आपकी इमेज रेंडर हो जाती है.
  5. विज़ुअल टेलीमेट्री पर ध्यान दें:
    • हेडर बैज: [EPHEMERAL DB / STORAGE] 💾 Local
    • इमेज वॉटरमार्क: 🏠 स्टैंप (सबसे नीचे दाएं कोने में मौजूद 127.0.0.1 कुछ समय के लिए दिखने वाला डिस्क बैज).

🐝 लाइव वर्कशॉप के लीडरबोर्ड में शामिल हों! अगर आप ऑनलाइन हैं और आपका प्रॉक्टर लीडरबोर्ड दिखा रहा है, तो इसमें शामिल होने के लिए, यहां अपना Cloud Run यूआरएल जोड़ें: 👉 लीडरबोर्ड पर अपना Cloud Run रजिस्टर करें

Google Cloud Run Console के ब्लॉग में, सेवा के वर्शन की जानकारी

4. 💥 समस्या: स्टेटलेस शॉक और "Puma Workaround" ट्रैप

Cloud Run एक स्टेटलेस और सर्वरलेस प्लैटफ़ॉर्म है. जब वेब ट्रैफ़िक शून्य पर पहुंच जाता है, तो Cloud Run, कंटेनर इंस्टेंस को शून्य पर ले जाता है, ताकि पैसे बचाए जा सकें. जब कोई नया एचटीटीपी अनुरोध आता है या कंटेनर का नया वर्शन डिप्लॉय किया जाता है, तो Cloud Run एक नई और क्लीन कंटेनर इमेज शुरू करता है.

प्रिंट नहीं हो पा रहे जॉब के लिए बैनर

सिंगल-कंटेनर डिप्लॉयमेंट में पोस्ट बनाने या इमेज अटैच करने पर, Rails, ActiveJob टास्क को लाइन में लगाता है. जैसे, इमेज डाइमेंशन का विश्लेषण करना या मेटाडेटा इंडेक्स करना. हालांकि, बैकग्राउंड वर्कर के न चलने की वजह से, आपको चेतावनी वाला बैनर दिखेगा:

सूचना: फ़िलहाल, आठ बैकग्राउंड जॉब पूरे होने बाकी हैं

The Tempting Fix: Running Solid Queue inside Puma

एक चतुर डेवलपर कह सकता है: "रुकिए! Rails 8 की मदद से, हम Solid Queue को सीधे तौर पर Puma वेब सर्वर प्रोसेस में चला सकते हैं. इसके लिए, हमें

SOLID_QUEUE_IN_PUMA=true

एनवायरमेंट वैरिएबल!"

चलिए, इस अस्थायी समाधान को Cloud Run पर टेस्ट करते हैं:

# Force a revision update to enable Solid Queue inside Puma
gcloud run services update blog \
  --region $GOOGLE_CLOUD_REGION \
  --update-env-vars SOLID_QUEUE_IN_PUMA=true

अब अपने ब्राउज़र पर वापस जाएं और पेज को रीफ़्रेश करें:

💥 स्टेटलेस शॉक:

  1. खुशखबरी: Solid Queue वर्कर अब Puma में चालू है! कोई भी नई नौकरी तुरंत खत्म हो जाती है.
  2. ठंडा पानी (द कैच!):
    • Cloud Run ने नया वर्शन डिप्लॉय किया है. इसलिए, कंटेनर के पिछले इंस्टेंस को बदल दिया गया है!
    • आपने जो लेख लिखा था और डिस्क पर मौजूद SQLite डेटाबेस फ़ाइल पूरी तरह से मिट गई है!
  3. आर्किटेक्चर से जुड़ी जानकारी: Puma में बैकग्राउंड वर्कर चलाने से, वेब थ्रेड के सीपीयू/रैम का इस्तेमाल होता है. साथ ही, इससे डेटा को सेव करने की समस्या भी हल नहीं होती.

5. तीसरे चरण में अपने-आप पुष्टि होने की सुविधा

Cloud Run डिप्लॉयमेंट और सूचनाओं को मैनेज करने की पुष्टि करें:

just workshop-eval 3

✨ अहम जानकारी: SOLID_QUEUE_IN_PUMA जैसे सिंगल-कंटेनर वर्कअराउंड, लोकल डेवलपमेंट के लिए काम के होते हैं. हालांकि, मॉडर्न क्लाउड आर्किटेक्चर में:

  • मीडिया फ़ाइलों के लिए, Google Cloud Storage (GCS) की ज़रूरत होती है (चौथा चरण).
  • रिलेशनल डेटा और जॉब कतारों के लिए, मैनेज किया गया Google Cloud SQL ज़रूरी है (पांचवां चरण).
  • ज़्यादा संसाधन इस्तेमाल करने वाले बैकग्राउंड वर्कर को एक अलग साइडकार कंटेनर में रखना चाहिए (छठा चरण).

6. चौथा चरण: तीन चरणों में लागू करना — GCS परसिस्टेंट स्टोरेज और POLA की चेतावनी

इस चरण में, हम मीडिया और फ़ाइल स्टोरेज को कंटेनर डिस्क से अलग करते हैं. इसके लिए, ActiveStorage को Google Cloud Storage (GCS) पर स्विच किया जाता है. साथ ही, IAM Credentials API (iam: true) के ज़रिए कम समय के लिए मान्य साइन किए गए यूआरएल का इस्तेमाल किया जाता है.

किसी भी कॉन्फ़िगरेशन को बदलने से पहले, यह जान लें कि Rails को GCS से कम्यूनिकेट करने के लिए इन तीन चीज़ों की ज़रूरत होती है:

① प्रोजेक्ट आईडी + बकेट का नाम — Rails को यह पता होना चाहिए कि उसे ब्लॉब कहां सेव करने हैं. ऐप्लिकेशन, एनवायरमेंट से GOOGLE_CLOUD_PROJECT को पढ़ता है और बकेट के नाम को ${GOOGLE_CLOUD_PROJECT}-activestorage-prod के तौर पर दिखाता है. पहले चरण में मौजूद Terraform ने यह बकेट पहले ही बना दिया है. आपको कुछ और करने की ज़रूरत नहीं है.

② सही अनुमतियों वाला सेवा खाता — Cloud Run, Compute Engine के डिफ़ॉल्ट सेवा खाते (PROJECT_NUMBER-compute@developer.gserviceaccount.com) के तौर पर काम करता है. इस एसए को बकेट पर दो आईएएम भूमिकाओं की ज़रूरत होती है:

  • roles/storage.objectAdmin — इसका इस्तेमाल, अपलोड और सर्व करने के लिए किया जाता है
  • roles/iam.serviceAccountTokenCreator खुद — IAM क्रेडेंशियल signBlob एपीआई को कॉल करने और कम समय के लिए मान्य हस्ताक्षर किए गए यूआरएल जनरेट करने के लिए

⚠️ आसान तरीका —

public: true GCS को चालू करने का सबसे तेज़ तरीका यह है कि storage.yml में public: true सेट किया जाए और बकेट पर allUsers:objectViewer का ऐक्सेस दिया जाए. इमेज तुरंत लोड हो जाती हैं. इसके लिए, साइन इन करने की ज़रूरत नहीं होती. ऐसा न करें. सार्वजनिक बकेट में, उपयोगकर्ता के अपलोड किए गए सभी मीडिया को हमेशा के लिए इंटरनेट पर लीक कर दिया जाता है. हमारा ब्लूप्रिंट, बकेट को 100% निजी रखने के लिए iam: true का इस्तेमाल करता है. हर इमेज यूआरएल एक हस्ताक्षर किया गया, खत्म होने वाला टोकन होता है. इसे IAM Credentials API तुरंत जनरेट करता है.

③

ACTIVE_STORAGE_SERVICE=google — यह एक एनवायरमेंट वैरिएबल है. इसकी मदद से, Rails को रनटाइम के दौरान लोकल डिस्क से GCS पर स्विच किया जाता है. कोड में कोई बदलाव नहीं किया गया है और न ही ऐप्लिकेशन लॉजिक को फिर से डिप्लॉय किया गया है. सिर्फ़ एक एनवायरमेंट वैरिएबल टॉगल किया गया है.

1. टाइम-मशीन रिवाइंड

टाइम मशीन को दूसरे चरण पर ले जाएं:

just workshop-rewind 2

blog/config/storage.yml की जांच करें — आपको दिखेगा कि ऐप्लिकेशन, तीन नाम वाले GCS एनवायरमेंट (dev / test / prod) को तय करता है. ये सभी एक ही सुरक्षित पैटर्न का इस्तेमाल करते हैं:

<% gcp_project = ENV.fetch("GOOGLE_CLOUD_PROJECT") { Rails.application.credentials.dig(:gcs, :project) } %>
<% gcs_signer_sa = ENV.fetch("GCS_SIGNER_SA_EMAIL") { "rails-cloudrun-sa@#{gcp_project}.iam.gserviceaccount.com" } %>

google_prod: &google_prod
  service: GCS
  project: <%= gcp_project %>
  bucket: <%= gcp_project %>-activestorage-prod  # ← derived from project ID, no extra env var!
  iam: true        # Sign URLs via IAM Credentials signBlob API (no private key JSON required!)
  gsa_email: <%= gcs_signer_sa %>

# Convenience alias — ACTIVE_STORAGE_SERVICE=google points here
google:
  <<: *google_prod

GCS IAM के हस्ताक्षर करने का आर्किटेक्चर

2. IAM की स्टोरेज और हस्ताक्षर करने की अनुमतियां देना

पक्का करें कि आपके Cloud Run रनटाइम सेवा खाते के पास, यूआरएल पर हस्ताक्षर करने और ऑब्जेक्ट अपलोड करने की अनुमतियां हों:

export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)")
export RUN_SA="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
export GCS_BUCKET="${GOOGLE_CLOUD_PROJECT}-activestorage-prod"

# Grant Storage Object Admin
gcloud storage buckets add-iam-policy-binding gs://$GCS_BUCKET \
  --member="serviceAccount:$RUN_SA" \
  --role="roles/storage.objectAdmin"

# Grant Service Account Token Creator (required for IAM signed URLs)
gcloud iam service-accounts add-iam-policy-binding $RUN_SA \
  --member="serviceAccount:$RUN_SA" \
  --role="roles/iam.serviceAccountTokenCreator"

3. GCS अटैच करके, Cloud Run पर तीसरा डिप्लॉयमेंट

GCS की सुविधा चालू करके फिर से डिप्लॉय करें. पक्का करें कि आप blog/ फ़ोल्डर में हों. ऐसा न होने पर, Cloud Run, Rails 8 Dockerfile के बजाय Buildpacks का इस्तेमाल करके इमेज बनाने की कोशिश करेगा. इससे इमेज नहीं बन पाएगी.

मौजूदा एनवायरमेंट वैरिएबल (मास्टर की, आईएपी कॉन्फ़िगरेशन वगैरह) को बनाए रखने के लिए, --update-env-vars (--set-env-vars नहीं) का इस्तेमाल करें:

cd blog
gcloud run deploy blog \
  --source . \
  --region $GOOGLE_CLOUD_REGION \
  --update-env-vars ACTIVE_STORAGE_SERVICE=google

💡 अहम जानकारी: अगर डिप्लॉयमेंट पूरा नहीं होता है, तो अपने टर्मिनल आउटपुट में दिए गए Cloud Build के लॉग लिंक पर क्लिक करें. यह लिंक, नीचे दी गई इमेज में दिखाया गया है. गड़बड़ी को समझने और उसे ठीक करने के लिए, Antigravity से भी मदद मांगी जा सकती है!

टर्मिनल आउटपुट में Cloud Build के फ़ेल होने का लॉग लिंक

4. ✨ सर्वाइविंग इमेज और क्लाउड स्टैंप

  1. अपने ब्लॉग का यूआरएल रीफ़्रेश करें.
  2. "Surviving the Cloud" नाम की नई ब्लॉग पोस्ट बनाएं और एक फ़ोटो अपलोड करें.
  3. इमेज के सबसे नीचे दाएं कोने में देखें:
    • 🏠 स्टैंप गायब हो गया है!
    • इसे रंगीन Cloud GCS स्टैंप (nanobanana_stamp_cloud.png) से बदल दिया गया है.
  4. किसी दूसरे कंटेनर को ज़बरदस्ती रीस्टार्ट करें. इससे चौथा वर्शन ट्रिगर होना चाहिए:
    gcloud run services update blog --region $GOOGLE_CLOUD_REGION --update-env-vars RESTART_TRIGGER=$(date +%s)
    
  5. पेज को रीफ़्रेश करें: SQLite डेटाबेस रीसेट होने के दौरान, इमेज बाइनरी, Google Cloud Storage में सुरक्षित रहती है! सीएलआई के ज़रिए पुष्टि करें:
    gcloud storage ls -l -r gs://$GCS_BUCKET/
    

यहां अपलोड किए गए उन ब्लॉब और मीडिया ऑब्जेक्ट की सूची दी गई है जो आपको Google Cloud Storage Browser Console में, अपने प्रोडक्शन बकेट (gs://$GCS_BUCKET) में दिख सकते हैं:

Google Cloud Storage Console में बकेट की जानकारी दिखाने वाली इमेज. इसमें इमेज के परसिस्टेंट ब्लॉब दिख रहे हैं

5. ⚠️ समस्या: नौकरी के लिए आवेदन सबमिट नहीं हो पा रहे हैं, यह बताने वाला बैनर

इमेज अपलोड करने पर, ActiveStorage ने डाइमेंशन और मेटाडेटा निकालने के लिए, विश्लेषण का काम (ActiveStorage::AnalyzeJob) कतार में लगा दिया.

हालांकि, Cloud Run फ़िलहाल सिर्फ़ एक वेब कंटेनर (puma) चला रहा है. Rails 8 में, Solid Queue बैकग्राउंड जॉब को डेटाबेस में सेव करता है, लेकिन कोई भी bundle exec rails solid_queue:start को एक्ज़ीक्यूट नहीं कर रहा है!

अपने ब्लॉग पेज पर सबसे ऊपर देखें: आपको blog/app/views/layouts/_check_stuck_jobs.html.erb की ओर से रेंडर किया गया, चेतावनी देने वाला एक बैनर दिखेगा.

हम इस समस्या को छठे चरण में ठीक करेंगे. इस चरण में, हम प्रोडक्शन-ग्रेड मल्टी-कंटेनर साइडकार आर्किटेक्चर पर अपग्रेड करेंगे. इसमें एक खास worker कंटेनर होगा, जो वेब ट्रैफ़िक से अलग Solid Queue को इंडिपेंडेंट तरीके से चलाएगा!

6. चौथे चरण की पुष्टि अपने-आप होना

अपने GCS कॉन्फ़िगरेशन और अटके हुए जॉब की टेलीमेट्री की पुष्टि करें:

just workshop-eval 4

7. पांचवां चरण: प्री-फ़्लाइट चेकलिस्ट: Cloud SQL, सीक्रेट, और डीबी कनेक्टिविटी

आपने तीसरे और चौथे चरण में, स्टेटलेस कंटेनर और Google Cloud Storage का इस्तेमाल करना सीख लिया है. वहीं, Terraform ने बैकग्राउंड में आपके प्रोडक्शन बैकएंड को तैयार कर दिया है!

हमारा पूरा तीन कंटेनर वाला प्रोडक्शन साइडकार आर्किटेक्चर (छठे चरण में 4 को डिप्लॉय करें) डिप्लॉय करने से पहले, यह चरण प्री-फ़्लाइट की जांच के तौर पर काम करता है. इससे डेटाबेस की स्थिति, कनेक्टिविटी, और सीक्रेट ऐक्सेस की पुष्टि की जा सकती है.

0. बूटस्ट्रैप एनवायरमेंट वैरिएबल

ज़रूरी सभी शेल वैरिएबल को सीधे तौर पर अपने Terraform आउटपुट से एक्सपोर्ट करें:

# Core project variables (should already be set from Step 0)
export GOOGLE_CLOUD_REGION="${GOOGLE_CLOUD_REGION:-europe-west1}"

# Compute runtime service account
export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)")
export RUN_SA="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"

# Cloud SQL instance name (from Terraform output, NOT hardcoded)
export SQL_INSTANCE_NAME=$(cd iac && terraform output -raw sql_instance_name 2>/dev/null || gcloud sql instances list --format='value(name)' --limit=1)

# Database password (from Terraform output)
export DB_PASSWORD=$(cd iac && terraform output -raw db_password 2>/dev/null || echo "CHANGE_ME")

# GCS bucket names
export GCS_BUCKET="${GOOGLE_CLOUD_PROJECT}-activestorage-prod"

echo "✅ Pre-flight environment variables ready:"
echo "   RUN_SA=$RUN_SA"
echo "   SQL_INSTANCE_NAME=$SQL_INSTANCE_NAME"
echo "   GCS_BUCKET=$GCS_BUCKET"

1. Cloud SQL की परफ़ॉर्मेंस की जांच

पुष्टि करें कि आपके मैनेज किए गए PostgreSQL इंस्टेंस की शुरुआती प्रोविज़निंग पूरी हो गई है और वह सही तरीके से काम कर रहा है:

echo "Checking instance: $SQL_INSTANCE_NAME"
gcloud sql instances describe $SQL_INSTANCE_NAME --format="value(state)"

आउटपुट RUNNABLE होना चाहिए.

2. (ज़रूरी नहीं) अपने लैपटॉप से डेटाबेस कनेक्टिविटी की जांच करना

प्रोडक्शन में, Cloud Run कंटेनर, Cloud SQL से सुरक्षित तरीके से कनेक्ट होते हैं. इसके लिए, वे एन्क्रिप्ट (सुरक्षित) किए गए साइडकार प्रॉक्सी (127.0.0.1:5432) का इस्तेमाल करते हैं. इससे डेटाबेस को सार्वजनिक इंटरनेट (0.0.0.0/0) पर नहीं दिखाया जाता.

ℹ️ ध्यान दें: यह चरण ज़रूरी नहीं है! Cloud Run में, आधिकारिक Cloud SQL Auth प्रॉक्सी साइडकार कंटेनर, एमटीएलएस कनेक्टिविटी को अपने-आप मैनेज करता है. वर्कशॉप पूरी करने के लिए, आपको स्थानीय तौर पर कुछ भी इंस्टॉल करने की ज़रूरत नहीं है.

अगर आपने अपनी मशीन पर cloud-sql-proxy और psql इंस्टॉल किए हैं और आपको अपने लैपटॉप से सीधे कनेक्टिविटी की पुष्टि करनी है, तो:

# Optional: test connectivity via Google-managed mTLS proxy
gcloud sql connect $SQL_INSTANCE_NAME --user=rails_user --database=rails_production

(अगर आपसे पासवर्ड मांगा जाता है, तो

$DB_PASSWORD

. अगर आपको यह तरीका नहीं अपनाना है, तो सीधे तीसरे चरण पर जाएं!)

3. Terraform की मदद से कॉन्फ़िगर किए गए सीक्रेट की जांच करना

git या कंटेनर एनवायरमेंट वैरिएबल में, डेटाबेस के पासवर्ड, एपीआई कुंजियां या Rails की मास्टर कुंजियां कभी भी सादे टेक्स्ट में सेव न करें. मॉडर्न क्लाउड आर्किटेक्चर में, हम ज़ीरो-ट्रस्ट रनटाइम इंजेक्शन के लिए Google Cloud Secret Manager का इस्तेमाल करते हैं.

ℹ️ Terraform ने पहले चरण में यह काम आपके लिए किया है:

  1. rails-master-key — इसका इस्तेमाल, रनटाइम के दौरान Rails क्रेडेंशियल को डिक्रिप्ट करने के लिए किया जाता है.
  2. rails-db-password — यह क्रिप्टोग्राफ़िक तौर पर सुरक्षित रैंडम पासवर्ड है, जो Cloud SQL उपयोगकर्ता से मेल खाता है.
  3. rails-admin-password — आपके शुरुआती एडमिन उपयोगकर्ता के लिए एक सुरक्षित पासवर्ड.

पुष्टि करें कि Secret Manager में आपके सीक्रेट मौजूद हों और चालू हों:

gcloud secrets list --filter="name:rails-"

Google Cloud Secret Manager Console में, कॉन्फ़िगर किए गए ऐप्लिकेशन के सीक्रेट की सूची

🔑 master.key को अपने लैपटॉप (लोकल सिंक) से सिंक करना

सुरक्षा की वजह से, blog/config/master.key को gitignored किया जाता है. इसलिए, हो सकता है कि आपके लोकल क्लोन में यह सुविधा अभी उपलब्ध न हो. इस स्निपेट को चलाएं, ताकि इसे Secret Manager से पुल किया जा सके. इससे आपके लोकल Rails टूल, क्रेडेंशियल को डिक्रिप्ट कर पाएंगे:

if [ ! -f blog/config/master.key ]; then
  echo "📥 Pulling rails-master-key from Secret Manager to local blog/config/master.key..."
  gcloud secrets versions access latest --secret=rails-master-key > blog/config/master.key
  echo "🔑 Created local blog/config/master.key! 🎉"
else
  echo "✅ Local blog/config/master.key already exists! 🚀"
fi

🧪 Playground: क्या आपको सिर्फ़ यह देखने के लिए कोई कस्टम सीक्रेट बनाना है कि यह कितना आसान है? Secret Manager सिर्फ़ Rails के लिए नहीं है! सीएलआई की एक आसान कमांड का इस्तेमाल करके, कोई भी सीक्रेट बनाया जा सकता है:

echo -n "MySuperSecretValue123!" | gcloud secrets create workshop-fun-secret --data-file=-
echo "✨ Created workshop-fun-secret in Secret Manager! 🪄"

4. सीक्रेट ऐक्सेसर की अनुमतियों की पुष्टि करना

Cloud Run कंटेनर को बूट के समय इन सीक्रेट को एनवायरमेंट वैरिएबल या वॉल्यूम माउंट के तौर पर माउंट करने के लिए, रनटाइम सेवा खाते ($RUN_SA) के पास हर सीक्रेट के लिए roles/secretmanager.secretAccessor की भूमिका होनी चाहिए.

पहले चरण में, Terraform ने यह अनुमति पहले ही दे दी है! rails-master-key पर आईएएम नीति बाइंडिंग की पुष्टि करें:

# Verify that Cloud Run runtime SA has Secret Accessor role
gcloud secrets get-iam-policy rails-master-key \
  --flatten="bindings[].members" \
  --format="table(bindings.role,bindings.members)" \
  --filter="bindings.members:$RUN_SA"

आपको ये चीज़ें दिखेंगी:

ROLE                                 MEMBERS
roles/secretmanager.secretAccessor   serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com

Cloud SQL Auth प्रॉक्सी की सुरक्षा की तुलना

5. उड़ान से पहले की पुष्टि अपने-आप होना

पांचवें चरण की ऑटोमेटेड टेस्ट सुइट चलाएं. इससे यह पुष्टि की जा सकेगी कि आपका डेटाबेस चालू है, सीक्रेट खाली नहीं हैं, और IAM अनुमतियां चालू हैं:

just workshop-eval 5

8. छठा चरण: 4 — एंटरप्राइज़ मल्टी-कंटेनर साइडकार (सबसे बेहतरीन तरीका) डिप्लॉय करना

अब हम सबसे अहम रेफ़रंस आर्किटेक्चर को असेंबल करते हैं: मल्टी-कंटेनर Cloud Run!

1. गोल्ड स्टैंडर्ड को वापस लाना

अपने रिपॉज़िटरी कॉन्फ़िगरेशन को कैननिकल main स्थिति पर वापस लाएं:

just workshop-restore-gold

2. तीन कंटेनर वाले प्रोडक्शन ब्लूप्रिंट की जांच करना

blog/compose.prod.yaml खोलें और आर्किटेक्चर की जांच करें:

Cloud Run मल्टी-कंटेनर प्रोडक्शन आर्किटेक्चर

graph LR
  Client[Internet / HTTPS Client] -->|Port 8080| Web[Web Container: Puma]
  Web -->|Localhost:5432| Proxy[Sidecar: Cloud SQL Auth Proxy]
  Worker[Worker Container: Solid Queue] -->|Localhost:5432| Proxy
  Proxy -->|IAM mTLS Tunnel| CloudSQL[(Google Cloud SQL PostgreSQL)]

प्रोडक्शन डिप्लॉयमेंट में, एक ही लोकल नेटवर्क शेयर करने वाले तीन कंटेनर एक साथ चलते हैं:

  1. web: Puma के ज़रिए पोर्ट 8080 पर एचटीटीपी ट्रैफ़िक दिखाता है.
  2. worker: बैकग्राउंड में प्रोसेस करने वाला कंटेनर, bundle exec rails solid_queue:start चला रहा है.
  3. cloudsql-proxy: 127.0.0.1:5432 से जुड़ा आधिकारिक Google Cloud SQL Auth प्रॉक्सी साइडकार (gcr.io/cloud-sql-connectors/cloud-sql-proxy:2).

3. Cloud Run जॉब की मदद से डेटाबेस माइग्रेशन करना

वेब ट्रैफ़िक को नए डिप्लॉयमेंट पर रूट करने से पहले, हमें Cloud SQL के ख़िलाफ़ डेटाबेस माइग्रेशन और शुरुआती सीडिंग को चलाना होगा.

⚖️ कंटेनर में माइग्रेशन कैसे चलाएं: दो रणनीतियां

कंटेनर वाले क्लाउड एनवायरमेंट में, डेटाबेस माइग्रेशन को लागू करने के दो सामान्य तरीके हैं:

  • विकल्प A: Docker Entrypoint में अपने-आप होने वाला बदलाव (entrypoint.sh कंटेनर बूट होने पर db:migrate को एक्ज़ीक्यूट करता है)
    • फ़ायदे: पूरी तरह से ऑटोमेटेड; डेवलपर को कमांड चलाने की ज़रूरत नहीं होती.
    • नुकसान: बिना सर्वर वाले ऑटोस्केलिंग में खतरनाक! जब Cloud Run, ज़्यादा ट्रैफ़िक की वजह से एक साथ 10 इंस्टेंस तक स्केल अप करता है, तो 10 कंटेनर एक साथ माइग्रेशन चलाने के लिए रेस करते हैं. इससे डेटाबेस लॉक हो जाता है, स्कीमा रेस की स्थितियां पैदा हो जाती हैं या बूट टाइमआउट हो जाता है.
  • दूसरा विकल्प: Cloud Run Job के ज़रिए साफ़ तौर पर (आर्किटेक्चर से जुड़ा हमारा विकल्प)
    • फ़ायदे: पूरा कंट्रोल, लेन-देन की सुरक्षा, और रेस की कोई शर्त नहीं. यह एक बार चलने वाला कंटेनर टास्क है, जो वेब ट्रैफ़िक को मैनेज करने से पूरी तरह से अलग है. अगर माइग्रेशन पूरा नहीं होता है, तो वेब पर विज्ञापन दिखाने की प्रोसेस पर कोई असर नहीं पड़ता.
    • कमियां: डिप्लॉयमेंट से पहले, सीएलआई जॉब या सीआई/सीडी चरण को ट्रिगर करना ज़रूरी है.

हम ज़्यादा से ज़्यादा प्रोडक्शन रिलायबिलिटी के लिए, विकल्प B चुनते हैं.

⚠️ ज़रूरी: DATABASE_URL फ़ॉर्मैट और Ruby 3.4.5 RFC 3986 Strictness

Cloud Run जॉब, नेटिव Unix सॉकेट प्रॉक्सी (/cloudsql/PROJECT:REGION:INSTANCE) का इस्तेमाल करके Cloud SQL से कनेक्ट होते हैं. DATABASE_URL में ट्रिपल-स्लैश फ़ॉर्मैट का इस्तेमाल करना ज़रूरी है:

postgresql:///rails_production?user=rails_user&password=PASS&host=/cloudsql/PROJECT:REGION:INSTANCE
# Core environment variables for database migration & initial admin seed
export GOOGLE_CLOUD_ACCOUNT="${GOOGLE_CLOUD_ACCOUNT:-$(gcloud config get-value account)}"
echo "Admin user will be seeded for: $GOOGLE_CLOUD_ACCOUNT"

# Get the latest blog image from Cloud Run (jobs don't support --source)
export BLOG_IMAGE=$(gcloud run services describe blog --region=$GOOGLE_CLOUD_REGION --format='value(spec.template.spec.containers[0].image)')

# Build the DATABASE_URL in triple-slash format (required for Unix socket proxy)
export DB_PASSWORD=$(gcloud secrets versions access latest --secret=rails-db-password)
export CLOUDSQL_CONNECTION="${GOOGLE_CLOUD_PROJECT}:${GOOGLE_CLOUD_REGION}:${SQL_INSTANCE_NAME}"
export DB_URL="postgresql:///rails_production?user=rails_user&password=${DB_PASSWORD}&host=/cloudsql/${CLOUDSQL_CONNECTION}"

# Create migration job — note ALL 4 database URL env vars and GOOGLE_CLOUD_ACCOUNT for seed user creation
gcloud run jobs create rails-migrate \
  --image=$BLOG_IMAGE \
  --command "bin/rails" \
  --args "db:prepare" \
  --set-env-vars="DATABASE_URL=${DB_URL},DATABASE_QUEUE_URL=${DB_URL},DATABASE_CACHE_URL=${DB_URL},DATABASE_CABLE_URL=${DB_URL},GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},GOOGLE_CLOUD_ACCOUNT=${GOOGLE_CLOUD_ACCOUNT}" \
  --set-secrets="RAILS_MASTER_KEY=rails-master-key:latest" \
  --set-cloudsql-instances="${CLOUDSQL_CONNECTION}" \
  --service-account=$RUN_SA \
  --region $GOOGLE_CLOUD_REGION 2>/dev/null || true

# Execute migration job
gcloud run jobs execute rails-migrate --region $GOOGLE_CLOUD_REGION --wait

💡 Rails 8 मल्टी-डेटाबेस: ऐप्लिकेशन, हर database.yml के लिए चार डेटाबेस (प्राइमरी, क्यू, कैश मेमोरी, केबल) का इस्तेमाल करता है. सभी चार DATABASE_*_URL एनवायरमेंट वैरिएबल, एक ही Cloud SQL इंस्टेंस पर पॉइंट करने चाहिए. ऐसा न होने पर, Solid Queue/Cache/Cable टेबल नहीं बनेंगी.

db:prepare के बाद, सॉलिड क्यू/कैश/केबल स्कीमा लोड करें:

# Schema load for queue, cache, and cable databases (creates solid_queue_jobs, etc.)
gcloud run jobs update rails-migrate \
  --command "bash" \
  --args "-c,DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bin/rails db:schema:load:queue db:schema:load:cache db:schema:load:cable" \
  --region $GOOGLE_CLOUD_REGION

gcloud run jobs execute rails-migrate --region $GOOGLE_CLOUD_REGION --wait

gcloud run jobs executions के आउटपुट में JOBNAME के बारे में जानकारी दी गई हैऊपर दिए गए फ़िगर में,

gcloud run jobs executions describe $JOBNAME

Google Cloud Run Jobs Console में rails-migrate जॉब के 'सफल हुआ' स्टेटस को दिखाया गया हैGoogle Cloud Run Jobs Console की इमेज

rails-migrate

execution Succeeded

4. चौथा डिप्लॉयमेंट: Docker Compose की मदद से, मल्टी-कंटेनर Cloud Run डिप्लॉय करना

अब सीधे compose.prod.yaml से, तीन कंटेनर वाला ओरिजनल प्रोडक्शन स्टैक (web, worker, cloudsql-proxy) डिप्लॉय करें:

# 1. Self-healing environment exports (guarantees no missing master key or DB password)
export RAILS_MASTER_KEY="${RAILS_MASTER_KEY:-$(cat config/master.key 2>/dev/null || gcloud secrets versions access latest --secret=rails-master-key)}"
export DB_PASSWORD=$(gcloud secrets versions access latest --secret=rails-db-password)
export CLOUDSQL_INSTANCE_CONNECTION_NAME="${GOOGLE_CLOUD_PROJECT}:${GOOGLE_CLOUD_REGION}:${SQL_INSTANCE_NAME}"

# 2. Database credentials & GCS attachments
export DB_USER="rails_user"
export DB_NAME="rails_production"
export GCS_BUCKET="${GCS_BUCKET}"
export ACTIVE_STORAGE_SERVICE="google"
export GOOGLE_CLOUD_ACCOUNT="${GOOGLE_CLOUD_ACCOUNT:-$(gcloud config get-value account)}"
export GEMINI_API_KEY="${GEMINI_API_KEY:-dummy-key}"

# 3. Deploy the full multi-container sidecar architecture to Cloud Run
gcloud run compose up compose.prod.yaml \
  --region=$GOOGLE_CLOUD_REGION \
  --allow-unauthenticated

Google Cloud Run Console के कंटेनर टैब में, तीन साइडकार कंटेनर दिखाए गए हैंGoogle Cloud Run Console: ‘कंटेनर' टैब में तीनों साइडकार कंटेनर दिख रहे हैं (

cloudsql-proxy

,

web

,

worker

)

💡 यूज़र इंटरफ़ेस (यूआई) में गड़बड़ी / Console में गड़बड़ी: Console के ड्रॉपडाउन में, आपको दिख सकता है कि Cloud Run ने सबसे ऊपर वाली एंट्री को Ingress container: cloudsql-proxy के तौर पर लेबल किया है. चिंता न करें! यह Google Cloud Console में सिर्फ़ एक विज़ुअल यूज़र इंटरफ़ेस (यूआई) गड़बड़ी है. इसे कंटेनर की डिपेंडेंसी के क्रम की वजह से हुई गड़बड़ी के तौर पर #149 में ट्रैक किया गया है. असल में, web ही एक ऐसा कंटेनर है जो एचटीटीपी पोर्ट 8080 पर सुनता है और 100% इनग्रेस वेब ट्रैफ़िक को मैनेज करता है. वहीं, cloudsql-proxy सिर्फ़ पोर्ट 5432 पर प्राइवेट PostgreSQL ट्रैफ़िक को मैनेज करता है!

5. ✨ शानदार पल: कोई चेतावनी नहीं मिली और क्लाउड पर डेटा पूरी तरह से सेव रहा!

गहरी सांस लें और अपनी स्क्रीन पर देखें: सभी चेतावनी वाले बैनर गायब हो गए हैं! 🪄

Cloud Run पर प्रोडक्शन ब्लॉग, जिसमें कोई चेतावनी नहीं है और Cloud Persistent Post शामिल हैप्रोडक्शन Rails 8 ब्लॉग: बेहतरीन यूज़र इंटरफ़ेस (यूआई), कोई चेतावनी वाला बैनर नहीं, और Cloud SQL की स्थिति हमेशा बनी रहती है!

अब यह ऐप्लिकेशन आधिकारिक तौर पर प्रोडक्शन-ग्रेड और क्लाउड-नेटिव है:

  • यह सुरक्षित एमटीएलएस टनलिंग के ज़रिए, मैनेज किए गए Google Cloud SQL (PostgreSQL) की मदद से काम करता है.
  • मीडिया को निजी Google Cloud Storage में सुरक्षित तरीके से सेव किया जाता है. साथ ही, IAM blob signing की सुविधा का इस्तेमाल किया जाता है.
  • अस्थायी स्टोरेज के बारे में कोई चेतावनी नहीं मिली है और न ही कोई काम रुका है.

Cloud Run का यूआरएल खोलें:

  1. टेलीमेट्री बैज देखें:
    • [CLOUD PERSISTENT 🐘 ☁️] की पुष्टि हो गई है!
    • फ़ुटर में मौजूद Google Cloud Run और GCS, दोनों बैज हरे रंग के दिखते हैं!
    • जॉब के रुकने की चेतावनी देने वाला बैनर अब नहीं दिखता!
  2. ब्लॉग पोस्ट और टिप्पणियां बनाना.
  3. अपनी पसंद के मुताबिक जितनी बार चाहें उतनी बार रीस्टार्ट या फिर से डिप्लॉय करें: आपका डेटा, पोस्ट, टिप्पणियां, और ऐसेट Cloud SQL और GCS में हमेशा के लिए सुरक्षित रहती हैं!

6. छठे चरण की पुष्टि अपने-आप होना

एक से ज़्यादा कंटेनर वाले कॉन्फ़िगरेशन की पुष्टि करें:

just workshop-eval 6

9. सातवां चरण: जनरेटिव एआई पाइपलाइन, पॉडकास्टिफ़ायर, और GCS ट्रेज़र हंट 🏴‍☠️

डेडिकेटेड कंटेनर में Solid Queue के चालू होने और Google Cloud Storage के ऐक्टिव होने पर, हम एसिंक्रोनस जनरेटिव एआई का इस्तेमाल कर सकते हैं!

1. NanoBanana Vintage Cover Generator (इस्तेमाल के लिए तैयार जेन एआई पाइपलाइन)

NanoBanana का मैस्कॉट

अच्छी खबर: यह सुविधा, कोडबेस में पहले से ही पूरी तरह से लागू की जा चुकी है! आपको कोई कोड लिखने की ज़रूरत नहीं है. यहां आपका काम, क्लाउड GenAI की एसिंक्रोनस पाइपलाइन को ट्रिगर करना और उसे काम करते हुए देखना है.

🧠 यह सुविधा पर्दे के पीछे कैसे काम करती है

  • पुष्टि करना: इसके लिए, किसी एपीआई पासकोड की ज़रूरत नहीं है! यह Cloud Run रनटाइम सेवा खाते के ज़रिए, ऐप्लिकेशन के डिफ़ॉल्ट क्रेडेंशियल (Vertex AI पर roles/aiplatform.user) का इस्तेमाल अपने-आप करता है. (इसके अलावा, अगर GEMINI_API_KEY दिया गया है, तो यह सीधे Gemini API को कॉल करता है).
  • पाइपलाइन: जब बिना कवर इमेज के कोई लेख बनाया जाता है, तो after_commit कॉलबैक, GenerateCoverImageJob को सॉलिड क्यू में शामिल करता है.
  • मॉडल: यह Google के मल्टीमॉडल मॉडल (Gemini 2.5 Flash Image / Imagen on Vertex AI) को, 1960 के दशक के इटैलियन फ़िल्म के ओरिजनल पोस्टर ("Locandina di un film 1960") को जनरेट करने के लिए प्रॉम्प्ट करता है. इसमें केले का कैमियो और चमकदार रूबी "8" भी शामिल है.
  • डाइनैमिक प्रॉवनेंस वॉटरमार्क: यह libvips का इस्तेमाल करके, इमेज के कोने पर डाइनैमिक तरीके से विज़ुअल बैज लगाता है. जैसे, GCS पर रंगीन क्लाउड स्टैंप.
  • टर्बो स्ट्रीम हॉट-स्वैप: इमेज अटैच होने पर, Turbo::StreamsChannel.broadcast_refresh_to(post) पेज को मैन्युअल तरीके से रीलोड किए बिना, लाइव तौर पर ब्राउज़र को अपडेट करता है!

NanoBanana के एआई का असिंक्रोनस आर्किटेक्चर सीक्वेंस डायग्राम

📐 Mermaid सीक्वेंस डायग्राम का सोर्स देखना

sequenceDiagram
  autonumber
  actor User as 👤 Reader / Author
  participant Web as 🌐 Web (Puma)
  participant DB as 🐘 Cloud SQL (Solid Queue)
  participant Worker as ⚙️ Worker (Solid Queue)
  participant Vertex as 🧠 Vertex AI (Gemini Flash / Imagen)
  participant GCS as ☁️ Google Cloud Storage

  User->>Web: POST /posts (Title & Body, No Cover)
  Web->>DB: 1. Save Post & Enqueue GenerateCoverImageJob
  Web-->>User: Redirect to Post (turbo_stream subscribed)

  Worker->>DB: 2. Dequeue GenerateCoverImageJob
  Worker->>Vertex: 3. Prompt for 1960s Italian Poster (ADC auth)
  Vertex-->>Worker: 4. Raw Image Buffer
  Worker->>Worker: 5. Stamp Provenance Watermark (libvips)
  Worker->>GCS: 6. Attach Blob via ActiveStorage (IAM signBlob)
  Worker->>Web: 7. Turbo::StreamsChannel.broadcast_refresh_to(post)
  Web-->>User: ⚡ Live UI Hot-Swap: Poster magically appears!

🧪 इसे लाइव आज़माएं!

इसे दो तरीकों से ट्रिगर किया जा सकता है:

  • विकल्प A (वेब यूज़र इंटरफ़ेस): नई पोस्ट पर क्लिक करें. इसके बाद, "Ruby on Rails 8 के साथ सर्वरलेस आर्किटेक्चर" जैसा कोई टाइटल डालें. कुछ कॉन्टेंट लिखें और कवर इमेज फ़ाइल इनपुट को खाली छोड़ दें. पोस्ट बनाएं पर क्लिक करें.
  • दूसरा विकल्प (सीएलआई रनर): इसे अपने टर्मिनल से चलाएं:
    bin/rails runner 'Post.create!(title: "Serverless Architecture with Ruby on Rails 8", body: "Exploring asynchronous AI pipelines with Solid Queue and NanoBanana!")'
    

लगभग 15 से 30 सेकंड तक इंतज़ार करें: Cloud Run में Solid Queue वर्कर के लॉग देखें. विंटेज पोस्टर, सीधे तौर पर आपकी पोस्ट पर दिखेगा!

📸 TODO(riccardo): add screenshot of a blog post with an AI-generated vintage 1960s Italian movie poster featuring a cameo banana and ruby 8

2. दो भाषाओं में पॉडकास्ट बनाने की सुविधा देने वाली क्वेस्ट (एंटीग्रैविटी कोडिंग की प्रैक्टिकल एक्सर्साइज़)

⚠️ अहम सूचना: ऊपर दिए गए कवर जनरेटर के उलट, यह सुविधा अभी लागू नहीं की गई है!

blog/app/jobs/podcastifier_job.rb खोलने पर, आपको खाली स्कैफ़ोल्ड स्टब दिखेगा:

class PodcastifierJob < ApplicationJob
  queue_as :default

  def perform(post_id)
    # TODO(student): COMPLETE_ME — Pair program with Google Antigravity to implement
    # Italian TTS podcast generation using voice 'it-IT-Wavenet-A' via Cloud TTS / ADC!
  end
end

इस हैंड्स-ऑन एक्सरसाइज़ में, आपको इस सुविधा को पूरा करने के लिए Google Antigravity के साथ मिलकर काम करना है:

  1. Prompt Antigravity:"app/jobs/podcastifier_job.rb में PodcastifierJob को लागू करने में मेरी मदद करो. इसे पोस्ट को फ़ेच करना चाहिए. साथ ही, Google Cloud Text-to-Speech (ADC क्रेडेंशियल के ज़रिए, भाषा कोड ‘it-IT' के साथ आवाज़ ‘it-IT-Wavenet-A') का इस्तेमाल करके, इटैलियन भाषा में ऑडियो की खास जानकारी को ट्रांसलेट या सिंथेसाइज़ करना चाहिए. इसके अलावा, इसे ActiveStorage का इस्तेमाल करके, ऑडियो फ़ाइल को post.podcast_audio_it से अटैच करना चाहिए!"
  2. देखने के लिए प्लेयर जोड़ें: app/views/posts/show.html.erb में, @post.podcast_audio_it.attached? होने पर, HTML5 प्लेयर जोड़ें.
  3. सिंथेसिस ट्रिगर करना: सेव करने पर, Solid Queue टेक्स्ट-टू-स्पीच की प्रोसेस को बैकग्राउंड में एसिंक्रोनस तरीके से पूरा करेगा.

Podcastifier का द्विभाषी यूज़र इंटरफ़ेस (यूआई), जिसमें दो ऑडियो प्लेयर हैं

🎧 Podcastifier के आउटपुट के सैंपल:

💡 क्या आपको मदद चाहिए या कोई समस्या आ रही है? जांच किया गया पूरा रेफ़रंस समाधान, solutions/podcastifier ब्रांच पर उपलब्ध है. git diff solutions/podcastifier की मदद से, इसे कभी भी देखा जा सकता है.

3. [ज़रूरी नहीं] 🏴‍☠️ GCS Treasure Hunt (Console Blob Recovery)

ℹ️ ज़रूरी शर्तें पूरी होने की जांच: लोकल

cloud-sql-proxy

CLI ज़रूरी है यह वैकल्पिक तरीका है. इससे आपके लोकल लैपटॉप को सीधे तौर पर Google Cloud SQL से कनेक्ट किया जाता है. इसके लिए, एन्क्रिप्ट (सुरक्षित) किए गए mTLS टनल का इस्तेमाल किया जाता है. देखें कि आपने CLI प्रॉक्सी इंस्टॉल की है या नहीं:

which cloud-sql-proxy
  • अगर इंस्टॉल है: नीचे दिया गया तरीका अपनाएं!
  • अगर आपने इसे इंस्टॉल नहीं किया है और आपको यह क्वेस्ट पूरी करनी है, तो: इसे इंस्टॉल करें:
    # Linux (x86_64)
    curl -o /tmp/cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.14.0/cloud-sql-proxy.linux.amd64
    chmod +x /tmp/cloud-sql-proxy && sudo mv /tmp/cloud-sql-proxy /usr/local/bin/cloud-sql-proxy
    # macOS (Homebrew)
    brew install cloud-sql-proxy
    
  • इसके अलावा: सातवें चरण पर जाकर, अपने-आप पुष्टि होने की सुविधा का इस्तेमाल करें!

क्या आपको वह फ़ोटो याद है जिसे आपने चौथे चरण में अपलोड किया था? कंटेनर के रीस्टार्ट होने से पहले, इस फ़ोटो को मिटा दिया गया था. वह इमेज फ़ाइल अब भी आपके निजी GCS बकेट में "अनाथ ब्लॉब" के तौर पर सुरक्षित है!

आइए, Rails कंसोल का इस्तेमाल करके इसे ठीक करें और इसे Cloud SQL पोस्ट से अटैच करें:

# Connect to your production database via Rails console and Cloud SQL Proxy
cloud-sql-proxy --port 5432 ${GOOGLE_CLOUD_PROJECT}:${GOOGLE_CLOUD_REGION}:${SQL_INSTANCE_NAME} &
DATABASE_URL=postgresql://rails_user:${DB_PASSWORD}@127.0.0.1:5432/rails_production bin/rails c

Rails कंसोल में जाकर:

# 1. Search for orphaned GCS blobs in ActiveStorage
orphan_blobs = ActiveStorage::Blob.where.missing(:attachments)
puts "🏴‍☠️ Found #{orphan_blobs.count} orphaned GCS blobs!"

# 2. Attach the surviving blob to your latest post
if orphan_blobs.any?
  post = Post.last
  post.cover_image.attach(orphan_blobs.first)
  post.save!
  puts "🎉 Rescued blob #{orphan_blobs.first.filename} attached to '#{post.title}'!"
end
exit

📸 TODO(riccardo): add screenshot of the interactive Rails console executing the GCS Treasure Hunt snippet and rescuing orphaned ActiveStorage blobs

अपने ब्लॉग को रीफ़्रेश करें: चौथे चरण में अपलोड की गई फ़ोटो फिर से दिखने लगेगी. साथ ही, यह Cloud SQL पोस्ट से हमेशा के लिए जुड़ जाएगी!

4. सातवें चरण की पुष्टि अपने-आप होना

जनरेटिव एआई से जुड़ी नौकरियों और ऐसेट की पुष्टि करें:

just workshop-eval 7

10. आठवां चरण: अपने हिसाब से विकल्प चुनना / ऐडवांस क्वेस्ट 🏆

अब जब आपने कैननिकल रेफ़रंस आर्किटेक्चर के बारे में जान लिया है, तो अपनी ग्रेजुएशन क्वेस्ट चुनें!

🛡️ पहली क्वेस्ट: Zero-Trust Google IAP (Identity-Aware Proxy)

  • कठिनाई का लेवल: सामान्य (एंटरप्राइज़ सिक्योरिटी)
  • लक्ष्य: अपने Cloud Run ऐप्लिकेशन को लॉक करें, ताकि सिर्फ़ पुष्टि किए गए Google / Gmail खाते ही इसे ऐक्सेस कर सकें. इससे पासवर्ड से लॉगिन करने की सुविधा पूरी तरह से बंद हो जाएगी!
  • यह सुविधा कैसे काम करती है:
    1. एक्सटर्नल एचटीटीपीएस ऐप्लिकेशन लोड बैलेंसर, Google OAuth को बंद कर देता है और Cloud Run तक ट्रैफ़िक पहुंचने से पहले पहचान की पुष्टि करता है.
    2. Google, पुष्टि किए गए पहचान हेडर (X-Goog-Authenticated-User-Email) फ़ॉरवर्ड करता है.
    3. Rails, blog/app/controllers/concerns/iap_authenticatable.rb के ज़रिए पुष्टि की गई Google आइडेंटिटी में अपने-आप लॉग इन हो जाता है:
      module IapAuthenticatable
        extend ActiveSupport::Concern
        included { before_action :authenticate_via_iap }
      
        private
        def authenticate_via_iap
          return unless (raw = request.headers["X-Goog-Authenticated-User-Email"]).present?
          email = raw.sub(/^accounts\.google\.com:/, "")
          user = User.find_or_create_by!(email_address: email) { |u| u.password = SecureRandom.hex(16) }
          start_new_session_for(user) unless authenticated?
        end
      end
      
    4. iac/iap.tf में enable_iap = true की मदद से Terraform मॉड्यूल चालू करें. साथ ही, उन Google खातों के बारे में बताएं जिन्हें अनुमति दी गई है:
      iap_allowed_users = [var.google_cloud_account]
      

आईएपी बैनर से लॉगिन की पहचान की गई

📊 Quest 2: प्रोडक्शन एसआरई टेलीमेट्री और Cloud Logging

  • कठिनाई का लेवल: सामान्य (जांचने की क्षमता)
  • लक्ष्य: स्ट्रक्चर्ड JSON फ़ॉर्मैट में ऐप्लिकेशन के लॉग को सीधे Google Cloud Logging पर स्ट्रीम करना. साथ ही, Cloud Error Reporting की मदद से प्रोडक्शन में होने वाली गड़बड़ियों को रीयल-टाइम में पकड़ना.
  • यह सुविधा कैसे काम करती है:
    • blog/config/environments/production.rb को कॉन्फ़िगर करें, ताकि वह GCP ट्रेस लेबल के साथ स्ट्रक्चर्ड JSON लॉग जनरेट कर सके.
    • जान-बूझकर टेस्ट अपवाद को ट्रिगर करें और देखें कि Google Cloud Error Reporting, गड़बड़ी को ग्रुप करके आपको तुरंत सूचना देता है या नहीं.

📸 TODO(riccardo): add screenshot of Google Cloud Error Reporting showing grouped production exceptions and Cloud Logging structured JSON payload with trace labels

🧠 Quest 3: pgvector सिमैंटिक सर्च और Gemini RAG

  • कठिनाई का लेवल: मुश्किल (जेन एआई कैपस्टोन)
  • लक्ष्य: Cloud SQL पर PostgreSQL में सेव की गई वेक्टर एम्बेडिंग का इस्तेमाल करके, कॉन्सेप्ट के आधार पर लेखों को खोजना.
  • यह सुविधा कैसे काम करती है:
    • अपने Cloud SQL PostgreSQL इंस्टेंस पर vector एक्सटेंशन चालू करें:
      CREATE EXTENSION IF NOT EXISTS vector;
      
    • Post#after_save पर neighbor gem को blog/Gemfile में जोड़ें और Gemini (text-embedding-004) की मदद से टेक्स्ट एम्बेडिंग जनरेट करें.
    • टर्बो स्ट्रीम की मदद से, सिमैंटिक सर्च बार को बेहतर बनाने के लिए, कोसाइन डिस्टेंस क्वेरी (<=>) का इस्तेमाल करें!

📸 TODO(riccardo): add screenshot of the live blog semantic search bar returning conceptual matches with cosine similarity scores

⚡ चौथा क्वेस्ट: एसईओ और परफ़ॉर्मेंस ऑडिट असिस्टेंट

  • कठिनाई का लेवल: आसान / मज़ेदार (डेवलपर अनुभव)
  • लक्ष्य: Antigravity और Speedgrapher टूल का इस्तेमाल करके, Core Web Vitals, सबसे बड़े एलिमेंट को रेंडर करने में लगने वाला समय (एलसीपी), और फ़्लेश-किनकैड / फ़ॉग रीडेबिलिटी इंडेक्स की जांच करना.

📸 TODO(riccardo): add screenshot of Speedgrapher / Lighthouse SEO and Core Web Vitals audit summary

🤔 Curiosity Box: Getting a Live Rails Console on Cloud Run

💡 सवाल: आम तौर पर, डेवलपर ट्रेडिशनल वीएम या Heroku-स्टाइल वाले PaaS प्लैटफ़ॉर्म पर, चालू इंस्टेंस में एसएसएच करते हैं या प्रोडक्शन डेटा की जांच करने या उसे ठीक करने के लिए, heroku run rails console का इस्तेमाल करते हैं. Cloud Run-नेटिव का मतलब क्या है और इसे कैसे सुरक्षित किया जाता है?

क्यों

gcloud run exec

Cloud Run सेवाओं के लिए मौजूद नहीं है

Cloud Run एक सर्वरलेस प्लैटफ़ॉर्म है: आपका कंटेनर, एक जैसे सैकड़ों इंस्टेंस के तौर पर चल सकता है. हालांकि, इसमें कोई स्टेबल आइडेंटिटी या पता करने योग्य शेल नहीं होता. यह Kubernetes (kubectl exec) से अलग है. इसमें किसी पॉड में एक नाम वाला सॉकेट होता है, जिससे अटैच किया जा सकता है.

# ❌ This does NOT exist for Cloud Run Services:
gcloud run services exec blog --region europe-west1 -- rails console

# ✅ This exists for Cloud Run JOBS (non-interactive, one-shot tasks):
gcloud run jobs execute my-job --region europe-west1 --wait

GCP के साथ काम करने वाले चार पैटर्न

पैटर्न

निर्देश

क्या यह इंटरैक्टिव है?

सुरक्षा

1. लोकल प्रॉक्सी + रिमोट डीबी

DATABASE_URL=... rails console

✅ पूरी तरह से

🔒 Cloud SQL Auth Proxy mTLS

2. Cloud Run जॉब (एक बार चलने वाला)

gcloud run jobs execute --wait

❌ सिर्फ़ स्क्रिप्ट

🔒 इसके लिए, आईएएम की भूमिका ज़रूरी है

3. Web Console gem + IAP

ब्राउज़र → /rails/console

✅ पूरी तरह से

🛡️ IAP Zero-Trust

4. Cloud Shell + प्रॉक्सी

Cloud Shell → bin/rails c

✅ पूरी तरह से

🔒 Google Identity

पैटर्न 1 (डेटा की जांच करने के लिए सुझाव दिया गया है): Cloud SQL Auth प्रॉक्सी के ज़रिए, Cloud SQL PostgreSQL से सीधे तौर पर कम्यूनिकेट करने वाली लोकल Rails कंसोल चलाएं:

# In one terminal: start the auth proxy
cloud-sql-proxy rails8-fl-20260907b-xm8ko4:europe-west1:your-instance

# In another terminal: open a read-write or sandbox console
DATABASE_URL=postgresql://rails_user:${DB_PASSWORD}@127.0.0.1:5432/rails_production \
  bin/rails console --sandbox

आपको नेटवर्क के संपर्क में आए बिना, पूरी तरह से इंटरैक्टिव आईआरबी मिलता है. Cloud SQL प्रॉक्सी, यूनिक्स डोमेन सॉकेट या लूपबैक पर mTLS का इस्तेमाल करती है.

तीसरा पैटर्न (वेब कंसोल + आईएपी ज़ीरो-ट्रस्ट, ब्राउज़र का सुरक्षित पाथ):

web-console gem, ब्राउज़र पर आधारित IRB सेशन उपलब्ध कराता है. सुरक्षा के बिना यह सुरक्षा से जुड़ी गंभीर समस्या है. इसे कभी भी सार्वजनिक तौर पर शेयर न करें. हालांकि, Google IAP (Quest 1) के साथ इस्तेमाल करने पर, अटैक सरफेस कम हो जाता है: आपकी अनुमति वाली सूची में शामिल, Google की सिर्फ़ वे पहचानें /rails/console एंडपॉइंट तक पहुंच सकती हैं जिनकी पुष्टि हो चुकी है.

# Gemfile — only load in development/staging, never production without IAP!
gem "web-console", group: :development

# config/environments/production.rb — if IAP is enabled:
config.web_console.allowed_ips = ["0.0.0.0/0"]  # IAP terminates auth before us

⚠️ पैटर्न 3 के लिए, Quest 1 (IAP) को पहले चालू करना ज़रूरी है. इसके बिना, सार्वजनिक यूआरएल पर /rails/console का इस्तेमाल करने का मतलब है कि आपने अपने सर्वर रूम को खुला छोड़ दिया है. IAP की मदद से, यह ऑपरेटर के लिए एक बेहतरीन टूल बन जाता है. साथ ही, इसे Google के ज़ीरो-ट्रस्ट सुरक्षा मॉडल के तहत सुरक्षित किया जाता है.

Antigravity से पूछें: "मुझे

rails console --sandbox

को Cloud SQL Auth प्रॉक्सी का इस्तेमाल करके, Cloud SQL प्रोडक्शन डेटाबेस के ख़िलाफ़ सुरक्षित तरीके से टेस्ट किया जा सकता है."

🏆 The Hive पर ग्रैजुएट होना: प्रॉक्टर से पुष्टि किया गया काम का सबूत

चुनी गई क्वेस्ट पूरी करने के बाद, The Hive लीडरबोर्ड पर जाकर, आठवें चरण की ग्रेजुएशन ट्रॉफ़ी 🏆 पर दावा करें:

  1. GitHub पर अपनी क्वेस्ट सबमिट करें:
    • आधिकारिक रिपॉज़िटरी पर नई समस्या खोलें: github.com/palladius/rails8-app-on-gcp/issues/new
    • टाइटल का फ़ॉर्मैट: 🎓 [Step 8 Completed] :
    • ईमेल के मुख्य हिस्से में, आपने जो काम किया है उसके बारे में कम शब्दों में जानकारी दें. साथ ही, Cloud Run पर डिप्लॉय किए गए अपने लाइव ऐप्लिकेशन का लिंक शामिल करें.
  2. अपने Cloud Run ऐप्लिकेशन को समस्या से कनेक्ट करें:
    • अपनी समस्या का नंबर नोट करें. जैसे, 88 या पूरा यूआरएल https://github.com/palladius/rails8-app-on-gcp/issues/88.
    • अपनी Cloud Run सेवा में STEP_8_GHI एनवायरमेंट वैरिएबल इंजेक्ट करें:
      gcloud run services update blog \
        --region europe-west1 \
        --update-env-vars STEP_8_GHI=<YOUR_ISSUE_NUMBER>
      
    • पुष्टि करें कि आपका /status.json एंडपॉइंट अब आपकी क्वेस्ट की जानकारी देता है:
      curl -s https://<YOUR_APP>.run.app/status.json | jq .quest
      
      आपको यह दिखना चाहिए:
      {
        "step_8_completed": true,
        "ghi_issue": 88,
        "ghi_url": "https://github.com/palladius/rails8-app-on-gcp/issues/88"
      }
      
  3. प्रॉक्टर से समीक्षा करवाएं और गोल्डन ट्रॉफ़ी अनलॉक करें:
    • The Hive लीडरबोर्ड देखें: आपकी लाइन में अब ऐंबर बैज दिखेगा: ⏳ GHI #XX review pending.
    • वर्कशॉप के प्रॉक्टर (@palladius, @emilianodellacasa या @ricc) से, अपने डिप्लॉयमेंट की जांच करने के लिए कहें.
    • जैसे ही कोई प्रॉक्टर आपकी समस्या पर LGTM कॉमेंट करेगा, The Hive आपकी प्रोग्रेस को अपने-आप 8/8 🏆 पर सेट कर देगा. साथ ही, आपको सुनहरे/बैंगनी रंग का चमकता हुआ बैज और एक स्थायी ट्रॉफ़ी मिलेगी. यह ट्रॉफ़ी सीधे तौर पर आपकी कैपस्टोन समस्या से जुड़ी होगी!

11. नतीजा और गैर-ज़रूरी डेटा हटाना 🎓

बधाई हो! 🎉

आपने Google Cloud Platform पर, प्रोडक्शन-ग्रेड और एंटरप्राइज़ के लिए तैयार Rails 8 ऐप्लिकेशन बनाया और उसे डिप्लॉय किया है:

  • ज़ीरो-ब्रांच प्रोग्रेशन: main पर टाइम-मशीन ओवरले की मदद से, मॉडर्न वर्कफ़्लो में महारत हासिल की.
  • Cloud Storage: इसमें आईएएम के साथ, निजी ऑब्जेक्ट स्टोरेज को ज़रूरत के हिसाब से बढ़ाया जा सकता है (iam: true).
  • Cloud SQL: मैनेज किया गया PostgreSQL, जिसे Cloud SQL Auth प्रॉक्सी mTLS टनल की मदद से सुरक्षित किया गया है.
  • Secret Manager: इसमें सादे टेक्स्ट वाले क्रेडेंशियल या .env फ़ाइलें लीक नहीं होती हैं.
  • Cloud Run मल्टी-कंटेनर: आइसोलेटेड Puma वेब, Solid Queue वर्कर, और प्रॉक्सी साइडकार.
  • जनरेटिव एआई: Vertex AI की मदद से, एसिंक्रोनस तरीके से विंटेज पोस्टर जनरेट करना और टीटीएस पॉडकास्ट सिंथेसिस करना.
  • क्वेस्ट: ज़ीरो-ट्रस्ट आईएपी, एसआरई ऑब्ज़र्वेबिलिटी, और pgvector एम्बेडिंग!

🧹 संसाधन हटाना

वर्कशॉप पूरी करने के बाद, आपसे शुल्क न लिया जाए, इसके लिए पक्का करें कि आपने Google Cloud संसाधनों को बंद कर दिया हो! अपने एनवायरमेंट के हिसाब से सबसे सही तरीका चुनें:

अगर आपको किसी ऐसे मौजूदा या शेयर किए गए Google Cloud प्रोजेक्ट का इस्तेमाल करना है जिसमें अन्य संसाधन या डेटा मौजूद है, तो इस विकल्प का इस्तेमाल करें. यह स्क्रिप्ट, इस वर्कशॉप के दौरान उपलब्ध कराए गए संसाधनों (Cloud Run, Cloud SQL, Secret Manager, GCS बकेट) को सिर्फ़ मिटाती है. इससे आपके प्रोजेक्ट के बाकी संसाधनों पर कोई असर नहीं पड़ता.

cd iac
terraform destroy -auto-approve

दूसरा विकल्प: पूरा प्रोजेक्ट मिटाना (कोई भी निशान न छोड़ना 🌪️)

अगर आपने वर्कशॉप के लिए कोई प्रोजेक्ट बनाया है (जैसे, वर्कशॉप क्रेडिट या सैंडबॉक्स का इस्तेमाल करके) और आपको यह पक्का करना है कि उसमें कोई भी निशान न रहे, तो इस विकल्प का इस्तेमाल करें. इसमें लॉग, मेटाडेटा, सेवा खाते, और बिलिंग लिंक शामिल हैं.

gcloud projects delete $GOOGLE_CLOUD_PROJECT --quiet