Merge pull request #12 from walter-base/flat-layout-and-central-marketplace

feat: target the flat layout and the central marketplace
This commit is contained in:
Walter Cheng
2026-08-23 20:06:18 -04:00
committed by GitHub
2 changed files with 101 additions and 11 deletions
+14 -4
View File
@@ -9,23 +9,33 @@ on:
type: string type: string
default: skills default: skills
claude_marketplace_file: claude_marketplace_file:
description: Claude marketplace manifest relative to the repository root. description: >-
Claude marketplace manifest relative to the repository root. Empty by
default: a plugin repository no longer carries one, because the
central marketplace is generated from the package registry.
required: false required: false
type: string type: string
default: .claude-plugin/marketplace.json default: ""
claude_plugin_file: claude_plugin_file:
description: Claude plugin manifest relative to the repository root. description: Claude plugin manifest relative to the repository root.
required: false required: false
type: string type: string
default: .claude-plugin/plugin.json default: .claude-plugin/plugin.json
codex_plugin_root: codex_plugin_root:
description: Codex plugin root relative to the repository root. description: >-
Codex plugin root relative to the repository root. Defaults to the
repository itself, matching the release workflow — these two described
the same layout differently, so CI passed while release failed.
required: false required: false
type: string type: string
default: "."
cursor_plugin_root: cursor_plugin_root:
description: Cursor plugin root relative to the repository root. description: >-
Cursor plugin root relative to the repository root. Empty disables
cursor validation.
required: false required: false
type: string type: string
default: ""
permissions: permissions:
contents: read contents: read
@@ -14,25 +14,53 @@ on:
type: string type: string
default: skills default: skills
claude_marketplace_file: claude_marketplace_file:
description: Claude marketplace manifest relative to the repository root. description: >-
Claude marketplace manifest relative to the repository root. Empty by
default: a plugin repository no longer carries one, because the
central marketplace is generated from the package registry.
required: false required: false
type: string type: string
default: .claude-plugin/marketplace.json default: ""
claude_plugin_file: claude_plugin_file:
description: Claude plugin manifest relative to the repository root. description: Claude plugin manifest relative to the repository root.
required: false required: false
type: string type: string
default: .claude-plugin/plugin.json default: .claude-plugin/plugin.json
codex_plugin_root: codex_plugin_root:
description: Codex plugin root relative to the repository root. description: >-
Codex plugin root relative to the repository root. Defaults to the
repository itself: codex's npm plugin source has no path field, so the
package root must be the plugin root.
required: false required: false
type: string type: string
default: plugins/marketplace default: "."
cursor_plugin_root: cursor_plugin_root:
description: Cursor plugin root relative to the repository root. description: >-
Cursor plugin root relative to the repository root. Empty disables
cursor validation. It defaulted to a scaffold path, which meant every
caller that stopped shipping a cursor bundle had to remember to blank
it or CI would demand a directory that never existed.
required: false required: false
type: string type: string
default: plugins/marketplace default: ""
marketplace_url:
description: >-
URL of the central marketplace manifest, printed in the release notes
as the way to install. Empty falls back to the per-release
instructions.
required: false
type: string
default: ""
marketplace_dispatch_url:
description: >-
Gitea workflow-dispatch endpoint for the manifest generator. Called
after publishing so the marketplace reflects a new plugin promptly
rather than at the next scheduled run. Gitea's own registry_package
event cannot be used: it only fires for packages linked to the
repository, and these are published from here.
required: false
type: string
default: ""
release_config_file: release_config_file:
description: Release Please configuration file. description: Release Please configuration file.
required: false required: false
@@ -128,6 +156,11 @@ on:
GITHUB_PAT: GITHUB_PAT:
description: Optional GitHub token for release-please pull requests. description: Optional GitHub token for release-please pull requests.
required: false required: false
MARKETPLACE_DISPATCH_TOKEN:
description: >-
Gitea token permitted to dispatch the manifest generator workflow.
Only needed when marketplace_dispatch_url is set.
required: false
GITEA_TOKEN: GITEA_TOKEN:
description: Gitea token with permission to publish generic packages. description: Gitea token with permission to publish generic packages.
required: false required: false
@@ -479,6 +512,38 @@ jobs:
tag_name: ${{ needs.release-please.outputs.tag_name }} tag_name: ${{ needs.release-please.outputs.tag_name }}
files: dist/* files: dist/*
- name: Refresh the central marketplace
# The manifest is derived from the package registry, so it only needs
# regenerating when the set of plugins changes — a new version of an
# existing plugin leaves it byte-identical, because entries carry no
# version and npm resolves `latest`. This call exists so a *new* plugin
# appears immediately rather than at the next scheduled run.
if: inputs.marketplace_dispatch_url != ''
env:
DISPATCH_URL: ${{ inputs.marketplace_dispatch_url }}
DISPATCH_TOKEN: ${{ secrets.MARKETPLACE_DISPATCH_TOKEN }}
shell: bash
run: |
set -euo pipefail
if [[ -z "${DISPATCH_TOKEN:-}" ]]; then
echo "marketplace_dispatch_url is set but MARKETPLACE_DISPATCH_TOKEN is not; skipping." >&2
exit 0
fi
# Never fail the release over this: the package is already published,
# and the generator's schedule will pick it up regardless. Failing here
# would turn a delayed catalogue into a red release.
status="$(curl --silent --show-error --output /dev/stderr --write-out '%{http_code}' \
--max-time 30 -X POST \
-H "Authorization: token ${DISPATCH_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"ref":"main"}' \
"$DISPATCH_URL" || true)"
if [[ "$status" == "204" || "$status" == "201" || "$status" == "200" ]]; then
echo "Requested marketplace regeneration (HTTP $status)."
else
echo "Could not reach the manifest generator (HTTP $status); the scheduled run will catch up." >&2
fi
- name: Write GitHub installation summary - name: Write GitHub installation summary
env: env:
VERSION: ${{ needs.release-please.outputs.version }} VERSION: ${{ needs.release-please.outputs.version }}
@@ -495,6 +560,7 @@ jobs:
GITEA_INSTALLER_URL: ${{ steps.gitea.outputs.installer_url }} GITEA_INSTALLER_URL: ${{ steps.gitea.outputs.installer_url }}
NPM_PACKAGE: ${{ steps.npm.outputs.npm_package }} NPM_PACKAGE: ${{ steps.npm.outputs.npm_package }}
NPM_REGISTRY_URL: ${{ steps.npm.outputs.npm_registry }} NPM_REGISTRY_URL: ${{ steps.npm.outputs.npm_registry }}
MARKETPLACE_URL: ${{ inputs.marketplace_url }}
run: | run: |
{ {
printf '# Agent plugin %s\n\n' "$VERSION" printf '# Agent plugin %s\n\n' "$VERSION"
@@ -511,7 +577,21 @@ jobs:
printf '%s\n\n' '```' printf '%s\n\n' '```'
fi fi
if [[ -n "$GITEA_INSTALLER_URL" ]]; then if [[ -n "$MARKETPLACE_URL" ]]; then
# One marketplace lists every plugin, so these instructions do
# not change per release and never name this version: the
# manifest points at the package and npm resolves the newest.
printf '## Claude Code\n\n'
printf '%s\n' '```bash'
printf 'claude plugin marketplace add %s\n' "$MARKETPLACE_URL"
printf 'claude plugin install %s@%s\n' "$CLAUDE_PLUGIN_NAME" "$CLAUDE_MARKETPLACE_NAME"
printf '%s\n\n' '```'
printf 'Later releases arrive with:\n\n'
printf '%s\n' '```bash'
printf 'claude plugin marketplace update %s\n' "$CLAUDE_MARKETPLACE_NAME"
printf '%s\n\n' '```'
elif [[ -n "$GITEA_INSTALLER_URL" ]]; then
printf '## Claude Code\n\n' printf '## Claude Code\n\n'
printf '%s\n' '```bash' printf '%s\n' '```bash'
printf 'curl --fail --location --retry 3 "%s" | bash -s -- claude\n' "$GITEA_INSTALLER_URL" printf 'curl --fail --location --retry 3 "%s" | bash -s -- claude\n' "$GITEA_INSTALLER_URL"