Implementing Concurrency Control
1. Setting Workflow Concurrency
| Property | Values | Description |
|---|---|---|
| concurrency | string or object |
Controls how workflows are handled when concurrent runs exist. |
Example: Basic Concurrency Configuration
name: Example Workflow
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
concurrency:
group: "build-${{ github.ref }}"
cancel-in-progress: true
steps:
- name: Checkout code
uses: actions/checkout@v4
concurrency key is defined at the job level, not workflow level.
| Field | Type | Description |
|---|---|---|
| group | string |
Defines the concurrency group. All workflows in the same group will be queued or canceled based on cancel-in-progress. |
| cancel-in-progress | boolean |
If true, cancels any in-progress workflow in the same group. Defaults to false. |
2. Defining Concurrency Group
| Property | Description | Values | Notes |
|---|---|---|---|
| concurrency.group | Defines the concurrency group for a workflow | {% raw %}${{ github.workflow }}{% endraw %} or custom string |
Used to control concurrent runs of a workflow |
| concurrency.cancel-in-progress | Cancel in-progress runs when a new run is triggered | true or false |
Defaults to false |
Example: Defining Concurrency Group
name: Example Workflow
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
steps:
- name: Checkout code
uses: actions/checkout@v4
3. Canceling In-Progress Runs
| Option | Values | Notes |
|---|---|---|
| concurrency | group: ${{ github.workflow }} |
Cancel in-progress runs in the same workflow |
| concurrency.cancel-in-progress | true |
Cancel previous runs when a new one starts |
Example: Canceling in-progress runs
name: CI
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
steps:
- name: Checkout code
uses: actions/checkout@v4
concurrency key is used to define a group of workflows that should be mutually exclusive. When cancel-in-progress is set to true, any in-progress run in the same group will be canceled when a new run starts.4. Using Branch-Based Concurrency
| Branch Type | Description | Use Case | Trigger |
|---|---|---|---|
| main | Primary branch for production code | Stable releases, deployment to production | Manual or automated on push |
| develop | Integration branch for features | Collaborative development, testing | Push or merge to develop |
| feature/<name> | Feature-specific branches | Isolated development, code review | Push to feature branch |
| release/<version> | Release preparation branches | Final testing, version tagging | Manual creation or merge from develop |
| hotfix/<name> | Emergency fixes to production | Quick bug fixes, patch releases | Push to hotfix branch |
Example: Branch Protection Rules
name: Branch Protection
on:
push:
branches:
- main
- develop
jobs:
enforce_branch_protection:
runs-on: ubuntu-latest
steps:
- name: Check branch protection rules
run: |
echo "Ensuring only allowed branches can merge to main"
# Implementation logic here
Summary of Branch-Based Concurrency
- main is for stable, production-ready code.
- develop is for ongoing feature development and integration.
- feature/<name> isolates feature development.
- release/<version> prepares for release.
- hotfix/<name> handles urgent production fixes.
5. Using PR-Based Concurrency
GitHub Actions supports concurrent workflow execution, but can be configured to limit concurrency based on pull requests (PRs) to prevent conflicts or resource contention. This is particularly useful in environments where workflows might interfere with each other.
| Option | Values | Description |
|---|---|---|
| concurrency.group | ${{ github.workflow }}-${{ github.ref }} |
Defines the concurrency group. By default, workflows in the same group are cancelled if a new workflow starts. |
| concurrency.cancel-in-progress | true |
When set to true, cancels any in-progress workflow runs in the same concurrency group. |
Example: PR-Based Concurrency Configuration
name: PR-Based Concurrency
on:
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
concurrency:
group: pr-${{ github.event.number }}
cancel-in-progress: true
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run tests
run: npm test
concurrency.group can be customized to include PR numbers or branch names to ensure that workflows for different PRs don't interfere with each other.
6. Setting Job-Level Concurrency
| Property | Values | Description |
|---|---|---|
| concurrency | string or object |
Controls the concurrency behavior for jobs in a workflow. |
Example: Basic concurrency configuration
name: Example Workflow
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
concurrency:
group: "build-${{ github.ref }}"
cancel-in-progress: true
steps:
- name: Checkout code
uses: actions/checkout@v4
concurrency property can be defined at the job level or workflow level. When set at the job level, it overrides any workflow-level concurrency settings for that specific job.
| Field | Type | Description |
|---|---|---|
| group | string |
Defines the concurrency group name. Jobs in the same group are considered part of the same concurrency set and will cancel each other if a new job starts. |
| cancel-in-progress | boolean |
If true, cancels any in-progress job in the same concurrency group when a new job is started. Defaults to false. |
Example: Using variables in concurrency group
jobs:
test:
runs-on: ubuntu-latest
concurrency:
group: "test-${{ github.ref }}-${{ github.run_id }}"
cancel-in-progress: true
7. Using Dynamic Concurrency Groups
Dynamic concurrency groups in GitHub Actions allow you to control the number of concurrent workflow runs based on runtime conditions or external factors. This is particularly useful for managing resource usage and ensuring that workflows don't overwhelm shared resources like databases or API endpoints.
| Property | Description | Values | Notes |
|---|---|---|---|
| concurrency | Defines the concurrency group for a workflow | string |
Can include variables and expressions. If not set, workflows run concurrently without restriction. |
| concurrency.cancel-in-progress | Controls whether to cancel in-progress runs when a new run is started | true or false |
Defaults to false. When set to true, new runs will cancel any in-progress runs in the same group. |
Example: Setting up a Dynamic Concurrency Group
name: Dynamic Concurrency Example
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
concurrency:
group: "build-${{ github.ref }}"
cancel-in-progress: true
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run build
run: echo "Building..."
concurrency.group can use context variables like github.ref, github.head_ref, or github.sha to dynamically create unique groups per branch or commit.
cancel-in-progress to true can lead to race conditions or incomplete builds if not carefully managed. Ensure that your workflows are resilient to cancellation.
8. Preventing Parallel Deployments
Parallel deployments can lead to race conditions, inconsistent states, or resource conflicts. GitHub Actions provides several mechanisms to prevent concurrent deployments and ensure controlled execution.
| Mechanism | Description | Usage |
|---|---|---|
| concurrency | Controls the concurrency of workflow runs. If a workflow is already running, subsequent runs are queued or canceled. | |
Example: Using Concurrency to Prevent Parallel Deployments
name: Deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
concurrency:
group: "deployment"
cancel-in-progress: true
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Deploy to production
run: echo "Deploying..."
concurrency key ensures that only one deployment job can run at a time within the same group. Setting cancel-in-progress to true cancels any in-progress jobs in the same group.
Best Practices for Concurrency Control
- Use a unique
groupname per deployment environment (e.g.,deployment-staging,deployment-production) to isolate workflows. - Enable
cancel-in-progressto prevent outdated deployments from running. - Combine concurrency with
needsorifconditions to enforce deployment order or dependencies.
9. Queuing Workflow Runs
GitHub Actions allows queuing of workflow runs when the maximum concurrency limit is reached. This ensures that workflows are not skipped and instead wait in a queue until resources become available.
| Property | Description | Default Value |
|---|---|---|
| concurrency | Controls the concurrency of workflow runs. When set, only one run from the same workflow can be active at a time. | None |
| concurrency.group | Defines the group name for concurrency. Runs in the same group are queued if a previous run is active. | None |
| concurrency.cancel-in-progress | When set to true, cancels any in-progress runs from the same group. | false |
Example: Configuring Concurrency
name: Example Workflow
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Checkout code
uses: actions/checkout@v4
concurrency setting is useful for preventing multiple workflow runs from running simultaneously in environments with limited resources.
cancel-in-progress to true will cancel any in-progress workflow runs from the same group, which may lead to incomplete builds.
10. Using Actor in Concurrency
| Property | Description | Example |
|---|---|---|
| actor.name | Name of the actor instance | "user-service" |
| actor.state | Current state of the actor (e.g., active, idle) |
"active" |
| actor.maxConcurrent | Maximum number of concurrent operations allowed | 5 |
Example: Actor Configuration
name: Actor Concurrency
on:
workflow_dispatch:
jobs:
run-actor:
runs-on: ubuntu-latest
steps:
- name: Initialize Actor
uses: actions/actor-init@v1
with:
actor-name: "user-service"
max-concurrent: 5
max-concurrent limits may cause job failures or throttling.
Actor Concurrency Best Practices
- Use actors to isolate stateful operations.
- Set
max-concurrentbased on system resource availability. - Monitor job execution logs for actor state transitions.
11. Handling Concurrency with Matrix
| Property | Description | Values | Notes |
|---|---|---|---|
| strategy.matrix | Defines the matrix of build configurations | { os: [ubuntu-latest, windows-latest], node-version: [14, 16, 18] } |
Each combination creates a separate job |
| strategy.matrix.include | Adds additional job configurations to the matrix | { os: macos-latest, node-version: 18, arch: arm64 } |
Useful for including special cases or experimental setups |
| strategy.matrix.exclude | Removes specific job configurations from the matrix | { os: windows-latest, node-version: 14 } |
Allows filtering out incompatible or unwanted combinations |
Example: Matrix Strategy Configuration
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [14, 16, 18]
include:
- os: macos-latest
node-version: 18
arch: arm64
exclude:
- os: windows-latest
node-version: 14
12. Monitoring Concurrent Runs
| Aspect | Description | Notes |
|---|---|---|
| concurrency | 1 |
Controls how many workflow runs can execute concurrently in a repository |
| concurrency.group | ${{ github.workflow }}-${{ github.ref }} |
Defines the group of workflows that are mutually exclusive |
| concurrency.cancel-in-progress | false |
When true, cancels in-progress runs when a new run is triggered |
Example: Configuring Concurrency Control
name: "Concurrent Workflow Control"
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
concurrency:
group: "build-${{ github.ref }}"
cancel-in-progress: true
steps:
- name: "Checkout Code"
uses: actions/checkout@v4
concurrency.group value must be unique per workflow to prevent unintended cancellation of runs.