Skip to content

Add deployment pipeline

Add and configure a deployment pipeline for your application.

The pipeline is implemented as a GitHub Actions workflow that builds and tests your application, and safely promotes the new build through your environments - stopping if anything fails.

Step 1: Add configuration files

Step 1.1: Add .gp.cicd.json

Create a new branch and add .gp.cicd.json. The file differs depending on your repository type.

  • Application repo — the repository contains code for a single application, while the associated infrastructure lives in a separate IaC repository (e.g., pirates-iac).
  • Application monorepo — the repository contains code for multiple applications, while the associated infrastructure lives in a separate IaC repository (e.g., pirates-iac).
  • Application repo w/infrastructure — the repository contains both application code and the associated infrastructure for a single application.

Select the tab that matches your repository type:

Download .gp.cicd.json:

repo-app/
gh api repos/oslokommune/golden-path-templates/contents/templates/gh-cicd-app/.gp.cicd.json \
  --jq '.content' | base64 -d > .gp.cicd.json

Update these values (many of which can be found in common-config.yml in your infrastructure repository):

Field Description Example
<team-name> Your team name pirates
<repo-iac> Infrastructure-as-code repository name pirates-iac
<dev-aws-account-id> AWS account ID for dev 123456789012
<prod-aws-account-id> AWS account ID for prod 987654321098
<dev-environment-name> Name of your dev environment pirates-dev
<prod-environment-name> Name of your prod environment pirates-prod
<aws-region> Your AWS region eu-west-1

Download .gp.cicd.json:

repo-app/
gh api repos/oslokommune/golden-path-templates/contents/templates/gh-cicd-app-monorepo/.gp.cicd.json \
  --jq '.content' | base64 -d > .gp.cicd.json

Update these values (many of which can be found in common-config.yml in your infrastructure repository):

Field Description Example
<team-name> Your team name pirates
<repo-iac> Infrastructure-as-code repository name pirates-iac
<dev-aws-account-id> AWS account ID for dev 123456789012
<prod-aws-account-id> AWS account ID for prod 987654321098
<dev-environment-name> Name of your dev environment pirates-dev
<prod-environment-name> Name of your prod environment pirates-prod
<aws-region> Your AWS region eu-west-1

Download .gp.cicd.json:

repo-app/
gh api repos/oslokommune/golden-path-templates/contents/templates/gh-cicd-app-hybrid/.gp.cicd.json \
  --jq '.content' | base64 -d > .gp.cicd.json

Update these values (many of which can be found in common-config.yml in your infrastructure repository):

Field Description Example
<team-name> Your team name pirates
<repo-iac> Infrastructure-as-code repository name pirates-iac
<dev-aws-account-id> AWS account ID for dev 123456789012
<prod-aws-account-id> AWS account ID for prod 987654321098
<dev-environment-name> Name of your dev environment pirates-dev
<prod-environment-name> Name of your prod environment pirates-prod
<aws-region> Your AWS region eu-west-1
<dev-iac-directory> The directory containing IaC for your dev environment stacks/dev
<prod-iac-directory> The directory containing IaC for your prod environment stacks/prod

Step 1.2: Add CODEOWNERS

Add a CODEOWNERS file to define who owns the repository and approves PRs:

repo-app/.github/CODEOWNERS
* @oslokommune/<github-team-name>
Field Description Example
<github-team-name> The name of your GitHub team utviklerflyt

Step 1.3: Add Renovate configuration

Download renovate.json5 to the repository root:

repo-app/
gh api repos/oslokommune/golden-path-templates/contents/templates/gh-cicd-app/renovate.json5 \
  --jq '.content' | base64 -d > renovate.json5

This overwrites any existing renovate.json5. If you have custom Renovate configuration, merge it into the downloaded file.

What is Renovate?

Renovate automatically creates pull requests to keep your dependencies up to date. Think of it as a better Dependabot. Learn more in the Renovate reference documentation.

Step 2: Add workflow

Grab one of the reference workflows below and address the few TODO comments. The main adaptation is in the build-and-upload-artifact job, where you customize the build and test steps to match your application.

Save the workflow to .github/workflows/<app-name>_deployment.yml (e.g., .github/workflows/too-tikki_deployment.yml).

Tip

The deployment pipeline is designed to build, upload and promote the exact same immutable artifact across environments ("build once, deploy many").

For static websites where configuration typically differs per environment, the zebra app's config.ts shows a reference approach for handling this.

Application type Repository type Reference implementation
Kotlin container Application monorepo too-tikki
Static website Application repo zebra
Go container Application repo w/infrastructure swordsmith

Note

For an application repository w/infrastructure, you should also add terraform-pr.yml:

repo-app/
gh api repos/oslokommune/golden-path-templates/contents/templates/gh-cicd-app-hybrid/.github/workflows/terraform-pr.yml \
  --jq '.content' | base64 -d > .github/workflows/terraform-pr.yml

If you're unsure how to set up the deployment pipeline for your application, contact Utviklerflyt.

Step 3: Create a pull request

Push the branch and create a pull request.

Verify that the build job succeeds and that no deployment occurs.

Step 4: Merge and deploy

Merge the pull request.

Step 5: Verify

When merging, the CI/CD workflow should deploy your app to your dev environment, and ask for confirmation for you to deploy to production. When this happens, approve it and verify that deployment to production succeeds.

Step 6: Remove image_uri override

If you edited config_override.tf in your infrastructure repository to override local.image_uri, as described in Configure infrastructure, remove the image_uri code line from repo-iac/environments/dev/app-example/config_override.tf as described in that guide. Remember to do so for both dev and prod.