Development to Production with GitHub Actions

3 min read

649 words

This blog post will outline a way to get changes from development into production. There are many different ways to do this. This is one way, and there is not the one way from dev to production. In the following, I will talk about a way that I have experience with and like the way of the process. The process described in this post will follow the typical Software Development Lifecycle. The definition of it will also not be part of the post. However I will briefly describe what happens in the 3 phases of development, staging and production.

Development

Development is done in branches that branch off the main branch of the repository. One argument for working in branches is that the work is done in isolation. This means that other developers can work on their own features and fixes without conflicting with each other. Another great thing about it is that you can prototype and test things that can be deployed, and if you are not satisfied with the result, you can easily discard it. Most importantly, with this practice, the main branch should always be in a deployable state.

To merge the new changes into the main branch, a pull request (PR) is required. In this step, it is optionally possible to create preview builds for other team members or product owners to check out the changes. This way, the feedback loop can be closer to the relevant stakeholders. And the desired changes will get into production faster.

Staging

Everything in the main branch of the respective repository is deployed to the staging environment. The staging environment is, at best, a 1:1 replica of the resources in the production environment. This means that the server setup should mirror the production setup.

Now that the PR has been merged into the main branch, a GitHub action is triggered to deploy the new state of the main branch to the staging environment. The following shows how the action is triggered:

name: Deploy to stage

on:
  push:
    branches:
      - main

jobs:
	...

The deployment steps vary depending on the technologies used, and are therefore not part of this post.

Additionally, the GitHub action should have a CI or test job that checks if the state of the branch is deployable. To avoid this step, or to reduce the chance of it happening, it is always a good idea to merge the current state of the `main' branch into a PR before merging it. This way, the PR's test/CI tasks will do the checks to see if the PR is deployable or not.

Since there may be files or paths that are not interesting to trigger a full deployment when merged into main, it is possible to ignore those paths. This way it is possible to save action minutes and thus reduce possible costs.

name: Deploy to stage

on:
  push:
    paths-ignore:
      - ".github/**"
      - "README.md"
    branches:
      - main
      
jobs:
	...

The code has been reviewed in the staging environment and is ready for production. Now it's time to use GitHub's release feature.

Production

Now that the code is in the staging environment and has been tested to perfection, it is time to move it into production. GitHub has the ability to create releases and take a branch that is packaged as a release. Our branch will be the `main' branch of the repository, since that is what we have in staging.

How to create a release can be found in the GitHub documentation.

Publishing a release is now the trigger to run another GitHub action that will build the application with the appropriate configuration and deploy it to the production environment to go live.

Below is the action trigger for this release's GitHub action:

name: Deploy to production

on:
  release:
    types: [ published ]

jobs:
	...