Skip to main content

Building Composite Actions

1. Creating Composite Action

Composite Actions allow you to combine multiple steps into a single reusable action. They are defined in a action.yml file and can be used in workflows.

Field Description Required Example
name The name of the action Yes My Composite Action
description A description of what the action does No Performs a set of steps in sequence
inputs Inputs that can be passed to the action No { 'input1': { 'required': true, 'default': 'value' } }
outputs Outputs that the action can produce No { 'output1': { 'value': '${{ steps.step1.outputs.output1 }}' } }
runs Defines how the action runs Yes { 'using': 'composite', 'steps': [...] }

Example: Basic Composite Action

name: 'My Composite Action'
description: 'A simple composite action'
inputs:
  greeting:
    description: 'The greeting to use'
    required: false
    default: 'Hello'
outputs:
  result:
    description: 'The result of the action'
    value: ${{ steps.step1.outputs.result }}
runs:
  using: 'composite'
  steps:
    - name: 'Say Greeting'
      shell: bash
      run: |
        echo "${{ inputs.greeting }} World!"
        echo "result=Hello World!" >> $GITHUB_OUTPUT

2. Defining Action Inputs

Property Description Required Type
name The name of the input parameter Yes string
description A description of the input parameter No string
required Whether the input is required No boolean
default The default value if not provided No any
options Valid values for the input (for enum-like behavior) No array of strings

Example: Defining Inputs in action.yml

name: 'My Composite Action'
description: 'A sample composite action'
inputs:
  environment:
    description: 'The environment to deploy to'
    required: true
    default: 'staging'
  debug:
    description: 'Enable debug mode'
    required: false
    default: 'false'
  target:
    description: 'Target deployment type'
    required: false
    options: ['web', 'mobile', 'api']
    default: 'web'

3. Defining Action Outputs

Property Description Example
outputs Defines the outputs that an action can return.
outputs:
  result:
    description: "The result of the action"

Example: Defining Outputs in action.yml

name: 'Composite Action Example'
description: 'A composite action with outputs'
inputs:
  input-value:
    description: 'Input value for processing'
    required: true
outputs:
  processed-result:
    description: 'The processed result from the action'
    value: ${{ steps.process.outputs.result }}
runs:
  using: 'composite'
  steps:
    - name: Process Input
      id: process
      run: |
        echo "result=processed_value" >> $GITHUB_OUTPUTS
      shell: bash
Note: The value field in outputs is evaluated at runtime and can reference steps or other action properties.

4. Using Runs Composite

Property Description Values
runs Defines the composite action's execution logic using: "composite"
runs.steps List of steps to execute in the composite action Array of step objects
runs.steps.uses Reference to an action or script to run String, e.g., actions/checkout@v4
runs.steps.with Input parameters to pass to the action or script Object with key-value pairs
runs.steps.env Environment variables to set for the step Object with key-value pairs
runs.steps.id Unique identifier for the step String
runs.steps.name Display name for the step String

Example: Using Runs Composite

name: "My Composite Action"
runs:
  using: "composite"
  steps:
    - name: "Checkout Code"
      uses: actions/checkout@v4
      with:
        repository: my-repo/my-project
    - name: "Setup Node"
      uses: actions/setup-node@v4
      with:
        node-version: "20"

5. Executing Multiple Steps

Composite actions can execute multiple steps in sequence using the runs property. Each step is defined as a list of actions to run in the composite action.

Step Description Configuration
runs.steps Defines the steps to execute in the composite action steps: array of step objects
runs.steps[].uses Specifies the action to run in this step uses: <action>
runs.steps[].with Passes input parameters to the action with: object with key-value pairs
runs.steps[].env Sets environment variables for the step env: object with key-value pairs

Example: Executing Multiple Steps

name: "Composite Action with Multiple Steps"
description: "A composite action that runs multiple steps"
inputs:
  greeting:
    description: "Greeting to use in the output"
    required: true
    default: "Hello"
outputs:
  result:
    description: "The result of the composite action"
    value: ${{ steps.step1.outputs.result }}
runs:
  using: "composite"
  steps:
    - name: "Step 1: Print Greeting"
      id: step1
      uses: actions/checkout@v4
      with:
        greeting: ${{ inputs.greeting }}
    - name: "Step 2: Run Script"
      id: step2
      uses: actions/github-script@v7
      with:
        script: |
          const result = `Greeting was: ${{ inputs.greeting }}`;
          console.log(result);
          return result;
Note: Steps in a composite action are executed sequentially, and each step can depend on the previous one. The id field allows referencing outputs from earlier steps.

Key Points

  • Each step in a composite action is defined under runs.steps
  • Steps can use other actions via the uses property
  • Inputs and environment variables can be passed to each step using with and env
  • Steps execute in order, and outputs from one step can be used in another

6. Setting Shell for Steps

Property Values Description
shell bash, sh, pwsh, powershell, python Specifies the shell to use for running commands in a step. Defaults to bash on Linux, sh on macOS, and powershell on Windows.

Example: Using PowerShell on Windows

steps:
  - name: Run PowerShell script
    shell: powershell
    run: |
      Write-Host "Hello from PowerShell"
      $env:MY_VAR = "test"

Example: Using Python Shell

steps:
  - name: Run Python script
    shell: python
    run: |
      import os
      print("Current directory:", os.getcwd())

7. Passing Inputs to Steps

Input Description Type Required
name The name of the input parameter string Yes
description A description of the input parameter string No
required Whether the input is required boolean No
default The default value if not provided string No

Example: Using Inputs in a Composite Action

name: 'Composite Action Example'
inputs:
  greeting:
    description: 'The greeting to use'
    required: true
    default: 'Hello'
  name:
    description: 'The name to greet'
    required: false
    default: 'World'
runs:
  using: 'composite'
  steps:
    - name: Greet
      run: |
        echo "${{ inputs.greeting }}, ${{ inputs.name }}!"
      shell: bash

8. Setting Output Values

Property Description Example
outputs Defines the outputs that a composite action can return.
outputs:
  message: 
    description: "The message output"
    value: ${{ steps.step1.outputs.message }}

Example: Setting Output Values in a Composite Action

name: "Composite Action with Outputs"
description: "A composite action that sets and returns outputs"

inputs:
  message:
    description: "Input message"
    required: true

outputs:
  result:
    description: "The processed message"
    value: ${{ steps.process.outputs.message }}

runs:
  using: "composite"
  steps:
    - name: Process Message
      id: process
      run: |
        echo "message=Processed: ${{ inputs.message }}" >> $GITHUB_OUTPUT
      shell: bash
Note: Output values are set using the GITHUB_OUTPUT file in composite actions.

9. Using Environment Variables

Variable Value Description
GITHUB_ACTION_PATH /home/runner/work/my-repo/my-repo Path to the action directory
GITHUB_ENV /home/runner/work/my-repo/my-repo/GITHUB_ENV File to write environment variables to
GITHUB_OUTPUT /home/runner/work/my-repo/my-repo/GITHUB_OUTPUT File to write outputs to

Example: Setting an environment variable in a composite action

name: 'Set Environment Variable'
runs:
  using: 'composite'
  steps:
    - name: Set environment variable
      run: echo "MY_VAR=value" >> $GITHUB_ENV
      shell: bash

Example: Reading an environment variable in a composite action

name: 'Read Environment Variable'
runs:
  using: 'composite'
  steps:
    - name: Use environment variable
      run: echo "The value is $MY_VAR"
      shell: bash

10. Handling Errors

Property Description Values
on-failure Defines action to take when a step fails continue, abort
continue-on-error Allows a step to continue even if it fails true, false

Example: Using continue-on-error

steps:
  - name: Install dependencies
    id: install
    run: npm install
    continue-on-error: true

  - name: Run tests
    if: steps.install.outcome == 'success'
    run: npm test

Example: Handling failure with on-failure

jobs:
  build:
    steps:
      - name: Build
        run: |
          echo "Building..."
          exit 1
        on-failure: |
          echo "Build failed, running cleanup"
          rm -rf build/
Note: on-failure is only supported in composite actions and cannot be used in regular job steps.

Error Handling Best Practices

  • Use continue-on-error: true for optional steps that shouldn't halt the workflow
  • Implement on-failure for composite actions to handle step failures gracefully
  • Log errors with descriptive messages to aid debugging

11. Using Pre and Post Steps

Pre and post steps are used to run setup or cleanup operations before or after a composite action runs.

Step Type Description Usage
pre Runs before the composite action's main steps pre: 'run: echo "Running pre-step"
post Runs after the composite action's main steps post: 'run: echo "Running post-step"

Example: Using pre and post steps in a composite action

name: 'Example Composite Action'
description: 'A composite action with pre and post steps'
inputs:
  greeting:
    description: 'Greeting to use'
    required: false
    default: 'Hello'
runs:
  using: 'composite'
  steps:
    - name: Pre-step
      uses: actions/github-script@v6
      with:
        script: |
          console.log('Running pre-step');
    - name: Main action
      run: echo "${{ inputs.greeting }} World!"
      shell: bash
    - name: Post-step
      uses: actions/github-script@v6
      with:
        script: |
          console.log('Running post-step');

12. Sharing Composite Actions

Aspect Description Details
Repository Location Where to store composite actions Store in a GitHub repository, typically under .github/workflows or as a reusable component in a dedicated repo.
Publishing Method How to share composite actions Use GitHub Marketplace or publish as a reusable workflow in a public repository.
Versioning How to version composite actions Use semantic version tags (e.g., v1.0.0) to manage releases and updates.
Documentation What to include in documentation Include a README.md with usage examples, parameters, and configuration options.
Access Control Who can use the action Actions in public repositories are accessible to everyone; private actions require appropriate permissions.

Example: Using a Shared Composite Action

name: Use Shared Composite Action
on:
  push:
    branches: [ main ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Use Composite Action
        uses: owner/repo/action-name@v1.0.0
        with:
          input-value: "example"
Note: Composite actions must be published in a repository with proper permissions to be used by others.
Warning: Ensure that composite actions are well-documented and tested before sharing to avoid breaking workflows.

13. Versioning Composite Actions

Version Type Description Usage
Major Breaking changes that require updates to the composite action usage actions/checkout@v3
Minor Backward-compatible features or enhancements actions/checkout@v3.0
Patch Backward-compatible bug fixes actions/checkout@v3.0.0

Example: Using a specific version in a workflow

jobs:
  build:
    steps:
      - name: Use composite action
        uses: my-org/my-repo@v2.1.0
Note: It is recommended to pin to a specific version or tag to ensure stability and prevent unexpected behavior from updates.

Was this article helpful?