1. Giriş
Google Cloud'da Rails 8 atölyesine hoş geldiniz. Bu uygulamalı codelab'de, modern bir Rails 8 uygulamasını basit bir yerel SQLite temelinden Google Cloud'da üretime hazır, kurumsal kullanıma uygun bir referans mimariye taşıyacaksınız.
Bu atölye çalışmasında yalnızca bir uygulamayı dağıtmıyoruz. Aynı zamanda görüşlere dayalı, production düzeyinde bir bulut modernizasyonu (doğru şekilde yapılan lift-and-shift!) gerçekleştiriyoruz.
Tipik "makinemde çalışıyor" yerel kurulumuyla (geçici disk, yerleşik SQLite, işlem içi işler) başlarsınız ve bunu Google Cloud'da kademeli olarak kurumsal, kusursuz bir bulut mimarisine dönüştürürsünüz:
- 🐘 Yerel SQLite → Cloud SQL (PostgreSQL): Yeniden başlatmalarda artık veritabanı silinmeyecek. Cloud SQL Auth Proxy (mTLS, genel IP yok) üzerinden güvenli bir şekilde bağlanan yönetilen PostgreSQL'e geçiyoruz.
- 🪣 Geçici yerel depolamadan → özel GCS'ye: Sunucusuz disk geçicidir. IAM imzalı URL'leri kullanarak ActiveStorage'ı özel Google Cloud Storage'a bağlıyoruz (
iam: true). Herkese açık paketler veya sızdırılmış anahtarlar yok. - 🚀 İşlem İçi İşlerden → Çok Container'lı Cloud Run: Rails monolitini ve sunucusuz bulutu birbirine bağlıyoruz. Standart Docker Compose'u kullanarak Cloud Run çok kapsayıcılı pod içinde Puma'nın yanında özel bir çalışan kapsayıcısı olarak Solid Queue'yu çalıştırıyoruz. Mikro hizmetlerin yayılması ve iş parçacığı kıtlığı yok. DHH bu durumdan gurur duyardı.
🍌 2026'da yaşadığımız için tüm yığını Google Antigravity ile güçlendiriyoruz. Bu, sonradan eklenen bir özellik değildir. Bu atölye çalışmasını daha iyi yürütmenize (ve keyif almanıza) yardımcı olacak istemlerimiz ve becerilerimiz var.
🏛️ Hedef Referans Mimarisi (1. Varyasyon: Temiz Düz Vektörlü Enterprise)
Üreteceğiniz ve dağıtacağınız standart Google Cloud referans mimarisini (Varyant 1: Temiz Düz Vektör Kurumsal) aşağıda bulabilirsiniz. Bu mimari, tüm yönetilen Google Cloud kalıcılık ve yapay zeka hizmetlerine bağlı, çok kapsayıcılı Cloud Run hizmetimizi gösterir:

🎞️ Mimaride Evrim: Sıfırdan Bulutta Yerel Mimarilere
Her atölye çalışması aşamasında, yığınımızın geçici tek makine temelinden tamamen yönetilen bir Google Cloud planına nasıl kademeli olarak modernleştiğini izleyin:

Neler öğreneceksiniz?
- Rails 8 ve Google Cloud'u anlaşılır hale getirmek için Google Antigravity ile birlikte nasıl eşli programlama yapılır?
- Otomatik uçuş öncesi teşhisleri çalıştırma (
just workshop-test). googlesağlayıcısını kullanarak engellemeden yerel geliştirmeye devam ederken Terraform'u kullanarak Google Cloud altyapısını eşzamansız olarak sağlama- Güvenlik karşıt kalıplarını ortadan kaldırma:
0.0.0.0/0açmak yerine özel GCS paketleri (iam: true) ve Cloud SQL Auth Proxy mTLS tünelleri. - Doğrudan Google Cloud Secret Manager'dan gizli anahtarların nasıl ekleneceği.
- Solid Queue aracılığıyla eşzamansız üretken yapay zeka arka plan görevlerini (NanoBanana kapak oluşturucu, iki dilli podcast sentezi) düzenleme.
Haydi, başlayalım.
2. 0. adım: Ön koşullar, Antigravity kurulumu ve faturalandırma doğrulaması
💡 Senaryo: Siz ve ekibiniz, görev açısından kritik öneme sahip bir Rails 8 uygulaması geliştiriyorsunuz. Koda dokunmadan veya bulut kaynaklarını başlatmadan önce araç zincirimizi oluşturmalı, Google Antigravity'yi bağlamalı ve Google Cloud kimlik bilgilerimizi ve faturalandırma temelini doğrulamalıyız.
1. Ön koşullar için yapılacaklar listesi
Başlamadan önce ortamınızda aşağıdaki araçların bulunduğundan emin olun:
just(1.21+): (just --version) Görev çalıştırıcı: Bu atölyedeki her komut birjusttarifi (Yapay zeka koşumunuzdan yüklemesini isteyin veyaskills/rails8app-workshopbölümüne bakın).- Git (2.30+): Sürüm denetimi, dallandırma ve depoyu klonlama için (
git --version). - Google Cloud SDK (
gcloudKSA): Yüklü ve güncel olmalıdır. - Terraform CLI (1.5+): Bildirim temelli altyapı sağlama için.
dockervedocker-compose: Yerel olarak yüklenmiş ve çalışıyor.- Ruby
3.4.5: (ruby -v—blog/.ruby-versiontarafından sabitlendi; eksikse yapay zeka koşumunuzdan3.4.5'ı yüklemesini isteyin). Rails 8,Gemfileiçinde tanımlanır vebundle installtarafından otomatik olarak yüklenir. - Google Antigravity 2.0: Bağımsız yapay zeka destekli eşli programlama asistanınız (Google Antigravity 2.0'ı indirin). Kişisel Gmail hesabınızla giriş yaparsınız. API jetonu gerekmez.
2. Google Cloud Kimlik Doğrulaması, Dedicated Yapılandırması ve ADC
Mevcut kurumsal, kişisel veya çok hesaplı gcloud kurulumlarıyla çakışmaları önlemek için bu atölye çalışması için özel bir adlandırılmış yapılandırma oluşturmanızı önemle tavsiye ederiz:
# 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
💡 Neden özel yapılandırma? gcloud config configurations create rails8-on-gcp-workshop kullanmak, tüm CLI ayarlarını (hesap, kota projesi, varsayılan bölge) özellikle bu atölye çalışması için yalıtır. İşlemi tamamladığınızda gcloud config configurations activate default ile istediğiniz zaman normal kurulumunuza geri dönebilirsiniz.

3. 🚨 GCP Faturalandırma Doğrulaması
⚠️ Not: Google Cloud SQL ve Cloud Run dağıtımları için etkin bir bağlı faturalandırma hesabı veya geçerli atölye eğitim kredileri gerekir. Şimdi kurulumunuzun doğru olduğundan emin olalım. Bunun için faturalandırma doğrulama kontrolünü çalıştırın:
gcloud beta billing projects describe $GOOGLE_CLOUD_PROJECT
billingEnabled: true öğesinin döndürüldüğünden emin olun. Faturalandırma hesaplarınızın tümünü de listeleyebilirsiniz:
gcloud billing accounts list
Bunlardan en az birinde OPEN: True simgesinin gösterildiğinden emin olun. Etkin bir faturalandırma hesabınız yoksa Google Cloud Console Faturalandırma Sayfası'nda bir faturalandırma hesabı bağlayın veya atölye kredisi kuponunuzu kullanın.

4. Depoyu Klonlama ve Antigravity ile Eşleştirme
Depoyu klonlayın ve dizine girin. Tamamen main üzerinde kaldığımızı unutmayın:
git clone https://github.com/palladius/rails8-app-on-gcp.git
cd rails8-app-on-gcp
Bu dizini Google Antigravity'de açın. Antigravity, depoyu otomatik olarak inceler, AGENTS.md dosyasını okur ve eşli programcı olarak yanınızda durur.
5. 🪫 Antigravity'de Ücretsiz Krediler Tükenirse
⚠️ Yeni kullandığınız Cloud kredileri, Antigravity'yi yeniden doldurmaz. Bunlar iki ayrı faturalandırma yüzeyidir: Antigravity'nin kotası Google AI planlarında (Google One) yer alır. Kuponlar ve Cloud kredileri ise Cloud Faturalandırma hesabına eklenir. Bir faturalandırma hesabını GCP projenize bağladığınızda tek bir ek Antigravity istemi almazsınız.
Ajan, kota mesajıyla durursa aşağıdaki adımları uygulayın. İlk iki adım ücretsiz ve anlıktır:
- Model havuzunu değiştirme Kota, model ailesi başına izlenir ve Antigravity'de iki bağımsız havuz (Gemini modelleri ve Claude/GPT modelleri) gösterilir. Claude ve GPT-OSS modelleri ücretsiz katmanda kullanılabilir. Bu nedenle, Gemini havuzu tükendiğinde diğer havuz genellikle kullanılmaz. İstem kutusunun altındaki model seçiciyi kullanın.

- Pro yerine Flash modelini seçin. Hız sınırları, aracının istek başına ne kadar iş yaptığıyla ilişkilidir. Bu nedenle, daha hafif bir model, kalan işi daha uzun süre yapabilir.
- Antigravity CLI'yı kendi Gemini API anahtarınızla kullanın. Kendi anahtarını getirme özelliği, Antigravity IDE'de desteklenmez. CLI, belgelenmiş alternatiftir. Google AI Studio'da ücretsiz bir anahtar oluşturun (proje gerekir ancak faturalandırma hesabı gerekmez). Ardından Antigravity CLI'yi indirip yapılandırın.
- Bekleyin veya yükseltin. Ücretsiz katman kotası haftalık olarak yenilenir (hata mesajında sıfırlama tarihiniz belirtilir). Masaüstü uygulamasında taban çizgiyi yükseltmenin tek belgelenmiş yolu Google AI Pro/Ultra'dır. Bu planlar her beş saatte bir yenilenir ve fazla kullanım için satın alınan yapay zeka kredilerini kullanabilir.
- Bu Antigravity atölyesi olsa da çoğu yapay zeka kodlama koşumu da çalışmalıdır. Koşumunuzu depodaki
AGENTS.mdveskills/dizinine yönlendirmeniz yeterlidir.
6. Otomatik 0. Adım Doğrulaması
0. adım ortamınızın değerlendirme paketiyle% 100 uyumlu olduğunu doğrulayın:
just workshop-eval 0
✨ İnanılmaz an: Antigravity ve atölye değerlendirme motoru, KSA sürümlerinizi, Ruby ortamınızı ve ADC kimlik doğrulamanızı 2 saniyeden kısa bir sürede doğrular.
3. 1. adım: Terraform Altyapısı Başlangıcı ve Uçuş Öncesi Teşhis
💡 Strateji: Google Cloud SQL PostgreSQL gibi yönetilen veritabanlarının sağlanması yaklaşık 10-12 dakika sürer. Daha sonra boşta beklemek yerine, yerel olarak geliştirme yaparken şu anda arka planda Terraform aracılığıyla değişmez altyapı başlatıyoruz.
1. Otomatik Uçuş Öncesi Teşhis Paketi'ni çalıştırma
Bulut altyapısını kullanıma sunmadan önce kapsamlı uçuş öncesi test paketini çalıştırın:
just workshop-test
Bu komut dosyası (bin/workshop_diagnostics.rb):
GOOGLE_CLOUD_ACCOUNTkimlik yapılandırmanızı doğrular.- Etkin faturalandırma ve proje bağlantısını doğrular.
- Vertex AI için Uygulama Varsayılan Kimlik Bilgileri'ni (ADC) doğrular.
- ActiveStorage kanarya tohumu resmini (
blog/app/assets/images/gcs_dev_image.jpg) onaylar.

.env eksikse belgelenmiş şablondan kopyalayın:
cp .env.dist .env
# Edit .env and configure GOOGLE_CLOUD_ACCOUNT with your Google/Gmail account
💡 İpucu: just workshop-test, projenizde faturalandırma API'sinin devre dışı olduğunu bildiriyorsa aşağıdaki yöntemlerle hızlıca etkinleştirebilirsiniz:
gcloud services enable cloudbilling.googleapis.com
2. ⏱️ Terraform Altyapısını Eşzamansız Olarak Başlatma
Uzak arka uç durumu paketi oluşturan ve altyapı dağıtımını tetikleyen tek adımlı Terraform tarifini çalıştırın:
just terraform-apply

Manuel alternatif (veya doğrudan `iac/bin/terraform-apply.sh` dosyasını çalıştırın)
# 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'un sağladıkları:
- Google Cloud Storage paketi: Özel erişim ve IAM kimlik bilgisi imzası (
iam: true) ile oluşturulur. - Canary Test Image: Uçtan uca blob doğrulamayı etkinleştirmek için
gcs_dev_image.jpgöğesini pakete yükler. - Google Cloud SQL PostgreSQL örneği: Arka planda sağlama işlemini başlatır (~10-12 dakika).

💡 Not: Eksik otomatik yedeklemelerle ilgili uyarıyı güvenle göz ardı edebilirsiniz. Bu atölye çalışması veritabanı için otomatik yedeklemelere ihtiyacımız olmayacak (ancak otomatik günlük yedeklemeler, gerçek üretim veritabanları için önemli bir en iyi uygulamadır).

📝 Cloud Run URL'nizi not edin: Terraform uygulama işlemi başarılı olmalı ve altyapı çıkışlarınızı yazdırmalıdır. cloud_run_url değerinizi not edin (veya panonuza kopyalayın). Canlı hizmetinizi doğrularken sonraki adımlarda bu değere ihtiyacınız olacak.
3. Otomatik 1. Adım Doğrulaması (İsteğe Bağlı)
1. adım ön koşullarınızın ve yapılandırmalarınızın başarılı olduğunu doğrulayın:
just workshop-eval 1
⏱️ Not: Bu değerlendirmede canlı bulut kaynakları kontrol edilir ve tamamlanması birkaç dakika sürebilir. Bu tamamen isteğe bağlıdır. Terminalinizde çalışırken beklemeden hemen sonraki adıma geçebilirsiniz.
4. 2. adım: Yerel temel, Mailpit ve yönetici oryantasyonu
Başlangıç noktamız, SQLite, Mailpit e-posta yakalama ve diske dayalı ActiveStorage ile localhost'ta çalışan temiz ve modern bir Rails 8 blog uygulamasıdır.
1. Uygulamayı yerel olarak başlatma
📁 Dizine dikkat edin. Bu depoda, blog/ içinde Rails uygulaması ve iac/ içinde Terraform bulunur. 1. adımda depo kökünde kaldığınız için 2. adımdaki her komut
blog/: Gemfile, bin/rails ve compose.yaml burada yaşıyor. Bu komutları kökten çalıştırmak no configuration file provided: not found ile veya Gemfile eksik olduğunda başarısız olur.
Rails uygulamasına geçin, sabitlenmiş Ruby'de olduğunuzu onaylayın, ardından gem'leri yükleyin ve veritabanını ayarlayın:
cd blog
ruby -v # must print 3.4.5 — see Step 0 if it does not
bundle install
bin/rails db:setup
🧯 Yazma izni hatası
/var/lib/gems/
veya
ruby -v
sistem Yakut'u (ör. 3.3.x) gösteriyor mu? Vanilla Linux sisteminde Ruby, .ruby-version dosyalarını tamamen yok sayıyor ve gem'leri sisteme genel olarak yüklemeye çalışıyor. rbenv öğesinin etkin terminal kabuğunuza yüklendiğinden emin olun:
eval "$(rbenv init - bash)" # or: eval "$(rbenv init - zsh)"
ruby -v # confirm it now outputs 3.4.5!
Not: 0. adımda 3.4.5 sürümünü yüklemeyi atladıysanız rbenv install 3.4.5 komutunu çalıştırın. Alternatif olarak, aşağıdaki A Modu (Docker Compose)'nu (just compose-up) kullanabilirsiniz. Bu mod, sabitlenmiş Ruby yığınını ana makine gem'lerine dokunmadan tamamen kapsayıcılar içinde çalıştırır.
💡 Bu konuyu düşünmek istemiyor musunuz? just install ve just compose-up, depo kökünden sizin için cd blog işlemini yapar.
2. 🌱 Akıllı Tohum Otomatik Keşfi ve Yönetici Bootstrap'i (21 ve 25 numaralı sorun)
Veritabanı başlangıcı (db/seeds.rb) Akıllı Ortam Otomatik Keşfi'ne sahiptir:
- Etkin veritabanı bağdaştırıcınızı (SQLite ve Postgres) ve depolama yapılandırmanızı inceler.
- Aşama 0 (Localhost)'ı algılar ve ilk yönetici kullanıcısını otomatik olarak oluşturup pedagojik gönderiyi başlatır:
[LOCAL BASELINE] Welcome to Rails 8 on Localhost!- Yerel disk depolama alanının geçici olduğunu bildiren filigranlı, kullanıma hazır yerel üzgün yüz resmi eki (
local_sad_image.png).
- ActionMailer aracılığıyla otomatik olarak şifre sıfırlama e-postası tetikler.
Başlangıç değerini doğrulayın veya yeniden çalıştırın (.env içindeki GOOGLE_CLOUD_ACCOUNT değeriniz otomatik olarak kullanılır):
bin/rails db:seed # or from repo root: just seed
Docker Compose ile yerel geliştirme yığınını başlatın:
docker compose up -d # from blog/ — or `just compose-up` from the repo root

Uygulama, yerel Mailpit SMTP sunucusu ve Adminer veritabanı görüntüleyici artık yalıtılmış kapsayıcılarda birlikte çalışıyor:
- Rails uygulaması: http://localhost:3000
- Mailpit Web Kullanıcı Arayüzü: http://localhost:8025
- Adminer DB UI: http://localhost:8081
🧯 3000 bağlantı noktası çakışması veya
server.pid
hatası mı? Daha önce yerel bir geliştirme sunucusu (bin/dev) başlattıysanız Ctrl+C ile durdurun. Docker, 3000 numaralı bağlantı noktasının zaten ayrıldığını belirtirse veya geride kalan bir server.pid bulursa şu komutla temizleyin:
just compose-down
rm -f blog/tmp/pids/server.pid
just compose-up
3. Mailpit deneyimi ve yönetici girişi
- Giden e-postaları Mailpit ile yakalama: Tarayıcınızda
http://localhost:8025adresini açın. Yerel gelen kutusuna bakın.db:seedsırasında ActionMailer, harici e-posta sunucularına veya kimlik bilgilerine dokunmadan Mailpit'in yerel olarak güvenli bir şekilde yakaladığı bir yönetici oryantasyon e-postası gönderdi:
2. Blog'a giriş yapın: Tarayıcınızda http://localhost:3000 adresini açın.
- Şifrenizi belirlemek için doğrudan Mailpit e-postasındaki şifre sıfırlama bağlantısını tıklayabilirsiniz.
- Alternatif olarak, Google Cloud hesabınızın e-posta adresini (
.env) ve varsayılan başlangıç şifresini (Ch4ng3m3!!1) kullanarak giriş yapın.
- Görsel Telemetri Rozetlerini İnceleyin:
- Kullanıcı arayüzündeki sarı ortam banner'ına ve rozetlere (
Notice: Ephemeral Database Active (POSTGRESQL)ve[EPHEMERAL DB / STORAGE] 💾 Local) dikkat edin. - Gönderi filigranına dikkat edin: 🏠 damgası (
nanobanana_stamp_local.pngkapak resminin sağ alt köşesinde). Bu sayede, öğelerinizin ve veritabanınızın şu anda geçici yerel depolama alanına bağlı olduğuna dair anında görsel onay alırsınız.
- Kullanıcı arayüzündeki sarı ortam banner'ına ve rozetlere (

💡 İsteğe bağlı profesyonel ipucu: Rails Console Workout Rails'in KSA'dan gelen doldurulmuş verilerinizle nasıl etkileşim kurduğunu merak mı ediyorsunuz? Etkileşimli konsola girin:
bin/rails console
Ortam değişkeninizi kullanarak önceden doldurulmuş yönetici kullanıcınızı dinamik olarak inceleyin:
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. 2. Adım Otomatik Doğrulama
Yerel temel çizginizi ve yönetici kurulumunuzu doğrulayın:
just workshop-eval 2

5. Sorun: Durum bilgisiz container'lar
Cloud Run container'ları durum bilgisiz ve kısa ömürlüdür. SQLite veritabanımızı ve yerel storage/ dizinimizi doğrudan Cloud Run'a dağıtırsak bir kapsayıcı sıfıra ölçeklendiğinde veya yeniden başlatıldığında tüm gönderiler ve yüklenen resimler kalıcı olarak silinir.
Bir sonraki adımda, Durumsuzluk Şoku'nu ilk elden deneyimlemek için bu kısa ömürlü yapılandırmayı Cloud Run'a kasıtlı olarak dağıtacağız.
5. 3. adım: 1. bölüm: Durumsuz Şok (3 Dakikada Erken WOW!)
Web'de herhangi bir şey görmeden önce bulut veritabanları için 15-20 dakika beklemek yerine, modern sunucusuz geliştirme erken bir zaferle başlar: tek kapsayıcılı Rails uygulamamızı 3 dakikadan kısa bir sürede doğrudan Google Cloud Run'a dağıtmak!
1. Zaman Makinesi ile Geçmişe Bakış
Başlangıç yapılandırmamızın% 100 geçici (yerel SQLite veritabanı ve yerel disk dosyası depolama) olmasını sağlamak için Zero-Branch Time-Machine motorunu kullanın:
just workshop-rewind 1
💡 Ne oldu?workshop-rewind 1, main dalından ayrılmadan stage-1-stateless yapılandırma katmanını blog/config/'e uyguladı. Uygulamanız, kapsayıcı diskte SQLite ve yerel dosya sisteminde ActiveStorage ile yapılandırılmış.
2. Tek Container'lı Puma'yı Cloud Run'a Dağıtma
Doğrudan kaynak koddan Cloud Run'a dağıtın. Modern Rails 8, kullanıma hazır olarak resmi ve üretime hazır bir Dockerfile otomatik olarak oluşturur (çok kademeli derlemeler, jemalloc ve kök olmayan güvenlik ile). blog/ klasöründen dağıtım yaptığınızda Google Cloud Build, bu yerel Dockerfile'yi doğrudan algılar ve yönetilen bir sunucusuz hizmet sağlar:
# 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
Şuna benzer bir ilerleme çıkışı görürsünüz:

⏳ Cloud Build, kapsayıcınızı paketleyip Cloud Run düzeltmesini sağlarken bu işlem birkaç dakika sürer.
🧯 Sorun Giderme ve Sık Karşılaşılan Sorunlar
PERMISSION_DENIED: Build failed because the default service account is missing required IAM permissions
? Aynı hataya neden olan iki farklı durum vardır:
- gcloud, sizin için bir API'yi etkinleştirdi. Dağıtım
The following APIs are not enabled ... cloudbuild.googleapis.comşeklinde yazdırıldıysa veYyanıtını verdiyseniz yeni izinlerin yayılması tamamlanmadan önce derleme başlatılmış olabilir. gcloud'un kendi isteminde "Bu işlem birkaç dakika sürer" uyarısı verilir. Bir dakika bekleyip aynı komutu tekrar çalıştırın. Bu genellikle işe yarar. 1. adımdaterraform applybu API'yi sizin için etkinleştirir. Bu nedenle, istemi görmemeniz gerekir. - Varsayılan Compute SA'da gerçekten roller eksik. Modern GCP projeleri, en az ayrıcalık ilkesini zorunlu kılar. Bu durum, kaynak dağıtımlarını bozar. Şunlarla düzeltin:
just project-status # grants storage.admin, logging.logWriter, artifactregistry.writer, cloudbuild.builds.builderjust workshop-testda artık bunu bildiriyor. Bu nedenle, dağıtım başarısız olmaya devam ederse yeniden çalıştırmanız önerilir.
Dağıtım sırasında:
- Cloud Run, Rails container görüntünüzü oluşturur.
- Herkese açık ve güvenli bir TLS alanı atar:
https://blog-[hash]-[region].a.run.app. - Trafik, 8080 numaralı bağlantı noktasında Puma'ya yönlendirilmeye başlar.
3. ✨ İlk WOW Anı
Oluşturulan Cloud Run URL'sini tarayıcınızda açın.
- Modern Rails 8 uygulamanız Google Cloud'da yayında!
- Yönetici kimlik bilgilerinizle (
GOOGLE_CLOUD_ACCOUNTveAPP_ADMIN_PASSWORD) giriş yapın. Giriş düğmesini bulamazsanız "Yeni Gönderi"'yi tıklayın. Önce kullanıcı ve şifre istenir:
- "Yeni Yayın"ı tıklayın, "İlk Cloud Run Yayınım" başlıklı bir makale yazın, resim ekleyin ve Yayın Oluştur'u tıklayın.
- Yayınlarınız tam biçimlendirmeyle yayınlanır ve resminiz oluşturulur.
- Görsel telemetriye dikkat edin:
- Başlık rozeti:
[EPHEMERAL DB / STORAGE] 💾 Local - Resim filigranı: 🏠 damgası (sağ alt köşedeki
127.0.0.1geçici disk rozeti).
- Başlık rozeti:
🐝 Canlı Atölye Arı Kovanı Skor Tablosu'na katılın! Onlineysanız ve gözetmeniniz skor tablosunu gösteriyorsa ve siz de katılmak istiyorsanız Cloud Run URL'nizi buraya ekleyin: 👉 Cloud Run'ınızı skor tablosuna kaydetme

4. 💥 The Catch: The Stateless Shock & The "Puma Workaround" Trap
Cloud Run, durum bilgisiz ve sunucusuz bir platformdur. Web trafiği sıfıra düştüğünde Cloud Run, para tasarrufu için kapsayıcı örneklerini sıfıra indirir. Yeni bir HTTP isteği geldiğinde veya yeni bir kapsayıcı sürümü dağıtıldığında Cloud Run, yepyeni ve temiz bir kapsayıcı görüntüsü başlatır.
Takılan İşler Banner'ı
Tek kapsayıcılı dağıtımda bir yayın oluşturduğunuzda veya resim eklediğinizde Rails, ActiveJob görevlerini (ör. resim boyutu analizi veya meta veri indeksleme) sıraya alır. Ancak arka planda çalışan olmadığı için şu uyarı banner'ını görürsünüz:

Cazip Çözüm: Puma'da Solid Queue'yu çalıştırma
Akıllı bir geliştirici şöyle diyebilir: "Bekle! Rails 8,
SOLID_QUEUE_IN_PUMA=true
ortam değişkeni!"
Bu geçici çözümü Cloud Run'da test edelim:
# 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
Şimdi tarayıcınıza geri dönüp sayfayı yenileyin:
💥 Durum Bilgisizliğin Şoku:
- İyi haber: Solid Queue çalışanı artık Puma'da etkin. Yeni işler hemen boşaltılır.
- Soğuk Duş (Yakalanma!):
- Cloud Run yeni bir düzeltme dağıttığı için önceki kapsayıcı örneği değiştirildi.
- Yazdığınız makale ve diskteki SQLite veritabanı dosyası tamamen silindi.
- Mimari Ders: Arka plan çalışanlarını Puma'da çalıştırmak değerli web iş parçacığı CPU/RAM'ini tüketir ve kalıcılık sorununu yine de çözmez.
5. 3. Adım Otomatik Doğrulama
Cloud Run dağıtımınızı ve uyarı işleme durumunuzu doğrulayın:
just workshop-eval 3
✨ Ders: SOLID_QUEUE_IN_PUMA gibi tek kapsayıcılı geçici çözümler yerel geliştirme için kullanışlıdır ancak modern bulut mimarisinde:
- Medya dosyaları için Google Cloud Storage (GCS) gerekir (4. adım).
- İlişkisel veriler ve iş kuyrukları için yönetilen Google Cloud SQL gerekir (5. adım).
- Yoğun arka plan görevleri, özel bir sidecar kapsayıcısında yer almalıdır (6. adım).
6. 4. adım: 3. dağıtım: GCS Kalıcı Depolama ve POLA Uyarısı
Bu adımda, ActiveStorage'ı Google Cloud Storage (GCS)'ye geçirerek, IAM Credentials API (iam: true) aracılığıyla kısa ömürlü imzalı URL'ler kullanarak medya ve dosya depolama alanını kapsayıcı diskten ayırıyoruz.
Herhangi bir yapılandırmaya dokunmadan önce Rails'in GCS ile iletişim kurmak için ihtiyaç duyduğu üç şeyi anlayın:
① Proje kimliği + paket adı: Rails, blob'ların nereye depolanacağını bilmelidir. Uygulama, ortamdan GOOGLE_CLOUD_PROJECT değerini okur ve paket adını ${GOOGLE_CLOUD_PROJECT}-activestorage-prod olarak türetir. 1. adımda oluşturduğunuz Terraform, bu paketi zaten oluşturdu. Başka bir işlem yapmanız gerekmez.
② Doğru izinlere sahip bir hizmet hesabı: Cloud Run, Compute Engine varsayılan hizmet hesabı (PROJECT_NUMBER-compute@developer.gserviceaccount.com) olarak çalışır. Bu hizmet hesabının pakette iki IAM rolü olması gerekir:
roles/storage.objectAdmin: Blob'ları yüklemek ve sunmak için- IAM Credentials
signBlobAPI'sini çağırmak ve kısa ömürlü imzalı URL'ler oluşturmak için kendisi üzerinderoles/iam.serviceAccountTokenCreator
⚠️ Cazip Kısayol —
public: true GCS'nin çalışmasını sağlamanın en hızlı yolu, storage.yml içinde public: true'yi ayarlamak ve pakette allUsers:objectViewer izni vermektir. Görseller anında yüklenir ve oturum açmanız gerekmez. Bunu yapmayın. Herkese açık bir paket, yüklenen tüm kullanıcı medyalarını herkese açık internete sızdırır ve bu durum kalıcı olur. Planımız, IAM Credentials API tarafından anında oluşturulan, imzalı ve süresi dolan bir jeton olan her resim URL'siyle iam: true kullanarak paketin% 100 özel kalmasını sağlar.
③
ACTIVE_STORAGE_SERVICE=google: Rails'i çalışma zamanında yerel diskten GCS'ye çeviren tek ortam değişkeni. Kod değişikliği veya uygulama mantığının yeniden dağıtılması gerekmez. Yalnızca bir ortam değişkeni geçişi yeterlidir.
1. Zaman Makinesi ile Geçmişe Bakış
Zaman makinesini 2. aşamaya ilerletin:
just workshop-rewind 2
İnceleyin blog/config/storage.yml. Uygulamanın, aynı güvenli kalıbı kullanan üç adlandırılmış GCS ortamı (dev / test / prod) tanımladığını görürsünüz:
<% 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

2. IAM Depolama ve İmzalama İzinleri Verme
Cloud Run çalışma zamanı hizmet hesabınızın URL'leri imzalamak ve nesneleri yüklemek için gerekli izinlere sahip olduğundan emin olun:
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. Üçüncü dağıtım: GCS eklenmiş Cloud Run
GCS etkinleştirilmiş olarak yeniden dağıtın. blog/ klasörünün içinde olduğunuzdan emin olun (aksi takdirde Cloud Run, Rails 8 Dockerfile yerine Buildpack'leri kullanarak derlemeye çalışır ve derleme hatalarına neden olur).
Mevcut ortam değişkenlerini (anahtar, UİSA yapılandırması vb.) korumak için --update-env-vars (--set-env-vars değil) kullanın:
cd blog
gcloud run deploy blog \
--source . \
--region $GOOGLE_CLOUD_REGION \
--update-env-vars ACTIVE_STORAGE_SERVICE=google
💡 İpucu: Dağıtım başarısız olursa terminal çıkışınızda kolayca sağlanan Cloud Build günlükleri bağlantısını tıklayın (aşağıdaki şekilde gösterildiği gibi). Antigravity'den hatayı çözme ve düzeltme konusunda da yardım isteyebilirsiniz.

4. ✨ The Surviving Image & The Cloud Stamp
- Blog URL'nizi yenileyin.
- "Bulutta Hayatta Kalma" başlıklı yeni bir blog yayını oluşturun ve bir fotoğraf yükleyin.
- Resmin sağ alt köşesine bakın:
- 🏠 damgası kaldırıldı.
- Bu damganın yerini rengarenk Cloud GCS Damgası (
nanobanana_stamp_cloud.png) almıştır.
- Başka bir kapsayıcıyı yeniden başlatmaya zorlayın (bu işlem dördüncü bir düzeltmeyi tetiklemelidir):
gcloud run services update blog --region $GOOGLE_CLOUD_REGION --update-env-vars RESTART_TRIGGER=$(date +%s) - Sayfayı yenileyin: SQLite veritabanı sıfırlanırken görüntü ikilisi Google Cloud Storage'da güvende kalır. CLI ile doğrulama:
gcloud storage ls -l -r gs://$GCS_BUCKET/
Google Cloud Storage Tarayıcı Konsolu'nda üretim paketinize (gs://$GCS_BUCKET) yüklenen blob'ların ve medya nesnelerinin listesini aşağıda bulabilirsiniz:

5. ⚠️ Sorun: Takılan İşler Uyarı Banner'ı
Resmi yüklediğinizde ActiveStorage, boyutları ve meta verileri ayıklamak için bir analiz işi (ActiveStorage::AnalyzeJob) oluşturdu.
Ancak Cloud Run şu anda yalnızca tek bir web kapsayıcısı (puma) çalıştırıyor. Rails 8'de Solid Queue, arka plan işlerini veritabanında saklıyor ancak bundle exec rails solid_queue:start'ı kimse yürütmüyor.
Blog sayfanızın üst kısmına bakın: blog/app/views/layouts/_check_stuck_jobs.html.erb tarafından oluşturulan parlak bir uyarı banner'ı görürsünüz.
6. adımda, web trafiğinden bağımsız olarak Solid Queue'yu çalıştıran özel bir worker kapsayıcısıyla üretime hazır çok kapsayıcılı bir yardımcı kapsayıcı mimarisine geçiş yaptığımızda bu sorunu düzgün bir şekilde çözeceğiz.
6. 4. Adım Otomatik Doğrulama
GCS yapılandırmanızı ve takılan işler telemetrinizi doğrulayın:
just workshop-eval 4
7. 5. adım: Uçuş öncesi kontrol listesi: Cloud SQL, Secrets ve veritabanı bağlantısı
3. ve 4. adımda durum bilgisi içermeyen kapsayıcılar ve Google Cloud Storage'ı öğrenirken Terraform, arka planda üretim arka ucunuzu hazırlamayı tamamladı.
Tam 3 kapsayıcılı üretim sidecar mimarimizi dağıtmadan önce (6. adımda 4 dağıtın) bu adım, veritabanı sağlığını, bağlantısını ve gizli erişimi doğrulamak için hızlı bir uçuş öncesi inceleme görevi görür.
0. Bootstrap ortam değişkenleri
Gerekli tüm kabuk değişkenlerini doğrudan Terraform çıkışlarınızdan dışa aktarın:
# 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 durum denetimi
Yönetilen PostgreSQL örneğinizin ilk sağlama işlemini tamamladığını ve sağlıklı olduğunu doğrulayın:
echo "Checking instance: $SQL_INSTANCE_NAME"
gcloud sql instances describe $SQL_INSTANCE_NAME --format="value(state)"
Çıkış RUNNABLE olmalıdır.
2. (İsteğe bağlı) Dizüstü bilgisayarınızdan veritabanı bağlantısını test etme
Üretim ortamında Cloud Run kapsayıcıları, veritabanını herkese açık internete (0.0.0.0/0) maruz bırakmadan şifrelenmiş bir yardımcı proxy (127.0.0.1:5432) aracılığıyla Cloud SQL'e güvenli bir şekilde bağlanır.
ℹ️ Not: Bu adım tamamen isteğe bağlıdır. Cloud Run'da, resmi Cloud SQL Auth Proxy yardımcı kapsayıcı, mTLS bağlantısını otomatik olarak işler. Çalıştayı tamamlamak için yerel olarak herhangi bir şey yüklemeniz gerekmez.
Makinenizde cloud-sql-proxy ve psql yüklüyse ve dizüstü bilgisayarınızdan doğrudan bağlantıyı doğrulamak istiyorsanız:
# Optional: test connectivity via Google-managed mTLS proxy
gcloud sql connect $SQL_INSTANCE_NAME --user=rails_user --database=rails_production
(Şifre istenirse
$DB_PASSWORD
. Aksi takdirde, doğrudan aşağıdaki 3. adıma geçebilirsiniz.)
3. Terraform ile sağlanan gizli anahtarları inceleme
Hiçbir zaman düz metin veritabanı şifrelerini, API anahtarlarını veya Rails ana anahtarlarını Git'te ya da kapsayıcı ortamı değişkenlerinde depolamayın. Modern bulut mimarisinde, sıfır güvenli çalışma zamanı ekleme için Google Cloud Secret Manager'ı kullanırız.
ℹ️ Terraform, 1. adımda bu işlemi sizin için gerçekleştirdi:
rails-master-key: Çalışma zamanında Rails kimlik bilgilerinin şifresini çözmek için.rails-db-password: Cloud SQL kullanıcısıyla eşleşen, kriptografik olarak güvenli bir rastgele şifre.rails-admin-password: İlk yönetici kullanıcınız için güvenli bir şifre.
Secret Manager'da sırlarınızın mevcut ve etkin olduğunu doğrulayın:
gcloud secrets list --filter="name:rails-"

🔑 master.key'ı dizüstü bilgisayarınızla senkronize etme (yerel senkronizasyon)
blog/config/master.key, güvenlik nedeniyle .gitignore dosyasında yer aldığından yerel kopyanızda henüz bulunmayabilir. Yerel Rails araçlarınızın kimlik bilgilerinin şifresini çözebilmesi için bu kolay kendi kendini onaran snippet'i çalıştırarak Secret Manager'dan çekin:
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: Ne kadar kolay olduğunu görmek için özel bir gizli anahtar oluşturmak mı istiyorsunuz? Secret Manager yalnızca Rails için değildir. Tek bir basit CLI komutuyla istediğiniz gizliyi oluşturabilirsiniz:
echo -n "MySuperSecretValue123!" | gcloud secrets create workshop-fun-secret --data-file=-
echo "✨ Created workshop-fun-secret in Secret Manager! 🪄"
4. Gizli erişimci izinlerini doğrulama
Cloud Run container'larının bu sırları başlatma sırasında ortam değişkenleri veya birim bağlamaları olarak bağlaması için çalışma zamanı hizmet hesabının ($RUN_SA) her sırda roles/secretmanager.secretAccessor rolüne sahip olması gerekir.
Terraform, bu izni 1. adımda zaten vermişti. rails-master-key üzerindeki IAM politikası bağlamasını doğrulayın:
# 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"
Aşağıdaki bilgileri görürsünüz:
ROLE MEMBERS
roles/secretmanager.secretAccessor serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com

5. Otomatik ön kontrol doğrulama
Veritabanınızın çalıştırılabilir olduğunu, sırların boş olmadığını ve IAM izinlerinin yeşil olduğunu onaylamak için otomatik 5. adım test paketini çalıştırın:
just workshop-eval 5
8. 6. adım: 4. dağıtım: Enterprise Multi-Container Sidecars (Altın Standart)
Şimdi nihai referans mimariyi oluşturuyoruz: Çok Container'lı Cloud Run.
1. Altın standardı geri yükleme
Depo yapılandırmanızı kanonik main durumuna geri yükleyin:
just workshop-restore-gold
2. 3 kapsayıcılı üretim planını inceleme
blog/compose.prod.yaml dosyasını açıp mimariyi inceleyin:

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)]
Üretim dağıtımı, aynı yerel ağı paylaşan üç koordineli kapsayıcıyı çalıştırır:
web: Puma üzerinden 8080 bağlantı noktasında HTTP trafiği sunar.worker:bundle exec rails solid_queue:startçalıştıran özel arka plan işleme container'ı.cloudsql-proxy:127.0.0.1:5432'ye bağlı resmi Google Cloud SQL Auth Proxy yardımcı dosyası (gcr.io/cloud-sql-connectors/cloud-sql-proxy:2).
3. Cloud Run işi aracılığıyla veritabanı taşımalarını çalıştırma
Web trafiğini yeni dağıtımımıza yönlendirmeden önce Cloud SQL'e karşı veritabanı taşıma ve ilk tohumlama işlemlerini çalıştırmamız gerekir.
⚖️ Container'larda Taşıma İşlemleri Nasıl Çalıştırılır: İki Strateji
Kapsamlı bulut ortamlarında, veritabanı taşıma işlemlerini yürütmek için iki yaygın yaklaşım vardır:
- A seçeneği: Docker giriş noktasında otomatik (
entrypoint.sh, kapsayıcı başlatıldığındadb:migratekomutunu yürütür)- Avantajları: Tamamen otomatiktir. Geliştiricilerin komut çalıştırmayı hatırlaması gerekmez.
- Dezavantajları: Sunucusuz otomatik ölçeklendirmede tehlikelidir. Cloud Run, yüksek trafik altında aynı anda 10 örneğe kadar ölçeklendiğinde 10 kapsayıcı aynı anda taşıma işlemlerini çalıştırmak için yarışır. Bu durum, veritabanı kilitlemesine, şema yarış koşullarına veya başlatma zaman aşımlarına neden olur.
- B seçeneği: Cloud Run işi aracılığıyla açıkça (mimari tercihimiz)
- Avantajları: Tam kontrol, işlemsel güvenlik ve sıfır yarış durumu. Yayınlama web trafiğinden tamamen ayrılmış, tek seferlik özel bir kapsayıcı görevi olarak çalışır. Taşıma işlemi başarısız olursa web'de yayın etkilenmez.
- Dezavantajları: Dağıtımdan önce bir CLI işinin veya CI/CD adımının tetiklenmesi gerekir.
Maksimum üretim güvenilirliği için B seçeneğini tercih ediyoruz.
⚠️ Kritik: DATABASE_URL Biçim ve Ruby 3.4.5 RFC 3986 Katılığı
Cloud Run İşleri, yerel Unix soketi proxy'sini (/cloudsql/PROJECT:REGION:INSTANCE) kullanarak Cloud SQL'e bağlanır. DATABASE_URL üç eğik çizgi biçiminde olmalıdır:
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 Çoklu Veritabanı: Uygulama, database.yml başına 4 veritabanı (birincil, sıra, önbellek, kablo) kullanır. 4 DATABASE_*_URL ortam değişkeninin tümü aynı Cloud SQL örneğini işaret etmelidir. Aksi takdirde Solid Queue/Cache/Cable tabloları oluşturulmaz.
db:prepare işleminden sonra Solid Queue/Cache/Cable şemalarını yükleyin:
# 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
Yukarıdaki şekilde,
gcloud run jobs executions describe $JOBNAME
Google Cloud Run Jobs Console'da gösterilen
rails-migrate
execution Succeeded (Yürütme başarılı)
4. Dördüncü dağıtım: Docker Compose ile çok container'lı Cloud Run dağıtımı
Şimdi, compose.prod.yaml üzerinden doğrudan orijinal 3 kapsayıcılı üretim yığınını (web, worker, cloudsql-proxy) dağıtın:
# 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: Üç yardımcı kapsayıcının tümünü gösteren "Kapsayıcılar" sekmesi (
cloudsql-proxy
,
web
,
worker
)
💡 Kullanıcı Arayüzüyle İlgili Merak / Konsol Hatası: Konsol açılır listesinde, Cloud Run'ın en üstteki girişi Ingress container: cloudsql-proxy olarak etiketlediğini fark edebilirsiniz. Merak etmeyin! Bu, tamamen kapsayıcı bağımlılığı sıralamasından kaynaklanan Google Cloud Console'daki görsel bir kullanıcı arayüzü hatasıdır (#149 numaralı hata olarak izlenir). Gerçekte, web, HTTP bağlantı noktası 8080'de dinleme yapan ve giriş web trafiğinin% 100'ünü işleyen tek kapsayıcıdır. cloudsql-proxy ise 5432 numaralı bağlantı noktasında yalnızca özel PostgreSQL trafiğine hizmet verir.
5. ✨ İşte o an: Sıfır uyarı ve tam bulut kalıcılığı!
Derin bir nefes alın ve ekranınıza hayran kalın: Tüm uyarı banner'ları kayboldu! 🪄
Üretim Rails 8 blogu: kusursuz kullanıcı arayüzü, sıfır uyarı banner'ı ve kalıcı Cloud SQL durumu!
Uygulama artık resmi olarak üretim düzeyinde ve buluta özel:
- Güvenli mTLS tüneli üzerinden yönetilen Google Cloud SQL (PostgreSQL) tarafından desteklenir.
- IAM blob imzasıyla özel Google Cloud Storage'da güvenli bir şekilde saklanan medya.
- Sıfır geçici depolama alanı uyarısı ve sıfır takılı iş uyarısı.
Cloud Run URL'nizi açın:
- Telemetri rozetlerine bakın:
[CLOUD PERSISTENT 🐘 ☁️]veritabanı başlangıcınızda doğrulanır.- Altbilgideki hem Google Cloud Run hem de GCS rozetleri yeşil renkte parlıyor.
- Takılan işler uyarı banner'ı tamamen kaldırıldı.
- Blog yayınları ve yorumlar oluşturma
- İstediğiniz kadar yeniden başlatın veya yeniden dağıtın: Verileriniz, yayınlarınız, yorumlarınız ve öğeleriniz Cloud SQL ve GCS'de kalıcı olarak saklanır.
6. Otomatik 6. Adım Doğrulaması
Çok kapsayıcılı yapılandırmayı doğrulayın:
just workshop-eval 6
9. 7. adım: Üretken yapay zeka işlem hatları, Podcastifier ve GCS hazine avı 🏴☠️
Solid Queue'nun özel bir kapsayıcıda çalışması ve Google Cloud Storage'ın etkin olması sayesinde, eşzamansız üretken yapay zekanın gücünden yararlanabiliriz.
1. NanoBanana Vintage Cover Generator (Kullanıma Hazır Üretken Yapay Zeka İşlem Hattı)

İyi haber: Bu işlev, kod tabanında zaten tamamen uygulanmış durumda. Herhangi bir kod yazmanız gerekmez. Buradaki göreviniz, eşzamansız bir bulut üretken yapay zeka ardışık düzenini tetiklemek ve çalışırken gözlemlemektir.
🧠 Kamera arkası işleyiş şekli
- Kimlik doğrulama: API anahtarı gerekmez. Cloud Run çalışma zamanı hizmet hesabı aracılığıyla Uygulama Varsayılan Kimlik Bilgileri'ni (Vertex AI'da
roles/aiplatform.user) otomatik olarak kullanır. (Alternatif olarak,GEMINI_API_KEYsağlanırsa doğrudan Gemini API'yi çağırır.) - İşlem hattı: Kapak resmi olmadan bir makale oluşturulduğunda,
after_commitgeri çağırma işlemiGenerateCoverImageJobSolid Queue'ya eklenir. - Model: Google'ın çok formatlı modelinden (Gemini 2.5 Flash Image / Vertex AI'da Imagen), cameo muz ve parlak yakut "8" ile tamamlanmış, 1960'lardan kalma otantik bir İtalyan film posteri ("Locandina di un film 1960") oluşturmasını ister.
- Dinamik Kaynak Filigranı: Köşeye görsel bir rozet (GCS'de renkli bulut damgası) dinamik olarak damgalamak için
libvipskullanılır. - Turbo Stream Hot-Swap: Resim eklendiğinde
Turbo::StreamsChannel.broadcast_refresh_to(post), okuyucunun tarayıcısını manuel olarak sayfa yeniden yüklenmeden canlı olarak günceller.

📐 Mermaid adım sırası diyagramı kaynağını görüntüleme
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!
🧪 Canlı Deneyin!
İki şekilde tetikleyebilirsiniz:
- A seçeneği (Web kullanıcı arayüzü): Yeni yayın'ı tıklayın, "Ruby on Rails 8 ile Sunucusuz Mimari" gibi bir başlık girin, biraz içerik yazın ve kapak resmi dosyası girişini boş bırakın. Yayın oluştur'u tıklayın.
- B seçeneği (CLI Runner): Terminalinizden çalıştırın:
bin/rails runner 'Post.create!(title: "Serverless Architecture with Ruby on Rails 8", body: "Exploring asynchronous AI pipelines with Solid Queue and NanoBanana!")'
Yaklaşık 15-30 saniye bekleyin: Cloud Run'daki Solid Queue çalışan günlüklerini izleyin. Vintage poster doğrudan gönderinizde görünür.
📸 YAPILACAKLAR(riccardo): Yapay zekayla üretilmiş, 1960'lardan kalma İtalyan film posteri içeren bir blog yayınının ekran görüntüsünü ekleyin. Poster, muz ve yakut 8'in yer aldığı bir cameo içeriyor.
2. The Bilingual Podcastifier Quest (Hands-On Antigravity Coding Exercise)
⚠️ Önemli Uyarı: Yukarıdaki Kapak Oluşturucu'nun aksine, bu özellik henüz kullanıma sunulmamıştır.
blog/app/jobs/podcastifier_job.rb dosyasını açarsanız boş bir iskele kaba kodu görürsünüz:
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
Bu uygulamalı alıştırmadaki göreviniz, bu özelliği tamamlamak için Google Antigravity ile birlikte çalışmaktır:
- Antigravity istemi:"
app/jobs/podcastifier_job.rb'de PodcastifierJob'u uygulamama yardım et. Gönderiyi getirmeli, Google Cloud Text-to-Speech'i (ADC kimlik bilgileri aracılığıyla "it-IT" dil koduyla "it-IT-Wavenet-A" sesi) kullanarak İtalyanca sesli özet oluşturmalı veya çevirmeli ve ActiveStorage'u kullanarak ses dosyasınıpost.podcast_audio_iteklemelidir." - Görünüme Oynatıcı Ekleme:
app/views/posts/show.html.erbbölümünde,@post.podcast_audio_it.attached?olduğunda bir HTML5oynatıcı ekleyin. - Sentezi Tetikleme: Kaydedildiğinde Solid Queue, metin okuma işini arka planda eşzamansız olarak yürütür.

🎧 Podcastifier'ın örnek çıktıları:
- 🇮🇹 Italian Overview (
it-IT-Wavenet-A) [İtalyanca Genel Bakış ()] - 🇬🇧 İngilizce Genel Bakış (
en-US-Wavenet-D)
💡 Yardıma mı ihtiyacınız var veya takıldınız mı? Savaş testinden geçmiş eksiksiz bir referans çözümü solutions/podcastifier dalında mevcuttur. Bu bilgiyi dilediğiniz zaman git diff solutions/podcastifier ile inceleyebilirsiniz.
3. [İSTEĞE BAĞLI] 🏴☠️ GCS Hazine Avı (Konsol Blob Kurtarma)
ℹ️ Ön Koşul Kontrolü: Yerel
cloud-sql-proxy
KSA Gerekli Bu isteğe bağlı alıştırma, yerel dizüstü bilgisayarınızı şifrelenmiş bir mTLS tüneli aracılığıyla doğrudan Google Cloud SQL'e bağlar. CLI proxy'nin yüklü olup olmadığını kontrol edin:
which cloud-sql-proxy
- Yüklüyse: Aşağıdaki adımlara geçin.
- Yüklü DEĞİLSE ve bu görevi yapmak istiyorsanız: Aşağıdaki yöntemlerle yükleyin:
# 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 - Aksi takdirde: 7. adımdaki otomatik doğrulama bölümüne geçebilirsiniz.
4. adımda, kapsayıcı yeniden başlatılmadan önce geçici SQLite veritabanı silinmeden yüklediğiniz fotoğrafı hatırlıyor musunuz? Bu resim dosyası, "üst öğesi olmayan blob" olarak özel GCS paketinizde güvenli bir şekilde durmaya devam eder.
Hata ayıklamak ve bir Cloud SQL gönderisine eklemek için Rails konsolunu kullanalım:
# 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 konsolunda:
# 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
Blogunuzu yenileyin: 4. Adım'daki Stateless Shock sırasında yüklenen fotoğraf yeniden oluşturulur ve Cloud SQL yayınınıza kalıcı olarak eklenir.
4. 7. adımda otomatik doğrulama
Üretken yapay zeka görevlerini ve öğelerini doğrulama:
just workshop-eval 7
10. 8. adım: Kendi maceranı seç / İleri seviye görevler 🏆
Kanonik referans mimarisinde uzmanlaştığınıza göre mezuniyet görevini seçin.
🛡️ 1. görev: Sıfır güvenli Google IAP (Identity-Aware Proxy)
- Zorluk: Orta (Enterprise Security)
- Amaç: Cloud Run uygulamanızı yalnızca doğrulanmış Google / Gmail hesaplarınızın erişebileceği şekilde kilitlemek ve şifreyle giriş yapma yöntemini tamamen ortadan kaldırmak.
- İşleyiş şekli:
- Harici HTTPS uygulama yük dengeleyicisi, Google OAuth'u sonlandırır ve trafik Cloud Run'a ulaşmadan önce kimliği doğrular.
- Google, doğrulanmış kimlik üstbilgilerini (
X-Goog-Authenticated-User-Email) yönlendirir. - Rails, doğrulanmış Google kimliğini
blog/app/controllers/concerns/iap_authenticatable.rbaracılığıyla otomatik olarak oturum açar: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 iac/iap.tfiçindeenable_iap = trueile Terraform modülünü etkinleştirin ve izin verilen Google Hesaplarınızı belirtin:iap_allowed_users = [var.google_cloud_account]

📊 2. Görev: Üretim SRE Telemetrisi ve Cloud Logging
- Zorluk: Orta (Gözlemlenebilirlik)
- Hedef: İzleme korelasyon kimlikleriyle yapılandırılmış JSON uygulama günlüklerini doğrudan Google Cloud Logging'e aktarın ve Cloud Error Reporting ile üretim istisnalarını gerçek zamanlı olarak yakalayın.
- İşleyiş şekli:
blog/config/environments/production.rb'yı, GCP izleme etiketleriyle yapılandırılmış JSON günlükleri yayacak şekilde yapılandırın.- Kasıtlı bir test istisnası tetikleyin ve Google Cloud Error Reporting'in sizi anında gruplandırıp bilgilendirmesini izleyin.
📸 TODO(riccardo): add screenshot of Google Cloud Error Reporting showing grouped production exceptions and Cloud Logging structured JSON payload with trace labels
🧠 3. Görev: pgvector Anlamsal Arama ve Gemini RAG
- Zorluk: Zor (Üretken Yapay Zeka Bitirme Projesi)
- Amaç: Cloud SQL'deki PostgreSQL'de depolanan vektör yerleştirmelerini kullanarak makalelerde kavramsal olarak arama yapın.
- İşleyiş şekli:
- Cloud SQL PostgreSQL örneğinizde
vectoruzantısını etkinleştirin:CREATE EXTENSION IF NOT EXISTS vector; neighborgem'iniblog/Gemfile'ye ekleyin vePost#after_saveüzerinde Gemini (text-embedding-004) ile metin yerleştirmeleri oluşturun.- Turbo Streams ile semantik arama çubuğunu desteklemek için kosinüs mesafesi sorguları (
<=>) gerçekleştirin.
- Cloud SQL PostgreSQL örneğinizde
📸 TODO(riccardo): add screenshot of the live blog semantic search bar returning conceptual matches with cosine similarity scores
⚡ 4. görev: SEO ve Performans Denetimi Asistanı
- Zorluk: Kolay / Eğlenceli (Geliştirici Deneyimi)
- Amaç: Antigravity ve Speedgrapher araçlarını kullanarak Core Web Vitals, Largest Contentful Paint (LCP) ve Flesch-Kincaid / Fog okunabilirlik indekslerini denetleyin.
📸 YAPILACAKLAR(riccardo): Speedgrapher / Lighthouse SEO ve Core Web Vitals denetleme özetinin ekran görüntüsünü ekleyin
🤔 Merak Kutusu: Cloud Run'da Canlı Rails Konsolu Alma
💡 Soru: Geleneksel sanal makinelerde veya Heroku tarzı PaaS platformlarında geliştiriciler, üretim verilerini canlı olarak incelemek ya da düzeltmek için genellikle çalışan bir örneğe SSH ile bağlanır veya heroku run rails console kullanır. Cloud Run'a özel eşdeğeri nedir ve nasıl zorlaştırılır?
Neden?
gcloud run exec
Cloud Run hizmetleri için mevcut değil
Cloud Run bir sunucusuz platformdur: Kapsayıcınız, sabit bir kimliği veya adreslenebilir kabuğu olmadan sıfır, bir veya yüzlerce özdeş örnek olarak çalışabilir. Bu, temel olarak Kubernetes'ten (kubectl exec) farklıdır. Kubernetes'te belirli bir kapsülün, bağlanabileceğiniz adlandırılmış bir soketi vardır.
# ❌ 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'de Yerel Olarak Desteklenen Dört Kalıp
Kalıp | Komut | Etkileşimli mi? | Güvenlik |
1. Yerel proxy + uzak veritabanı |
| ✅ Tam | 🔒 Cloud SQL Auth Proxy mTLS |
2. Cloud Run işi (tek seferlik) |
| ❌ Yalnızca senaryo | 🔒 IAM rolü gerekir |
3. Web Console gem'i + IAP | Tarayıcı → | ✅ Tam | 🛡️ IAP Zero-Trust |
4. Cloud Shell + Proxy | Cloud Shell → | ✅ Tam | 🔒 Google kimliği |
1. Kalıp (Veri incelemesi için önerilir): Cloud SQL Auth Proxy aracılığıyla doğrudan Cloud SQL PostgreSQL ile iletişim kuran yerel bir Rails konsolu çalıştırın:
# 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
Sıfır ağ maruziyetiyle tam IRB etkileşimi elde edersiniz. Cloud SQL Proxy, Unix alan soketi veya geri döngü üzerinden mTLS kullanır.
3. Kalıp (Web Konsolu + IAP Zero-Trust, güvenliği artırılmış tarayıcı yolu):
web-console gem, tarayıcı tabanlı bir IRB oturumu sağlar. Korunmadığı takdirde kritik bir güvenlik açığı oluşturur. Bu nedenle, herkese açık olarak hiçbir zaman kullanmayın. Ancak Google IAP (Quest 1) ile birlikte kullanıldığında saldırı yüzeyi daralır: Yalnızca izin verilenler listenizdeki doğrulanmış Google kimlikleri /rails/console uç noktasına ulaşabilir.
# 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. kalıbın kullanılabilmesi için öncelikle Quest 1'in (UİSA) etkinleştirilmesi gerekir. Bu sertifika olmadan, herkese açık bir URL'de /rails/console kullanmak sunucu odanızı kilitlemeden bırakmaya eşdeğerdir. IAP ile Google düzeyinde sıfır güvenlikle güçlendirilmiş etkili bir operatör aracı haline gelir.
Antigravity'ye sorun: " nasıl çalıştırılır?"
rails console --sandbox
Cloud SQL Auth Proxy'yi kullanarak Cloud SQL üretim veritabanıma karşı güvenli bir şekilde çalıştırabilirim."
🏆 The Hive'da mezuniyet: Gözetmen tarafından onaylanmış iş kanıtı
Seçtiğiniz görevi tamamladıktan sonra The Hive Leaderboard'da 8. Adım Mezuniyet Kupası 🏆'nı talep edin:
- Görevlerinizi GitHub'da Gönderme:
- Resmi depoda yeni bir sorun açın: github.com/palladius/rails8-app-on-gcp/issues/new
- Başlık biçimi:
🎓 [Step 8 Completed]: - Gövdeye, başardıklarınızla ilgili kısa bir açıklama ve canlı Cloud Run dağıtımınızın bağlantısını ekleyin.
- Cloud Run uygulamanızı sorununuzla ilişkilendirin:
- Sorun numaranızı (ör.
88veya tam URLhttps://github.com/palladius/rails8-app-on-gcp/issues/88) not edin. STEP_8_GHIortam değişkenini Cloud Run hizmetinize ekleyin:gcloud run services update blog \ --region europe-west1 \ --update-env-vars STEP_8_GHI=<YOUR_ISSUE_NUMBER>/status.jsonuç noktanızın artık görevinizi bildirdiğini doğrulayın: Aşağıdaki bilgileri görürsünüz: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" }
- Sorun numaranızı (ör.
- Gözetmen incelemenizi alın ve altın kupayı kazanın:
- The Hive skor tablosunu kontrol edin: Satırınızda artık kehribar rengi bir rozet gösterilir:
⏳ GHI #XX review pending. - Atölye gözetmenlerinden (@palladius, @emilianodellacasa veya @ricc) dağıtımınızı incelemelerini isteyin.
- Bir gözetmen sorununuzla ilgili yorum yaptığında
LGTMThe Hive, ilerlemenizi otomatik olarak 8/8 🏆'a yükseltir. Bu durumda, altın/mor renkte parlayan bir rozet ve doğrudan bitirme projesi sorununuzla bağlantılı kalıcı bir kupa alırsınız.
- The Hive skor tablosunu kontrol edin: Satırınızda artık kehribar rengi bir rozet gösterilir:
11. Sonuç ve Temizleme 🎓
Tebrikler! 🎉
Google Cloud Platform'da üretime hazır, kurumsal düzeyde bir Rails 8 uygulaması oluşturup dağıtmış olmanız gerekir:
- Sıfır Şube İlerlemesi:
mainüzerinde Time Machine katmanlarıyla modern iş akışlarında uzmanlaşma. - Cloud Storage: IAM blob imzalama (
iam: true) ile ölçeklenebilir, özel nesne depolama alanı. - Cloud SQL: Cloud SQL Auth Proxy mTLS tünelleriyle güvenliği sağlanan yönetilen PostgreSQL.
- Secret Manager: Düz metin biçiminde kimlik bilgisi veya
.envdosyası sızıntısı yok. - Cloud Run Çok Kapsayıcılı: Yalıtılmış Puma web, Solid Queue çalışan ve proxy yan kapsayıcıları.
- Üretken Yapay Zeka: Vertex AI ile asenkron eski poster üretimi ve TTS podcast sentezi.
- Görevler: Sıfır güven temelli IAP, SRE Observability ve pgvector yerleştirmeleri
🧹 Kaynak Temizleme
Çalıştayı tamamladıktan sonra ücretlendirilmeye devam etmemek için Google Cloud kaynaklarınızı temizlemeyi unutmayın. Ortamınıza en uygun yaklaşımı seçin:
1. seçenek: Terraform Teardown (önerilen / varsayılan 🟢)
Diğer kaynakların veya verilerin bulunduğu mevcut ya da paylaşılan bir Google Cloud projesi kullanıyorsanız bu seçeneği belirleyin. Bu komut, projenizin geri kalanına dokunmadan yalnızca bu atölye çalışması sırasında sağlanan kaynakları (Cloud Run, Cloud SQL, Secret Manager, GCS bucket'ları) tamamen yok eder.
cd iac
terraform destroy -auto-approve
2. seçenek: Projenin tamamen silinmesi (Hiç iz bırakmayın 🌪️)
Özel bir atölye projesi oluşturduysanız (ör. atölye kredileri veya bir sandbox kullanarak) ve günlükler, meta veriler, hizmet hesapları ve faturalandırma bağlantıları dahil olmak üzere hiçbir iz kalmamasını istiyorsanız bu seçeneği kullanın.
gcloud projects delete $GOOGLE_CLOUD_PROJECT --quiet