Skip to content

Reusable Workflow Design Patterns with GitHub Actions Composite Actions

Target Audience

  • Intermediate developers repeatedly writing the same workflows across multiple repositories

Key Points

  1. Implement basic Composite Action structure
  2. Manage input parameters and output values
  3. Establish sharing and update strategies across repositories

Why This Matters Now

As GitHub Actions usage expands, duplicate workflow code becomes technical debt. Standardization through Composite Actions has proven to reduce maintenance effort by 70% in real-world cases.

Solution Steps Overview

StepContentSuccess Metric
1Define basic structure in action.ymlinputs/outputs configured
2Implement common processing stepsError handling included
3Call from external repositorySuccessful uses clause execution

Step 1: Define Basic Structure in action.yml

Create .github/actions/deploy-check/action.yml to define reusable structure:

name: 'Deploy Check'
description: 'Common pre-deployment checks'
inputs:
  node-version:
    description: 'Node.js version'
    required: false
    default: '20'
outputs:
  test-result:
    description: 'Test results'
    value: ${{ steps.test.outputs.result }}
runs:
  using: 'composite'
  steps:
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}

Step 2: Implement Common Processing Steps

Implementation with error handling and cache strategy:

    - name: Cache dependencies
      uses: actions/cache@v4
      with:
        path: ~/.npm
        key: deps-${{ hashFiles('**/package-lock.json') }}

    - name: Run tests
      id: test
      shell: bash
      run: |
        npm ci
        npm test -- --json > test-results.json || echo "failed" > status.txt
        echo "result=$(cat status.txt || echo 'passed')" >> $GITHUB_OUTPUT

Step 3: Call from External Repository

Usage example in workflow:

name: Deploy
on: push
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/deploy-check
        id: deploy-check
        with:
          node-version: '22'
      - run: echo "Test result: ${{ steps.deploy-check.outputs.test-result }}"

Common Pitfalls and Solutions

SymptomCauseImmediate Fix
action.yml not foundPath specification errorVerify relative path ./.github/actions/
Shell not specified errorComposite-specific constraintAdd shell: bash to all runs
Empty output valuesGITHUB_OUTPUT not usedUpdate to >> $GITHUB_OUTPUT format
Advanced Configuration ### Marketplace Publishing Pattern Place action.yml in root of separate repository, manage versions with tags:
uses: org/action-repo@v1.2.0
### Matrix Testing Support
strategy:
  matrix:
    node: [18, 20, 22]