@@ -117,7 +117,7 @@ runs:
117
117
trap 'exit_code="$?"; echo "exit_code=$exit_code" >> "$GITHUB_OUTPUT"' EXIT
118
118
args="${{ steps.arg.outputs.arg-check }}${{ steps.arg.outputs.arg-diff }}${{ steps.arg.outputs.arg-list }}${{ steps.arg.outputs.arg-recursive }}${{ steps.arg.outputs.arg-write }}"
119
119
echo "${{ inputs.tool }} fmt${{ steps.arg.outputs.arg-chdir }}${args}" | sed 's/ -/\n -/g' > tf.command.txt
120
- ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} fmt${args} > >(tee -a tf.console.txt) 2> tf.console.txt
120
+ ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} fmt${args} > >(tee tf.console.txt) 2> >(tee tf.console.txt >&2)
121
121
122
122
- id : initialize
123
123
shell : bash
@@ -126,7 +126,7 @@ runs:
126
126
trap 'exit_code="$?"; echo "exit_code=$exit_code" >> "$GITHUB_OUTPUT"' EXIT
127
127
args="${{ steps.arg.outputs.arg-backend-config }}${{ steps.arg.outputs.arg-backend }}${{ steps.arg.outputs.arg-var-file }}${{ steps.arg.outputs.arg-var }}${{ steps.arg.outputs.arg-force-copy }}${{ steps.arg.outputs.arg-from-module }}${{ steps.arg.outputs.arg-get }}${{ steps.arg.outputs.arg-lock-timeout }}${{ steps.arg.outputs.arg-lock }}${{ steps.arg.outputs.arg-lockfile }}${{ steps.arg.outputs.arg-migrate-state }}${{ steps.arg.outputs.arg-plugin-dir }}${{ steps.arg.outputs.arg-reconfigure }}${{ steps.arg.outputs.arg-test-directory }}${{ steps.arg.outputs.arg-upgrade }}"
128
128
echo "${{ inputs.tool }} init${{ steps.arg.outputs.arg-chdir }}${args}" | sed 's/ -/\n -/g' > tf.command.txt
129
- ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} init${args} > >(tee -a tf.console.txt) 2> tf.console.txt
129
+ ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} init${args} > >(tee tf.console.txt) 2> >(tee tf.console.txt >&2)
130
130
131
131
- if : ${{ inputs.arg-workspace != '' }}
132
132
id : workspace
@@ -136,7 +136,7 @@ runs:
136
136
trap 'exit_code="$?"; echo "exit_code=$exit_code" >> "$GITHUB_OUTPUT"' EXIT
137
137
args="${{ steps.arg.outputs.arg-or-create }} ${{ inputs.arg-workspace }}"
138
138
echo "${{ inputs.tool }} workspace select${{ steps.arg.outputs.arg-chdir }}${args}" | sed 's/ -/\n -/g' > tf.command.txt
139
- ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} workspace select${args} > >(tee -a tf.console.txt) 2> tf.console.txt
139
+ ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} workspace select${args} > >(tee tf.console.txt) 2> >(tee tf.console.txt >&2)
140
140
141
141
- if : ${{ inputs.validate == 'true' }}
142
142
id : validate
@@ -146,7 +146,7 @@ runs:
146
146
trap 'exit_code="$?"; echo "exit_code=$exit_code" >> "$GITHUB_OUTPUT"' EXIT
147
147
args="${{ steps.arg.outputs.arg-var-file }}${{ steps.arg.outputs.arg-var }}${{ steps.arg.outputs.arg-no-tests }}${{ steps.arg.outputs.arg-test-directory }}"
148
148
echo "${{ inputs.tool }} validate${{ steps.arg.outputs.arg-chdir }}${args}" | sed 's/ -/\n -/g' > tf.command.txt
149
- ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} validate${args} > >(tee -a tf.console.txt) 2> tf.console.txt
149
+ ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} validate${args} > >(tee tf.console.txt) 2> >(tee tf.console.txt >&2)
150
150
151
151
- if : ${{ inputs.label-pr == 'true' && steps.identifier.outputs.pr != 0 }}
152
152
continue-on-error : true
@@ -166,7 +166,7 @@ runs:
166
166
trap 'exit_code="$?"; echo "exit_code=$exit_code" >> "$GITHUB_OUTPUT"; if [[ "$exit_code" == "2" ]]; then exit 0; fi' EXIT
167
167
args="${{ steps.arg.outputs.arg-destroy }}${{ steps.arg.outputs.arg-var-file }}${{ steps.arg.outputs.arg-var }}${{ steps.arg.outputs.arg-compact-warnings }}${{ steps.arg.outputs.arg-concise }}${{ steps.arg.outputs.arg-detailed-exitcode }}${{ steps.arg.outputs.arg-generate-config-out }}${{ steps.arg.outputs.arg-lock-timeout }}${{ steps.arg.outputs.arg-lock }}${{ steps.arg.outputs.arg-parallelism }}${{ steps.arg.outputs.arg-refresh-only }}${{ steps.arg.outputs.arg-refresh }}${{ steps.arg.outputs.arg-replace }}${{ steps.arg.outputs.arg-target }} -out=tf.plan"
168
168
echo "${{ inputs.tool }} plan${{ steps.arg.outputs.arg-chdir }}${args}" | sed 's/ -/\n -/g' > tf.command.txt
169
- ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} plan${args} > >(tee -a tf.console.txt) 2> tf.console.txt
169
+ ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} plan${args} > >(tee tf.console.txt) 2> >(tee tf.console.txt >&2)
170
170
171
171
- if : ${{ inputs.command == 'apply' && inputs.arg-auto-approve != 'true' }}
172
172
id : download
@@ -228,13 +228,13 @@ runs:
228
228
run : |
229
229
# TF plan parity.
230
230
# Generate a new plan file, then compare it with the previous one.
231
- # Both plan files are normalized by sorting and removing empty lines .
232
- ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} plan${{ steps.arg.outputs.arg-destroy }}${{ steps.arg.outputs.arg-var-file }}${{ steps.arg.outputs.arg-var }}${{ steps.arg.outputs.arg-compact-warnings }}${{ steps.arg.outputs.arg-concise }}${{ steps.arg.outputs.arg-detailed-exitcode }}${{ steps.arg.outputs.arg- generate-config-out }}${{ steps.arg.outputs.arg-lock-timeout }}${{ steps.arg.outputs.arg-lock }}${{ steps.arg.outputs.arg-parallelism }}${{ steps.arg.outputs.arg-refresh-only }}${{ steps.arg.outputs.arg-refresh }}${{ steps.arg.outputs.arg-replace }}${{ steps.arg.outputs.arg-target }} -out=tf.plan.parity > /dev/null
233
- ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} show${{ steps.arg.outputs.arg-var-file }}${{ steps.arg.outputs.arg-var }} tf.plan.parity | sort | sed '/^$/d ' > tf.plan.new
234
- cat tf.console.txt | sort | sed '/^$/d ' > tf.plan.old
231
+ # Both plan files are normalized by sorting JSON keys, removing timestamps and ${{ steps.arg.outputs.arg-detailed-exitcode }} to avoid false-positives .
232
+ ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} plan${{ steps.arg.outputs.arg-destroy }}${{ steps.arg.outputs.arg-var-file }}${{ steps.arg.outputs.arg-var }}${{ steps.arg.outputs.arg-compact-warnings }}${{ steps.arg.outputs.arg-concise }}${{ steps.arg.outputs.arg-generate-config-out }}${{ steps.arg.outputs.arg-lock-timeout }}${{ steps.arg.outputs.arg-lock }}${{ steps.arg.outputs.arg-parallelism }}${{ steps.arg.outputs.arg-refresh-only }}${{ steps.arg.outputs.arg-refresh }}${{ steps.arg.outputs.arg-replace }}${{ steps.arg.outputs.arg-target }} -out=tf.plan.parity
233
+ ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} show${{ steps.arg.outputs.arg-var-file }}${{ steps.arg.outputs.arg-var }} -json tf.plan.parity | jq -S 'del(.timestamp) ' > tf.plan.new
234
+ ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} show${{ steps.arg.outputs.arg-var-file }}${{ steps.arg.outputs.arg-var }} -json tf.plan | jq -S 'del(.timestamp) ' > tf.plan.old
235
235
236
236
# If both plan files are identical, then replace the old plan file with the new one to prevent avoidable stale apply.
237
- diff --brief tf.plan.new tf.plan.old > /dev/null && mv "${{ format('{0}{1}tf.plan.parity', inputs.arg-chdir || inputs.working-directory, (inputs.arg-chdir || inputs.working-directory) && '/' || '') }}" "${{ format('{0}{1}tf.plan', inputs.arg-chdir || inputs.working-directory, (inputs.arg-chdir || inputs.working-directory) && '/' || '') }}"
237
+ diff tf.plan.new tf.plan.old && mv "${{ format('{0}{1}tf.plan.parity', inputs.arg-chdir || inputs.working-directory, (inputs.arg-chdir || inputs.working-directory) && '/' || '') }}" "${{ format('{0}{1}tf.plan', inputs.arg-chdir || inputs.working-directory, (inputs.arg-chdir || inputs.working-directory) && '/' || '') }}"
238
238
rm -f tf.plan.new tf.plan.old "${{ format('{0}{1}tf.plan.parity', inputs.arg-chdir || inputs.working-directory, (inputs.arg-chdir || inputs.working-directory) && '/' || '') }}"
239
239
240
240
- id : apply
@@ -255,7 +255,7 @@ runs:
255
255
fi
256
256
args="${{ steps.arg.outputs.arg-destroy }}${var_file}${var}${{ steps.arg.outputs.arg-backup }}${{ steps.arg.outputs.arg-compact-warnings }}${{ steps.arg.outputs.arg-concise }}${{ steps.arg.outputs.arg-lock-timeout }}${{ steps.arg.outputs.arg-lock }}${{ steps.arg.outputs.arg-parallelism }}${{ steps.arg.outputs.arg-refresh-only }}${{ steps.arg.outputs.arg-refresh }}${{ steps.arg.outputs.arg-replace }}${{ steps.arg.outputs.arg-state-out }}${{ steps.arg.outputs.arg-state }}${{ steps.arg.outputs.arg-target }}${plan}"
257
257
echo "${{ inputs.tool }} apply${{ steps.arg.outputs.arg-chdir }}${args}" | sed 's/ -/\n -/g' > tf.command.txt
258
- ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} apply${args} > >(tee -a tf.console.txt) 2> tf.console.txt
258
+ ${{ inputs.tool }}${{ steps.arg.outputs.arg-chdir }} apply${args} > >(tee tf.console.txt) 2> >(tee tf.console.txt >&2)
259
259
260
260
- id : post
261
261
if : ${{ !cancelled() && steps.identifier.outcome == 'success' }}
@@ -268,20 +268,21 @@ runs:
268
268
# Remove each comma-delemited argument from the command.
269
269
IFS=',' read -ra args <<< "${{ inputs.hide-args }}"
270
270
for arg in "${args[@]}"; do
271
- command=$(echo "$command" | grep -v "^ -${arg}\b")
271
+ command=$(echo "$command" | grep --invert-match "^ -${arg}\b")
272
272
done
273
273
command=$(echo "$command" | tr -d '\n')
274
274
echo "command=$command" >> "$GITHUB_OUTPUT"
275
275
276
276
# Parse the tf.console.txt file, truncated for character limit.
277
- console=$(grep -v '\.\.\.$' tf.console.txt | head -c 42000 | sed '${/^ /d}')
277
+ console=$(grep --invert-match '\.\.\.' tf.console.txt | head --bytes=42000 || true)
278
+ if [[ ${#console} -eq 42000 ]]; then console="${console}"$'\n…'; fi
278
279
{ echo 'result<<EOTFVIAPR'
279
280
echo "$console"
280
281
echo EOTFVIAPR
281
282
} >> "$GITHUB_OUTPUT"
282
283
283
284
# Parse the tf.console.txt file for the summary.
284
- summary=$(cat tf.console.txt | tac | grep -m 1 -E '^(Error:|Plan:|Apply complete!|No changes.|Success)' | tac || echo "View output.")
285
+ summary=$(tac tf.console.txt | grep -m 1 -E '^(Error:|Plan:|Apply complete!|No changes.|Success)' | tac || echo "View output.")
285
286
echo "summary=$summary" >> "$GITHUB_OUTPUT"
286
287
287
288
# Add summary to the job status.
@@ -295,16 +296,23 @@ runs:
295
296
296
297
# If tf.diff.txt exists, display it within a diff block, truncated for character limit.
297
298
if [[ -s tf.diff.txt ]]; then
299
+ # Get count of lines in tf.diff.txt which don't start with "# ".
300
+ diff_count=$(grep --invert-match '^# ' tf.diff.txt | wc -l)
301
+ if [[ $diff_count -eq 1 ]]; then diff_change="change"; else diff_change="changes"; fi
302
+
303
+ # Parse diff of changes, truncated for character limit.
304
+ diff_truncated=$(head --bytes=24000 tf.diff.txt)
305
+ if [[ ${#diff_truncated} -eq 24000 ]]; then diff_truncated="${diff_truncated}"$'\n…'; fi
298
306
{ echo 'diff<<EOTFVIAPR'
299
- head -c 24000 tf.diff.txt
307
+ echo "$diff_truncated"
300
308
echo EOTFVIAPR
301
309
} >> "$GITHUB_OUTPUT"
302
310
303
311
diff="
304
- <details><summary>Diff of changes .</summary>
312
+ <details><summary>Diff of ${diff_count} ${diff_change} .</summary>
305
313
306
314
\`\`\`diff
307
- $(head -c 24000 tf.diff.txt)
315
+ ${diff_truncated}
308
316
\`\`\`
309
317
</details>"
310
318
else
0 commit comments