{"meta":{"title":"Reuse workflows","intro":"Learn how to avoid duplication when creating a workflow by reusing existing workflows.","product":"GitHub Actions","breadcrumbs":[{"href":"/en/actions","title":"GitHub Actions"},{"href":"/en/actions/how-tos","title":"How-tos"},{"href":"/en/actions/how-tos/reuse-automations","title":"Reuse automations"},{"href":"/en/actions/how-tos/reuse-automations/reuse-workflows","title":"Reuse workflows"}],"documentType":"article"},"body":"# Reuse workflows\n\nLearn how to avoid duplication when creating a workflow by reusing existing workflows.\n\n## Creating a reusable workflow\n\nReusable 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.\n\nFor a workflow to be reusable, the values for `on` must include `workflow_call`:\n\n```yaml\non:\n  workflow_call:\n```\n\n## Using inputs and secrets in a reusable workflow\n\nYou 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.\n\n1. In the reusable workflow, use the `inputs` and `secrets` keywords to define inputs or secrets that will be passed from a caller workflow.\n\n   ```yaml\n   on:\n     workflow_call:\n       inputs:\n         config-path:\n           required: true\n           type: string\n       secrets:\n         personal_access_token:\n           required: true\n   ```\n\n   For details of the syntax for defining inputs and secrets, see [`on.workflow_call.inputs`](/en/actions/reference/workflows-and-actions/workflow-syntax#onworkflow_callinputs) and [`on.workflow_call.secrets`](/en/actions/reference/workflows-and-actions/workflow-syntax#onworkflow_callsecrets).\n\n2. In the reusable workflow, reference the input or secret that you defined in the `on` key in the previous step.\n\n   > \\[!NOTE]\n   > If the secrets are inherited by using `secrets: inherit` in the calling workflow, you can reference them even if they are not explicitly defined in the `on` key. For more information, see [Workflow syntax for GitHub Actions](/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idsecretsinherit).\n\n   ```yaml\n   jobs:\n     reusable_workflow_job:\n       runs-on: ubuntu-latest\n       steps:\n       - uses: actions/labeler@v6\n         with:\n           repo-token: ${{ secrets.personal_access_token }}\n           configuration-path: ${{ inputs.config-path }}\n   ```\n\n   In the example above, `personal_access_token` is a secret that's defined at the repository or organization level.\n\n   > \\[!WARNING]\n   > Environment secrets cannot be passed from the caller workflow as `on.workflow_call` does not support the `environment` keyword. If you include `environment` in 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](/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments) and [Workflow syntax for GitHub Actions](/en/actions/reference/workflows-and-actions/workflow-syntax#onworkflow_call).\n\n3. Pass the input or secret from the caller workflow.\n\n   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).\n\n   ```yaml\n   jobs:\n     call-workflow-passing-data:\n       uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main\n       with:\n         config-path: .github/labeler.yml\n       secrets:\n         personal_access_token: ${{ secrets.token }}\n   ```\n\n   Workflows that call reusable workflows in the same organization or enterprise can use the `inherit` keyword to implicitly pass the secrets.\n\n   ```yaml\n   jobs:\n     call-workflow-passing-data:\n       uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main\n       with:\n         config-path: .github/labeler.yml\n       secrets: inherit\n   ```\n\n### Example reusable workflow\n\nThis reusable workflow file named `workflow-B.yml` (we'll refer to this later in the [example caller workflow](#example-caller-workflow)) takes an input string and a secret from the caller workflow and uses them in an action.\n\n```yaml copy\nname: Reusable workflow example\n\non:\n  workflow_call:\n    inputs:\n      config-path:\n        required: true\n        type: string\n    secrets:\n      token:\n        required: true\n\njobs:\n  triage:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/labeler@v6\n      with:\n        repo-token: ${{ secrets.token }}\n        configuration-path: ${{ inputs.config-path }}\n```\n\n## Calling a reusable workflow\n\nYou 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.\n\n[`jobs.<job_id>.uses`](/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_iduses)\n\nYou reference reusable workflow files using one of the following syntaxes:\n\n* `$/.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.\n* `{owner}/{repo}/.github/workflows/{filename}@{ref}` for reusable workflows in public and private repositories.\n* `./.github/workflows/{filename}` for reusable workflows in the same repository.\n\nWhen 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](/en/actions/reference/security/secure-use#reusing-third-party-workflows).\n\nWhen 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.\n\nYou can call multiple workflows, referencing each in a separate job.\n\n```yaml\njobs:\n  call-workflow-1-in-local-repo:\n    uses: octo-org/this-repo/.github/workflows/workflow-1.yml@172239021f7ba04fe7327647b213799853a9eb89\n  call-workflow-2-in-local-repo:\n    uses: ./.github/workflows/workflow-2.yml\n  # The `$/` syntax is not available in GitHub Enterprise Server.\n  call-workflow-in-same-repo-at-running-commit:\n    uses: $/.github/workflows/workflow-2.yml\n  call-workflow-in-another-repo:\n    uses: octo-org/another-repo/.github/workflows/workflow.yml@v1\n```\n\n### Example caller workflow\n\nThis workflow file calls two workflow files. The second of these, `workflow-B.yml` (shown in the [example reusable workflow](#example-reusable-workflow)), is passed an input (`config-path`) and a secret (`token`).\n\n```yaml copy\nname: Call a reusable workflow\n\non:\n  pull_request:\n    branches:\n      - main\n\njobs:\n  call-workflow:\n    uses: octo-org/example-repo/.github/workflows/workflow-A.yml@v1\n\n  call-workflow-passing-data:\n    permissions:\n      contents: read\n      pull-requests: write\n    uses: octo-org/example-repo/.github/workflows/workflow-B.yml@main\n    with:\n      config-path: .github/labeler.yml\n    secrets:\n      token: ${{ secrets.GITHUB_TOKEN }}\n```\n\n## Passing inputs and secrets to a reusable workflow\n\nTo 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).\n\n```yaml\njobs:\n  call-workflow-passing-data:\n    uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main\n    with:\n      config-path: .github/labeler.yml\n    secrets:\n      personal_access_token: ${{ secrets.token }}\n```\n\nWorkflows that call reusable workflows in the same organization or enterprise can use the `inherit` keyword to implicitly pass the secrets.\n\n```yaml\njobs:\n  call-workflow-passing-data:\n    uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main\n    with:\n      config-path: .github/labeler.yml\n    secrets: inherit\n```\n\n## Using a matrix strategy with a reusable workflow\n\nJobs using the matrix strategy can call a reusable workflow.\n\nA 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](/en/actions/how-tos/write-workflows/choose-what-workflows-do/run-job-variations).\n\nThis 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.\n\n```yaml copy\njobs:\n  ReusableMatrixJobForDeployment:\n    strategy:\n      matrix:\n        target: [dev, stage, prod]\n    uses: octocat/octo-repo/.github/workflows/deployment.yml@main\n    with:\n      target: ${{ matrix.target }}\n```\n\n## Nesting reusable workflows\n\nYou 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*.\n\nLoops in the workflow tree are not permitted.\n\n> \\[!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](/en/actions/reference/workflows-and-actions/reusing-workflow-configurations).\n\nFrom within a reusable workflow you can call another reusable workflow.\n\n```yaml copy\nname: Reusable workflow\n\non:\n  workflow_call:\n\njobs:\n  call-another-reusable:\n    uses: octo-org/example-repo/.github/workflows/another-reusable.yml@v1\n```\n\n## Passing secrets to nested workflows\n\nYou 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](/en/actions/how-tos/reuse-automations/reuse-workflows#passing-inputs-and-secrets-to-a-reusable-workflow) above, and the reference article [Workflow syntax for GitHub Actions](/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idsecretsinherit). 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.\n\nIn 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.\n\n```yaml\njobs:\n  workflowA-calls-workflowB:\n    uses: octo-org/example-repo/.github/workflows/B.yml@main\n    secrets: inherit # pass all secrets\n```\n\n```yaml\njobs:\n  workflowB-calls-workflowC:\n    uses: different-org/example-repo/.github/workflows/C.yml@main\n    secrets:\n      repo-token: ${{ secrets.personal_access_token }} # pass just this secret\n```\n\n## Using outputs from a reusable workflow\n\nA reusable workflow may generate data that you want to use in the caller workflow. To use these outputs, you must specify them as the outputs of the reusable workflow.\n\nIf a reusable workflow that sets an output is executed with a matrix strategy, the output will be the output set by the last successful completing reusable workflow of the matrix which actually sets a value.\nThat means if the last successful completing reusable workflow sets an empty string for its output, and the second last successful completing reusable workflow sets an actual value for its output, the output will contain the value of the second last completing reusable workflow.\n\nThe following reusable workflow has a single job containing two steps. In each of these steps we set a single word as the output: \"hello\" and \"world.\" In the `outputs` section of the job, we map these step outputs to job outputs called: `output1` and `output2`. In the `on.workflow_call.outputs` section we then define two outputs for the workflow itself, one called `firstword` which we map to `output1`, and one called `secondword` which we map to `output2`.\n\nThe `value` must be set to the value of a job-level output within the called workflow. Step-level outputs must first be mapped to job-level outputs as shown below.\n\nFor more information, see [Passing information between jobs](/en/actions/how-tos/write-workflows/choose-what-workflows-do/pass-job-outputs) and [Workflow syntax for GitHub Actions](/en/actions/reference/workflows-and-actions/workflow-syntax#onworkflow_calloutputs).\n\n```yaml copy\nname: Reusable workflow\n\non:\n  workflow_call:\n    # Map the workflow outputs to job outputs\n    outputs:\n      firstword:\n        description: \"The first output string\"\n        value: ${{ jobs.example_job.outputs.output1 }}\n      secondword:\n        description: \"The second output string\"\n        value: ${{ jobs.example_job.outputs.output2 }}\n\njobs:\n  example_job:\n    name: Generate output\n    runs-on: ubuntu-latest\n    # Map the job outputs to step outputs\n    outputs:\n      output1: ${{ steps.step1.outputs.firstword }}\n      output2: ${{ steps.step2.outputs.secondword }}\n    steps:\n      - id: step1\n        run: echo \"firstword=hello\" >> $GITHUB_OUTPUT\n      - id: step2\n        run: echo \"secondword=world\" >> $GITHUB_OUTPUT\n```\n\nWe can now use the outputs in the caller workflow, in the same way you would use the outputs from a job within the same workflow. We reference the outputs using the names defined at the workflow level in the reusable workflow: `firstword` and `secondword`. In this workflow, `job1` calls the reusable workflow and `job2` prints the outputs from the reusable workflow (\"hello world\") to standard output in the workflow log.\n\n```yaml copy\nname: Call a reusable workflow and use its outputs\n\non:\n  workflow_dispatch:\n\njobs:\n  job1:\n    uses: octo-org/example-repo/.github/workflows/called-workflow.yml@v1\n\n  job2:\n    runs-on: ubuntu-latest\n    needs: job1\n    steps:\n      - run: echo ${{ needs.job1.outputs.firstword }} ${{ needs.job1.outputs.secondword }}\n```\n\nFor more information on using job outputs, see [Workflow syntax for GitHub Actions](/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idoutputs). If you want to share something other than a variable (e.g. a build artifact) between workflows, see [Store and share data with workflow artifacts](/en/actions/tutorials/store-and-share-data).\n\n## Monitoring which workflows are being used\n\nOrganizations that use GitHub Enterprise Cloud can interact with the audit log via the GitHub REST API to monitor which workflows are being used. For more information, see [the GitHub Enterprise Cloud documentation](/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/reviewing-the-audit-log-for-your-organization#using-the-audit-log-api).\n\n## Next steps\n\nTo find information on the intricacies of reusing workflows, see [Reusing workflow configurations](/en/actions/reference/workflows-and-actions/reusing-workflow-configurations)."}