Reusable Workflow vs Composite Action di GitHub Actions

Foto oleh RICHI Manufacture via Wikimedia Commons (CC BY 4.0)
Composite action membungkus urutan langkah yang menyisip ke sebuah job yang tetap dikendalikan pemanggil, dan ia berjalan di runner pemanggil. Reusable workflow membungkus satu atau lebih job utuh, mendefinisikan runner-nya sendiri, dan dipanggil di tingkat job alih-alih sebagai langkah. Singkatnya, composite action berbagi langkah dan reusable workflow berbagi job.
Tidak secara langsung. Composite action tidak punya blok secrets dan tidak bisa membaca konteks secrets sendiri. Untuk memakai secret Anda harus mengirim nilainya sebagai input biasa dari langkah pemanggil. Jika logika bersama Anda sangat bergantung pada secret, itu sinyal kuat untuk memakai reusable workflow.
Gunakan secrets: inherit pada job pemanggil alih-alih mendaftar setiap secret. Ini menyerahkan semua secret workflow pemanggil ke workflow yang dipanggil. Ini hanya bekerja ketika pemanggil dan reusable workflow berada di organisasi atau enterprise yang sama.
Taruh composite action dan reusable workflow Anda di satu repositori terpusat, sering dinamai ci-templates, dan rujuk dari setiap repo lain. Sematkan rujukan ke tag atau SHA commit penuh alih-alih branch yang bergerak agar perubahan tidak diam-diam merusak setiap pipeline hilir. Publikasikan versi baru di balik tag seperti v1 dan v2 agar pemakai memutakhirkan dengan sengaja.
Setiap langkah run di dalam composite action harus mendeklarasikan shell-nya sendiri, seperti shell: bash. Berbeda dari langkah workflow biasa, shell tidak diwarisi dari pemanggil. Melupakannya adalah alasan paling umum composite action gagal dimuat dengan galat validasi yang membingungkan.

Foto oleh RICHI Manufacture via Wikimedia Commons (CC BY 4.0)
Ringkasan Utama
Gunakan composite action untuk berbagi urutan langkah di dalam satu job, seperti awalan checkout-dan-setup yang berjalan di runner pemanggil. Gunakan reusable workflow untuk berbagi satu atau lebih job utuh, mengatur runner, menjaga environment, dan menerima secret. Composite action menyisip ke dalam job; reusable workflow dipanggil sebagai sebuah job.
Setiap tim yang menjalankan CI di lebih dari segelintir repositori menabrak tembok yang sama: empat puluh baris checkout, setup bahasa, restore cache, lint, dan test yang sama disalin-tempel ke setiap file workflow. Ketika versi Node naik atau cache key berubah, Anda menyuntingnya di dua belas tempat dan melewatkan dua. GitHub Actions memberi Anda dua alat untuk membunuh duplikasi itu, dan keduanya terus tertukar karena sama-sama disebut reuse. Keduanya tidak dapat saling menggantikan.
Perbedaannya lebih sederhana daripada yang dibuat kebanyakan artikel. Composite action membungkus langkah. Reusable workflow membungkus job. Begitu itu dipahami, hampir setiap keputusan mengikuti secara otomatis, termasuk ke mana secret bisa mengalir dan runner mana yang menjalankan kode Anda. Saya menjalankan CI di beberapa layanan kecil pada VPS swakelola, dan menetapkan pembagian ini dengan benar itulah yang menjaga logika deploy saya tetap di satu file alih-alih tersebar di setiap repo.
Composite action dirujuk dari dalam daftar steps sebuah job dengan sintaks uses yang sama yang sudah Anda pakai untuk action pihak ketiga. Ia tidak bisa mendefinisikan runner-nya sendiri, tidak bisa memuat job, dan langkah internalnya menyusut menjadi satu baris di log. Ia berjalan di mesin mana pun yang dipilih job pemanggil. Reusable workflow sebaliknya: ia dirujuk di tingkat job, mendefinisikan runner-nya sendiri dengan runs-on, bisa memuat beberapa job, dan setiap langkah tercatat secara real time. Perbedaan ketinggian itu menggerakkan segala hal lainnya.
| Dimensi | Composite action | Reusable workflow |
|---|---|---|
| Unit reuse | Urutan langkah | Satu atau lebih job utuh |
| Cara pemanggilan | Sebagai langkah (uses di dalam steps) | Di tingkat job (uses pada job) |
| Kontrol runner | Berjalan di runner pemanggil | Mendefinisikan runs-on sendiri |
| Secret | Tidak ada blok secrets; kirim nilai sebagai input | Secret native plus secrets inherit |
| Logging | Menyusut jadi satu langkah | Setiap langkah tercatat terpisah |
| Marketplace | Bisa dipublikasikan ke Marketplace | Tidak bisa dipublikasikan; dirujuk lewat path |
Pilih composite action ketika beberapa workflow butuh awalan yang sama tetapi masing-masing berlanjut berbeda sesudahnya. Kasus klasiknya adalah checkout, menyiapkan runtime bahasa, dan me-restore cache dependensi. Job test Anda menambah langkah test setelahnya, job build menambah langkah build, dan job release menambah langkah pengemasan. Composite action membiarkan tiap job memegang kendali penuh atas apa yang datang berikutnya sambil berbagi setup yang membosankan. Anda juga bisa menumpuk beberapa composite action dan langkah inline dalam job yang sama dalam urutan apa pun, yang tidak bisa dilakukan reusable workflow.
# .github/actions/setup-node-app/action.yml
name: "Setup Node app"
description: "Checkout, install Node, restore cache, install deps"
inputs:
node-version:
description: "Node version to install"
required: false
default: "20"
runs:
using: "composite"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: "npm"
- run: npm ci
shell: bash # required on every run step in a composite action# a workflow in the same repo consuming the composite action
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: ./.github/actions/setup-node-app
with:
node-version: "22"
- run: npm test # this job keeps control after setupSetiap langkah run di dalam composite action harus mendeklarasikan shell-nya sendiri (misalnya shell: bash). Ia tidak diwarisi dari pemanggil, dan melupakannya adalah alasan paling umum sebuah composite action gagal dimuat dengan galat validasi yang membingungkan.
Pilih reusable workflow ketika Anda ingin membakukan seluruh pipeline, bukan sekadar awalan. Tim platform memiliki pemilihan runner, gerbang environment, graf job, dan kontrak secret; tim pemakai cukup memanggilnya dan mengirim parameter. Ini alat yang tepat ketika logika bersama harus berjalan di runner tertentu terlepas dari pemanggil, ketika ia perlu memakai secret, atau ketika eksekusi bergantung pada kondisi if yang dievaluasi di tingkat job. Pipeline deploy saya ada di sini: satu reusable workflow mendefinisikan build, push ke registry, dan deploy SSH, dan setiap repo layanan memanggilnya dengan input environment yang berbeda.
# .github/workflows/deploy.yml in the org/ci-templates repo
on:
workflow_call:
inputs:
environment:
required: true
type: string
secrets:
SSH_KEY:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh
env:
SSH_KEY: ${{ secrets.SSH_KEY }}Input bertipe dan berperilaku sama untuk keduanya: Anda mendeklarasikannya dan mengirimnya dengan kata kunci with. Secret adalah tempat keduanya berbeda tajam. Reusable workflow punya blok secrets kelas satu di trigger workflow_call-nya, dan pemanggil boleh mengirim setiap secret secara eksplisit atau memakai secrets inherit untuk menyerahkan semua secret workflow pemanggil sekaligus. Inherit hanya bekerja ketika pemanggil dan workflow yang dipanggil berada di organisasi atau enterprise yang sama.
# the caller: reusable workflow is invoked as the job itself
jobs:
call-deploy:
uses: my-org/ci-templates/.github/workflows/deploy.yml@v1
with:
environment: production
secrets: inherit # hands over all caller secrets at onceComposite action tidak punya blok secrets dan tidak bisa membaca konteks secrets sendiri. Untuk memakai secret di dalamnya Anda harus mengirim nilainya sebagai input biasa dari langkah pemanggil. GitHub tetap menyamarkan nilai secret terdaftar di log, tetapi Anda kehilangan kontrak secret bertipe, jadi anggap logika yang penuh secret sebagai sinyal bahwa Anda ingin reusable workflow, bukan composite action.
Untuk reuse antar repo, taruh kedua artefak di satu repositori terpusat, biasa dinamai seperti ci-templates, dan rujuk dari setiap repo lain. Sematkan rujukan Anda ke tag atau SHA commit penuh, jangan pernah ke branch yang bergerak, agar perubahan pada logika bersama tidak diam-diam merusak setiap pipeline hilir sekaligus. Luncurkan versi baru maju dengan tag seperti v1, v2 dan biarkan pemakai memutakhirkan dengan sengaja. Sadari batas platform saat Anda menyusunnya: satu workflow hanya bisa merujuk sejumlah terbatas reusable workflow, dan nesting punya kedalaman maksimum, jadi jaga rantai tetap dangkal dan datar alih-alih membangun menara dalam berisi workflow memanggil workflow.
Hibrida praktis bekerja paling baik dalam skala besar: simpan logika setup kecil dan generik sebagai composite action agar job mana pun bisa menyusunnya, dan simpan seluruh pipeline baku sebagai reusable workflow. Reusable workflow itu sendiri bisa memakai composite action Anda secara internal, memberi Anda satu tempat untuk reuse tingkat langkah dan satu tempat untuk reuse tingkat job.
Keduanya saling melengkapi, bukan bersaing. Tim dengan CI paling rapi yang pernah saya lihat memakai keduanya dengan sengaja: composite action untuk awalan langkah yang dapat dipakai ulang dan reusable workflow untuk pipeline baku yang memakainya. Tetapkan perbedaan langkah-versus-job dengan benar dan sisanya hanyalah menyambung input dan, dengan hati-hati, secret.