name: Build and Release
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
# This ensures the workflow only runs on tags matching the pattern vX.Y.Z
jobs:
build:
name: Build
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ['1.24.x']
platform: [linux-amd64, windows-amd64, darwin-amd64, darwin-arm64]
include:
- platform: linux-amd64
os: ubuntu-latest
GOOS: linux
GOARCH: amd64
binary_name: databricks-mcp-server
asset_name: databricks-mcp-server-linux-amd64
- platform: windows-amd64
os: ubuntu-latest
GOOS: windows
GOARCH: amd64
binary_name: databricks-mcp-server.exe
asset_name: databricks-mcp-server-windows-amd64.exe
- platform: darwin-amd64
os: ubuntu-latest
GOOS: darwin
GOARCH: amd64
binary_name: databricks-mcp-server
asset_name: databricks-mcp-server-darwin-amd64
- platform: darwin-arm64
os: ubuntu-latest
GOOS: darwin
GOARCH: arm64
binary_name: databricks-mcp-server
asset_name: databricks-mcp-server-darwin-arm64
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
- name: Get version from tag
id: get_version
run: |
if [[ $GITHUB_REF == refs/tags/v* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
else
# For non-tag builds, try to get the latest tag or use version from version.go if no tags exist
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LATEST_TAG" ]; then
# Extract version from version.go if no tags exist
VERSION=$(grep -oP 'Version = "\K[^"]+' version.go || echo "0.0.0")
VERSION="$VERSION-dev-$(git rev-parse --short HEAD)"
else
VERSION="${LATEST_TAG#v}-dev-$(git rev-parse --short HEAD)"
fi
fi
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Build
env:
GOOS: ${{ matrix.GOOS }}
GOARCH: ${{ matrix.GOARCH }}
run: |
go build -trimpath -ldflags="-s -w -X 'main.Version=${{ env.VERSION }}' -X 'main.BuildDate=$(date -u +%Y-%m-%dT%H:%M:%SZ)' -X 'main.GitCommit=$(git rev-parse --short HEAD)'" -o ${{ matrix.binary_name }}
- name: Install UPX
if: matrix.GOOS != 'darwin'
run: |
sudo apt-get update
sudo apt-get install -y upx-ucl
- name: Compress binary with UPX
if: matrix.GOOS != 'darwin'
run: |
upx --best --lzma ${{ matrix.binary_name }}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.asset_name }}
path: ${{ matrix.binary_name }}
release:
permissions: write-all
name: Create Release
needs: build
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.release_outputs.outputs.upload_url }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate Changelog
id: changelog
run: |
# Get the current tag
CURRENT_TAG=${GITHUB_REF#refs/tags/}
echo "Current tag: $CURRENT_TAG"
# Check if this is the first tag
TAG_COUNT=$(git tag | wc -l)
if [ "$TAG_COUNT" -le 1 ]; then
# This is the first tag or there's only one tag (the current one)
echo "This is the first release. Including all commits."
# Get all commits up to the current tag
CHANGELOG=$(git log --pretty=format:"* %s (%h)" $CURRENT_TAG)
# If the changelog is empty (can happen with the first tag), get all commits
if [ -z "$CHANGELOG" ]; then
echo "Getting all commits for the first release."
CHANGELOG=$(git log --pretty=format:"* %s (%h)")
fi
else
# Try to get the previous tag
PREVIOUS_TAG=$(git describe --tags --abbrev=0 $CURRENT_TAG^ 2>/dev/null || echo "")
if [ -z "$PREVIOUS_TAG" ]; then
# If we can't get the previous tag, get all commits up to the current tag
echo "No previous tag found. Using all commits up to $CURRENT_TAG."
CHANGELOG=$(git log --pretty=format:"* %s (%h)" $CURRENT_TAG)
else
echo "Previous tag: $PREVIOUS_TAG"
# Get commits between the previous tag and the current tag
CHANGELOG=$(git log --pretty=format:"* %s (%h)" $PREVIOUS_TAG..$CURRENT_TAG)
fi
fi
# Save changelog to output
echo "CHANGELOG<<EOF" >> $GITHUB_ENV
echo "$CHANGELOG" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
release_name: Release ${{ github.ref_name }}
body: |
# Release ${{ github.ref_name }} of databricks-mcp-server
## Changelog
${{ env.CHANGELOG }}
draft: false
prerelease: false
# The release ID is needed for the upload-assets job
- name: Set release outputs
id: release_outputs
run: |
echo "release_id=${{ steps.create_release.outputs.id }}" >> $GITHUB_OUTPUT
echo "upload_url=${{ steps.create_release.outputs.upload_url }}" >> $GITHUB_OUTPUT
upload-assets:
name: Upload Release Assets
needs: release
runs-on: ubuntu-latest
strategy:
matrix:
asset:
- name: databricks-mcp-server-linux-amd64
path: artifacts/databricks-mcp-server-linux-amd64/databricks-mcp-server
content_type: application/octet-stream
- name: databricks-mcp-server-windows-amd64.exe
path: artifacts/databricks-mcp-server-windows-amd64.exe/databricks-mcp-server.exe
content_type: application/octet-stream
- name: databricks-mcp-server-darwin-amd64
path: artifacts/databricks-mcp-server-darwin-amd64/databricks-mcp-server
content_type: application/octet-stream
- name: databricks-mcp-server-darwin-arm64
path: artifacts/databricks-mcp-server-darwin-arm64/databricks-mcp-server
content_type: application/octet-stream
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release.outputs.upload_url }}
asset_path: ${{ matrix.asset.path }}
asset_name: ${{ matrix.asset.name }}
asset_content_type: ${{ matrix.asset.content_type }}
publish-npm:
name: Publish NPM Packages
needs: [release, upload-assets]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js
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: Get version from tag
id: get_version
run: |
# Remove 'v' prefix from tag name
VERSION=${GITHUB_REF#refs/tags/v}
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Prepare main npm package
run: |
# Update main package version and dependencies
jq ".version = \"${VERSION}\"" npm/package.json > tmp.json && mv tmp.json npm/package.json
jq ".optionalDependencies |= with_entries(.value = \"${VERSION}\")" npm/package.json > tmp.json && mv tmp.json npm/package.json
# Copy README and LICENSE to main package
cp README.md LICENSE npm/
- name: Publish main package
run: |
cd npm
npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Prepare and publish platform-specific packages
run: |
# Create directories for platform-specific packages
mkdir -p npm/databricks-mcp-server-darwin-amd64/bin
mkdir -p npm/databricks-mcp-server-darwin-arm64/bin
mkdir -p npm/databricks-mcp-server-linux-amd64/bin
mkdir -p npm/databricks-mcp-server-windows-amd64/bin
# Copy binaries to their respective npm package directories
cp artifacts/databricks-mcp-server-darwin-amd64/databricks-mcp-server npm/databricks-mcp-server-darwin-amd64/bin/
cp artifacts/databricks-mcp-server-darwin-arm64/databricks-mcp-server npm/databricks-mcp-server-darwin-arm64/bin/
cp artifacts/databricks-mcp-server-linux-amd64/databricks-mcp-server npm/databricks-mcp-server-linux-amd64/bin/
cp artifacts/databricks-mcp-server-windows-amd64.exe/databricks-mcp-server.exe npm/databricks-mcp-server-windows-amd64/bin/
# Make binaries executable
chmod +x npm/databricks-mcp-server-darwin-amd64/bin/databricks-mcp-server
chmod +x npm/databricks-mcp-server-darwin-arm64/bin/databricks-mcp-server
chmod +x npm/databricks-mcp-server-linux-amd64/bin/databricks-mcp-server
chmod +x npm/databricks-mcp-server-windows-amd64/bin/databricks-mcp-server.exe
# Create package.json and publish for each platform-specific package
for dir in npm/databricks-mcp-server-*; do
if [ -d "$dir" ]; then
pkg_name=$(basename "$dir")
os_name=${pkg_name#databricks-mcp-server-}
# Extract CPU architecture from package name
if [[ "$os_name" == *"arm64"* ]]; then
cpu_arch="arm64"
else
cpu_arch="x64"
fi
# Extract only the OS part and convert windows to win32
if [[ "$os_name" == windows* ]]; then
os_name="win32"
elif [[ "$os_name" == darwin* ]]; then
os_name="darwin"
elif [[ "$os_name" == linux* ]]; then
os_name="linux"
fi
# Create package.json file
echo '{
"name": "'$pkg_name'",
"version": "'$VERSION'",
"description": "Platform-specific binary for databricks-mcp-server",
"os": ["'$os_name'"],
"cpu": ["'$cpu_arch'"]
}' > "$dir/package.json"
# Publish the platform-specific package
cd "$dir"
npm publish --access public
cd ../..
fi
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}