From 158efdd5b50fdfdc73759af544bf83ee94fcd3e7 Mon Sep 17 00:00:00 2001 From: Justin Bollinger Date: Mon, 13 Apr 2026 10:32:40 -0400 Subject: [PATCH] feat: add auto-tagging workflow for semver bumps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Automatically creates a new git tag on push to main based on conventional commit prefixes: feat: bumps minor (2.5.x → 2.6.0), fix:/perf: bumps patch (2.5.1 → 2.5.2). The new tag triggers the existing release workflow to create a GitHub release. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/auto-tag.yml | 80 ++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 .github/workflows/auto-tag.yml diff --git a/.github/workflows/auto-tag.yml b/.github/workflows/auto-tag.yml new file mode 100644 index 0000000..92ad803 --- /dev/null +++ b/.github/workflows/auto-tag.yml @@ -0,0 +1,80 @@ +name: Auto Tag + +on: + push: + branches: + - main + +permissions: + contents: write + +jobs: + tag: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + fetch-depth: 0 + + - name: Determine version bump + id: bump + run: | + # Get the latest semver tag + latest_tag=$(git tag --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1) + if [ -z "$latest_tag" ]; then + echo "No semver tag found, starting at v0.1.0" + echo "new_tag=v0.1.0" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "Latest tag: $latest_tag" + + # Get commits since last tag + commits=$(git log "$latest_tag"..HEAD --pretty=format:"%s") + + if [ -z "$commits" ]; then + echo "No new commits since $latest_tag" + echo "skip=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + + # Parse current version + version="${latest_tag#v}" + major=$(echo "$version" | cut -d. -f1) + minor=$(echo "$version" | cut -d. -f2) + patch=$(echo "$version" | cut -d. -f3) + + # Check commit prefixes for bump type + bump="none" + while IFS= read -r msg; do + if echo "$msg" | grep -qE '^feat(\(.+\))?!?:'; then + bump="minor" + elif echo "$msg" | grep -qE '^(fix|perf)(\(.+\))?:' && [ "$bump" != "minor" ]; then + bump="patch" + fi + done <<< "$commits" + + if [ "$bump" = "none" ]; then + echo "No feat/fix/perf commits, skipping tag" + echo "skip=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + + if [ "$bump" = "minor" ]; then + minor=$((minor + 1)) + patch=0 + else + patch=$((patch + 1)) + fi + + new_tag="v${major}.${minor}.${patch}" + echo "Bump: $bump → $new_tag" + echo "new_tag=$new_tag" >> "$GITHUB_OUTPUT" + + - name: Create tag + if: steps.bump.outputs.skip != 'true' + env: + NEW_TAG: ${{ steps.bump.outputs.new_tag }} + run: | + git tag "$NEW_TAG" + git push origin "$NEW_TAG"