From 8191d71e7276d3e14a8d9fc22a52fba8e9e0fbee Mon Sep 17 00:00:00 2001 From: dhruvja Date: Sat, 12 Sep 2026 19:05:57 +0700 Subject: [PATCH 1/5] feat: track skill versions and require bumps for updates --- .github/workflows/version.yml | 39 +++++++++++++ .gitignore | 3 + CHANGELOG.md | 6 ++ README.md | 41 ++++++++++++++ build.sh | 10 +++- install.sh | 3 + scripts/check-version.py | 63 +++++++++++++++++++++ skill/VERSION | 1 + tests/test_version.py | 103 ++++++++++++++++++++++++++++++++++ 9 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/version.yml create mode 100644 CHANGELOG.md create mode 100644 scripts/check-version.py create mode 100644 skill/VERSION create mode 100644 tests/test_version.py diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml new file mode 100644 index 0000000..f747a8f --- /dev/null +++ b/.github/workflows/version.yml @@ -0,0 +1,39 @@ +name: Version check + +on: + pull_request: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +jobs: + version: + runs-on: ubuntu-latest + steps: + - name: Fetch source and comparison base + env: + BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} + run: | + git init . + git remote add origin "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git" + git fetch --depth=1 origin "$GITHUB_SHA" + git checkout --detach FETCH_HEAD + if [[ -n "$BASE_SHA" && ! "$BASE_SHA" =~ ^0+$ ]]; then + git fetch --depth=1 origin "$BASE_SHA" + fi + - name: Check version and changelog + env: + BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} + run: | + args=() + if [[ -n "$BASE_SHA" && ! "$BASE_SHA" =~ ^0+$ ]]; then + args=(--base "$BASE_SHA") + fi + python3 scripts/check-version.py "${args[@]}" + - name: Test version enforcement + run: python3 -m unittest discover -s tests + - name: Build and validate artifacts + run: bash build.sh diff --git a/.gitignore b/.gitignore index 506cf9c..47b2fde 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ Thumbs.db # Build artifacts dist/ + +# Python validation caches +__pycache__/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b2e1da6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +## 0.1.0 + +- Establish version tracking for the existing MagicBlock skill and its packaged artifacts. +- Require a version increase and changelog entry when skill content or packaging changes. diff --git a/README.md b/README.md index 94387fc..285bdc1 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,47 @@ Produces: - `dist/magicblock.full.cursor.mdc` — full Cursor rule - `dist/magicblock.zip` — zipped `skill/` folder for Claude.ai upload +## Versioning and updates + +`skill/VERSION` is the single source of truth for the skill's version, starting at `0.1.0`. +It is independent of MagicBlock SDK and protocol versions. Folder installs and ZIPs include +`VERSION`; generated single-file artifacts include a `Skill version` comment. +Run `./install.sh --version` to print the source checkout's version, or read `VERSION` in +an installed skill directory. + +Every PR changing `skill/`, `build.sh`, or `install.sh` must increase `skill/VERSION` and +add an entry at the top of `CHANGELOG.md`. Use stable `MAJOR.MINOR.PATCH` versions: + +- Patch for corrections and compatible packaging fixes. +- Minor for new product coverage or compatible workflows. +- Major for incompatible installation or workflow changes. + +Bump once per PR, not once per commit. README-only and CI-only changes do not require a bump. +If another version lands first, update the PR's version and changelog against the new base. +The Version check workflow checks this on PRs and pushes to `main`. Repository maintainers +should make its `version` job a required status check in branch protection. + +Run the same check locally before opening a PR: + +```bash +git fetch origin +python3 scripts/check-version.py --base origin/main +python3 -m unittest discover -s tests +./build.sh +``` + +To update a manual installation to the latest version on `main`, start from a clean clone: + +```bash +cd magicblock-dev-skill +git switch main +git pull --ff-only origin main +./install.sh --codex # reuse your original target flags +``` + +Installed copies do not update automatically. Review the changelog and rerun the installer +when updating. Keep using the same target and project directory for project-scoped installs. + ## Recommended companion skill: `solana-dev` This skill covers MagicBlock-specific patterns: ER/PER, delegation, oracles, Session Keys, cranks, VRF, diff --git a/build.sh b/build.sh index 61b0038..d9488ae 100755 --- a/build.sh +++ b/build.sh @@ -11,6 +11,11 @@ REFERENCE_DIR="$SKILL_DIR/references" DIST_DIR="$SCRIPT_DIR/dist" SKILL_NAME="magicblock" REPO_URL="https://github.com/magicblock-labs/magicblock-dev-skill" +SKILL_VERSION="$(cat "$SKILL_DIR/VERSION")" +if [[ ! "$SKILL_VERSION" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then + echo "Error: skill/VERSION must contain a stable MAJOR.MINOR.PATCH version" >&2 + exit 1 +fi GIT_CONTEXT=false GIT_ROOT="" if command -v git >/dev/null 2>&1; then @@ -384,6 +389,7 @@ build_flattened() { local ref { echo "" + echo "" echo "" echo "" echo "" @@ -426,6 +432,7 @@ build_system_prompt() { else echo "" fi + echo "" echo "" echo "" echo "" @@ -523,7 +530,8 @@ validate_artifacts() { echo "Error: unresolved relative Markdown link in $artifact" >&2 exit 1 fi - if ! grep -Fq "" "$artifact" || \ + if ! grep -Fq "" "$artifact" || \ + ! grep -Fq "" "$artifact" || \ ! grep -Fq "" "$artifact" || \ ! grep -Fq "" "$artifact"; then echo "Error: incomplete source provenance in $artifact" >&2 diff --git a/install.sh b/install.sh index 4953630..cf289bb 100755 --- a/install.sh +++ b/install.sh @@ -54,6 +54,7 @@ Modifiers: --full For single-file targets, preload every product reference. Default single-file installs keep deep guides on demand --path PATH Install the raw skill/ folder to a custom path + --version Print the version in this source checkout -h, --help Show this help message Defaults: @@ -168,6 +169,8 @@ while [[ $# -gt 0 ]]; do exit 1 fi CUSTOM_PATH="$2"; shift 2 ;; + --version) + cat "$SOURCE_DIR/VERSION"; exit 0 ;; -h|--help) print_help; exit 0 ;; *) diff --git a/scripts/check-version.py b/scripts/check-version.py new file mode 100644 index 0000000..40a4cd9 --- /dev/null +++ b/scripts/check-version.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +"""Validate the skill version and require bumps against a Git base revision.""" + +import argparse +from pathlib import Path +import re +import subprocess + +VERSION_PATH = "skill/VERSION" +VERSION_PATTERN = r"(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)" + + +def parse_version(value): + value = value.strip() + if not re.fullmatch(VERSION_PATTERN, value): + raise ValueError("skill/VERSION must contain a stable MAJOR.MINOR.PATCH version") + return tuple(map(int, value.split("."))) + + +def git(root, *args): + return subprocess.check_output(["git", *args], cwd=root, text=True, stderr=subprocess.PIPE) + + +def check(root, base=None): + current = (root / VERSION_PATH).read_text().strip() + current_version = parse_version(current) + entries = re.findall(r"^## (.+)$", (root / "CHANGELOG.md").read_text(), re.MULTILINE) + if not entries or entries[0] != current: + raise ValueError(f"CHANGELOG.md must start with an entry for {current}") + if base is None: + return + + # A missing base or failed Git command must fail the check, not look like a first release. + git(root, "rev-parse", "--verify", f"{base}^{{commit}}") + base_paths = git(root, "ls-tree", "-r", "--name-only", base).splitlines() + if VERSION_PATH not in base_paths: + if current_version != (0, 1, 0): + raise ValueError("The initial tracked version must be 0.1.0") + return + + previous = parse_version(git(root, "show", f"{base}:{VERSION_PATH}")) + if current_version < previous: + raise ValueError("The skill version cannot decrease") + changed = git(root, "diff", "--name-only", "-z", "--no-renames", base, "--").split("\0") + skill_changed = any(path.startswith("skill/") or path in ("build.sh", "install.sh") + for path in changed) + if skill_changed and current_version <= previous: + raise ValueError("Skill or packaging changed: increase skill/VERSION and add a changelog entry") + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--base", help="Git base revision to compare, e.g. origin/main") + args = parser.parse_args() + try: + check(Path(__file__).resolve().parents[1], args.base) + except (ValueError, OSError, subprocess.CalledProcessError) as error: + parser.exit(1, f"Version check failed: {error}\n") + print("Version check passed") + + +if __name__ == "__main__": + main() diff --git a/skill/VERSION b/skill/VERSION new file mode 100644 index 0000000..6e8bf73 --- /dev/null +++ b/skill/VERSION @@ -0,0 +1 @@ +0.1.0 diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 0000000..51c3b41 --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,103 @@ +import importlib.util +from pathlib import Path +import subprocess +import tempfile +import unittest + +spec = importlib.util.spec_from_file_location( + "check_version", Path(__file__).resolve().parents[1] / "scripts/check-version.py" +) +version = importlib.util.module_from_spec(spec) +spec.loader.exec_module(version) + + +class VersionCheckTests(unittest.TestCase): + def setUp(self): + self.temp = tempfile.TemporaryDirectory() + self.addCleanup(self.temp.cleanup) + self.root = Path(self.temp.name) + self.git("init", "-q") + (self.root / "skill").mkdir() + self.write("skill/SKILL.md", "Original skill\n") + self.write("skill/references/guide.md", "Original reference\n") + self.write("build.sh", "original build\n") + self.write("install.sh", "original installer\n") + self.write("README.md", "original readme\n") + self.release("0.1.0") + self.git("add", ".") + self.git("-c", "user.name=dhruvja", "-c", "user.email=dhruvja@users.noreply.github.com", + "commit", "-qm", "test: initial version fixture") + + def git(self, *args): + return subprocess.check_output(["git", *args], cwd=self.root, text=True, + stderr=subprocess.DEVNULL) + + def write(self, path, content): + target = self.root / path + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text(content) + + def release(self, number): + self.write("skill/VERSION", number + "\n") + self.write("CHANGELOG.md", f"# Changelog\n\n## {number}\n\n- Test change.\n") + + def test_unchanged_and_readme_only_pass(self): + version.check(self.root, "HEAD") + self.write("README.md", "updated readme\n") + version.check(self.root, "HEAD") + + def test_content_and_packaging_require_bump(self): + for path in ("skill/SKILL.md", "skill/references/guide.md", "build.sh", "install.sh"): + with self.subTest(path=path): + original = (self.root / path).read_text() + self.write(path, "changed\n") + with self.assertRaisesRegex(ValueError, "increase skill/VERSION"): + version.check(self.root, "HEAD") + self.write(path, original) + + def test_deleted_reference_requires_bump(self): + (self.root / "skill/references/guide.md").unlink() + with self.assertRaisesRegex(ValueError, "increase skill/VERSION"): + version.check(self.root, "HEAD") + + def test_valid_bumps_pass(self): + self.write("skill/SKILL.md", "updated skill\n") + for number in ("0.1.1", "0.2.0", "1.0.0", "0.10.0"): + with self.subTest(number=number): + self.release(number) + version.check(self.root, "HEAD") + + def test_bump_requires_current_changelog_entry(self): + self.write("skill/VERSION", "0.1.1\n") + with self.assertRaisesRegex(ValueError, "CHANGELOG.md"): + version.check(self.root, "HEAD") + + def test_downgrade_fails(self): + self.release("0.0.9") + with self.assertRaisesRegex(ValueError, "cannot decrease"): + version.check(self.root, "HEAD") + + def test_invalid_versions_fail(self): + for number in ("v0.1.0", "01.1.0", "1.0", "1.0.0-beta", "1.0.0\n2.0.0"): + with self.subTest(number=number): + self.release(number) + with self.assertRaisesRegex(ValueError, "MAJOR.MINOR.PATCH"): + version.check(self.root, "HEAD") + + def test_missing_base_fails(self): + with self.assertRaises(subprocess.CalledProcessError): + version.check(self.root, "missing-ref") + + def test_initial_version(self): + self.git("rm", "-q", "skill/VERSION") + self.git("-c", "user.name=dhruvja", "-c", "user.email=dhruvja@users.noreply.github.com", + "commit", "-qm", "test: unversioned fixture") + self.release("0.1.0") + version.check(self.root, "HEAD") + self.release("0.2.0") + with self.assertRaisesRegex(ValueError, "initial tracked version"): + version.check(self.root, "HEAD") + + +if __name__ == "__main__": + unittest.main() From bbe3af3595f933149d2813b554da04f9a23f99fb Mon Sep 17 00:00:00 2001 From: dhruvja Date: Sat, 12 Sep 2026 19:07:54 +0700 Subject: [PATCH 2/5] chore: remove GitHub version workflow --- .github/workflows/version.yml | 39 ----------------------------------- CHANGELOG.md | 2 +- README.md | 7 ++----- 3 files changed, 3 insertions(+), 45 deletions(-) delete mode 100644 .github/workflows/version.yml diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml deleted file mode 100644 index f747a8f..0000000 --- a/.github/workflows/version.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Version check - -on: - pull_request: - push: - branches: [main] - workflow_dispatch: - -permissions: - contents: read - -jobs: - version: - runs-on: ubuntu-latest - steps: - - name: Fetch source and comparison base - env: - BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} - run: | - git init . - git remote add origin "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git" - git fetch --depth=1 origin "$GITHUB_SHA" - git checkout --detach FETCH_HEAD - if [[ -n "$BASE_SHA" && ! "$BASE_SHA" =~ ^0+$ ]]; then - git fetch --depth=1 origin "$BASE_SHA" - fi - - name: Check version and changelog - env: - BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} - run: | - args=() - if [[ -n "$BASE_SHA" && ! "$BASE_SHA" =~ ^0+$ ]]; then - args=(--base "$BASE_SHA") - fi - python3 scripts/check-version.py "${args[@]}" - - name: Test version enforcement - run: python3 -m unittest discover -s tests - - name: Build and validate artifacts - run: bash build.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index b2e1da6..3772e92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,4 +3,4 @@ ## 0.1.0 - Establish version tracking for the existing MagicBlock skill and its packaged artifacts. -- Require a version increase and changelog entry when skill content or packaging changes. +- Add a local check for a version increase and changelog entry when skill content or packaging changes. diff --git a/README.md b/README.md index 285bdc1..facaf77 100644 --- a/README.md +++ b/README.md @@ -107,12 +107,9 @@ add an entry at the top of `CHANGELOG.md`. Use stable `MAJOR.MINOR.PATCH` versio - Minor for new product coverage or compatible workflows. - Major for incompatible installation or workflow changes. -Bump once per PR, not once per commit. README-only and CI-only changes do not require a bump. +Bump once per PR, not once per commit. README-only changes do not require a bump. If another version lands first, update the PR's version and changelog against the new base. -The Version check workflow checks this on PRs and pushes to `main`. Repository maintainers -should make its `version` job a required status check in branch protection. - -Run the same check locally before opening a PR: +Run the version check locally before opening a PR: ```bash git fetch origin From e22c66724683e47c5024a8608cedfedf5ad05ba8 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Sat, 12 Sep 2026 19:09:53 +0700 Subject: [PATCH 3/5] chore: remove version check tests --- .gitignore | 3 -- README.md | 1 - tests/test_version.py | 103 ------------------------------------------ 3 files changed, 107 deletions(-) delete mode 100644 tests/test_version.py diff --git a/.gitignore b/.gitignore index 47b2fde..506cf9c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,3 @@ Thumbs.db # Build artifacts dist/ - -# Python validation caches -__pycache__/ diff --git a/README.md b/README.md index facaf77..b45e64e 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,6 @@ Run the version check locally before opening a PR: ```bash git fetch origin python3 scripts/check-version.py --base origin/main -python3 -m unittest discover -s tests ./build.sh ``` diff --git a/tests/test_version.py b/tests/test_version.py deleted file mode 100644 index 51c3b41..0000000 --- a/tests/test_version.py +++ /dev/null @@ -1,103 +0,0 @@ -import importlib.util -from pathlib import Path -import subprocess -import tempfile -import unittest - -spec = importlib.util.spec_from_file_location( - "check_version", Path(__file__).resolve().parents[1] / "scripts/check-version.py" -) -version = importlib.util.module_from_spec(spec) -spec.loader.exec_module(version) - - -class VersionCheckTests(unittest.TestCase): - def setUp(self): - self.temp = tempfile.TemporaryDirectory() - self.addCleanup(self.temp.cleanup) - self.root = Path(self.temp.name) - self.git("init", "-q") - (self.root / "skill").mkdir() - self.write("skill/SKILL.md", "Original skill\n") - self.write("skill/references/guide.md", "Original reference\n") - self.write("build.sh", "original build\n") - self.write("install.sh", "original installer\n") - self.write("README.md", "original readme\n") - self.release("0.1.0") - self.git("add", ".") - self.git("-c", "user.name=dhruvja", "-c", "user.email=dhruvja@users.noreply.github.com", - "commit", "-qm", "test: initial version fixture") - - def git(self, *args): - return subprocess.check_output(["git", *args], cwd=self.root, text=True, - stderr=subprocess.DEVNULL) - - def write(self, path, content): - target = self.root / path - target.parent.mkdir(parents=True, exist_ok=True) - target.write_text(content) - - def release(self, number): - self.write("skill/VERSION", number + "\n") - self.write("CHANGELOG.md", f"# Changelog\n\n## {number}\n\n- Test change.\n") - - def test_unchanged_and_readme_only_pass(self): - version.check(self.root, "HEAD") - self.write("README.md", "updated readme\n") - version.check(self.root, "HEAD") - - def test_content_and_packaging_require_bump(self): - for path in ("skill/SKILL.md", "skill/references/guide.md", "build.sh", "install.sh"): - with self.subTest(path=path): - original = (self.root / path).read_text() - self.write(path, "changed\n") - with self.assertRaisesRegex(ValueError, "increase skill/VERSION"): - version.check(self.root, "HEAD") - self.write(path, original) - - def test_deleted_reference_requires_bump(self): - (self.root / "skill/references/guide.md").unlink() - with self.assertRaisesRegex(ValueError, "increase skill/VERSION"): - version.check(self.root, "HEAD") - - def test_valid_bumps_pass(self): - self.write("skill/SKILL.md", "updated skill\n") - for number in ("0.1.1", "0.2.0", "1.0.0", "0.10.0"): - with self.subTest(number=number): - self.release(number) - version.check(self.root, "HEAD") - - def test_bump_requires_current_changelog_entry(self): - self.write("skill/VERSION", "0.1.1\n") - with self.assertRaisesRegex(ValueError, "CHANGELOG.md"): - version.check(self.root, "HEAD") - - def test_downgrade_fails(self): - self.release("0.0.9") - with self.assertRaisesRegex(ValueError, "cannot decrease"): - version.check(self.root, "HEAD") - - def test_invalid_versions_fail(self): - for number in ("v0.1.0", "01.1.0", "1.0", "1.0.0-beta", "1.0.0\n2.0.0"): - with self.subTest(number=number): - self.release(number) - with self.assertRaisesRegex(ValueError, "MAJOR.MINOR.PATCH"): - version.check(self.root, "HEAD") - - def test_missing_base_fails(self): - with self.assertRaises(subprocess.CalledProcessError): - version.check(self.root, "missing-ref") - - def test_initial_version(self): - self.git("rm", "-q", "skill/VERSION") - self.git("-c", "user.name=dhruvja", "-c", "user.email=dhruvja@users.noreply.github.com", - "commit", "-qm", "test: unversioned fixture") - self.release("0.1.0") - version.check(self.root, "HEAD") - self.release("0.2.0") - with self.assertRaisesRegex(ValueError, "initial tracked version"): - version.check(self.root, "HEAD") - - -if __name__ == "__main__": - unittest.main() From 9d8934d2d25725f49cdbf530914a855e5e6065ee Mon Sep 17 00:00:00 2001 From: dhruvja Date: Mon, 14 Sep 2026 10:59:46 +0700 Subject: [PATCH 4/5] chore: remove skill changelog requirement --- CHANGELOG.md | 6 ------ README.md | 7 +++---- scripts/check-version.py | 5 +---- 3 files changed, 4 insertions(+), 14 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 3772e92..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,6 +0,0 @@ -# Changelog - -## 0.1.0 - -- Establish version tracking for the existing MagicBlock skill and its packaged artifacts. -- Add a local check for a version increase and changelog entry when skill content or packaging changes. diff --git a/README.md b/README.md index b45e64e..ca785c6 100644 --- a/README.md +++ b/README.md @@ -100,15 +100,14 @@ It is independent of MagicBlock SDK and protocol versions. Folder installs and Z Run `./install.sh --version` to print the source checkout's version, or read `VERSION` in an installed skill directory. -Every PR changing `skill/`, `build.sh`, or `install.sh` must increase `skill/VERSION` and -add an entry at the top of `CHANGELOG.md`. Use stable `MAJOR.MINOR.PATCH` versions: +Every PR changing `skill/`, `build.sh`, or `install.sh` must increase `skill/VERSION`. Use stable `MAJOR.MINOR.PATCH` versions: - Patch for corrections and compatible packaging fixes. - Minor for new product coverage or compatible workflows. - Major for incompatible installation or workflow changes. Bump once per PR, not once per commit. README-only changes do not require a bump. -If another version lands first, update the PR's version and changelog against the new base. +If another version lands first, update the PR's version against the new base. Run the version check locally before opening a PR: ```bash @@ -126,7 +125,7 @@ git pull --ff-only origin main ./install.sh --codex # reuse your original target flags ``` -Installed copies do not update automatically. Review the changelog and rerun the installer +Installed copies do not update automatically. Review the merged PRs or Git history and rerun the installer when updating. Keep using the same target and project directory for project-scoped installs. ## Recommended companion skill: `solana-dev` diff --git a/scripts/check-version.py b/scripts/check-version.py index 40a4cd9..6b07536 100644 --- a/scripts/check-version.py +++ b/scripts/check-version.py @@ -24,9 +24,6 @@ def git(root, *args): def check(root, base=None): current = (root / VERSION_PATH).read_text().strip() current_version = parse_version(current) - entries = re.findall(r"^## (.+)$", (root / "CHANGELOG.md").read_text(), re.MULTILINE) - if not entries or entries[0] != current: - raise ValueError(f"CHANGELOG.md must start with an entry for {current}") if base is None: return @@ -45,7 +42,7 @@ def check(root, base=None): skill_changed = any(path.startswith("skill/") or path in ("build.sh", "install.sh") for path in changed) if skill_changed and current_version <= previous: - raise ValueError("Skill or packaging changed: increase skill/VERSION and add a changelog entry") + raise ValueError("Skill or packaging changed: increase skill/VERSION") def main(): From 822c796ab5ce7c70d1bf61933a55788d9e84b027 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Mon, 14 Sep 2026 11:00:51 +0700 Subject: [PATCH 5/5] chore: remove local version check script --- README.md | 8 +----- scripts/check-version.py | 60 ---------------------------------------- 2 files changed, 1 insertion(+), 67 deletions(-) delete mode 100644 scripts/check-version.py diff --git a/README.md b/README.md index ca785c6..b133435 100644 --- a/README.md +++ b/README.md @@ -108,13 +108,7 @@ Every PR changing `skill/`, `build.sh`, or `install.sh` must increase `skill/VER Bump once per PR, not once per commit. README-only changes do not require a bump. If another version lands first, update the PR's version against the new base. -Run the version check locally before opening a PR: - -```bash -git fetch origin -python3 scripts/check-version.py --base origin/main -./build.sh -``` +Update `skill/VERSION` manually and run `./build.sh` to rebuild the artifacts. To update a manual installation to the latest version on `main`, start from a clean clone: diff --git a/scripts/check-version.py b/scripts/check-version.py deleted file mode 100644 index 6b07536..0000000 --- a/scripts/check-version.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python3 -"""Validate the skill version and require bumps against a Git base revision.""" - -import argparse -from pathlib import Path -import re -import subprocess - -VERSION_PATH = "skill/VERSION" -VERSION_PATTERN = r"(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)" - - -def parse_version(value): - value = value.strip() - if not re.fullmatch(VERSION_PATTERN, value): - raise ValueError("skill/VERSION must contain a stable MAJOR.MINOR.PATCH version") - return tuple(map(int, value.split("."))) - - -def git(root, *args): - return subprocess.check_output(["git", *args], cwd=root, text=True, stderr=subprocess.PIPE) - - -def check(root, base=None): - current = (root / VERSION_PATH).read_text().strip() - current_version = parse_version(current) - if base is None: - return - - # A missing base or failed Git command must fail the check, not look like a first release. - git(root, "rev-parse", "--verify", f"{base}^{{commit}}") - base_paths = git(root, "ls-tree", "-r", "--name-only", base).splitlines() - if VERSION_PATH not in base_paths: - if current_version != (0, 1, 0): - raise ValueError("The initial tracked version must be 0.1.0") - return - - previous = parse_version(git(root, "show", f"{base}:{VERSION_PATH}")) - if current_version < previous: - raise ValueError("The skill version cannot decrease") - changed = git(root, "diff", "--name-only", "-z", "--no-renames", base, "--").split("\0") - skill_changed = any(path.startswith("skill/") or path in ("build.sh", "install.sh") - for path in changed) - if skill_changed and current_version <= previous: - raise ValueError("Skill or packaging changed: increase skill/VERSION") - - -def main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--base", help="Git base revision to compare, e.g. origin/main") - args = parser.parse_args() - try: - check(Path(__file__).resolve().parents[1], args.base) - except (ValueError, OSError, subprocess.CalledProcessError) as error: - parser.exit(1, f"Version check failed: {error}\n") - print("Version check passed") - - -if __name__ == "__main__": - main()