From e40125a7469e1a872a0cc7cea06b9d5d19d6e93c Mon Sep 17 00:00:00 2001 From: Corey Haines <34802794+coreyhaines31@users.noreply.github.com> Date: Tue, 26 May 2026 11:12:39 -0700 Subject: [PATCH] fix: keep plugin.json version in sync with marketplace.json (closes #323) (#326) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plugin.json's version field had been stuck at 1.9.0 across three releases (v2.0, v2.0.1, v2.1.0) while marketplace.json was bumped each time. Claude Code uses plugin.json's version for the update check, so `claude plugin update marketing-skills@marketingskills` reported "already at the latest version (1.9.0)" and refused to pull anything new — even when main had real new content (sms skill, refreshed ai-seo / image / video). Three changes: 1. .claude-plugin/plugin.json: bumped 1.9.0 → 2.1.0 to clear the current drift. 2. .github/scripts/sync-skills.js: added updatePluginVersion() that reads marketplace.json's metadata.version and copies it into plugin.json's version field. Idempotent — no-op when they already match. 3. .github/workflows/sync-skills.yml: added marketplace.json to the `paths` filter so the sync workflow runs whenever marketplace.json changes (previously it only ran on skills/** changes, which is why release commits that only bumped marketplace.json never triggered the sync). Also added .claude-plugin/plugin.json to the file_pattern so the bot commit captures the auto-bump. Verified locally: script bumped 1.9.0 → 2.1.0, then a second run reported "Everything is already in sync." Co-authored-by: Claude Opus 4.7 --- .claude-plugin/plugin.json | 2 +- .github/scripts/sync-skills.js | 30 +++++++++++++++++++++++++++++- .github/workflows/sync-skills.yml | 5 +++-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index b2f45c8..a4c9d56 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "marketing-skills", "description": "Marketing skills for AI agents — conversion optimization, copywriting, SEO, paid ads, ad creative, and growth", - "version": "1.9.0", + "version": "2.1.0", "author": { "name": "Corey Haines" }, diff --git a/.github/scripts/sync-skills.js b/.github/scripts/sync-skills.js index f56ffe4..0dc90a1 100644 --- a/.github/scripts/sync-skills.js +++ b/.github/scripts/sync-skills.js @@ -11,6 +11,7 @@ const path = require("path"); const SKILLS_DIR = "skills"; const MARKETPLACE_FILE = ".claude-plugin/marketplace.json"; +const PLUGIN_FILE = ".claude-plugin/plugin.json"; const README_FILE = "README.md"; /** @@ -157,13 +158,36 @@ function updateMarketplace(skills) { return { updated: true, removedSkillsArray: hadStaleSkillsArray }; } +/** + * Update plugin.json's `version` field to match marketplace.json's + * `metadata.version`. Claude Code uses plugin.json's version for the update + * check (`claude plugin update`); if it drifts from marketplace.json the + * update path silently breaks. + */ +function updatePluginVersion() { + if (!fs.existsSync(PLUGIN_FILE)) return { updated: false }; + + const marketplace = JSON.parse(fs.readFileSync(MARKETPLACE_FILE, "utf8")); + const plugin = JSON.parse(fs.readFileSync(PLUGIN_FILE, "utf8")); + const marketplaceVersion = marketplace.metadata && marketplace.metadata.version; + + if (!marketplaceVersion) return { updated: false }; + if (plugin.version === marketplaceVersion) return { updated: false }; + + const oldVersion = plugin.version; + plugin.version = marketplaceVersion; + fs.writeFileSync(PLUGIN_FILE, JSON.stringify(plugin, null, 2) + "\n"); + return { updated: true, oldVersion, newVersion: marketplaceVersion }; +} + function main() { const skills = getSkillsWithMetadata(); const marketplaceResult = updateMarketplace(skills); const readmeUpdated = updateReadme(skills); + const pluginResult = updatePluginVersion(); - if (!marketplaceResult.updated && !readmeUpdated) { + if (!marketplaceResult.updated && !readmeUpdated && !pluginResult.updated) { console.log("Everything is already in sync"); return; } @@ -175,6 +199,10 @@ function main() { console.log(`Updated marketplace.json (${skills.length} skills)`); } + if (pluginResult.updated) { + console.log(`Bumped plugin.json version: ${pluginResult.oldVersion} → ${pluginResult.newVersion}`); + } + if (readmeUpdated) { console.log("Updated README.md skills table"); } diff --git a/.github/workflows/sync-skills.yml b/.github/workflows/sync-skills.yml index 4e9d5b9..bcbb97a 100644 --- a/.github/workflows/sync-skills.yml +++ b/.github/workflows/sync-skills.yml @@ -5,6 +5,7 @@ on: branches: [main] paths: - 'skills/**' + - '.claude-plugin/marketplace.json' jobs: sync: @@ -26,5 +27,5 @@ jobs: with: commit_user_name: Coreybot commit_user_email: coreybot+github-actions[bot]@users.noreply.github.com - commit_message: "chore: sync skills with marketplace.json and README" - file_pattern: ".claude-plugin/marketplace.json README.md" + commit_message: "chore: sync skills with marketplace.json, plugin.json, and README" + file_pattern: ".claude-plugin/marketplace.json .claude-plugin/plugin.json README.md"