Skip to main content
Repo memakai dua workflow di .github/workflows/:
WorkflowTriggerFungsi
ci.ymlPush & PR ke mainLint, doctor, docs, tests
deploy-cloudflare.ymlManual (workflow_dispatch)Deploy ke app.sertifikasitrainer.com
Repo GitHub: trisnalesmana/aimentor
Tab Actions: github.com/trisnalesmana/aimentor/actions

Status saat ini

Ringkasan kondisi pipeline setelah workflow di-push ke main:
KomponenStatusKeterangan
Workflow CI✅ AktifJalan otomatis tiap push/PR ke main
Workflow Deploy Cloudflare✅ Ada, belum pernah di-runHanya manual lewat Actions
CI run terakhir✅ HijauLint, doctor, docs, web tests lulus
API tests di CI✅ Blockingvitest run di apps/api — 352 tests
Environment production✅ DibuatMasih perlu isi secrets sebelum deploy
Repository secrets❌ Belum diisiDeploy akan gagal tanpa secrets di bawah
CI sudah jalan. CD belum siap dipakai sampai environment production dan secrets di-setup di GitHub.

Job CI — mana yang blocking?

JobBlocking?Catatan
Lint (lint:ci)YaHanya scripts/, thub, .github/
thub doctorYaCek struktur repo, bukan secret nyata
Mintlify docsYavalidate + broken-links
Web testsYaVitest di apps/web
API testsYabun run test (vitest) di apps/api

Cara cek sendiri

Lewat browser

  1. Buka Actions
  2. Klik workflow CI — run hijau = pipeline utama lulus
  3. Klik workflow Deploy Cloudflare — kalau kosong, belum pernah dijalankan
  4. Settings → Environments — pastikan ada production
  5. Settings → Secrets and variables → Actions — cek secret sudah terisi

Lewat GitHub CLI

# Workflow terdaftar
gh workflow list --repo trisnalesmana/aimentor

# Run CI terbaru
gh run list --repo trisnalesmana/aimentor --limit 5

# Detail satu run (ganti ID dari list di atas)
gh run view <RUN_ID> --repo trisnalesmana/aimentor

# Log job yang gagal
gh run view <RUN_ID> --repo trisnalesmana/aimentor --log-failed

# Cek secrets (nama saja, nilai tidak ditampilkan)
gh secret list --repo trisnalesmana/aimentor

# Cek environment
gh api repos/trisnalesmana/aimentor/environments

Checklist setup CD

Centang ini sebelum menjalankan Deploy Cloudflare pertama kali:
1

Buat environment production

GitHub → Settings → Environments → New environment → nama: production
Opsional: tambah required reviewers supaya deploy butuh approval.
2

Isi DOTENV_SHARED

Salin seluruh isi file .env shared lokal (bukan path file).
Format: satu KEY=value per baris, multiline secret di GitHub.
3

Isi DATABASE_URL

URL Neon production untuk migrate saat deploy, misalnya: postgresql://...@ep-xxx.neon.tech/neondb?sslmode=require
4

Isi token Cloudflare

  • CLOUDFLARE_API_TOKEN — token dengan akses Workers (Wrangler)
  • CLOUDFLARE_ACCOUNT_ID — dari dashboard Cloudflare
5

(Opsional) WORKER_SECRETS_B64

Kalau opsi Push worker secrets aktif saat deploy:
./thub secrets generate
base64 -w0 .cloudflare/worker-secrets.json
Salin output ke secret WORKER_SECRETS_B64.
6

Jalankan deploy manual

Actions → Deploy CloudflareRun workflow → pilih branch main.

CI (ci.yml)

Setiap push atau PR ke main menjalankan job paralel:
bun run lint:ci — Biome pada scripts/, thub, .github/ (blocking).
bun run lint (seluruh monorepo) belum di-gate di CI karena masih ada lint debt legacy.
./thub doctor --ci — cek struktur env, script, dan dependency (blocking).
mint validate + mint broken-links di apps/docs (blocking).
bun run test (vitest) di apps/api dengan TZ=Asia/Jakarta (blocking).
bun run test di apps/web (blocking).

Simulasi lokal

bun run lint:ci
./thub doctor --ci
cd apps/docs && npx -y mint@latest validate && npx -y mint@latest broken-links
cd apps/web && bun run test
cd apps/api && bun run test

CD (deploy-cloudflare.yml)

Deploy hanya manual — tidak auto-deploy saat merge ke main.
1

Buat environment `production`

Di GitHub repo → Settings → Environments → tambah production.
Opsional: aktifkan required reviewers untuk gate deploy.
2

Isi repository secrets

SecretWajibKeterangan
DOTENV_SHAREDYaIsi penuh file .env shared (multiline)
DATABASE_URLYaURL Neon untuk migrate production
CLOUDFLARE_API_TOKENYaToken Wrangler dengan akses Workers
CLOUDFLARE_ACCOUNT_IDYaAccount ID Cloudflare
WORKER_SECRETS_B64Opsional*Base64 dari .cloudflare/worker-secrets.json
* Diperlukan jika opsi Push worker secrets diaktifkan saat deploy.
3

Generate WORKER_SECRETS_B64

./thub secrets generate
base64 -w0 .cloudflare/worker-secrets.json
Salin output ke secret WORKER_SECRETS_B64.
4

Jalankan workflow

GitHub → ActionsDeploy CloudflareRun workflow.Input opsional:
InputDefaultArti
Skip database migrationfalseLewati psql migrate
Skip web buildfalseDeploy tanpa rebuild frontend
Push worker secretstrueSync secrets ke Wrangler sebelum deploy
Run smoke testtrue./thub smoke prod setelah deploy

Apa yang dijalankan di CI deploy

  1. scripts/ci-materialize-env.sh — tulis .env dari DOTENV_SHARED, optional DATABASE_URL.env.production.local, lalu ./thub env merge --prod
  2. scripts/ci-push-worker-secrets.sh — decode WORKER_SECRETS_B64 → push via sync-worker-secrets.sh
  3. scripts/deploy-prod.sh — migrate, build, deploy Workers
  4. ./thub smoke prod — health check production

Perbandingan dengan deploy lokal

Lokal (./thub deploy)GitHub Actions
Env.env + override lokalSecret DOTENV_SHARED
KonfirmasiKetik yesWorkflow dispatch
Secrets./thub secrets pushWORKER_SECRETS_B64 + script CI
Targetapp.sertifikasitrainer.comSama
Deploy lokal tetap valid untuk hotfix cepat; CI/CD untuk audit trail dan env terpusat di GitHub.

Troubleshooting CI

Pesan: lockfile had changes, but lockfile is frozen.Penyebab: package.json berubah (misalnya workspace apps/docs) tapi bun.lock belum di-commit.Perbaikan lokal:
bun install
git add bun.lock
git commit -m "fix(ci): sync bun.lock"
git push
Pastikan bun install --frozen-lockfile sukses dan tidak ada file .env yang di-commit. Doctor CI tidak butuh secret nyata — hanya struktur repo.
Saat ini tidak menggagalkan workflow (continue-on-error). Banyak test API butuh env lengkap atau masih assertion lama. Job ini informatif dulu — perbaikan test API bisa dilakukan bertahap.
Secret harus berisi seluruh isi .env shared, bukan path file. Format KEY=value per baris.
Cek DATABASE_URL di environment production. URL harus reachable dari runner GitHub (Neon dengan SSL).
Tunggu propagasi Cloudflare (~1 menit), lalu re-run hanya smoke: ./thub smoke prod lokal dengan env production, atau re-run workflow dengan skip migrate/build.