name: Container Image Releaser
on:
push:
tags:
- "*"
branches:
- "main"
concurrency: ci-container-release
permissions:
contents: read
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
if: "!contains(github.event.commits[0].message, '[noci]')"
timeout-minutes: 30
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744
with:
submodules: true
fetch-depth: 0
- name: Registry Login
uses: docker/login-action@dd4fa0671be5250ee6f50aedf4cb05514abda2c7
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Setup QEMU
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55
- name: Build and Push Container Image
run: |
# Get the tag if this was a tag push event
if [[ "${{ github.ref_type }}" == "tag" ]]; then
TAG=${{ github.ref_name }}
# Validate tag format (must be vX.Y.Z)
if [[ $TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
# Build and push with both version tag and latest
docker buildx build --push --platform linux/amd64,linux/arm64 \
-t $REGISTRY/$IMAGE_NAME:$TAG \
-t $REGISTRY/$IMAGE_NAME:latest \
.
else
echo "Invalid tag format. Must be in format vX.Y.Z (e.g. v1.2.3)"
exit 1
fi
else
# For non-tag pushes, just use latest tag
docker buildx build --push --platform linux/amd64,linux/arm64 \
-t $REGISTRY/$IMAGE_NAME:latest \
.
fi
publish-mcp-registry:
if: startsWith(github.ref, 'refs/tags/') # only run this when new tag is publish
needs: build
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC authentication
contents: read
defaults:
run:
working-directory: ./.mcp-publisher
steps:
- name: Checkout code
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6
- name: Ensure jq is installed
run: sudo apt-get update && sudo apt-get install -y jq
- name: Get version from tag
# Strip 'v' prefix from tag (e.g., v1.0.0 -> 1.0.0) as
# - we want clean version (x.y.z) without v prefix, since its already added by registry UI
# - in case of docker image, we hardcode in server.json docker image identifier
run: echo "VET_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
- name: fill version in server.json
run: sed -i "s/VERSION_FROM_ENV/$VET_VERSION/g" server.json
# publish mcp server
- 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 MCP Registry
run: ./mcp-publisher login github-oidc
- name: Publish server to MCP Registry
run: ./mcp-publisher publish
verify-publish-mcp-registry:
needs: publish-mcp-registry
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Ensure jq is installed
run: sudo apt-get update && sudo apt-get install -y jq
- name: Get version from tag
# Strip 'v' prefix from tag (e.g., v1.0.0 -> 1.0.0) as
# - we want clean version (x.y.z) without v prefix, since its already added by registry UI
# - in case of docker image, we hardcode in server.json docker image identifier
run: echo "VET_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
- name: Query MCP Registry and verify server is published
env:
SERVER_NAME: "io.github.safedep/vet-mcp"
REGISTRY_URL: "https://registry.modelcontextprotocol.io/v0.1/servers"
run: |
export EXPECTED_VERSION=$VET_VERSION
echo "Checking MCP Registry for $SERVER_NAME"
# Query registry
url="${REGISTRY_URL}?search=${SERVER_NAME}"
echo "Requesting: $url"
http_status=$(curl -s -o response.json -w "%{http_code}" "$url")
if [ "$http_status" -ne 200 ]; then
echo "Registry query failed with HTTP status $http_status"
cat response.json || true
exit 1
fi
# Pretty print the response for debugging
echo "Registry response (truncated):"
jq 'if .servers then {servers: (.servers | length)} else . end' response.json
# Check for name and version match
jq -e --arg name "$SERVER_NAME" --arg ver "$EXPECTED_VERSION" 'any(.servers[]; .server.name == $name and .server.version == $ver)' response.json >/dev/null || {
echo "ERROR: Server $SERVER_NAME with version $EXPECTED_VERSION not found"
echo "Full response:"
cat response.json
exit 1
}
echo "Found server $SERVER_NAME with version $EXPECTED_VERSION"