Copy-pasted YAML is hard to maintain. In this lesson you will create reusable workflows that other pipelines call as jobs, build a composite action for shared setup steps, and learn how to use third-party actions safely.
📖 What You’ll Learn: reusable workflows vs composite actions, defining workflow_call with inputs, secrets and outputs, calling workflows from the same and other repositories, composite actions and their rules, JavaScript and Docker actions, and safe use of third-party actions.
♻️ Why Reuse?
As repositories multiply, the same YAML gets copied everywhere: checkout, set up Node, install, run tests, upload the report. Copies drift apart and every fix must be made ten times. GitHub Actions has two ways to reuse:
| Reusable workflow | Composite action | |
|---|---|---|
| Reuses | Whole jobs (one or more) | Steps inside a job |
| Defined with | on: workflow_call in .github/workflows/ | action.yml with runs.using: composite |
| Called with | jobs.<id>.uses: | steps[*].uses: |
| Can choose its own runner | ✅ | ❌ (runs in the caller’s job) |
| Can use secrets directly | Passed in by the caller | Via inputs only |
| Best for | Standard pipelines (test, deploy) | Small shared step sequences (setup, notify) |
📄 Reusable Workflows
1. Define the reusable workflow
# .github/workflows/playwright-tests.yml
name: Playwright tests (reusable)
on:
workflow_call:
inputs:
project:
type: string
default: chromium
base-url:
type: string
required: true
secrets:
TEST_PASSWORD:
required: true
outputs:
result:
description: Test result
value: ${{ jobs.e2e.outputs.result }}
jobs:
e2e:
runs-on: ubuntu-latest
outputs:
result: ${{ steps.run.outcome }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: npm
- run: npm ci
- run: npx playwright install --with-deps ${{ inputs.project }}
- id: run
run: npx playwright test --project=${{ inputs.project }}
env:
BASE_URL: ${{ inputs.base-url }}
TEST_PASSWORD: ${{ secrets.TEST_PASSWORD }}
2. Call it
# .github/workflows/ci.yml
name: CI
on: [ pull_request ]
jobs:
chromium:
uses: ./.github/workflows/playwright-tests.yml # same repository
with:
project: chromium
base-url: https://staging.example.com
secrets:
TEST_PASSWORD: ${{ secrets.TEST_PASSWORD }}
firefox:
uses: acme/ci-templates/.github/workflows/playwright-tests.yml@v1 # another repository
with:
project: firefox
base-url: https://staging.example.com
secrets: inherit # pass all of the caller's secrets
| Rule | Detail |
|---|---|
| Reference | ./.github/workflows/file.yml (same repo) or owner/repo/.github/workflows/file.yml@ref |
| Version | Pin @ref to a tag (@v1) or commit SHA for stability |
| Inputs | Typed: string, number, boolean |
| Secrets | Passed explicitly or with secrets: inherit |
| Access | The called workflow must be in a public repository, or in a private repository whose settings allow access |
| Matrix | You can call a reusable workflow inside a matrix with strategy on the calling job |
🧱 Composite Actions
A composite action bundles steps. Create a folder with an action.yml:
# .github/actions/setup-playwright/action.yml
name: Setup Playwright
description: Install Node, dependencies and Playwright browsers
inputs:
browsers:
description: Browsers to install
default: chromium
runs:
using: composite
steps:
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: npm
- run: npm ci
shell: bash
- run: npx playwright install --with-deps ${{ inputs.browsers }}
shell: bash
📝 Note: Every run step in a composite action must declare a shell.
Use it in any job:
steps:
- uses: actions/checkout@v4 # checkout first: local actions live in the repo
- uses: ./.github/actions/setup-playwright
with:
browsers: chromium firefox
- run: npx playwright test
🧰 Other Kinds of Custom Actions
| Type | Written in | Use when |
|---|---|---|
| Composite | YAML steps | Combining existing commands and actions |
| JavaScript | Node.js (runs.using: node20 or newer) | Logic, API calls, fast startup |
| Docker container | Any language in a container | Specific tools or environments (Linux runners only) |
Publish actions from a public repository to the GitHub Marketplace by adding an action.yml in the root and creating a release.
🛡️ Using Third-Party Actions Safely
- Prefer actions from verified creators (GitHub, Docker, Microsoft, AWS…).
- Pin third-party actions to a full commit SHA (with a version comment) so a moved tag cannot change what runs:
uses: some-org/some-action@<40-char-sha> # v2.1.0. - Let Dependabot update action versions with
package-ecosystem: github-actions. - Limit
permissionsofGITHUB_TOKEN(secrets and environments).
📝 Assignment
- Create a reusable workflow
test.ymlwith aprojectinput and a required secret, and call it twice fromci.ymlfor two browsers. - Return an output from the reusable workflow and print it in the caller.
- Create a composite action
setup-playwrightand use it in a job. - Call a reusable workflow inside a matrix.
- Pin one third-party action to a commit SHA and add a Dependabot config for GitHub Actions updates.
❓ FAQ
🤔 What is a reusable workflow in GitHub Actions?
A workflow with the workflow_call trigger that other workflows can call as a job, passing inputs and secrets.
🤔 What is the difference between a reusable workflow and a composite action?
A reusable workflow reuses whole jobs and chooses its own runner. A composite action reuses a sequence of steps inside the caller’s job.
🤔 How do I pass secrets to a reusable workflow?
Under secrets: in the calling job, either one by one or with secrets: inherit.
🤔 How do I create a custom GitHub Action?
Create an action.yml describing inputs and how it runs (composite, JavaScript or Docker), in its own folder or repository, then reference it with uses:.
🤔 Should I pin GitHub Actions to a version?
Yes. Use a version tag for trusted publishers and a full commit SHA for third-party actions to avoid unexpected changes.
🎯 Next Steps
- 🚀 Deploy with GitHub Actions
- 🏋️ GitHub Actions Hands-on Practice Projects
- 📘 Git and GitHub Tutorial: full course
🎬 Learn Git and GitHub step by step: watch the series on YouTube!
Subscribe to SqaToolsByDY • Practice on sqatools.in