8. modulCI/CD, környezetek, migrációk, release-stratégia
Cloudflare for Devs · 8. modul · bővített kiadás

CI/CD, környezetek, migrációk, release-stratégia

Ez a modul nem szépíti a dolgokat: pontosan megmondjuk, mi az, amit a platform készen ad (version-modell, PR-preview-k, kanári, rollback), mi az, ami csak konvenció (a környezetek), és mi az, amit neked kell megépítened (a séma-migrációk fegyelme). A végén a hibaforgatókönyvek: mi van, ha a migráció élesben hasal el.

8.1Az alap: version és deployment

Beanstalkon a „deploy" egyetlen esemény: az új kód felmegy, a régi eltűnik. A Workers ezt kettévágja, és minden más erre épül:

npx wrangler versions upload   # feltöltés forgalom nélkül → version ID + preview URL
npx wrangler versions deploy   # forgalom ráengedése / arányállítás
npx wrangler deploy            # a kettő egyben: upload + 100% promote
npx wrangler rollback          # vissza az előző deployolt versionre — másodpercek

Mivel a versionök már fent vannak a hálózaton, a kanári-emelés és a rollback csak metaadat-átállítás — nem újra-deploy. Ez az, amit a CodeDeploy blue/green környezet-duplázással közelített.

8.2Környezetek: pontosan mi különül el, és ki hozza létre?

Az első tisztázandó: a Cloudflare-nek nincs „environment" nevű platformfogalma úgy, ahogy az AWS-en egy külön account vagy egy Beanstalk environment létezik. Amit „staging"-nek hívsz, az három dolog konvenciója:

  1. egy nevesített konfig-blokk a wrangler-fájlban (env.staging),
  2. egy ebből születő külön Worker (my-app-staging) saját route-tal,
  3. és külön erőforrás-példányok, amiket te hozol létre és kötsz be.

Ez a harmadik pont a kulcs, amit sokan elsőre félreértenek: az env.staging blokk megírása nem hoz létre semmit. A staging D1-et, R2 bucketet, queue-t, KV namespace-t neked kell megteremtened, névvel megkülönböztetve, majd a konfigban az adott env alá bekötnöd:

# a staging világ erőforrásai — egyszeri létrehozás
npx wrangler d1 create app-staging --location weur
npx wrangler r2 bucket create uploads-staging
npx wrangler queues create jobs-staging
npx wrangler kv namespace create CONFIG_STAGING

# és ugyanez -prod utótaggal a productionnek
wrangler.jsonc — a két világ, teljesen szétválasztva
{
  "name": "my-app",
  "main": "./.output/server/index.mjs",
  "compatibility_date": "2026-08-02",
  "compatibility_flags": ["nodejs_compat"],

  "env": {
    "staging": {
      "name": "my-app-staging",
      "route": { "pattern": "staging.example.com/*", "zone_name": "example.com" },
      "vars": { "APP_ENV": "staging" },
      "d1_databases": [{ "binding": "DB", "database_name": "app-staging", "database_id": "…" }],
      "r2_buckets":   [{ "binding": "UPLOADS", "bucket_name": "uploads-staging" }],
      "queues": { "producers": [{ "binding": "JOBS", "queue": "jobs-staging" }] }
    },
    "production": {
      "name": "my-app-production",
      "route": { "pattern": "app.example.com/*", "zone_name": "example.com" },
      "vars": { "APP_ENV": "production" },
      "d1_databases": [{ "binding": "DB", "database_name": "app-prod", "database_id": "…" }],
      "r2_buckets":   [{ "binding": "UPLOADS", "bucket_name": "uploads-prod" }],
      "queues": { "producers": [{ "binding": "JOBS", "queue": "jobs-prod" }] }
    }
  }
}
A vasszabály, ami mindenkit meglep egyszer: a bindings és a vars nem öröklődnek a top-level konfigból a nevesített env-ekbe — a docs ezt hívja non-inheritable keys-nek. Minden env-ben mindent explicit fel kell sorolni. Ez szándékos: így nem fordulhat elő, hogy egy kihagyott sor miatt a staging csendben a prod DB-re bindol. A tünet, amiből felismered: „stagingen undefined az env.DB" — a staging blokkból kimaradt a d1_databases.

Hol van ez pontosan leírva? Mert jogos az igény, hogy ne az én szavamra kelljen hinni:

TémaHivatalos doksi
Environments működése, öröklés szabályaidevelopers.cloudflare.com/workers/wrangler/environments
Non-inheritable keys listája…/workers/wrangler/configuration („Non-inheritable keys" szakasz)
Builds + environments összekötése…/workers/ci-cd/builds/advanced-setups („Wrangler Environments")
Branch-vezérlés, non-prod buildek…/workers/ci-cd/builds/build-branches
Preview URL-ek + Access-védelem…/workers/versions-and-deployments/preview-urls
D1 migrációk…/d1/reference/migrations

8.3Workers Builds és a PR-k: mi történik valójában?

A Builds branch-logikája két ágra bomlik, és mindkét ághoz saját parancsot rendelsz:

EseményMi fut leAlapértelmezés
push a production branchre (main)build command → deploy commandnpx wrangler deploy
push bármely más branchre (ha a non-production branch builds be van kapcsolva)build command → non-production branch deploy commandnpx wrangler versions upload → preview URL, PR-komment

Most jön a rész, amit a marketingoldalak elmosnak, és amire a kérdésed pontosan rátapintott: mi a PR-preview valójában?

A PR-preview KÓD-preview, nem KÖRNYEZET-preview. A versions upload feltölti a branch kódját versionként, kapsz rá URL-t — de a version bindingjai a build során használt configból jönnek. Alapbeállításban (env-ek nélkül) ez azt jelenti, hogy a PR-preview ugyanazokra az erőforrásokra (DB! bucket! queue!) mutat, mint az éles Worker. A docs ezt ki is mondja (a Pages-migrációs útmutatóban): a Workers nem támogat natívan eltérő bindingokat production és non-production buildekhez — a hivatalos ajánlás a Wrangler environments használata a parancsokban.

A helyes, biztonságos alapfelállás tehát ez a parancspár a Builds beállításaiban:

# Deploy command (production branch):
npx wrangler deploy --env production

# Non-production branch deploy command (minden PR):
npx wrangler versions upload --env staging

Ezzel minden PR-preview a staging erőforrásokon fut: staging DB, staging bucket, staging queue. A reviewer kattint a PR-kommentben lévő URL-re, és egy élő, de veszélytelen változatot néz. Ez a legtöbb csapatnak pontosan elég — és ez a berendezkedés kb. 20 perc munka.

És a „minden PR-nak saját, izolált környezete" álom?

Őszintén: ezt a platform nem adja készen. Nincs beépített „ephemeral environment per PR" — a PR-ek a közös staging erőforrásokon osztoznak. Ebből három következmény és három szintű megoldás adódik:

SzintMit csinálszMikor elég / mikor kell
1. Közös staging (alapeset)minden PR-preview ugyanarra a staging DB-re/bucketre mutata PR-ek 95%-ának elég; ütközés ritka, mert a preview-t emberek kattintgatják, nem terhelés éri
2. Szkriptelt per-PR erőforráskülső CI-ben (Actions): PR-nyitáskor API-val létrehozod a pr-123 nevű D1-et/queue-t, egy generált env-konfiggal buildelsz, PR-záráskor takarítaszha a PR-ek gyakran hoznak séma-változást, és a közös staging DB folyton „el van rontva" — ez kb. egy napnyi CI-munka, és teljesen működőképes minta
3. Branchelhető adatbázisPostgres + Hyperdrive esetén Neon-féle szolgáltató, ahol a DB branchelhető: PR-onként copy-on-write adatbázis-branch, prod-szerű adattalha a per-PR izoláció prod-szerű adattal kell — D1-nek nincs branch fogalma (a Time Travel visszaállítás, nem elágazás)

8.4A séma-migráció helye a pipeline-ban

Ez a modul legfontosabb szakasza, mert itt találkozik minden korábbi szál: a kanári (két kódverzió fut egyszerre!), a rollback (kódot vált, sémát nem!) és a DB-fegyelem. Előbb a három elv, aztán a konkrét workflow.

A három elv

  1. A migráció a repo része és verziózott. Sorszámozott fájlok (migrations/0007_add_invoice_status.sql), a PR-ban együtt utaznak a kódváltozással — a reviewer egyszerre látja a séma- és kódváltozást. Az állapotkönyvelést a wrangler d1 migrations apply végzi (meta-tábla a DB-ben: mi futott már le).
  2. A migráció külön pipeline-lépés, a kód-deploy ELŐTT fut. Soha nem a Worker kódjából, soha nem „majd az első kérés migrál" — hanem explicit lépésként: előbb a séma, aztán a kód.
  3. Minden migráció expand–contract. Mivel kanári alatt a régi és az új kód egyszerre fut ugyanazon a sémán, és mivel a rollback bármikor visszahozhatja a régi kódot, a séma minden pillanatban mindkét szomszédos kódverziót ki kell szolgálja. Gyakorlatban: expand fázis (új oszlop/tábla hozzáadása — a régi kód nem tud róla, nem is zavarja), majd külön, későbbi release-ben a contract (a régi oszlop törlése, amikor már biztosan senki nem használja).
Expand–contract: miért két release a „rename oszlop"? Release N — expand + új oszlop (nullable/default) kód: MINDKETTŐT írja, újat olvassa köztes állapot backfill batchekben (Queues/Workflow) kanári és rollback IS biztonságos Release N+1 — contract régi oszlop törlése csak ha N-re már nem kell rollback Az anti-minta: „egy release-ben átnevezem az oszlopot és átírom a kódot" — kanári alatt a régi kódverzió azonnal törik, és a rollback sem ment meg.
8/1. ábra — Az expand–contract nem „best practice díszítés": a kanári és a másodperces rollback előfeltétele.

A konkrét workflow — auto és manuális határvonallal

FázisSéma-lépésAuto/manuális?
PRa migration fájl a PR része; lokálisan --local apply + tesztek; a PR-preview a staging sémán futauto (CI teszteli)
Merge → stagingwrangler d1 migrations apply app-staging --env staging --remote, aztán deploy staging, smoke tesztekauto — a staging arra van, hogy itt derüljön ki a baj
Production1) migráció apply (expand), 2) kanári 10%, 3) 100%gated — emberi jóváhagyás a migráció ÉS a kanári-emelés előtt
Contractrégi oszlop/tábla törlésekülön, későbbi PR — soha nem ugyanabban a release-ben

Hova építed ezt? Két működő elrendezés van, és a válasz a prod-gate igényedtől függ:

A) Workers Builds egyedül — a deploy command lánccá fűzhető: npx wrangler d1 migrations apply app-db --env production --remote && npx wrangler deploy --env production. Ez működik, de auto-migrál minden main-pushnál, emberi kapu nélkül — kis csapatnak, alacsony kockázatú sémáknál vállalható, éles multitenant SaaS-nál nem ezt ajánlom.

B) GitHub Actions a prod-úthoz (ajánlott) — a PR-preview-t és a staginget viheti a Builds, a production-release viszont Actions-workflow, amelyben a production GitHub environmentre required reviewers van beállítva — a migráció és a kanári csak jóváhagyás után indul:

.github/workflows/release.yml — vázlat
jobs:
  migrate-and-canary:
    environment: production        # ← itt áll meg, amíg valaki jóvá nem hagyja
    steps:
      - run: npx wrangler d1 migrations apply app-db --env production --remote
      - run: npx wrangler versions upload --env production   # → version ID
      - run: npx wrangler versions deploy … # 10% kanári a friss versionre
  promote:
    needs: migrate-and-canary
    environment: production-promote  # második kapu: 100%-ra emelés
    steps:
      - run: npx wrangler versions deploy … # 100%

Multitenant, DB-per-tenant felállásnál (5b. modul) a prod-migráció lépés nem egy apply, hanem a Workflow-alapú flotta-runner elindítása — canary tenantokkal, verziókönyveléssel; az elve ugyanez: gated indítás, automatizált végrehajtás.

8.5Amikor a migráció élesben elhasal

És most a kérdésed legkeményebb része: mi van, ha a prod-adat olyan állapotban van, amit a teszt nem fedett le? Vegyük sorra a klasszikus hibamódokat — mindhez a megelőzés ÉS a mentés.

a) Adat-függő hiba: a NULL, amire senki nem gondolt

Tünet: a ALTER TABLE … ADD COLUMN x TEXT NOT NULL vagy egy CREATE UNIQUE INDEX elszáll, mert a prod-ban vannak NULL-ok/duplikátumok, amik a staging játékadatában nem voltak.

b) Timeout: a nagy tábla, amit egyben akartál átírni

Tünet: az UPDATE orders SET status_v2 = … egy 40 milliós táblán túllépi az időkorlátot (D1-nél a query-korlátokat, Postgresnél lock-vihart okoz).

c) Félbeszakadt migráció: mi az állapot most?

d) A playbook — mi a teendők sorrendje élesben

  1. Állj. A pipeline ne lépjen tovább (ezért kell a kanári-emelés elé is kapu) — félkész séma + új kód 100%-on a legrosszabb kombó.
  2. Mérd fel: a migráció el sem indult (pre-flight fogta meg — nincs kár), félbeszakadt (séma részleges — mi ment át?), vagy lefutott, de rossz (adat sérült)?
  3. A futó szolgáltatást védd először: ha az új kód már kanárin van, wrangler rollback — az expand-jellegű séma a régi kódot nem zavarja, tehát a userek szempontjából a tűz el van oltva másodpercek alatt. Ez az igazi hozadéka az egész fegyelemnek.
  4. Aztán a séma: fix-forward (javított migráció újrafuttatása) az alapeset; Time Travel/restore csak adatsérülésnél, a friss írások mérlegelésével; multitenant flottánál a runner a hibás tenantnál állt meg — a többiek vagy érintetlenek, vagy már készen vannak, a registry mutatja.
  5. Utólag: ami élesben bukott, az a stagingen hiányzó adat-eset volt → kerüljön be a prod-export-frissítésbe vagy a pre-flight query-k közé. A playbook így öngyógyító.

8.6Secrets: röviden, de pontosan

8.7A teljes kép: az ajánlott pipeline

PULL REQUEST (auto) tesztek + migration --local apply a CI-ban versions upload --env staging staging bindingokkal! preview URL a PR-ban élő review, veszély nélkül MERGE → MAIN (auto) migrate staging → deploy --env staging smoke tesztek staging.example.com PRODUCTION (kapukkal) ⛔ kapu 1 jóváhagyás pre-flight + migrate prod expand-only! kanári 10% metrikák figyelése ⛔ kapu 2 emelés OK? 100% baj esetén bármelyik pontról: wrangler rollback (kód, másodpercek) → aztán séma fix-forward
8/2. ábra — A teljes folyamat. Auto, ami visszafordítható (PR, staging); kapu, ami nem (prod-migráció, 100%-emelés).
AWS-fogalom náladCloudflare-megfelelő
CodePipeline / CodeBuildWorkers Builds és/vagy GitHub Actions + wrangler
Beanstalk staging environmentWrangler env: külön Worker + általad létrehozott külön erőforrások
blue/green (CodeDeploy)versions + gradual deployment — környezet-duplázás nélkül
deploy jóváhagyási lépésGitHub environment + required reviewers a prod-workflow-n
újra-deploy régi verzióból (percek)wrangler rollback (másodpercek, ~100 versionig)
Flyway/Liquibase futtatás a pipeline-banwrangler d1 migrations apply (vagy a flotta-Workflow) — ugyanott: deploy előtt, gated

8.8Ellenőrizd magad

  1. Mit hoz létre az env.staging blokk megírása a wrangler-konfigban — és mit nem?
    Válasz

    Csak konfigurációt: deploykor ebből születik a külön my-app-staging Worker a saját route-jával. A mögötte lévő erőforrásokat (staging D1, R2, queue, KV) NEM hozza létre — azokat te teremted meg (wrangler d1 create app-staging stb.) és kötöd be a blokkba. És mivel a bindings nem öröklődnek, mindet explicit fel kell sorolni.

  2. Alapbeállítású Workers Builds + PR-preview: milyen adatbázisra mutat a preview, és mi a helyes beállítás?
    Válasz

    Env-ek nélkül a preview version a configban lévő (azaz az éles) bindingokra mutat — a PR-preview kód-preview, nem környezet-preview. Helyesen: a non-production branch deploy command npx wrangler versions upload --env staging — így minden PR a staging erőforrásokon fut.

  3. Miért előfeltétele az expand–contract a kanárinak és a rollbacknek — nem csak „best practice"?
    Válasz

    Kanári alatt a régi és új kódverzió egyszerre fut ugyanazon a sémán; rollbacknél pedig a régi kód jön vissza a már migrált sémára. Ha a séma-változás breaking (rename, drop), a régi verzió azonnal törik — a kanári hibázik, a rollback nem ment meg. Az expand-fázisú séma mindkét szomszédos kódverziót kiszolgálja.

  4. Hol a határ az auto és a gated között a séma-migrációknál, és miért ott?
    Válasz

    Staging-ig minden auto (PR-teszt, staging apply + deploy) — ott a hiba olcsó, és pont az a dolga, hogy kiderüljön. A prod-migráció és a 100%-ra emelés gated (pl. GitHub environment + required reviewers), mert ezek nem, vagy csak drágán visszafordíthatók.

  5. A prod-migráció elszáll: NOT NULL oszlop nem vehető fel, mert NULL-ok vannak, amik a stagingen nem voltak. Mi a három védvonal, aminek ezt meg kellett volna fognia, és mi a teendő most?
    Válasz

    Védvonalak: prod-szerű adat a stagingen (rendszeres export/import), pre-flight ellenőrző query a migráció előtt (COUNT a NULL-okra → abort), és a szabály, hogy NOT NULL csak DEFAULT-tal vagy backfill utáni második lépésként megy fel. Teendő: a migráció el sem indult vagy elején állt meg → fix-forward: backfill-lépés beiktatása (batchelve!), majd a javított migráció újrafuttatása; a futó szolgáltatás közben érintetlen, mert a kód-deploy még el sem indult.

  6. 40 milliós tábla minden sorát át kell alakítani. Mi kerül a migrációs fájlba, és mi nem — és hova kerül a többi?
    Válasz

    A fájlba csak a séma-DDL (új oszlop, nullable/default). A tömeges adat-átalakítás backfill: külön, batchelt Workflow (LIMIT-elt UPDATE-ek step.do-ban, folytatható), időnyomás nélkül, mert az expand-séma alatt a régi és új oszlop együtt él. A contract (régi oszlop törlése) külön, későbbi release.

  7. Mikor nyúlsz a D1 Time Travelhez migráció-baleset után, és miért nem ez az első eszköz?
    Válasz

    Csak adatsérülésnél, és csak ha a sérülés óta kevés éles írás történt — mert a restore az egész DB-t viszi vissza, a friss legitim írásokkal együtt. Az első eszköz a kód-rollback (az expand-séma a régi kódnak nem árt) + fix-forward a sémán.

Előző7. modul — Aszinkron munka: Queues, Cron, Workflows, Durable Objects Következő 9. modul — Observability, biztonság, költségmodell