name: Build
on:
workflow_dispatch:
workflow_call:
push:
branches: [ main ]
pull_request:
jobs:
test:
name: โ
Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: rustup update
- run: cargo install cargo-deny
- run: cargo fmt -- --check
- run: cargo clippy --all --all-targets --all-features
- run: cargo deny check
- run: cargo build --release
build-binaries:
name: ๐ฆ๏ธ Build binaries for ${{ matrix.os }} (${{ matrix.target }})
strategy:
fail-fast: false
matrix:
include:
- os: linux
target: x86_64-unknown-linux-gnu
runner: ubuntu-latest
- os: linux
target: aarch64-unknown-linux-gnu
runner: ubuntu-24.04-arm64
- os: macos
target: x86_64-apple-darwin
runner: macos-latest
- os: macos
target: aarch64-apple-darwin
runner: macos-latest
- os: windows
target: x86_64-pc-windows-msvc
runner: windows-latest
- os: windows
target: aarch64-pc-windows-msvc
runner: windows-latest
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- name: Add cross-compilation target
run: rustup update && rustup target add ${{ matrix.target }}
- name: Install Linux dependencies
if: matrix.os == 'linux'
run: sudo apt update && sudo apt install -y pkg-config libssl-dev build-essential perl make
- name: Install macOS dependencies
if: matrix.os == 'macos'
run: brew install protobuf
- uses: Swatinem/rust-cache@v2
- name: Build binary
run: cargo build --release --target ${{ matrix.target }}
# env:
# CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: sparql-mcp_${{ matrix.target }}
path: target/${{ matrix.target }}/release/sparql-mcp${{ matrix.os == 'windows' && '.exe' || '' }}
- if: startsWith(github.ref, 'refs/tags/')
name: Prepare for release
run: |
mv target/${{ matrix.target }}/release/sparql-mcp${{ matrix.os == 'windows' && '.exe' || '' }} sparql-mcp_${{ matrix.target }}${{ matrix.os == 'windows' && '.exe' || '' }}
- uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
sparql-mcp_${{ matrix.target }}${{ matrix.os == 'windows' && '.exe' || '' }}
generate-changelog:
name: ๐๏ธ Generate changelog for the GitHub release
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
outputs:
release_body: ${{ steps.git-cliff.outputs.content }}
steps:
- name: Checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Generate a changelog
uses: orhun/git-cliff-action@v4
id: git-cliff
with:
config: cliff.toml
args: -vv --latest --strip header
env:
OUTPUT: CHANGES.md
- name: Release
uses: softprops/action-gh-release@v2
with:
body_path: CHANGES.md
docker:
name: ๐ณ Build Docker ${{ matrix.platform }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
outputs:
image-digest: ${{ steps.build.outputs.digest }}
image-metadata: ${{ steps.meta.outputs.json }}
steps:
- uses: actions/checkout@v5
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/sib-swiss/sparql-mcp
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
id: build
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64
# platforms: linux/amd64, linux/arm64
# platforms: ${{ matrix.platform }}
# push: true
push: false
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# outputs: type=image,name=ghcr.io/sib-swiss/sparql-mcp,push-by-digest=true,name-canonical=true,push=true
# Inspired by pydantic CI: https://github.com/pydantic/pydantic-core/blob/main/.github/workflows/ci.yml
build_wheels:
name: ๐ Wheels for ${{ matrix.os }} (${{ matrix.target }} - ${{ matrix.interpreter || 'all' }}${{ matrix.os == 'linux' && format(' - {0}', matrix.manylinux == 'auto' && 'manylinux' || matrix.manylinux) || '' }})
strategy:
fail-fast: false
matrix:
os: [linux, macos, windows]
target: [x86_64, aarch64]
manylinux: [auto]
# interpreter: ["3.8 3.9 3.10 3.11 3.12 3.13"]
include:
# Using pypy when possible for performance, manylinux for various platforms, plus x86_64 pypy
- os: linux
manylinux: auto
target: i686
- os: linux
manylinux: auto
target: aarch64 # -bit ARM
# - os: linux
# manylinux: auto
# target: armv7 # 32-bit ARM
# interpreter: 3.8 3.9 3.10 3.11 3.12 3.13
# - os: linux
# manylinux: auto
# target: ppc64le
# interpreter: 3.9 3.10 3.11 3.12 3.13
# - os: linux
# manylinux: auto
# target: s390x
# interpreter: 3.9 3.10 3.11 3.12 3.13
- os: linux
manylinux: auto
target: x86_64
# musllinux
- os: linux
manylinux: musllinux_1_1
target: x86_64
- os: linux
manylinux: musllinux_1_1
target: aarch64
# MacOS
- os: macos
target: x86_64
- os: macos
target: aarch64
# Windows
# x86_64 pypy builds are not PGO optimized, i686 not supported by pypy, aarch64 only 3.11 and up, also not PGO optimized
# x86_64 pypy3.9 pypy3.10 failing due to ring
- os: windows
target: x86_64
interpreter: 3.9 3.10 3.11 3.12 3.13
- os: windows
target: i686
python-architecture: x86
interpreter: 3.9 3.10 3.11 3.12 3.13
- os: windows
target: aarch64
interpreter: 3.11 3.12 3.13
runs-on: ${{ (matrix.os == 'linux' && 'ubuntu') || matrix.os }}-latest
steps:
- uses: actions/checkout@v5
- uses: docker/setup-qemu-action@v3
if: matrix.os == 'linux' && matrix.target == 'aarch64'
with:
platforms: linux/${{ matrix.target }}
- if: matrix.os == 'linux'
run: sudo apt update && sudo apt install -y pkg-config libssl-dev build-essential perl make
- uses: actions/setup-python@v5
with:
python-version: '3.13'
architecture: ${{ matrix.python-architecture || 'x64' }}
- run: pip install -U twine typing_extensions 'ruff==0.5.0'
- name: Build wheels
uses: PyO3/maturin-action@v1
# env: # NOTE: ring linux aarch64 error: https://github.com/briansmith/ring/issues/1728
# CFLAGS_aarch64_unknown_linux_gnu: -D__ARM_ARCH=8
env:
# Set OpenSSL environment variables for Linux builds
OPENSSL_DIR: ${{ matrix.os == 'linux' && '/usr' || '' }}
OPENSSL_LIB_DIR: ${{ matrix.os == 'linux' && '/usr/lib/x86_64-linux-gnu' || '' }}
OPENSSL_INCLUDE_DIR: ${{ matrix.os == 'linux' && '/usr/include/openssl' || '' }}
# NOTE: ring linux aarch64 error: https://github.com/briansmith/ring/issues/1728
# CFLAGS_aarch64_unknown_linux_gnu: -D__ARM_ARCH=8
with:
target: ${{ matrix.target }}
manylinux: ${{ matrix.manylinux }}
args: --release --out dist --interpreter ${{ matrix.interpreter || '3.9 3.10 3.11 3.12 3.13 pypy3.9 pypy3.10 pypy3.11' }}
rust-toolchain: stable
docker-options: -e CI
- run: ${{ (matrix.os == 'windows' && 'dir') || 'ls -lh' }} dist/
- run: twine check --strict dist/*
- uses: actions/upload-artifact@v4
with:
name: sparql_mcp_wheel_${{ matrix.os }}_${{ matrix.target }}_${{ matrix.interpreter || 'all' }}_${{ matrix.manylinux }}
path: dist
# - name: Publish to PyPI
# if: startsWith(github.ref, 'refs/tags/')
# run: twine upload dist/*
# env:
# TWINE_USERNAME: __token__
# TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}