workflow_call

Reusable Workflows with workflow_call

A workflow whose on includes workflow_call can be called by other workflows as if it were a job. It declares its interface, typed inputs, secrets and outputs, and runs its own jobs on the caller's behalf:

.github/workflows/catalog-check.yml, a reusable workflowYAML
name: Catalog check
on:
  workflow_call:
    inputs:
      genre:
        type: string
        required: true
    secrets:
      shelf-key:
        required: true
    outputs:
      count:
        description: Books in the genre
        value: ${{ jobs.count.outputs.count }}
permissions:
  contents: read
jobs:
  count:
    runs-on: ubuntu-24.04
    outputs:
      count: ${{ steps.books.outputs.count }}
    steps:
      - uses: actions/checkout@v7
      - id: setup
        uses: ./.github/actions/setup-booknest
      - id: books
        uses: ./.github/actions/count-books
        with:
          genre: ${{ inputs.genre }}
      - env:
          SHELF_API_KEY: ${{ secrets.shelf-key }}
          NODE: ${{ steps.setup.outputs.node-version }}
        run: echo "Node $NODE, key $SHELF_API_KEY, ${{ steps.books.outputs.count }} books"

A caller references it by path in the same repository (./.github/workflows/...) or as owner/repo/.github/workflows/file.yml@ref from another one; a private reusable workflow is callable only from repositories its owner allows. Calls nest up to ten levels deep, and one workflow file may reach at most 50 unique reusable workflows, nested ones included. The called workflow runs with the caller's github context and can only lower the permissions the caller grants. Compared with a composite action (Composite Actions), a reusable workflow holds whole jobs, with their own runners, environments and matrices; an action holds steps inside one job.