name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 1.0.0)'
required: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
permissions:
contents: write
packages: write
jobs:
# ===========================================
# Build and Test
# ===========================================
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1
with:
java-version: '25'
distribution: 'mandrel'
cache: 'maven'
- name: Run tests
run: ./mvnw verify
# ===========================================
# Build Native Binaries
# ===========================================
build-native:
name: Build Native (${{ matrix.name }})
needs: test
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: macos-14
name: macos-arm64
artifact: mcp-sessionize-macos-arm64
- os: macos-15
name: macos-x64
artifact: mcp-sessionize-macos-x64
- os: ubuntu-latest
name: linux-x64
artifact: mcp-sessionize-linux-x64
- os: windows-latest
name: windows-x64
artifact: mcp-sessionize-windows-x64.exe
steps:
- uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1
with:
java-version: '25'
distribution: 'mandrel'
cache: 'maven'
- name: Build native image
run: ./mvnw package -Pnative -DskipTests
- name: Rename binary (Unix)
if: runner.os != 'Windows'
run: mv target/*-runner target/${{ matrix.artifact }}
- name: Rename binary (Windows)
if: runner.os == 'Windows'
run: move target\*-runner.exe target\${{ matrix.artifact }}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: target/${{ matrix.artifact }}
# ===========================================
# Create GitHub Release
# ===========================================
release:
name: Create Release
needs: build-native
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Get version from tag
id: version
run: |
VERSION=${GITHUB_REF_NAME#v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
- uses: graalvm/setup-graalvm@v1
with:
java-version: '25'
distribution: 'mandrel'
cache: 'maven'
- name: Set version and build JAR
run: |
./mvnw versions:set -DnewVersion=${{ steps.version.outputs.version }} -DgenerateBackupPoms=false
./mvnw package -DskipTests -Dquarkus.package.jar.type=uber-jar
mv target/*-runner.jar target/mcp-sessionize.jar
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release files
run: |
mkdir -p release
cp target/mcp-sessionize.jar release/
cp artifacts/mcp-sessionize-macos-arm64/mcp-sessionize-macos-arm64 release/
cp artifacts/mcp-sessionize-macos-x64/mcp-sessionize-macos-x64 release/
cp artifacts/mcp-sessionize-linux-x64/mcp-sessionize-linux-x64 release/
cp artifacts/mcp-sessionize-windows-x64.exe/mcp-sessionize-windows-x64.exe release/
chmod +x release/mcp-sessionize-*
ls -la release/
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
release/mcp-sessionize.jar
release/mcp-sessionize-macos-arm64
release/mcp-sessionize-macos-x64
release/mcp-sessionize-linux-x64
release/mcp-sessionize-windows-x64.exe
generate_release_notes: true
body: |
## Installation
### Via npm (recommended) - No Java required!
```bash
npx mcp-sessionize@${{ steps.version.outputs.version }}
```
### Via Docker
```bash
docker run -i --rm ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }}
```
### Native binaries (no Java required)
- **macOS ARM64**: `mcp-sessionize-macos-arm64`
- **macOS x64**: `mcp-sessionize-macos-x64`
- **Linux x64**: `mcp-sessionize-linux-x64`
- **Windows x64**: `mcp-sessionize-windows-x64.exe`
### Via JAR (requires Java 25+)
```bash
java -jar mcp-sessionize.jar
```
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ===========================================
# Build and Push Docker Image
# ===========================================
docker:
name: Publish Docker Image
needs: release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
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}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ===========================================
# Publish to npm (5 packages: 1 main + 4 platform-specific)
# ===========================================
npm:
name: Publish to npm
needs: [release, build-native]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create platform packages and copy binaries
run: |
VERSION=${{ needs.release.outputs.version }}
# Platform configurations: npm_name, artifact_name, os, cpu
declare -a PLATFORMS=(
"mcp-sessionize-darwin-arm64:mcp-sessionize-macos-arm64:darwin:arm64"
"mcp-sessionize-darwin-x64:mcp-sessionize-macos-x64:darwin:x64"
"mcp-sessionize-linux-x64:mcp-sessionize-linux-x64:linux:x64"
"mcp-sessionize-windows-x64:mcp-sessionize-windows-x64.exe:win32:x64"
)
for PLATFORM in "${PLATFORMS[@]}"; do
IFS=':' read -r NPM_NAME ARTIFACT_NAME OS CPU <<< "$PLATFORM"
echo "Creating package: $NPM_NAME"
mkdir -p npm/$NPM_NAME/bin
# Copy binary
if [[ "$OS" == "win32" ]]; then
cp artifacts/$ARTIFACT_NAME/$ARTIFACT_NAME npm/$NPM_NAME/bin/$NPM_NAME.exe
else
cp artifacts/$ARTIFACT_NAME/$ARTIFACT_NAME npm/$NPM_NAME/bin/$NPM_NAME
chmod +x npm/$NPM_NAME/bin/$NPM_NAME
fi
# Generate package.json for platform package
cat > npm/$NPM_NAME/package.json << EOF
{
"name": "$NPM_NAME",
"version": "$VERSION",
"description": "MCP Server for Sessionize Event Data - $OS $CPU binary",
"repository": {
"type": "git",
"url": "https://github.com/jeanlopezxyz/mcp-sessionize"
},
"os": ["$OS"],
"cpu": ["$CPU"],
"author": "Jean Lopez",
"license": "Apache-2.0"
}
EOF
done
- name: Create main package
run: |
VERSION=${{ needs.release.outputs.version }}
# Generate package.json for main package with optionalDependencies
cat > npm/mcp-sessionize/package.json << EOF
{
"name": "mcp-sessionize",
"version": "$VERSION",
"description": "MCP Server for Sessionize Event Data - Access speakers, sessions, and schedules",
"main": "./bin/index.js",
"bin": {
"mcp-sessionize": "bin/index.js"
},
"optionalDependencies": {
"mcp-sessionize-darwin-arm64": "$VERSION",
"mcp-sessionize-darwin-x64": "$VERSION",
"mcp-sessionize-linux-x64": "$VERSION",
"mcp-sessionize-windows-x64": "$VERSION"
},
"keywords": [
"mcp",
"sessionize",
"conference",
"speakers",
"sessions",
"schedule",
"claude",
"ai"
],
"repository": {
"type": "git",
"url": "https://github.com/jeanlopezxyz/mcp-sessionize"
},
"author": "Jean Lopez",
"license": "Apache-2.0",
"homepage": "https://github.com/jeanlopezxyz/mcp-sessionize#readme"
}
EOF
# Copy LICENSE to main package
cp LICENSE npm/mcp-sessionize/ || echo "No LICENSE file found"
- name: Publish platform packages
run: |
for PKG in mcp-sessionize-darwin-arm64 mcp-sessionize-darwin-x64 mcp-sessionize-linux-x64 mcp-sessionize-windows-x64; do
echo "Publishing $PKG..."
cd npm/$PKG
npm publish --access public
cd ../..
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish main package
run: |
cd npm/mcp-sessionize
npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}