How does deployment work in GitHub Actions?
Deployment in GitHub Actions involves workflow files defining the steps required to deliver code to specific environments. Workflows can contain jobs with various steps, such as building, testing, and deploying code, which run in a sequence defined by dependencies or can be parallelized for efficiency.
Each job can specify the environment where it should run, such as staging or production, ensuring that deployments are organized and contained in isolated contexts. GitHub Actions provides tools to manage deployment concurrency, ensuring that only one workflow runs per environment at a time. This prevents conflicts from multiple simultaneous deployments.
GitHub Actions also allows developers to set up deployment-specific configurations, like environment protection rules and secret management, enhancing the security and control of the deployment pipeline. For example, workflows can include approval requirements or specify branch restrictions to ensure only authorized changes are deployed.
Triggering a simple deployment
To initiate a deployment in GitHub Actions, workflows can be triggered by events such as a push to a specific branch, a pull request, or a manual dispatch. This variety of triggers gives developers flexibility in how and when deployments are initiated, making it possible to adapt deployment workflows to project needs.
For example, a typical setup might trigger deployments automatically when a push is made to the main branch or when a pull request to that branch is opened, synchronized, or reopened. Additionally, developers can use workflow_dispatch
to enable manual deployment triggers, allowing for manual intervention if needed.
Related content: Read our guide to Continuous Deployment
What are GitHub Actions environments?
GitHub Actions environments provide isolated contexts for safely and efficiently executing deployment workflows. They define settings or variables that control workflow execution, ensuring predictable and reproducible outcomes. By segregating deployments into distinct environments, such as development, staging, or production, developers can test changes thoroughly without risk to live systems.
Additionally, environments in GitHub Actions support environment protection rules and secret management. These features ensure that sensitive data remains secure and processes require appropriate approvals before proceeding. Controlled environments mean deployments are less prone to failure, providing a reliable framework for software delivery.
How environments relate to deployments
In GitHub Actions, environments manage and control deployment workflows by associating jobs with specific environments, such as development, staging, or production. When a workflow job that references an environment runs, GitHub creates a deployment object, which records the details of the environment in use.
This object tracks the deployment’s progress, updating its status as the workflow progresses. Key information, such as the deployment status and the environment URL, is stored in this object, which can be accessed through the GitHub REST or GraphQL APIs.
Deployment protection rules
Deployment protection rules in GitHub Actions ensure that specified conditions are met before a job referencing an environment can proceed. These rules can enforce various safeguards, such as requiring manual approval or delaying a job until conditions are satisfied. Protection rules may restrict deployments to set branches, ensuring only authorized changes reach production.
Specific reviewers can be required to approve jobs that interact with protected environments, ensuring an extra layer of scrutiny. GitHub allows up to six reviewers per environment, and users can configure these settings to prevent self-approval, ensuring that deployment decisions involve multiple stakeholders.
Environment secrets and variables
GitHub Actions environments support secure storage of secrets and variables, which are only accessible to workflow jobs that reference the corresponding environment. Secrets, such as API keys or tokens, remain protected until a reviewer approves the job for environments that require manual approval.
Variables can also be stored within environments, providing reusable values that workflow jobs can reference. These variables are accessed via the vars
context, helping developers manage configuration settings and other environment-specific data more efficiently.
Learn more in our detailed guide to GitHub Actions secrets
Tutorial: Deploying with GitHub Actions
Here’s an overview of triggering a deployment, implementing concurrency, and selecting the runner environment. These instructions are adapted from the official documentation.
Triggering a deployment
In GitHub Actions, deployments can be triggered by events like a push, a pull request, or manual intervention. This flexibility allows developers to control when and how deployments occur.
For example, the following configuration triggers a deployment when:
- A push is made to the
main
branch. - A pull request to the
main
branch is opened, synced, or reopened. - A user manually starts the deployment using the script below.
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
This setup ensures that the deployment is automated but can also be initiated manually when needed. The push
and pull_request
events help maintain a Continuous Deployment pipeline, while workflow_dispatch
provides manual control when specific deployment conditions arise.
Using concurrency
Concurrency in GitHub Actions ensures that only one deployment job or workflow from the same concurrency group is executed at a time. This mechanism prevents overlapping deployments, which could lead to conflicts or inconsistencies.
In the following example, a deployment job will be part of the production
concurrency group. If any job in this group is already running, the new job will enter a pending state. If multiple jobs are queued, only one job will run at a time, and pending jobs will be canceled when a new deployment is triggered.
name: Deployment
concurrency: production
on:
push:
branches:
- main
jobs:
deployment:
runs-on: ubuntu-latest
environment: production
steps:
- name: deploy
# deployment steps go here
In this case, only one deployment to the production
environment can run concurrently. If another deployment is triggered while one is already in progress, it will wait for the current deployment to complete or be canceled.
Concurrency can also be defined at the job level to ensure other jobs in the workflow continue running independently.
Choosing a runner
In GitHub Actions, a runner is the environment where workflows are executed. Based on project needs, users can choose between GitHub-hosted runners or self-hosted runners.
GitHub-hosted runners
GitHub-hosted runners are virtual machines (VMs) that GitHub automatically provides for each job. These runners support multiple operating systems, like Ubuntu, Windows, and macOS. They come pre-configured with a wide variety of software, making them a convenient option for most projects.
Use the runs-on
keyword in the workflow YAML file to specify a GitHub-hosted runner. Here’s an example of how to run a job on an Ubuntu VM:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build and test
run: npm run build
In this example, the job runs on the latest version of Ubuntu, and GitHub automatically provisions the runner. The VM is decommissioned once the job is completed, ensuring a clean environment for every workflow run.
Self-hosted runners
Self-hosted runners are machines that developers manage themselves. They are useful if more control is needed over the execution environment, such as for deploying to private infrastructure or when GitHub-hosted runners do not meet performance or security requirements.
Self-hosted runners can be configured to run on Linux, Windows, or macOS, and developers can install any required software. This flexibility allows users to customize the environment but requires additional setup and maintenance.
Here’s how a developer might configure a self-hosted runner:
jobs:
deploy:
runs-on: self-hosted
steps:
- name: Deploy to private server
run: ./deploy.sh
In this case, the job runs on the organization’s own infrastructure, and GitHub Actions connects to the machine to execute the job.
Octopus Deploy: Ultimate GitHub Actions alternative for full Continuous Delivery
Octopus has a set of GitHub Actions that let you handle your CI in GitHub and seamlessly transfer to Octopus for CD at scale. This lets you use features purpose-built to support complex deployments at scale.
The Octopus UI lets you visualize deployment processes and status. The process can be stored using configuration as code in version control, but you can still view and edit it through the UI, which makes it easier to understand.
Tenanted deployments make it possible to use a single deployment process to manage deployment regions, physical locations (like retail stores or hospitals), or tenant-specific instances of your software.
Octopus handles modern and traditional software deployments, so you can see all your deployments in one place regardless of whether you target Kubernetes clusters, platform-as-a-service, or virtual machines in the cloud, data center, or elsewhere.
You can create shared variables and secrets and have the values applied during the deployment, so your configuration is always correct.
On top of deployments, Octopus also lets you create automated runbooks. You can use these to remove toil from routine maintenance work, to provide emergency operations, and to provide self-service push-button actions to your teams.
Learn more about Octopus Deploy
Help us continuously improve
Please let us know if you have any feedback about this page.