Merge pull request #87 from speakeasy-api/chore/go-module-regen #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Go module release | |
| # After a go/ sync (or API change) merges to main, cut the next go/vX.Y.Z tag | |
| # and GitHub Release. Requires an initial manual go/v0.1.0 tag first. | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'go/generated/**' | |
| - 'go/published_server_refs.txt' | |
| - 'go/go.mod' | |
| - 'go/LICENSE' | |
| - 'go/doc.go' | |
| - 'go/embed.go' | |
| - 'go/generate.go' | |
| - 'go/guides.go' | |
| - 'go/index_gen.go' | |
| - 'go/ref.go' | |
| - 'go/resolve.go' | |
| workflow_dispatch: | |
| inputs: | |
| bump: | |
| description: Semver bump (patch, minor, major) | |
| required: true | |
| default: patch | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| concurrency: | |
| group: go-module-release | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.AGENT_PAT || secrets.GITHUB_TOKEN }} | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go/go.mod | |
| cache-dependency-path: | | |
| go/go.mod | |
| go/internal/gen/go.sum | |
| - name: Resolve next version | |
| id: ver | |
| env: | |
| BUMP: ${{ github.event.inputs.bump || 'patch' }} | |
| run: | | |
| set -euo pipefail | |
| latest="$(git tag -l 'go/v*' --sort=-v:refname | grep -E '^go/v[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || true)" | |
| if [ -z "$latest" ]; then | |
| echo "No go/v* tags yet. Cut go/v0.1.0 manually once, then re-run." | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| echo "latest=$latest" >> "$GITHUB_OUTPUT" | |
| ver="${latest#go/v}" | |
| IFS=. read -r major minor patch <<<"$ver" | |
| case "$BUMP" in | |
| major) major=$((major + 1)); minor=0; patch=0 ;; | |
| minor) minor=$((minor + 1)); patch=0 ;; | |
| patch) patch=$((patch + 1)) ;; | |
| *) echo "unknown bump: $BUMP"; exit 1 ;; | |
| esac | |
| next="go/v${major}.${minor}.${patch}" | |
| module_ver="v${major}.${minor}.${patch}" | |
| echo "tag=$next" >> "$GITHUB_OUTPUT" | |
| echo "module_ver=$module_ver" >> "$GITHUB_OUTPUT" | |
| echo "Next tag: $next (module @${module_ver})" | |
| - name: Verify module before tagging | |
| if: steps.ver.outputs.skip != 'true' | |
| run: | | |
| set -euo pipefail | |
| (cd go/internal/gen && go run .) | |
| if [ -n "$(git status --porcelain -- go/)" ]; then | |
| echo "go/ drift on main; refusing to tag:" | |
| git status --porcelain -- go/ | |
| exit 1 | |
| fi | |
| (cd go && gofmt -l . | tee /tmp/gofmt.out) | |
| if [ -s /tmp/gofmt.out ]; then | |
| echo "gofmt needed before release" | |
| exit 1 | |
| fi | |
| (cd go && go vet . && go test .) | |
| (cd go/internal/gen && go test .) | |
| - name: Create tag and GitHub Release | |
| if: steps.ver.outputs.skip != 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.AGENT_PAT || secrets.GITHUB_TOKEN }} | |
| TAG: ${{ steps.ver.outputs.tag }} | |
| MODULE_VER: ${{ steps.ver.outputs.module_ver }} | |
| PREV: ${{ steps.ver.outputs.latest }} | |
| run: | | |
| set -euo pipefail | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "Tag $TAG already exists; nothing to do" | |
| exit 0 | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git tag -a "$TAG" -m "mcp-setup-docs Go module ${MODULE_VER}" | |
| git push origin "$TAG" | |
| notes_file="${RUNNER_TEMP:-/tmp}/go-module-release-notes.md" | |
| base_guides="${RUNNER_TEMP:-/tmp}/go-module-release-guides-base.txt" | |
| head_guides="${RUNNER_TEMP:-/tmp}/go-module-release-guides-head.txt" | |
| git ls-tree -d --name-only "${PREV}:go/generated/guides" 2>/dev/null \ | |
| | sort -u > "$base_guides" || : > "$base_guides" | |
| git ls-tree -d --name-only "HEAD:go/generated/guides" 2>/dev/null \ | |
| | sort -u > "$head_guides" || : > "$head_guides" | |
| mapfile -t added_guides < <(comm -13 "$base_guides" "$head_guides") | |
| mapfile -t removed_guides < <(comm -23 "$base_guides" "$head_guides") | |
| updated_guides=() | |
| while IFS= read -r slug; do | |
| [ -z "$slug" ] && continue | |
| if ! git diff --quiet "$PREV" -- "go/generated/guides/${slug}"; then | |
| updated_guides+=("$slug") | |
| fi | |
| done < <(comm -12 "$base_guides" "$head_guides") | |
| mapfile -t other_files < <( | |
| git diff --name-only "$PREV" -- go/ \ | |
| | grep -v '^go/generated/guides/' \ | |
| | sort -u || true | |
| ) | |
| fmt_backticks() { | |
| local out="" s | |
| for s in "$@"; do | |
| [ -z "$s" ] && continue | |
| if [ -n "$out" ]; then out+=", "; fi | |
| out+="\`${s}\`" | |
| done | |
| printf '%s' "$out" | |
| } | |
| { | |
| echo "Go module \`github.com/speakeasy-api/mcp-setup-docs/go@${MODULE_VER}\`" | |
| echo | |
| echo '```bash' | |
| echo "go get github.com/speakeasy-api/mcp-setup-docs/go@${MODULE_VER}" | |
| echo '```' | |
| echo | |
| echo "### Changes since ${PREV}" | |
| if [ "${#added_guides[@]}" -gt 0 ]; then | |
| echo "- **Added guides:** $(fmt_backticks "${added_guides[@]}")" | |
| fi | |
| if [ "${#updated_guides[@]}" -gt 0 ]; then | |
| echo "- **Updated guides:** $(fmt_backticks "${updated_guides[@]}")" | |
| fi | |
| if [ "${#removed_guides[@]}" -gt 0 ]; then | |
| echo "- **Removed guides:** $(fmt_backticks "${removed_guides[@]}")" | |
| fi | |
| if [ "${#other_files[@]}" -gt 0 ]; then | |
| echo "- **Other:** $(fmt_backticks "${other_files[@]}")" | |
| fi | |
| if [ "${#added_guides[@]}" -eq 0 ] \ | |
| && [ "${#updated_guides[@]}" -eq 0 ] \ | |
| && [ "${#removed_guides[@]}" -eq 0 ] \ | |
| && [ "${#other_files[@]}" -eq 0 ]; then | |
| echo "- Sync publishable guides into the Go module embed" | |
| fi | |
| } > "$notes_file" | |
| gh release create "$TAG" --title "$TAG" --notes-file "$notes_file" | |
| - name: Prime module proxy | |
| if: steps.ver.outputs.skip != 'true' | |
| env: | |
| MODULE_VER: ${{ steps.ver.outputs.module_ver }} | |
| run: | | |
| set -euo pipefail | |
| # Best-effort: proxy indexing can lag; don't fail the release on it. | |
| GOPROXY=https://proxy.golang.org go list -m "github.com/speakeasy-api/mcp-setup-docs/go@${MODULE_VER}" \ | |
| || echo "proxy prime not ready yet for @${MODULE_VER}" |