fix sse stream (#3) #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: Auto Release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: write | |
| pull-requests: read | |
| # Serialize runs so two PRs merged back-to-back can't both read the same | |
| # "latest" tag and race on `gh release create`. | |
| concurrency: | |
| group: auto-release-main | |
| cancel-in-progress: false | |
| jobs: | |
| release: | |
| name: Tag & Release | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| # fetch-depth: 0 is load-bearing, not just for `--generate-notes`: | |
| # "Compute next version" reads the local tag list to find the highest | |
| # released semver. At depth 0 checkout fetches with the refspec | |
| # `+refs/tags/*:refs/tags/*` and omits `--no-tags`, so every tag is | |
| # present locally. Lowering this silently truncates version history. | |
| fetch-depth: 0 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Resolve merged PR and bump type | |
| id: pr | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| SHA: ${{ github.sha }} | |
| run: | | |
| set -euo pipefail | |
| # Ask GitHub which PR this pushed commit belongs to, rather than | |
| # parsing the commit subject. This is merge-strategy agnostic (works | |
| # for squash, merge-commit and rebase) and returns empty for a direct | |
| # push to main, which we treat as "nothing to release". | |
| PR_NUMBER=$(gh api "repos/${REPO}/commits/${SHA}/pulls" --jq '.[0].number // ""') | |
| if [ -z "$PR_NUMBER" ]; then | |
| echo "No PR is associated with ${SHA} (direct push to main?). Nothing to release." | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| LABELS=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}" --jq '.labels[].name') | |
| if echo "$LABELS" | grep -qx 'skip-release'; then | |
| echo "PR #${PR_NUMBER} has 'skip-release' label — no release." | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| BUMP=$(echo "$LABELS" | grep -E '^(major|minor|patch)$' | head -1 || true) | |
| if [ -z "$BUMP" ]; then | |
| echo "::error::PR #${PR_NUMBER} has no major/minor/patch/skip-release label. (PR Release Label Check should have blocked this merge.)" | |
| exit 1 | |
| fi | |
| echo "Merged PR: #${PR_NUMBER} (bump: ${BUMP})" | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| echo "bump=${BUMP}" >> "$GITHUB_OUTPUT" | |
| echo "pr_number=${PR_NUMBER}" >> "$GITHUB_OUTPUT" | |
| - name: Compute next version | |
| if: steps.pr.outputs.skip == 'false' | |
| id: version | |
| env: | |
| BUMP: ${{ steps.pr.outputs.bump }} | |
| run: | | |
| set -euo pipefail | |
| # Highest existing semver tag, not the most recently created release. | |
| # Tags are read locally (see the checkout step) so the whole history | |
| # is considered — a paged `gh release list` window can miss a high | |
| # release that was created before a burst of newer backports, which | |
| # would regress LATEST and re-derive an already-published NEXT. | |
| # | |
| # `--sort=v:refname` orders numerically (v1.10.0 > v1.9.0) and sorts | |
| # prereleases below their stable release, so `tail -1` can only be a | |
| # stable version. grep keeps that to canonical vX.Y.Z: Go module tags | |
| # must be v-prefixed for `go get ...@vX.Y.Z`, and rejecting leading | |
| # zeros keeps the arithmetic below out of bash's octal parsing. | |
| LATEST=$(git tag -l --sort=v:refname 'v[0-9]*.[0-9]*.[0-9]*' \ | |
| | grep -E '^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$' \ | |
| | tail -n 1 || true) | |
| if [ -z "$LATEST" ]; then | |
| LATEST="v0.0.0" | |
| fi | |
| CLEAN="${LATEST#v}" | |
| IFS='.' read -r MAJOR MINOR PATCH <<< "$CLEAN" | |
| case "$BUMP" in | |
| major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;; | |
| minor) MINOR=$((MINOR + 1)); PATCH=0 ;; | |
| patch) PATCH=$((PATCH + 1)) ;; | |
| esac | |
| NEXT="v${MAJOR}.${MINOR}.${PATCH}" | |
| echo "Highest existing tag: ${LATEST} -> Next: ${NEXT} (bump: ${BUMP})" | |
| echo "next=${NEXT}" >> "$GITHUB_OUTPUT" | |
| echo "previous=${LATEST}" >> "$GITHUB_OUTPUT" | |
| - name: Guard the v2+ import path | |
| if: steps.pr.outputs.skip == 'false' | |
| env: | |
| NEXT: ${{ steps.version.outputs.next }} | |
| run: | | |
| set -euo pipefail | |
| # Go's module rules: at v2 and above the major version must be part | |
| # of the module path (github.com/hoophq/mcpproxy/v2). Tagging v2.0.0 | |
| # against an unsuffixed go.mod produces a tag `go get` refuses to | |
| # resolve, so fail here instead of publishing a broken release. | |
| MAJOR="${NEXT#v}"; MAJOR="${MAJOR%%.*}" | |
| WANT="github.com/${{ github.repository }}" | |
| if [ "$MAJOR" -ge 2 ]; then | |
| WANT="${WANT}/v${MAJOR}" | |
| fi | |
| GOT=$(go list -m) | |
| if [ "$GOT" != "$WANT" ]; then | |
| echo "::error::Releasing ${NEXT} needs module path '${WANT}', but go.mod declares '${GOT}'. Update go.mod and every internal import first." | |
| exit 1 | |
| fi | |
| - name: Release module | |
| if: steps.pr.outputs.skip == 'false' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| NEXT: ${{ steps.version.outputs.next }} | |
| PREVIOUS: ${{ steps.version.outputs.previous }} | |
| SHA: ${{ github.sha }} | |
| run: | | |
| set -euo pipefail | |
| if gh release view "$NEXT" >/dev/null 2>&1; then | |
| echo "::error::Release $NEXT already exists. Another run may have created it; investigate before retrying." | |
| exit 1 | |
| fi | |
| # Creating the release also creates the vNEXT tag at $SHA. That tag is | |
| # the published artifact: `go get github.com/hoophq/mcpproxy@NEXT`. | |
| ARGS=(--title "$NEXT" --target "$SHA" --generate-notes) | |
| if [ "$PREVIOUS" != "v0.0.0" ]; then | |
| ARGS+=(--notes-start-tag "$PREVIOUS") | |
| fi | |
| gh release create "$NEXT" "${ARGS[@]}" | |
| echo "Released github.com/${{ github.repository }}@${NEXT}" |