Skip to content

test sfor CI

test sfor CI #32

Workflow file for this run

name: Build and Release
on:
push:
branches: [ main ]
pull_request:
jobs:
dotnet-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build managed projects
run: dotnet build --configuration Release --no-restore
native-linux:
needs: dotnet-build
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake libopenblas-dev liblapack-dev liblapacke-dev
- name: Configure native build
run: cmake -S native -B native/build/linux -DCMAKE_BUILD_TYPE=Release
- name: Build native library
run: cmake --build native/build/linux --target mlxsharp --config Release
- name: Package native artifact
run: |
mkdir -p artifacts/native/linux-x64
cp native/build/linux/libmlxsharp.so artifacts/native/linux-x64/
- name: Upload native artifact
uses: actions/upload-artifact@v4
with:
name: native-linux-x64
path: artifacts/native/linux-x64/libmlxsharp.so
native-macos:
needs: dotnet-build
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install CMake
run: brew install cmake
- name: Configure native build
run: cmake -S native -B native/build/macos -DCMAKE_BUILD_TYPE=Release
- name: Build native library
run: cmake --build native/build/macos --target mlxsharp --config Release
- name: Package native artifact
run: |
mkdir -p artifacts/native/osx-arm64
cp native/build/macos/libmlxsharp.dylib artifacts/native/osx-arm64/
- name: Upload native artifact
uses: actions/upload-artifact@v4
with:
name: native-osx-arm64
path: artifacts/native/osx-arm64/libmlxsharp.dylib
package-test:
needs:
- native-linux
- native-macos
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Show .NET info
run: dotnet --info
- name: Restore dependencies
run: dotnet restore
- name: Build C# projects (initial validation)
run: dotnet build --configuration Release --no-restore
- name: Setup Python for HuggingFace
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install HuggingFace CLI
run: pip install huggingface_hub
- name: Download test model from HuggingFace
run: |
mkdir -p models
huggingface-cli download mlx-community/Qwen1.5-0.5B-Chat-4bit --local-dir models/Qwen1.5-0.5B-Chat-4bit
echo "Model files:"
ls -la models/Qwen1.5-0.5B-Chat-4bit/
- name: Download macOS native library
uses: actions/download-artifact@v4
with:
name: native-osx-arm64
path: artifacts/native/osx-arm64
- name: Download Linux native library
uses: actions/download-artifact@v4
with:
name: native-linux-x64
path: artifacts/native/linux-x64
- name: Stage native libraries in project
run: |
mkdir -p src/MLXSharp/runtimes/osx-arm64/native
cp artifacts/native/osx-arm64/libmlxsharp.dylib src/MLXSharp/runtimes/osx-arm64/native/
mkdir -p src/MLXSharp/runtimes/linux-x64/native
cp artifacts/native/linux-x64/libmlxsharp.so src/MLXSharp/runtimes/linux-x64/native/
- name: Build C# projects with native libraries
run: dotnet build --configuration Release --no-restore
- name: Copy native library to test output
run: |
TEST_OUTPUT="src/MLXSharp.Tests/bin/Release/net9.0"
mkdir -p "$TEST_OUTPUT/runtimes/osx-arm64/native"
cp src/MLXSharp/runtimes/osx-arm64/native/libmlxsharp.dylib "$TEST_OUTPUT/runtimes/osx-arm64/native/"
ls -la "$TEST_OUTPUT/runtimes/osx-arm64/native/"
- name: Run tests
run: |
dotnet test \
--configuration Release \
--no-build \
--logger "trx;LogFileName=TestResults.trx" \
--logger "console;verbosity=detailed" \
--results-directory artifacts/test-results
env:
MLXSHARP_MODEL_PATH: ${{ github.workspace }}/models/Qwen1.5-0.5B-Chat-4bit
- name: Prepare artifact folders
run: |
mkdir -p artifacts/test-results
mkdir -p artifacts/packages
mkdir -p artifacts/native
cp artifacts/native/osx-arm64/libmlxsharp.dylib artifacts/native/
cp artifacts/native/linux-x64/libmlxsharp.so artifacts/native/
- name: Pack MLXSharp library
run: dotnet pack src/MLXSharp/MLXSharp.csproj --configuration Release --output artifacts/packages -p:MLXSharpMacNativeBinary=$GITHUB_WORKSPACE/artifacts/native/osx-arm64/libmlxsharp.dylib -p:MLXSharpLinuxNativeBinary=$GITHUB_WORKSPACE/artifacts/native/linux-x64/libmlxsharp.so
- name: Pack MLXSharp.SemanticKernel library
run: dotnet pack src/MLXSharp.SemanticKernel/MLXSharp.SemanticKernel.csproj --configuration Release --output artifacts/packages -p:MLXSharpMacNativeBinary=$GITHUB_WORKSPACE/artifacts/native/osx-arm64/libmlxsharp.dylib -p:MLXSharpLinuxNativeBinary=$GITHUB_WORKSPACE/artifacts/native/linux-x64/libmlxsharp.so -p:MLXSharpSkipLinuxNativeValidation=true
- name: Verify package contains native libraries
run: |
echo "Checking package contents..."
shopt -s nullglob
packages=(artifacts/packages/*.nupkg)
if [ ${#packages[@]} -eq 0 ]; then
echo "✗ ERROR: No packages were produced"
exit 1
fi
missing=0
for package in "${packages[@]}"; do
echo "Inspecting ${package}"
filename=$(basename "${package}")
case "${filename}" in
MLXSharp.SemanticKernel.*.nupkg)
echo " ↷ Skipping native check for ${filename}"
;;
MLXSharp.*.nupkg)
package_missing=0
if unzip -l "${package}" | grep -q "runtimes/osx-arm64/native/libmlxsharp.dylib"; then
echo " ✓ macOS library present"
else
echo " ✗ macOS library missing"
package_missing=1
fi
if unzip -l "${package}" | grep -q "runtimes/linux-x64/native/libmlxsharp.so"; then
echo " ✓ Linux library present"
else
echo " ✗ Linux library missing"
package_missing=1
fi
if [ ${package_missing} -ne 0 ]; then
unzip -l "${package}"
missing=1
fi
;;
*)
echo " ↷ Skipping native check for ${filename}"
;;
esac
done
if [ $missing -ne 0 ]; then
exit 1
fi
- name: Upload native artifact
uses: actions/upload-artifact@v4
with:
name: native-libs
path: artifacts/native
- name: Upload packages artifact
uses: actions/upload-artifact@v4
with:
name: packages
path: artifacts/packages
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: artifacts/test-results
- name: Publish test results
if: always()
uses: actions/upload-test-results@v1
with:
test-results: artifacts/test-results/TestResults.trx
check-name: dotnet tests
release:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: package-test
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: Determine MLX version
id: mlx_version
run: |
git submodule update --init --recursive
git -C extern/mlx fetch --tags
if MLX_TAG=$(git -C extern/mlx describe --tags --abbrev=0 2>/dev/null); then
echo "Detected MLX tag: ${MLX_TAG}"
else
echo "::warning::Unable to determine MLX tag; falling back to commit hash"
MLX_TAG="unknown"
fi
MLX_COMMIT=$(git -C extern/mlx rev-parse --short HEAD)
echo "tag=${MLX_TAG}" >> "$GITHUB_OUTPUT"
echo "commit=${MLX_COMMIT}" >> "$GITHUB_OUTPUT"
- name: Extract version from Directory.Build.props
id: version
run: |
VERSION=$(grep -oP '<Version>\K[^<]+' Directory.Build.props)
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Extracted version: $VERSION"
- name: Check if tag exists
id: check_tag
run: |
if git ls-remote --tags origin | grep -q "refs/tags/v${{ steps.version.outputs.version }}"; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "Tag v${{ steps.version.outputs.version }} already exists"
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "Tag v${{ steps.version.outputs.version }} does not exist"
fi
- name: Download package artifacts
if: steps.check_tag.outputs.exists == 'false'
uses: actions/download-artifact@v4
with:
name: packages
path: artifacts/packages
- name: Publish to NuGet
if: steps.check_tag.outputs.exists == 'false'
run: |
for package in artifacts/packages/*.nupkg; do
echo "Publishing $package..."
dotnet nuget push "$package" \
--api-key ${{ secrets.NUGET_API_KEY }} \
--source https://api.nuget.org/v3/index.json \
--skip-duplicate || true
done
- name: Create Git tag
if: steps.check_tag.outputs.exists == 'false'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "v${{ steps.version.outputs.version }}" -m "Release v${{ steps.version.outputs.version }}"
git push origin "v${{ steps.version.outputs.version }}"
- name: Generate release notes
if: steps.check_tag.outputs.exists == 'false'
id: release_notes
env:
RELEASE_VERSION: ${{ steps.version.outputs.version }}
MLX_TAG: ${{ steps.mlx_version.outputs.tag }}
MLX_COMMIT: ${{ steps.mlx_version.outputs.commit }}
run: |
PREVIOUS_TAG=$(git describe --abbrev=0 --tags $(git rev-list --tags --skip=1 --max-count=1) 2>/dev/null || echo "")
if [ -z "$PREVIOUS_TAG" ]; then
COMMITS=$(git log --pretty=format:"- %s (%h)" --reverse)
else
COMMITS=$(git log ${PREVIOUS_TAG}..HEAD --pretty=format:"- %s (%h)" --reverse)
fi
echo "## What's Changed" > release_notes.md
echo "" >> release_notes.md
echo "$COMMITS" >> release_notes.md
echo "" >> release_notes.md
echo "## Upstream MLX" >> release_notes.md
echo "- Version: ${MLX_TAG}" >> release_notes.md
echo "- Commit: ${MLX_COMMIT}" >> release_notes.md
echo "" >> release_notes.md
echo "## NuGet Packages" >> release_notes.md
echo "- [MLXSharp v${RELEASE_VERSION}](https://www.nuget.org/packages/MLXSharp/${RELEASE_VERSION})" >> release_notes.md
echo "- [MLXSharp.SemanticKernel v${RELEASE_VERSION}](https://www.nuget.org/packages/MLXSharp.SemanticKernel/${RELEASE_VERSION})" >> release_notes.md
cat release_notes.md
- name: Create GitHub Release
if: steps.check_tag.outputs.exists == 'false'
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.version.outputs.version }}
name: Release v${{ steps.version.outputs.version }}
body_path: release_notes.md
files: artifacts/packages/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}