Running jobs on specific branches with GitHub Actions is a common scenario implemented by DevOps and SRE professionals. This allows you to control which branches trigger specific jobs within your workflows. This can be important for maintaining efficient CI/CD processes, especially if you want tests to run on every branch while restricting deployment actions to only the main branch. This article explains how to configure several different methods of running GitHub Actions workflow jobs on specific branches in the repo.
Table of Contents
Setting up Branch-Specific Triggers
One of the key features of GitHub Actions is the ability to fine-tune when and where your workflows run by setting up branch-specific triggers. This functionality helps with maintaining an organized and efficient CI/CD pipeline, as it allows you to control the execution of workflows based on the branch involved in the event. Whether you’re pushing code, creating pull requests, or merging branches, you can define rules that determine which branches should trigger specific workflows.
Branch-specific triggers provide several benefits:
- Targeted Workflow Execution: Ensuring that only relevant branches trigger certain workflows helps in managing resources efficiently and avoids unnecessary builds or deployments.
- Enhanced Control: By specifying branches, you can have more control over your development and release processes, making it easier to enforce branch policies and workflows tailored to different stages of your project.
- Improved Stability: Running workflows only on specific branches like
mainordevelopreduces the risk of errors in critical branches, as workflows can include thorough testing and deployment steps that are not needed for feature branches.
Basic Branch Filtering
Filtering workflows to run only on specific branches is a fundamental feature of GitHub Actions. This allows you to control when and where your workflows are triggered, ensuring that jobs only run in the intended branches. By doing so, you can maintain a clean, efficient CI/CD process tailored to your development needs.
Branch filtering in GitHub Actions is configured using the branches keyword within the on field of your workflow YAML file. This configuration dictates that the workflow should only trigger on specified branches.
To trigger a workflow only on pushes to the main branch and pull requests targeting main, your workflow YAML configuration would look like this:
on:
push:
branches:
- main
pull_request:
branches:
- main
In this example:
- The workflow will trigger only when a push or pull request targets the
mainbranch.
This ensures that actions like tests, builds, and deployments are executed exclusively for changes in the main branch, keeping your CI/CD pipeline focused and relevant.
Multiple Branch Filters
For projects with multiple important branches, you can set up workflows to run on several branches by listing them under the branches key. This is particularly useful for release branches, hotfix branches, or any other important branch patterns.
on:
push:
branches:
- main
- dev
- 'feature/**'
pull_request:
branches:
- main
- dev
- 'feature/**'
In this example:
- The workflow will trigger on pushes and pull requests to the
main,dev, and any branch that matches thefeature/**pattern. - Using the wildcard pattern
feature/**enables the workflow to trigger for all branches starting withfeature/, such asfeature/login-pageorfeature/new-api.
Configuring Scheduled GitHub Actions Triggers: If you’re interested in learning more about configuring scheduled GitHub Actions workflows using CRON expressions, I recommend you read the “Configure Scheduled Trigger in GitHub Actions using Cron expression” article.
Using Wildcards
Wildcards provide a flexible way to manage workflow triggers in GitHub Actions, allowing you to specify patterns for branches rather than listing each branch individually. This is particularly useful in projects with numerous branches following a naming convention. Wildcards simplify the YAML configuration and reduce the need for frequent updates to the workflow file as new branches are created.
Basic Wildcard Usage
Wildcards in GitHub Actions are used to match multiple branch names with a single pattern. The most commonly used wildcard characters are * and **.
If you need to include multiple branches or patterns, you can use wildcards:
on:
push:
branches:
- main
- 'feature/*'
pull_request:
branches:
- main
- 'feature/*'
In this example:
- The workflow will trigger on any push or pull request to branches that start with
feature/, such asfeature/login,feature/signup, orfeature/123.
The * wildcard matches any sequence of characters within a single directory level.
Advanced Wildcard Usage
For more complex scenarios, the ** wildcard can be used to match multiple directory levels. This is particularly useful when your branch naming includes nested structures.
on:
push:
branches:
- 'releases/**'
pull_request:
branches:
- 'releases/**'
In this example:
- The workflow triggers on any push or pull request to branches within the
releases/directory, regardless of the depth of the directory structure. For example, it matchesreleases/v1.0,releases/v1.0/patch1, andreleases/v2.1/feature.
The ** wildcard matches any sequence of characters across multiple directory levels.
Combining Wildcards with Specific Branches
You can combine wildcard patterns with specific branch names to create a comprehensive branch filter configuration. This approach provides both flexibility and precision.
on:
push:
branches:
- main
- develop
- 'feature/*'
- 'hotfix/**'
pull_request:
branches:
- main
- develop
- 'feature/*'
- 'hotfix/**'
In this configuration:
- The workflow triggers on pushes and pull requests to the
mainanddevelopbranches. - It also triggers on any branch that matches the
feature/*andhotfix/**patterns, allowing for flexible inclusion of feature and hotfix branches at various levels.
Using Branch Ignoring
In contrast to including specific branches, you can also set up workflows to ignore certain branches using the branches-ignore keyword. This can be useful when you want the workflow to run on all branches except a few specified ones.
on:
push:
branches-ignore:
- experimental
pull_request:
branches-ignore:
- experimental
In this example:
- The workflow will run on pushes and pull requests to all branches except the
experimentalbranch. - This approach is beneficial when you have branches that are not ready for the usual CI/CD processes, such as experimental or feature branches that are under active development and frequent changes.
Combining Branch Filters and Ignoring
Combining branch filters and ignoring specific branches provides a powerful and flexible way to control when and how your workflows are triggered. This combination allows you to fine-tune your CI/CD processes to suit the unique needs of your project, ensuring that only relevant changes invoke the necessary workflows. By using both branches and branches-ignore keywords in your workflow configuration, you can precisely target or exclude branches as required.
on:
push:
branches:
- '*'
branches-ignore:
- 'temp/**'
pull_request:
branches:
- '*'
branches-ignore:
- 'temp/**'
In this example:
- The workflow will trigger on pushes and pull requests to all branches except those under the
temp/prefix. - The
'*'wildcard indicates all branches, whilebranches-ignoreexcludes specific patterns, offering a flexible way to manage workflow triggers.
Using wildcards in GitHub Actions is a powerful way to streamline and manage your workflow triggers efficiently. By leveraging both single (*) and double (**) wildcards, you can create flexible and dynamic branch filters that reduce the need for constant updates to your workflow configuration. This approach simplifies the maintenance of your CI/CD pipeline and ensures that your workflows are only triggered by relevant branches, enhancing overall productivity and workflow management.
Using Workflow Dispatch for Manual Triggers
Sometimes you might want to manually trigger workflows. GitHub Actions supports this through adding a workflow_dispatch event to the YAML configuration. This allows you to trigger the workflow manually using the web interface or the GitHub API.
Here’s an example configuration:
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
required: true
default: 'production'
push:
branches:
- main
This configuration allows you to manually trigger the workflow from the Actions tab in GitHub, providing inputs like the target Environment configured in GitHub.
More Information: If you’re interested in learning a bit more about manual GitHub Actions Triggers, then I recommend you go read the “Configuring Manual Triggers in GitHub Actions with
workflow_dispatch” article.
Defining Jobs and Dependencies
In GitHub Actions, jobs within a workflow run in parallel by default. However, you can define dependencies to run jobs sequentially. This is particularly useful when you want to run tests first and deploy only if the tests pass.
Sequential Job Execution
Here’s how you can set up two jobs where the deployment job runs only if the tests pass:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests
run: npm test
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Deploy
run: ./deploy.sh
In this configuration:
- The
testjob runs on every push or pull request. - The
deployjob depends on thetestjob (needs: test), meaning it will only run if thetestjob completes successfully. - The
deployjob includes a condition to ensure it only runs for themainbranch (if: github.ref == 'refs/heads/main').
Conditional Job Execution
You can use conditional expressions to control whether a job runs. This is useful for ensuring jobs only execute under certain conditions, such as when a pull request is merged.
on:
pull_request:
branches:
- dev
types:
- closed
jobs:
deploy:
if: ${{ github.event.pull_request.merged == true }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Deploy
run: ./deploy.sh
Advanced Features and Best Practices
These features not only simplify complex automation but also enhance the robustness and efficiency of your CI/CD pipelines. From sharing data between jobs to utilizing contexts and expressions, these advanced capabilities enable you to build sophisticated and highly customizable workflows. Let’s look at some more tools and techniques to elevate your GitHub Actions configurations to the next level.
Sharing Data Between Jobs
GitHub Actions supports sharing data between jobs in a workflow. This can simplify your YAML files and create more complex automations.
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v2
with:
name: build
path: build/
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download build artifacts
uses: actions/download-artifact@v2
with:
name: build
- name: Deploy
run: ./deploy.sh
Context and Expressions
Use contexts and expressions to access information about workflow runs, runner environments, jobs, and steps. Contexts can be particularly powerful when used in conditionals.
if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
Environment-Specific Workloads
When working on projects that require multiple environments, such as development, staging, and production, GitHub Actions provides robust features to manage these environments effectively. By creating environment-specific workflows, you can define rules and secrets tailored to each environment, ensuring smooth transitions and maintaining security and consistency across your deployment pipeline.
Creating and Managing Environments
GitHub allows you to create environments directly in your repository settings. Each environment can have its own set of protection rules and secrets. This segregation is vital for managing different stages of your application lifecycle, from development to production.
Steps to Create Environments:
- Navigate to your repository on GitHub.
- Go to the “Settings” tab.
- Select “Environments” from the left sidebar.
- Click “New environment” and name it (e.g.,
development,staging,production). - Add necessary environment protection rules and secrets.
Protection rules can include requirements like manual approvals for deployments, restrictions on which branches can deploy to the environment, and more. Secrets are securely stored variables, such as API keys or database credentials, that your workflows can use without exposing them in your codebase.
Referencing Environments in Workflows
Once environments are set up, you can reference them in your workflow files to apply environment-specific configurations. This helps in maintaining a clean and organized deployment process.
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Deploy to production
run: ./deploy.sh
env:
API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
In this example:
- The
deployjob runs in theproductionenvironment. - It accesses a secret specific to the
productionenvironment using${{ secrets.PRODUCTION_API_KEY }}.
Environment Protection Rules
Protection rules enhance the security and integrity of your deployment process. You can set rules that require specific reviewers to approve deployments, limit which branches can trigger deployments, and enforce waiting periods.
Example Protection Rules:
- Required Reviewers: Ensure that specific team members must approve a workflow run before it can proceed.
- Branch Restrictions: Limit deployments to specific branches, preventing unauthorized code from being deployed.
- Wait Timer: Introduce mandatory wait times before a deployment can occur, providing a buffer for additional checks or reviews.
Environment-Specific Deployment Strategies
Different environments often require different deployment strategies. For instance, your development environment might use continuous deployment to quickly reflect changes, while production might use a more controlled, manual process.
Continuous Deployment to Development:
jobs:
deploy:
runs-on: ubuntu-latest
environment: development
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Deploy to development
run: ./deploy-dev.sh
env:
API_KEY: ${{ secrets.DEVELOPMENT_API_KEY }}
Manual Deployment to Production:
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Approval
uses: hmarr/auto-approve-action@v2.0.0
- name: Deploy to production
run: ./deploy-prod.sh
env:
API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
In these examples:
- The development deployment runs automatically upon code changes.
- The production deployment requires manual approval before proceeding.
Using environment-specific workflows in GitHub Actions allows you to tailor your CI/CD processes to different stages of your application lifecycle. By leveraging environment protection rules and secrets, you can ensure secure, efficient, and consistent deployments across development, staging, and production environments. This approach not only enhances your deployment pipeline’s robustness but also provides a scalable framework for managing complex projects with multiple environments.
Summary
Configuring GitHub Actions to run jobs on specific branches can greatly streamline your CI/CD pipeline. By using branch filters and job dependencies, you can ensure that tests run across all branches while deployments are restricted to the main branch or other specific branches. This configuration helps maintain code quality and stability, making your development process more efficient and reliable.
Implementing these configurations in your workflows will give you precise control over your CI/CD processes, ensuring that each job runs exactly when and where it’s supposed to. Happy automating!
Original Article Source: Configuring GitHub Actions to Run Jobs on Specific Branches written by Chris Pietschmann (If you're reading this somewhere other than Build5Nines.com, it was republished without permission.)
Microsoft Azure Regions: Interactive Map of Global Datacenters
Create Azure Architecture Diagrams with Microsoft Visio
Unlock GitHub Copilot’s Full Potential: Why Every Repo Needs an AGENTS.md File
Azure Network Security Best Practices to Protect Your Cloud Infrastructure
IPv4 Address CIDR Range Reference and Calculator




