Skip to content

Commit 2b7e776

Browse files
Merge pull request cli#12581 from cli/copilot/update-bump-go-script-resilience
Fix bump-go.sh to tolerate missing toolchain directive
2 parents 1e6bb88 + e5f5427 commit 2b7e776

1 file changed

Lines changed: 60 additions & 34 deletions

File tree

.github/workflows/scripts/bump-go.sh

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#!/usr/bin/env bash
22
#
3-
# bump-go.sh Update go.mod `go` directive and toolchain to latest stable Go release.
3+
# bump-go.sh -- Update go.mod `go` directive and toolchain to latest stable Go release.
44
#
55
# Usage:
66
# ./bump-go.sh [--apply|-a] <path/to/go.mod>
77
#
8-
# By default the script runs in *dryrun* mode: it creates a local branch,
8+
# By default the script runs in *dry-run* mode: it creates a local branch,
99
# commits the version bump, shows the exact patch, **checks for an existing PR**
1010
# with the same title, and exits. Nothing is pushed. The temporary branch is
1111
# deleted automatically on exit, so your working tree stays clean. Pass
12-
# --apply (or -a) to push the branch and open a new PR *only if one doesnt
12+
# --apply (or -a) to push the branch and open a new PR *only if one doesn't
1313
# already exist*.
1414
# -----------------------------------------------------------------------------
1515
set -euo pipefail
@@ -35,52 +35,66 @@ done
3535
[[ -z "$GO_MOD" ]] && usage
3636
[[ -f "$GO_MOD" ]] || { echo "Error: '$GO_MOD' not found" >&2; exit 1; }
3737

38+
REPO="cli/cli"
39+
MODULE_DIR=$(dirname "$GO_MOD")
40+
GO_SUM="$MODULE_DIR/go.sum"
41+
3842
# ---- Discover latest stable Go release --------------------------------------
39-
echo "Fetching latest stable Go version"
43+
echo "Fetching latest stable Go version..."
4044
LATEST_JSON=$(curl -fsSL https://go.dev/dl/?mode=json | jq -c '[.[] | select(.stable==true)][0]')
4145
FULL_VERSION=$(jq -r '.version' <<< "$LATEST_JSON") # e.g. go1.23.4
4246
TOOLCHAIN_VERSION="${FULL_VERSION#go}" # e.g. 1.23.4
43-
# `go mod tidy` will always add `.0` if there is no minor version
44-
# so let's just ensure .0 is suffixed to the go directive.
4547
GO_DIRECTIVE_VERSION="$(cut -d. -f1-2 <<< "$TOOLCHAIN_VERSION").0"
4648

47-
echo " → go : $GO_DIRECTIVE_VERSION"
48-
echo " → toolchain : $TOOLCHAIN_VERSION"
49+
echo " → go directive : $GO_DIRECTIVE_VERSION"
50+
echo " → toolchain : go$TOOLCHAIN_VERSION"
4951

50-
# ---- Prepare Git branch ---------------------------------------------------
51-
CURRENT_GO_DIRECTIVE=$(grep -E '^go ' "$GO_MOD" | cut -d ' ' -f2)
52-
CURRENT_TOOLCHAIN_DIRECTIVE=$(grep -E '^toolchain ' "$GO_MOD" | cut -d ' ' -f2)
52+
# ---- Read current go.mod state using go mod edit ----------------------------
53+
GO_MOD_JSON=$(go mod edit -json "$GO_MOD")
54+
CURRENT_GO_DIRECTIVE=$(jq -r '.Go // ""' <<< "$GO_MOD_JSON")
55+
CURRENT_TOOLCHAIN=$(jq -r '.Toolchain // ""' <<< "$GO_MOD_JSON")
5356

54-
if [[ "$CURRENT_GO_DIRECTIVE" = "$GO_DIRECTIVE_VERSION" && \
55-
"$CURRENT_TOOLCHAIN_DIRECTIVE" = "go$TOOLCHAIN_VERSION" ]]; then
56-
echo "Already on latest Go version: $CURRENT_GO_DIRECTIVE (toolchain: $CURRENT_TOOLCHAIN_DIRECTIVE)"
57-
exit 0
58-
fi
57+
echo " → current go : $CURRENT_GO_DIRECTIVE"
58+
echo " → current tc : ${CURRENT_TOOLCHAIN:-(none)}"
5959

60+
# ---- Prepare Git branch -----------------------------------------------------
6061
BRANCH="bump-go-$TOOLCHAIN_VERSION"
62+
BRANCH_CREATED=0
63+
6164
cleanup() {
62-
git checkout - >/dev/null 2>&1 || true
63-
git branch -D "$BRANCH" >/dev/null 2>&1 || true
65+
if [[ $BRANCH_CREATED -eq 1 ]]; then
66+
git checkout - >/dev/null 2>&1 || true
67+
git branch -D "$BRANCH" >/dev/null 2>&1 || true
68+
fi
6469
}
6570
trap cleanup EXIT
6671

6772
echo "Creating branch $BRANCH"
6873
git switch -c "$BRANCH" >/dev/null 2>&1
74+
BRANCH_CREATED=1
6975

7076
# ---- Patch go.mod -----------------------------------------------------------
71-
if [[ "$CURRENT_GO_DIRECTIVE" != "$GO_DIRECTIVE_VERSION" ]]; then
72-
sed -Ei.bak "s/^go [0-9]+\.[0-9]+.*$/go $GO_DIRECTIVE_VERSION/" "$GO_MOD"
73-
echo " • go directive $CURRENT_GO_DIRECTIVE$GO_DIRECTIVE_VERSION"
74-
fi
75-
76-
if [[ "$CURRENT_TOOLCHAIN_DIRECTIVE" != "go$TOOLCHAIN_VERSION" ]]; then
77-
sed -Ei.bak "s/^toolchain go[0-9]+\.[0-9]+\.[0-9]+.*$/toolchain go$TOOLCHAIN_VERSION/" "$GO_MOD"
78-
echo " • toolchain $CURRENT_TOOLCHAIN_DIRECTIVE → go$TOOLCHAIN_VERSION"
77+
# Always set both directives and let `go mod tidy` normalize.
78+
# When the go directive version matches the toolchain version, tidy will remove
79+
# the toolchain line because it is redundant -- this is expected Go behavior.
80+
go mod edit -go="$GO_DIRECTIVE_VERSION" -toolchain="go$TOOLCHAIN_VERSION" "$GO_MOD"
81+
echo " • set go directive → $GO_DIRECTIVE_VERSION"
82+
echo " • set toolchain → go$TOOLCHAIN_VERSION"
83+
84+
# Let go mod tidy reconcile dependencies and normalize directives.
85+
echo " • running go mod tidy..."
86+
pushd "$MODULE_DIR" > /dev/null
87+
go mod tidy
88+
popd > /dev/null
89+
90+
# ---- Check if anything actually changed -------------------------------------
91+
if git diff --quiet -- "$GO_MOD" "$GO_SUM" 2>/dev/null; then
92+
echo "Already on latest Go version -- no changes needed."
93+
exit 0
7994
fi
8095

81-
rm -f "$GO_MOD.bak"
82-
8396
git add "$GO_MOD"
97+
[[ -f "$GO_SUM" ]] && git add "$GO_SUM"
8498

8599
# ---- Commit -----------------------------------------------------------------
86100
COMMIT_MSG="Bump Go to $TOOLCHAIN_VERSION"
@@ -90,31 +104,43 @@ COMMIT_HASH=$(git rev-parse --short HEAD)
90104
PR_TITLE="$COMMIT_MSG"
91105

92106
# ---- Check for existing PR --------------------------------------------------
93-
existing_pr=$(gh search prs --repo cli/cli --match title "$PR_TITLE" --json title --jq "map(select(.title == \"$PR_TITLE\") | .title) | length > 0")
107+
existing_pr=$(gh search prs --repo "$REPO" --state open --match title "$PR_TITLE" \
108+
--json title --jq "map(select(.title == \"$PR_TITLE\") | .title) | length > 0")
94109

95110
if [[ "$existing_pr" == "true" ]]; then
96111
echo "Found an existing open PR titled '$PR_TITLE'. Skipping push/PR creation."
97112
if [[ $APPLY -eq 0 ]]; then
98-
echo -e "\n=== DRYRUN DIFF (commit $COMMIT_HASH):\n"
113+
echo -e "\n=== DRY-RUN DIFF (commit $COMMIT_HASH):\n"
99114
git --no-pager show --color "$COMMIT_HASH"
100115
fi
101116
exit 0
102117
fi
103118

104-
# ---- Dryrun handling -------------------------------------------------------
119+
# ---- Dry-run handling -------------------------------------------------------
105120
if [[ $APPLY -eq 0 ]]; then
106-
echo -e "\n=== DRYRUN DIFF (commit $COMMIT_HASH):\n"
121+
echo -e "\n=== DRY-RUN DIFF (commit $COMMIT_HASH):\n"
107122
git --no-pager show --color "$COMMIT_HASH"
108123
echo -e "\nIf --apply were provided, script would continue with:\n git push -u origin $BRANCH\n gh pr create --title \"$PR_TITLE\" --body <body>\n"
109124
exit 0
110125
fi
111126

112127
# ---- Push & PR --------------------------------------------------------------
128+
FINAL_GO_MOD_JSON=$(go mod edit -json "$GO_MOD")
129+
FINAL_GO=$(jq -r '.Go // ""' <<< "$FINAL_GO_MOD_JSON")
130+
FINAL_TC=$(jq -r '.Toolchain // ""' <<< "$FINAL_GO_MOD_JSON")
131+
132+
# Build PR body reflecting final state after tidy
133+
if [[ -n "$FINAL_TC" ]]; then
134+
TC_LINE="* **toolchain:** \`$FINAL_TC\`"
135+
else
136+
TC_LINE="* **toolchain:** _(none -- \`go mod tidy\` removed it because the go directive already implies go$TOOLCHAIN_VERSION)_"
137+
fi
138+
113139
PR_BODY=$(cat <<EOF
114140
This PR updates Go to the latest stable release.
115141
116-
* **go directive:** \`$GO_DIRECTIVE_VERSION\`
117-
* **toolchain:** \`$TOOLCHAIN_VERSION\`
142+
* **go directive:** \`$FINAL_GO\`
143+
$TC_LINE
118144
EOF
119145
)
120146

0 commit comments

Comments
 (0)