build-q (bq) 🚀
build-q (dibaca bq) adalah CLI Python zero-dependency untuk operasi docker buildx lokal & remote yang selaras dengan pipeline CI/CD (Jenkins X). Satu perintah pendek bq menggantikan docker buildx build yang panjang, dengan auto-detect Git, cicd/cicd.json, secret netrc, resource limit, dan idempotency check terhadap registry.
Selain build, bq menyediakan scaffolding CI/CD (--init-jx, --init-legacy), bootstrap GitHub Actions trigger (--gh-action-init), setup secrets (--init-secrets), migrasi Dockerfile legacy ke pola --mount=type=secret (--fix-dockerfile), auto-init Docker Buildx builder (--init), dan mode compose (--compose) untuk build via make build && make release.
📚 Panduan Cepat untuk Pemula
Bagian ini untuk yang baru pertama kali pakai bq. Kalau sudah familiar, lanjut ke Instalasi.
Apa saja yang perlu di-install?
Sebelum pakai bq, siapkan tools berikut di laptop:
| Tools | Wajib? | Kegunaan | Cara install (macOS via Homebrew) |
|---|---|---|---|
| Python 3.7+ | ✅ Wajib | Runtime bq |
brew install python (biasanya sudah ada) |
| pipx | ✅ Rekomendasi | Install CLI Python secara terisolasi | brew install pipx && pipx ensurepath |
| Docker Desktop / Colima | ✅ Wajib | Docker engine + Buildx plugin | brew install --cask docker atau brew install colima docker docker-buildx |
| Git | ✅ Wajib | Auto-detect repo/branch | brew install git (biasanya sudah ada) |
GitHub CLI (gh) |
⚠️ Wajib untuk --clone, --remote, --gh-auth, --init-secrets, --gh-action-init |
Autentikasi GitHub, fetch token, clone repo | brew install gh && gh auth login |
| kubectl | ⚙️ Opsional | Fetch webhook token otomatis dari k8s (--init-secrets) |
brew install kubectl |
Cek versi setelah install:
python3 --version # >= 3.7
pipx --version
docker --version
docker buildx version
git --version
gh --version && gh auth status
kubectl version --client # opsional
Install bq (pemula, langkah demi langkah)
# 1. Install pipx (kalau belum ada)
brew install pipx
pipx ensurepath # tambahkan pipx ke PATH — restart terminal setelah ini
# 2. Install build-q
pipx install build-q
# 3. Verifikasi
bq --version # harus menampilkan versi terpasang
build-q --version # alias — sama saja
# 4. Bootstrap awal (buat config + Docker buildx builder)
bq --init
Setelah bq --init selesai, file config akan ada di ~/.build-q/.env dan Docker Buildx builder siap dipakai.
Upgrade ke versi terbaru
# Rekomendasi (pipx)
pipx upgrade build-q
# Kalau pakai pip biasa
pip install --upgrade build-q
# Pin versi tertentu (opsional)
pipx install --force build-q==0.1.11
# Cek versi yang sedang terpasang
bq --version
Tips: jika pipx upgrade bilang "already at latest" tapi kamu yakin ada rilis baru, refresh cache PyPI:
pipx install --force build-q # reinstall dari PyPI terbaru
Uninstall
pipx uninstall build-q # kalau install via pipx
pip uninstall build-q # kalau install via pip
rm -rf ~/.build-q # hapus config (opsional)
Alur 5 menit pertama (pemula)
# 1. Masuk ke folder service Go/.NET yang sudah ada Dockerfile
cd my-service
# 2. Preview command yang akan dijalankan (aman — tidak eksekusi)
bq --dry-run
# 3. Build tanpa push ke registry
bq --no-push
# 4. Build + push ke registry (mode default)
bq
Kalau muncul error builder not found → jalankan bq --init sekali dulu.
Kalau muncul error authentication required saat push → login ke Docker Hub / registry: docker login.
🛠 Fitur
Build & Push
-
Zero-dependency: hanya Python 3.7+ standard library.
-
Git auto-detection: nama repo & ref (branch/tag/short-SHA) dari Git.
-
Mode sumber kode: build lokal,
--clone(viaghCLI), atau--remote(Buildx Git context). -
Registry idempotency: cek image di registry sebelum build → skip bila sudah ada (bypass
--rebuild). -
Smart env mapping (ref → env) — INLINE dengan pipeline Tekton di
~/jenkins-x/pipeline(lighthousetriggers.yaml+webhook-server.py).bq(bq --clone/bq --compose) menyimpulkan environment otomatis dari nama ref, sama persis dengan case shell di pipeline. Nilai dipakai sebagai--build-arg BRANCH=(buildx) danENV=(compose):Ref (branch/tag) ENV IMAGE_TAG di pipeline v1.2.3,refs/tags/v*productionv1.2.3(basename ref)developdevelopshort SHA stagingstagingshort SHA sandboxsandboxshort SHA main,master, unknown, kosongstaging(fallback Tekton*))short SHA Perhatikan: push ke
main/masterTIDAK memicu production di JX — tagv*yang memicu. Override manual:--build-arg BRANCH=custom(buildx). -
Default netrc secret:
--secret id=netrc,src=$HOME/.netrcotomatis. -
Resource limit default: memory & CPU aman untuk laptop.
-
CI/CD alignment: baca
PORT/PORT2/PROJECT/IMAGEdaricicd/cicd.json. -
Dry run: pratinjau command tanpa eksekusi.
-
GitHub org shorthand: set
GITHUB_ORG=...di config → cukupbq <repo>bukanbq <owner>/<repo>. -
--remotefallback HTTPS: bilaSSH_AUTH_SOCKtidak tersetel,bqotomatis pindah ke HTTPS +GIT_AUTH_TOKEN(viagh auth token) untuk Buildx Git context — tidak perlu ssh-agent. -
--composemode: jalankanmake build ENV=...+make release ENV=...sebagai alternatifdocker buildx(cocok untuk repo yang alur build-nya via Makefile + docker compose).
Setup & Automation
--init: buat file config~/.build-q/.envdan auto-create Docker Buildx builder (bootstrap).- Template terpusat di gist: sejak
v0.1.14,--init-jx,--init-legacy, dan--gh-action-initfetch template dari gist mamatnurahmat (6 file). Cache lokal di~/.build-q/templates/(TTL 1 jam). Fallback ke bundled snapshot bila offline. Update / perbaikan template harus dilakukan di gist (viagh gist edit) — semua userbqotomatis dapat versi terbaru pada scaffold berikutnya. --init-jx: scaffoldMakefile+compose.yaml+Dockerfile(modern secret mount) +.github/workflows/trigger-ci.ymldaricicd/cicd.json. Auto-panggil--init-secretsbila git remote GitHub terdeteksi.--init-legacy: scaffoldMakefile+compose.yamluntuk pola legacy (Dockerfile pakaiARG GITHUB_USER/GITHUB_TOKEN— bukan BuildKit secret). Makefile auto-ambilgh auth tokenuntuk local dev. Dockerfile tidak di-overwrite — cocok untuk repo lama yang belum bisa migrasi ke secret mount.--gh-action-init: bootstrap standar.github/workflows/trigger-ci.ymlsebagai satu-satunya workflow — hapus semua workflow YAML lain di.github/workflows/, tulis ulang trigger-ci.yml, lalu set webhook secrets (WEBHOOK_TRIGGER_URL,WEBHOOK_TRIGGER_TOKEN).--init-secrets: set GitHub Actions secrets (WEBHOOK_TRIGGER_URL,WEBHOOK_TRIGGER_TOKEN) — auto-fetch token dari k8s secretwebhook-trigger-tokendi namespacejenkins-x, auto-detect target repo darigit remote.--fix-dockerfile: migrasi Dockerfile legacy menjadi modern. Deteksi & auto-fix:FROM ... as ...→AS(uppercase)- Hapus
ARG GITHUB_USER/ARG GITHUB_TOKEN RUN echo "machine github.com ..." > ~/.netrc && chmod ... && <cmd>→RUN --mount=type=secret,id=netrc,target=/root/.netrc \ ...- Baru: standalone
RUN echo ... > ~/.netrc(tanpa&& chmod && ...) → dihapus, lalu mount secret otomatis ditambahkan ke RUN line yang berisigo mod tidy/downloadataugo get. - Baru:
MAINTAINER foo(deprecated) →LABEL maintainer="foo" - Baru:
ENV KEY value(legacy) →ENV KEY=value - Backup asli disimpan ke
Dockerfile.bak.
--gh-auth: injeksi--build-arg GITHUB_USER+GITHUB_TOKENdarighCLI (workaround untuk Dockerfile legacy yang belum dimigrasi).- Auto-recover builder stale:
ensure_builderdeteksi endpoint rusak (misal socket Colima lama) dan recreate otomatis.
📦 Instalasi
pipx install build-q # rekomendasi (CLI global, virtualenv terisolasi)
# atau
pip install build-q
Dua entry point tersedia: build-q dan shorthand bq.
Upgrade ke versi terbaru:
pipx upgrade build-q
# atau
pip install --upgrade build-q
⚙️ Konfigurasi Awal (sekali saja)
bq --init # buat ~/.build-q/.env + create Docker buildx builder
bq --init --force # recreate config; builder tetap aman (cek dulu, buat bila tidak ada)
bq --config # tampilkan konfigurasi aktif
~/.build-q/.env
| Variable | Default | Keterangan |
|---|---|---|
BUILDER_NAME |
mybuilder |
Nama Docker Buildx builder |
REGISTRY_URL |
registry.example.com |
Docker registry (Qoin: loyaltolpi) |
DEFAULT_MEMORY |
4g |
Memory limit build |
DEFAULT_CPU_PERIOD |
100000 |
CPU period |
DEFAULT_CPU_QUOTA |
200000 |
CPU quota |
GIT_SSH_PREFIX |
git@github.com: |
Prefix SSH untuk --remote |
GITHUB_ORG |
(kosong) | Default org untuk shorthand bq <repo> |
WEBHOOK_TRIGGER_URL |
https://cicd-hw.qoin.id/trigger |
Endpoint webhook Jenkins X |
JX_KUBE_CONTEXT |
(kosong = current) | kubectl context untuk fetch token |
JX_KUBE_NAMESPACE |
jenkins-x |
Namespace secret |
JX_TOKEN_SECRET |
webhook-trigger-token |
Nama k8s secret berisi token |
GH_CLI |
false (sejak v0.1.22) |
false = jalur native (REST + git). true = fallback ke gh CLI (legacy) |
GITHUB_USER |
(kosong) | Username GitHub. Dipakai bila GH_CLI=false; bila kosong, di-fetch dari /user |
GITHUB_TOKEN |
(kosong) | Personal Access Token — WAJIB bila GH_CLI=false. Scope: repo, read:user, actions:write (untuk --init-secrets) |
DOCKERHUB_USER |
(kosong) | Username DockerHub (persiapan future docker login auto) |
DOCKERHUB_ORG |
(kosong) | Prefix image untuk rollout suggestion (mis. loyaltolpi). Fallback ke REGISTRY_URL bila kosong |
DOCKERHUB_TOKEN |
(kosong) | PAT DockerHub (untuk pemakaian manual) |
GITOPS_REPO |
Qoin-Digital-Indonesia/gitops |
Repo GitOps untuk suggestion gitops-set-image |
GITOPS_BRANCH |
main |
Branch target di repo GitOps |
GITOPS_INFRA |
cce |
cce (Huawei CCE) atau k8s (SLS). Override per-run: --infra |
NS_SUFFIX |
qoin |
Fallback global: ns = <env>-<suffix> bila --ns tidak diberikan dan cicd.PROJECT kosong. Sejak v0.1.22 cicd.PROJECT menang. |
Toggle native (tanpa gh CLI)
Default GH_CLI=true — bq tetap memakai gh CLI persis seperti sebelumnya, tidak ada breaking change. Untuk mengaktifkan jalur native (stdlib urllib + git):
GH_CLI=false
GITHUB_USER=your-login
GITHUB_TOKEN=ghp_xxx
Fitur yang dialihkan: fetch cicd.json, resolve commit SHA, ambil auth token, --gh-auth, --clone, --init-secrets. Untuk --init-secrets di mode native, install extra: pip install pynacl (dibutuhkan enkripsi libsodium sebelum PUT ke API).
Bila
~/.build-q/.envsudah ada dari versi sebelumnya, tambahkan tiga baris di atas secara manual — atau jalankanbq --init --forceuntuk regenerate (perhatikan config lain akan direset ke default).
🚀 Rollout suggestions pasca-build
Sejak v0.1.18, setelah build sukses (atau --dry-run), bq menampilkan dua perintah siap copy-paste yang membungkus tools eksternal set-image (imperative — kubectl set image + rollout status) dan gitops-set-image (declarative — patch YAML di repo GitOps lalu push).
Contoh output:
✅ Build completed successfully.
📤 Rollout suggestions (copy-paste ke terminal):
# 1) Hot-patch cluster (imperative, cepat)
set-image staging-qoin qoinhub-mono-webadmin 76e23f3
# 2) Via GitOps (declarative, ArgoCD sync)
gitops-set-image Qoin-Digital-Indonesia/gitops main \
cce/staging-qoin/qoinhub-mono-webadmin_deployment.yaml \
loyaltolpi/qoinhub-mono-webadmin:76e23f3
ℹ️ ns fallback: staging-qoin — override dengan --ns <name>
Tip: --ns <name> | --infra {cce|k8s} | --gitops-path <path>
Flag override runtime:
| Flag | Default | Keterangan |
|---|---|---|
--ns NAME |
<env>-<NS_SUFFIX> |
Namespace target. env dihitung dari branch (staging→staging, main→staging fallback, tag v*→production) |
--infra {cce,k8s} |
GITOPS_INFRA di .env |
Path template jadi {infra}/{ns}/{app}_deployment.yaml |
--gitops-path PATH |
(auto) | Bypass template — path YAML eksplisit |
Suggestion hanya print, tidak mengeksekusi. Cocok untuk review sebelum apply.
🔎 bq --check — verifikasi kesiapan repo (sejak v0.1.22)
Cek repo remote tanpa clone: apakah artifact CI/CD, image registry, dan file GitOps sudah sesuai ekspektasi.
bq --check ngenwal-be-saasidentityserver4client-manager staging --remote
Output:
🔍 Checking Qoin-Digital-Indonesia/ngenwal-…-manager @ staging
📦 Repository access:
✅ ref 'staging' → e82836bcad4c
🧩 CICD config:
✅ cicd/cicd.json (212 bytes)
• IMAGE = ngenwal-…-manager
• PROJECT = ngenwal
• PORT = 6770
🧱 Init artifacts (jx-init):
✅ Makefile
✅ compose.yaml
✅ Dockerfile
✅ .github/workflows/trigger-ci.yml
📦 Registry:
⚠️ loyaltolpi/ngenwal-…:e82836b — NOT BUILT
🎯 GitOps:
✅ Qoin-Digital-Indonesia/gitops@main:cce/staging-ngenwal/ngenwal-…_deployment.yaml
📊 Summary: 2/2 wajib lulus, 1 warning
Exit code 0 bila semua wajib lulus (repo/ref + cicd config), 1 bila ada yang miss. Warning (missing artifact / image belum ada) tidak menggagalkan.
Bila ditemukan artifact OUTDATED, --check mencetak suggestion bq --pr-fix … di akhir output.
🩹 bq --pr-fix <repo> <ref> — one-shot fix (sejak v0.1.24)
Untuk repo yang init-nya OUTDATED (deteksi via --check), satu perintah menyelesaikan seluruh siklus fix:
bq --pr-fix ngenwal-be-snapconvert-manager master
# Preflight → clone → branch fix/jx-init-<ts> → regenerate 4 file →
# commit → push → set 2 repo secrets → open PR → cleanup
Prasyarat di ~/.build-q/.env:
GH_CLI=false+GITHUB_TOKEN(scope:repo,actions:write,read:user)WEBHOOK_TRIGGER_URL+WEBHOOK_TRIGGER_TOKEN(auto-fetched dari k8s pada preflight bila kosong; disimpan untuk run selanjutnya)- Package
pynacl(untuk enkripsi repo secret):pip install pynacl
Flag override:
| Flag | Default | Keterangan |
|---|---|---|
--pr-branch NAME |
fix/jx-init-<timestamp> |
Nama branch fix eksplisit |
--keep-workdir |
(delete) | Jangan hapus /tmp/bq-pr-fix-… setelah selesai |
--dry-run |
(execute) | Stop sebelum push/set-secret/open-PR. Workdir dipertahankan untuk inspeksi. |
Deduplikasi: bila PR untuk branch fix sudah ada (open), print URL PR eksisting alih-alih buat baru.
Contoh minimal untuk Qoin:
BUILDER_NAME=cloud-loyaltolpi
REGISTRY_URL=loyaltolpi
GITHUB_ORG=Qoin-Digital-Indonesia
WEBHOOK_TRIGGER_URL=https://cicd-hw.qoin.id/trigger
🚀 Panduan Penggunaan
1. Build dari direktori lokal
Auto-detect nama repo & branch dari git:
cd my-service
bq # build + push (default)
bq --no-push # build tanpa push
bq --dry-run # preview command saja
bq my-service staging # eksplisit repo/ref
2. Build dari repo remote tanpa clone
# Dengan GITHUB_ORG di config → shorthand
bq plus-be-paymentlink-manager staging --remote
# Tanpa GITHUB_ORG → sertakan owner
bq Qoin-Digital-Indonesia/plus-be-paymentlink-manager staging --remote
# URL SSH/HTTPS penuh juga OK
bq git@github.com:owner/repo.git v1.0.0 --remote
Catatan
--remote: bilaSSH_AUTH_SOCKtidak tersetel (tidak jalaninssh-agent),bqotomatis fallback ke HTTPS +GIT_AUTH_TOKENsecret (viagh auth token) supaya Buildx Git context tetap bisa jalan tanpa perlu bootstrap ssh-agent.
3. Build dengan clone via gh CLI
bq --clone plus-be-paymentlink-manager staging
bq --clone plus-be-paymentlink-manager staging --clean # hapus folder setelah build
4. Preview command (dry-run)
bq --dry-run
bq plus-be-paymentlink-manager staging --remote --no-image-check --dry-run
5. Paksa rebuild (bypass image check)
bq plus-be-paymentlink-manager staging --remote --rebuild
6. Bootstrap CI/CD service baru (Jenkins X — modern, secret mount)
mkdir my-new-service && cd my-new-service
mkdir cicd && cat > cicd/cicd.json <<EOF
{"IMAGE":"my-new-service","PROJECT":"qoinplus","PORT":"8080"}
EOF
bq --init-jx # scaffold Makefile/compose/Dockerfile/workflow
git init && git remote add origin git@github.com:Qoin-Digital-Indonesia/my-new-service.git
bq --init-secrets # set webhook secrets di GitHub (auto-detect repo)
git add . && git commit -m "chore: bootstrap CI/CD"
git push -u origin main # trigger Jenkins X pipeline via GitHub Actions
7. Bootstrap CI/CD service legacy (Dockerfile pakai ARG GITHUB_USER/TOKEN)
Kalau Dockerfile di repo lama belum bisa dimigrasi ke --mount=type=secret, pakai --init-legacy. Makefile-nya akan auto-ambil gh auth token untuk local dev.
cd my-old-service # Dockerfile-nya masih pakai ARG GITHUB_USER/TOKEN
bq --init-legacy # scaffold Makefile + compose.yaml (Dockerfile TIDAK ditimpa)
gh auth login # sekali saja
make build ENV=staging # token auto-diambil dari `gh auth token`
make release ENV=staging
8. Bootstrap GitHub Actions trigger sebagai satu-satunya workflow
Berguna kalau repo punya banyak workflow lama yang tidak dipakai lagi:
cd existing-repo
bq --gh-action-init # hapus workflow lain + tulis trigger-ci.yml + set webhook secrets
bq --gh-action-init --token xxxx # skip kubectl fetch, pakai token eksplisit
9. Migrasi Dockerfile legacy (ARG-based netrc → secret mount)
cd my-old-service
bq --fix-dockerfile # migrasi ./Dockerfile (backup ke .bak)
bq --fix-dockerfile path/to/Dockerfile
bq --no-push --rebuild # test build hasil migrasi
Yang di-fix otomatis:
FROM x as y→FROM x AS yARG GITHUB_USER/TOKENdihapusRUN echo "machine github.com ..." > ~/.netrc && chmod ... && <cmd>→RUN --mount=type=secret,id=netrc,...- Standalone
RUN echo ... > ~/.netrc→ dihapus, secret mount otomatis nempel diRUN go mod tidy/download/get MAINTAINER foo→LABEL maintainer="foo"ENV KEY value→ENV KEY=value
10. Workaround Dockerfile legacy tanpa migrasi (--gh-auth)
bq plus-be-service staging --remote --rebuild --gh-auth
# → inject GITHUB_USER dari `gh api user` + GITHUB_TOKEN dari `gh auth token`
11. Setup secrets Jenkins X untuk repo existing
cd existing-repo
bq --init-secrets # auto-detect dari git
bq --init-secrets Qoin-Digital-Indonesia/foo-service # eksplisit
bq --init-secrets foo-service --token xxxx # skip kubectl
12. Mode --compose (build via make build && make release)
Untuk repo yang alur build-nya sudah pakai Makefile + docker compose (mis. hasil --init-jx / --init-legacy). ENV= disimpulkan dari ref — lihat tabel Smart env mapping di atas:
# auto-detect: repo & ref dari git di direktori aktif
bq --compose # branch `develop` → ENV=develop
bq --compose my-service staging # ENV=staging
bq --compose my-service v1.2.3 # ENV=production
bq --compose my-service main # ENV=production
bq --compose --dry-run # preview command
# gabung dengan --clone (clone dulu, cd, lalu make build+release)
bq --clone Qoin-Digital-Indonesia/foo staging --compose # ENV=staging
bq --clone Qoin-Digital-Indonesia/foo v1.2.3 --compose # ENV=production
Registry idempotency di --compose: tag yang di-probe mengikuti aturan Makefile — git describe --tags --exact-match || git rev-parse --short HEAD. Jadi kalau HEAD di tag v1.2.3, bq cek registry/image:v1.2.3 (bukan short commit) — sama dengan tag yang di-push make release, sehingga early skip berfungsi benar.
13. Contoh full (customize secret, platform, build-arg)
bq plus-be-service staging \
--secret id=custom,src=/path/to/secret \
--platform linux/amd64 \
--no-push \
--build-arg BRANCH=custom-branch \
--build-arg FEATURE_FLAG=on
🔗 Perintah Lengkap
bq [<repo> [<ref>]] [OPTIONS]
Subcommands (mutually exclusive):
--init Buat ~/.build-q/.env + init Buildx builder
--init --force Recreate config
--config Tampilkan konfigurasi aktif
--init-jx Scaffold Makefile/compose/Dockerfile/workflow (modern secret mount)
--init-jx --force Overwrite file existing
--init-legacy Scaffold Makefile + compose.yaml pola legacy (ARG GITHUB_USER/TOKEN)
--init-legacy --force Overwrite file existing
--gh-action-init Bootstrap standar trigger-ci.yml (hapus workflow lain + set secrets)
--init-secrets [<repo>] Set GitHub Actions webhook secrets
--fix-dockerfile [PATH] Migrasi Dockerfile legacy ke secret mount (+ MAINTAINER/ENV/standalone netrc)
Build modes:
(default) Build dari direktori lokal via docker buildx
--clone <owner/repo> Clone via `gh` CLI, lalu build
--clone ... --clean Hapus folder clone setelah build
--remote Build via Buildx Git context (tanpa clone) — auto-fallback HTTPS bila SSH_AUTH_SOCK kosong
--compose Jalankan `make build ENV=... && make release ENV=...` (bukan buildx)
Build options:
--cicd PATH Path cicd.json (default: cicd/cicd.json)
--context DIR Build context (default: .)
-f, --dockerfile PATH Path Dockerfile (default: Dockerfile)
-t, --tag IMAGE:TAG Override image tag
--push / --no-push Push image (default: push)
--image-check / --rebuild Cek image di registry, skip bila ada (default: on)
--no-image-check Sama dengan --rebuild
--platform PLATFORM Target platform (default: linux/amd64)
--build-arg KEY=VALUE Build arg (dapat diulang)
--secret id=ID,src=PATH Secret build (dapat diulang; netrc otomatis)
--gh-auth Inject GITHUB_USER/TOKEN dari `gh` CLI
--token VALUE Webhook token (dengan --init-secrets / --gh-action-init)
--dry-run Preview command tanpa eksekusi
--version Tampilkan versi
📋 Requirements
- Python 3.7+
- Docker + Buildx plugin
- Git (opsional; wajib untuk auto-detect & mode local)
- GitHub CLI (
gh) — wajib untuk--clone,--remote,--gh-auth,--init-secrets,--gh-action-init - kubectl — opsional; hanya untuk
--init-secrets/--gh-action-init(fetch token otomatis dari cluster)
📄 Template Terpusat (Gist)
Sejak v0.1.14, template scaffolding hidup di gist publik, bukan hard-coded di package:
- URL gist: https://gist.github.com/mamatnurahmat/35cc4c36e7c7c2d236a1b5149cdbcfd9
- Raw base:
https://gist.githubusercontent.com/mamatnurahmat/<gist-id>/raw/<filename> - 6 file:
Makefile.modern,compose.yaml.modern,Dockerfile.modern,Makefile.legacy,compose.yaml.legacy,trigger-ci.yml
Alur load:
load_template(name)
├── 1. cache ~/.build-q/templates/<file> (TTL 3600s, fresh?) ─► pakai
├── 2. fetch dari gist raw URL ─► refresh cache + pakai
├── 3. cache lama (expired) ─► pakai (dengan warning)
└── 4. bundled snapshot di build_q/templates.py ─► pakai (warning)
Cara update template
Update HARUS via gist, jangan edit build_q/templates.py. _BUNDLED_* di file itu hanya snapshot offline-fallback.
# Clone gist untuk edit local
gh gist clone 35cc4c36e7c7c2d236a1b5149cdbcfd9 build-q-templates
cd build-q-templates
# Edit file yang ingin diubah (mis. Makefile.modern)
vim Makefile.modern
# Commit + push (gist adalah git repo — otomatis publish)
git commit -am "fix: adjust Makefile.modern IMAGE_TAG logic"
git push
# Verifikasi raw URL sudah kepakai
curl -s https://gist.githubusercontent.com/mamatnurahmat/35cc4c36e7c7c2d236a1b5149cdbcfd9/raw/Makefile.modern | head
Force refresh cache di sisi user
Kalau user ingin ambil template terbaru sebelum TTL expired:
rm -rf ~/.build-q/templates # hapus cache — next scaffold auto-fetch
# atau override TTL per-invocation:
BUILD_Q_GIST_TTL=0 bq --init-jx
Override gist source (advanced)
Untuk fork/private mirror, override via env vars:
export BUILD_Q_GIST_USER=your-org
export BUILD_Q_GIST_ID=abcd1234...
export BUILD_Q_GIST_TTL=7200 # 2 jam
export BUILD_Q_GIST_TIMEOUT=15 # 15 detik
bq --init-jx
Pipeline Tekton pakai gist yang SAMA (Opsi B strict)
Sejak ~/jenkins-x/pipeline versi terbaru, Tekton pipeline overlay Makefile/compose/Dockerfile dari gist ini SEBELUM make build. Hasilnya BYTE-IDENTICAL dengan bq --init-jx — jadi tidak ada drift antara build lokal bq --compose dan build pipeline JX.
Alur di pipeline (step sync-scaffold di .lighthouse/triggers.yaml):
- Early-skip:
docker manifest inspect— kalau image sudah ada, skip semuanya. - Validate:
cicd/cicd.jsonwajib ada (fail-fast kalau tidak). - Auto-detect mode:
ARG GITHUB_USER/TOKENdi Dockerfile → legacy (Dockerfile tidak di-overlay). Else → modern (semua 3 file di-overlay). - Fetch dari gist raw URL, render placeholder pakai
sed s|{{KEY}}|VALUE|gdengan 7 keys (IMAGE, PROJECT, PORT, CLUSTER, DEPLOYMENT, NODETYPE, ORG_REGISTRY) — sama persis denganrender()dibuild_q/templates.py. make build && make release(fail-fast, tanpa|| echo WARN).
BREAKING: repo yang customize Makefile / compose.yaml / Dockerfile (modern mode) akan di-overlay tiap build. Custom target Makefile HILANG. Kalau perlu kustomisasi, edit di gist saja (semua repo dapat perubahan otomatis).
Sinkronisasi bundled fallback (maintainer only)
Saat rilis bq baru, refresh _BUNDLED_* di build_q/templates.py agar offline user tetap dapat template terkini:
GID=35cc4c36e7c7c2d236a1b5149cdbcfd9
for f in Makefile.modern compose.yaml.modern Dockerfile.modern Makefile.legacy compose.yaml.legacy trigger-ci.yml; do
curl -s "https://gist.githubusercontent.com/mamatnurahmat/$GID/raw/$f" > "/tmp/$f"
done
# lalu paste isi ke masing-masing _BUNDLED_* di build_q/templates.py
🧭 Troubleshooting
| Gejala | Kemungkinan penyebab | Solusi |
|---|---|---|
builder "mybuilder" not found |
Buildx belum di-bootstrap | bq --init |
authentication required saat push |
Belum login registry | docker login (atau docker login <registry>) |
invalid empty ssh agent socket (mode --remote) |
SSH_AUTH_SOCK kosong |
Sudah auto-fallback ke HTTPS + gh auth token. Kalau tetap gagal → gh auth login |
gh: command not found |
GitHub CLI belum ter-install | brew install gh && gh auth login |
--init-secrets gagal fetch token |
Konteks kubectl salah / secret tidak ada | Set JX_KUBE_CONTEXT di ~/.build-q/.env, atau --token xxxx |
| Build sukses tapi image tidak muncul di registry | Salah REGISTRY_URL di config |
bq --config → verifikasi, lalu bq --init --force |
bq --version tidak berubah setelah upgrade |
pipx cache | pipx install --force build-q |
🚀 Development & Release
Ada dua cara rilis: (A) via GitHub Actions otomatis dari tag — direkomendasikan, dan (B) via Makefile lokal — cocok untuk hotfix/debug.
A. Auto-release via GitHub Actions (rekomendasi)
Workflow .github/workflows/pypi-release.yml dipicu oleh push tag v* (atau manual via workflow_dispatch) dan otomatis build + upload ke PyPI.
Flow rilis versi berikutnya:
# 1. Bump versi (patch) — auto-update pyproject.toml + build_q/__init__.py
python3 scripts/bump_version.py # bump patch (0.1.12 → 0.1.13)
# atau versi eksplisit:
python3 scripts/bump_version.py 0.2.0
# 2. Baca versi baru
VER=$(grep -m1 '^version = ' pyproject.toml | sed 's/.*"\(.*\)".*/\1/')
echo "Releasing v$VER"
# 3. Commit bump
git add pyproject.toml build_q/__init__.py
git commit -m "release: v$VER"
# 4. Tag + push (tag inilah yang memicu workflow)
git tag "v$VER"
git push origin main "v$VER"
# 5. Pantau workflow
gh run watch --repo mamatnurahmat/build-q --exit-status
# atau lihat di browser:
gh run list --workflow=pypi-release.yml --repo mamatnurahmat/build-q --limit 3
Setelah workflow selesai (± 15 detik), package tersedia di:
- https://pypi.org/project/build-q//
- Upgrade user:
pipx upgrade build-q
Apa yang dilakukan workflow (lihat .github/workflows/pypi-release.yml):
- Checkout repo pada commit tag.
- Setup Python 3.12.
- Verifikasi tag — pastikan
v<X>cocok dengan version dipyproject.tomldanbuild_q/__init__.py. Bila mismatch, gagal (mencegah rilis "kosong"). - Install
build+twine. - Build sdist + wheel via
python -m build. - Validate dengan
twine check dist/*. - Upload via
twine upload --skip-existing— kalau versi sudah ada di PyPI, aman skip (idempoten). - Summary dengan link PyPI.
Autentikasi: workflow pakai GitHub Actions secret PYPI_API_TOKEN (username __token__). Token PyPI project-scoped ini di-set sekali via gh secret set. Cara set/rotate token:
# Metode andal — pakai env-file (JANGAN pakai --body - karena pipe stdin
# rawan corrupt untuk token panjang).
TMPFILE=$(mktemp) && chmod 600 "$TMPFILE"
python3 -c "
import configparser, os
c = configparser.ConfigParser()
c.read(os.path.expanduser('~/.pypirc'))
print('PYPI_API_TOKEN=' + c['pypi']['password'])
" > "$TMPFILE"
gh secret set -f "$TMPFILE" --repo mamatnurahmat/build-q
rm -f "$TMPFILE"
# Verifikasi:
gh secret list --repo mamatnurahmat/build-q
Manual trigger tanpa tag (misal untuk re-upload versi yang sudah ada di pyproject.toml — --skip-existing akan handle):
gh workflow run pypi-release.yml --repo mamatnurahmat/build-q
Cek/re-run workflow yang gagal:
gh run list --workflow=pypi-release.yml --repo mamatnurahmat/build-q --limit 5
gh run view <RUN_ID> --repo mamatnurahmat/build-q --log-failed
gh run rerun <RUN_ID> --failed --repo mamatnurahmat/build-q
B. Release manual via Makefile (lokal)
Cocok untuk hotfix cepat / troubleshoot. Baca kredensial dari ~/.pypirc lokal.
make build # build sdist + wheel ke dist/
make install # install lokal (pipx editable)
make release # bump patch, build, install, upload ke PyPI
make release V=1.0.0 # release versi spesifik
make clean # bersihkan artefak
Langkah make release:
scripts/bump_version.pybump patch dipyproject.toml+build_q/__init__.py.- Build sdist + wheel via
python3 -m build(fallback:pipx run --spec build pyproject-build). - Install lokal editable via
pipx install -e . --force. - Upload ke PyPI via
pipx run twine upload --skip-existing dist/*— kredensial dari~/.pypirc.
⚠️ Setelah
make release, jangan lupa commit + tag + push supaya history Git & GitHub Actions selaras dengan PyPI:VER=$(grep -m1 '^version = ' pyproject.toml | sed 's/.*"\(.*\)".*/\1/') git add pyproject.toml build_q/__init__.py git commit -m "release: v$VER" git tag "v$VER" && git push origin main "v$VER"Tag push tetap akan memicu workflow, tapi karena
--skip-existing, upload akan skip (idempoten).
Release troubleshooting
| Gejala | Penyebab | Solusi |
|---|---|---|
| Workflow gagal di step Verify tag matches | Tag v0.1.13 tapi pyproject.toml masih 0.1.12 |
Jalankan python3 scripts/bump_version.py 0.1.13 dulu, commit, re-tag |
Workflow gagal 403 Forbidden di upload |
Secret PYPI_API_TOKEN corrupt / kadaluwarsa |
Re-set secret via metode env-file di atas |
PyPI 400 File already exists |
Versi sudah pernah di-upload dari lokal | Sudah di-handle --skip-existing — workflow tetap hijau |
| Version di PyPI tidak berubah setelah tag | Tag lama di-hapus & re-push versi sama | PyPI TIDAK menerima re-upload versi yang sama — bump patch dulu |
📄 License
MIT
Release files for build-q 0.1.24
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| build_q-0.1.24.tar.gz | 68.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| build_q-0.1.24-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 120.4 kB
Release files / build_q-0.1.24.tar.gz
| Download URL | build_q-0.1.24.tar.gz |
|---|---|
| Size | 68.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c393ed68b0ab924dacfc3edc1a426d04f6e4e1c6e6fee83920a35ddac61dc11f
|
|
BLAKE2b-256 checksum How to use checksums |
9fb7bce8c2b511fac286dbc3d794eebd2a7978b1b588d9cf5021cfd8d1df62a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / build_q-0.1.24-py3-none-any.whl
| Download URL | build_q-0.1.24-py3-none-any.whl |
|---|---|
| Size | 52.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c4bd5ed9dab7f1edb89d2df63a240b19ec97450fae8d38ec90bb196ba8a00259
|
|
BLAKE2b-256 checksum How to use checksums |
9588e44e8594069c91813f2ce2eac99cd2cf7838838bcbba9dd559776826129a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|