Skip to content

Commit ea15338

Browse files
committed
test: add cross-stack E2E tests
1 parent 89cef3c commit ea15338

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

stacks-test-e2e.sh

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env bashunit
2+
3+
# Run full e2e tests operating on the example/ directory
4+
5+
set_up() {
6+
cd example
7+
export MAKE="make -f ../stacks.mk ENV=dev-eu CLICOLOR_FORCE=0"
8+
}
9+
10+
tear_down() {
11+
$MAKE deepclean && rm -rf ../registry.opentofu.org
12+
}
13+
14+
test_plan_apply_refresh_destroy_clean() {
15+
# Run an initial full plan and apply to have a clean state
16+
output="$($MAKE plan)"
17+
assert_matches '\[network/vpc.*Plan.*0 to destroy' "$output"
18+
assert_matches '\[instances.*Plan.*0 to destroy' "$output"
19+
assert_matches '\[org.*Plan.*0 to destroy' "$output"
20+
output="$($MAKE plan)"
21+
assert_matches 'Nothing to be done for.*plan' "$output"
22+
touch instances/main.tf
23+
output="$($MAKE plan)"
24+
assert_not_matches '\[network/vpc' "$output"
25+
assert_matches '\[instances.*Plan.*0 to destroy' "$output"
26+
assert_not_matches '\[org' "$output"
27+
output=$($MAKE apply)
28+
assert_matches '\[network/vpc.*Apply complete' "$output"
29+
assert_matches '\[instances.*Apply complete' "$output"
30+
assert_matches '\[org.*Apply complete' "$output"
31+
output=$($MAKE refresh)
32+
assert_matches '\[network/vpc.*Outputs:' "$output"
33+
assert_matches '\[instances.*Outputs:' "$output"
34+
assert_matches '\[org.*Outputs:' "$output"
35+
output=$($MAKE plan)
36+
assert_matches '\[network/vpc.*No changes' "$output"
37+
assert_matches '\[instances.*No changes' "$output"
38+
assert_matches '\[org.*No changes' "$output"
39+
output=$($MAKE plan)
40+
assert_matches 'Nothing to be done for.*plan' "$output"
41+
output=$(TF_CLI_ARGS='-auto-approve' $MAKE destroy)
42+
assert_matches '\[network/vpc.*Destroy complete' "$output"
43+
assert_matches '\[instances.*Destroy complete' "$output"
44+
assert_matches '\[org.*Destroy complete' "$output"
45+
output=$($MAKE clean)
46+
assert_contains "network/vpc/$ENV" "$output"
47+
assert_contains "instances/$ENV" "$output"
48+
assert_contains "org/$ENV" "$output"
49+
50+
# cleanup
51+
rm .terraform.lock.hcl
52+
assert_empty "$(git status --porcelain -- .)"
53+
}
54+
55+
test_plan_changed() {
56+
# Run an initial full plan and apply to have a clean state
57+
$MAKE plan >/dev/null 2>&1
58+
$MAKE apply >/dev/null 2>&1
59+
60+
# test dynamic skipping
61+
echo '# change' >> network/vpc/main.tf
62+
output=$($MAKE plan-changed DIFF_BASE=HEAD)
63+
assert_matches '\[network/vpc.*No changes' "$output"
64+
assert_matches 'Skip.*instances' "$output"
65+
assert_not_matches '\[org' "$output"
66+
# test downstream dependencies of changed stacks
67+
echo 'output "new" { value = 123 }' >> network/vpc/main.tf
68+
output=$($MAKE plan-changed DIFF_BASE=HEAD)
69+
assert_matches '\[network/vpc.*Plan.*0 to destroy' "$output"
70+
assert_matches '\[instances.*Plan.*0 to destroy' "$output"
71+
assert_not_matches '\[org.*Plan' "$output"
72+
output=$($MAKE apply-changed DIFF_BASE=HEAD)
73+
assert_matches '\[network/vpc.*Apply complete' "$output"
74+
assert_matches '\[instances.*Apply complete' "$output"
75+
assert_not_matches '\[org.*Apply' "$output"
76+
77+
# cleanup
78+
$MAKE clean >/dev/null 2>&1
79+
rm .terraform.lock.hcl
80+
git checkout network/vpc/main.tf
81+
assert_empty "$(git status --porcelain -- .)"
82+
}
83+
84+
test_failed_apply_stale_plan() {
85+
# break 'instances' main.tf to fail during apply
86+
echo -e 'resource "terraform_data" "fail" {\nprovisioner "local-exec" {\n command = "exit 1"\n}\n}' >> instances/main.tf
87+
output=$($MAKE plan)
88+
assert_matches '\[instances.*Plan.*0 to destroy' "$output"
89+
# The apply should fail
90+
! $MAKE apply >/dev/null 2>&1
91+
# plan should be stale and get replanned
92+
output=$($MAKE plan)
93+
assert_matches 'terraform_data.*fail.*is tainted' "$output"
94+
assert_matches '\[instances.*Plan.*1 to destroy' "$output"
95+
96+
# cleanup
97+
$MAKE clean >/dev/null 2>&1
98+
rm .terraform.lock.hcl
99+
git checkout instances/main.tf
100+
assert_empty "$(git status --porcelain -- .)"
101+
}

stacks-test.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,21 @@ test_tfvars_precedence() {
5959
assert_contains '/network_2-dev-eu-.auto.tfvars: network/dev-eu.tfvars' "$output"
6060
}
6161

62+
63+
test_cross_stack_dependencies() {
64+
# Run the script to test cross-stack dependency extraction
65+
cd example/
66+
output=$(bash ../stacks-gen-deps.sh dev-eu 2 network/vpc instances network/vpc/main.tf instances/main.tf)
67+
68+
# Check for downstream/upstream mapping
69+
assert_contains 'DOWNSTREAMS_network/vpc += instances' "$output"
70+
assert_contains 'UPSTREAMS_instances += network/vpc' "$output"
71+
72+
# Check for plan and outputs dependencies
73+
assert_matches 'instances/[^/]+/tfplan.json: .*network/vpc/[^/]+/tfplan.json' "$output"
74+
assert_matches 'instances/[^/]+/outputs.json: .*network/vpc/[^/]+/outputs.json' "$output"
75+
76+
# Check for destroy and refresh dependencies
77+
assert_matches 'network/vpc/[^/]+/.destroy: destroy-instances' "$output"
78+
assert_matches 'instances/[^/]+/.refresh: refresh-network/vpc' "$output"
79+
}

0 commit comments

Comments
 (0)