name: Publish # On every GitHub Release this: # 1. builds a MULTI-ARCH (linux/amd64 + linux/arm64) container image and pushes # it to GHCR (always) and Docker Hub (only when the DOCKERHUB_USERNAME / # DOCKERHUB_TOKEN repo secrets are set), # 2. publishes the server to the official MCP Registry via GitHub OIDC (no # secrets needed). # The image version/tags come from tractorbeeam365/__init__.py, so a manual # workflow_dispatch re-run produces the same tags as the release. # # arm64 is built under QEMU emulation, so a release build is slower than the # amd64-only CI build. All dependencies ship musllinux aarch64 wheels, so no # in-image compilation happens. Buildx layer cache (type=gha) is shared between # the GHCR and Docker Hub steps, so the emulated build cost is paid once. on: release: types: [published] workflow_dispatch: env: GHCR_IMAGE: ghcr.io/ringosystems/tractorbeeam-mcp DOCKERHUB_IMAGE: docker.io/ringosystems/tractorbeeam365-mcp DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} jobs: build-push: runs-on: ubuntu-latest permissions: contents: read packages: write outputs: version: ${{ steps.ver.outputs.version }} steps: - uses: actions/checkout@v4 - name: Resolve version from package id: ver run: | V=$(grep -oP '__version__\s*=\s*"\K[^"]+' tractorbeeam365/__init__.py) echo "version=$V" >> "$GITHUB_OUTPUT" echo "Building version $V" - name: Set up QEMU (enables arm64 emulation) uses: docker/setup-qemu-action@v3 - uses: docker/setup-buildx-action@v3 - name: Log in to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push to GHCR uses: docker/build-push-action@v6 with: context: . push: true provenance: false platforms: linux/amd64,linux/arm64 cache-from: type=gha cache-to: type=gha,mode=max tags: | ${{ env.GHCR_IMAGE }}:${{ steps.ver.outputs.version }} ${{ env.GHCR_IMAGE }}:latest labels: | org.opencontainers.image.version=${{ steps.ver.outputs.version }} org.opencontainers.image.revision=${{ github.sha }} # Docker Hub is best-effort: a bad/expired token must not block GHCR or the # MCP Registry publish below. - name: Log in to Docker Hub id: dh_login if: ${{ env.DOCKERHUB_USERNAME != '' }} continue-on-error: true uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push to Docker Hub if: ${{ env.DOCKERHUB_USERNAME != '' && steps.dh_login.outcome == 'success' }} continue-on-error: true uses: docker/build-push-action@v6 with: context: . push: true provenance: false platforms: linux/amd64,linux/arm64 cache-from: type=gha cache-to: type=gha,mode=max tags: | ${{ env.DOCKERHUB_IMAGE }}:${{ steps.ver.outputs.version }} ${{ env.DOCKERHUB_IMAGE }}:latest labels: | org.opencontainers.image.version=${{ steps.ver.outputs.version }} org.opencontainers.image.revision=${{ github.sha }} # NOTE: the Docker Hub repository description/overview is NOT synced here. # That API only accepts the account password, not a Personal Access Token, # so it cannot be automated for a token-only (or SSO) account. Set the # short description and overview once in the Docker Hub UI; the image itself # already carries org.opencontainers.image.* metadata labels. publish-mcp-registry: needs: build-push runs-on: ubuntu-latest permissions: id-token: write # required for MCP Registry OIDC auth contents: read steps: - uses: actions/checkout@v4 - name: Sync server.json version + image tag to the release env: VERSION: ${{ needs.build-push.outputs.version }} run: | jq --arg v "$VERSION" \ '.version = $v | .packages[0].identifier = "ghcr.io/ringosystems/tractorbeeam-mcp:" + $v' \ server.json > server.tmp && mv server.tmp server.json echo "--- server.json ---"; cat server.json - name: Install mcp-publisher run: | curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher - name: Authenticate to the MCP Registry (GitHub OIDC) run: ./mcp-publisher login github-oidc - name: Publish to the MCP Registry run: ./mcp-publisher publish