Duplikasi konfigurasi CI/CD di banyak repositori menimbulkan masalah pemeliharaan: perubahan kecil pada tahap linting, testing, atau deployment mengharuskan pembaruan file konfigurasi secara manual di puluhan tempat. GitHub Actions menyediakan Reusable Workflows (melalui trigger workflow_call) untuk mendistribusikan satu definisi pipeline standar ke seluruh repositori dalam organisasi.
Reusable Workflows vs Composite Actions
GitHub Actions menawarkan dua mekanisme modularisasi: Reusable Workflows dan Composite Actions. Pemilihan fitur ini harus disesuaikan dengan kebutuhan abstraksi dan lingkup eksekusi pipeline.
- Reusable Workflows (
workflow_call): Mengabstraksi seluruh job atau multiple jobs. Fitur ini mendukung isolasi runner berbeda untuk tiap job, deployment environments, secret management tingkat job, integrasi matrix build, dan konkurensi native. - Composite Actions: Mengabstraksi kumpulan steps di dalam satu job yang sama. Seluruh step berjalan pada runner yang sama, berbagi disk, dan tidak dapat memisahkan job dependency atau mendefinisikan matrix lintas step secara independen.
Gunakan Reusable Workflows ketika Anda ingin mendefinisikan end-to-end pipeline standar organisasi (misal: build, security scan, lalu deploy). Gunakan Composite Actions jika Anda hanya ingin mengemas urutan command pendek yang dapat dipakai ulang di dalam satu step eksekusi (misal: setup runtime dan cache dependency).
Implementasi: Target (Called) Workflow
Target workflow diletakkan pada repositori terpusat (contoh: acme-corp/shared-workflows). File ditempatkan di direktori .github/workflows/. Target workflow menggunakan trigger workflow_call, mendefinisikan inputs, secrets, dan outputs.
# File: .github/workflows/node-build-test.yml pada repositori shared-workflows
name: Reusable Node CI
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: '20'
run-linter:
required: false
type: boolean
default: true
secrets:
NPM_TOKEN:
required: false
SONAR_TOKEN:
required: true
outputs:
build-artifact-name:
description: "Nama artifact hasil build"
value: ${{ jobs.build.outputs.artifact-name }}
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- name: Install dependencies
run: npm ci
- name: Run ESLint
if: ${{ inputs.run-linter }}
run: npm run lint
- name: Run Test Suite
run: npm test
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
build:
needs: lint-and-test
runs-on: ubuntu-latest
outputs:
artifact-name: ${{ steps.export-name.outputs.name }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- name: Build Application
run: npm run build
- name: Export Artifact Identifier
id: export-name
run: echo "name=build-${{ github.sha }}" >> $GITHUB_OUTPUT
Implementasi: Caller Workflow
Repositori aplikasi downstream memanggil workflow terpusat menggunakan sintaks uses: {owner}/{repo}/.github/workflows/{filename}@{ref}. Nilai ref dapat berupa branch, commit SHA, atau Git release tag.
# File: .github/workflows/ci.yml pada repositori downstream (misal: frontend-app)
name: Application CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
run-shared-pipeline:
uses: acme-corp/shared-workflows/.github/workflows/[email protected]
with:
node-version: '20'
run-linter: true
secrets:
SONAR_TOKEN: ${{ secrets.DOWNSTREAM_SONAR_TOKEN }}
NPM_TOKEN: ${{ secrets.DOWNSTREAM_NPM_TOKEN }}
notify:
needs: run-shared-pipeline
runs-on: ubuntu-latest
steps:
- name: Log artifact name from shared workflow
run: |
echo "Build output: ${{ needs.run-shared-pipeline.outputs.build-artifact-name }}"
Manajemen Secrets: Explicit vs Inherit
Terdapat dua cara mendistribusikan credentials dari caller ke reusable workflow:
1. Explicit Secret Passing
Secret dipetakan satu per satu via blok secrets: pada caller workflow. Pendekatan ini mengikuti prinsip least privilege, karena workflow target hanya memiliki akses terhadap variabel yang secara eksplisit dideklarasikan.
2. Secret Inheritance (secrets: inherit)
Caller meneruskan semua organization dan repository secrets langsung ke target workflow menggunakan sintaks:
jobs:
call-pipeline:
uses: acme-corp/shared-workflows/.github/workflows/node-build-test.yml@v1
secrets: inherit
Peringatan Keamanan: Penggunaan secrets: inherit mengizinkan reusable workflow mengakses seluruh secrets yang terlihat oleh caller repository. Jika repositori workflow terpusat dikelola oleh tim berbeda atau mengonsumsi reusable actions dari pihak ketiga, pastikan review integritas kode diperketat guna mencegah eksfiltrasi secret.Strategi Semantic Versioning untuk Mencegah Breaking Change
Pembaruan pada repositori reusable workflow tidak boleh merusak (break) pipeline downstream yang sedang berjalan. Terapkan konvensi Semantic Versioning (vMAJOR.MINOR.PATCH) dengan mekanisme Git tags:
- Major Pinning (
@v1): Caller mereferensikan major tag. Tim platform memperbarui tagv1secara otomatis (memindahkan pointer git tag) setiap kali ada release versi patch (v1.0.1) atau minor non-breaking (v1.1.0). Caller mendapatkan fitur dan bugfix tanpa intervensi. - Exact Tag Pinning (
@v1.2.0): Direkomendasikan untuk aplikasi dengan regulasi ketat atau pipeline deployment produksi yang memerlukan determinisme penuh. - Commit SHA Pinning (
@hash): Cara paling aman untuk mitigasi serangan supply-chain, namun memerlukan otomasi seperti Dependabot atau Renovate untuk pembaruan berkala.
Aturan Depresiasi Parameter
Ketika menambahkan atau mengubah parameter pada target workflow:
- Jangan mengubah input yang sudah ada menjadi
required: truedalam major release yang sama. - Jika parameter lama diganti, pertahankan parameter lama dengan status opsional dan fallback nilai ke parameter baru selama masa transisi.
- Naikkan versi ke major berikutnya (misal:
v2.0.0) jika terjadi perubahan struktur output atau penghapusan input lama.
Aksesibilitas Repositori dan Batasan Teknis
- Tingkat Akses Repositori: Agar repositori privat downstream dapat mengakses target workflow, repositori
shared-workflowsharus diatur sebagai Internal (jika menggunakan GitHub Enterprise) atau berada dalam organisasi yang sama dengan permission Action access diubah ke: "Accessible from repositories in the 'acme-corp' organization" pada menu Settings > Actions > General. - Nesting Limit: Reusable workflow dapat memanggil reusable workflow lain hingga kedalaman maksimum 4 tingkat. Pemanggilan melingkar (circular dependency) akan ditolak oleh parser GitHub Actions saat kompilasi pipeline.
- Environment Variables: Variabel level workflow (
env:di root caller) tidak diwariskan ke reusable workflow. Nilai harus dilewatkan secara eksplisit viainputs.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!