# Add apply workflow

Add a Terraform apply workflow so that merges to your default branch automatically apply infrastructure changes.

## Step 1: Add the apply workflow

Create a new branch:

```bash title="repo-iac/"
git checkout -b add-apply-workflow
```

Download [`terraform-apply.yml`](https://github.com/oslokommune/golden-path-templates/blob/main/templates/gh-terraform-iac/.github/workflows/terraform-apply.yml){:target="_blank"} to `.github/workflows/terraform-apply.yml`:

```bash title="repo-iac/"
gh api repos/oslokommune/golden-path-templates/contents/templates/gh-terraform-iac/.github/workflows/terraform-apply.yml \
  --jq '.content' | base64 -d > .github/workflows/terraform-apply.yml
```

<!-- prettier-ignore-start -->
!!! note
    `on.push.paths` needs to match the directory structure in your repository.
<!-- prettier-ignore-end -->

## Step 2: Disable production

The apply workflow automatically applies stacks with file changes once pushed to your default branch. To reduce risk of accidents, starting by excluding production is the recommended approach, so you can verify and become comfortable with this behavior in `dev` first.

```yaml title=".github/workflows/terraform-apply.yml"
with:
  ignored-stacks: "<prod-iac-directory>/**"
```

| Field                  | Description                                                  | Example       |
| ---------------------- | ------------------------------------------------------------ | ------------- |
| `<prod-iac-directory>` | The directory containing IaC for your production environment | `stacks/prod` |

<!-- prettier-ignore-start -->
!!! warning "Broken stacks"
    If you noted any stacks with issues or unexpected drift during [Add plan workflow](add-plan-workflow.md#step-8-verify-the-plan-workflow-against-all-stacks), fix the issues or temporarily prevent the workflows from running against them to avoid failed workflow runs or accidents - you can gradually fix these stacks over time and remove them from `ignored-stacks` as they are resolved.

    You should ignore the broken stacks in **both** `terraform-apply.yml` and `terraform-pr.yml`.

    !!! example "Disable Terraform plan"
        Example on how to disable Terraform plan for broken stacks:

        ```yaml title=".github/workflows/terraform-pr.yml"
        with:
          ignored-stacks: |
            stacks/dev/broken-stack
            stacks/prod/another-broken-stack
        ```

    !!! example "Disable Terraform apply"
        Example on how to disable Terraform apply in `prod` and for broken stacks:
        ```yaml title=".github/workflows/terraform-apply.yml"
        with:
          ignored-stacks: |
            stacks/prod/**
            stacks/dev/broken-stack
            stacks/prod/another-broken-stack
        ```
<!-- prettier-ignore-end -->

## Step 3: Verify

Add a comment to `config_override.tf` in `cicd-common` in both your `dev` and `prod` environments, and create a pull request.

Verify that:

1. The plan workflow runs and comments on the PR with a plan for `cicd-common` in **both** `dev` and `prod`
1. After merging, the apply workflow triggers and applies **only** the stack in `dev` - the `prod` stack should be skipped due to `ignored-stacks`

## Step 4: Enable production

After a few days, once you are comfortable with how the apply workflow behaves in `dev` and the majority of your stacks report "No changes" on a full plan run, you can remove the production directory from `ignored-stacks` in `terraform-apply.yml`. A few individually ignored stacks are fine.

<!-- prettier-ignore-start -->
!!! warning "Avoid applying locally"
    Once the apply workflow is enabled for an environment, try to avoid running `terraform apply` locally for stacks in that environment. The workflow applies whatever is on your default branch - if you apply changes locally that are not on `main`, the next push overwrites them.
<!-- prettier-ignore-end -->

## Done

Your infrastructure repository now has automated Terraform plan and apply workflows. Changes on pull requests trigger a plan, and merges to your default branch automatically trigger an apply.
