Release #50
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| bump: | |
| description: 'Version bump type' | |
| required: true | |
| type: choice | |
| default: patch | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| custom_version: | |
| description: 'Custom version (overrides bump, e.g. 2.0.0-beta.1)' | |
| required: false | |
| type: string | |
| permissions: | |
| contents: write | |
| id-token: write | |
| packages: write | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| # ────────────────────────────────────────────── | |
| # 1. Bump versions, validate, tag & release | |
| # ────────────────────────────────────────────── | |
| release: | |
| name: Release | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| outputs: | |
| version: ${{ steps.ver.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Configure git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| - name: Determine version | |
| id: ver | |
| run: | | |
| CURRENT=$(node -p "require('./package.json').version") | |
| if [ -n "${{ inputs.custom_version }}" ]; then | |
| NEW="${{ inputs.custom_version }}" | |
| NEW="${NEW#v}" # strip accidental leading v | |
| else | |
| IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" | |
| case "${{ inputs.bump }}" in | |
| major) NEW="$((MAJOR + 1)).0.0" ;; | |
| minor) NEW="$MAJOR.$((MINOR + 1)).0" ;; | |
| patch) NEW="$MAJOR.$MINOR.$((PATCH + 1))" ;; | |
| esac | |
| fi | |
| echo "version=$NEW" >> "$GITHUB_OUTPUT" | |
| echo "### Version: $CURRENT → $NEW" >> "$GITHUB_STEP_SUMMARY" | |
| - name: Bump package.json and server.json | |
| env: | |
| VERSION: ${{ steps.ver.outputs.version }} | |
| run: | | |
| npm version "$VERSION" --no-git-tag-version --allow-same-version | |
| node --input-type=module <<'NODE' | |
| import fs from 'node:fs'; | |
| const path = 'server.json'; | |
| const data = JSON.parse(fs.readFileSync(path, 'utf8')); | |
| data.version = process.env.VERSION; | |
| if (Array.isArray(data.packages)) { | |
| for (const pkg of data.packages) { | |
| if (pkg && typeof pkg === 'object') { | |
| pkg.version = process.env.VERSION; | |
| } | |
| } | |
| } | |
| fs.writeFileSync(path, `${JSON.stringify(data, null, 2)}\n`); | |
| NODE | |
| npm install --package-lock-only --ignore-scripts | |
| - name: Install & validate | |
| run: | | |
| npm ci | |
| npm run lint | |
| npm run type-check | |
| npm run test | |
| npm run build | |
| - name: Commit, tag & push | |
| env: | |
| VERSION: ${{ steps.ver.outputs.version }} | |
| run: | | |
| git add package.json package-lock.json server.json | |
| git diff --cached --quiet || git commit -m "release: v$VERSION" | |
| git tag -l "v$VERSION" | grep -q "v$VERSION" || git tag -a "v$VERSION" -m "v$VERSION" | |
| git push origin master | |
| if git ls-remote --exit-code origin "refs/tags/v$VERSION" &>/dev/null; then | |
| echo "::notice::Tag v$VERSION already on remote — skipped" | |
| else | |
| git push origin "refs/tags/v$VERSION" | |
| fi | |
| - name: Create GitHub release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VERSION: ${{ steps.ver.outputs.version }} | |
| run: | | |
| if gh release view "v$VERSION" &>/dev/null; then | |
| echo "::notice::Release v$VERSION already exists — skipped" | |
| else | |
| gh release create "v$VERSION" --title "v$VERSION" --generate-notes | |
| fi | |
| # ────────────────────────────────────────────── | |
| # 2. Publish to npm (runs in parallel with Docker) | |
| # ────────────────────────────────────────────── | |
| publish-npm: | |
| name: npm | |
| needs: release | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| env: | |
| VERSION: ${{ needs.release.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: v${{ needs.release.outputs.version }} | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Install & build | |
| run: npm ci | |
| # Trusted Publishing: No NODE_AUTH_TOKEN needed — OIDC handles auth | |
| - name: Publish | |
| run: | | |
| npm publish --access public --provenance --ignore-scripts || { | |
| if npm view "@j0hanz/code-lens-mcp@$VERSION" version 2>/dev/null; then | |
| echo "::notice::v$VERSION already on npm — skipped" | |
| else | |
| exit 1 | |
| fi | |
| } | |
| - name: Summary | |
| run: | | |
| cat >> "$GITHUB_STEP_SUMMARY" <<EOF | |
| ## 📦 Published to npm | |
| | | | | |
| |---|---| | |
| | **Package** | [\`@j0hanz/code-lens-mcp@$VERSION\`](https://www.npmjs.com/package/@j0hanz/code-lens-mcp) | | |
| | **Auth** | Trusted Publishing (OIDC) | | |
| | **Provenance** | ✅ | | |
| EOF | |
| # ────────────────────────────────────────────── | |
| # 3. Publish to MCP Registry (after npm, needs package available) | |
| # ────────────────────────────────────────────── | |
| publish-mcp: | |
| name: MCP Registry | |
| needs: [release, publish-npm] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| env: | |
| VERSION: ${{ needs.release.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: v${{ needs.release.outputs.version }} | |
| - name: Publish | |
| run: | | |
| OS=$(uname -s | tr '[:upper:]' '[:lower:]') | |
| ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') | |
| curl -fsSL "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_${OS}_${ARCH}.tar.gz" \ | |
| | tar xz mcp-publisher | |
| chmod +x mcp-publisher | |
| ./mcp-publisher login github-oidc | |
| ./mcp-publisher publish | |
| - name: Summary | |
| run: | | |
| cat >> "$GITHUB_STEP_SUMMARY" <<EOF | |
| ## 📡 Published to MCP Registry | |
| | | | | |
| |---|---| | |
| | **Server** | \`io.github.j0hanz/code-lens@$VERSION\` | | |
| | **Registry** | [registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io) | | |
| EOF | |
| # ────────────────────────────────────────────── | |
| # 4. Build & push Docker image (runs in parallel with npm) | |
| # ────────────────────────────────────────────── | |
| publish-docker: | |
| name: Docker | |
| needs: release | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: v${{ needs.release.outputs.version }} | |
| - uses: docker/setup-qemu-action@v3 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=semver,pattern={{version}},value=v${{ needs.release.outputs.version }} | |
| type=semver,pattern={{major}}.{{minor}},value=v${{ needs.release.outputs.version }} | |
| type=semver,pattern={{major}},value=v${{ needs.release.outputs.version }} | |
| type=raw,value=latest | |
| - name: Build & push | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| push: true | |
| platforms: linux/amd64,linux/arm64 | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Summary | |
| env: | |
| VERSION: ${{ needs.release.outputs.version }} | |
| run: | | |
| cat >> "$GITHUB_STEP_SUMMARY" <<EOF | |
| ## 🐳 Docker Image Published | |
| | | | | |
| |---|---| | |
| | **Image** | \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$VERSION\` | | |
| | **Platforms** | linux/amd64, linux/arm64 | | |
| EOF |