> **Page index:** https://km.oslo.systems/llms.txt lists every page on this site, with a link to its Markdown version.

# 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 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 repository**—the repository contains code for a single application, while the associated infrastructure lives in a separate IaC repository (for example, `pirates-iac`).
- **Application monorepo**—the repository contains code for many applications, while the associated infrastructure lives in a separate IaC repository (for example, `pirates-iac`).
- **Application repository with 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` AWS environment | `pirates-dev` |
| `<prod-environment-name>` | Name of your `prod` AWS environment | `pirates-prod` |
| `<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` |
| `<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` AWS environment | `pirates-dev` |
| `<prod-environment-name>` | Name of your `prod` AWS environment | `pirates-prod` |
| `<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` |
| `<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` AWS environment | `pirates-dev` |
| `<prod-environment-name>` | Name of your `prod` AWS 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](<https://github.com/orgs/oslokommune/teams>) | `utviklerflyt` |

### Step 1.3: Add Renovate configuration

Download [renovate.json5](<https://github.com/oslokommune/golden-path-templates/blob/main/templates/gh-cicd-app/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.

> [!NOTE]
>
> **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](<https://km.oslo.systems/terraform-automation/renovate/index.md>).

## 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` (for example, `.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`](<https://github.com/oslokommune/pirates-app-zebra/blob/main/src/config.ts>) shows a reference approach for handling this.

| Application type | Repository type | Reference implementation |
| --- | --- | --- |
| Kotlin container | Application repository | [hello-world](<https://github.com/oslokommune/pirates-app-hello-world/blob/main/.github/workflows/hello-world_deployment.yml>) |
| Kotlin container | Application monorepo | [too-tikki](<https://github.com/oslokommune/pirates-apps/blob/main/.github/workflows/too-tikki_deployment.yml>) |
| Static website | Application repository | [zebra](<https://github.com/oslokommune/pirates-app-zebra/blob/main/.github/workflows/zebra_deployment.yml>) |
| Go container | Application repository with infrastructure | [`swordsmith`](<https://github.com/oslokommune/pirates-app-swordsmith/blob/main/.github/workflows/swordsmith_deployment.yml>) |

> [!NOTE]
>
> For an application repository w/infrastructure, you should also add [`terraform-pr.yml`](<https://github.com/oslokommune/golden-path-templates/blob/main/templates/gh-cicd-app-hybrid/.github/workflows/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](<https://km.oslo.systems/help/contact-us/index.md>).

## 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](<https://km.oslo.systems/application/migrate-to-latest-cicd/configure-infrastructure/#step-2-configure-the-application-stack>), 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`.
