From c390e16b5c51415468aa59465dfef4b641dea63d Mon Sep 17 00:00:00 2001 From: Alex Dunmow Date: Thu, 4 Jun 2026 20:18:26 +0800 Subject: [PATCH] build(make): auto-bump release version + distribute-sdk subcommand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `make release` (no args) infers the next version from the last vX.Y.Z tag using conventional-commits: BREAKING/`!:` → major, `feat` → minor, otherwise → patch. LEVEL=major|minor|patch forces; VERSION=vX.Y.Z is the explicit escape hatch. - New `distribute-sdk` subcommand commits + pushes the pin bump in each downstream. Surgical (commits go.mod + go.sum only) so any unrelated WIP in a downstream is left alone instead of getting swept into the commit. Repos without an origin remote land the commit locally. - `release` now chains tag → push → update-sdk → distribute-sdk so one command takes the ecosystem from new commit to fully-distributed. --- Makefile | 82 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 78022bd..8f64561 100644 --- a/Makefile +++ b/Makefile @@ -38,19 +38,79 @@ update-sdk: ); \ done -# Tag + push a new SDK release, then bump the pin in every downstream repo. -# Usage: make release VERSION=v0.11.0 +# Cut a new SDK release: tag, push, bump every downstream's pin, and commit +# + push the pin bump in each downstream. +# +# Defaults: version is auto-bumped from the last vX.Y.Z tag. Level is +# inferred from conventional-commits since that tag: BREAKING/`!:` → major, +# `feat` → minor, otherwise → patch. +# +# Overrides: +# make release # auto-bump (recommended) +# make release LEVEL=minor # force level +# make release VERSION=v1.2.3 # explicit version .PHONY: release release: - @if [ -z "$(VERSION)" ]; then echo "usage: make release VERSION=vX.Y.Z" >&2; exit 1; fi - @case "$(VERSION)" in v[0-9]*.[0-9]*.[0-9]*) ;; *) echo "VERSION must look like vX.Y.Z (got $(VERSION))" >&2; exit 1 ;; esac - @if ! git diff-index --quiet HEAD --; then echo "working tree dirty; commit before releasing" >&2; exit 1; fi - git push origin HEAD - git tag -a "$(VERSION)" -m "release $(VERSION)" - git push origin "$(VERSION)" - $(MAKE) update-sdk SDK_VERSION=$(VERSION) - @echo "==> $(VERSION) tagged + pushed; downstream go.mod files bumped." - @echo " Review each downstream and commit the pin bump." + @set -e; \ + if [ -n "$(VERSION)" ]; then \ + case "$(VERSION)" in v[0-9]*.[0-9]*.[0-9]*) ;; *) echo "VERSION must look like vX.Y.Z (got $(VERSION))" >&2; exit 1 ;; esac; \ + next="$(VERSION)"; \ + else \ + current=$$(git describe --tags --abbrev=0 --match='v[0-9]*' 2>/dev/null | sed 's/^v//'); \ + if [ -z "$$current" ]; then echo "no existing vX.Y.Z tag; pass VERSION=vX.Y.Z" >&2; exit 1; fi; \ + commits=$$(git log "v$$current..HEAD" --pretty=format:%s); \ + if [ -z "$$commits" ]; then echo "no commits since v$$current; nothing to release" >&2; exit 1; fi; \ + level=$${LEVEL:-}; \ + if [ -z "$$level" ]; then \ + if echo "$$commits" | grep -qE "(^|[[:space:]])(BREAKING[ -]CHANGE|[a-z]+(\([^)]+\))?!:)"; then level=major; \ + elif echo "$$commits" | grep -qE "^feat(\(|:)"; then level=minor; \ + else level=patch; fi; \ + echo "==> auto-detected $$level bump from conventional-commits since v$$current"; \ + fi; \ + major=$$(echo $$current | cut -d. -f1); \ + minor=$$(echo $$current | cut -d. -f2); \ + patch=$$(echo $$current | cut -d. -f3); \ + case "$$level" in \ + patch) patch=$$((patch+1)) ;; \ + minor) minor=$$((minor+1)); patch=0 ;; \ + major) major=$$((major+1)); minor=0; patch=0 ;; \ + *) echo "LEVEL must be patch|minor|major (got $$level)" >&2; exit 1 ;; \ + esac; \ + next="v$$major.$$minor.$$patch"; \ + echo "==> bumping v$$current -> $$next"; \ + fi; \ + if ! git diff-index --quiet HEAD --; then echo "working tree dirty; commit before releasing" >&2; exit 1; fi; \ + git push origin HEAD; \ + git tag -a "$$next" -m "release $$next"; \ + git push origin "$$next"; \ + $(MAKE) update-sdk SDK_VERSION=$$next; \ + $(MAKE) distribute-sdk SDK_VERSION=$$next; \ + echo "==> $$next tagged, pushed, and distributed." + +# Commit + push the SDK pin bump in each downstream. Surgical: only commits +# go.mod / go.sum so any unrelated WIP in the downstream is left alone (and +# unpushed). Repos without an `origin` remote are committed locally only. +.PHONY: distribute-sdk +distribute-sdk: + @set -e; \ + if [ -z "$(SDK_VERSION)" ]; then echo "usage: make distribute-sdk SDK_VERSION=vX.Y.Z" >&2; exit 1; fi; \ + for dir in $(SDK_DOWNSTREAM_DIRS); do \ + if [ ! -f "$$dir/go.mod" ]; then continue; fi; \ + ( \ + cd "$$dir"; \ + if git diff --quiet HEAD -- go.mod go.sum; then \ + exit 0; \ + fi; \ + echo "==> $$dir: commit + push pin bump"; \ + git add -- go.mod go.sum; \ + git commit -m "chore: bump core to $(SDK_VERSION)" -- go.mod go.sum >/dev/null; \ + if git config --get remote.origin.url >/dev/null 2>&1; then \ + git push origin HEAD 2>&1 | tail -1; \ + else \ + echo " (no origin remote — committed locally only)"; \ + fi; \ + ); \ + done .PHONY: check-sdk-pins check-sdk-pins: