Skip to content

Commit ee50873

Browse files
committed
Add a workflow to deal with provider locks
- if dependabot opened the PR, commit any updated lock files - if a human opened the PR, fail if lock files are not updated
1 parent 456a377 commit ee50873

2 files changed

Lines changed: 213 additions & 9 deletions

File tree

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
name: Update Provider Lock Files
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- "infra/shared/versions.tf"
7+
8+
jobs:
9+
update-locks:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
18+
with:
19+
# Use the pull request head ref to ensure we're on the PR branch
20+
ref: ${{ github.head_ref }}
21+
# Use PAT for Dependabot PRs, regular token for others
22+
token: ${{ github.actor == 'dependabot[bot]' && secrets.DEPENDABOT_PAT || secrets.GITHUB_TOKEN }}
23+
24+
- name: Set up Go
25+
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
26+
27+
- name: Install tfupdate
28+
run: |
29+
go install github.com/minamijoyo/tfupdate@latest
30+
31+
- name: Install hcl2json
32+
run: |
33+
go install github.com/tmccombs/hcl2json@latest
34+
35+
- name: Run lock update script
36+
run: |
37+
./infra/scripts/upgrade_tf_version.sh --lock-only
38+
39+
- name: Check for changed files
40+
id: git-check
41+
run: |
42+
# Check if there are any changes
43+
if git diff --quiet && git diff --cached --quiet; then
44+
echo "changed=false" >> "${GITHUB_OUTPUT}"
45+
echo "No changes detected"
46+
else
47+
echo "changed=true" >> "${GITHUB_OUTPUT}"
48+
echo "Changes detected:"
49+
git diff --name-only
50+
fi
51+
52+
- name: Handle Dependabot PR - commit lock files
53+
if: steps.git-check.outputs.changed == 'true' && github.actor == 'dependabot[bot]'
54+
env:
55+
PUSH_REF: ${{ github.head_ref }}
56+
run: |
57+
git config --local user.email "action@github.com"
58+
git config --local user.name "GitHub Action"
59+
60+
# Add only .terraform.lock.hcl files
61+
git add '**/.terraform.lock.hcl'
62+
63+
# Check if there are staged changes
64+
if git diff --cached --quiet; then
65+
echo "No .terraform.lock.hcl files to commit"
66+
else
67+
git commit -m "Update provider lock files"
68+
# Push using the PAT token configured in checkout
69+
git push origin HEAD:"${PUSH_REF}"
70+
fi
71+
72+
- name: Check for uncommitted changes (Dependabot PR)
73+
if: github.actor == 'dependabot[bot]'
74+
run: |
75+
# After committing lock files, check if there are still any changes
76+
if ! git diff --quiet || ! git diff --cached --quiet; then
77+
echo "Error: There are still uncommitted changes after processing lock files:"
78+
git status --porcelain
79+
echo ""
80+
echo "Changed files:"
81+
git diff --name-only
82+
if git diff --cached --quiet; then
83+
echo "No staged changes"
84+
else
85+
echo "Staged changes:"
86+
git diff --cached --name-only
87+
fi
88+
echo ""
89+
echo "This suggests there are changes beyond just .terraform.lock.hcl files that need attention."
90+
exit 1
91+
else
92+
echo "All changes have been properly handled"
93+
fi
94+
95+
- name: Check for missing lock updates (Non-Dependabot PR)
96+
if: steps.git-check.outputs.changed == 'true' && github.actor != 'dependabot[bot]'
97+
env:
98+
COMMENT_MARKER: "<!-- provider-locks: missing updates -->"
99+
GH_TOKEN: ${{ github.token }}
100+
run: |
101+
# SC2296: GitHub Actions uses `${{ ... }}` for expressions, which shellcheck misinterprets as invalid parameter expansion.
102+
# shellcheck disable=SC2296
103+
# SC2016: Expressions like `${{ ... }}` are not standard shell and are used by GitHub Actions; shellcheck would incorrectly flag them.
104+
# shellcheck disable=SC2016
105+
echo "Error: Provider lock files are out of date!"
106+
echo ""
107+
echo "You have modified infra/shared/versions.tf but the corresponding .terraform.lock.hcl files"
108+
echo "have not been updated. Please run the following command locally and commit the changes:"
109+
echo ""
110+
echo " ./infra/scripts/upgrade_tf_version.sh --lock-only"
111+
echo ""
112+
echo "Changed files detected:"
113+
git status --porcelain
114+
echo ""
115+
git diff --name-only
116+
117+
# Leave a comment on the PR
118+
cat <<EOF > "${{runner.temp}}/pr-comment.md"
119+
> [!WARNING]
120+
> **Provider lock files are out of date!**
121+
>
122+
> You have modified \`infra/shared/versions.tf\` but the corresponding \`.terraform.lock.hcl\` files
123+
> have not been updated. Please run the following command locally and commit the changes:
124+
>
125+
> \`\`\`bash
126+
> ./infra/scripts/upgrade_tf_version.sh --lock-only
127+
> \`\`\`
128+
129+
${COMMENT_MARKER}
130+
EOF
131+
132+
# Remove any existing comments from this workflow
133+
old_comment_ids=$(gh api "repos/{owner}/{repo}/issues/${{github.event.pull_request.number}}/comments" --jq 'map(select((.user.login == "github-actions[bot]") and (.body | endswith($ENV.COMMENT_MARKER + "\n")))) | .[].id')
134+
for comment_id in $old_comment_ids; do
135+
gh api -X DELETE "repos/{owner}/{repo}/issues/comments/${comment_id}"
136+
done
137+
138+
gh pr comment "${{github.event.pull_request.html_url}}" --body-file "${{runner.temp}}/pr-comment.md"
139+
140+
exit 1
141+
142+
- name: Comment on Dependabot PR success
143+
if: steps.git-check.outputs.changed == 'true' && github.actor == 'dependabot[bot]'
144+
env:
145+
COMMENT_MARKER: "<!-- provider-locks: dependabot updated -->"
146+
GH_TOKEN: ${{ github.token }}
147+
run: |
148+
# shellcheck disable=SC2296
149+
# shellcheck disable=SC2016
150+
# Leave a comment on the PR
151+
cat <<EOF > "${{runner.temp}}/pr-comment.md"
152+
> [!NOTE]
153+
> **Provider lock files have been automatically updated**
154+
>
155+
> This Dependabot PR modified \`infra/shared/versions.tf\`, so the corresponding
156+
> \`.terraform.lock.hcl\` files have been automatically updated and committed.
157+
>
158+
> The changes are ready for review and merge.
159+
160+
${COMMENT_MARKER}
161+
EOF
162+
163+
# Remove any existing comments from this workflow
164+
old_comment_ids=$(gh api "repos/{owner}/{repo}/issues/${{github.event.pull_request.number}}/comments" --jq 'map(select((.user.login == "github-actions[bot]") and (.body | endswith($ENV.COMMENT_MARKER + "\n")))) | .[].id')
165+
for comment_id in $old_comment_ids; do
166+
gh api -X DELETE "repos/{owner}/{repo}/issues/comments/${comment_id}"
167+
done
168+
169+
gh pr comment "${{github.event.pull_request.html_url}}" --body-file "${{runner.temp}}/pr-comment.md"
170+
171+
- name: Remove stale comments when no changes needed
172+
if: steps.git-check.outputs.changed == 'false'
173+
env:
174+
COMMENT_MARKER_MISSING: "<!-- provider-locks: missing updates -->"
175+
COMMENT_MARKER_DEPENDABOT: "<!-- provider-locks: dependabot updated -->"
176+
GH_TOKEN: ${{ github.token }}
177+
run: |
178+
# shellcheck disable=SC2296
179+
# shellcheck disable=SC2016
180+
# Remove any existing comments from this workflow since no changes are needed
181+
old_comment_ids=$(gh api "repos/{owner}/{repo}/issues/${{github.event.pull_request.number}}/comments" --jq 'map(select((.user.login == "github-actions[bot]") and ((.body | endswith($ENV.COMMENT_MARKER_MISSING + "\n")) or (.body | endswith($ENV.COMMENT_MARKER_DEPENDABOT + "\n"))))) | .[].id')
182+
for comment_id in $old_comment_ids; do
183+
echo "Removing stale comment: $comment_id"
184+
gh api -X DELETE "repos/{owner}/{repo}/issues/comments/${comment_id}"
185+
done
186+
187+
echo "No provider lock updates needed - removed any stale comments"

infra/scripts/upgrade_tf_version.sh

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ IGNORED_PROVIDERS=("auth0/auth0")
1010
# Global variable for terraform version override
1111
TF_VERSION="latest"
1212

13+
# Global variable for lock-only mode
14+
LOCK_ONLY=false
15+
1316
# Function to check if a command is available
1417
check_command() {
1518
local cmd="$1"
@@ -21,11 +24,15 @@ check_command() {
2124

2225
# Function to get terraform version from versions.tf
2326
get_terraform_version() {
27+
check_command "hcl2json"
28+
check_command "jq"
2429
hcl2json versions.tf | jq -r '.terraform[0].required_version'
2530
}
2631

2732
# Function to get filtered providers using jq
2833
get_filtered_providers() {
34+
check_command "hcl2json"
35+
check_command "jq"
2936
# Convert bash array to jq array format for filtering
3037
local ignored_json
3138
ignored_json=$(printf '%s\n' "${IGNORED_PROVIDERS[@]}" | jq -R . | jq -s .)
@@ -41,6 +48,8 @@ get_filtered_providers() {
4148

4249
# Function to get provider info (source and version) for tracking changes
4350
get_provider_info() {
51+
check_command "hcl2json"
52+
check_command "jq"
4453
# Convert bash array to jq array format for filtering
4554
local ignored_json
4655
ignored_json=$(printf '%s\n' "${IGNORED_PROVIDERS[@]}" | jq -R . | jq -s .)
@@ -56,6 +65,7 @@ get_provider_info() {
5665

5766
# Function to update providers
5867
update_providers() {
68+
check_command "tfupdate"
5969
pushd "$SHARED_DIR" >/dev/null || exit 1
6070
echo "Updating providers..."
6171

@@ -114,12 +124,14 @@ update_providers() {
114124

115125
# Function to lock providers
116126
lock_providers() {
127+
check_command "tfupdate"
117128
echo "Locking providers..."
118129
tfupdate lock -r --platform linux_arm64 --platform linux_amd64 --platform darwin_amd64 --platform windows_amd64 -i infra/shared infra/
119130
}
120131

121132
# Function to update terraform
122133
update_terraform() {
134+
check_command "tfupdate"
123135
pushd "$SHARED_DIR" >/dev/null || exit 1
124136
echo "Updating terraform..."
125137

@@ -155,20 +167,25 @@ while [[ $# -gt 0 ]]; do
155167
TF_VERSION="$2"
156168
shift 2
157169
;;
170+
--lock-only)
171+
LOCK_ONLY=true
172+
shift
173+
;;
158174
*)
159-
echo "Usage: $0 [--tf-version VERSION]"
175+
echo "Usage: $0 [--tf-version VERSION] [--lock-only]"
160176
echo " --tf-version VERSION Set terraform to specific version (default: latest)"
177+
echo " --lock-only Only update provider locks, skip terraform and provider updates"
161178
echo " (no args) Update terraform, providers, and lock providers"
162179
exit 1
163180
;;
164181
esac
165182
done
166183

167-
# Check for required commands
168-
check_command "tfupdate"
169-
check_command "hcl2json"
170-
check_command "jq"
171-
172-
update_terraform
173-
update_providers
174-
lock_providers
184+
if [[ "$LOCK_ONLY" == "true" ]]; then
185+
echo "Running in lock-only mode..."
186+
lock_providers
187+
else
188+
update_terraform
189+
update_providers
190+
lock_providers
191+
fi

0 commit comments

Comments
 (0)