Skip to content

Commit 00fbb3d

Browse files
TMHSDigitalclaude
andcommitted
fix: reconcile plugin.json manifest with repo and CI-gate it
- plugin.json: bump version to 0.5.0 and enumerate snippets (17), templates (2), and examples (4) alongside skills and rules - validate.yml: new validate-manifest job asserting every manifest path exists, every content file/dir on disk is listed, and manifest version equals VERSION - release.yml: new step rewrites the plugin.json version line on each release so the pipeline owns it - AGENTS.md: document the new job and ownership Closes #28 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 5a96cef commit 00fbb3d

4 files changed

Lines changed: 115 additions & 3 deletions

File tree

.cursor-plugin/plugin.json

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "blender-developer-tools",
33
"displayName": "Blender Developer Tools",
44
"description": "Cursor and Claude Code skills, rules, snippets, and templates for Blender Python add-on and scripting development",
5-
"version": "0.2.3",
5+
"version": "0.5.0",
66
"author": {
77
"name": "TMHSDigital",
88
"email": "contact@users.noreply.github.com"
@@ -34,5 +34,34 @@
3434
"rules/type-annotate-props-and-defend-context.mdc",
3535
"rules/prefer-temp-override-over-context-copy.mdc",
3636
"rules/use-foreach-set-for-bulk-data.mdc"
37+
],
38+
"snippets": [
39+
"snippets/action-ensure-channelbag-for-slot.py",
40+
"snippets/app-handler-registration.py",
41+
"snippets/bmesh-load-edit-free.py",
42+
"snippets/canonical-object-creation.py",
43+
"snippets/canonical-object-deletion.py",
44+
"snippets/cross-version-property-delete.py",
45+
"snippets/depsgraph-evaluated-mesh.py",
46+
"snippets/driver-with-custom-function.py",
47+
"snippets/foreach-get-vertices.py",
48+
"snippets/foreach-set-vertices.py",
49+
"snippets/pointerproperty-binding.py",
50+
"snippets/principled-bsdf-material.py",
51+
"snippets/register-classes-factory.py",
52+
"snippets/shader-node-group.py",
53+
"snippets/temp-override-context.py",
54+
"snippets/usd-export-evaluation-mode.py",
55+
"snippets/version-branch-skeleton.py"
56+
],
57+
"templates": [
58+
"templates/extension-addon-template",
59+
"templates/headless-batch-script-template"
60+
],
61+
"examples": [
62+
"examples/depsgraph-export",
63+
"examples/gn-sdf-remesh",
64+
"examples/swatch-grid",
65+
"examples/turntable"
3766
]
3867
}

.github/workflows/release.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,27 @@ jobs:
122122
previous-version: ${{ steps.current.outputs.version }}
123123
meta-repo-ref: v1.15.1
124124

125+
- name: Sync plugin manifest version
126+
if: steps.check.outputs.skip == 'false' && steps.bump.outputs.release == 'true'
127+
env:
128+
NEW_VERSION: ${{ steps.new.outputs.version }}
129+
run: |
130+
python3 - << 'PYEOF'
131+
import os
132+
import re
133+
134+
path = '.cursor-plugin/plugin.json'
135+
text = open(path).read()
136+
text = re.sub(
137+
r'^( "version": ")[^"]+(",)$',
138+
rf'\g<1>{os.environ["NEW_VERSION"]}\g<2>',
139+
text,
140+
count=1,
141+
flags=re.M,
142+
)
143+
open(path, 'w').write(text)
144+
PYEOF
145+
125146
- name: Commit version bump
126147
if: steps.check.outputs.skip == 'false' && steps.bump.outputs.release == 'true'
127148
run: |

.github/workflows/validate.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,62 @@ jobs:
157157
echo "Templates: $template_count"
158158
echo "Snippets: $snippet_count"
159159
160+
validate-manifest:
161+
name: Validate plugin manifest
162+
runs-on: ubuntu-latest
163+
steps:
164+
- uses: actions/checkout@v7
165+
166+
- name: Check plugin.json matches filesystem and VERSION
167+
run: |
168+
python3 << 'PYEOF'
169+
import glob
170+
import json
171+
import os
172+
import sys
173+
174+
errors = []
175+
manifest = json.load(open('.cursor-plugin/plugin.json'))
176+
177+
version = open('VERSION').read().strip()
178+
if manifest.get('version') != version:
179+
errors.append(
180+
f"plugin.json version '{manifest.get('version')}' != VERSION '{version}'"
181+
)
182+
183+
# Every manifest path must exist on disk.
184+
for key in ('skills', 'rules', 'snippets', 'templates', 'examples'):
185+
for path in manifest.get(key, []):
186+
if not os.path.exists(path):
187+
errors.append(f'{key}: manifest lists missing path {path}')
188+
189+
# Every content file/dir on disk must be listed in the manifest.
190+
expected = {
191+
'skills': sorted(glob.glob('skills/*/SKILL.md')),
192+
'rules': sorted(glob.glob('rules/*.mdc')),
193+
'snippets': sorted(glob.glob('snippets/*.py')),
194+
'templates': sorted(
195+
d for d in glob.glob('templates/*') if os.path.isdir(d)
196+
),
197+
'examples': sorted(
198+
d for d in glob.glob('examples/*') if os.path.isdir(d)
199+
),
200+
}
201+
for key, paths in expected.items():
202+
listed = {p.replace('\\', '/') for p in manifest.get(key, [])}
203+
for path in paths:
204+
if path.replace('\\', '/') not in listed:
205+
errors.append(f'{key}: {path} on disk but not in manifest')
206+
207+
if errors:
208+
for e in errors:
209+
print(f'::error::{e}', file=sys.stderr)
210+
sys.exit(1)
211+
212+
counts = {k: len(manifest.get(k, [])) for k in expected}
213+
print(f'Manifest verified at v{version}: {counts}')
214+
PYEOF
215+
160216
validate-counts:
161217
name: Validate content counts
162218
runs-on: ubuntu-latest

AGENTS.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,18 @@ way, and a one-paragraph rationale. 30 to 80 lines is the right size.
111111
asserts the README aggregate counts (12 skills, 6 rules, 2 templates, 17
112112
snippets) match filesystem reality. The counts language in `README.md` is
113113
load-bearing: the job greps for it.
114+
- `validate.yml` also runs a `validate-manifest` job that checks
115+
`.cursor-plugin/plugin.json` against reality: every listed path must exist,
116+
every skill, rule, snippet, template, and example on disk must be listed,
117+
and the manifest `version` must equal `VERSION`. The release pipeline owns
118+
the manifest `version` line (see `release.yml` below) — never hand-edit it.
114119
- `drift-check.yml` consumes `Developer-Tools-Directory/.github/actions/
115120
drift-check@v1.15` to enforce ecosystem standards-version markers.
116121
- `release.yml` auto-bumps the version, tags, force-updates floating tags
117122
`v0` and `v0.1`, and runs `release-doc-sync@v1` to rewrite CHANGELOG.md,
118-
CLAUDE.md `**Version:**`, and ROADMAP.md `**Current:**`. Triggered on
119-
push to `main` for content-changing paths only.
123+
CLAUDE.md `**Version:**`, and ROADMAP.md `**Current:**`. It also rewrites
124+
the `"version"` line in `.cursor-plugin/plugin.json` so the manifest tracks
125+
each release. Triggered on push to `main` for content-changing paths only.
120126
- `label-sync.yml` self-heals labels via `gh label create --force` per
121127
label, then applies them to the PR.
122128

0 commit comments

Comments
 (0)