Skip to content

QInt4 radix-sort keys (Ascending/DescendingQInt4) + fix QInt4-CONSTAN… #87

QInt4 radix-sort keys (Ascending/DescendingQInt4) + fix QInt4-CONSTAN…

QInt4 radix-sort keys (Ascending/DescendingQInt4) + fix QInt4-CONSTAN… #87

name: T4 Drift Check
# Catches the recurring "ILGPU/*.cs edited manually but matching .tt template
# wasn't updated" trap that has bitten this repo at least 3 times (most recently
# 2026-04-25, when CapabilityContext.cs's manual Float16Native additions blocked
# the GitHub Pages deploy with 9 OpenCL compile errors).
#
# The trap: local incremental builds skip T4 transforms, so manual .cs edits
# build clean and ship. Then a fresh-clone clean build (CI, deploy, new dev
# laptop) runs T4 first thing, regenerates .cs WITHOUT the manual edits, and
# downstream consumers fail to compile.
#
# This workflow forces the trap to surface on every push: it does what CI does
# (clean build, T4 transforms run) and fails if any .cs file under ILGPU/
# differs from what's committed. The fix is always the same: port the manual
# edit to the matching .tt template, regen the .cs, commit both in sync.
on:
push:
branches: [master]
paths:
- 'ILGPU/**'
- 'ILGPU.Algorithms/**'
- '.github/workflows/tt-drift-check.yml'
pull_request:
branches: [master]
paths:
- 'ILGPU/**'
- 'ILGPU.Algorithms/**'
- '.github/workflows/tt-drift-check.yml'
workflow_dispatch:
jobs:
check-drift:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
- name: Force clean build of ILGPU/ (runs T4 transforms fresh)
# -p:TextTemplateTransformSkipUpToDate=false bypasses T4.Build's --skip-up-to-date
# check. On fresh CI clones all mtimes are equal so T4 runs anyway, but setting the
# flag explicitly keeps CI behavior identical to the local _check-tt-drift.bat
# which DOES need the flag (working-tree .cs mtimes are typically newer than .tt).
run: |
rm -rf ILGPU/obj ILGPU/bin ILGPU.Algorithms/obj ILGPU.Algorithms/bin
dotnet build ILGPU/ILGPU.csproj -c Release --nologo -p:TextTemplateTransformSkipUpToDate=false
- name: Verify no .tt template drift
shell: bash
run: |
set -e
# Anything modified by the build that ISN'T in obj/bin is .tt regen output.
# Restrict the diff to source files; obj/ + bin/ + project.assets.json are
# build artifacts that always change.
drifted=$(git diff --name-only -- 'ILGPU/**' 'ILGPU.Algorithms/**' \
':!ILGPU/obj' ':!ILGPU/bin' ':!ILGPU.Algorithms/obj' ':!ILGPU.Algorithms/bin')
if [ -n "$drifted" ]; then
echo "::error::T4 template drift detected. The following .cs files"
echo "::error::were regenerated by the build and differ from what's committed:"
echo "$drifted" | while read f; do echo "::error:: $f"; done
echo ""
echo "Root cause: a .cs file in ILGPU/ was edited manually, but the"
echo "matching .tt template wasn't updated. Local incremental builds"
echo "passed because T4 didn't run; CI's clean build runs T4 fresh"
echo "and regenerates .cs without the manual edits."
echo ""
echo "Fix: port the manual .cs edit into the matching .tt template,"
echo "regen the .cs (run 'rm -rf ILGPU/obj && dotnet build ILGPU/'),"
echo "commit BOTH the .tt and the regenerated .cs in the same change."
echo ""
echo "See ILGPU/CLAUDE.md and Docs/development.md for the full pattern."
echo ""
echo "--- diff of drifted files ---"
git --no-pager diff -- 'ILGPU/**' 'ILGPU.Algorithms/**' \
':!ILGPU/obj' ':!ILGPU/bin' ':!ILGPU.Algorithms/obj' ':!ILGPU.Algorithms/bin'
exit 1
fi
echo "OK: no .tt template drift. Generated .cs files match committed state."