-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdestroy-pr-environment
More file actions
executable file
·133 lines (111 loc) · 4.58 KB
/
Copy pathdestroy-pr-environment
File metadata and controls
executable file
·133 lines (111 loc) · 4.58 KB
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
#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# Destroy the temporary environment that was created for the pull request.
#
# Positional parameters:
# app_name (required) – the name of subdirectory of /infra that holds the
# application's infrastructure code.
# environment - the name of the application environment (e.g. dev, staging, prod)
# pr_number - the pull request number in GitHub
# -----------------------------------------------------------------------------
set -euo pipefail
app_name="$1"
environment="$2"
pr_number="$3"
# Validate app_name
if [ ! -d "infra/${app_name}/service" ]; then
echo "Error: App '${app_name}' not found in infra/"
exit 1
fi
workspace="p-${pr_number}"
# Safety check: never allow deleting the default workspace
if [ "$workspace" = "default" ] || [ -z "$workspace" ]; then
echo "Error: Refusing to delete default or empty workspace"
exit 1
fi
echo "::group::Initialize Terraform with backend for environment: ${environment}"
terraform -chdir="infra/${app_name}/service" init -backend-config="${environment}.azurerm.tfbackend"
echo "::endgroup::"
echo "Check if Terraform workspace exists: ${workspace}"
# List workspaces and check if our workspace exists
# Note: workspace list shows current workspace with "* " prefix, others with " " prefix
if terraform -chdir="infra/${app_name}/service" workspace list | grep -qE "^[* ] +${workspace}$"; then
echo "Workspace ${workspace} exists, proceeding with destroy"
else
echo "Workspace ${workspace} does not exist - nothing to destroy"
echo "This can happen if the workspace was already cleaned up or never created"
exit 0
fi
echo "Select Terraform workspace: ${workspace}"
terraform -chdir="infra/${app_name}/service" workspace select "${workspace}"
echo "::group::Destroy resources"
# Retry terraform destroy to handle transient Azure API errors
max_tf_attempts=3
tf_attempt=0
tf_success=false
while [ $tf_attempt -lt $max_tf_attempts ] && [ "$tf_success" = "false" ]; do
tf_attempt=$((tf_attempt + 1))
if [ $tf_attempt -gt 1 ]; then
echo "Retry attempt ${tf_attempt}/${max_tf_attempts} after transient failure..."
fi
if terraform -chdir="infra/${app_name}/service" destroy -var="environment_name=${environment}" -input=false -auto-approve; then
tf_success=true
echo "Terraform destroy succeeded"
else
if [ $tf_attempt -lt $max_tf_attempts ]; then
echo "Terraform destroy failed, waiting 30s before retry..."
sleep 30
fi
fi
done
if [ "$tf_success" = "false" ]; then
echo "Error: Terraform destroy failed after ${max_tf_attempts} attempts"
exit 1
fi
echo "::endgroup::"
echo "Select default workspace"
terraform -chdir="infra/${app_name}/service" workspace select default
echo "Delete workspace: ${workspace}"
terraform -chdir="infra/${app_name}/service" workspace delete "${workspace}"
pr_info=$(cat <<EOF
<!-- ${app_name} - begin PR environment info -->
## Preview environment for ${app_name}
♻️ Environment destroyed ♻️
<!-- ${app_name} - end PR environment info -->
EOF
)
echo "Update PR description with PR environment info"
echo "${pr_info}"
# Retry to handle transient GitHub API errors when updating the PR body. This
# does NOT protect against races between concurrent workflows updating the same
# PR body; that requires a locking/read-modify-write fix tracked in
# https://github.com/navapbc/template-infra/issues/982
# TODO(https://github.com/navapbc/template-infra/issues/982): handle concurrent PR body updates
max_attempts=5
attempt=0
updated=false
while [ $attempt -lt $max_attempts ] && [ "$updated" = "false" ]; do
attempt=$((attempt + 1))
# Read current PR body
pr_body="$(gh pr view "${pr_number}" --json body | jq --raw-output .body)"
if [[ $pr_body == *"<!-- ${app_name} - begin PR environment info -->"*"<!-- ${app_name} - end PR environment info -->"* ]]; then
pr_body="${pr_body//<!-- ${app_name} - begin PR environment info -->*<!-- ${app_name} - end PR environment info -->/$pr_info}"
else
pr_body="${pr_body}"$'\n\n'"${pr_info}"
fi
# Try to update the PR body
if gh pr edit "${pr_number}" --body "${pr_body}"; then
updated=true
echo "Successfully updated PR description"
else
if [ $attempt -lt $max_attempts ]; then
echo "Failed to update PR description (attempt ${attempt}/${max_attempts}), retrying in 2s..."
sleep 2
fi
fi
done
if [ "$updated" = "false" ]; then
echo "Warning: Failed to update PR description after ${max_attempts} attempts"
# Don't fail the workflow just because we couldn't update the PR body
echo "Continuing despite PR update failure..."
fi