Skip to content

Commit 114a3c6

Browse files
authored
Merge pull request #9748 from nilo19/feat/auto-bump-module
feat: auto update go module drifts
2 parents 765f435 + b421a08 commit 114a3c6

File tree

3 files changed

+263
-3
lines changed

3 files changed

+263
-3
lines changed

.github/workflows/codespell.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# https://github.com/codespell-project/codespell
44
name: codespell
55
on:
6+
workflow_dispatch:
67
push:
78
branches: [ master, 'release-**' ]
89
pull_request:

.github/workflows/go-mod-consistency.yaml

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
name: Go Module Consistency
22

33
on:
4+
workflow_dispatch:
45
push:
56
branches: [ master, 'release-**' ]
67
pull_request:
78
branches: [ master, 'release-**' ]
89

910
permissions:
1011
contents: read
12+
pull-requests: write
1113

1214
jobs:
1315
go-mod-consistency:
@@ -37,7 +39,7 @@ jobs:
3739
health-probe-proxy/go.sum
3840
kubetest2-aks/go.sum
3941
40-
- name: Run go mod tidy and verify
42+
- name: Run go mod tidy, vendor, and verify
4143
run: |
4244
set -euo pipefail
4345
modules=(
@@ -51,14 +53,107 @@ jobs:
5153
health-probe-proxy
5254
kubetest2-aks
5355
)
56+
vendor_modules=(
57+
.
58+
)
5459
for m in "${modules[@]}"; do
5560
echo ">> go mod tidy (${m})"
5661
(cd "${m}" && go mod tidy)
62+
if [[ " ${vendor_modules[*]} " == *" ${m} "* ]]; then
63+
echo ">> go mod vendor (${m})"
64+
(cd "${m}" && go mod vendor)
65+
fi
5766
echo ">> go mod verify (${m})"
5867
(cd "${m}" && go mod verify)
5968
done
6069
61-
- name: Fail on uncommitted changes
70+
- name: Detect go module drift
71+
id: diff
72+
run: |
73+
set -euo pipefail
74+
status_output="$(git status --porcelain)"
75+
if [ -z "${status_output}" ]; then
76+
echo "changed=false" >> "$GITHUB_OUTPUT"
77+
exit 0
78+
fi
79+
echo "changed=true" >> "$GITHUB_OUTPUT"
80+
81+
- name: Write summary
82+
if: steps.diff.outputs.changed == 'true'
83+
run: |
84+
set -euo pipefail
85+
{
86+
echo "### Go module drift detected"
87+
echo ""
88+
echo "A maintainer can apply the updates by running:"
89+
echo "- Update Go Modules (Manual): https://github.com/${GITHUB_REPOSITORY}/actions/workflows/update-go-mods.yaml"
90+
if [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then
91+
echo "- PR: #${{ github.event.pull_request.number }}"
92+
fi
93+
echo ""
94+
echo "Diff summary:"
95+
echo '```'
96+
git diff --stat
97+
echo '```'
98+
} >> "$GITHUB_STEP_SUMMARY"
99+
100+
- name: Notify pull request
101+
if: github.event_name == 'pull_request' && steps.diff.outputs.changed == 'true'
102+
continue-on-error: true
103+
env:
104+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
105+
run: |
106+
set -euo pipefail
107+
108+
pr_number="${{ github.event.pull_request.number }}"
109+
author="$(jq -r '.pull_request.user.login // empty' "${GITHUB_EVENT_PATH}")"
110+
reviewers="$(jq -r '.pull_request.requested_reviewers[].login // empty' "${GITHUB_EVENT_PATH}" | sed 's/^/@/' | paste -sd ' ' -)"
111+
teams="$(jq -r '.pull_request.requested_teams[].slug // empty' "${GITHUB_EVENT_PATH}" | sed "s|^|@${GITHUB_REPOSITORY_OWNER}/|" | paste -sd ' ' -)"
112+
113+
mentions=""
114+
if [[ -n "${author}" ]]; then
115+
mentions="@${author}"
116+
fi
117+
if [[ -n "${reviewers}" ]]; then
118+
mentions="${mentions} ${reviewers}"
119+
fi
120+
if [[ -n "${teams}" ]]; then
121+
mentions="${mentions} ${teams}"
122+
fi
123+
mentions="$(printf '%s' "${mentions}" | xargs || true)"
124+
125+
marker="<!-- go-mod-drift -->"
126+
workflow_url="https://github.com/${GITHUB_REPOSITORY}/actions/workflows/update-go-mods.yaml"
127+
diffstat="$(git diff --stat)"
128+
129+
body="$(printf '%s\n' \
130+
"${marker}" \
131+
"${mentions}" \
132+
"" \
133+
"Go module files are out of date for this PR (go.mod/go.sum and/or vendor)." \
134+
"" \
135+
"A maintainer can apply the generated updates by running:" \
136+
"- Workflow: ${workflow_url}" \
137+
"- Input: pr_number=${pr_number}" \
138+
"" \
139+
"Note: commits pushed by GitHub Actions using GITHUB_TOKEN don't auto-trigger other push/pull_request workflows, so checks may need to be manually re-run." \
140+
"" \
141+
"Diff summary:" \
142+
"${diffstat}" \
143+
)"
144+
145+
comment_id="$(gh api "repos/${GITHUB_REPOSITORY}/issues/${pr_number}/comments" --paginate | jq -r --arg marker "${marker}" '.[] | select(.user.login=="github-actions[bot]" and (.body | contains($marker))) | .id' | head -n 1)"
146+
if [[ -n "${comment_id}" && "${comment_id}" != "null" ]]; then
147+
gh api -X PATCH "repos/${GITHUB_REPOSITORY}/issues/comments/${comment_id}" -f body="${body}" >/dev/null
148+
exit 0
149+
fi
150+
151+
gh api -X POST "repos/${GITHUB_REPOSITORY}/issues/${pr_number}/comments" -f body="${body}" >/dev/null
152+
153+
- name: Fail on go module drift
154+
if: steps.diff.outputs.changed == 'true'
62155
run: |
156+
set -euo pipefail
157+
git status --porcelain
63158
git diff --stat
64-
git diff --quiet
159+
exit 1
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
name: Update Go Modules (Manual)
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
pr_number:
7+
description: Pull request number to update (same-repo PRs only)
8+
required: true
9+
type: string
10+
11+
permissions:
12+
actions: write
13+
contents: write
14+
pull-requests: write
15+
16+
jobs:
17+
update-go-mods:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Harden Runner
21+
uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
22+
with:
23+
egress-policy: audit
24+
25+
- name: Resolve pull request
26+
id: pr
27+
env:
28+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
run: |
30+
set -euo pipefail
31+
pr_number="${{ inputs.pr_number }}"
32+
33+
pr_json="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${pr_number}")"
34+
head_repo="$(printf '%s' "${pr_json}" | jq -r '.head.repo.full_name')"
35+
head_ref="$(printf '%s' "${pr_json}" | jq -r '.head.ref')"
36+
head_sha="$(printf '%s' "${pr_json}" | jq -r '.head.sha')"
37+
38+
echo "head_repo=${head_repo}" >> "$GITHUB_OUTPUT"
39+
echo "head_ref=${head_ref}" >> "$GITHUB_OUTPUT"
40+
echo "head_sha=${head_sha}" >> "$GITHUB_OUTPUT"
41+
42+
if [[ "${head_repo}" != "${GITHUB_REPOSITORY}" ]]; then
43+
echo "cross_repo=true" >> "$GITHUB_OUTPUT"
44+
else
45+
echo "cross_repo=false" >> "$GITHUB_OUTPUT"
46+
fi
47+
48+
- name: Stop (forked PRs not supported)
49+
if: steps.pr.outputs.cross_repo == 'true'
50+
env:
51+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
52+
run: |
53+
set -euo pipefail
54+
pr_number="${{ inputs.pr_number }}"
55+
head_repo="${{ steps.pr.outputs.head_repo }}"
56+
gh pr comment "${pr_number}" --repo "${GITHUB_REPOSITORY}" --body \
57+
"This PR targets \`${GITHUB_REPOSITORY}\`, but its head branch is in \`${head_repo}\`.\n\nI can't push go.mod/go.sum/vendor updates to forked PR branches.\n\nPlease run \`go mod tidy\` (and \`go mod vendor\` if needed) locally and push the result to the PR branch."
58+
exit 1
59+
60+
- name: Checkout PR branch
61+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.2.2
62+
with:
63+
ref: ${{ steps.pr.outputs.head_ref }}
64+
fetch-depth: 0
65+
66+
- name: Setup Go
67+
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
68+
with:
69+
go-version-file: go.mod
70+
check-latest: true
71+
cache-dependency-path: |
72+
go.sum
73+
tests/go.sum
74+
pkg/azclient/go.sum
75+
pkg/azclient/cache/go.sum
76+
pkg/azclient/configloader/go.sum
77+
pkg/azclient/trace/go.sum
78+
pkg/azclient/client-gen/go.sum
79+
health-probe-proxy/go.sum
80+
kubetest2-aks/go.sum
81+
82+
- name: Run go mod tidy, vendor, and verify
83+
run: |
84+
set -euo pipefail
85+
modules=(
86+
.
87+
tests
88+
pkg/azclient
89+
pkg/azclient/cache
90+
pkg/azclient/configloader
91+
pkg/azclient/trace
92+
pkg/azclient/client-gen
93+
health-probe-proxy
94+
kubetest2-aks
95+
)
96+
vendor_modules=(
97+
.
98+
)
99+
for m in "${modules[@]}"; do
100+
echo ">> go mod tidy (${m})"
101+
(cd "${m}" && go mod tidy)
102+
if [[ " ${vendor_modules[*]} " == *" ${m} "* ]]; then
103+
echo ">> go mod vendor (${m})"
104+
(cd "${m}" && go mod vendor)
105+
fi
106+
echo ">> go mod verify (${m})"
107+
(cd "${m}" && go mod verify)
108+
done
109+
110+
- name: Detect changes
111+
id: diff
112+
run: |
113+
set -euo pipefail
114+
status_output="$(git status --porcelain)"
115+
if [ -z "${status_output}" ]; then
116+
echo "changed=false" >> "$GITHUB_OUTPUT"
117+
exit 0
118+
fi
119+
printf '%s\n' "${status_output}"
120+
echo "changed=true" >> "$GITHUB_OUTPUT"
121+
122+
- name: Commit and push go module updates
123+
if: steps.diff.outputs.changed == 'true'
124+
run: |
125+
set -euo pipefail
126+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
127+
git config user.name "github-actions[bot]"
128+
git add -A
129+
git commit -m "chore: tidy go modules"
130+
git push origin "HEAD:${{ steps.pr.outputs.head_ref }}"
131+
132+
- name: Trigger CI workflows (best effort)
133+
if: steps.diff.outputs.changed == 'true'
134+
continue-on-error: true
135+
env:
136+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
137+
run: |
138+
set -euo pipefail
139+
ref="${{ steps.pr.outputs.head_ref }}"
140+
workflows=(
141+
go-mod-consistency.yaml
142+
lint.yaml
143+
trivy.yaml
144+
codespell.yaml
145+
)
146+
for wf in "${workflows[@]}"; do
147+
echo "Dispatching ${wf} on ${ref}"
148+
gh workflow run "${wf}" --repo "${GITHUB_REPOSITORY}" --ref "${ref}" || true
149+
done
150+
151+
- name: Comment on pull request
152+
env:
153+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
154+
run: |
155+
set -euo pipefail
156+
pr_number="${{ inputs.pr_number }}"
157+
if [[ "${{ steps.diff.outputs.changed }}" != "true" ]]; then
158+
gh pr comment "${pr_number}" --repo "${GITHUB_REPOSITORY}" --body \
159+
"No go.mod/go.sum/vendor updates were needed."
160+
exit 0
161+
fi
162+
163+
gh pr comment "${pr_number}" --repo "${GITHUB_REPOSITORY}" --body \
164+
"Pushed go.mod/go.sum/vendor updates to \`${{ steps.pr.outputs.head_ref }}\`.\n\nNote: commits pushed by GitHub Actions using \`GITHUB_TOKEN\` don't auto-trigger other \`push\`/ \`pull_request\` workflows. This workflow tries to dispatch common CI workflows; if checks didn't start, run them manually from the **Actions** tab."

0 commit comments

Comments
 (0)