Update External Plugins #14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Update External Plugins | |
| # Auto-bump external-plugin pins (source.ref + mirrored version) when an | |
| # upstream publishes a newer release. Opens a reviewable chore(...) PR; | |
| # manifest-only chore commits do not trigger an agent-plugins release. | |
| on: | |
| schedule: | |
| - cron: '17 6 * * *' # daily, 06:17 UTC | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| concurrency: | |
| group: update-external-plugins | |
| cancel-in-progress: false | |
| jobs: | |
| update: | |
| name: Resolve and pin latest external releases | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.x' | |
| - name: Update external plugin pins | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: python3 .github/scripts/update_external_plugins.py | |
| - name: Validate manifest sync | |
| run: | | |
| python3 << 'EOF' | |
| import json, re, sys | |
| claude = json.load(open('.claude-plugin/marketplace.json')) | |
| agents = json.load(open('.agents/plugins/marketplace.json')) | |
| a_by_name = {p.get('name'): p for p in agents.get('plugins', [])} | |
| def norm(url): | |
| m = re.match(r'^git@github\.com:(.+?)(?:\.git)?$', (url or '').strip()) | |
| if m: | |
| return m.group(1).lower() | |
| m = re.match(r'^https://github\.com/(.+?)(?:\.git)?$', | |
| (url or '').strip()) | |
| return m.group(1).lower() if m else (url or '').strip().lower() | |
| errors = [] | |
| for e in claude.get('plugins', []): | |
| s = e.get('source') | |
| if not isinstance(s, dict) or s.get('source') != 'github': | |
| continue | |
| name, repo = e.get('name'), s.get('repo', '') | |
| ref, ver = s.get('ref', ''), e.get('version') | |
| if ver is not None and ref != f"v{ver}": | |
| errors.append(f"{name}: ref {ref!r} != v+version {ver!r}") | |
| a = a_by_name.get(name) | |
| if a is None: | |
| errors.append(f"{name}: missing from .agents manifest") | |
| continue | |
| a_src = a.get('source', {}) | |
| if norm(a_src.get('url', '')) != repo.lower(): | |
| errors.append(f"{name}: .agents repo mismatch") | |
| if a_src.get('ref', '') != ref: | |
| errors.append( | |
| f"{name}: ref mismatch claude {ref!r} vs " | |
| f".agents {a_src.get('ref','')!r}") | |
| if errors: | |
| print("\n".join(f"❌ {x}" for x in errors)) | |
| sys.exit(1) | |
| print("✅ external manifests in sync") | |
| EOF | |
| - name: Open PR | |
| id: cpr | |
| uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 | |
| with: | |
| branch: automation/external-plugin-updates | |
| base: master | |
| commit-message: 'chore(external-plugins): update external plugin pins' | |
| title: 'chore(external-plugins): update external plugin pins' | |
| body: | | |
| Automated external-plugin pin update. | |
| Bumps `source.ref` in both manifests (and the mirrored | |
| `version` in `.claude-plugin/marketplace.json`) to the latest | |
| eligible upstream release. Manifest-only `chore:` change - no | |
| agent-plugins release is triggered. | |
| Review the diff against the upstream changelog before merging. | |
| delete-branch: true | |
| add-paths: | | |
| .claude-plugin/marketplace.json | |
| .agents/plugins/marketplace.json | |
| - name: Auto-merge | |
| # The inline "Validate manifest sync" step above is the gate: if it | |
| # fails the workflow stops and no PR exists. Manifest-only chore PR | |
| # -> no agent-plugins release. Squash-merge immediately. | |
| if: >- | |
| ${{ steps.cpr.outputs.pull-request-number != '' && | |
| (steps.cpr.outputs.pull-request-operation == 'created' || | |
| steps.cpr.outputs.pull-request-operation == 'updated') }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR: ${{ steps.cpr.outputs.pull-request-number }} | |
| run: | | |
| gh pr merge "$PR" --squash --delete-branch \ | |
| --subject 'chore(external-plugins): update external plugin pins' |