When you have a lot of workflows in your repository. There would be a scenario where you want to reuse some steps instead of writing them repeatedly and updating them when the versions are updated in multiple files.
Creating a composite action is one way to achieve this with GitHub Actions.
One Common Example I can think of is Setting up the desired language and installing the dependencies. Which is most common and used in most of the workflows.
To create a re-usable action that can be used in your workflows. you have to create an action.yml file under the .github folder
Let’s call our action setup-node-bun-install
- Let’s create a file in this way
.github/actions/setup-node-bun-install/action.yml
runs:
using: "composite"
steps:One thing to observe in this is the runs property that contains the list of steps to run
The Folder structure for this would be something like this
.github
- workflows
- lint-ts.yml
- actions
- setup-node-bun-install/action.yml
- eas-build/action.yml
- setup-jdk-generate-apk.yml
Let’s implement the setup-node-bun-install composite action
name: "Setup Node + Bun + Install Dependencies"
description: "Setup Node.js, Bun, and install project dependencies."
runs:
using: "composite"
steps:
- name: 📦 Setup Node.js
uses: actions/setup-node@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: 📦 Install Project Dependencies
run: bun install --frozen-lockfile
shell: bashNow this composite action can be used like this
name: Type Check (tsc)
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
type-check:
name: Type Check (tsc)
runs-on: ubuntu-latest
steps:
- name: 📦 Checkout project repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 📦 Setup Node + Bun + Install Dependencies
uses: ./.github/actions/setup-node-bun-install
- name: 📦 Install Reviewdog
if: github.event_name == 'pull_request'
uses: reviewdog/action-setup@v1
- name: 🏃♂️ Run TypeScript PR # Reviewdog tsc errorformat: %f:%l:%c - error TS%n: %m
# We only need to add the reviewdog step if it's a pull request
if: github.event_name == 'pull_request'
run: |
bun type-check | reviewdog -name="tsc" -efm="%f(%l,%c): error TS%n: %m" -reporter="github-pr-review" -filter-mode="nofilter" -fail-on-error -tee
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name:
🏃♂️ Run TypeScript Commit
# If it's not a Pull Request then we just need to run the type-check
if: github.event_name != 'pull_request'
run: bun type-check