diff --git a/content/actions/using-workflows/reusing-workflows.md b/content/actions/using-workflows/reusing-workflows.md index a49884dc40..bbdf28e7fe 100644 --- a/content/actions/using-workflows/reusing-workflows.md +++ b/content/actions/using-workflows/reusing-workflows.md @@ -69,7 +69,11 @@ Called workflows that are owned by the same user or organization{% ifversion ghe ## Limitations +{% ifversion nested-reusable-workflow %} +* You can connect up to four levels of workflows. For more information, see "[Calling a nested reusable workflow](#calling-a-nested-reusable-workflow)." +{% else %} * Reusable workflows can't call other reusable workflows. +{% endif %} * Reusable workflows stored within a private repository can only be used by workflows within the same repository. * Any environment variables set in an `env` context defined at the workflow level in the caller workflow are not propagated to the called workflow. For more information about the `env` context, see "[Context and expression syntax for GitHub Actions](/actions/reference/context-and-expression-syntax-for-github-actions#env-context)."{% ifversion actions-reusable-workflow-matrix %}{% else %} * The `strategy` property is not supported in any job that calls a reusable workflow.{% endif %} @@ -105,7 +109,13 @@ You can define inputs and secrets, which can be passed from the caller workflow {% endraw %} For details of the syntax for defining inputs and secrets, see [`on.workflow_call.inputs`](/actions/reference/workflow-syntax-for-github-actions#onworkflow_callinputs) and [`on.workflow_call.secrets`](/actions/reference/workflow-syntax-for-github-actions#onworkflow_callsecrets). {% ifversion actions-inherit-secrets-reusable-workflows %} -1. In the reusable workflow, reference the input or secret that you defined in the `on` key in the previous step. If the secrets are inherited using `secrets: inherit`, you can reference them even if they are not defined in the `on` key. +1. In the reusable workflow, reference the input or secret that you defined in the `on` key in the previous step. + + {% note %} + + **Note**: 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](/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idsecretsinherit)." + + {% endnote %} {%- else %} 1. In the reusable workflow, reference the input or secret that you defined in the `on` key in the previous step. {%- endif %} @@ -263,6 +273,56 @@ jobs: ``` {% endraw %} +{% ifversion nested-reusable-workflow %} +## Nesting reusable workflows + +You can connect a maximum of four levels of workflows - that is, the top-level caller workflow and up to three levels of reusable workflows. For example: _caller-workflow.yml_ → _called-workflow-1.yml_ → _called-workflow-2.yml_ → _called-workflow-3.yml_. Loops in the workflow tree are not permitted. + +From within a reusable workflow you can call another reusable workflow. + +{% raw %} +```yaml{:copy} +name: Reusable workflow + +on: + workflow_call: + +jobs: + call-another-reusable: + uses: octo-org/example-repo/.github/workflows/another-reusable.yml@v1 +``` +{% endraw %} + +### Passing secrets to nested workflows + +You can use `jobs..secrets` in a calling workflow to pass named secrets to a directly called workflow. Alternatively, you can use `jobs..secrets.inherit` to pass all of the calling workflow's secrets to a directly called workflow. For more information, see the section "[Passing inputs and secrets to a reusable workflow](/actions/using-workflows/reusing-workflows#passing-inputs-and-secrets-to-a-reusable-workflow)" above, and the reference article "[Workflow syntax for GitHub Actions](/actions/using-workflows/workflow-syntax-for-github-actions#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. + +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. + +{% raw %} +```yaml +jobs: + workflowA-calls-workflowB: + uses: octo-org/example-repo/.github/workflows/B.yml@main + secrets: inherit # pass all secrets +``` + +```yaml +jobs: + workflowB-calls-workflowC: + uses: different-org/example-repo/.github/workflows/C.yml@main + secrets: + envPAT: ${{ secrets.envPAT }} # pass just this secret +``` +{% endraw %} + +### Access and permissions + +A workflow that contains nested reusable workflows will fail if any of the nested workflows is inaccessible to the initial caller workflow. For more information, see "[Access to reusable workflows](/actions/using-workflows/reusing-workflows#access-to-reusable-workflows)." + +`GITHUB_TOKEN` permissions can only be the same or more restrictive in nested workflows. For example, in the workflow chain A > B > C, if workflow A has `package: read` token permission, then B and C cannot have `package: write` permission. For more information, see "[Automatic token authentication](/actions/security-guides/automatic-token-authentication)." +{% endif %} + ## Using outputs from a reusable workflow A 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.{% ifversion actions-reusable-workflow-matrix %} diff --git a/data/features/nested-reusable-workflow.yml b/data/features/nested-reusable-workflow.yml new file mode 100644 index 0000000000..702f7ac1c1 --- /dev/null +++ b/data/features/nested-reusable-workflow.yml @@ -0,0 +1,7 @@ +# Issues 7093 +# Reusable workflows can call other reusable workflows +versions: + fpt: '*' + ghec: '*' + ghes: '>=3.7' + ghae: 'issue-7093'