-
Notifications
You must be signed in to change notification settings - Fork 0
205 lines (187 loc) · 7.73 KB
/
Copy pathgo-module-consumer-bump.yml
File metadata and controls
205 lines (187 loc) · 7.73 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
name: Go module consumer bump
# After a go/vX.Y.Z tag lands, open (or refresh) a PR on the consumer repo that
# pins the new module version in its go.mod. The bump branch on the consumer is
# machine-owned: every release rebuilds it from the consumer default branch and
# force-pushes, so a single PR always shows the newest version.
on:
push:
tags:
- 'go/v*'
workflow_dispatch:
inputs:
version:
description: Module version to pin (for example v0.1.4). Empty uses the latest go/v* tag.
required: false
type: string
concurrency:
group: go-module-consumer-bump
cancel-in-progress: false
permissions:
contents: read
env:
CONSUMER_REPO: speakeasy-api/gram
MODULE_PATH: github.com/speakeasy-api/mcp-setup-docs/go
BUMP_BRANCH: chore/bump-mcp-setup-docs-go
jobs:
bump:
runs-on: ubuntu-latest
steps:
# Scoped to the consumer repo and valid for an hour, unlike a PAT.
- name: Mint a gram-bot token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.GRAM_BOT_APP_ID }}
private-key: ${{ secrets.GRAM_BOT_PRIVATE_KEY }}
owner: speakeasy-api
repositories: gram
permission-contents: write
permission-pull-requests: write
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Resolve module version
id: ver
env:
INPUT_VERSION: ${{ github.event.inputs.version }}
run: |
set -euo pipefail
if [ -n "${INPUT_VERSION:-}" ]; then
ver="${INPUT_VERSION}"
elif [ "${GITHUB_REF_TYPE}" = "tag" ]; then
ver="${GITHUB_REF_NAME}"
else
ver="$(git tag -l 'go/v*' --sort=-v:refname | head -1)"
fi
ver="${ver#go/}"
ver="v${ver#v}"
if ! printf '%s' "$ver" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "not a release version: '$ver'"
exit 1
fi
echo "version=$ver" >> "$GITHUB_OUTPUT"
echo "tag=go/$ver" >> "$GITHUB_OUTPUT"
echo "Pinning ${MODULE_PATH}@${ver}"
- name: Checkout consumer
uses: actions/checkout@v4
with:
repository: ${{ env.CONSUMER_REPO }}
token: ${{ steps.app-token.outputs.token }}
path: consumer
fetch-depth: 1
- uses: actions/setup-go@v5
with:
go-version-file: consumer/go.mod
cache-dependency-path: consumer/go.sum
- name: Bump the module version
id: bump
working-directory: consumer
env:
VERSION: ${{ steps.ver.outputs.version }}
run: |
set -euo pipefail
current="$(awk -v m="$MODULE_PATH" '$1 == m {print $2; exit}' go.mod)"
if [ -z "$current" ]; then
echo "${CONSUMER_REPO} go.mod does not require ${MODULE_PATH}; nothing to bump."
exit 1
fi
echo "previous=$current" >> "$GITHUB_OUTPUT"
if [ "$current" = "$VERSION" ]; then
echo "${CONSUMER_REPO} already pins ${VERSION}."
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Proxy indexing lags the tag push; retry until the version resolves.
attempts=12
for i in $(seq 1 "$attempts"); do
if go get "${MODULE_PATH}@${VERSION}"; then
break
fi
if [ "$i" -eq "$attempts" ]; then
echo "${MODULE_PATH}@${VERSION} never resolved; re-run this workflow later."
exit 1
fi
echo "attempt ${i}: ${MODULE_PATH}@${VERSION} not on the proxy yet; retry in 20s"
sleep 20
done
# The consumer CI runs `go mod tidy` and fails on a dirty tree.
go mod tidy
if [ -z "$(git status --porcelain -- go.mod go.sum)" ]; then
echo "go get produced no change; nothing to open."
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ -n "$(git status --porcelain | grep -v -E '^ M go\.(mod|sum)$' || true)" ]; then
echo "unexpected files changed; refusing to open a PR:"
git status --porcelain
exit 1
fi
echo "changed=true" >> "$GITHUB_OUTPUT"
- name: Collect release notes
id: notes
if: steps.bump.outputs.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.ver.outputs.tag }}
run: |
set -euo pipefail
notes_file="${RUNNER_TEMP:-/tmp}/consumer-bump-notes.md"
gh release view "$TAG" --repo "$GITHUB_REPOSITORY" --json body --jq .body \
> "$notes_file" 2>/dev/null || : > "$notes_file"
echo "file=$notes_file" >> "$GITHUB_OUTPUT"
- name: Open or update the bump PR
if: steps.bump.outputs.changed == 'true'
working-directory: consumer
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
VERSION: ${{ steps.ver.outputs.version }}
PREVIOUS: ${{ steps.bump.outputs.previous }}
TAG: ${{ steps.ver.outputs.tag }}
NOTES_FILE: ${{ steps.notes.outputs.file }}
run: |
set -euo pipefail
# Commit as the app, so the consumer CI runs on the pushed branch.
git config user.name "gram-bot[bot]"
git config user.email "gram-bot[bot]@users.noreply.github.com"
title="chore(deps): bump ${MODULE_PATH} from ${PREVIOUS} to ${VERSION}"
git checkout -B "$BUMP_BRANCH"
git add -- go.mod go.sum
git commit -m "$title"
# Machine-owned branch: the lease fails loudly if the remote moved.
git fetch --depth=1 origin "+refs/heads/${BUMP_BRANCH}:refs/remotes/origin/${BUMP_BRANCH}" 2>/dev/null || true
git push -u origin "HEAD:refs/heads/${BUMP_BRANCH}" --force-with-lease
release_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/releases/tag/${TAG}"
body_file="${RUNNER_TEMP:-/tmp}/consumer-bump-pr.md"
{
echo "## Summary"
echo "- Pin \`${MODULE_PATH}\` to \`${VERSION}\` (was \`${PREVIOUS}\`)"
echo "- Opened by \`go-module-consumer-bump\` in ${GITHUB_REPOSITORY} after the \`${TAG}\` release"
echo "- Branch is machine-owned — the next release force-pushes over it"
echo "- If this bump breaks CI, branch off \`${BUMP_BRANCH}\`, fix it there, and close this PR."
echo " Commits pushed onto this branch are lost on the next release."
echo
echo "## Release notes"
echo "[\`${TAG}\`](${release_url})"
if [ -s "${NOTES_FILE:-}" ]; then
echo
cat "$NOTES_FILE"
fi
echo
echo "## Test plan"
echo "- [ ] Consumer CI is green (\`go mod tidy\` leaves the tree clean)"
echo "- [ ] Setup docs lookups still resolve the guides the release changed"
} > "$body_file"
existing="$(gh pr list --repo "$CONSUMER_REPO" --head "$BUMP_BRANCH" --state open \
--json number --jq '.[0].number // empty')"
if [ -n "$existing" ]; then
echo "Updated existing PR #${existing} on ${CONSUMER_REPO}"
gh pr edit "$existing" --repo "$CONSUMER_REPO" --title "$title" --body-file "$body_file"
else
gh pr create --repo "$CONSUMER_REPO" \
--head "$BUMP_BRANCH" \
--title "$title" \
--body-file "$body_file"
gh pr edit "$BUMP_BRANCH" --repo "$CONSUMER_REPO" \
--add-label dependencies --add-label go --add-label automation || true
fi