Creating a reusable workflow
Reusable workflows are YAML-formatted files, very similar to any other workflow file. As with other workflow files, you locate reusable workflows in the .github/workflows directory of a repository. Subdirectories of the workflows directory are not supported.
For a workflow to be reusable, the values for on must include workflow_call:
on:
workflow_call:
Using inputs and secrets in a reusable workflow
You can define inputs and secrets, which can be passed from the caller workflow and then used within the called workflow. There are three stages to using an input or a secret in a reusable workflow.
-
In the reusable workflow, use the
inputsandsecretskeywords to define inputs or secrets that will be passed from a caller workflow.on: workflow_call: inputs: config-path: required: true type: string secrets: personal_access_token: required: trueFor details of the syntax for defining inputs and secrets, see
on.workflow_call.inputsandon.workflow_call.secrets. -
In the reusable workflow, reference the input or secret that you defined in the
onkey in the previous step.Note
If the secrets are inherited by using
secrets: inheritin the calling workflow, you can reference them even if they are not explicitly defined in theonkey. For more information, see Workflow syntax for GitHub Actions.jobs: reusable_workflow_job: runs-on: ubuntu-latest steps: - uses: actions/labeler@v6 with: repo-token: ${{ secrets.personal_access_token }} configuration-path: ${{ inputs.config-path }}In the example above,
personal_access_tokenis a secret that's defined at the repository or organization level.Warning
Environment secrets cannot be passed from the caller workflow as
on.workflow_calldoes not support theenvironmentkeyword. If you includeenvironmentin the reusable workflow at the job level, the environment secret will be used, and not the secret passed from the caller workflow. For more information, see Managing environments for deployment and Workflow syntax for GitHub Actions. -
Pass the input or secret from the caller workflow.
To pass named inputs to a called workflow, use the
withkeyword in a job. Use thesecretskeyword to pass named secrets. For inputs, the data type of the input value must match the type specified in the called workflow (either boolean, number, or string).jobs: call-workflow-passing-data: uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main with: config-path: .github/labeler.yml secrets: personal_access_token: ${{ secrets.token }}Workflows that call reusable workflows in the same organization or enterprise can use the
inheritkeyword to implicitly pass the secrets.jobs: call-workflow-passing-data: uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main with: config-path: .github/labeler.yml secrets: inherit
Example reusable workflow
This reusable workflow file named workflow-B.yml (we'll refer to this later in the example caller workflow) takes an input string and a secret from the caller workflow and uses them in an action.
name: Reusable workflow example
on:
workflow_call:
inputs:
config-path:
required: true
type: string
secrets:
token:
required: true
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v6
with:
repo-token: ${{ secrets.token }}
configuration-path: ${{ inputs.config-path }}
name: Reusable workflow example
on:
workflow_call:
inputs:
config-path:
required: true
type: string
secrets:
token:
required: true
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v6
with:
repo-token: ${{ secrets.token }}
configuration-path: ${{ inputs.config-path }}
Calling a reusable workflow
You call a reusable workflow by using the uses keyword. Unlike when you are using actions within a workflow, you call reusable workflows directly within a job, and not from within job steps.
You reference reusable workflow files using one of the following syntaxes:
$/.github/workflows/{filename}for a reusable workflow in the same repository. This is the recommended syntax for referencing a reusable workflow in the same repository. This syntax is not available in GitHub Enterprise Server.{owner}/{repo}/.github/workflows/{filename}@{ref}for reusable workflows in public and private repositories../.github/workflows/{filename}for reusable workflows in the same repository.
When you reference a reusable workflow with {owner}/{repo} and @{ref}, the {ref} can be a SHA, a release tag, or a branch name. If a release tag and a branch have the same name, the release tag takes precedence over the branch name. Using the commit SHA is the safest option for stability and security. For more information, see Secure use reference.
When you reference a reusable workflow in the same repository using $/ or ./ (without {owner}/{repo} and @{ref}), the called workflow is from the same commit as the caller workflow. A $/ reference must not include an @{ref} suffix, and $/ is not available in GitHub Enterprise Server. Ref prefixes such as refs/heads and refs/tags are not allowed. You cannot use contexts or expressions in this keyword.
You can call multiple workflows, referencing each in a separate job.
jobs:
call-workflow-1-in-local-repo:
uses: octo-org/this-repo/.github/workflows/workflow-1.yml@172239021f7ba04fe7327647b213799853a9eb89
call-workflow-2-in-local-repo:
uses: ./.github/workflows/workflow-2.yml
# The `$/` syntax is not available in GitHub Enterprise Server.
call-workflow-in-same-repo-at-running-commit:
uses: $/.github/workflows/workflow-2.yml
call-workflow-in-another-repo:
uses: octo-org/another-repo/.github/workflows/workflow.yml@v1
Example caller workflow
This workflow file calls two workflow files. The second of these, workflow-B.yml (shown in the example reusable workflow), is passed an input (config-path) and a secret (token).
name: Call a reusable workflow
on:
pull_request:
branches:
- main
jobs:
call-workflow:
uses: octo-org/example-repo/.github/workflows/workflow-A.yml@v1
call-workflow-passing-data:
permissions:
contents: read
pull-requests: write
uses: octo-org/example-repo/.github/workflows/workflow-B.yml@main
with:
config-path: .github/labeler.yml
secrets:
token: ${{ secrets.GITHUB_TOKEN }}
name: Call a reusable workflow
on:
pull_request:
branches:
- main
jobs:
call-workflow:
uses: octo-org/example-repo/.github/workflows/workflow-A.yml@v1
call-workflow-passing-data:
permissions:
contents: read
pull-requests: write
uses: octo-org/example-repo/.github/workflows/workflow-B.yml@main
with:
config-path: .github/labeler.yml
secrets:
token: ${{ secrets.GITHUB_TOKEN }}
Passing inputs and secrets to a reusable workflow
To pass named inputs to a called workflow, use the with keyword in a job. Use the secrets keyword to pass named secrets. For inputs, the data type of the input value must match the type specified in the called workflow (either boolean, number, or string).
jobs:
call-workflow-passing-data:
uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main
with:
config-path: .github/labeler.yml
secrets:
personal_access_token: ${{ secrets.token }}
Workflows that call reusable workflows in the same organization or enterprise can use the inherit keyword to implicitly pass the secrets.
jobs:
call-workflow-passing-data:
uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main
with:
config-path: .github/labeler.yml
secrets: inherit
Using a matrix strategy with a reusable workflow
Jobs using the matrix strategy can call a reusable workflow.
A matrix strategy lets you use variables in a single job definition to automatically create multiple job runs that are based on the combinations of the variables. For example, you can use a matrix strategy to pass different inputs to a reusable workflow. For more information about matrices, see Running variations of jobs in a workflow.
This example job below calls a reusable workflow and references the matrix context by defining the variable target with the values [dev, stage, prod]. It will run three jobs, one for each value in the variable.
jobs:
ReusableMatrixJobForDeployment:
strategy:
matrix:
target: [dev, stage, prod]
uses: octocat/octo-repo/.github/workflows/deployment.yml@main
with:
target: ${{ matrix.target }}
jobs:
ReusableMatrixJobForDeployment:
strategy:
matrix:
target: [dev, stage, prod]
uses: octocat/octo-repo/.github/workflows/deployment.yml@main
with:
target: ${{ matrix.target }}
Nesting reusable workflows
You can connect a maximum of ten levels of workflows - that is, the top-level caller workflow and up to nine levels of reusable workflows. For example: caller-workflow.yml → called-workflow-1.yml → called-workflow-2.yml → called-workflow-3.yml → ... → called-workflow-9.yml.
Loops in the workflow tree are not permitted.
Note
Nested reusable workflows require all workflows in the chain to be accessible to the caller, and permissions can only be maintained or reduced—not elevated—throughout the chain. For more information, see Reusing workflow configurations.
From within a reusable workflow you can call another reusable workflow.
name: Reusable workflow
on:
workflow_call:
jobs:
call-another-reusable:
uses: octo-org/example-repo/.github/workflows/another-reusable.yml@v1
name: Reusable workflow
on:
workflow_call:
jobs:
call-another-reusable:
uses: octo-org/example-repo/.github/workflows/another-reusable.yml@v1
Passing secrets to nested workflows
You can use jobs.<job_id>.secrets in a calling workflow to pass named secrets to a directly called workflow. Alternatively, you can use jobs.<job_id>.secrets.inherit to pass all of the calling workflow's secrets to a directly called workflow. For more information, see the section Reuse workflows above, and the reference article Workflow syntax for GitHub Actions. Secrets are only passed to directly called workflow, so in the workflow chain A > B > C, workflow C will only receive secrets from A if they have been passed from A to B, and then from B to C.
In the following example, workflow A passes all of its secrets to workflow B, by using the inherit keyword, but workflow B only passes one secret to workflow C. Any of the other secrets passed to workflow B are not available to workflow C.
jobs:
workflowA-calls-workflowB:
uses: octo-org/example-repo/.github/workflows/B.yml@main
secrets: inherit # pass all secrets
jobs:
workflowB-calls-workflowC:
uses: different-org/example-repo/.github/workflows/C.yml@main
secrets: