Communitygithub.com

Afresto-Next/afresto-claude-skills

name: afresto-deploy

What is afresto-claude-skills?

afresto-claude-skills is a Claude Code agent skill that name: afresto-deploy.

Works withClaude Code~Codex CLI~Cursor
npx skills add Afresto-Next/afresto-claude-skills

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Deploy Afresto Next

Tumpukan: backend Go (push→GHCR→Watchtower ~5 mnt) · web React (Vite→Cloudflare Worker, manual wrangler deploy) · mobile RN/Expo di repo terpisah <repo-mobile> (EAS OTA). Deploy produksi = selalu minta izin user dulu (mereka menyetujui tiap kali).

🔴 Aturan #1 — repo ini sering dipakai BANYAK TAB AGENT sekaligus

git status kerap menampilkan berkas termodifikasi milik sesi lain. Karena itu:

  • JANGAN git add -a / git commit -a / git add . — akan menyapu pekerjaan setengah jadi sesi lain masuk commit-mu.
  • Stage SELEKTIF tiap berkas milikmu, lalu verifikasi: git diff --cached --name-only — pastikan tak ada berkas asing (yang sering nyasar: web/src/pages/ChatPage.tsx, backend/internal/db/dbgen/models.go bila bukan hasil regen-mu).
  • Berkas dipakai bersama dua sesi (mis. ExamPage) & kamu hanya mau hunk-mu: jangan stash/reset (menarik berkas dari bawah kaki agent lain). Sunting index Git lewat blob: git show :path > tmp → buang hunk mereka dari tmpSHA=$(git hash-object -w tmp)git update-index --cacheinfo 100644,$SHA,path. Berkas di disk tak tersentuh.
  • 🚨 cwd tool Bash bisa MENETAP dari cd .../web (atau worktree) di panggilan sebelumnya. Lalu git add backend/... GAGAL pathspec did not match (atau MEN-stage tree yang salah). Sebelum stage selektif, cd <repo-root> && dulu (atau pakai path absolut). Verifikasi git diff --cached --name-only menampilkan path relatif-root yang benar (bukan ../backend, src/...).
  • Setelah deploy: cek git status — pastikan berkas kerja sesi lain masih utuh.

Gerbang mutu Go (sebelum commit backend)

Padanan Pint + PHPStan ala Laravel untuk Go. Jalankan lokal sebelum stage berkas backend:

  • Format: cd backend && gofmt -l .harus KOSONG. Ada isi → gofmt -w . (auto-fix), stage hasilnya. (Padanan pint --test.)
  • Build + vet: go build ./... && go vet ./... hijau.
  • Analisis statis (target): golangci-lint run ./... (bungkus gofmt/govet/staticcheck/errcheck/ineffassign/unused/misspell). Padanan phpstan analyse.
  • ⚠️ Status: gerbang CI belum aktif. Belum ada backend/.golangci.yml maupun .github/workflows/ci.yml, dan staticcheck masih usang → jadi format+build+vet ini manual dulu. Rencana enforce di CI + config lengkap: docs/plan/00-tooling-quality-gate.md. Kode generated internal/db/dbgen dikecualikan dari lint.
  • Test menyertai perubahan → skill afresto-testing (go test ./...; integration ter-skip tanpa TEST_DATABASE_URL).

🔴 Aturan #00 — pekerjaan BERMAKNA masuk GitHub issue DULU (sejak 5 Sep 2026)

Berlaku sebelum Aturan #0 (cabang + PR): sebelum menyentuh kode sama sekali.

Tujuannya bukan formalitas. Permintaan yang datang lewat obrolan hanya diketahui dua pihak — tim tak bisa membacanya, pemilik tak punya tempat menugaskan, dan modulnya tak meninggalkan jejak siapa mengerjakan apa.

Kapan WAJIB issue

Fitur baru · perubahan yang dilihat sekolah · perubahan skema DB · apa pun yang butuh keputusan produk · pekerjaan yang lebih dari satu PR.

Kapan TIDAK perlu

Bug yang jelas & sempit · koreksi teks/label · dokumentasi · tindak lanjut langsung dari komentar review PR.

Ragu → buat issue. Murah, dan bisa ditutup. Ambang ini yang menjaga aturannya hidup: kalau setiap permintaan sepele jadi issue, orang akan mulai melewatinya diam-diam, dan sekali dilewati tanpa akibat, aturannya mati.

Yang dilakukan agen

  1. Telusuri kode secukupnya untuk mengisi "temuan awal" & menemukan blocker — jangan menebak.
  2. Buat issue pakai template .github/ISSUE_TEMPLATE/pekerjaan.md, beri label modul:* (itu yang membentuk catatan per modul), plus butuh-keputusan bila ada yang menggantung.
  3. BERHENTI. Jangan koding, jangan buat cabang, jangan menugaskan diri sendiri. Penugasan adalah tindakan pemilik; tim juga perlu ruang memberi masukan/merevisi ide.
  4. Laporkan nomor issue-nya ke pemilik, beserta keputusan yang masih menggantung (bila ada).

🔑 Pemilik boleh melewatinya dengan bilang "kerjakan sekarang" — issue tetap dibuat sebagai catatan, pekerjaan jalan terus. Aturan ini mengatur bawaan, bukan memenjarakan.

Blocker yang baru ketahuan DI TENGAH pengerjaan

Beri tahu sebelum melanjutkan: komentar di issue (supaya tim ikut melihat) dan sampaikan ke pemilik. Bila keputusannya menghentikan pekerjaan → tambah label butuh-keputusan. Jangan diam-diam memilih tafsir sendiri lalu jalan terus — itu yang menghasilkan pekerjaan yang "selesai" tapi salah.

Menutup lingkarannya

PR wajib memuat Closes #<nomor> di badannya. Itu yang menyambungkan issue → PR → orang, sehingga gh issue list --label modul:ujian --state all menjadi catatan siapa mengerjakan apa di modul itu. Tanpa baris itu, jejaknya putus.

🔴 Aturan #0 — JANGAN commit/push langsung ke main (tim 4 orang, sejak 25 Jul 2026)

Semua kerja lewat cabang + Pull Request; hanya reviewer yang merge ke main (merge = pemicu deploy).

  1. Sebelum mulai: git checkout main && git pull — bila ada migrasi baru, jalankan migrasi dulu.
  2. Buat/checkout cabang bertema SEBELUM menyentuh kode:
    • fitur → feat/<nama> · bug → bugfix/<nama> · bug ber-issue → cabang baru + pelajari issue-nya.
  3. Commit selektif → git push -u origin <cabang> (BUKAN ke main).
  4. Buka PR ke main: gh pr create bila gh login; kalau belum, beri user URL https://github.com/Afresto-Next/next/compare/main...<cabang>?expand=1.
  5. Reviewer approve & merge → deploy. JANGAN merge PR sendiri.
  • Bagian "Push backend / Deploy WEB" di bawah = mekanik yang jalan SETELAH PR merge ke main (biasanya oleh yang bertugas deploy), bukan izin push langsung ke main.
  • Perubahan skill pun lewat PR (CODEOWNERS).

Urutan langkah

1. Commit (Bash tool = Git Bash / sh, BUKAN PowerShell)

  • Pesan multi-baris: heredoc git commit -q -F - <<'EOF' … EOF. JANGAN @'…'@ (itu here-string PowerShell → subjek tercemar jadi @ ...).
  • Akhiri pesan: Co-Authored-By: Claude Opus 4.8 <[email protected]>.
  • Warning "CRLF will be replaced by LF" = normal, abaikan.
  • Commit ke cabang tugasmu (feat/* · bugfix/*), bukan main (lihat Aturan #0). User commit saat diminta.

🔴 JANGAN git add -A / git add <dir>/ — sudah 3x menyapu berkas user

Repo ini menyimpan banyak berkas kerja user yang belum terlacak: docs/bskap/ (gambar+PDF), docs/analisis butir soal/, elibrary/, cloudflare/**/.wrangler/ (cache akun). Sekali -A, semuanya ikut.

Kejadian nyata: git add docs/ menyeret PDF/xls/gambar BSKAP (25 Jul & 2 Agu); git add -A menyeret 446 berkas termasuk wrangler-account.json (9 Agu).

git add path/ke/berkas1 path/ke/berkas2        # SATU PER SATU, selalu
git commit -q -F - <<'EOF'
...
EOF
git show --name-only --format="" HEAD | wc -l   # cocok dgn yang kamu niatkan?

Kalau jumlahnya melenceng: git reset --soft HEAD~1 && git reset, stage ulang yang benar. Bila sudah ter-push ke cabang sendiri, git push --force-with-lease aman.

2. Migrasi DB — WAJIB di commit TIP

.github/workflows/migrate.yml mendeteksi migrasi via git diff --name-only HEAD~1 HEAD (hanya commit teratas), berjalan setelah "Build & Push Docker Images" sukses (workflow_run).

  • Bila push berisi migrasi → migrasi harus ada di commit TIP (satu commit berisi migrasi+kode = aman).
  • Migrasi jalan otomatis di self-hosted runner VM setelah build. run --rm migrate sinkron → job GAGAL keras bila error (bukan senyap).
  • Verifikasi migrasi: cek tab Actions → "Migrate DB" hijau untuk commit itu (gh CLI tersedia: gh run list --workflow="Migrate DB (self-hosted)" --limit 1 — agen bisa cek sendiri, tak perlu menyuruh user). Watchtower tukar image api di poll berikutnya (~5 mnt), hampir selalu setelah migrasi selesai.
  • SEBELUM push migrasi, verifikasi SQL-nya via psql BEGIN; … ROLLBACK; di DB lokal (v102 = prod). Lihat skill afresto-db-change / jebakan-rekayasa §4.

🔴 Nomor migrasi: periksa ulang TEPAT SEBELUM MERGE, bukan saat membuat cabang

Rekan tim bisa men-merge seri migrasi lain selagi cabangmu terbuka. Nomor kembar membuat goose PANIK di sortAndConnectMigrations — bukan galat SQL, jadi mudah salah dibaca. ✅ Tak ada kerusakan data: panik terjadi saat mengumpulkan daftar, sebelum satu pun dijalankan.

Kejadian nyata (9 Agu 2026): dipilih 00138 saat membuat cabang; saat merge, tim sudah memakai 0013800140. Perbaikan pertama menamainya 00140 dan masih bentrok — karena menebak lagi. Hitung, jangan tebak:

git pull                                        # WAJIB dulu, biar lihat migrasi rekan
MAX=$(ls backend/migrations/ | sed 's/_.*//' | sort -n | tail -1)
NEXT=$(printf "%05d" $((10#$MAX + 1)))
ls backend/migrations/ | sed 's/_.*//' | sort | uniq -d   # HARUS KOSONG

Kalau sudah terlanjur: git mv ke nomor baru, PR kecil, merge, lalu jalankan ulang workflow "Migrate DB (self-hosted)" dari tab Actions.

3. Push backend (SETELAH PR merge ke main — lihat Aturan #0)

Merge PR → main diperbarui → GHCR → Watchtower ~5 mnt menukar image. Tak ada perubahan backend = tak perlu tunggu Watchtower. (Saat mengembangkan: git push -u origin <cabang> lalu PR — jangan push main.)

⚠️ SETELAH merge backend: CEK 502 (sudah kambuh 6x)

Membuat-ulang container api/worker sering memicu outage total — semua container Up tapi seluruh rute 502. Praktis tiap merge backend adalah lemparan dadu.

curl -s -o /dev/null -w "%{http_code}
" --max-time 15 https://next.afresto.co/api/v1/auth/me
# 401 = SEHAT (minta autentikasi) · 502 = outage

Bila 502 → Actions → "Ops — pulihkan API" → restart-docker (tanpa SSH, pulih <1 menit). Jangan membedah fitur yang baru di-deploy: 502 + container Up = restart daemon Docker. Detail: docs/ops-auto-pulih.md.

4. Deploy WEB — dari WORKTREE BERSIH (karena banyak tab agent)

npm run build membaca SELURUH working tree → pekerjaan setengah jadi sesi lain ikut terbit. Jadi build & deploy dari worktree di commit-mu:

rm -rf /c/wtd 2>/dev/null; git worktree add --detach /c/wtd <SHA-commit-mu>
cd /c/wtd && git status --short   # harus KOSONG (bersih)
cd /c/wtd/web && npm ci && npm run build
cd /c/wtd/cloudflare/web-worker && npx wrangler deploy
cd <repo-projectTwo> && git worktree remove --force /c/wtd && git worktree prune
  • 🔥 Path worktree WAJIB PENDEK (/c/wtd) — scratchpad dalam + nama PDF kaldik DKI yang panjang → error Windows "Filename too long" saat checkout.
  • Verifikasi bundel benar bila perlu: grep -rl "<penanda fiturmu>" /c/wtd/web/dist/assets/*.js — tapi hati-hati positif palsu (penanda umum bisa dari fitur lain).
  • Cloudflare cache aset ~20 dtk → uji dengan Ctrl+F5. (200 tapi ukuran ~397 byte = fallback, bukan aset asli.)

5. Mobile OTA — repo terpisah, --environment WAJIB

cd "<repo-mobile>"
npx eas update --branch preview --environment preview --message "…" --non-interactive
  • 🔥 --environment WAJIB (preview/production) — tanpa itu update salah environment/gagal.
  • Repo mobile punya remote GitHub (Afresto-Next/afresto-next-mobile) → berlaku Aturan #0: cabang → PR → merge, jangan push langsung ke main.
  • OTA hanya JS/aset. Perubahan modul native → CRASH bila via OTA → wajib build ulang.

🔥 eas update mengirim WORKING TREE, bukan commit

Sama persis dengan npm run build di langkah 4 — seluruh direktori kerja ikut terbundel, termasuk pekerjaan setengah jadi sesi lain. Tanda * pada baris Commit <hash>* di hasil publikasi = tree kotor.

WAJIB tepat sebelum publish — cetak, lalu cocokkan dengan baris Commit di hasil:

echo "publish dari: $(git branch --show-current) @ $(git log --oneline -1 --format=%h)"
git log --oneline HEAD..origin/main   # KOSONG = tak ada pekerjaan orang lain yang tertinggal
  • Publikasikan dari main, bukan cabang fitur. Dari cabang, pekerjaan orang lain yang sudah merge HILANG dari channel — OTA mengganti seluruh bundel, tidak menambal.
  • Produksi: pinggirkan dulu perubahan tak-commit milik sesi lain (git stash push -- <berkas>git stash pop). Produksi tak boleh membawa kode yang belum ditinjau.

🚨 Cabang bisa BERPINDAH di tengah pekerjaan (banyak tab agent, satu klon)

Kejadian 20 Agu 2026: publikasi preview jelas dari main @ d0938fa; perintah berikutnya mendapati HEAD sudah di cabang lain @ 8126a50 — sesi lain berpindah cabang di klon yang sama. Produksi sempat menjalankan kode 3 PR lebih lama, tanpa satu pun error.

➡️ Jangan berasumsi cabang masih sama antar-perintah. Cetak ulang tiap kali (perintah di atas). ➡️ Pencegahan sesungguhnya: OTA dari WORKTREE, sama seperti deploy web di langkah 4 — sesi lain tak bisa menggeser cabangnya:

rm -rf /c/wtm 2>/dev/null; git worktree add --detach /c/wtm <SHA-commit-mu>
cd /c/wtm && git status --short          # harus KOSONG
npm ci && npx eas update --branch <ch> --environment <env> --message "…" --non-interactive
cd <repo-mobile> && git worktree remove --force /c/wtm && git worktree prune

🪤 Path worktree pendek (/c/wtm) — alasan sama dengan langkah 4. 🪤 npm ci di worktree perlu waktu; untuk OTA kecil boleh tetap di klon utama asal verifikasi cabang+commit di atas dijalankan dan hasilnya cocok.

🏢 GHCR & organisasi GitHub — repo kini di org Afresto-Next

Repo (next, afresto-next-mobile, afresto-claude-skills) pindah dari ristology/*org Afresto-Next (20 Jul 2026). Runbook transfer lengkap: docs/runbook-transfer-next-org.md.

  • 🚨 Transfer repo ke org = path GHCR ikut owner → Watchtower BEKU DIAM-DIAM. CI tag image ghcr.io/${GITHUB_REPOSITORY_OWNER}/afresto-next-{api,web,migrate} — owner mengikuti pemilik repo. Setelah transfer, image baru masuk ghcr.io/afresto-next/* TAPI VM docker-compose.prod.yml masih pull ghcr.io/${GHCR_OWNER:-ristology}/*produksi tak update (image lama tetap jalan, TANPA error). Package GHCR TIDAK ikut pindah (tetap milik akun lama; org bikin package BARU yang private). FIX di VM (~/afresto-next): set GHCR_OWNER=afresto-next di .envdocker login ghcr.io (PAT read:packages) → pull api web migrateup -drestart watchtower (watchtower bind ~/.docker/config.json; tanpa restart pakai creds lama → auto-update mati senyap). Runner self-hosted + variabel Actions DEPLOY_DIR IKUT pindah otomatis (tak perlu daftar ulang; tetap verifikasi Settings→Actions→Runners online). Rollback: balik GHCR_OWNER lama + pull/up. 🚫 JANGAN hapus package ghcr.io/ristology/* lama sampai path baru stabil beberapa siklus.
  • 🪤 docker compose pull (tanpa argumen) GAGAL untuk image :local (caddy/backup dibangun DI VM, bukan GHCR) → "pull access denied … afresto-next-caddy"WAJAR, abaikan. Pull selektif pull api web migrate. up -d tak menariknya (image lokal sudah ada).

Verifikasi tanpa akses langsung (probe dari luar)

  • Rute baru ada? curl -o /dev/null -w '%{http_code}' https://afresto.co/api/v1/<rute>401 = terdaftar (backend baru naik), 404 = belum. Host benar: afresto.co / origin.afresto.co + prefix /api/v1. api.afresto.co TIDAK ADA (selalu 404).
  • Migrasi schools sehat? GET https://afresto.co/api/v1/public/branding?subdomain=demo → 200 = SELECT * schools sehat.
  • Perubahan PERILAKU (bukan rute baru) tak bisa di-probe → jangan klaim "terverifikasi", sebut tunggu Watchtower / uji di next.afresto.co (demo, bebas dicoba).

🔥 Checklist ringkas sebelum bilang "selesai"

  1. Backend? gofmt -l backend kosong + go build/vet hijau + test menyertai (afresto-testing).
  2. git status → hanya berkasku ter-stage; sesi lain utuh.
  3. Migrasi (bila ada) di commit TIP; Actions "Migrate DB" hijau.
  4. Web dari worktree bersih /c/wtd; worktree dibersihkan setelahnya.
  5. OTA pakai --environment, dari main, dan cabang+commit dicetak lalu dicocokkan dengan baris Commit di hasil publikasi (* = tree kotor, kerja sesi lain ikut terkirim).
  6. Backend butuh Watchtower ~5 mnt sebelum diuji; web cukup Ctrl+F5.
  7. Sentuh auth/nilai? Pertimbangkan /code-review pada diff dulu.

Terkait: afresto-db-change · afresto-code-style (arsitektur berlapis) · afresto-testing · docs/plan/00 (gerbang mutu) · memori afresto-next-jebakan-rekayasa (§11b migrate.yml, §11 heredoc), afresto-next-progress-2026-07-17-sore (pola worktree), afresto-next-gcp-vm-deploy, afresto-next-frontend-cloudflare-worker.

Related Skills