Free

Niech Claude wdraża na produkcję

Błędy deploya nie mają objawów. Cztery barierki — osobne vaulty, skrypty EDITOR, weryfikacja przez odczyt wstecz, flip runtime po env — żeby Claude był użyteczny bez spalenia wszystkiego.


Największa różnica między wdrożeniem a pisaniem kodu: wdrożenie jest jednorazowe, wysokiej stawki, bolesne do cofnięcia. Napisz zepsutą linię kodu, jeden test łapie. Napisz zepsutą linię credentials, dowiesz się dopiero przy pierwszej prawdziwej płatności — użytkownicy obciążyli kartę, pieniądze nie trafiły na twoje konto, logi to same 400.

Niedawno przeniosłem how2claude z lokalnego deva na produkcję razem z Claude'em: konto Stripe live, portfel x402 mainnet, Google OAuth, Kamal secrets. Claude nie wie, które wartości są testowe, a które prawdziwe. Nie wie, że sk_live_ vs sk_test_ to różnica jednej litery z apokaliptycznymi konsekwencjami. Barierki stawiasz ty.

Barierka #1: osobne pliki credentials dla dev i prod

Rails domyślnie ma config/credentials.yml.enc, deszyfrowane przez config/master.key. Jeśli używasz tego domyślnego, przegrałeś.

Jeśli wrzucisz sk_live_xxx do tego pliku i potem puścisz testy lokalnie, twój kod testowy używa Stripe produkcji. Każdy przebieg testów obciąża prawdziwą kartę.

Podziel na dwa:
- config/credentials.yml.enc + config/master.key: dev/test, trzyma sk_test_xxx
- config/credentials/production.yml.enc + config/credentials/production.key: prod, trzyma sk_live_xxx

Oba .key w .gitignore, oba .enc zacommitowane. production.key żyje tylko na maszynie deploy.

Potem Kamal secrets musi wskazywać na właściwy plik:

 # .kamal/secrets
-RAILS_MASTER_KEY=$(cat config/master.key)
+RAILS_MASTER_KEY=$(cat config/credentials/production.key)

Wewnątrz kontenera RAILS_MASTER_KEY wskazuje teraz na klucz produkcji, a to, co się deszyfruje, to credentials produkcji. Patrzyłem jak Claude pisze tę linię — domyślny template Kamal to config/master.key (ten dev), który cicho wdraża dev Stripe key na produkcję.

Barierka #2: używaj skryptu EDITOR, nie kopiuj-wklej

bin/rails credentials:edit --environment production otwiera interaktywny edytor. Claude nie potrafi sterować interaktywnym edytorem. Ty też nie chcesz ręcznie wklejać tuzina sekretów (jeden typo i wszystko pada).

Użyj tego pattern'u:

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 wygląda tak:

# ARGV[0] to ścieżka do tymczasowego rozszyfrowanego pliku YAML
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 zapisuje rozszyfrowany YAML do pliku tymczasowego, woła twój "EDITOR" z tą ścieżką jako argumentem, i szyfruje ponownie przy wyjściu. Twój "EDITOR" to po prostu skrypt Ruby, który chirurgicznie zmienia jeden klucz i zapisuje.

Dlaczego to dobre:
- Precyzyjne: dotyka tylko stripe.webhook_secret, niczego innego.
- Idempotentne: puszczenie dwa razy to to samo co raz.
- Audytowalne: skrypt jest diffem. Claude go pisze, ty rzucasz okiem, wiesz dokładnie co zmieni.
- Znika po usunięciu: po rm nie ma na dysku credential w plaintextcie, nie ma w historii shella paste'a whsec_....

Jeden skrypt na credential: set_stripe_live_key.rb, set_webhook_secret.rb, set_price_ids.rb, set_wallet_address.rb. rm każdy zaraz po.

Barierka #3: weryfikuj odczytując wstecz przez Rails runner

Po zapisaniu nie wierz że zapisał poprawnie. Odczytaj wstecz:

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
"

Kluczem są sprawdzenia prefixu i długości, a nie tylko wydrukowanie wartości.

  • Stripe live secret zawsze ma prefix sk_live_. Jeśli odczytasz wstecz sk_test_, Claude wrzucił test key do pliku prod — bug, którego nie znajdziesz do pierwszej prawdziwej płatności.
  • Webhook secrets zawsze mają prefix whsec_. Format prawidłowy lub nie, widać na pierwszy rzut oka.
  • Adresy portfeli EVM zawsze mają 42 znaki, 0x.... Zła długość oznacza że jakiś inny znak się wcisnął.

Dodanie sprawdzeń prefixu blokuje większość typo, pominiętych pól i pomieszanych środowisk.

Barierka #4: przełączaj w runtimie po env, nie ręcznie przy deployu

Kuszące jest pomyśleć "zmienię network na mainnet przed deployem". Taki przełącznik opiera się na ludzkiej pamięci. Prędzej czy później cię sparzy.

Wpisz regułę do initializera:

# 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

Ten sam kod, testnet (sepolia) w dev, mainnet (base) w prod. Przy deployu nic do zmiany. Claude nie może "zapomnieć przełączyć", bo przełączanie nie jest jego robotą.

Ten sam trik dla basescan_tx_url, widoczności Plan (plany dev-only nie renderują się w prod), wyboru Stripe price ID, itd. Wszystko co różni się między dev i prod, flipuj przez Rails.env. Nie polegaj na tym że przypomnisz sobie przy deployu.

Ostatni krok: przejdź prawdziwy flow sam

Z czterema barierkami na miejscu, pierwszy klik płatności prawdziwymi pieniędzmi i tak musisz zrobić sam.

W poprzednim artykule Debugowanie cichych bugów z Claude'em opisałem pierwszy klik płatności x402 na produkcji: invalid_string at payTo w konsoli. 43. znak adresu portfela to znak zapytania pełnej szerokości który wkradł się z chińskiego IME. Sprawdzenia prefixu nie mogły złapać (0x był na miejscu), testy nie mogły złapać (testy nie odpalają prawdziwych transakcji), tylko prawdziwy klik to wywołał.

Barierki deploya nie są dla Claude'a. Są dla ciebie — zautomatyzuj to co da się zautomatyzować (prefixy, długości, flipy env) żeby zaoszczędzona uwaga szła na prawdziwe interakcje których automatyka nie pokrywa.


Pełny flow Claude-deploy:

  1. Oddziel credentials dev i prod do osobnych plików .enc + .key.
  2. Dla każdej wartości do ustawienia napisz jednorazowy skrypt Ruby, karm przez EDITOR=script, od razu usuń.
  3. Po każdym zapisie odczytaj wstecz przez Rails runner, sprawdzaj prefixy i długości.
  4. Wszystkie różnice dev/prod flipuj przez Rails.env, nie przy deployu.
  5. Przycisk prawdziwych pieniędzy pierwszy raz klikasz sam.

Deploy to nie "pisanie kodu o wyższych stawkach". Deploy to "pisanie kodu gdzie nikt ci nie mówi że się mylisz". Barierki istnieją by zamienić "nikt nie mówi" na "wiesz w 15 sekund".