Migrating from CircleCI to Github Actions
Introduction
We are encouraging development teams to move away from CircleCI to Github Actions for build, test and deployments, and have built Github Actions that pretty-much behave the same as CircleCI, but without using external services (eg. quay.io)
This document is a guide to migrationg from CircleCI to Github Actions. Obviously it can’t detail every change that needs to be made, since there may be differences in deployment pipelines from component to component (different environments, approval gates and test regimes) but it’s intended to act as a guide.
It is also a work in progress - if, when following this document you encounter any issues, please raise them in #ask-prisons-digital-sre
Finally this document is intended as a guide to migrating apps built from the Kotlin and Typescript templates, although elements of it may well be useful to migrate other applications.
Moving from CircleCI to Github Actions has a couple of pre-requisities that need to be completed before moving over, and then a couple of ‘on-the-day’ moves to deactivate CircleCI and start using Github Actions. These are covered below.
Prerequisites
These are the same as any project built using the existing templates, mainly:
- You must be a member of a team in the Ministry of Justice GitHub organisation. That team must belong to parent team HMPPS Developers.
Teams are managed by the hmpps-github-teams project.
Updating Cloud Platform namespaces
The key to being able to deploy with Github Actions is storing Kubernetes credentials within Github itself, rather than in Circle CI environment variables or contexts. The good news is that Cloud Platforms can facilitate this by creating service accounts that can populate the environments section of Github, and both apply permissions for approval/deployment (in the same way as contexts did in CircleCI) and store the secrets so that they can be referred to by Github Actions.
Furthermore, these secrets can automatically be rotated, improving security. This section details how to create the service account and populate the environments
Namespaces and mappings
It is assumed that each deployment environment has its own namespace, but this namespace can be shared by a number of components within a product (eg. ui and api).
This is the important bit: for this to make sense, the environments should all match: (links show examples within the template repo)
- The environment created in Github
- The environment in the namespace configuration
- The helm
values-xxx.yaml
filename - The ENVIRONMENT_NAME within the helm
values-xxx.yaml
file
github Service acccount
Within the hmpps-templates-dev namespace definition there is a file called resources/serviceaccount-github.tf
This should be copied into the appropriate namespace’s resources directory, and the following changes made:
- github_repos
Each of the repositories that uses this namespace should be listed on row 5
- github_environments
This refers to the var.environment
variable within resources/variables.tf - this is one of the parameters that needs to match with all the others.
- data “github_team”
- resource “github_repository_environment” “env” -> reviewers
These configure the review constraints for the environments. Add the appropriate github teams that are authorised to review and approve deployments for this environment, based on the existing entries.
time definition
So that tokens can be rotated, the following entry should be added within resources/versions.tf:
time = { source = "hashicorp/time" version = "~> 0.9.0" }
Once this PR has been approved and the Terraform has run, the Github repositories to which this namespace applies will have a corresponding environment entry within the settings:
Creating the build/test/deploy workflow
A boilerplate Github workflow file can be found in the appropriate template repository:
- HMPPS Kotlin Template: pipeline.yml
- HMPPS Typescript Template: pipeline.yml
This pipeline is configured for building, testing and deploying to a development environment, so should be able to be copied to your existing project.
Refer to the .circleci/config.yml
file within your existing project to figure out the gates for other environments - in general, it should be fairly obvious which changes should be made to the the pipeline file so it behaves in a similar manner.
Removing CircleCI
Here are the processes required to remove CircleCI from the process, and replace the elements with Github Actions.
- Remove
.circleci/config.yml
- On the Github site:
- within Settings -> Webhooks, delete https://circleci.com/hooks/github
- within Settings -> Branches -> main, there will be some status checks that include
ci/circleci:
- for each status check, there will be a corresponding one for Github Actions - enter the status check names in the search box and add the non-CircleCI response
- then remove the circle CI one
That completes the move of the app to Github Actions
Appendix - Application Insights
There is a new method by which the Application Insights secret is deployed. This uses an SSM value that’s referenced within an appinsights.tf
resource within the hmpps-templates-dev namespace definition.
This creates a secret called application-insights within the namespace with the corresponding access key.
With existing (CircleCI deployed) apps, the Application Insights secret is added to the application’s secrets during the bootstrap process, and referred to in the Helm values.yaml
configuration:
namespace_secrets: hmpps-your-application: APPINSIGHTS_INSTRUMENTATIONKEY: 'APPINSIGHTS_INSTRUMENTATIONKEY' . .
To use the Terraform managed secret (which new projects use by default), it’s a simple case of adding the appinsights.tf
file to your namespaces (ensuring that you change the contents to match the correct environment) and then modifying the values.yaml
file to move the secret to its own application - application-insights
namespace_secrets: hmpps-your-application: EXISTING_ENV: EXISTING_SECRET_VALUE . . application-insights: APPINSIGHTS_INSTRUMENTATIONKEY: 'APPINSIGHTS_INSTRUMENTATIONKEY' . .