Skip to content

Commit ee772b2

Browse files
Terraform workflow (#55)
Co-authored-by: Anmol Nagpal <[email protected]>
1 parent 3ab9299 commit ee772b2

File tree

3 files changed

+324
-0
lines changed

3 files changed

+324
-0
lines changed
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
run-name: 'Terraform workflow'
2+
on:
3+
workflow_call:
4+
inputs:
5+
working_directory:
6+
required: true
7+
type: string
8+
description: 'Root directory of the terraform where all resources exist.'
9+
provider:
10+
required: true
11+
type: string
12+
default: aws
13+
description: 'Cloud provider to run the workflow. e.g. azurerm, aws, gcp or digitalocean'
14+
aws_region:
15+
required: false
16+
type: string
17+
default: us-east-2
18+
description: 'AWS region of terraform deployment.'
19+
gcp_region:
20+
required: false
21+
type: string
22+
description: 'GCP region of terraform deployment.'
23+
var_file:
24+
required: false
25+
type: string
26+
description: 'Terraform var file directory. e.g. vars/dev.tfvars'
27+
destroy:
28+
type: string
29+
default: false
30+
description: 'you want to destroy infra or not'
31+
approvers:
32+
required: false
33+
type: string
34+
description: 'Approvals list to approve apply or destroy'
35+
terraform_version:
36+
type: string
37+
default: 1.3.6
38+
description: 'Required erraform version '
39+
timeout:
40+
required: false
41+
type: number
42+
default: 10
43+
description: 'Timeout for approval step'
44+
secrets:
45+
AZURE_CREDENTIALS:
46+
required: false
47+
description: 'Azure Credentials to install Azure in github runner.'
48+
AWS_ACCESS_KEY_ID:
49+
required: false
50+
description: 'AWS Access Key ID to install AWS CLI.'
51+
BUILD_ROLE:
52+
required: false
53+
description: 'AWS OIDC role for aws authentication.'
54+
AWS_SECRET_ACCESS_KEY:
55+
required: false
56+
description: 'AWS Secret access key to install AWS CLI'
57+
AWS_SESSION_TOKEN:
58+
required: false
59+
description: 'AWS Session Token to install AWS CLI'
60+
GCP_SA_KEY:
61+
required: false
62+
description: 'GCP service account Secret access key to install GCP CLI'
63+
PROJECT_ID:
64+
required: false
65+
description: 'GCP Secret access key to install GCP CLI'
66+
DIGITALOCEAN_ACCESS_TOKEN:
67+
required: false
68+
description: 'Digitalocean access Token to install Digitalocean CLI'
69+
SPACES_ACCESS_KEY_ID:
70+
required: false
71+
description: 'Spaces access key ID for digitalocean if required'
72+
SPACES_SECRET_ACCESS_KEY:
73+
required: false
74+
description: 'Spaces secret access key for digitalocean if required'
75+
76+
jobs:
77+
terraform-workflow:
78+
runs-on: ubuntu-latest
79+
env:
80+
ARM_SKIP_PROVIDER_REGISTRATION: true
81+
DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
82+
SPACES_ACCESS_KEY_ID: ${{ secrets.SPACES_ACCESS_KEY_ID }}
83+
SPACES_SECRET_ACCESS_KEY: ${{ secrets.SPACES_SECRET_ACCESS_KEY }}
84+
outputs:
85+
tfplanExitCode: ${{ steps.tf-plan.outputs.exitcode }}
86+
87+
steps:
88+
- name: Checkout
89+
uses: actions/checkout@v3
90+
91+
- name: Install AWS CLI
92+
if: ${{ inputs.provider == 'aws' }}
93+
uses: aws-actions/configure-aws-credentials@v2
94+
with:
95+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
96+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
97+
aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }}
98+
role-to-assume: ${{ secrets.BUILD_ROLE }}
99+
aws-region: ${{ inputs.aws_region }}
100+
role-duration-seconds: 900
101+
role-skip-session-tagging: true
102+
103+
- name: Install Azure CLI
104+
if: ${{ inputs.provider == 'azurerm' }}
105+
uses: azure/login@v1
106+
with:
107+
creds: ${{ secrets.AZURE_CREDENTIALS }}
108+
109+
- name: Install GCP CLI
110+
if: ${{ inputs.provider == 'gcp' }}
111+
uses: google-github-actions/auth@v0
112+
with:
113+
service_account_key: ${{ secrets.GCP_SA_KEY }}
114+
project_id: ${{ secrets.PROJECT_ID }}
115+
region: ${{ inputs.gcp_region }}
116+
117+
- name: Install doctl
118+
if: ${{ inputs.provider == 'digitalocean' }}
119+
uses: digitalocean/action-doctl@v2
120+
with:
121+
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
122+
123+
- name: Set up Terraform
124+
uses: hashicorp/setup-terraform@v2
125+
with:
126+
terraform_version: ${{ inputs.terraform_version }}
127+
128+
- name: 'Terraform Format'
129+
if: ${{ inputs.destroy != 'true' }}
130+
id: fmt
131+
uses: 'dflook/terraform-fmt-check@v1'
132+
with:
133+
actions_subcommand: 'fmt'
134+
path: ${{ inputs.working_directory }}
135+
136+
- name: terraform init
137+
run: |
138+
cd ${{ inputs.working_directory }}
139+
terraform init
140+
141+
- name: 'Terraform validate'
142+
if: ${{ inputs.destroy != 'true' }}
143+
id: validate
144+
uses: dflook/terraform-validate@v1
145+
with:
146+
tf_actions_working_dir: ${{ inputs.working_directory }}
147+
148+
- name: Terraform Plan
149+
id: tf-plan
150+
run: |
151+
export exitcode=0
152+
cd ${{ inputs.working_directory }}
153+
if [ "${{ inputs.destroy }}" = "true" ]; then
154+
if [ -n "${{ inputs.var_file }}" ]; then
155+
terraform plan -destroy -out tfplan --var-file=${{ inputs.var_file }}
156+
else
157+
terraform plan -destroy -out tfplan
158+
fi
159+
else
160+
if [ -n "${{ inputs.var_file }}" ]; then
161+
terraform plan -out tfplan --var-file=${{ inputs.var_file }}
162+
else
163+
terraform plan -out tfplan
164+
fi
165+
fi
166+
167+
- name: Publish Terraform Plan
168+
uses: actions/upload-artifact@v3
169+
with:
170+
name: tfplan
171+
path: ${{ inputs.working_directory }}/tfplan
172+
173+
- name: Create String Output
174+
id: tf-plan-string
175+
run: |
176+
cd ${{ inputs.working_directory }}
177+
TERRAFORM_PLAN=$(terraform show -no-color tfplan)
178+
delimiter="$(openssl rand -hex 8)"
179+
echo "summary<<${delimiter}" >> $GITHUB_OUTPUT
180+
echo "## Terraform Plan Output" >> $GITHUB_OUTPUT
181+
echo "<details><summary>Click to expand</summary>" >> $GITHUB_OUTPUT
182+
echo "" >> $GITHUB_OUTPUT
183+
echo '```terraform' >> $GITHUB_OUTPUT
184+
echo "$TERRAFORM_PLAN" >> $GITHUB_OUTPUT
185+
echo '```' >> $GITHUB_OUTPUT
186+
echo "</details>" >> $GITHUB_OUTPUT
187+
echo "${delimiter}" >> $GITHUB_OUTPUT
188+
189+
- name: "Accept plan or deny"
190+
uses: trstringer/manual-approval@v1
191+
timeout-minutes: ${{ inputs.timeout }}
192+
with:
193+
secret: ${{ github.TOKEN }}
194+
approvers: ${{ inputs.approvers }}
195+
issue-title: "Terraform Plan for Infrastructure Update"
196+
issue-body: ${{ steps.tf-plan-string.outputs.summary }}
197+
198+
- name: terraform apply
199+
if: ${{ inputs.destroy != 'true' }}
200+
run: |
201+
if [ -n "${{ inputs.var_file }}" ]; then
202+
cd ${{ inputs.working_directory }}
203+
terraform apply -var-file="${{ inputs.var_file }}" -auto-approve
204+
else
205+
cd ${{ inputs.working_directory }}
206+
terraform apply -auto-approve
207+
fi
208+
209+
- name: Terraform destroy
210+
if: ${{ inputs.destroy == 'true' }}
211+
id: destroy
212+
run: |
213+
if [ -n "${{ inputs.var_file }}" ]; then
214+
cd ${{ inputs.working_directory }}
215+
terraform destroy -var-file="${{ inputs.var_file }}" -auto-approve
216+
else
217+
cd ${{ inputs.working_directory }}
218+
terraform destroy -auto-approve
219+
fi

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Above example is just a simple example to call workflow from github shared workf
6161
6. [Terraform Lint Workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/terraform-lint.md)
6262
7. [Terraform Checks Workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/terraform-checks.md)
6363
7. [Checkov Workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/checkov.md)
64+
8. [Terraform Workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/terraform_workflow.md)
6465
6566
## Feedback
6667
If you come accross a bug or have any feedback, please log it in our [issue tracker](https://github.com/clouddrove/github-shared-workflows/issues), or feel free to drop us an email at [[email protected]](mailto:[email protected]).

docs/terraform_workflow.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
## [Terraform Workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/.github/workflows/terraform_workflow.yml)
2+
3+
This workflow is used to apply and destroy terraform infra using GitHub Actions. It utilizes the workflows defined in `.github/workflows/terraform_workflow.yml`
4+
5+
#### Usage
6+
This workflow generates an issue before the apply or destroy step with a required plan in it. If we comment "yes", "lgtm" the workflow will proceed to the next step. However, if we comment "deny," the workflow will be canceled.
7+
8+
#### Example of a Terraform workflow for a AWS cloud provider
9+
```yaml
10+
name: terraform workflow
11+
permissions: write-all
12+
on:
13+
push:
14+
branches: [ master ]
15+
pull_request:
16+
workflow_dispatch:
17+
jobs:
18+
prod:
19+
uses: clouddrove/github-shared-workflows/.github/workflows/terraform_workflow.yml@master
20+
with:
21+
provider: # aws
22+
working_directory: # Specify terraform code directory in repo
23+
var_file: # name of tfvar file e.g "variable.tfvar"
24+
aws_region: # specify region eg. us-east-2
25+
approvers: # Assignee name for approve apply or destroy step
26+
terraform_version: # Specify terraform version e.g 1.3.6
27+
destroy: # If the value is set to true, the workflow proceeds to the destroy step. However, the default value is false
28+
secrets:
29+
AWS_ACCESS_KEY_ID: # Specify AWS Access key ID
30+
AWS_SECRET_ACCESS_KEY: # Specify AWS Secret Access key ID
31+
AWS_SESSION_TOKEN: # Specify Session ID
32+
33+
```
34+
35+
#### Example of a Terraform workflow for a Azure cloud provider
36+
```yaml
37+
name: terraform workflow
38+
permissions: write-all
39+
on:
40+
push:
41+
branches: [ master ]
42+
pull_request:
43+
workflow_dispatch:
44+
jobs:
45+
prod:
46+
uses: clouddrove/github-shared-workflows/.github/workflows/terraform_workflow.yml@master
47+
with:
48+
provider: # azurerm
49+
working_directory: # Specify terraform code directory in repo
50+
var_file: # Name of tfvar file e.g "variable.tfvar"
51+
approvers: # Assignee name for approve apply or destroy step
52+
terraform_version: # Specify terraform version e.g 1.3.6
53+
destroy: # If the value is set to true, the workflow proceeds to the destroy step. However, the default value is false
54+
secrets:
55+
AZURE_CREDENTIALS: # Specify Azure credentilas
56+
```
57+
58+
#### Example of a Terraform workflow for a Digitalocean cloud provider
59+
```yaml
60+
name: terraform workflow
61+
permissions: write-all
62+
on:
63+
push:
64+
branches: [ master ]
65+
pull_request:
66+
workflow_dispatch:
67+
jobs:
68+
prod:
69+
uses: clouddrove/github-shared-workflows/.github/workflows/terraform_workflow.yml@master
70+
with:
71+
provider: # digitalocean
72+
working_directory: # Specify terraform code directory in repo
73+
var_file: # Name of tfvar file e.g "variable.tfvar"
74+
approvers: # Assignee name for approve apply or destroy step
75+
terraform_version: # Specify terraform version e.g 1.3.6
76+
destroy: # If the value is set to true, the workflow proceeds to the destroy step. However, the default value is false
77+
secrets:
78+
DIGITALOCEAN_TOKEN: # Digitalocean token
79+
SPACES_ACCESS_KEY_ID: # Provide spaces access key id if required
80+
SPACES_SECRET_ACCESS_KEY: # Provide spaces secret access key if required
81+
```
82+
83+
#### Example of a Terraform workflow for a GCP cloud provider
84+
```yaml
85+
name: terraform workflow
86+
permissions: write-all
87+
on:
88+
push:
89+
branches: [ master ]
90+
pull_request:
91+
workflow_dispatch:
92+
jobs:
93+
prod:
94+
uses: clouddrove/github-shared-workflows/.github/workflows/terraform_workflow.yml@master
95+
with:
96+
provider: # gcp
97+
working_directory: # Specify terraform code directory in repo
98+
var_file: # Name of tfvar file e.g "variable.tfvar"
99+
approvers: # Assignee name for approve apply or destroy step
100+
terraform_version: # Specify terraform version e.g 1.3.6
101+
destroy: # If the value is set to true, the workflow proceeds to the destroy step. However, the default value is false
102+
secrets:
103+
GCP_SA_KEY: # GCP service account Secret access key
104+
```

0 commit comments

Comments
 (0)