forked from DevSecTop/TF-via-PR
-
Notifications
You must be signed in to change notification settings - Fork 0
/
action.yml
367 lines (356 loc) · 15.8 KB
/
action.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
name: OpenTofu/Terraform via Pull Request
author: Rishav Dhar (@rdhar)
description: GitHub Action to plan and apply OpenTofu/Terraform (TF) via pull request (PR) automation.
branding:
color: purple
icon: package
inputs:
# Input parameters.
cache_plugins:
description: Boolean flag to cache TF plugins for faster workflow runs (requires .terraform.lock.hcl file).
required: false
default: "false"
comment_pr:
description: Boolean flag to add PR comment of TF command output.
required: false
default: "true"
encrypt_passphrase:
description: String passphrase to encrypt the TF plan file.
required: false
default: ""
fmt_enable:
description: Boolean flag to enable TF fmt command and display diff of changes.
required: false
default: "true"
label_pr:
description: Boolean flag to add PR label of TF command to run.
required: false
default: "true"
outline_enable:
description: Boolean flag to add an outline diff of TF plan file.
required: false
default: "true"
tf_tool:
description: String name of the TF tool to use and override default assumption from wrapper environment variable.
required: false
default: "terraform"
tf_version:
description: String version constraint of the TF tool to install and use.
required: false
default: ""
update_comment:
description: Boolean flag to update existing PR comment instead of creating a new comment and deleting the old one.
required: false
default: "false"
validate_enable:
description: Boolean flag to enable TF validate command check.
required: false
default: "false"
# TF arguments.
arg_auto_approve:
description: Boolean flag to toggle skipping of interactive approval of plan before applying.
required: false
default: ""
arg_backend:
description: Boolean flag to toggle TF backend initialization.
required: false
default: ""
arg_backend_config:
description: Comma-separated string list of file path(s) to the backend configuration.
required: false
default: ""
arg_backup:
description: Boolean flag to toggle backup of the existing state file before modifying.
required: false
default: ""
arg_chdir:
description: String path to the working directory where the TF command should be run.
required: false
default: ""
arg_check:
description: Boolean flag to toggle checking of file formatting with appropriate exit code.
required: false
default: ""
arg_cloud:
description: Boolean flag to toggle TF backend initialization.
required: false
default: ""
arg_command:
description: String name of the TF command to run (either 'plan' or 'apply').
required: false
default: "plan"
arg_compact_warnings:
description: Boolean flag to toggle compact output for warnings.
required: false
default: ""
arg_concise:
description: Boolean flag to toggle skipping of refresh log lines.
required: false
default: ""
arg_destroy:
description: Boolean flag to toggle destruction of all managed objects.
required: false
default: ""
arg_detailed_exitcode:
description: String to set the detailed exit code mode.
required: false
default: ""
arg_diff:
description: Boolean flag to toggle display diff of formatting changes.
required: false
default: "true"
arg_force_copy:
description: Boolean flag to toggle suppression of prompts about copying state data.
required: false
default: ""
arg_from_module:
description: String path to copy contents from the given module source into the target directory.
required: false
default: ""
arg_generate_config_out:
description: String path to write the generated configuration.
required: false
default: ""
arg_get:
description: Boolean flag to toggle downloading of modules for the configuration.
required: false
default: ""
arg_ignore_remote_version:
description: Boolean flag to toggle checking if the local and remote TF versions use compatible state representations.
required: false
default: ""
arg_json:
description: Boolean flag to toggle JSON output format.
required: false
default: ""
arg_list:
description: Boolean flag to toggle listing of files whose formatting differs.
required: false
default: "false"
arg_lock:
description: Boolean flag to toggle state locking during state operations.
required: false
default: ""
arg_lock_timeout:
description: String duration to retry a state lock.
required: false
default: ""
arg_lockfile:
description: String to set dependency lockfile mode.
required: false
default: ""
arg_migrate_state:
description: Boolean flag to toggle reconfiguration of the backend, attempting to migrate any existing state.
required: false
default: ""
arg_no_tests:
description: Boolean flag to toggle validation of test files.
required: false
default: ""
arg_or_create:
description: Boolean flag to toggle workspace creation if it doesn't exist.
required: false
default: ""
arg_out:
description: String path to write the generated plan.
required: false
default: "tfplan"
arg_parallelism:
description: String number to limit the number of concurrent operations.
required: false
default: ""
arg_plugin_dir:
description: Comma-separated string list of directory path(s) containing plugin binaries.
required: false
default: ""
arg_reconfigure:
description: Boolean flag to toggle reconfiguration of the backend, ignoring any saved configuration.
required: false
default: ""
arg_recursive:
description: Boolean flag to toggle recursive processing of directories.
required: false
default: "true"
arg_refresh:
description: Boolean flag to skip checking of external changes to remote objects.
required: false
default: ""
arg_refresh_only:
description: Boolean flag to toggle checking of remote objects still match the current configuration without proposing any actions to undo external changes.
required: false
default: ""
arg_replace:
description: Comma-separated string list of resource addresses to replace.
required: false
default: ""
arg_state:
description: String path to read and save state.
required: false
default: ""
arg_state_out:
description: String path to write state.
required: false
default: ""
arg_target:
description: Comma-separated string list of resource addresses to target.
required: false
default: ""
arg_test_directory:
description: String path to the test directory.
required: false
default: ""
arg_upgrade:
description: Boolean flag to toggle upgrading the latest module and provider versions allowed within configured constraints.
required: false
default: ""
arg_var:
description: Comma-separated string list of variables to set in the format 'key=value'.
required: false
default: ""
arg_var_file:
description: Comma-separated string list of file path(s) to the variable configuration.
required: false
default: ""
arg_workspace:
description: String name of the workspace to select or create.
required: false
default: ""
arg_write:
description: Boolean flag to toggle writing of formatted files.
required: false
default: "false"
outputs:
check_id:
description: String output of the workflow check run ID.
value: ${{ steps.tf.outputs.check_id }}
comment_id:
description: String output of the PR comment ID.
value: ${{ steps.tf.outputs.comment_id }}
fmt_result:
description: String output of the TF fmt command.
value: ${{ steps.tf.outputs.fmt_result }}
header:
description: String output of the TF command input.
value: ${{ steps.tf.outputs.header }}
identifier:
description: String output of the TF run's unique identifier.
value: ${{ steps.tf.outputs.identifier }}
last_result:
description: String output of the last TF command.
value: ${{ steps.tf.outputs.last_result }}
outline:
description: String outline of the TF plan.
value: ${{ steps.tf.outputs.outline }}
summary:
description: String summary of the last TF command.
value: ${{ steps.tf.outputs.summary }}
runs:
using: composite
steps:
- name: Cache TF plugins
id: cache_plugins
if: inputs.cache_plugins == 'true' && hashFiles(format('{0}/.terraform.lock.hcl', inputs.arg_chdir))
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
key: ${{ runner.os }}-${{ inputs.tf_tool }}-${{ inputs.tf_version }}-${{ hashFiles(format('{0}/.terraform.lock.hcl', inputs.arg_chdir)) }}
path: |
~/.terraform.d
${{ inputs.arg_chdir }}/.terraform
- name: Install TF via tenv
if: inputs.tf_version != ''
env:
TF_TOOL: ${{ inputs.tf_tool }}
TF_VERSION: ${{ inputs.tf_version }}
shell: bash
run: |
VERSION=$(curl --no-progress-meter --location https://api.github.com/repos/tofuutils/tenv/releases/latest | jq -r .tag_name)
curl --remote-name --no-progress-meter --location "https://github.com/tofuutils/tenv/releases/latest/download/tenv_${VERSION}_amd64.deb"
sudo dpkg --install "tenv_${VERSION}_amd64.deb"
tenv "$TF_TOOL" install "$TF_VERSION"
tenv update-path
- name: Command TF
id: tf
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
# Input parameters.
cache_hit: ${{ steps.cache_plugins.outputs.cache-hit }}
comment_pr: ${{ inputs.comment_pr }}
encrypt_passphrase: ${{ inputs.encrypt_passphrase }}
fmt_enable: ${{ inputs.fmt_enable }}
label_pr: ${{ inputs.label_pr }}
outline_enable: ${{ inputs.outline_enable }}
tf_tool: ${{ inputs.tf_tool }}
update_comment: ${{ inputs.update_comment }}
validate_enable: ${{ inputs.validate_enable }}
# TF environment variables.
TF_CLI_ARGS: ${{ env.TF_CLI_ARGS != '' && format('{0} -no-color', env.TF_CLI_ARGS) || '-no-color' }}
TF_IN_AUTOMATION: true
TF_INPUT: false
MATRIX: ${{ toJSON(matrix) }}
# TF arguments.
arg_auto_approve: ${{ inputs.arg_auto_approve != '' && format('-auto-approve={0}', inputs.arg_auto_approve) || '' }}
arg_backend: ${{ inputs.arg_backend != '' && format('-backend={0}', inputs.arg_backend) || '' }}
arg_backend_config: ${{ inputs.arg_backend_config != '' && format('-backend-config={0}', inputs.arg_backend_config) || '' }}
arg_backup: ${{ inputs.arg_backup != '' && format('-backup={0}', inputs.arg_backup) || '' }}
arg_chdir: ${{ inputs.arg_chdir != '' && format('-chdir={0}', inputs.arg_chdir) || '' }}
arg_check: ${{ inputs.arg_check != '' && format('-check={0}', inputs.arg_check) || '' }}
arg_cloud: ${{ inputs.arg_cloud != '' && format('-cloud={0}', inputs.arg_cloud) || '' }}
arg_command: ${{ inputs.arg_command }}
arg_compact_warnings: ${{ inputs.arg_compact_warnings != '' && format('-compact-warnings={0}', inputs.arg_compact_warnings) || '' }}
arg_concise: ${{ inputs.arg_concise != '' && format('-concise={0}', inputs.arg_concise) || '' }}
arg_destroy: ${{ inputs.arg_destroy != '' && format('-destroy={0}', inputs.arg_destroy) || '' }}
arg_detailed_exitcode: ${{ inputs.arg_detailed_exitcode != '' && format('-detailed-exitcode={0}', inputs.arg_detailed_exitcode) || '' }}
arg_diff: ${{ inputs.arg_diff != '' && format('-diff={0}', inputs.arg_diff) || '' }}
arg_force_copy: ${{ inputs.arg_force_copy != '' && format('-force-copy={0}', inputs.arg_force_copy) || '' }}
arg_from_module: ${{ inputs.arg_from_module != '' && format('-from-module={0}', inputs.arg_from_module) || '' }}
arg_generate_config_out: ${{ inputs.arg_generate_config_out != '' && format('-generate-config-out={0}', inputs.arg_generate_config_out) || '' }}
arg_get: ${{ inputs.arg_get != '' && format('-get={0}', inputs.arg_get) || '' }}
arg_ignore_remote_version: ${{ inputs.arg_ignore_remote_version != '' && format('-ignore-remote-version={0}', inputs.arg_ignore_remote_version) || '' }}
arg_json: ${{ inputs.arg_json != '' && format('-json={0}', inputs.arg_json) || '' }}
arg_list: ${{ inputs.arg_list != '' && format('-list={0}', inputs.arg_list) || '' }}
arg_lock: ${{ inputs.arg_lock != '' && format('-lock={0}', inputs.arg_lock) || '' }}
arg_lock_timeout: ${{ inputs.arg_lock_timeout != '' && format('-lock-timeout={0}', inputs.arg_lock_timeout) || '' }}
arg_lockfile: ${{ inputs.arg_lockfile != '' && format('-lockfile={0}', inputs.arg_lockfile) || '' }}
arg_migrate_state: ${{ inputs.arg_migrate_state != '' && format('-migrate-state={0}', inputs.arg_migrate_state) || '' }}
arg_no_tests: ${{ inputs.arg_no_tests != '' && format('-no-tests={0}', inputs.arg_no_tests) || '' }}
arg_or_create: ${{ inputs.arg_or_create != '' && format('-or-create={0}', inputs.arg_or_create) || '' }}
arg_out: ${{ inputs.arg_out != '' && format('-out={0}', inputs.arg_out) || '' }}
arg_parallelism: ${{ inputs.arg_parallelism != '' && format('-parallelism={0}', inputs.arg_parallelism) || '' }}
arg_plugin_dir: ${{ inputs.arg_plugin_dir != '' && format('-plugin-dir={0}', inputs.arg_plugin_dir) || '' }}
arg_reconfigure: ${{ inputs.arg_reconfigure != '' && format('-reconfigure={0}', inputs.arg_reconfigure) || '' }}
arg_recursive: ${{ inputs.arg_recursive != '' && format('-recursive={0}', inputs.arg_recursive) || '' }}
arg_refresh: ${{ inputs.arg_refresh != '' && format('-refresh={0}', inputs.arg_refresh) || '' }}
arg_refresh_only: ${{ inputs.arg_refresh_only != '' && format('-refresh-only={0}', inputs.arg_refresh_only) || '' }}
arg_replace: ${{ inputs.arg_replace != '' && format('-replace={0}', inputs.arg_replace) || '' }}
arg_state: ${{ inputs.arg_state != '' && format('-state={0}', inputs.arg_state) || '' }}
arg_state_out: ${{ inputs.arg_state_out != '' && format('-state-out={0}', inputs.arg_state_out) || '' }}
arg_target: ${{ inputs.arg_target != '' && format('-target={0}', inputs.arg_target) || '' }}
arg_test_directory: ${{ inputs.arg_test_directory != '' && format('-test-directory={0}', inputs.arg_test_directory) || '' }}
arg_upgrade: ${{ inputs.arg_upgrade != '' && format('-upgrade={0}', inputs.arg_upgrade) || '' }}
arg_var: ${{ inputs.arg_var != '' && format('-var={0}', inputs.arg_var) || '' }}
arg_var_file: ${{ inputs.arg_var_file != '' && format('-var-file={0}', inputs.arg_var_file) || '' }}
arg_workspace: ${{ inputs.arg_workspace }}
arg_workspace_alt: ${{ inputs.arg_workspace != '' && format('-workspace={0}', inputs.arg_workspace) || '' }}
arg_write: ${{ inputs.arg_write != '' && format('-write={0}', inputs.arg_write) || '' }}
with:
retries: 3
result-encoding: string
script: await require(`${process.env.GITHUB_ACTION_PATH}/action.js`)({ context, core, exec, github });
- name: Encrypt TF plan file
if: inputs.encrypt_passphrase != ''
env:
encrypt_passphrase: ${{ inputs.encrypt_passphrase }}
working_directory: ${{ inputs.arg_chdir }}/${{ inputs.arg_out }}
shell: bash
run: |
TEMP_FILE=$(mktemp)
printf %s "$encrypt_passphrase" > "$TEMP_FILE"
openssl enc -aes-256-ctr -pbkdf2 -salt -in "$working_directory" -out "$working_directory.encrypted" -pass file:"$TEMP_FILE"
mv "$working_directory.encrypted" "$working_directory"
- name: Upload TF plan file
if: inputs.arg_command == 'plan'
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
name: ${{ steps.tf.outputs.identifier }}
path: ${{ inputs.arg_chdir }}/${{ inputs.arg_out }}
overwrite: true