Note
GitHub-hosted runners are not currently supported on GitHub Enterprise Server. You can see more information about planned future support on the GitHub public roadmap.
About YAML syntax for workflows
Workflow files use YAML syntax, and must have either a .yml or .yaml file extension. If you're new to YAML and want to learn more, see Learn YAML in Y minutes.
You must store workflow files in the .github/workflows directory of your repository.
name
The name of the workflow. GitHub displays the names of your workflows under your repository's "Actions" tab. If you omit name, GitHub displays the workflow file path relative to the root of the repository.
run-name
The name for workflow runs generated from the workflow. GitHub displays the workflow run name in the list of workflow runs on your repository's "Actions" tab. If run-name is omitted or is only whitespace, then the run name is set to event-specific information for the workflow run. For example, for a workflow triggered by a push or pull_request event, it is set as the commit message or the title of the pull request.
This value can include expressions and can reference the github and inputs contexts.
Example of run-name
run-name: Deploy to ${{ inputs.deploy_target }} by @${{ github.actor }}
on
To automatically trigger a workflow, use on to define which events can cause the workflow to run. For a list of available events, see Events that trigger workflows.
You can define single or multiple events that can trigger a workflow, or set a time schedule. You can also restrict the execution of a workflow to only occur for specific files, tags, or branch changes. These options are described in the following sections.
Using a single event
For example, a workflow with the following on value will run when a push is made to any branch in the workflow's repository:
on: push
Using multiple events
You can specify a single event or multiple events. For example, a workflow with the following on value will run when a push is made to any branch in the repository or when someone forks the repository:
on: [push, fork]
If you specify multiple events, only one of those events needs to occur to trigger your workflow. If multiple triggering events for your workflow occur at the same time, multiple workflow runs will be triggered.
Using activity types
Some events have activity types that give you more control over when your workflow should run. Use on.<event_name>.types to define the type of event activity that will trigger a workflow run.
For example, the issue_comment event has the created, edited, and deleted activity types. If your workflow triggers on the label event, it will run whenever a label is created, edited, or deleted. If you specify the created activity type for the label event, your workflow will run when a label is created but not when a label is edited or deleted.
on:
label:
types:
- created
If you specify multiple activity types, only one of those event activity types needs to occur to trigger your workflow. If multiple triggering event activity types for your workflow occur at the same time, multiple workflow runs will be triggered. For example, the following workflow triggers when an issue is opened or labeled. If an issue with two labels is opened, three workflow runs will start: one for the issue opened event and two for the two issue labeled events.
on:
issues:
types:
- opened
- labeled
For more information about each event and their activity types, see Events that trigger workflows.
Using filters
Some events have filters that give you more control over when your workflow should run.
For example, the push event has a branches filter that causes your workflow to run only when a push to a branch that matches the branches filter occurs, instead of when any push occurs.
on:
push:
branches:
- main
- 'releases/**'
Using activity types and filters with multiple events
If you specify activity types or filters for an event and your workflow triggers on multiple events, you must configure each event separately. You must append a colon (:) to all events, including events without configuration.
For example, a workflow with the following on value will run when:
- A label is created
- A push is made to the
mainbranch in the repository - A push is made to a GitHub Pages-enabled branch
on:
label:
types:
- created
push:
branches:
- main
page_build:
on.<event_name>.types
Use on.<event_name>.types to define the type of activity that will trigger a workflow run. Most GitHub events are triggered by more than one type of activity. For example, the label is triggered when a label is created, edited, or deleted. The types keyword enables you to narrow down activity that causes the workflow to run. When only one activity type triggers a webhook event, the types keyword is unnecessary.
You can use an array of event types. For more information about each event and their activity types, see Events that trigger workflows.
on:
label:
types: [created, edited]
on.<pull_request|pull_request_target>.<branches|branches-ignore>
When using the pull_request and pull_request_target events, you can configure a workflow to run only for pull requests that target specific branches.
Use the branches filter when you want to include branch name patterns or when you want to both include and exclude branch names patterns. Use the branches-ignore filter when you only want to exclude branch name patterns. You cannot use both the branches and branches-ignore filters for the same event in a workflow.
If you define both branches/branches-ignore and paths/paths-ignore, the workflow will only run when both filters are satisfied.
The branches and branches-ignore keywords accept glob patterns that use characters like *, **, +, ?, ! and others to match more than one branch name. If a name contains any of these characters and you want a literal match, you need to escape each of these special characters with \. For more information about glob patterns, see the Workflow syntax for GitHub Actions.
Example: Including branches
The patterns defined in branches are evaluated against the Git ref's name. For example, the following workflow would run whenever there is a pull_request event for a pull request targeting:
- A branch named
main(refs/heads/main) - A branch named
mona/octocat(refs/heads/mona/octocat) - A branch whose name starts with
releases/, likereleases/10(refs/heads/releases/10)
on:
pull_request:
# Sequence of patterns matched against refs/heads
branches:
- main
- 'mona/octocat'
- 'releases/**'
You should not use path or branch filtering to skip workflow runs if the workflow is required. For more information, see Skipping workflow runs and Required workflows.
If a workflow is skipped due to branch filtering, path filtering, or a commit message, then checks associated with that workflow will remain in a "Pending" state. A pull request that requires those checks to be successful will be blocked from merging.
Example: Excluding branches
When a pattern matches the branches-ignore pattern, the workflow will not run. The patterns defined in branches-ignore are evaluated against the Git ref's name. For example, the following workflow would run whenever there is a pull_request event unless the pull request is targeting:
- A branch named
mona/octocat(refs/heads/mona/octocat) - A branch whose name matches
releases/**-alpha, likereleases/beta/3-alpha(refs/heads/releases/beta/3-alpha)
on:
pull_request:
# Sequence of patterns matched against refs/heads
branches-ignore:
- 'mona/octocat'
- 'releases/**-alpha'
Example: Including and excluding branches
You cannot use branches and branches-ignore to filter the same event in a single workflow. If you want to both include and exclude branch patterns for a single event, use the branches filter along with the ! character to indicate which branches should be excluded.
If you define a branch with the ! character, you must also define at least one branch without the ! character. If you only want to exclude branches, use branches-ignore instead.
The order that you define patterns matters.
- A matching negative pattern (prefixed with
!) after a positive match will exclude the Git ref. - A matching positive pattern after a negative match will include the Git ref again.
The following workflow will run on pull_request events for pull requests that target releases/10 or releases/beta/mona, but not for pull requests that target releases/10-alpha or releases/beta/3-alpha because the negative pattern !releases/**-alpha follows the positive pattern.
on:
pull_request:
branches:
- 'releases/**'
- '!releases/**-alpha'
on.push.<branches|tags|branches-ignore|tags-ignore>
When using the push event, you can configure a workflow to run on specific branches or tags.
Use the branches filter when you want to include branch name patterns or when you want to both include and exclude branch names patterns. Use the branches-ignore filter when you only want to exclude branch name patterns. You cannot use both the branches and branches-ignore filters for the same event in a workflow.
Use the tags filter when you want to include tag name patterns or when you want to both include and exclude tag names patterns. Use the tags-ignore filter when you only want to exclude tag name patterns. You cannot use both the tags and tags-ignore filters for the same event in a workflow.
If you define only tags/tags-ignore or only branches/branches-ignore, the workflow won't run for events affecting the undefined Git ref. If you define neither tags/tags-ignore or branches/branches-ignore, the workflow will run for events affecting either branches or tags. If you define both branches/branches-ignore and paths/paths-ignore, the workflow will only run when both filters are satisfied.
The branches, branches-ignore, tags, and tags-ignore keywords accept glob patterns that use characters like *, **, +, ?, ! and others to match more than one branch or tag name. If a name contains any of these characters and you want a literal match, you need to escape each of these special characters with \. For more information about glob patterns, see the Workflow syntax for GitHub Actions.
Example: Including branches and tags
The patterns defined in branches and tags are evaluated against the Git ref's name. For example, the following workflow would run whenever there is a push event to:
- A branch named
main(refs/heads/main) - A branch named
mona/octocat(refs/heads/mona/octocat) - A branch whose name starts with
releases/, likereleases/10(refs/heads/releases/10) - A tag named
v2(refs/tags/v2) - A tag whose name starts with
v1., likev1.9.1(refs/tags/v1.9.1)
on:
push:
# Sequence of patterns matched against refs/heads
branches:
- main
- 'mona/octocat'
- 'releases/**'
# Sequence of patterns matched against refs/tags
tags:
- v2
- v1.*
Example: Excluding branches and tags
When a pattern matches the branches-ignore or tags-ignore pattern, the workflow will not run. The patterns defined in branches and tags are evaluated against the Git ref's name. For example, the following workflow would run whenever there is a push event, unless the push event is to:
- A branch named
mona/octocat(refs/heads/mona/octocat) - A branch whose name matches
releases/**-alpha, likereleases/beta/3-alpha(refs/heads/releases/beta/3-alpha) - A tag named
v2(refs/tags/v2) - A tag whose name starts with
v1., likev1.9(refs/tags/v1.9)
on:
push:
# Sequence of patterns matched against refs/heads
branches-ignore:
- 'mona/octocat'
- 'releases/**-alpha'
# Sequence of patterns matched against refs/tags
tags-ignore:
- v2
- v1.*
Example: Including and excluding branches and tags
You can't use branches and branches-ignore to filter the same event in a single workflow. Similarly, you can't use tags and tags-ignore to filter the same event in a single workflow. If you want to both include and exclude branch or tag patterns for a single event, use the branches or tags filter along with the ! character to indicate which branches or tags should be excluded.
If you define a branch with the ! character, you must also define at least one branch without the ! character. If you only want to exclude branches, use branches-ignore instead. Similarly, if you define a tag with the ! character, you must also define at least one tag without the ! character. If you only want to exclude tags, use tags-ignore instead.
The order that you define patterns matters.
- A matching negative pattern (prefixed with
!) after a positive match will exclude the Git ref. - A matching positive pattern after a negative match will include the Git ref again.
The following workflow will run on pushes to releases/10 or releases/beta/mona, but not on releases/10-alpha or releases/beta/3-alpha because the negative pattern !releases/**-alpha follows the positive pattern.
on:
push:
branches:
- 'releases/**'
- '!releases/**-alpha'
on.<push|pull_request|pull_request_target>.<paths|paths-ignore>
When using the push and pull_request events, you can configure a workflow to run based on what file paths are changed. Path filters are not evaluated for pushes of tags.
Use the paths filter when you want to include file path patterns or when you want to both include and exclude file path patterns. Use the paths-ignore filter when you only want to exclude file path patterns. You cannot use both the paths and paths-ignore filters for the same event in a workflow. If you want to both include and exclude path patterns for a single event, use the paths filter prefixed with the ! character to indicate which paths should be excluded.
Note
The order that you define paths patterns matters:
- A matching negative pattern (prefixed with
!) after a positive match will exclude the path. - A matching positive pattern after a negative match will include the path again.
If you define both branches/branches-ignore and paths/paths-ignore, the workflow will only run when both filters are satisfied.
The paths and paths-ignore keywords accept glob patterns that use the * and ** wildcard characters to match more than one path name. For more information, see the Workflow syntax for GitHub Actions.
Example: Including paths
If at least one path matches a pattern in the paths filter, the workflow runs. For example, the following workflow would run anytime you push a JavaScript file (.js).
on:
push:
paths:
- '**.js'
You should not use path or branch filtering to skip workflow runs if the workflow is required. For more information, see Skipping workflow runs and Required workflows.
If a workflow is skipped due to path filtering, branch filtering, or a commit message, then checks associated with that workflow will remain in a "Pending" state. A pull request that requires those checks to be successful will be blocked from merging.
Example: Excluding paths
When all the path names match patterns in paths-ignore, the workflow will not run. If any path names do not match patterns in paths-ignore, even if some path names match the patterns, the workflow will run.
A workflow with the following path filter will only run on push events that include at least one file outside the docs directory at the root of the repository.
on:
push:
paths-ignore:
- 'docs/**'
Example: Including and excluding paths
You cannot use paths and paths-ignore to filter the same event in a single workflow. If you want to both include and exclude path patterns for a single event, use the paths filter prefixed with the ! character to indicate which paths should be excluded.
If you define a path with the ! character, you must also define at least one path without the ! character. If you only want to exclude paths, use paths-ignore instead.
The order that you define paths patterns matters:
- A matching negative pattern (prefixed with
!) after a positive match will exclude the path. - A matching positive pattern after a negative match will include the path again.
This example runs anytime the push event includes a file in the sub-project directory or its subdirectories, unless the file is in the sub-project/docs directory. For example, a push that changed sub-project/index.js or sub-project/src/index.js will trigger a workflow run, but a push changing only sub-project/docs/readme.md will not.
on:
push:
paths:
- 'sub-project/**'
- '!sub-project/docs/**'
Git diff comparisons
Note
If you push more than 1,000 commits, or if GitHub does not generate the diff due to a timeout, the workflow will always run.
The filter determines if a workflow should run by evaluating the changed files and running them against the paths-ignore or paths list. If there are no files changed, the workflow will not run.
GitHub generates the list of changed files using two-dot diffs for pushes and three-dot diffs for pull requests:
- Pull requests: Three-dot diffs are a comparison between the most recent version of the topic branch and the commit where the topic branch was last synced with the base branch.
- Pushes to existing branches: A two-dot diff compares the head and base SHAs directly with each other.
- Pushes to new branches: A two-dot diff against the parent of the ancestor of the deepest commit pushed.
Diffs are limited to 300 files. If there are files changed that aren't matched in the first 300 files returned by the filter, the workflow will not run. You may need to create more specific filters so that the workflow will run automatically.
For more information, see About comparing branches in pull requests.
on.schedule
You can use on.schedule to define a time schedule for your workflows. You can schedule a workflow to run at specific UTC times using POSIX cron syntax. Scheduled workflows run on the latest commit on the default or base branch. The shortest interval you can run scheduled workflows is once every 5 minutes.
This example triggers the workflow every day at 5:30 and 17:30 UTC:
on:
schedule:
# * is a special character in YAML so you have to quote this string
- cron: '30 5,17 * * *'
A single workflow can be triggered by multiple schedule events. You can access the schedule event that triggered the workflow through the github.event.schedule context. This example triggers the workflow to run at 5:30 UTC every Monday-Thursday, but skips the Not on Monday or Wednesday step on Monday and Wednesday.
on:
schedule:
- cron: '30 5 * * 1,3'
- cron: '30 5 * * 2,4'
jobs:
test_schedule:
runs-on: ubuntu-latest
steps:
- name: Not on Monday or Wednesday
if: github.event.schedule != '30 5 * * 1,3'
run: echo "This step will be skipped on Monday and Wednesday"
- name: Every time
run: echo "This step will always run"
For more information about cron syntax, see Events that trigger workflows.
on.workflow_call
Use on.workflow_call to define the inputs and outputs for a reusable workflow. You can also map the secrets that are available to the called workflow. For more information on reusable workflows, see Reusing workflows.
on.workflow_call.inputs
When using the workflow_call keyword, you can optionally specify inputs that are passed to the called workflow from the caller workflow. For more information about the workflow_call keyword, see Events that trigger workflows.
In addition to the standard input parameters that are available, on.workflow_call.inputs requires a type parameter. For more information, see on.workflow_call.inputs.<input_id>.type.
If a default parameter is not set, the default value of the input is false for a boolean, 0 for a number, and "" for a string.
Within the called workflow, you can use the inputs context to refer to an input. For more information, see Accessing contextual information about workflow runs.
If a caller workflow passes an input that is not specified in the called workflow, this results in an error.
Example of on.workflow_call.inputs
on:
workflow_call:
inputs:
username:
description: 'A username passed from the caller workflow'
default: 'john-doe'
required: false
type: string
jobs:
print-username:
runs-on: ubuntu-latest
steps:
- name: Print the input name to STDOUT
run: echo The username is ${{ inputs.username }}
For more information, see Reusing workflows.
on.workflow_call.inputs.<input_id>.type
Required if input is defined for the on.workflow_call keyword. The value of this parameter is a string specifying the data type of the input. This must be one of: boolean, number, or string.
on.workflow_call.outputs
A map of outputs for a called workflow. Called workflow outputs are available to all downstream jobs in the caller workflow. Each output has an identifier, an optional description, and a value. The value must be set to the value of an output from a job within the called workflow.
In the example below, two outputs are defined for this reusable workflow: workflow_output1 and workflow_output2. These are mapped to outputs called job_output1 and job_output2, both from a job called my_job.
Example of on.workflow_call.outputs
on:
workflow_call:
# Map the workflow outputs to job outputs
outputs:
workflow_output1:
description: "The first job output"
value: ${{ jobs.my_job.outputs.job_output1 }}
workflow_output2:
description: "The second job output"
value: ${{ jobs.my_job.outputs.job_output2 }}
For information on how to reference a job output, see jobs.<job_id>.outputs. For more information, see Reusing workflows.
on.workflow_call.secrets
A map of the secrets that can be used in the called workflow.
Within the called workflow, you can use the secrets context to refer to a secret.
Note
If you are passing the secret to a nested reusable workflow, then you must use jobs.<job_id>.secrets again to pass the secret. For more information, see Reusing workflows.
If a caller workflow passes a secret that is not specified in the called workflow, this results in an error.
Example of on.workflow_call.secrets
on:
workflow_call:
secrets:
access-token:
description: 'A token passed from the caller workflow'
required: false
jobs:
pass-secret-to-action:
runs-on: ubuntu-latest
steps:
# passing the secret to an action
- name: Pass the received secret to an action
uses: ./.github/actions/my-action
with:
token: ${{ secrets.access-token }}
# passing the secret to a nested reusable workflow
pass-secret-to-workflow:
uses: ./.github/workflows/my-workflow
secrets:
token: ${{ secrets.access-token }}
on.workflow_call.secrets.<secret_id>
A string identifier to associate with the secret.
on.workflow_call.secrets.<secret_id>.required
A boolean specifying whether the secret must be supplied.
on.workflow_run.<branches|branches-ignore>
When using the workflow_run event, you can specify what branches the triggering workflow must run on in order to trigger your workflow.
The branches and branches-ignore filters accept glob patterns that use characters like *, **, +, ?, ! and others to match more than one branch name. If a name contains any of these characters and you want a literal match, you need to escape each of these special characters with \. For more information about glob patterns, see the Workflow syntax for GitHub Actions.
For example, a workflow with the following trigger will only run when the workflow named Build runs on a branch whose name starts with releases/:
on:
workflow_run:
workflows: ["Build"]
types: [requested]
branches:
- 'releases/**'
A workflow with the following trigger will only run when the workflow named Build runs on a branch that is not named canary:
on:
workflow_run:
workflows: ["Build"]
types: [requested]
branches-ignore:
- "canary"
You cannot use both the branches and branches-ignore filters for the same event in a workflow. If you want to both include and exclude branch patterns for a single event, use the branches filter along with the ! character to indicate which branches should be excluded.
The order that you define patterns matters.
- A matching negative pattern (prefixed with
!) after a positive match will exclude the branch. - A matching positive pattern after a negative match will include the branch again.
For example, a workflow with the following trigger will run when the workflow named Build runs on a branch that is named releases/10 or releases/beta/mona but will not releases/10-alpha, releases/beta/3-alpha, or main.
on:
workflow_run:
workflows: ["Build"]
types: [requested]
branches:
- 'releases/**'
- '!releases/**-alpha'
on.workflow_dispatch
When using the workflow_dispatch event, you can optionally specify inputs that are passed to the workflow.
This trigger only receives events when the workflow file is on the default branch.
on.workflow_dispatch.inputs
The triggered workflow receives the inputs in the inputs context. For more information, see Contexts.
Note
- The workflow will also receive the inputs in the
github.event.inputscontext. The information in theinputscontext andgithub.event.inputscontext is identical except that theinputscontext preserves Boolean values as Booleans instead of converting them to strings. Thechoicetype resolves to a string and is a single selectable option. - The maximum number of top-level properties for
inputsis 10. - The maximum payload for
inputsis 65,535 characters.
Example of on.workflow_dispatch.inputs
on:
workflow_dispatch:
inputs:
logLevel:
description: 'Log level'
required: true
default: 'warning'
type: choice
options:
- info
- warning
- debug
print_tags:
description: 'True to print to STDOUT'
required: true
type: boolean
tags:
description: 'Test scenario tags'
required: true
type: string
environment:
description: 'Environment to run tests against'
type: environment
required: true
jobs:
print-tag:
runs-on: ubuntu-latest
if: ${{ inputs.print_tags }}
steps:
- name: Print the input tag to STDOUT
run: echo The tags are ${{ inputs.tags }}
on.workflow_dispatch.inputs.<input_id>.required
A boolean specifying whether the input must be supplied.
on.workflow_dispatch.inputs.<input_id>.type
The value of this parameter is a string specifying the data type of the input. This must be one of: boolean, choice, number, environment or string.
permissions
You can use permissions to modify the default permissions granted to the GITHUB_TOKEN, adding or removing access as required, so that you only allow the minimum required access. For more information, see Automatic token authentication.
You can use permissions either as a top-level key, to apply to all jobs in the workflow, or within specific jobs. When you add the permissions key within a specific job, all actions and run commands within that job that use the GITHUB_TOKEN gain the access rights you specify. For more information, see jobs.<job_id>.permissions.
For each of the available permissions, shown in the table below, you can assign one of the access levels: read (if applicable), write, or none. write includes read. If you specify the access for any of these permissions, all of those that are not specified are set to none.
Available permissions and details of what each allows an action to do:
| Permission | Allows an action using GITHUB_TOKEN to |
|---|---|
actions | Work with GitHub Actions. For example, actions: write permits an action to cancel a workflow run. For more information, see Permissions required for GitHub Apps. |
checks | Work with check runs and check suites. For example, checks: write permits an action to create a check run. For more information, see Permissions required for GitHub Apps. |
contents | Work with the contents of the repository. For example, contents: read permits an action to list the commits, and contents: write allows the action to create a release. For more information, see Permissions required for GitHub Apps. |
deployments | Work with deployments. For example, deployments: write permits an action to create a new deployment. For more information, see Permissions required for GitHub Apps. |
discussions | Work with GitHub Discussions. For example, discussions: write permits an action to close or delete a discussion. For more information, see Using the GraphQL API for Discussions. |
issues | Work with issues. For example, issues: write permits an action to add a comment to an issue. For more information, see Permissions required for GitHub Apps. |
packages | Work with GitHub Packages. For example, packages: write permits an action to upload and publish packages on GitHub Packages. For more information, see About permissions for GitHub Packages. |
pages | Work with GitHub Pages. For example, pages: write permits an action to request a GitHub Pages build. For more information, see Permissions required for GitHub Apps. |
pull-requests | Work with pull requests. For example, pull-requests: write permits an action to add a label to a pull request. For more information, see Permissions required for GitHub Apps. |
repository-projects | Work with GitHub projects (classic). For example, repository-projects: write permits an action to add a column to a project (classic). For more information, see Permissions required for GitHub Apps. |
security-events | Work with GitHub code scanning and Dependabot alerts. For example, security-events: read permits an action to list the Dependabot alerts for the repository, and security-events: write allows an action to update the status of a code scanning alert. For more information, see Repository permissions for 'Code scanning alerts' and Repository permissions for 'Dependabot alerts' in "Permissions required for GitHub Apps." |
statuses | Work with commit statuses. For example, statuses:read permits an action to list the commit statuses for a given reference. For more information, see Permissions required for GitHub Apps. |
Defining access for the GITHUB_TOKEN scopes
You can define the access that the GITHUB_TOKEN will permit by specifying read, write, or none as the value of the available permissions within the permissions key.
permissions:
actions: read|write|none
checks: read|write|none
contents: read|write|none
deployments: read|write|none
issues: read|write|none
discussions: read|write|none
packages: read|write|none
pages: read|write|none
pull-requests: read|write|none
repository-projects: read|write|none
security-events: read|write|none
statuses: read|write|none
If you specify the access for any of these permissions, all of those that are not specified are set to none.
You can use the following syntax to define one of read-all or write-all access for all of the available permissions:
permissions: read-all
permissions: write-all
You can use the following syntax to disable permissions for all of the available permissions:
permissions: {}
Changing the permissions in a forked repository
You can use the permissions key to add and remove read permissions for forked repositories, but typically you can't grant write access. The exception to this behavior is where an admin user has selected the Send write tokens to workflows from pull requests option in the GitHub Actions settings. For more information, see Managing GitHub Actions settings for a repository.
Setting the GITHUB_TOKEN permissions for all jobs in a workflow
You can specify permissions at the top level of a workflow, so that the setting applies to all jobs in the workflow.
Example: Setting the GITHUB_TOKEN permissions for an entire workflow
This example shows permissions being set for the GITHUB_TOKEN that will apply to all jobs in the workflow. All permissions are granted read access.
name: "My workflow"
on: [ push ]
permissions: read-all
jobs:
...
env
A map of variables that are available to the steps of all jobs in the workflow. You can also set variables that are only available to the steps of a single job or to a single step. For more information, see jobs.<job_id>.env and jobs.<job_id>.steps[*].env.
Variables in the env map cannot be defined in terms of other variables in the map.
When more than one environment variable is defined with the same name, GitHub uses the most specific variable. For example, an environment variable defined in a step will override job and workflow environment variables with the same name, while the step executes. An environment variable defined for a job will override a workflow variable with the same name, while the job executes.
Example of env
env:
SERVER: production
defaults
Use defaults to create a map of default settings that will apply to all jobs in the workflow. You can also set default settings that are only available to a job. For more information, see jobs.<job_id>.defaults.
When more than one default setting is defined with the same name, GitHub uses the most specific default setting. For example, a default setting defined in a job will override a default setting that has the same name defined in a workflow.
defaults.run
You can use defaults.run to provide default shell and working-directory options for all run steps in a workflow. You can also set default settings for run that are only available to a job. For more information, see jobs.<job_id>.defaults.run. You cannot use contexts or expressions in this keyword.
When more than one default setting is defined with the same name, GitHub uses the most specific default setting. For example, a default setting defined in a job will override a default setting that has the same name defined in a workflow.
Example: Set the default shell and working directory
defaults:
run:
shell: bash
working-directory: ./scripts
defaults.run.shell
Use shell to define the shell for a step. This keyword can reference several contexts. For more information, see Contexts.
| Supported platform | shell parameter | Description | Command run internally |
|---|---|---|---|
| Linux / macOS | unspecified | The default shell on non-Windows platforms. Note that this runs a different command to when bash is specified explicitly. If bash is not found in the path, this is treated as sh. | bash -e {0} |
| All | bash | The default shell on non-Windows platforms with a fallback to sh. When specifying a bash shell on Windows, the bash shell included with Git for Windows is used. | bash --noprofile --norc -eo pipefail {0} |
| All | pwsh | The PowerShell Core. GitHub appends the extension .ps1 to your script name. | pwsh -command ". '{0}'" |
| All | python | Executes the python command. | python {0} |
| Linux / macOS | sh | The fallback behavior for non-Windows platforms if no shell is provided and bash is not found in the path. | sh -e {0} |
| Windows | cmd | GitHub appends the extension .cmd to your script name and substitutes for {0}. | %ComSpec% /D /E:ON /V:OFF /S /C "CALL "{0}"". |
| Windows | pwsh | This is the default shell used on Windows. The PowerShell Core. GitHub appends the extension .ps1 to your script name. If your self-hosted Windows runner does not have PowerShell Core installed, then PowerShell Desktop is used instead. | pwsh -command ". '{0}'". |
| Windows | powershell | The PowerShell Desktop. GitHub appends the extension .ps1 to your script name. | powershell -command ". '{0}'". |
When more than one default setting is defined with the same name, GitHub uses the most specific default setting. For example, a default setting defined in a job will override a default setting that has the same name defined in a workflow.
defaults.run.working-directory
Use working-directory to define the working directory for the shell for a step. This keyword can reference several contexts. For more information, see Contexts.
Tip
Ensure the working-directory you assign exists on the runner before you run your shell in it.
When more than one default setting is defined with the same name, GitHub uses the most specific default setting. For example, a default setting defined in a job will override a default setting that has the same name defined in a workflow.
concurrency
Use concurrency to ensure that only a single job or workflow using the same concurrency group will run at a time. A concurrency group can be any string or expression. The expression can only use github, inputs and vars contexts. For more information about expressions, see Evaluate expressions in workflows and actions.
You can also specify concurrency at the job level. For more information, see jobs.<job_id>.concurrency.
This means that there can be at most one running and one pending job in a concurrency group at any time. When a concurrent job or workflow is queued, if another job or workflow using the same concurrency group in the repository is in progress, the queued job or workflow will be pending. Any existing pending job or workflow in the same concurrency group, if it exists, will be canceled and the new queued job or workflow will take its place.
To also cancel any currently running job or workflow in the same concurrency group, specify cancel-in-progress: true. To conditionally cancel currently running jobs or workflows in the same concurrency group, you can specify cancel-in-progress as an expression with any of the allowed expression contexts.
Note
- The concurrency group name is case insensitive. For example,
prodandProdwill be treated as the same concurrency group. - Ordering is not guaranteed for jobs or workflow runs using concurrency groups. Jobs or workflow runs in the same concurrency group are handled in an arbitrary order.
Example: Using concurrency and the default behavior
The default behavior of GitHub Actions is to allow multiple jobs or workflow runs to run concurrently. The concurrency keyword allows you to control the concurrency of workflow runs.
For example, you can use the concurrency keyword immediately after where trigger conditions are defined to limit the concurrency of entire workflow runs for a specific branch:
on:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
You can also limit the concurrency of jobs within a workflow by using the concurrency keyword at the job level:
on:
push:
branches:
- main
jobs:
job-1:
runs-on: ubuntu-latest
concurrency:
group: example-group
cancel-in-progress: true
Example: Concurrency groups
Concurrency groups provide a way to manage and limit the execution of workflow runs or jobs that share the same concurrency key.
The concurrency key is used to group workflows or jobs together into a concurrency group. When you define a concurrency key, GitHub Actions ensures that only one workflow or job with that key runs at any given time. If a new workflow run or job starts with the same concurrency key, GitHub Actions will cancel any workflow or job already running with that key. The concurrency key can be a hard-coded string, or it can be a dynamic expression that includes context variables.
It is possible to define concurrency conditions in your workflow so that the workflow or job is part of a concurrency group.
This means that when a workflow run or job starts, GitHub will cancel any workflow runs or jobs that are already in progress in the same concurrency group. This is useful in scenarios where you want to prevent parallel runs for a certain set of a workflows or jobs, such as the ones used for deployments to a staging environment, in order to prevent actions that could cause conflicts or consume more resources than necessary.
In this example, job-1 is part of a concurrency group named staging_environment. This means that if a new run of job-1 is triggered, any runs of the same job in the staging_environment concurrency group that are already in progress will be cancelled.
jobs:
job-1:
runs-on: ubuntu-latest
concurrency:
group: staging_environment
cancel-in-progress: true
Alternatively, using a dynamic expression such as concurrency: ci-${{ github.ref }} in your workflow means that the workflow or job would be part of a concurrency group named ci- followed by the reference of the branch or tag that triggered the workflow. In this example, if a new commit is pushed to the main branch while a previous run is still in progress, the previous run will be cancelled and the new one will start:
on:
push:
branches:
- main
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
Example: Using concurrency to cancel any in-progress job or run
To use concurrency to cancel any in-progress job or run in GitHub Actions, you can use the concurrency key with the cancel-in-progress option set to true:
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
Note that in this example, without defining a particular concurrency group, GitHub Actions will cancel any in-progress run of the job or workflow.
Example: Using a fallback value
If you build the group name with a property that is only defined for specific events, you can use a fallback value. For example, github.head_ref is only defined on pull_request events. If your workflow responds to other events in addition to pull_request events, you will need to provide a fallback to avoid a syntax error. The following concurrency group cancels in-progress jobs or runs on pull_request events only; if github.head_ref is undefined, the concurrency group will fallback to the run ID, which is guaranteed to be both unique and defined for the run.
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
Example: Only cancel in-progress jobs or runs for the current workflow
If you have multiple workflows in the same repository, concurrency group names must be unique across workflows to avoid canceling in-progress jobs or runs from other workflows. Otherwise, any previously in-progress or pending job will be canceled, regardless of the workflow.
To only cancel in-progress runs of the same workflow, you can use the github.workflow property to build the concurrency group:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Example: Only cancel in-progress jobs on specific branches
If you would like to cancel in-progress jobs on certain branches but not on others, you can use conditional expressions with cancel-in-progress. For example, you can do this if you would like to cancel in-progress jobs on development branches but not on release branches.
To only cancel in-progress runs of the same workflow when not running on a release branch, you can set cancel-in-progress to an expression similar to the following:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ !contains(github.ref, 'release/')}}
In this example, multiple pushes to a release/1.2.3 branch would not cancel in-progress runs. Pushes to another branch, such as main, would cancel in-progress runs.