6
Build dan Rilis
Makefile di akar repository adalah satu-satunya pintu masuk build. Dari berkas itu lahir dua jenis artefak: paket Python yang diunggah ke PyPI dan image Docker yang diunggah ke DockerHub. Keduanya berbagi satu sumber versi, berkas VERSION, dan satu set variabel yang dihitung di awal Makefile. Rilis otomatis berjalan lewat dua workflow GitHub Actions yang terpisah: .github/workflows/publish.yaml untuk mempublikasikan image, dan .github/workflows/codeql.yaml untuk analisis kode statis. Makefile:1-14
Sumber versi tunggal
Seluruh nilai di Makefile diturunkan dari satu berkas kecil. Baris VERSION := $(shell cat VERSION | tr -d '\n') membaca isi VERSION tanpa newline, dan berkas itu hanya berisi satu baris, v2.6.3. VERSION:1-1 Dari nilai tersebut, PACKAGE dibentuk dengan cut -c 2- sehingga nama arsip menjadi apkleaks-2.6.3, sementara IMAGE bernilai dwisiswant0/apkleaks. Makefile:1-14
| Variabel | Nilai pada commit ini | Dipakai oleh |
|---|---|---|
AUTHOR | dwisiswant0 | IMAGE |
APP | apkleaks | IMAGE, PACKAGE |
IMAGE | dwisiswant0/apkleaks | build-images, upload-images, clean |
VERSION | v2.6.3 (dari VERSION) | tag image, docker push |
PACKAGE | apkleaks-2.6.3 | check-package, upload-package |
PYTHON | python3, atau venv/bin/python3 bila direktori venv/ ada | semua target Python |
⚠️
cut -c 2-membuang satu karakter tanpa memeriksa isinya. Baris pertamaVERSIONharus diawaliv, karena bila tidak,PACKAGEkehilangan digit pertama versi dan poladist/$(PACKAGE)*yang dibacacheck-packagesertaupload-packagetidak akan menemukan arsip hasil build. Makefile:1-14
Makefile juga memilih interpreter secara otomatis. Bila direktori venv/ sudah ada, PYTHON diubah menjadi venv/bin/python3; bila belum, python3 sistem yang dipakai. Target setup-venv mengikat venv sebagai prasyarat, lalu menimpa PYTHON khusus untuk target setup di dalamnya. Makefile:16-25
Alur target make
Rantai target bercabang dua setelah setup: satu cabang menuju dist/ untuk paket Python, cabang lain menuju tag image Docker. Target agregat build-all dan upload-all hanya menggabungkan kedua cabang tersebut. Makefile:38-50
graph LR
VF["VERSION"] --> VAR["VERSION dan PACKAGE"]
VF --> BP
ST["setup"] --> BP["build-package"]
BP --> DIST["dist/apkleaks-2.6.3"]
DIST --> CP["check-package"]
CP --> UP["upload-package"]
UP --> PYPI["PyPI"]
ST --> BI["build-images"]
BI --> IMG["apkleaks:latest + apkleaks:v2.6.3"]
IMG --> UI["upload-images"]
UI --> HUB["DockerHub"]
style VAR fill:#f59e0b,color:#000
style ST fill:#f59e0b,color:#000
style CP fill:#f59e0b,color:#000
style DIST fill:#8b5cf6,color:#fff
style IMG fill:#8b5cf6,color:#fff
style BP fill:#2d7d46,color:#fff
style UP fill:#2d7d46,color:#fff
style BI fill:#2d7d46,color:#fff
style UI fill:#2d7d46,color:#fff
style PYPI fill:#336791,color:#fff
style HUB fill:#336791,color:#fff
%% fig: Rantai target make dari setup ke dua artefak
%% desc: Setiap cabang berawal dari satu versi di VERSION; cabang paket berakhir di PyPI lewat dist/, sedangkan cabang image berakhir di DockerHub.Perintah tiap target dapat dibaca langsung dari Makefile. build-package menjalankan $(PYTHON) -m build, check-package menjalankan twine check dist/$(PACKAGE)*, dan upload-package menjalankan twine upload dist/$(PACKAGE)*; karena itu setup memasang build dan twine di samping requirements.txt. Makefile:27-34 build-images melakukan docker build -t $(IMAGE):latest . lalu memberi tag kedua dengan $(VERSION), sedangkan upload-images mendorong kedua tag tersebut. Makefile:38-50
| Target | Perintah yang dijalankan | Hasil |
|---|---|---|
venv | python3 -m venv venv | direktori venv/ |
setup | pip install -r requirements.txt, lalu pip install build twine | dependensi build dan unggah |
setup-venv | prasyarat venv, lalu setup dengan PYTHON venv | dependensi di dalam venv |
build-package | python -m build | arsip di dist/ |
check-package | twine check dist/$(PACKAGE)* | validasi metadata arsip |
upload-package | twine upload dist/$(PACKAGE)* | rilis PyPI |
pypi | prasyarat check-package, build-package | rilis PyPI |
build-images | docker build -t dwisiswant0/apkleaks:latest ., lalu docker tag ke :v2.6.3 | dua tag image lokal |
upload-images | docker push tag latest dan v2.6.3 | image di DockerHub |
docker | prasyarat build-images | alias build image |
build-all | prasyarat build-package, build-images | paket dan image |
upload-all | prasyarat upload-package, upload-images | rilis PyPI dan DockerHub |
clean | rm -rfv dist/ venv/, lalu docker image rm -f dwisiswant0/apkleaks | artefak lokal dihapus |
⚠️ Target
pypidideklarasikan sebagaipypi: check-package build-package, sehinggacheck-packagelebih dulu daripadabuild-package, padahalcheck-packagemembacadist/$(PACKAGE)*. Pada kondisidist/kosong, prasyarat pertama itu gagal sebelum arsip sempat dibuat. Makefile:36-36
⚠️
cleanbersifat destruktif:rm -rfv dist/ venv/menghapus seluruh arsip build dan virtualenv, laludocker image rm -f dwisiswant0/apkleaksmenghapus image lokal tanpa konfirmasi. Setelahclean,PYTHONkembali kepython3sistem karena direktorivenv/sudah tidak ada. Makefile:52-54
Versi dinamis pada paket Python
pyproject.toml tidak menulis nomor versi secara literal. Berkas itu menandai dynamic = ["dependencies", "version"], lalu [tool.setuptools.dynamic] memetakan version ke berkas VERSION dan dependencies ke berkas requirements.txt. pyproject.toml:141 pyproject.toml:22-242 Dengan begitu, python -m build di target build-package menghasilkan arsip yang nomornya selalu mengikuti satu baris di VERSION.
Backend build adalah setuptools.build_meta dengan requires = ["setuptools>=68"], dan berkas yang didaftarkan sebagai paket adalah apkleaks* serta config*, dengan package-data "*" = ["*.json"] agar berkas pola JSON ikut masuk ke arsip. pyproject.toml:26-303 pyproject.toml:32-344 Entry point CLI apkleaks = "apkleaks.cli:main" juga didefinisikan di sini, sehingga paket hasil build memasang perintah apkleaks. pyproject.toml:16-175
Nomor versi dibaca kembali saat runtime, bukan saat build: fungsi header() mencoba importlib.metadata, lalu pkg_resources, dan akhirnya membaca berkas VERSION di direktori induk cli.py sebagai upaya terakhir. apkleaks/cli.py:10-196
Image Docker
Target build-images memakai Dockerfile di akar repository sebagai build context. Image berjalan di atas python:3-slim, memasang requirements.txt, menyalin seluruh isi repository ke /app, dan memakai ENTRYPOINT ["python", "/app/apkleaks.py"] sehingga container memanggil skrip utama, bukan perintah apkleaks hasil instalasi paket. Dockerfile:18-25
| Sumber tag | Tag yang dihasilkan |
|---|---|
make build-images | dwisiswant0/apkleaks:latest dan dwisiswant0/apkleaks:v2.6.3 |
publish.yaml lewat docker/metadata-action | {{version}}, {{major}}.{{minor}}, {{major}}, tag sha, dan tag schedule |
⚠️
publish.yamlmengirimbuild-argsberisiVERSION=${{ env.VERSION }}ke build image, tetapiDockerfiletidak mendeklarasikanARG VERSIONdan tidak memakainya di perintah mana pun. Nilai itu tidak berpengaruh pada isi image. .github/workflows/publish.yaml:43-497
Workflow publish.yaml
Workflow ini dipicu oleh push pada tag yang cocok dengan pola v*, atau dijalankan manual lewat workflow_dispatch dengan input tag yang wajib diisi. .github/workflows/publish.yaml:1-118 Nilai versi disatukan di variabel env.VERSION: input tag bila dipicu manual, atau github.ref_name bila dipicu tag. Langkah actions/checkout@v4 memakai fetch-depth: 0 dan ref yang diisi env.VERSION. .github/workflows/publish.yaml:13-239
graph LR
TAG["push tag v*"] --> VER["env VERSION"]
DISPATCH["workflow_dispatch input tag"] --> VER
VER --> CO["actions/checkout@v4 ref = VERSION"]
CO --> META["docker/metadata-action@v5"]
META --> BPUSH["docker/build-push-action@v6"]
LOGIN["docker/login-action@v3"] --> BPUSH
BPUSH --> HUB["DockerHub github.repository"]
style TAG fill:#2d7d46,color:#fff
style DISPATCH fill:#2d7d46,color:#fff
style BPUSH fill:#2d7d46,color:#fff
style VER fill:#f59e0b,color:#000
style LOGIN fill:#f59e0b,color:#000
style META fill:#8b5cf6,color:#fff
style CO fill:#8b5cf6,color:#fff
style HUB fill:#336791,color:#fff
%% fig: Alur workflow publish dari tag ke DockerHub
%% desc: Tag atau input manual menjadi env VERSION, checkout memakai nilai itu, metadata menghitung daftar tag, lalu build-push-action mendorong image yang sudah login.Daftar tag dihitung oleh docker/metadata-action@v5 dari env.VERSION: type=semver,pattern={{version}} dengan match=v(\d.\d.\d), lalu {{major}}.{{minor}}, {{major}}, ditambah type=sha dan type=schedule. Pola match itu memakai . sebagai wildcard, bukan literal titik, sehingga tag seperti v2x6x3 pun lolos. .github/workflows/publish.yaml:25-3410
Sebelum push, workflow menyiapkan docker/setup-qemu-action@v3 dan docker/setup-buildx-action@v3, lalu login memakai secrets.DOCKER_USERNAME dan secrets.DOCKER_TOKEN. .github/workflows/publish.yaml:36-4111 Langkah terakhir docker/build-push-action@v6 memakai push: true dengan tags dan labels dari keluaran steps.meta. .github/workflows/publish.yaml:43-497
⚠️ Rilis image bergantung pada dua secret repository,
DOCKER_USERNAMEdanDOCKER_TOKEN. Tanpa keduanya, langkah login gagal dan tidak ada tag yang terdorong walau trigger tagv*sudah terpenuhi. .github/workflows/publish.yaml:36-4111
Workflow codeql.yaml
Workflow ini murni analisis dan tidak menyentuh artefak rilis. Pemicunya adalah push ke master, pull_request ke master dan dev, serta jadwal cron: "26 16 * * 0". .github/workflows/codeql.yaml:1-1212 Pekerjaan analyze berjalan di ubuntu-latest dengan fail-fast: false dan matrix bahasa tunggal python, memakai actions/checkout@v2 lalu github/codeql-action versi @v1 untuk init, autobuild, dan analyze. .github/workflows/codeql.yaml:14-3213
⚠️ Karena pemicunya hanya
master,dev, dan jadwal mingguan, tagv*tidak menjalankan CodeQL.publish.yamljuga tidak mendeklarasikanneedske pekerjaananalyze, jadi kedua workflow berdiri sendiri dan hasil analisis tidak pernah menahan rilis. .github/workflows/codeql.yaml:14-3213
Perbedaan urutan antara kedua jalur rilis perlu diingat saat melepas versi baru. make upload-all menjalankan upload-package lalu upload-images secara berurutan, sedangkan jalur GitHub Actions hanya membangun image. Untuk rilis PyPI, python -m twine upload atau target upload-package tetap harus dijalankan manual dari mesin yang punya kredensial. .github/workflows/publish.yaml:1-118