Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ci: select downloadable Bloomberg C++ SDK #640

ci: select downloadable Bloomberg C++ SDK

ci: select downloadable Bloomberg C++ SDK #640

Workflow file for this run

name: CI
on:
pull_request:
push:
branches: [main, feat/**, fix/**]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
packages: read
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
# ════════════════════════════════════════════════════════════════════════════
# Detect latest Bloomberg SDK version (runs first, others depend on it)
# ════════════════════════════════════════════════════════════════════════════
sdk-version:
name: Detect SDK Version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.detect.outputs.version }}
steps:
- name: Detect latest downloadable Bloomberg C++ SDK version
id: detect
run: |
INDEX_URL="https://blpapi.bloomberg.com/repository/releases/python/simple/blpapi/"
versions=$(curl -fsSL "$INDEX_URL" \
| grep -oP 'blpapi-\K[0-9]+\.[0-9]+\.[0-9]+(?:\.[0-9]+)?' \
| sort -Vr \
| uniq)
for VERSION in $versions; do
linux_url="https://blpapi.bloomberg.com/download/releases/raw/files/blpapi_cpp_${VERSION}-linux.tar.gz"
macos_url="https://blpapi.bloomberg.com/download/releases/raw/files/blpapi_cpp_${VERSION}-macos-arm64.tar.gz"
windows_url="https://blpapi.bloomberg.com/download/releases/raw/files/blpapi_cpp_${VERSION}-windows.zip"
if curl -fsIL "$linux_url" >/dev/null \
&& curl -fsIL "$macos_url" >/dev/null \
&& curl -fsIL "$windows_url" >/dev/null; then
echo "Detected Bloomberg C++ SDK version: $VERSION"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
exit 0
fi
done
echo "No downloadable Bloomberg C++ SDK archives found" >&2
exit 1
# ════════════════════════════════════════════════════════════════════════════
# Generate bindings once on Linux, consume artifact on Windows jobs
# ════════════════════════════════════════════════════════════════════════════
generate-bindings:
name: Generate blpapi bindings artifact
needs: sdk-version
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository_owner }}/xbbg-ci:latest
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Setup Bloomberg SDK
id: sdk
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Linux
- name: Export Bloomberg SDK env
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk.outputs.lib-rel-dir }}"
{
echo "BLPAPI_ROOT=$SDK_ROOT"
echo "LIBRARY_PATH=$LIB_DIR:$LIBRARY_PATH"
echo "LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH"
} >> "$GITHUB_ENV"
- name: Generate bindings artifact
run: |
mkdir -p "$GITHUB_WORKSPACE/ci-bindings"
BLPAPI_BINDINGS_EXPORT_PATH="$GITHUB_WORKSPACE/ci-bindings/bindings.rs" cargo build -p blpapi-sys
test -s "$GITHUB_WORKSPACE/ci-bindings/bindings.rs"
- name: Upload bindings artifact
uses: actions/upload-artifact@v7
with:
name: blpapi-bindings
path: ci-bindings/bindings.rs
retention-days: 7
# ════════════════════════════════════════════════════════════════════════════
# Rust Lint (fast, no SDK needed)
# ════════════════════════════════════════════════════════════════════════════
lint-rust:
name: Lint (Rust)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: rustfmt
cache: false
- name: Rust format check
run: cargo fmt --all -- --check
# ════════════════════════════════════════════════════════════════════════════
# Codegen freshness (fast, no SDK needed)
# ════════════════════════════════════════════════════════════════════════════
codegen:
name: Codegen Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: rustfmt
cache: false
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Check generated files are up to date
run: python defs/codegen/generate.py --check
# ════════════════════════════════════════════════════════════════════════════
# Python Lint (fast, no SDK needed)
# ════════════════════════════════════════════════════════════════════════════
lint-python:
name: Lint (Python)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup pixi
uses: prefix-dev/[email protected]
with:
pixi-version: latest
environments: lint
cache: true
- name: Python lint
run: pixi run -e lint lint
- name: Python format check
run: pixi run -e lint fmt-check
- name: Type check (advisory)
run: pixi run -e lint typecheck || true
# JavaScript wrapper quality (Oxfmt/Oxlint/ESLint/TypeScript/Vitest)
# ════════════════════════════════════════════════════════════════════════════
lint-js:
name: Quality (JS wrapper)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup pixi
uses: prefix-dev/[email protected]
with:
pixi-version: latest
environments: js
cache: true
- name: Install js-xbbg dependencies
working-directory: js-xbbg
run: npm ci
- name: JS quality suite
run: pixi run -e js js-quality
# ════════════════════════════════════════════════════════════════════════════
# Security - cargo-audit (vulnerabilities)
# ════════════════════════════════════════════════════════════════════════════
audit:
name: Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: cargo-bins/[email protected]
- run: cargo binstall -y cargo-audit && cargo audit
# ════════════════════════════════════════════════════════════════════════════
# Security - cargo-deny (licenses, bans, sources)
# ════════════════════════════════════════════════════════════════════════════
deny:
name: Deny
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: cargo-bins/[email protected]
- run: cargo binstall -y cargo-deny && cargo deny check
# ════════════════════════════════════════════════════════════════════════════
# Check (clippy) - split by OS to enable Linux container + Windows artifact
# ════════════════════════════════════════════════════════════════════════════
check-linux:
name: Check (Linux)
needs: sdk-version
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository_owner }}/xbbg-ci:latest
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Setup Bloomberg SDK (Linux)
id: sdk-linux
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Linux
- name: Export Bloomberg SDK env (Linux)
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.lib-rel-dir }}"
{
echo "BLPAPI_ROOT=$SDK_ROOT"
echo "LIBRARY_PATH=$LIB_DIR:$LIBRARY_PATH"
echo "LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH"
} >> "$GITHUB_ENV"
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
target: x86_64-unknown-linux-gnu
components: clippy
rustflags: ""
- name: Cargo clippy
run: cargo clippy --workspace --all-targets -- -D warnings
check-windows:
name: Check (Windows)
needs: [sdk-version, generate-bindings]
runs-on: windows-latest
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
target: x86_64-pc-windows-msvc
components: clippy
rustflags: ""
- name: Download pre-generated bindings
uses: actions/download-artifact@v8
with:
name: blpapi-bindings
path: ci-bindings
- name: Configure pre-generated bindings path
shell: pwsh
run: |
$bindingsPath = Join-Path $env:GITHUB_WORKSPACE "ci-bindings\bindings.rs"
if (-not (Test-Path $bindingsPath)) {
throw "Bindings artifact not found at $bindingsPath"
}
"BLPAPI_PREGENERATED_BINDINGS=$bindingsPath" >> $env:GITHUB_ENV
- name: Setup Bloomberg SDK (Windows)
id: sdk-windows
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Windows
- name: Export Bloomberg SDK env (Windows)
shell: pwsh
run: |
$sdkPath = Join-Path $env:GITHUB_WORKSPACE '${{ steps.sdk-windows.outputs.sdk-rel-root }}'
$binPath = Join-Path $env:GITHUB_WORKSPACE '${{ steps.sdk-windows.outputs.bin-rel-dir }}'
"BLPAPI_ROOT=$sdkPath" >> $env:GITHUB_ENV
"PATH=$binPath;$env:PATH" >> $env:GITHUB_ENV
- name: Cargo clippy
shell: bash
run: cargo clippy --workspace --all-targets -- -D warnings
check-macos:
name: Check (macOS)
needs: [sdk-version, generate-bindings]
runs-on: macos-latest
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
target: aarch64-apple-darwin
components: clippy
rustflags: ""
- name: Download pre-generated bindings
uses: actions/download-artifact@v8
with:
name: blpapi-bindings
path: ci-bindings
- name: Configure pre-generated bindings path (macOS)
run: |
BINDINGS_PATH="$GITHUB_WORKSPACE/ci-bindings/bindings.rs"
test -s "$BINDINGS_PATH"
echo "BLPAPI_PREGENERATED_BINDINGS=$BINDINGS_PATH" >> "$GITHUB_ENV"
- name: Setup Bloomberg SDK (macOS)
id: sdk-macos
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: macOS
- name: Export Bloomberg SDK env (macOS)
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-macos.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-macos.outputs.lib-rel-dir }}"
echo "BLPAPI_ROOT=$SDK_ROOT" >> "$GITHUB_ENV"
echo "DYLD_LIBRARY_PATH=$LIB_DIR:$DYLD_LIBRARY_PATH" >> "$GITHUB_ENV"
- name: Cargo clippy
run: cargo clippy --workspace --all-targets -- -D warnings
# ════════════════════════════════════════════════════════════════════════════
# NAPI core packaging validation
# ════════════════════════════════════════════════════════════════════════════
core-packages:
name: NAPI Core Packages (${{ matrix.label }})
needs: [sdk-version, generate-bindings]
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
label: linux-x64
core_package_dir: js-xbbg/packages/xbbg-core-linux-x64
- os: windows-latest
label: win32-x64
core_package_dir: js-xbbg/packages/xbbg-core-win32-x64
- os: macos-15
label: darwin-arm64
core_package_dir: js-xbbg/packages/xbbg-core-darwin-arm64
runs-on: ${{ matrix.os }}
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
rustflags: ""
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: js-xbbg/package-lock.json
- name: Download pre-generated bindings
uses: actions/download-artifact@v8
with:
name: blpapi-bindings
path: ci-bindings
- name: Configure pre-generated bindings path (Linux)
if: runner.os == 'Linux'
run: |
BINDINGS_PATH="$GITHUB_WORKSPACE/ci-bindings/bindings.rs"
test -s "$BINDINGS_PATH"
echo "BLPAPI_PREGENERATED_BINDINGS=$BINDINGS_PATH" >> "$GITHUB_ENV"
- name: Configure pre-generated bindings path (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$bindingsPath = Join-Path $env:GITHUB_WORKSPACE "ci-bindings\bindings.rs"
if (-not (Test-Path $bindingsPath)) {
throw "Bindings artifact not found at $bindingsPath"
}
"BLPAPI_PREGENERATED_BINDINGS=$bindingsPath" >> $env:GITHUB_ENV
- name: Configure pre-generated bindings path (macOS)
if: runner.os == 'macOS'
run: |
BINDINGS_PATH="$GITHUB_WORKSPACE/ci-bindings/bindings.rs"
test -s "$BINDINGS_PATH"
echo "BLPAPI_PREGENERATED_BINDINGS=$BINDINGS_PATH" >> "$GITHUB_ENV"
- name: Cache Bloomberg SDK (Linux)
if: runner.os == 'Linux'
id: cache-sdk-linux-core
uses: actions/cache@v5
with:
path: ~/blpapi
key: blpapi-Linux-${{ env.BLPAPI_VERSION }}
- name: Download Bloomberg SDK (Linux)
if: runner.os == 'Linux' && steps.cache-sdk-linux-core.outputs.cache-hit != 'true'
run: |
mkdir -p "$HOME/blpapi"
curl -sSL "https://blpapi.bloomberg.com/download/releases/raw/files/blpapi_cpp_${BLPAPI_VERSION}-linux.tar.gz" \
| tar -xz -C "$HOME/blpapi" --strip-components=1
- name: Setup Bloomberg SDK (Linux)
if: runner.os == 'Linux'
run: |
ln -sf "$HOME/blpapi/Linux" "$HOME/blpapi/lib"
ln -sf "$HOME/blpapi/lib/libblpapi3_64.so" "$HOME/blpapi/lib/libblpapi3.so"
echo "BLPAPI_ROOT=$HOME/blpapi" >> "$GITHUB_ENV"
echo "LD_LIBRARY_PATH=$HOME/blpapi/lib:$LD_LIBRARY_PATH" >> "$GITHUB_ENV"
- name: Cache Bloomberg SDK (Windows)
if: runner.os == 'Windows'
id: cache-sdk-windows-core
uses: actions/cache@v5
with:
path: ~/blpapi
key: blpapi-Windows-${{ env.BLPAPI_VERSION }}
- name: Download Bloomberg SDK (Windows)
if: runner.os == 'Windows' && steps.cache-sdk-windows-core.outputs.cache-hit != 'true'
shell: pwsh
run: |
$sdkUrl = "https://blpapi.bloomberg.com/download/releases/raw/files/blpapi_cpp_${{ env.BLPAPI_VERSION }}-windows.zip"
Invoke-WebRequest -Uri $sdkUrl -OutFile blpapi.zip
Expand-Archive -Path blpapi.zip -DestinationPath $HOME/blpapi
- name: Setup Bloomberg SDK (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$sdkPath = (Get-ChildItem $HOME/blpapi -Directory)[0].FullName
"BLPAPI_ROOT=$sdkPath" >> $env:GITHUB_ENV
- name: Cache Bloomberg SDK (macOS)
if: runner.os == 'macOS'
id: cache-sdk-macos-core
uses: actions/cache@v5
with:
path: ~/blpapi
key: blpapi-macOS-${{ env.BLPAPI_VERSION }}
- name: Download Bloomberg SDK (macOS)
if: runner.os == 'macOS' && steps.cache-sdk-macos-core.outputs.cache-hit != 'true'
run: |
mkdir -p "$HOME/blpapi"
curl -sSL "https://blpapi.bloomberg.com/download/releases/raw/files/blpapi_cpp_${BLPAPI_VERSION}-macos-arm64.tar.gz" \
| tar -xz -C "$HOME/blpapi" --strip-components=1
- name: Setup Bloomberg SDK (macOS)
if: runner.os == 'macOS'
run: |
ln -sf "$HOME/blpapi/Darwin" "$HOME/blpapi/lib"
ln -sf "$HOME/blpapi/lib/libblpapi3_64.so" "$HOME/blpapi/lib/libblpapi3.dylib"
echo "BLPAPI_ROOT=$HOME/blpapi" >> "$GITHUB_ENV"
echo "DYLD_LIBRARY_PATH=$HOME/blpapi/lib:$DYLD_LIBRARY_PATH" >> "$GITHUB_ENV"
- name: Install js-xbbg dependencies
run: npm --prefix js-xbbg ci
- name: Build js-xbbg native package
run: npm --prefix js-xbbg run build
- name: Stage packaged core native addon
run: npm --prefix js-xbbg run stage:native-package
- name: Validate core native package export
run: |
node -e "const addon = require('./${{ matrix.core_package_dir }}'); console.log(addon.binaryPath);"
- name: Remove local js-xbbg build artifact (Unix)
if: runner.os != 'Windows'
run: rm -f js-xbbg/napi_xbbg.node
- name: Remove local js-xbbg build artifact (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: Remove-Item js-xbbg\napi_xbbg.node -Force
- name: Smoke test packaged @xbbg/core install
shell: bash
run: npm --prefix js-xbbg run smoke:packaged-install -- 0.0.0-ci
- name: Upload staged core package artifact
uses: actions/upload-artifact@v7
with:
name: core-package-${{ matrix.label }}
path: ${{ matrix.core_package_dir }}
retention-days: 7
# ════════════════════════════════════════════════════════════════════════════
# Offline bundle packaging (one zip per platform, per commit)
# ════════════════════════════════════════════════════════════════════════════
pack-offline-bundles:
name: Pack offline bundles
needs: [core-packages]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "24"
- name: Download linux core package artifact
uses: actions/download-artifact@v4
with:
name: core-package-linux-x64
path: js-xbbg/packages/xbbg-core-linux-x64
- name: Download windows core package artifact
uses: actions/download-artifact@v4
with:
name: core-package-win32-x64
path: js-xbbg/packages/xbbg-core-win32-x64
- name: Download macOS core package artifact
uses: actions/download-artifact@v4
with:
name: core-package-darwin-arm64
path: js-xbbg/packages/xbbg-core-darwin-arm64
- name: Install js-xbbg dependencies
working-directory: js-xbbg
run: npm ci
- name: Build offline bundles
run: |
mkdir -p dist-offline
for label in linux-x64 win32-x64 darwin-arm64; do
npm --prefix js-xbbg run build:offline-bundle -- --label "$label" --out-dir dist-offline
done
ls -1 dist-offline
- name: Upload offline bundles
uses: actions/upload-artifact@v4
with:
name: offline-bundles
path: dist-offline/*.zip
retention-days: 7
# ════════════════════════════════════════════════════════════════════════════
# Build wheels via setuptools-rust + uv (matrix: OS × Python version)
# ════════════════════════════════════════════════════════════════════════════
build:
name: Build (Python ${{ matrix.python }}, ${{ matrix.target }})
needs: [sdk-version, generate-bindings, check-linux, check-windows, check-macos]
strategy:
fail-fast: false
matrix:
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
os: [ubuntu-latest, windows-latest, macos-latest]
target: [x86_64-unknown-linux-gnu, x86_64-pc-windows-msvc, aarch64-apple-darwin]
exclude:
# Linux target only on ubuntu
- os: ubuntu-latest
target: x86_64-pc-windows-msvc
- os: ubuntu-latest
target: aarch64-apple-darwin
# Windows target only on windows
- os: windows-latest
target: x86_64-unknown-linux-gnu
- os: windows-latest
target: aarch64-apple-darwin
- os: macos-latest
target: x86_64-unknown-linux-gnu
- os: macos-latest
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.os }}
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
rustflags: ""
- name: Download pre-generated bindings
uses: actions/download-artifact@v8
with:
name: blpapi-bindings
path: ci-bindings
- name: Configure pre-generated bindings path (Linux)
if: runner.os == 'Linux'
run: |
BINDINGS_PATH="$GITHUB_WORKSPACE/ci-bindings/bindings.rs"
test -s "$BINDINGS_PATH"
echo "BLPAPI_PREGENERATED_BINDINGS=$BINDINGS_PATH" >> "$GITHUB_ENV"
- name: Configure pre-generated bindings path (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$bindingsPath = Join-Path $env:GITHUB_WORKSPACE "ci-bindings\bindings.rs"
if (-not (Test-Path $bindingsPath)) {
throw "Bindings artifact not found at $bindingsPath"
}
"BLPAPI_PREGENERATED_BINDINGS=$bindingsPath" >> $env:GITHUB_ENV
- name: Configure pre-generated bindings path (macOS)
if: runner.os == 'macOS'
run: |
BINDINGS_PATH="$GITHUB_WORKSPACE/ci-bindings/bindings.rs"
test -s "$BINDINGS_PATH"
echo "BLPAPI_PREGENERATED_BINDINGS=$BINDINGS_PATH" >> "$GITHUB_ENV"
- name: Setup Bloomberg SDK (Linux)
if: runner.os == 'Linux'
id: sdk-linux
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Linux
- name: Export Bloomberg SDK env (Linux)
if: runner.os == 'Linux'
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.lib-rel-dir }}"
{
echo "BLPAPI_ROOT=$SDK_ROOT"
echo "LIBRARY_PATH=$LIB_DIR:$LIBRARY_PATH"
echo "LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH"
} >> "$GITHUB_ENV"
- name: Setup Bloomberg SDK (Windows)
if: runner.os == 'Windows'
id: sdk-windows
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Windows
- name: Export Bloomberg SDK env (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$sdkPath = Join-Path $env:GITHUB_WORKSPACE '${{ steps.sdk-windows.outputs.sdk-rel-root }}'
$binPath = Join-Path $env:GITHUB_WORKSPACE '${{ steps.sdk-windows.outputs.bin-rel-dir }}'
"BLPAPI_ROOT=$sdkPath" >> $env:GITHUB_ENV
"PATH=$binPath;$env:PATH" >> $env:GITHUB_ENV
- name: Setup Bloomberg SDK (macOS)
if: runner.os == 'macOS'
id: sdk-macos
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: macOS
- name: Export Bloomberg SDK env (macOS)
if: runner.os == 'macOS'
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-macos.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-macos.outputs.lib-rel-dir }}"
echo "BLPAPI_ROOT=$SDK_ROOT" >> "$GITHUB_ENV"
echo "DYLD_LIBRARY_PATH=$LIB_DIR:$DYLD_LIBRARY_PATH" >> "$GITHUB_ENV"
- name: Setup Python ${{ matrix.python }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python }}
allow-prereleases: true
- name: Setup uv
uses: astral-sh/setup-uv@v7
- name: Build wheel (setuptools-rust via uv)
run: uv build --wheel --out-dir dist/
- name: Upload wheel
uses: actions/upload-artifact@v7
with:
name: wheel-${{ matrix.os }}-py${{ matrix.python }}
path: dist/*.whl
# ════════════════════════════════════════════════════════════════════════════
# Test wheels (matrix: OS × Python version)
# ════════════════════════════════════════════════════════════════════════════
test:
name: Test (Python ${{ matrix.python }}, ${{ matrix.os }})
needs: [sdk-version, build]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Setup Python ${{ matrix.python }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python }}
allow-prereleases: true
- name: Setup uv
uses: astral-sh/setup-uv@v7
- name: Download wheel
uses: actions/download-artifact@v8
with:
name: wheel-${{ matrix.os }}-py${{ matrix.python }}
path: dist
- name: Setup Bloomberg SDK (Linux)
if: runner.os == 'Linux'
id: sdk-linux
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Linux
- name: Export Bloomberg SDK env (Linux)
if: runner.os == 'Linux'
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.lib-rel-dir }}"
{
echo "BLPAPI_ROOT=$SDK_ROOT"
echo "LIBRARY_PATH=$LIB_DIR:$LIBRARY_PATH"
echo "LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH"
} >> "$GITHUB_ENV"
- name: Setup Bloomberg SDK (macOS)
if: runner.os == 'macOS'
id: sdk-macos
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: macOS
- name: Export Bloomberg SDK env (macOS)
if: runner.os == 'macOS'
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-macos.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-macos.outputs.lib-rel-dir }}"
echo "BLPAPI_ROOT=$SDK_ROOT" >> "$GITHUB_ENV"
echo "DYLD_LIBRARY_PATH=$LIB_DIR:$DYLD_LIBRARY_PATH" >> "$GITHUB_ENV"
- name: Install blpapi from Bloomberg
run: uv pip install --system --index-url https://blpapi.bloomberg.com/repository/releases/python/simple/ blpapi
- name: Install wheel and test dependencies
shell: bash
run: |
# Install the specific wheel for this Python version
WHEEL=$(echo dist/*.whl)
uv pip install --system "${WHEEL}[test]"
- name: Copy tests to temp directory
# Run from temp dir to avoid importing local source instead of installed package
run: |
mkdir -p "${{ runner.temp }}/test-run"
cp -r py-xbbg/tests "${{ runner.temp }}/test-run/"
shell: bash
- name: Run tests
working-directory: ${{ runner.temp }}/test-run
run: pytest tests -v -m "not live"
- name: Run tests with coverage
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.12'
working-directory: ${{ runner.temp }}/test-run
run: pytest tests --cov=xbbg --cov-report=xml -v -m "not live"
- name: Upload coverage
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.12'
uses: codecov/codecov-action@v5
with:
files: coverage.xml
fail_ci_if_error: false
# ════════════════════════════════════════════════════════════════════════════
# Unused Dependencies (optional, non-blocking)
# ════════════════════════════════════════════════════════════════════════════
udeps:
name: Unused Deps
needs: [sdk-version, check-linux]
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository_owner }}/xbbg-ci:latest
continue-on-error: true
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Setup Bloomberg SDK (Linux)
id: sdk-linux
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Linux
- name: Export Bloomberg SDK env (Linux)
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.lib-rel-dir }}"
{
echo "BLPAPI_ROOT=$SDK_ROOT"
echo "LIBRARY_PATH=$LIB_DIR:$LIBRARY_PATH"
echo "LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH"
} >> "$GITHUB_ENV"
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: nightly
rustflags: ""
- name: Install cargo-binstall
run: curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
- run: |
export PATH="$HOME/.cargo/bin:$PATH"
cargo binstall -y --force cargo-udeps
cargo +nightly udeps --workspace --all-targets --exclude pyo3-xbbg
# ════════════════════════════════════════════════════════════════════════════
# Unsafe Code Audit (optional, non-blocking)
# ════════════════════════════════════════════════════════════════════════════
geiger:
name: Unsafe Audit
needs: [sdk-version, check-linux]
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository_owner }}/xbbg-ci:latest
continue-on-error: true
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Setup Bloomberg SDK (Linux)
id: sdk-linux
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Linux
- name: Export Bloomberg SDK env (Linux)
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.lib-rel-dir }}"
{
echo "BLPAPI_ROOT=$SDK_ROOT"
echo "LIBRARY_PATH=$LIB_DIR:$LIBRARY_PATH"
echo "LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH"
} >> "$GITHUB_ENV"
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: rust-src
rustflags: ""
- name: Install cargo-binstall
run: curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
- name: Run cargo-geiger
run: |
export PATH="$HOME/.cargo/bin:$PATH"
cargo binstall -y --force cargo-geiger
for crate in blpapi-sys xbbg-core xbbg-async pyo3-xbbg; do
echo "=== $crate ==="
# Allow warnings about unscanned files (generated bindings, C files)
cargo-geiger --manifest-path "$GITHUB_WORKSPACE/crates/$crate/Cargo.toml" || true
done
# ════════════════════════════════════════════════════════════════════════════
# Bloomberg SDK ABI Compatibility (optional, non-blocking)
# ════════════════════════════════════════════════════════════════════════════
abi-compat:
name: ABI Compat
needs: sdk-version
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository_owner }}/xbbg-ci:latest
continue-on-error: true
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Install bindgen-cli
run: cargo install bindgen-cli --version 0.72.1
- name: Run ABI compatibility check
run: |
# Read min supported version from defs/bloomberg.toml (single source of truth),
# then check that version plus the latest detected SDK.
MIN_SDK=$(grep '^min_sdk_version' defs/bloomberg.toml | sed 's/.*= *"\(.*\)"/\1/')
bash scripts/abi-check.sh --versions "$MIN_SDK $BLPAPI_VERSION"
# ════════════════════════════════════════════════════════════════════════════
# Semver Compatibility (optional, non-blocking)
# ════════════════════════════════════════════════════════════════════════════
semver:
name: Semver Check
needs: [sdk-version, check-linux]
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository_owner }}/xbbg-ci:latest
continue-on-error: true
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Full history for baseline
- name: Setup Bloomberg SDK (Linux)
id: sdk-linux
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Linux
- name: Export Bloomberg SDK env (Linux)
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.lib-rel-dir }}"
{
echo "BLPAPI_ROOT=$SDK_ROOT"
echo "LIBRARY_PATH=$LIB_DIR:$LIBRARY_PATH"
echo "LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH"
} >> "$GITHUB_ENV"
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
rustflags: ""
- name: Install cargo-binstall
run: curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
- name: Run cargo-semver-checks
run: |
export PATH="$HOME/.cargo/bin:$PATH"
cargo binstall -y --force cargo-semver-checks
# Check if Rust crates directory exists in main branch
if git show origin/main:crates/xbbg-core/Cargo.toml >/dev/null 2>&1; then
cargo-semver-checks --baseline-rev origin/main
else
echo "Skipping: Rust crates not in baseline yet (will run after merge to main)"
fi
# ════════════════════════════════════════════════════════════════════════════
# Kani Verification (disabled — no #[kani::proof] harnesses exist yet)
# Re-enable once proof harnesses are added to workspace crates.
# ════════════════════════════════════════════════════════════════════════════
# kani:
# name: Kani
# needs: [sdk-version, check-linux]
# runs-on: ubuntu-latest
# continue-on-error: true
# env:
# BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
# steps:
# - uses: actions/checkout@v6
#
# - name: Install libclang
# run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libclang-dev
#
# - name: Cache Bloomberg SDK
# id: cache-sdk
# uses: actions/cache@v5
# with:
# path: ~/blpapi
# key: blpapi-Linux-${{ env.BLPAPI_VERSION }}
#
# - name: Download Bloomberg SDK (Linux)
# if: steps.cache-sdk.outputs.cache-hit != 'true'
# run: |
# mkdir -p "$HOME/blpapi"
# curl -sSL "https://blpapi.bloomberg.com/download/releases/raw/files/blpapi_cpp_${BLPAPI_VERSION}-linux.tar.gz" \
# | tar -xz -C "$HOME/blpapi" --strip-components=1
#
# - name: Setup Bloomberg SDK (Linux)
# run: |
# ln -sf "$HOME/blpapi/Linux" "$HOME/blpapi/lib"
# ln -sf "$HOME/blpapi/lib/libblpapi3_64.so" "$HOME/blpapi/lib/libblpapi3.so"
# echo "BLPAPI_ROOT=$HOME/blpapi" >> "$GITHUB_ENV"
# echo "LD_LIBRARY_PATH=$HOME/blpapi/lib:$LD_LIBRARY_PATH" >> "$GITHUB_ENV"
#
# - name: Run Kani
# uses: model-checking/kani-github-action@v1
# with:
# args: --workspace --exclude blpapi-sys --exclude pyo3-xbbg
# ════════════════════════════════════════════════════════════════════════════
# CI Status (required gate for merging)
# ════════════════════════════════════════════════════════════════════════════
ci-status:
name: CI Status
runs-on: ubuntu-latest
needs: [codegen, lint-rust, lint-python, audit, deny, check-linux, check-windows, check-macos, build, test]
if: always()
steps:
- name: Check required jobs
run: |
if [[ "${{ needs.codegen.result }}" != "success" ]] || \
[[ "${{ needs.lint-rust.result }}" != "success" ]] || \
[[ "${{ needs.lint-python.result }}" != "success" ]] || \
[[ "${{ needs.audit.result }}" != "success" ]] || \
[[ "${{ needs.deny.result }}" != "success" ]] || \
[[ "${{ needs.check-linux.result }}" != "success" ]] || \
[[ "${{ needs.check-windows.result }}" != "success" ]] || \
[[ "${{ needs.check-macos.result }}" != "success" ]] || \
[[ "${{ needs.build.result }}" != "success" ]] || \
[[ "${{ needs.test.result }}" != "success" ]]; then
echo "❌ One or more required jobs failed"
echo " codegen: ${{ needs.codegen.result }}"
echo " lint-rust: ${{ needs.lint-rust.result }}"
echo " lint-python: ${{ needs.lint-python.result }}"
echo " audit: ${{ needs.audit.result }}"
echo " deny: ${{ needs.deny.result }}"
echo " check-linux: ${{ needs.check-linux.result }}"
echo " check-windows: ${{ needs.check-windows.result }}"
echo " check-macos: ${{ needs.check-macos.result }}"
echo " build: ${{ needs.build.result }}"
echo " test: ${{ needs.test.result }}"
exit 1
fi
echo "✅ All CI checks passed!"
# ════════════════════════════════════════════════════════════════════════════
# Auto-generate type stubs (runs LAST, only after all CI passes)
# ════════════════════════════════════════════════════════════════════════════
update-stubs:
name: Update Type Stubs
needs: [sdk-version, ci-status]
if: needs.ci-status.result == 'success' && github.event_name == 'push'
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository_owner }}/xbbg-ci:latest
continue-on-error: true
permissions:
contents: write
env:
BLPAPI_VERSION: ${{ needs.sdk-version.outputs.version }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.ref }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Configure git for container
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Setup Bloomberg SDK
id: sdk-linux
uses: ./.github/actions/setup-blpapi-sdk
with:
version: ${{ env.BLPAPI_VERSION }}
os: Linux
- name: Export Bloomberg SDK env
run: |
SDK_ROOT="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.sdk-rel-root }}"
LIB_DIR="$GITHUB_WORKSPACE/${{ steps.sdk-linux.outputs.lib-rel-dir }}"
{
echo "BLPAPI_ROOT=$SDK_ROOT"
echo "LIBRARY_PATH=$LIB_DIR:$LIBRARY_PATH"
echo "LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH"
} >> "$GITHUB_ENV"
- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
rustflags: ""
- name: Build stub generator
run: cargo build -p pyo3-xbbg --bin stub_gen --no-default-features --features live,stub-gen
- name: Regenerate stubs
run: CARGO_MANIFEST_DIR="$GITHUB_WORKSPACE/bindings/pyo3-xbbg" ./target/debug/stub_gen
- name: Commit stubs if changed
run: |
git add py-xbbg/src/xbbg/_core/__init__.pyi py-xbbg/src/xbbg/__init__.pyi py-xbbg/src/xbbg/py.typed
if git diff --cached --quiet; then
echo "Type stubs are already up to date"
else
git commit -m "chore: regenerate type stubs [skip ci]"
git push
fi