Deploy hataları belirtisizdir. Dört korkuluk — ayrı vault'lar, EDITOR script'leri, geri okuma kontrolü, env'e göre runtime çevirme — Claude'u yararlı tutar, yakmadan.
Deploy ile kod yazmak arasındaki en büyük fark: deploy tek atışlık, yüksek bahisli ve geri almak can sıkıcıdır. Bozuk bir satır kod yazarsın, bir test koşusu yakalar. Bozuk bir satır credentials yazarsın, ilk gerçek ödemenin başarısız olduğunda öğrenirsin — kullanıcılar kartı çektirmiş, para hesabına düşmemiş, loglar sadece 400 dolu.
Yakın zamanda how2claude'u yerel dev'den prodüksiyona Claude ile taşıdım: Stripe live hesabı, x402 mainnet cüzdanı, Google OAuth, Kamal secrets. Claude hangi değerlerin test hangilerinin gerçek olduğunu bilmiyor. sk_live_ ile sk_test_ arasındaki tek harflik farkın kıyamet sonuçları olduğunu bilmiyor. Korkulukları sen diziyorsun.
Rails varsayılan olarak config/credentials.yml.enc kullanır, şifre çözücü config/master.key. Bu varsayılanı kullanıyorsan kaybettin.
sk_live_xxx'ı bu dosyaya koyarsan ve yerelde test koşarsan, test kodun prodüksiyon Stripe'ı çağırıyor demektir. Her test koşusunda gerçek kart çekiliyor.
İkiye böl:
- config/credentials.yml.enc + config/master.key: dev/test, sk_test_xxx tutar
- config/credentials/production.yml.enc + config/credentials/production.key: prod, sk_live_xxx tutar
Her iki .key .gitignore'a, her iki .enc commit edilir. production.key sadece deploy makinesinde durur.
Sonra Kamal secrets doğru dosyayı göstermeli:
# .kamal/secrets
-RAILS_MASTER_KEY=$(cat config/master.key)
+RAILS_MASTER_KEY=$(cat config/credentials/production.key)
Container içindeki RAILS_MASTER_KEY artık prodüksiyon anahtarını gösteriyor ve çözülen şey prodüksiyon credentials'ıdır. Claude'un bu satırı yazarken özellikle dikkat ettim — varsayılan Kamal şablonu config/master.key'dir (dev olanı), ki bu sessizce dev Stripe key'ini prodüksiyona deploy eder.
bin/rails credentials:edit --environment production etkileşimli bir editör açar. Claude etkileşimli editörü sürdüremez. Sen de düzinelerce gizli değeri elle yapıştırmak istemezsin (bir yazım hatası her şeyi bozar).
Bu kalıbı kullan:
EDITOR="ruby script/set_prod_webhook_secret.rb" \
bin/rails credentials:edit --environment production
rm script/set_prod_webhook_secret.rb
script/set_prod_webhook_secret.rb şöyle görünür:
# ARGV[0] şifresi çözülmüş geçici YAML dosyasının yolu
file = ARGV[0]
require "yaml"
data = YAML.load_file(file) || {}
data["stripe"] ||= {}
data["stripe"]["webhook_secret"] = "whsec_GHWObNAKFh2HPOlJpbGmlYfIiKz1C8EY"
File.write(file, data.to_yaml)
Rails şifresi çözülmüş YAML'ı geçici bir dosyaya yazar, o yolu argüman olarak "EDITOR"ünü çağırır ve çıkışta yeniden şifreler. Senin "EDITOR"ün aslında cerrahi olarak bir anahtarı değiştirip kaydeden bir Ruby scripti.
Neden iyi:
- Hassas: sadece stripe.webhook_secret'a dokunur, başka hiçbir şeye.
- Idempotent: iki kez çalıştırmak bir kez çalıştırmakla aynı.
- Denetlenebilir: script'in kendisi diff'tir. Claude yazar, sen bir bakarsın, ne değişeceğini tam olarak bilirsin.
- Silmede yok olur: rm'den sonra diskte düz metin credential yok, shell geçmişinde whsec_... yapıştırması yok.
Her credential için bir script: set_stripe_live_key.rb, set_webhook_secret.rb, set_price_ids.rb, set_wallet_address.rb. Her birini hemen sonra rm'le.
Yazdıktan sonra doğru yazdığına güvenme. Geri oku:
bin/rails runner -e production "
c = Rails.application.credentials
puts 'sk_live set: ' + c.dig(:stripe, :secret_key).to_s.start_with?('sk_live_').to_s
puts 'webhook_secret set: ' + c.dig(:stripe, :webhook_secret).to_s.start_with?('whsec_').to_s
puts 'wallet prefix: ' + c.dig(:x402, :wallet_address).to_s[0..5]
puts 'wallet len: ' + c.dig(:x402, :wallet_address).to_s.length.to_s
"
Anahtar, sadece değerleri yazdırmak değil prefix ve uzunluk kontrolleri.
sk_live_ ile başlar. Geri okuyunca sk_test_ çıkarsa, Claude test key'ini prod dosyasına koymuş — ilk gerçek ödemeye kadar bulamayacağın bir bug.whsec_ ile başlar. Formatın doğru mu yanlış mı, bir bakışta görülür.0x...'tır. Yanlış uzunluk, başka bir karakterin sızdığı anlamına gelir.Prefix kontrolleri eklemek çoğu yazım hatasını, eksik alanı ve karışmış ortamı engeller.
"Deploy öncesi network'ü mainnet'e çeviririm" demek cazip gelir. Bu tür bir geçiş insan hafızasına bağlıdır. Er geç seni yakar.
Kuralı initializer'a göm:
# config/initializers/x402.rb
X402.configure do |c|
c.wallet_address = Rails.application.credentials.dig(:x402, :wallet_address)
c.chain = Rails.env.production? ? "base" : "base-sepolia"
end
Aynı kod, dev'de testnet (sepolia), prod'da mainnet (base). Deploy anında değiştirilecek bir şey yok. Claude "geçiş yapmayı unutmaz" çünkü geçiş onun işi değil.
Aynı numara basescan_tx_url için, Plan görünürlüğü için (dev-only planlar prod'da render olmaz), Stripe price ID seçimi için ve diğerleri. Dev ile prod arasında farklı olan her şeyi Rails.env ile çevir. Deploy anında hatırlamaya bel bağlama.
Dört korkuluk da yerindeyken, ilk gerçek para ödemesine yine de sen tıklamalısın.
Önceki yazı Sessiz Hataları Claude ile Ayıklamak'ta yazdım: prodüksiyonda ilk x402 ödeme tıklamasında console'da invalid_string at payTo. Cüzdan adresinin 43. karakteri Çince IME'den sızmış tam genişlikli bir soru işaretiydi. Prefix kontrolleri yakalayamadı (0x hâlâ oradaydı), testler yakalayamadı (testler gerçek işlem göndermez), sadece bir gerçek tıklama ortaya çıkardı.
Deploy korkulukları Claude için değil. Senin için — otomatikleştirilebilecek olanları otomatikleştir (prefix'ler, uzunluklar, env çevirmeleri) ki kazandığın dikkat, otomatikleştirmenin kapsamayacağı gerçek etkileşimlere gitsin.
Claude-deploy'un tam akışı:
.enc + .key dosyalarına ayır.EDITOR=script üzerinden besle, hemen sil.Rails.env üzerinden çevir, deploy anında değil.Deploy "daha yüksek bahisli kod yazmak" değildir. Deploy "kimsenin sana yanlışını söylemediği kod yazmak"tır. Korkuluklar "kimse söylemiyor"u "15 saniyede öğreniyorsun"a çevirmek için vardır.