# 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:

=== "Application repository"

    Download `.gp.cicd.json`:

    ```bash title="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`    |

=== "Application monorepo"

    Download `.gp.cicd.json`:

    ```bash title="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`    |

=== "Application repository with infrastructure"

    Download `.gp.cicd.json`:

    ```bash title="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:

```text title="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){:target="_blank"} to the repository root:

```bash title="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.

<!-- prettier-ignore-start -->
!!! info "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](../../terraform-automation/renovate.md).
<!-- prettier-ignore-end -->

## 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`).

<!-- prettier-ignore-start -->
<!-- "promote" is the standard CI/CD term for artifact promotion (moving one immutable build through environments), not corporate jargon. -->
<!-- vale NeedsRewrite.CorporateJargon = NO -->
!!! 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){:target="_blank"} shows a reference approach for handling this.
<!-- vale NeedsRewrite.CorporateJargon = YES -->
<!-- prettier-ignore-end -->

| 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)  |

<!-- prettier-ignore-start -->
!!! 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){:target="_blank"}:

    ```bash title="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
    ```
<!-- prettier-ignore-end -->

If you're unsure how to set up the deployment pipeline for your application, [contact Utviklerflyt](../../help/contact-us.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](configure-infrastructure.md#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`.
