diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index dfb35bd..ab7d23b 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -31,7 +31,8 @@ jobs: run: | mkdir -p _site cp -r schema _site/schema - cp server.json _site/server.json + # the image tag follows "version", which release-please bumps + jq '.packages[0].identifier = "ghcr.io/virtbase/proxbase:" + .version' server.json > _site/server.json echo proxbase.virtbase.com > _site/CNAME printf 'Proxbase\n' > _site/index.html - uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f276330..fbe667b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,3 +88,47 @@ jobs: major="${RELEASE_TAG%%.*}" git tag -f "$major" "$RELEASE_TAG^{commit}" git push -f origin "refs/tags/$major" + + # Publishes server.json for the released image to the MCP registry + # (registry.modelcontextprotocol.io), authenticated by the workflow's OIDC token. + mcp-registry: + needs: [release-please, goreleaser] + if: ${{ !cancelled() && needs.goreleaser.result == 'success' }} + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + env: + RELEASE_TAG: ${{ inputs.tag || needs.release-please.outputs.tag }} + PUBLISHER_VERSION: v1.8.1 + PUBLISHER_SHA256: a06c9096dcb9727c13555b6be26c7effa707b01f06a4c561ba7a3635443cf2cc # mcp-publisher_linux_amd64.tar.gz + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ env.RELEASE_TAG }} + persist-credentials: false + - name: Install mcp-publisher + run: | + curl -fsSLo mcp-publisher.tar.gz "https://github.com/modelcontextprotocol/registry/releases/download/$PUBLISHER_VERSION/mcp-publisher_linux_amd64.tar.gz" + echo "$PUBLISHER_SHA256 mcp-publisher.tar.gz" | sha256sum -c + tar -xzf mcp-publisher.tar.gz mcp-publisher + - name: Set version and image tag + run: | + version="${RELEASE_TAG#v}" + jq --arg v "$version" '.version = $v | .packages[0].identifier = "ghcr.io/virtbase/proxbase:" + $v' server.json > server.tmp + mv server.tmp server.json + cat server.json + - name: Wait for the image + run: | + # The registry checks the image's io.modelcontextprotocol.server.name label. + image="ghcr.io/virtbase/proxbase:${RELEASE_TAG#v}" + for _ in $(seq 30); do + docker buildx imagetools inspect "$image" --format '{{json .Image.Config.Labels}}' 2>/dev/null | + jq -e '."io.modelcontextprotocol.server.name" == "io.github.virtbase/proxbase"' >/dev/null && exit 0 + sleep 10 + done + echo "::error::$image is not pullable or lacks the MCP label" + exit 1 + - run: ./mcp-publisher validate + - run: ./mcp-publisher login github-oidc + - run: ./mcp-publisher publish diff --git a/docs/mcp.md b/docs/mcp.md index 6997b5d..9e333ab 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -121,10 +121,11 @@ conversation accordingly. Progress and errors are logged to stderr. [MCP registry](https://registry.modelcontextprotocol.io) as the container image (`io.github.virtbase/proxbase`); the image carries the matching `io.modelcontextprotocol.server.name` label and Pages publishes the file at -`https://proxbase.virtbase.com/server.json`. Publishing is manual after a release: +`https://proxbase.virtbase.com/server.json`. The `Release` workflow publishes every +release with `mcp-publisher` and the workflow's OIDC token +([releasing.md](releasing.md)). By hand, after setting `version` and the image tag in `server.json` to the release: ```bash -# set "version" and the image tag in server.json to the release, then: mcp-publisher login github # as a member of the virtbase organization mcp-publisher publish ``` diff --git a/docs/releasing.md b/docs/releasing.md index 8de89cb..4143530 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -11,10 +11,20 @@ Releases are automatic; nobody tags by hand. release. The same `Release` workflow then runs GoReleaser, which uploads archives, deb/rpm/apk packages, SBOMs, `checksums.txt` with its cosign bundle, pushes the amd64 image to GHCR (signed), updates the Homebrew tap and attests build - provenance. Afterwards the major tag (`v0`) is moved to the release for - `uses: virtbase/proxbase@v0`. -4. Optional, manual: update `version` and the image tag in `server.json` and publish - it to the MCP registry (see [mcp.md](mcp.md#mcp-registry)). + provenance. Afterwards the workflow + - moves the major tag (`v0`) to the release for `uses: virtbase/proxbase@v0`, and + - publishes `server.json` with the release's version and image tag to the + [MCP registry](mcp.md#mcp-registry) (OIDC login, after the labelled image is + pullable). release-please keeps `version` in `server.json` current. +4. Manual, optional: list the release in the GitHub Marketplace. GitHub offers no + API for this: open the release, **Edit**, tick *Publish this Action to the GitHub + Marketplace*, **Update release** (two-factor authentication required). The first + time, an organization owner accepts the Marketplace Developer Agreement there. + Users of `@v0` get new releases through the tag either way; the tick only updates + the version shown on the Marketplace page. + +To re-run the publishing for an existing release, run the `Release` workflow manually +with its tag. Local dry run (no signing, no publishing): diff --git a/release-please-config.json b/release-please-config.json index fe70e96..6d88182 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -9,6 +9,9 @@ "bump-patch-for-minor-pre-major": false, "include-component-in-tag": false, "include-v-in-tag": true, + "extra-files": [ + { "type": "json", "path": "server.json", "jsonpath": "$.version" } + ], "changelog-sections": [ { "type": "feat", "section": "Features" }, { "type": "fix", "section": "Bug Fixes" },