GitHub Actions
Custom Actions
Create a Composite Action
Composite actions let you encapsulate multiple workflow steps into a single, reusable GitHub Actions component. In this guide, you’ll learn how to author a composite action from scratch, define its metadata, and integrate it into your workflows.
Metadata File Basics
Every custom GitHub Action requires a metadata file named action.yml
or action.yaml
. This file uses YAML syntax to describe your action’s configuration:
Key | Required | Description |
---|---|---|
name | Yes | A unique identifier for the action. |
description | No | A short summary of what the action does. |
author | No | The creator or maintainer of the action. |
inputs | No | Define parameters your action accepts. |
outputs | No | Expose values for downstream steps. |
runs | Yes | Specifies how the action executes (e.g., composite ). |
branding | No | Marketplace icon and color settings. |
Note
Learn more about metadata syntax in the GitHub Actions docs.
runs
Syntax for Composite Actions
To bundle multiple workflow steps, set using: "composite"
under runs
. You can then list any combination of uses
, run
, if
, shell
, or id
fields as you would in a standard workflow.
runs:
using: "composite"
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Run a script
run: echo "Hello from composite!"
Reference inputs with ${{ inputs.INPUT_NAME }}
and step outputs with ${{ steps.STEP_ID.outputs.OUTPUT_NAME }}
.
Example: npm-custom-action
Let’s create a composite action to cache and install npm dependencies. Save this file as.github/custom-actions/npm-action/action.yml
in your repository:
name: "npm-custom-action"
description: "Cache and install npm dependencies"
inputs:
cache-path:
description: "Directory to cache (e.g., node_modules)"
required: true
default: "node_modules"
runs:
using: "composite"
steps:
- name: Cache npm dependencies
uses: actions/cache@v3
with:
path: ${{ inputs.cache-path }}
key: ${{ runner.os }}-node-modules-${{ hashFiles('package-lock.json') }}
- name: Install dependencies
run: npm install
How It Works
- Inputs
cache-path
: Specifies which folder to cache (defaults tonode_modules
).
- Steps
- Cache npm dependencies: Uses
actions/cache@v3
to store and restore the specified directory. - Install dependencies: Runs
npm install
to fetch packages.
- Cache npm dependencies: Uses
Using the Composite Action
In your main workflow (e.g., .github/workflows/ci.yml
), replace the redundant caching and install steps with your new composite action:
name: CI Pipeline
on: [push, pull_request]
jobs:
unit-testing:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Prepare npm
uses: ./.github/custom-actions/npm-action
with:
cache-path: node_modules
- name: Run tests
run: npm test
- name: Archive test results
if: always()
uses: actions/upload-artifact@v3
with:
name: test-results
path: test-results.xml
Note
You can reference the composite action via its relative path (./.github/custom-actions/npm-action
). Pass inputs under with:
just like any other action.
Conclusion
By defining a composite action, you can centralize common steps—such as caching and installation—into a single reusable unit. This reduces duplication across workflows and simplifies maintenance. For advanced scenarios, consider adding:
- Output parameters to pass data downstream
- Conditional steps (
if
) for dynamic behavior - Branding options for Marketplace listings
Links and References
- GitHub Actions Metadata Syntax
- Composite run steps actions
- actions/cache GitHub Repository
- actions/setup-node GitHub Repository
Watch Video
Watch video content