Skip to content

Commit ab290b0

Browse files
committed
Add support for ephemeral variables in terraform >= 1.10.0
These must be specified again when applying a saved plan, but must not be specified in earlier versions of Terraform or OpenTofu
1 parent 4d4081d commit ab290b0

File tree

6 files changed

+168
-20
lines changed

6 files changed

+168
-20
lines changed

.github/workflows/test-apply.yaml

+97
Original file line numberDiff line numberDiff line change
@@ -1430,3 +1430,100 @@ jobs:
14301430
uses: ./terraform-apply
14311431
with:
14321432
path: tests/workflows/test-apply/outputs
1433+
1434+
ephemeral:
1435+
runs-on: ubuntu-24.04
1436+
name: Apply a plan with ephemeral variables
1437+
permissions:
1438+
contents: read
1439+
pull-requests: write
1440+
env:
1441+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1442+
steps:
1443+
- name: Checkout
1444+
uses: actions/checkout@v4
1445+
with:
1446+
persist-credentials: false
1447+
1448+
- name: Plan using default ephemeral value
1449+
uses: ./terraform-plan
1450+
with:
1451+
label: test-apply ephemeral
1452+
path: tests/workflows/test-apply/ephemeral
1453+
1454+
- name: Apply using default ephemeral value
1455+
uses: ./terraform-apply
1456+
id: apply
1457+
with:
1458+
label: test-apply ephemeral
1459+
path: tests/workflows/test-apply/ephemeral
1460+
1461+
- name: Verify outputs
1462+
env:
1463+
OUTPUT_STRING: ${{ steps.apply.outputs.v }}
1464+
run: |
1465+
if [[ "$OUTPUT_STRING" != "non-ephemeral" ]]; then
1466+
echo "::error:: output s not set correctly"
1467+
exit 1
1468+
fi
1469+
1470+
##
1471+
1472+
- name: Plan using explicit ephemeral value
1473+
uses: ./terraform-plan
1474+
with:
1475+
label: test-apply ephemeral 2
1476+
path: tests/workflows/test-apply/ephemeral
1477+
variables: |
1478+
region = "eu-west-1"
1479+
mv = "hello"
1480+
1481+
- name: Apply using explicit ephemeral value
1482+
uses: ./terraform-apply
1483+
id: apply2
1484+
with:
1485+
label: test-apply ephemeral 2
1486+
path: tests/workflows/test-apply/ephemeral
1487+
variables: |
1488+
region = "eu-west-1"
1489+
mv = "hello"
1490+
1491+
- name: Verify outputs
1492+
env:
1493+
OUTPUT_STRING: ${{ steps.apply2.outputs.v }}
1494+
run: |
1495+
if [[ "$OUTPUT_STRING" != "hello" ]]; then
1496+
echo "::error:: output s not set correctly"
1497+
exit 1
1498+
fi
1499+
1500+
##
1501+
1502+
- name: Plan using explicit non-ephemeral value
1503+
uses: ./terraform-plan
1504+
with:
1505+
label: test-apply ephemeral 3
1506+
path: tests/workflows/test-apply/ephemeral
1507+
variables: |
1508+
region = "eu-west-2"
1509+
mv = "goodbye"
1510+
1511+
- name: Apply using mismatched explicit non-ephemeral value
1512+
uses: ./terraform-apply
1513+
continue-on-error: true
1514+
id: apply3
1515+
with:
1516+
label: test-apply ephemeral 3
1517+
path: tests/workflows/test-apply/ephemeral
1518+
variables: |
1519+
region = "eu-west-2"
1520+
mv = "mismatch"
1521+
1522+
- name: Check failed to apply
1523+
env:
1524+
OUTCOME: ${{ steps.apply3.outcome }}
1525+
run: |
1526+
if [[ "$OUTCOME" != "failure" ]]; then
1527+
echo "Apply did not fail correctly"
1528+
exit 1
1529+
fi

image/actions.sh

+25-9
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,8 @@ function set-common-plan-args() {
360360
}
361361

362362
function set-variable-args() {
363+
VARIABLE_ARGS=""
364+
363365
if [[ -n "$INPUT_VAR_FILE" ]]; then
364366
for file in $(echo "$INPUT_VAR_FILE" | tr ',' '\n'); do
365367

@@ -368,32 +370,46 @@ function set-variable-args() {
368370
exit 1
369371
fi
370372

371-
PLAN_ARGS="$PLAN_ARGS -var-file=$(relative_to "$INPUT_PATH" "$file")"
373+
VARIABLE_ARGS="$VARIABLE_ARGS -var-file=$(relative_to "$INPUT_PATH" "$file")"
372374
done
373375
fi
374376

375377
if [[ -n "$INPUT_VARIABLES" ]]; then
376378
echo "$INPUT_VARIABLES" >"$STEP_TMP_DIR/variables.tfvars"
377-
PLAN_ARGS="$PLAN_ARGS -var-file=$STEP_TMP_DIR/variables.tfvars"
379+
VARIABLE_ARGS="$VARIABLE_ARGS -var-file=$STEP_TMP_DIR/variables.tfvars"
378380
fi
379381
}
380382

381-
function set-plan-args() {
382-
set-common-plan-args
383+
function set-deprecated-var-args() {
384+
DEPRECATED_VAR_ARGS=""
383385

384386
if [[ -n "$INPUT_VAR" ]]; then
385387
for var in $(echo "$INPUT_VAR" | tr ',' '\n'); do
386-
PLAN_ARGS="$PLAN_ARGS -var $var"
388+
DEPRECATED_VAR_ARGS="$DEPRECATED_VAR_ARGS -var $var"
387389
done
388390
fi
391+
}
389392

393+
function masked-deprecated-vars() {
394+
if [[ -n "$DEPRECATED_VAR_ARGS" ]]; then
395+
echo "-var <masked>"
396+
else
397+
echo ""
398+
fi
399+
}
400+
401+
function set-plan-args() {
402+
set-common-plan-args
403+
set-deprecated-var-args
390404
set-variable-args
391405

392406
export PLAN_ARGS
393407
}
394408

395409
function set-remote-plan-args() {
396410
set-common-plan-args
411+
VARIABLE_ARGS=""
412+
DEPRECATED_VAR_ARGS=""
397413

398414
local AUTO_TFVARS_COUNTER=0
399415

@@ -466,11 +482,11 @@ function plan() {
466482
fi
467483

468484
# shellcheck disable=SC2086
469-
debug_log $TOOL_COMMAND_NAME plan -input=false -no-color -detailed-exitcode -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT_ARG '$PLAN_ARGS' # don't expand PLAN_ARGS
485+
debug_log $TOOL_COMMAND_NAME plan -input=false -no-color -detailed-exitcode -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT_ARG $PLAN_ARGS "$(masked-deprecated-vars)" $VARIABLE_ARGS
470486

471487
set +e
472488
# shellcheck disable=SC2086
473-
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME plan -input=false -no-color -detailed-exitcode -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT_ARG $PLAN_ARGS) \
489+
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME plan -input=false -no-color -detailed-exitcode -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT_ARG $PLAN_ARGS $DEPRECATED_VAR_ARGS $VARIABLE_ARGS ) \
474490
2>"$STEP_TMP_DIR/terraform_plan.stderr" \
475491
| $TFMASK \
476492
| tee /dev/fd/3 "$STEP_TMP_DIR/terraform_plan.stdout" \
@@ -494,11 +510,11 @@ function plan() {
494510

495511
function destroy() {
496512
# shellcheck disable=SC2086
497-
debug_log $TOOL_COMMAND_NAME destroy -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS
513+
debug_log $TOOL_COMMAND_NAME destroy -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS "$(masked-deprecated-vars)" $VARIABLE_ARGS
498514

499515
set +e
500516
# shellcheck disable=SC2086
501-
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME destroy -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS) \
517+
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME destroy -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS $DEPRECATED_VAR_ARGS $VARIABLE_ARGS) \
502518
2>"$STEP_TMP_DIR/terraform_destroy.stderr" \
503519
| tee /dev/fd/3 \
504520
>"$STEP_TMP_DIR/terraform_destroy.stdout"

image/entrypoints/apply.sh

+16-6
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,33 @@ function apply() {
3232
set +e
3333
if [[ -n "$PLAN_OUT" ]]; then
3434

35+
# With Terrraform >= 1.10 Ephemeral variables must be specified again in the apply command.
36+
# Non-ephemeral variables may be specified again, but may not be different from the plan.
37+
# Terraform < 1.1.0 must not specify any variables when applying a saved plan.
38+
39+
SAVED_PLAN_VARIABLES=""
40+
if [[ "$TOOL_PRODUCT_NAME" == "Terraform" ]] && test-terraform-version ">=" "1.10.0"; then
41+
SAVED_PLAN_VARIABLES="$VARIABLE_ARGS"
42+
fi
43+
3544
# shellcheck disable=SC2086
36-
debug_log $TOOL_COMMAND_NAME apply -input=false -no-color -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT
45+
debug_log $TOOL_COMMAND_NAME apply -input=false -no-color -lock-timeout=300s $PARALLEL_ARG $SAVED_PLAN_VARIABLES $PLAN_OUT
3746
# shellcheck disable=SC2086
38-
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME apply -input=false -no-color -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT) \
47+
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME apply -input=false -no-color -lock-timeout=300s $PARALLEL_ARG $SAVED_PLAN_VARIABLES $PLAN_OUT) \
3948
2>"$STEP_TMP_DIR/terraform_apply.stderr" \
4049
| $TFMASK \
4150
| tee "$STEP_TMP_DIR/terraform_apply.stdout"
4251
APPLY_EXIT=${PIPESTATUS[0]}
4352
>&2 cat "$STEP_TMP_DIR/terraform_apply.stderr"
53+
4454
else
4555
# There is no plan file to apply, since the remote backend can't produce them.
4656
# Instead we need to do an auto approved apply using the arguments we would normally use for the plan
4757

58+
# shellcheck disable=SC2086,SC2016
59+
debug_log $TOOL_COMMAND_NAME apply -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS "$(masked-deprecated-vars)" $VARIABLE_ARGS
4860
# shellcheck disable=SC2086
49-
debug_log $TOOL_COMMAND_NAME apply -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG '$PLAN_ARGS' # don't expand plan args
50-
# shellcheck disable=SC2086
51-
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME apply -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS) \
61+
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME apply -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS $DEPRECATED_VAR_ARGS $VARIABLE_ARGS) \
5262
2>"$STEP_TMP_DIR/terraform_apply.stderr" \
5363
| $TFMASK \
5464
| tee "$STEP_TMP_DIR/terraform_apply.stdout"
@@ -95,7 +105,7 @@ if [[ "$INPUT_PLAN_PATH" != "" ]]; then
95105
exit 1
96106
fi
97107

98-
PLAN_OUT=$(realpath $INPUT_PLAN_PATH)
108+
PLAN_OUT=$(realpath "$INPUT_PLAN_PATH")
99109
PLAN_EXIT=2
100110
else
101111
plan

image/entrypoints/test.sh

+2-3
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ function set-test-args() {
3030

3131
function test() {
3232

33-
debug_log $TOOL_COMMAND_NAME test -no-color $TEST_ARGS '$PLAN_ARGS' # don't expand PLAN_ARGS
33+
debug_log $TOOL_COMMAND_NAME test -no-color $TEST_ARGS $VARIABLE_ARGS
3434

3535
set +e
3636
# shellcheck disable=SC2086
37-
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME test -no-color $TEST_ARGS $PLAN_ARGS) \
37+
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME test -no-color $TEST_ARGS $VARIABLE_ARGS) \
3838
2>"$STEP_TMP_DIR/terraform_test.stderr" \
3939
| tee /dev/fd/3 \
4040
>"$STEP_TMP_DIR/terraform_test.stdout"
@@ -59,7 +59,6 @@ function test() {
5959
}
6060

6161
set-test-args
62-
PLAN_ARGS=""
6362
set-variable-args
6463

6564
test

image/src/github_pr_comment/__main__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -642,8 +642,6 @@ def main() -> int:
642642

643643
debug(f'diff {proposed_plan_path} {approved_plan_path}')
644644
diff_complete = subprocess.run(['diff', proposed_plan_path, approved_plan_path], check=False, capture_output=True, encoding='utf-8')
645-
sys.stdout.write(diff_complete.stdout)
646-
sys.stderr.write(diff_complete.stderr)
647645

648646
if diff_complete.returncode != 0:
649647
sys.stdout.write("""Performing diff between the pull request plan and the plan generated at execution time.
@@ -652,6 +650,9 @@ def main() -> int:
652650
Plan differences:
653651
""")
654652

653+
sys.stdout.write(diff_complete.stdout)
654+
sys.stderr.write(diff_complete.stderr)
655+
655656
if comment.headers.get('plan_text_format', 'text').endswith('trunc'):
656657
sys.stdout.write('\nThe plan text was too large for a PR comment, not all differences may be shown here.')
657658

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
variable "region" {
2+
type = string
3+
default = "eu-west-2"
4+
}
5+
6+
variable "mv" {
7+
type = string
8+
default = "non-ephemeral"
9+
}
10+
11+
provider "aws" {
12+
region = var.region
13+
}
14+
15+
output "v" {
16+
value = var.mv
17+
}
18+
19+
resource "random_string" "add" {
20+
length = 5
21+
}
22+
23+
terraform {
24+
required_version = ">=1.10"
25+
}

0 commit comments

Comments
 (0)