CI/CD: GitHub Actions → Cloudflare Pages
Kode Anda tinggal di repo GitHub privat (harryosmar/pangaea.id), dan setiap perubahan mengalir
lewat Pull Request. Inilah bagian yang mengubah "PR ter-merge" jadi "situs live ter-update" —
rangkaian CI/CDⓘ-nya, ujung ke ujung, lengkap dengan tiap perintah yang benar-benar Anda jalankan.
Satu fitur = satu Pull Request
Tak ada yang dirilis langsung ke main. Setiap perubahan dimulai dari sebuah branch, lalu dibuka
sebagai PR, dan baru ter-merge setelah semua cek hijau. Merge hijau itulah yang menerbitkan situs.
Dua cara menyambungkan Pages
Ada dua cara mendapatkan deploy Cloudflare Pages. Keduanya jalan; kami pakai yang kedua, dan alasannya penting.
Cara mudah — integrasi Git native
Cara yang kami pakai — GitHub Actions
Repo sudah berisi .github/workflows/deploy.yml: ia menjalankan build + typecheck di tiap PR,
dan baru men-deploy ke Pages setelah Anda menambahkan dua secret repository. Sebelum keduanya
ada, workflow tetap hijau tapi dorman — jadi Anda bisa memakai integrasi native dulu sekarang dan
beralih nanti.
File workflow-nya, dijelaskan
Seluruh pipeline ada di satu file yang sudah ikut dalam repo —
.github/workflows/deploy.yml.
Ini dia, sedikit dipangkas:
name: Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read # least-privilege: the job only reads the repo
jobs:
build-deploy:
runs-on: ubuntu-latest
env:
CF_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run typecheck
- name: Build
run: npm run build # prerender → dist/ + csp-hash.mjs (its last step)
env:
VITE_GA_ID: ${{ vars.VITE_GA_ID }}
# Deploy ONLY on a push to main, and only once the token secret exists.
- name: Deploy to Cloudflare Pages
if: ${{ github.event_name == 'push' && env.CF_API_TOKEN != '' }}
uses: cloudflare/wrangler-action@v4
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy apps/labs/dist --project-name=pangaea-id --branch=main
# After a real deploy, ping IndexNow so Bing/Yandex recrawl within minutes.
- name: Notify IndexNow (Bing/Yandex)
if: ${{ github.event_name == 'push' && env.CF_API_TOKEN != '' }}
continue-on-error: true
run: npm run indexnow -w @pangaea/labs
Langkah demi langkah:
on:— job berjalan di tiap push kemaindan tiap pull request kemain.permissions: contents: read— token GitHub job ini hanya bisa membaca repo; tak lebih.env: CF_API_TOKEN— memunculkan secret sekali agar langkah deploy bisa menguji apakah ia terisi.checkout+setup-node— clone repo dan pasang Node 20 dengan cache npm.npm ci— install bersih sesuai lockfile (reproducible, beda darinpm install).npm run typecheck— gate pertama. Error tipe menggagalkan job dan memblok PR.Build→npm run build— mem-prerenderⓘ tiap halaman kedist/dan menjalankancsp-hash.mjsdi langkah terakhir (alasan kami build di sini, bukan di container Cloudflare).VITE_GA_IDdatang dari GitHub Actions Variable (publik by design; kalau kosong = GA4 tetap no-op).Deploy …— gate yang menentukan:if: github.event_name == 'push' && env.CF_API_TOKEN != ''. Jadi PR mem-build + typecheck tapi tak pernah men-deploy, dan selama secret-nya belum ada, langkah ini cuma dilewati (job tetap hijau). Begitu ia jalan,wrangler-actionmengunggahdist/ke project Pagespangaea-id.Notify IndexNow— gate yang sama, pluscontinue-on-error: true. Setelah deploy sungguhan, ia mem-ping Bing/Yandex agar halaman baru atau yang berubah di-crawl ulang dalam hitungan menit; kegagalan sesaat tak pernah membuat deploy yang sehat ikut ditandai merah.
Rangkai deploy-nya: token → secret → Actions → Pages → domain
Ini jalur yang benar-benar dipakai situs. GitHub Actions mem-build (jadi csp-hash.mjs selalu jalan)
dan mengunggah ke Pages dengan wrangler. Satu push ke main = satu deploy live.
Langkah 1 — Buat project Pages (sekali)
wrangler pages deploy tidak membuat project secara otomatis — ia akan error Project not found [8000007]. Jadi buat dulu sekali saja. Bisa lewat dashboard (Workers & Pages → Create → Pages →
Use direct upload, bukan "Connect to Git" → beri nama persis pangaea-id, yang harus sama
dengan --project-name di workflow → Create), atau dari CLI:
npx wrangler login # membuka OAuth di browser, sekali saja
npx wrangler pages project create pangaea-id --production-branch=main
Langkah 2 — Buat token API hak-minimal
Profile → API Tokens → Create Token → Create Custom Token, persis:
- Token name —
github-actions-pages-deploy - Permission —
Account·Cloudflare Pages·Edit(yang ini saja, tak ada lagi) - Account Resources —
Include· akun Anda
Lalu Continue → Create, dan salin token sekarang — Cloudflare menampilkannya sekali saja.
Do
- Buat Custom Token dengan satu permission
Cloudflare Pages · Editsaja - Batasi ke satu akun Anda, dan salin nilainya segera
Don't
- Memberi
DNS/Zone/Workers/SSL—pages deploytak membutuhkannya, dan token yang sempit membatasi dampaknya kalau sampai bocor - Memakai template jadi (mis. "Edit Cloudflare Workers" — itu pilihan yang keliru, cakupannya terlalu luas)
Langkah 3 — Ambil Account ID Anda
Workers & Pages → sidebar kanan → Account ID (string hex 32 karakter).
Langkah 4 — Tambah dua secret GitHub
Repo → Settings → Secrets and variables → Actions → tab Secrets (bukan Variables) → New repository secret. Nama harus cocok persis:
CLOUDFLARE_API_TOKEN— token dari Langkah 2CLOUDFLARE_ACCOUNT_ID— ID dari Langkah 3
Langkah 5 — Deploy
Push atau merge ke main. Pantau GitHub → Actions → Deploy: langkah "Deploy … to Cloudflare
Pages" berubah dari skipped ke success, dan pangaea-id.pages.dev pun live. Langkah terakhir
"Notify IndexNowⓘ" lalu mem-ping Bing/Yandex agar halaman baru atau yang berubah di-crawl ulang dalam
hitungan menit — sifatnya best-effort (continue-on-error), dan ia hanya jalan setelah deploy
sungguhan.
Langkah 6 — Arahkan domain ke sana
Di Pages project → Custom domains → Set up a domain, tambahkan www.pangaea.id dan pangaea.id
(langkah ini menukar record parkir dengan record proxied yang benar). Lalu tambahkan redirect apex →
www 301 — lihat Bagian 3 · Root → www.
Contekan
Seluruh pipeline dalam satu baris:
merge PR → Actions build (npm run build → csp-hash) → wrangler pages deploy → npm run indexnow → live di www.pangaea.id dalam ~30d
Roll back kapan saja di Pages → Deployments → Rollback (instan, tanpa build ulang). Untuk memverifikasi rangkaiannya, read-only:
gh run list --branch main --limit 1 # run "Deploy" terbaru harusnya: success
curl -sI https://pangaea-id.pages.dev/ # 200 begitu project punya satu deployment
Troubleshooting: deploy pertama bilang "project not found"
npx wrangler login # kalau belum login
npx wrangler pages project create pangaea-id --production-branch=main
npx wrangler pages deploy apps/labs/dist --project-name=pangaea-id
Belum yakin project-nya sudah ada? Lihat dulu daftar project Anda — kalau pangaea-id ada di situ,
lewati langkah create dan langsung deploy (atau push ke main):
npx wrangler pages project list
Jangan
- Terus mengulang deploy berharap berhasil. "Not found" berarti project-nya memang belum ada — buat sekali, lalu deploy.
Pertanyaan umum
Bagaimana situs benar-benar dirilis saat Pull Request di-merge?
Merge ke main memicu pipeline deploy: GitHub Actions membangun situs (npm run build, lalu langkah pasca-build wajib csp-hash.mjs yang mengisi hash CSP asli ke _headers), mengunggah hasilnya ke Cloudflare Pages dengan wrangler, lalu menjalankan satu ping IndexNow terakhir (npm run indexnow) agar Bing/Yandex meng-crawl ulang halaman yang berubah dalam hitungan menit. Satu push ke main sama dengan satu deploy live, biasanya sekitar 30 detik. (Token API dan dua secret repository dirangkai di bagian atas.)
Kenapa GitHub Actions, bukan "Connect to Git" milik Cloudflare?
Karena integrasi Git bawaan membangun di dalam container Cloudflare sendiri dan akan melewati langkah csp-hash.mjs repo, sehingga hash CSP-nya salah. Ia juga pintu satu arah — begitu sebuah project memakai integrasi Git, Anda tak bisa mengembalikannya ke direct upload. Jadi build tetap di GitHub Actions, yang menjalankan langkah pasca-build lalu men-deploy.
Ada yang salah terkirim — bagaimana membatalkannya?
Roll back seketika di Pages → Deployments → Rollback. Ia mengarahkan ulang situs live ke deployment sukses sebelumnya tanpa build ulang, jadi pemulihannya langsung.
Berikutnya
Pipeline ini merilis situs statis yang domainnya diarahkan Bagian 1. Cerita bahasa-sederhana kenapa Cloudflare Pages alih-alih VPS sewaan ada di catatan build kami, Rilis — Git → CI/CD → Pages; serah-terima DNS yang lebih dulu ada di Arahkan domain ke Cloudflare (DNS).
Sources