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:

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)

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:

github environment

Creating the build/test/deploy workflow

A boilerplate Github workflow file can be found in the appropriate template repository:

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'   
  . 
  .