CI fix #23
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: Build and release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| tags: | |
| - 'v*.*.*' | |
| pull_request: | |
| workflow_dispatch: | |
| inputs: | |
| make_release: | |
| description: "Also publish a GitHub release from this manual run" | |
| type: boolean | |
| default: true | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| # Pinned python-build-standalone release bundled into every published package, | |
| # so releases are self-contained and ABI-stable regardless of the runner's | |
| # ambient Python. See https://github.com/astral-sh/python-build-standalone | |
| PBS_RELEASE: "20260623" | |
| PBS_PYTHON_VERSION: "3.14.6" | |
| jobs: | |
| build: | |
| name: ${{ matrix.name }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: Linux x86_64 | |
| os: ubuntu-22.04 | |
| package: linux-x86_64 | |
| mads_asset: "*Linux-x86_64.tar.gz" | |
| pbs_triple: x86_64-unknown-linux-gnu | |
| - name: Linux aarch64 | |
| os: ubuntu-22.04-arm | |
| package: linux-aarch64 | |
| mads_asset: "*Linux-aarch64.tar.gz" | |
| pbs_triple: aarch64-unknown-linux-gnu | |
| - name: macOS arm64 | |
| os: macos-15 | |
| package: macos-arm64 | |
| mads_asset: "*Darwin-universal.sh" | |
| cmake_osx_architectures: "arm64" | |
| pbs_triple: aarch64-apple-darwin | |
| - name: macOS x86_64 | |
| os: macos-14 | |
| package: macos-x86_64 | |
| mads_asset: "*Darwin-universal.sh" | |
| cmake_osx_architectures: "x86_64" | |
| pbs_triple: x86_64-apple-darwin | |
| - name: Windows x86_64 | |
| os: windows-2022 | |
| package: windows-x86_64 | |
| mads_asset: "*Windows-AMD64.exe" | |
| pbs_triple: x86_64-pc-windows-msvc | |
| steps: | |
| - name: Check out sources | |
| uses: actions/checkout@v6 | |
| # Used only for the stdlib JSON heredocs in the "Install MADS" steps below. | |
| # The interpreter shipped to users is the bundled one downloaded later. | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.x' | |
| - name: Install Linux build dependencies | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| clang \ | |
| cmake \ | |
| extra-cmake-modules \ | |
| ninja-build \ | |
| python3 python3-dev \ | |
| pkg-config | |
| - name: Set up MSVC | |
| if: runner.os == 'Windows' | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| with: | |
| arch: amd64 | |
| - name: Install MADS on Linux | |
| if: runner.os == 'Linux' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "$RUNNER_TEMP/mads-release" "$RUNNER_TEMP/mads" | |
| curl -fsSL \ | |
| -H "Authorization: Bearer $GH_TOKEN" \ | |
| -H "X-GitHub-Api-Version: 2022-11-28" \ | |
| -H "User-Agent: mads-chat-ci" \ | |
| "https://api.github.com/repos/pbosetti/MADS/releases/latest" \ | |
| -o "$RUNNER_TEMP/mads-release/latest.json" | |
| asset_url="$( | |
| python3 - "$RUNNER_TEMP/mads-release/latest.json" "${{ matrix.mads_asset }}" <<'PY' | |
| import fnmatch | |
| import json | |
| import sys | |
| with open(sys.argv[1], encoding="utf-8") as handle: | |
| release = json.load(handle) | |
| for asset in release["assets"]: | |
| if fnmatch.fnmatch(asset["name"], sys.argv[2]): | |
| print(asset["url"]) | |
| break | |
| else: | |
| raise SystemExit(f"No MADS release asset matches {sys.argv[2]}") | |
| PY | |
| )" | |
| curl -fL \ | |
| -H "Accept: application/octet-stream" \ | |
| -H "Authorization: Bearer $GH_TOKEN" \ | |
| -H "X-GitHub-Api-Version: 2022-11-28" \ | |
| -H "User-Agent: mads-chat-ci" \ | |
| "$asset_url" \ | |
| -o "$RUNNER_TEMP/mads-release/mads.tar.gz" | |
| archive="$RUNNER_TEMP/mads-release/mads.tar.gz" | |
| tar -xzf "$archive" -C "$RUNNER_TEMP/mads" | |
| agent_header="$(find "$RUNNER_TEMP/mads" -type f -path '*/include/agent.hpp' -print -quit)" | |
| if [ -z "$agent_header" ]; then | |
| echo "Could not find MADS headers after extracting $archive" >&2 | |
| exit 1 | |
| fi | |
| mads_root="${agent_header%/include/agent.hpp}" | |
| test -f "$mads_root/lib/libMadsCore.so" | |
| echo "MADS_ROOT=$mads_root" >> "$GITHUB_ENV" | |
| echo "$mads_root/bin" >> "$GITHUB_PATH" | |
| - name: Install MADS on macOS | |
| if: runner.os == 'macOS' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "$RUNNER_TEMP/mads-release" "$RUNNER_TEMP/mads" | |
| curl -fsSL \ | |
| -H "Authorization: Bearer $GH_TOKEN" \ | |
| -H "X-GitHub-Api-Version: 2022-11-28" \ | |
| -H "User-Agent: mads-chat-ci" \ | |
| "https://api.github.com/repos/pbosetti/MADS/releases/latest" \ | |
| -o "$RUNNER_TEMP/mads-release/latest.json" | |
| asset_url="$( | |
| python3 - "$RUNNER_TEMP/mads-release/latest.json" "${{ matrix.mads_asset }}" <<'PY' | |
| import fnmatch | |
| import json | |
| import sys | |
| with open(sys.argv[1], encoding="utf-8") as handle: | |
| release = json.load(handle) | |
| for asset in release["assets"]: | |
| if fnmatch.fnmatch(asset["name"], sys.argv[2]): | |
| print(asset["url"]) | |
| break | |
| else: | |
| raise SystemExit(f"No MADS release asset matches {sys.argv[2]}") | |
| PY | |
| )" | |
| installer="$RUNNER_TEMP/mads-release/mads.sh" | |
| curl -fL \ | |
| -H "Accept: application/octet-stream" \ | |
| -H "Authorization: Bearer $GH_TOKEN" \ | |
| -H "X-GitHub-Api-Version: 2022-11-28" \ | |
| -H "User-Agent: mads-chat-ci" \ | |
| "$asset_url" \ | |
| -o "$installer" | |
| sh "$installer" --skip-license --prefix="$RUNNER_TEMP/mads" --exclude-subdir | |
| agent_header="$(find "$RUNNER_TEMP/mads" -type f -path '*/include/agent.hpp' -print -quit)" | |
| if [ -z "$agent_header" ]; then | |
| echo "Could not find MADS headers after running $installer" >&2 | |
| exit 1 | |
| fi | |
| mads_root="${agent_header%/include/agent.hpp}" | |
| test -f "$mads_root/lib/libMadsCore.dylib" | |
| echo "MADS_ROOT=$mads_root" >> "$GITHUB_ENV" | |
| echo "$mads_root/bin" >> "$GITHUB_PATH" | |
| - name: Install MADS on Windows | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| New-Item -ItemType Directory -Force "$env:RUNNER_TEMP\mads-release", "$env:RUNNER_TEMP\mads" | Out-Null | |
| $headers = @{ | |
| Authorization = "Bearer $env:GH_TOKEN" | |
| Accept = "application/vnd.github+json" | |
| "X-GitHub-Api-Version" = "2022-11-28" | |
| "User-Agent" = "mads-chat-ci" | |
| } | |
| $release = Invoke-RestMethod -Uri "https://api.github.com/repos/pbosetti/MADS/releases/latest" -Headers $headers | |
| $asset = $release.assets | | |
| Where-Object { $_.name -like "${{ matrix.mads_asset }}" } | | |
| Select-Object -First 1 | |
| if (-not $asset) { | |
| throw "No MADS release asset matches ${{ matrix.mads_asset }}" | |
| } | |
| $installer = "$env:RUNNER_TEMP\mads-release\mads.exe" | |
| $downloadHeaders = @{ | |
| Authorization = "Bearer $env:GH_TOKEN" | |
| Accept = "application/octet-stream" | |
| "X-GitHub-Api-Version" = "2022-11-28" | |
| "User-Agent" = "mads-chat-ci" | |
| } | |
| Invoke-WebRequest -Uri $asset.url -Headers $downloadHeaders -OutFile $installer | |
| $installRoot = "$env:RUNNER_TEMP\mads" | |
| $process = Start-Process ` | |
| -FilePath $installer ` | |
| -ArgumentList "/VERYSILENT", "/SUPPRESSMSGBOXES", "/NORESTART", "/SP-", "/CURRENTUSER", "/DIR=$installRoot" ` | |
| -Wait ` | |
| -PassThru | |
| if ($process.ExitCode -ne 0) { | |
| throw "MADS installer failed with exit code $($process.ExitCode)" | |
| } | |
| $agentHeader = Get-ChildItem $installRoot -Recurse -Filter agent.hpp | | |
| Where-Object { $_.FullName -match '\\include\\agent\.hpp$' } | | |
| Select-Object -First 1 | |
| if (-not $agentHeader) { | |
| throw "Could not find MADS headers after running $installer" | |
| } | |
| $madsRoot = Split-Path (Split-Path $agentHeader.FullName -Parent) -Parent | |
| $madsImportLibrary = Join-Path $madsRoot "lib\MadsCore.lib" | |
| if (-not (Test-Path $madsImportLibrary)) { | |
| throw "Could not find $madsImportLibrary" | |
| } | |
| "MADS_ROOT=$madsRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| "$madsRoot\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append | |
| - name: Download bundled CPython | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| case "${{ matrix.pbs_triple }}" in | |
| *windows*) py=python.exe ;; | |
| *) py=bin/python3 ;; | |
| esac | |
| url="https://github.com/astral-sh/python-build-standalone/releases/download/${PBS_RELEASE}/cpython-${PBS_PYTHON_VERSION}+${PBS_RELEASE}-${{ matrix.pbs_triple }}-install_only_stripped.tar.gz" | |
| # $RUNNER_TEMP is a native path (e.g. "D:\a\_temp" on Windows). MSYS | |
| # tar/curl in Git Bash need a POSIX path ("/d/a/_temp"), so normalise | |
| # with cygpath where available (Windows); on Linux/macOS it's a no-op. | |
| dest="$RUNNER_TEMP/pbs" | |
| if command -v cygpath >/dev/null 2>&1; then | |
| dest="$(cygpath -u "$RUNNER_TEMP")/pbs" | |
| fi | |
| mkdir -p "$dest" | |
| # Pipe straight into tar (no -f): a "D:" archive path would otherwise | |
| # be parsed as a remote host:path spec. Works the same with bsdtar. | |
| curl -fsSL "$url" | tar -xz -C "$dest" | |
| # Populate the bundled interpreter's own site-packages. | |
| "$dest/python/$py" -m pip install --upgrade pip | |
| "$dest/python/$py" -m pip install numpy | |
| # Export PBS_DIR in a form CMake/pwsh understand: a mixed Windows path | |
| # with forward slashes ("D:/a/_temp/pbs/python") on Windows, the plain | |
| # POSIX path elsewhere. | |
| bundle="$dest/python" | |
| if command -v cygpath >/dev/null 2>&1; then | |
| bundle="$(cygpath -m "$dest/python")" | |
| fi | |
| echo "PBS_DIR=$bundle" >> "$GITHUB_ENV" | |
| - name: Configure | |
| if: runner.os != 'Windows' | |
| env: | |
| CC: clang | |
| CXX: clang++ | |
| CMAKE_OSX_ARCHITECTURES: ${{ matrix.cmake_osx_architectures }} | |
| run: | | |
| extra_args=() | |
| if [ -n "${CMAKE_OSX_ARCHITECTURES:-}" ]; then | |
| extra_args+=("-DCMAKE_OSX_ARCHITECTURES=$CMAKE_OSX_ARCHITECTURES") | |
| fi | |
| cmake -S . -B build -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_INSTALL_PREFIX="$PWD/package" \ | |
| -DMADS_ROOT="$MADS_ROOT" \ | |
| -DPYTHON_AGENT_BUNDLE_PYTHON=ON \ | |
| -DPYTHON_BUNDLE_DIR="$PBS_DIR" \ | |
| "${extra_args[@]}" | |
| - name: Configure | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| cmake -S . -B build -G Ninja ` | |
| -DCMAKE_BUILD_TYPE=Release ` | |
| "-DCMAKE_INSTALL_PREFIX=$env:GITHUB_WORKSPACE\package" ` | |
| "-DMADS_ROOT=$env:MADS_ROOT" ` | |
| -DPYTHON_AGENT_BUNDLE_PYTHON=ON ` | |
| "-DPYTHON_BUNDLE_DIR=$env:PBS_DIR" | |
| - name: Build | |
| run: cmake --build build --config Release --parallel | |
| - name: Package | |
| run: cmake --build build --config Release --target package --parallel | |
| - name: Upload package | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: mads-chat-${{ matrix.package }} | |
| path: build/*.zip | |
| if-no-files-found: error | |
| release: | |
| name: Create GitHub release | |
| if: >- | |
| startsWith(github.ref, 'refs/tags/') || | |
| (github.event_name == 'workflow_dispatch' && inputs.make_release) | |
| needs: build | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download packages | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: mads-chat-* | |
| path: dist | |
| merge-multiple: true | |
| - name: Create release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$GITHUB_REF_TYPE" = "tag" ]; then | |
| release_tag="$GITHUB_REF_NAME" | |
| release_title="$GITHUB_REF_NAME" | |
| extra_args=(--verify-tag) | |
| else | |
| safe_ref="$(printf '%s' "$GITHUB_REF_NAME" | tr -c '[:alnum:]._-' '-')" | |
| short_sha="${GITHUB_SHA::7}" | |
| release_tag="${safe_ref}-${short_sha}" | |
| release_title="${GITHUB_REF_NAME} ${short_sha}" | |
| extra_args=(--target "$GITHUB_SHA") | |
| fi | |
| gh release create "$release_tag" dist/*.zip \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --title "$release_title" \ | |
| --generate-notes \ | |
| "${extra_args[@]}" |