From ff31726e0d95f469ab75fcc754165f91c77f4f49 Mon Sep 17 00:00:00 2001 From: CyanoTex Date: Mon, 6 Apr 2026 18:09:43 +0200 Subject: [PATCH] feat: local version bump automation with CI check - Pre-commit hook auto-bumps patch version on first code commit per branch - CI workflow validates version bump on PRs (safety net) - Bump script at scripts/bump-version.js for manual use - README documents the one-time git hooks setup Replaces the GitHub Actions auto-bump approach which can't push to branch-protected main on personal repos without a PAT. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- .githooks/pre-commit | 29 +++++++++++++++++ .github/workflows/version-bump.yml | 52 ++++++++++++++++++++++++++++++ README.md | 10 ++++++ scripts/bump-version.js | 21 ++++++++++++ 6 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 .githooks/pre-commit create mode 100644 .github/workflows/version-bump.yml create mode 100644 scripts/bump-version.js diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 37f8796..d3e7dee 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -7,7 +7,7 @@ }, "metadata": { "description": "Roblox Knowledge Engine — queries 11 data sources to answer any Roblox development question", - "version": "1.0.0" + "version": "1.0.1" }, "plugins": [ { diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 1baebd8..5f21dbc 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "bloxus", - "version": "1.0.0", + "version": "1.0.1", "description": "Roblox Knowledge Engine — queries 11 data sources to answer any Roblox development question", "author": { "name": "CyanoTex" diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100644 index 0000000..c0c466d --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,29 @@ +#!/bin/bash +# Auto-bump plugin version on first code commit per branch. + +# Skip on main +branch=$(git symbolic-ref --short HEAD 2>/dev/null) +if [ "$branch" = "main" ]; then + exit 0 +fi + +# Skip if already bumped vs main +main_version=$(git show main:.claude-plugin/plugin.json 2>/dev/null | grep -oP '"version":\s*"\K[^"]+') +current_version=$(grep -oP '"version":\s*"\K[^"]+' .claude-plugin/plugin.json) + +if [ "$main_version" != "$current_version" ]; then + exit 0 +fi + +# Skip if only docs/config staged +ignored='README\.md|LICENSE|CONTRIBUTING\.md|\.github/|\.githooks/|docs/' +version_files='\.claude-plugin/(plugin|marketplace)\.json' +code_staged=$(git diff --cached --name-only | grep -vE "$ignored" | grep -vE "$version_files" | head -1) + +if [ -z "$code_staged" ]; then + exit 0 +fi + +# Bump and stage +node "$(git rev-parse --show-toplevel)/scripts/bump-version.js" +git add .claude-plugin/plugin.json .claude-plugin/marketplace.json diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml new file mode 100644 index 0000000..fe4ef19 --- /dev/null +++ b/.github/workflows/version-bump.yml @@ -0,0 +1,52 @@ +name: Version Bump Check + +on: + pull_request: + branches: [main] + +jobs: + check-version: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check if code changed without version bump + run: | + BASE=${{ github.event.pull_request.base.sha }} + HEAD=${{ github.event.pull_request.head.sha }} + + IGNORED="README\.md|LICENSE|CONTRIBUTING\.md|\.github/|\.githooks/|docs/" + + CODE_CHANGED=$(git diff --name-only "$BASE" "$HEAD" | grep -vE "$IGNORED" | head -1) + + if [ -z "$CODE_CHANGED" ]; then + echo "Only docs/config changed — no version bump needed." + exit 0 + fi + + echo "Code files changed:" + git diff --name-only "$BASE" "$HEAD" | grep -vE "$IGNORED" + + VERSION_BUMPED=$(git diff --name-only "$BASE" "$HEAD" | grep -E "^\.claude-plugin/(plugin|marketplace)\.json$" | head -1) + + if [ -z "$VERSION_BUMPED" ]; then + echo "" + echo "::error::Code changed but no version bump detected. The pre-commit hook should handle this automatically — run: git config core.hooksPath .githooks" + exit 1 + fi + + PLUGIN_VER=$(git show "$HEAD:.claude-plugin/plugin.json" | grep -oP '"version":\s*"\K[^"]+') + MARKET_VER=$(git show "$HEAD:.claude-plugin/marketplace.json" | grep -oP '"version":\s*"\K[^"]+') + + echo "" + echo "Versions: plugin.json=$PLUGIN_VER, marketplace.json=$MARKET_VER" + + if [ "$PLUGIN_VER" != "$MARKET_VER" ]; then + echo "" + echo "::error::Version mismatch! plugin.json=$PLUGIN_VER, marketplace.json=$MARKET_VER" + exit 1 + fi + + echo "Version bump confirmed: $PLUGIN_VER" diff --git a/README.md b/README.md index 9359d83..002b964 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,16 @@ Bloxus is an AI coding-assistant skill that automatically activates when you wor - **Context7 sources**: Queried live via MCP — no local caching of docs content. - **DevForum**: Public Discourse API — community-generated content, cross-reference with official docs. +## Development Setup + +After cloning, enable the project git hooks: + +```bash +git config core.hooksPath .githooks +``` + +This wires up automatic version bumping — the pre-commit hook bumps the patch version in `plugin.json` and `marketplace.json` on the first code commit of each branch. + ## Contributing Want to add Bloxus support for another AI tool? See [CONTRIBUTING.md](./CONTRIBUTING.md) for the edition structure, parity requirements, and submission process. diff --git a/scripts/bump-version.js b/scripts/bump-version.js new file mode 100644 index 0000000..69c67da --- /dev/null +++ b/scripts/bump-version.js @@ -0,0 +1,21 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); + +const root = path.join(__dirname, '..'); +const files = [ + path.join(root, '.claude-plugin', 'plugin.json'), + path.join(root, '.claude-plugin', 'marketplace.json'), +]; + +const pluginData = JSON.parse(fs.readFileSync(files[0], 'utf8')); +const current = pluginData.version; +const [major, minor, patch] = current.split('.').map(Number); +const next = `${major}.${minor}.${patch + 1}`; + +for (const file of files) { + const content = fs.readFileSync(file, 'utf8'); + fs.writeFileSync(file, content.replace(`"version": "${current}"`, `"version": "${next}"`)); +} + +console.log(`${current} → ${next}`);