Skip to content

Release

Release #200

Workflow file for this run

name: Release
on:
workflow_run:
workflows: ["Main"]
types: [completed]
branches: [main]
jobs:
release:
# Only run if Main workflow succeeded
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
environment: production
permissions:
contents: write
id-token: write # Required for OIDC trusted publishing
env:
MCP_PUBLISHER_VERSION: v1.7.9
MCP_PUBLISHER_LINUX_AMD64_SHA256: ab128162b0616090b47cf245afe0a23f3ef08936fdce19074f5ba0a4469281ac
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Get root version and release state
id: version
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(jq -r '.version' package.json)
TAG="v$VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "tag_exists=true" >> $GITHUB_OUTPUT
else
echo "tag_exists=false" >> $GITHUB_OUTPUT
fi
if gh release view "$TAG" >/dev/null 2>&1; then
echo "release_exists=true" >> $GITHUB_OUTPUT
else
echo "release_exists=false" >> $GITHUB_OUTPUT
fi
if npm view "githits@$VERSION" version >/dev/null 2>&1; then
echo "npm_published=true" >> $GITHUB_OUTPUT
else
echo "npm_published=false" >> $GITHUB_OUTPUT
fi
if git rev-parse "$TAG" >/dev/null 2>&1 && npm view "githits@$VERSION" version >/dev/null 2>&1 && gh release view "$TAG" >/dev/null 2>&1; then
echo "$TAG, GitHub Release, and githits@$VERSION already exist, skipping root release"
echo "should_release=false" >> $GITHUB_OUTPUT
else
echo "Root release has missing artifacts, continuing"
echo "should_release=true" >> $GITHUB_OUTPUT
fi
- name: Setup Bun
if: steps.version.outputs.should_release == 'true'
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Setup Node.js
if: steps.version.outputs.should_release == 'true'
uses: actions/setup-node@v7
with:
node-version-file: ".node-version"
registry-url: "https://registry.npmjs.org"
# Trusted publishing requires npm 11.5.1+; the npm bundled with the
# pinned .node-version satisfies this. Do not upgrade to npm@latest
# (npm/cli#9722).
- name: Install dependencies
if: steps.version.outputs.should_release == 'true'
run: bun install --frozen-lockfile
- name: Build
if: steps.version.outputs.should_release == 'true'
run: bun run build
# Authentication via npm Trusted Publishing (OIDC)
# - No NPM_TOKEN secret needed
# - Provenance attestation is generated automatically
# - Requires trusted publisher configured on npmjs.com:
# Package Settings > Publishing access > Add trusted publisher
# Repository: GitHits-com/githits-cli, Workflow: release.yml
# See: https://docs.npmjs.com/trusted-publishers
- name: Publish to npm
if: steps.version.outputs.should_release == 'true' && steps.version.outputs.npm_published == 'false'
run: npm publish --access public
- name: Install MCP publisher
if: steps.version.outputs.should_release == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
DOWNLOAD_DIR="$RUNNER_TEMP/mcp-publisher-download"
INSTALL_DIR="$RUNNER_TEMP/mcp-publisher-bin"
mkdir -p "$DOWNLOAD_DIR" "$INSTALL_DIR"
gh release download "$MCP_PUBLISHER_VERSION" \
--repo modelcontextprotocol/registry \
--pattern "mcp-publisher_linux_amd64.tar.gz" \
--dir "$DOWNLOAD_DIR"
echo "${MCP_PUBLISHER_LINUX_AMD64_SHA256} ${DOWNLOAD_DIR}/mcp-publisher_linux_amd64.tar.gz" | sha256sum --check
tar -xzf "${DOWNLOAD_DIR}/mcp-publisher_linux_amd64.tar.gz" -C "$INSTALL_DIR"
chmod +x "$INSTALL_DIR/mcp-publisher"
echo "$INSTALL_DIR" >> "$GITHUB_PATH"
- name: Prepare MCP registry manifest
if: steps.version.outputs.should_release == 'true'
id: mcp_manifest
run: |
set -euo pipefail
VERSION="${{ steps.version.outputs.version }}"
MANIFEST="$RUNNER_TEMP/server.json"
jq --arg version "$VERSION" '
.version = $version
| (.packages[]? | select(.registryType == "npm" and .identifier == "githits") | .version) = $version
' server.json > "$MANIFEST"
echo "path=$MANIFEST" >> "$GITHUB_OUTPUT"
- name: Azure login
if: steps.version.outputs.should_release == 'true'
uses: azure/login@v3
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Authenticate MCP registry
if: steps.version.outputs.should_release == 'true'
env:
MCP_REGISTRY_KEY_VAULT_NAME: ${{ secrets.MCP_REGISTRY_KEY_VAULT_NAME }}
MCP_REGISTRY_SIGNING_KEY_NAME: ${{ secrets.MCP_REGISTRY_SIGNING_KEY_NAME }}
run: |
set -euo pipefail
mcp-publisher login http azure-key-vault \
--domain githits.com \
--vault "$MCP_REGISTRY_KEY_VAULT_NAME" \
--key "$MCP_REGISTRY_SIGNING_KEY_NAME"
- name: Validate MCP registry manifest
if: steps.version.outputs.should_release == 'true'
env:
MCP_SERVER_JSON: ${{ steps.mcp_manifest.outputs.path }}
run: |
set -euo pipefail
jq -e '
.name == "com.githits/githits"
and .version == "${{ steps.version.outputs.version }}"
and any(.remotes[]?; .url == "https://mcp.githits.com")
and any(.packages[]?; .registryType == "npm" and .identifier == "githits" and .version == "${{ steps.version.outputs.version }}")
' "$MCP_SERVER_JSON" >/dev/null
set +e
VALIDATE_OUTPUT="$(mcp-publisher validate "$MCP_SERVER_JSON" 2>&1)"
VALIDATE_STATUS=$?
set -e
if [ "$VALIDATE_STATUS" -eq 0 ]; then
echo "$VALIDATE_OUTPUT"
elif grep -qi "Unknown command: validate" <<<"$VALIDATE_OUTPUT"; then
echo "::warning::mcp-publisher $MCP_PUBLISHER_VERSION does not implement validate; publish will perform registry validation"
else
echo "$VALIDATE_OUTPUT"
exit "$VALIDATE_STATUS"
fi
- name: Publish to MCP registry
if: steps.version.outputs.should_release == 'true'
env:
MCP_SERVER_JSON: ${{ steps.mcp_manifest.outputs.path }}
run: |
set -euo pipefail
PUBLISH_LOG="$RUNNER_TEMP/mcp-publisher-publish.log"
set +e
mcp-publisher publish "$MCP_SERVER_JSON" >"$PUBLISH_LOG" 2>&1
PUBLISH_STATUS=$?
set -e
if [ "$PUBLISH_STATUS" -eq 0 ]; then
cat "$PUBLISH_LOG"
exit 0
fi
if grep -Eiq "already exists|409|conflict|duplicate" "$PUBLISH_LOG"; then
echo "MCP registry version already exists; treating publish as complete."
exit 0
fi
cat "$PUBLISH_LOG"
exit "$PUBLISH_STATUS"
- name: Create GitHub Release
if: steps.version.outputs.should_release == 'true' && steps.version.outputs.release_exists == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="v${{ steps.version.outputs.version }}"
if [ "${{ steps.version.outputs.tag_exists }}" = "true" ]; then
gh release create "$TAG" --verify-tag \
--title "$TAG" \
--generate-notes
else
gh release create "$TAG" \
--title "$TAG" \
--generate-notes
fi