Skip to content

CI

CI #4321

Workflow file for this run

name: CI
on:
workflow_dispatch: # Allows you to run this workflow manually from the Actions tab
push:
paths-ignore:
- '.github/workflows/deploy-site.yml'
- 'Docs/**'
- 'Site/**'
pull_request:
paths-ignore:
- '.github/workflows/deploy-site.yml'
- 'Docs/**'
- 'Site/**'
schedule:
# Run daily at 00:00 so we get notified if CI is broken before a pull request
# is submitted.
- cron: '0 0 * * *'
env:
DOTNET_NOLOGO: true
jobs:
# Check some basic style rules.
check-style:
# Do not run this job for pull requests where both branches are from the same repo.
# Jobs that depend on this one will be skipped too.
# This prevents duplicate CI runs for our own pull requests, whilst preserving the ability to
# run the CI for each branch push to a fork, and for each pull request originating from a fork.
if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || github.event_name == 'push' || github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id
needs:
- check-style-line-lengths
- check-style-line-endings
- check-style-copyright-headers
runs-on: ubuntu-latest
steps:
- run: echo "All style checks done"
check-style-line-lengths:
if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || github.event_name == 'push' || github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check line length
run: .github/workflows/Scripts/CheckLineLength.ps1 -path Src
check-style-line-endings:
if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || github.event_name == 'push' || github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check T4 line endings
run: .github/workflows/Scripts/CheckT4LineEndings.ps1 -path Src
check-style-copyright-headers:
if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || github.event_name == 'push' || github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup the latest .NET 8 SDK
uses: actions/[email protected]
with:
dotnet-version: 8.0.x
- name: Check Copyright Headers
run: |
dotnet run --configuration=Release -p:TreatWarningsAsErrors=true --project Tools/CopyrightUpdateTool
if [[ -z "$(git status --porcelain)" ]]; then
exit 0
else
git status --porcelain
exit 1
fi
# Setup the OS matrix so that CUDA tests do not run on forks, as it needs self-hosted runners.
# Skip running on macOS in most cases.
setup-os-matrix:
# Do not run this job for pull requests where both branches are from the same repo.
# Jobs that depend on this one will be skipped too.
# This prevents duplicate CI runs for our own pull requests, whilst preserving the ability to
# run the CI for each branch push to a fork, and for each pull request originating from a fork.
if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || github.event_name == 'push' || github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id
runs-on: ubuntu-latest
steps:
- name: Check if repo is fork
id: is-fork
run: echo "fork=$(gh api repos/${{ github.repository }} | jq .fork)" >> $GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Setup OS matrix
id: setup-os-matrix
run: |
os=("ubuntu-latest" "windows-latest")
# runs on macOS only if there is a push to master, or a tag is
# pushed, we do this since macOS builds last too long and ILGPU
# is rarely used on a macOS
(
[ "${{ github.event_name }}" == "workflow_dispatch" ] ||
[ "${{ github.event_name }}" == "schedule" ] ||
(
[ "${{ github.event_name }}" == "push" ] &&
(
[ "${{ github.ref }}" == "refs/heads/master" ] ||
[[ "${{ github.ref }}" =~ "refs/tags/v" ]]
)
)
) && os+=("macos-latest")
[ "${{ steps.is-fork.outputs.fork }}" == "false" ] && os+=("cuda")
echo "os=$(jq -cn '$ARGS.positional' --args ${os[@]})" >> $GITHUB_OUTPUT
outputs:
os: ${{ steps.setup-os-matrix.outputs.os }}
# Check that building the entire solution for all target frameworks works.
build:
# Do not run this job for pull requests where both branches are from the same repo.
# Jobs that depend on this one will be skipped too.
# This prevents duplicate CI runs for our own pull requests, whilst preserving the ability to
# run the CI for each branch push to a fork, and for each pull request originating from a fork.
if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || github.event_name == 'push' || github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id
runs-on: windows-latest
strategy:
matrix:
path: [Src, Samples, Tools]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup the latest .NET 8 SDK
uses: actions/[email protected]
with:
dotnet-version: 8.0.x
- name: Build
run: dotnet build ${{ matrix.path }} --configuration=Release -p:TreatWarningsAsErrors=true
# Run tests for all supported combinations of OS/library/framework.
test-library:
needs: setup-os-matrix
strategy:
matrix:
os: ${{ fromJson(needs.setup-os-matrix.outputs.os) }}
library: [ILGPU, ILGPU.Algorithms, ILGPU.Analyzers]
framework: [net6.0, net7.0, net8.0]
flavor: [CPU, Velocity, Velocity128]
exclude:
- library: ILGPU.Algorithms
flavor: Velocity
- library: ILGPU.Algorithms
flavor: Velocity128
- library: ILGPU.Analyzers
flavor: Velocity
- library: ILGPU.Analyzers
flavor: Velocity128
- os: cuda
flavor: Velocity
- os: cuda
flavor: Velocity128
- os: cuda
library: ILGPU.Analyzers
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup the latest .NET 6 SDK
if: matrix.framework == 'net6.0'
uses: actions/[email protected]
with:
dotnet-version: 6.0.x
- name: Setup the latest .NET 7 SDK
if: matrix.framework == 'net7.0'
uses: actions/[email protected]
with:
dotnet-version: 7.0.x
- name: Setup the latest .NET 8 SDK
uses: actions/[email protected]
with:
dotnet-version: 8.0.x
- name: Set test flavor
id: test-flavor
shell: bash
run: |
flavor="Tests.${{ matrix.flavor }}"
[[ "${{ matrix.os }}" == cuda ]] && flavor="Tests.Cuda"
[[ "${{ matrix.library }}" == "ILGPU.Analyzers" ]] && flavor="Tests"
echo "flavor=$flavor" >> $GITHUB_OUTPUT
- name: Build and test
run: dotnet test Src/${{ matrix.library }}.${{ steps.test-flavor.outputs.flavor }} --configuration=Release --framework=${{ matrix.framework }} -p:TreatWarningsAsErrors=true
env:
ILGPU_CLEAN_TESTS: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || (github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v'))) }}
# Ensure that ILGPU libraries are built using the same version tag.
check-version:
# Do not run this job for pull requests where both branches are from the same repo.
# Jobs that depend on this one will be skipped too.
# This prevents duplicate CI runs for our own pull requests, whilst preserving the ability to
# run the CI for each branch push to a fork, and for each pull request originating from a fork.
if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || github.event_name == 'push' || github.event.pull_request.head.repo.id != github.event.pull_request.base.repo.id
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check version
id: version
shell: pwsh
run: |
$xpath = "/Project/PropertyGroup/LibraryVersionPrefix/text()"
$main_version = (Select-Xml -path Src/Directory.Build.props -XPath $xpath).Node.Value
if ("${{ github.ref }}" -like "refs/tags/v*") {
$tag = "${{ github.ref }}".SubString(11)
if (-not ($tag -eq $main_version)) {
echo "::error ::There is a mismatch between the project version ($main_version) and the tag ($tag)"
exit 1
}
}
if (-not ("${{ github.ref }}" -like "refs/tags/v*")) {
$suffix = "preview-$(Get-Date -Format yyyyMMddHHmmss -AsUTC)-$(git rev-parse --short HEAD)"
$main_version = "$main_version-$suffix"
}
echo "version=$main_version" >> $env:GITHUB_OUTPUT
echo "suffix=$suffix" >> $env:GITHUB_OUTPUT
outputs:
version: ${{ steps.version.outputs.version }}
suffix: ${{ steps.version.outputs.suffix }}
# Create the NuGet packages, with fixes for portable symbols.
package-library:
needs: check-version
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup the latest .NET 8 SDK
uses: actions/[email protected]
with:
dotnet-version: 8.0.x
- name: Create NuGet packages
run: |
$suffix = "${{ needs.check-version.outputs.suffix }}"
if ([bool]$suffix) {
$params = "--version-suffix", $suffix
}
dotnet pack Src --configuration=Release @params
- name: Upload NuGet package artifacts
uses: actions/upload-artifact@v4
with:
name: nuget-packages
path: ./Bin/Release/ILGPU*.${{ needs.check-version.outputs.version }}.*nupkg
# Create the Samples zip file, replacing ILGPU project references with equivalent NuGet package references.
package-samples:
needs:
- check-version
- package-library
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup the latest .NET 8 SDK
uses: actions/[email protected]
with:
dotnet-version: 8.0.x
# Change the ILGPU project references to NuGet package references
- name: Update sample references
id: package
run: .github/workflows/Scripts/UpdateSampleReferences.ps1 -version "${{ needs.check-version.outputs.version }}" -suffix "${{ needs.check-version.outputs.suffix }}"
# Compress the Samples folder
- name: Compress samples
run: |
$artifactPath = "Samples-${{ needs.check-version.outputs.version }}.zip"
Compress-Archive .\Samples\* -DestinationPath $artifactPath
# Verify that the sample projects can compile after switching to NuGet references
- name: Download NuGet package artifact
uses: actions/download-artifact@v4
with:
name: nuget-packages
path: local-nuget-packages
- name: Compile sample projects
run: |
# Decompress sample projects into temp folder
$tempFolder = Join-Path $env:RUNNER_TEMP "TempSamples"
Expand-Archive "Samples-*.zip" -DestinationPath $tempFolder
# Add local nuget packages
# NB: We use a fully qualified path because relative paths are relative to the
# NuGet.Config file. This could either be the NuGet.Config file in the samples,
# or the global NuGet.Config file (if we did not create one in the samples)
pushd $tempFolder
$repoPath = Resolve-Path (Join-Path $env:GITHUB_WORKSPACE "local-nuget-packages")
dotnet nuget add source $repoPath --name "ILGPU Local NuGet Packages"
# Ensure sample projects can compile
dotnet build --configuration=Release -p:TreatWarningsAsErrors=true
popd
# Upload samples artifact (for version tags and master branch only)
- name: Upload Samples artifact
uses: actions/upload-artifact@v4
if: github.event_name == 'push' && !github.event.repository.fork && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v'))
with:
name: samples
path: ./Samples-*.zip
# Virtual job that can be configured as a required check before a PR can be
# merged.
# As GitHub considers a check as successful if it is skipped, we need to
# check its status in another workflow (check-required.yml) and create a
# check there.
all-required-checks-done:
needs:
- check-style
- build
- test-library
- package-library
- package-samples
runs-on: ubuntu-latest
steps:
- run: echo "All required checks done"
# Publish a preview version of the NuGet packages on feedz.io when there is
# a push to master.
publish-preview:
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && !github.event.repository.fork
needs: all-required-checks-done
runs-on: ubuntu-latest
steps:
- name: Download NuGet package artifact
uses: actions/download-artifact@v4
with:
name: nuget-packages
- name: Publish to FeedzIO
run: dotnet nuget push "*.nupkg" --api-key ${{ secrets.FEEDZIO_API_KEY }} --source https://f.feedz.io/ilgpu/preview/nuget/index.json
# Create a GitHub release and publish the NuGet packages to nuget.org when
# a tag is pushed.
publish-release:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && !github.event.repository.fork
# Depends explictly on the 'check-version' job so we can access its output
needs:
- all-required-checks-done
- check-version
runs-on: ubuntu-latest
steps:
- name: Download NuGet package artifact
uses: actions/download-artifact@v4
with:
name: nuget-packages
- name: Download Samples artifact
uses: actions/download-artifact@v4
with:
name: samples
# if tag contains "-" treat it as pre-release
# example: 1.0.0-beta1
- name: Create release
uses: softprops/action-gh-release@v2
with:
name: Release v${{ needs.check-version.outputs.version }}
draft: true
prerelease: ${{ contains(needs.check-version.outputs.version, '-') }}
files: |
*.nupkg
Samples-*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to NuGet
run: dotnet nuget push "*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json