Skip to content

Commit 79996a0

Browse files
authored
Merge pull request #14 from RSS-Engineering/add-terraform-plan-action
Fix bad logic for validation
2 parents d5076ec + 38ead45 commit 79996a0

File tree

3 files changed

+161
-11
lines changed

3 files changed

+161
-11
lines changed

docs/cicd/deploying_with_github_actions.md

Lines changed: 159 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
The deployment flow for Github Actions is such that when a Pull Request is created/changed an action will generate a Terraform plan and attach it as a comment to the Pull Request. In order to ensure the consistency of the plan, branch protections should be added to the master branch such that a pull request can only be merged against the latest master commit
44

5-
These settings are (at least):
5+
## Github Repository Settings
6+
7+
Apply these settings to your repository and default branch:
68

79
- Settings -> Pull Requests
810
- Check **Allow merge commits**
@@ -16,9 +18,21 @@ These settings are (at least):
1618
- Add the name of your GH Actions workflow to *Status checks that are required*
1719
- Check **Include administrators**
1820

19-
Once these settings are applied to your repo. Add a workflow file to your code.
20-
This example shows how to automatically add plan comments to your pull requests.
21-
This uses a standard Github action for generating a terraform plan. The documentation for this action is available [here](https://github.com/RSS-Engineering/terraform/blob/main/gh_actions/attach_plan_to_pr/README.md)
21+
## Actions
22+
23+
There several workflows that you can add to properly manage your project.
24+
25+
*NOTE:* These workflows require that credentials be added to your repo to access
26+
your infrastructure. While these examples assume an AWS environment, it is not a
27+
requirement. Any cloud provider that can be configured via environment variables
28+
will be compatible.
29+
30+
### Code Validation and Terraform Planning
31+
32+
This workflow uses a standard action for validating terraform code and generating
33+
a terraform plan. The documentation for this action is available [here](https://github.com/RSS-Engineering/terraform/blob/main/gh_actions/attach_plan_to_pr/README.md).
34+
This is also a good place to add additional static analysis to your project. It
35+
can be manually invoked to apply to any branch or a number of environments.
2236

2337
```yaml
2438
name: Validate Pull Request
@@ -28,6 +42,16 @@ on:
2842
paths-ignore:
2943
- 'docs/**'
3044
- 'README.md'
45+
workflow_dispatch:
46+
inputs:
47+
env:
48+
description: 'Plan for Environment'
49+
required: true
50+
default: 'staging'
51+
type: choice
52+
options:
53+
- prod
54+
- staging
3155

3256
jobs:
3357
terraform:
@@ -38,21 +62,147 @@ jobs:
3862
- name: Checkout Repository
3963
uses: actions/checkout@v2
4064

65+
# This step is only necessary to switch between multiple environments.
66+
- name: Build Credentials
67+
id: creds
68+
run: |
69+
if [ "$ENV" = "staging" ]
70+
then
71+
echo "::set-output name=access_key::$STAGING_ACCESS_KEY"
72+
echo "::set-output name=secret_key::$STAGING_SECRET_KEY"
73+
echo "::set-output name=env::$ENV"
74+
else
75+
echo "::set-output name=access_key::$PROD_ACCESS_KEY"
76+
echo "::set-output name=secret_key::$PROD_SECRET_KEY"
77+
echo "::set-output name=env::prod"
78+
fi
79+
env:
80+
ENV: ${{ github.event.inputs.env || 'prod' }}
81+
PROD_ACCESS_KEY: ${{ secrets.PROD_AWS_ACCESS_KEY_ID }}
82+
PROD_SECRET_KEY: ${{ secrets.PROD_AWS_SECRET_ACCESS_KEY }}
83+
STAGING_ACCESS_KEY: ${{ secrets.STAGING_AWS_ACCESS_KEY_ID }}
84+
STAGING_SECRET_KEY: ${{ secrets.STAGING_AWS_SECRET_ACCESS_KEY }}
85+
4186
- name: Build Terraform Plan
42-
uses: RSS-Engineering/terraform/gh_actions/attach_plan_to_pr@v1.1.2
87+
uses: RSS-Engineering/terraform/gh_actions/attach_plan_to_pr@v1.1.3
4388
id: plan
4489
env:
45-
ENV: prod
90+
ENV: ${{ steps.creds.outputs.env }}
4691
AWS_DEFAULT_REGION: "us-west-2"
47-
AWS_ACCESS_KEY_ID: ${{ secrets.PROD_AWS_ACCESS_KEY_ID }}
48-
AWS_SECRET_ACCESS_KEY: ${{ secrets.PROD_AWS_SECRET_ACCESS_KEY }}
92+
AWS_ACCESS_KEY_ID: ${{ steps.creds.outputs.access_key }}
93+
AWS_SECRET_ACCESS_KEY: ${{ steps.creds.outputs.secret_key }}
4994
with:
5095
terraform_version: 1.0.1
51-
root: infrastructure/environments/prod
96+
root: infrastructure/environments/${{ steps.creds.outputs.env }}
5297
text_artifact_name: tf-plan-${{ github.sha }}.txt
5398
plan_artifact_name: tf-plan-${{ github.sha }}
5499

55100
- name: Terraform Plan Status
56101
if: steps.plan.outcome == 'failure'
57102
run: exit 1
58103
```
104+
105+
### Deployment
106+
107+
This workflow applies terraform changes to your infrastructure. It is invoked
108+
automatically when a Pull Request is merged to the master branch (change this if
109+
your default branch is named differently). It can also be invoked manually to
110+
deploy to lower environments.
111+
112+
```yaml
113+
name: Deploy
114+
115+
on:
116+
push:
117+
branches:
118+
- master
119+
paths-ignore:
120+
- 'docs/**'
121+
- 'README.md'
122+
workflow_dispatch:
123+
inputs:
124+
env:
125+
description: 'Deploy to Environment'
126+
required: true
127+
default: 'staging'
128+
type: choice
129+
options:
130+
- staging
131+
# Uncomment the line below if you want to be able to manually deploy to production (not recommended)
132+
# - prod
133+
134+
jobs:
135+
terraform:
136+
name: "Apply Terraform changes"
137+
runs-on: ubuntu-latest
138+
139+
steps:
140+
- name: Checkout Repository
141+
uses: actions/checkout@v2
142+
143+
- name: Setup Terraform
144+
uses: hashicorp/setup-terraform@v1
145+
with:
146+
terraform_version: 1.0.1
147+
148+
- name: Build Credentials
149+
id: creds
150+
run: |
151+
if [ "$ENV" = "staging" ]
152+
then
153+
echo "::set-output name=access_key::$STAGING_ACCESS_KEY"
154+
echo "::set-output name=secret_key::$STAGING_SECRET_KEY"
155+
echo "::set-output name=env::$ENV"
156+
else
157+
echo "::set-output name=access_key::$PROD_ACCESS_KEY"
158+
echo "::set-output name=secret_key::$PROD_SECRET_KEY"
159+
echo "::set-output name=env::prod"
160+
fi
161+
env:
162+
# github.event.inputs.env will be empty when invoked via master push thus defaulting to 'prod'
163+
ENV: ${{ github.event.inputs.env || 'prod' }}
164+
PROD_ACCESS_KEY: ${{ secrets.PROD_AWS_ACCESS_KEY_ID }}
165+
PROD_SECRET_KEY: ${{ secrets.PROD_AWS_SECRET_ACCESS_KEY }}
166+
STAGING_ACCESS_KEY: ${{ secrets.STAGING_AWS_ACCESS_KEY_ID }}
167+
STAGING_SECRET_KEY: ${{ secrets.STAGING_AWS_SECRET_ACCESS_KEY }}
168+
169+
- name: Get Lockfile path
170+
id: lockfile_path
171+
run: echo "infrastructure/environments/${{ steps.creds.outputs.env }}/.terraform.lock.hcl"
172+
173+
- name: Load cached Terraform Providers
174+
uses: actions/cache@v3
175+
with:
176+
path: infrastructure/environments/${{ steps.creds.outputs.env }}/.terraform
177+
key: tf-providers-${{ hashFiles(steps.lockfile_path.output.stdout) }}
178+
179+
- name: Initialize Terraform
180+
env:
181+
ENV: ${{ steps.creds.outputs.env }}
182+
AWS_DEFAULT_REGION: "us-west-2"
183+
AWS_ACCESS_KEY_ID: ${{ steps.creds.outputs.access_key }}
184+
AWS_SECRET_ACCESS_KEY: ${{ steps.creds.outputs.secret_key }}
185+
run: terraform -chdir=infrastructure/environments/${{ steps.creds.outputs.env }} init
186+
187+
- name: Validate Terraform
188+
env:
189+
ENV: ${{ steps.creds.outputs.env }}
190+
AWS_DEFAULT_REGION: "us-west-2"
191+
AWS_ACCESS_KEY_ID: ${{ steps.creds.outputs.access_key }}
192+
AWS_SECRET_ACCESS_KEY: ${{ steps.creds.outputs.secret_key }}
193+
run: |
194+
terraform fmt -check -recursive -diff infrastructure
195+
terraform -chdir=infrastructure/environments/${{ steps.creds.outputs.env }} validate
196+
197+
- name: Terraform Plan Status
198+
if: steps.plan.outcome == 'failure'
199+
run: exit 1
200+
201+
- name: Terraform Apply
202+
env:
203+
ENV: ${{ steps.creds.outputs.env }}
204+
AWS_DEFAULT_REGION: "us-west-2"
205+
AWS_ACCESS_KEY_ID: ${{ steps.creds.outputs.access_key }}
206+
AWS_SECRET_ACCESS_KEY: ${{ steps.creds.outputs.secret_key }}
207+
run: terraform -chdir=infrastructure/environments/${{ steps.creds.outputs.env }} apply --auto-approve
208+
```

gh_actions/attach_plan_to_pr/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ The terraform plan in human-readable output
4646

4747
```yaml
4848
- name: Build Terraform Plan
49-
uses: RSS-Engineering/terraform/gh_actions/attach_plan_to_pr@v1.1.2
49+
uses: RSS-Engineering/terraform/gh_actions/attach_plan_to_pr@v1.1.3
5050
id: plan
5151
env:
5252
ENV: prod

gh_actions/attach_plan_to_pr/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ runs:
6565
run: terraform -chdir=${{ inputs.root }} init
6666

6767
- name: Validate Terraform
68-
if: inputs.validate_format != 'true'
68+
if: inputs.validate_format == 'true'
6969
shell: bash
7070
run: |
7171
terraform fmt -check -recursive -diff infrastructure

0 commit comments

Comments
 (0)