Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/actions/cubin-packs/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
name: Fetch the CUBIN packs
description: >
Pull the LFS-tracked CUBIN packs and nothing else, so a job that needs them
does not pay for the whole LFS store and no workflow repeats the pattern.

runs:
using: composite
steps:
# One home for the pattern. `.gitattributes` is the source of truth -- it is
# what marks these paths as LFS, and tests/contract/test_build_contract.py
# asserts the line -- and a copy that drifts from it fails quietly: the pull
# matches nothing, the packs stay pointers, and the error surfaces later as
# "is a Git LFS pointer" rather than as a stale glob.
#
# Callers check out with `lfs: false` and keep their credentials: this is an
# internal repo and the pull authenticates with the header checkout leaves in
# the local git config.
- shell: bash
env:
PACKS: cpp/kernels/cutedsl_*/cubins/packs/*.tar.xz
run: |
git lfs pull --include="${PACKS}"
echo "materialized $(git lfs ls-files -I "${PACKS}" | wc -l) packs"
56 changes: 56 additions & 0 deletions .github/actions/prek/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
name: Set up prek
description: >
Install the prek pinned in requirements-dev.txt and restore its hook
environments, so a job runs the same hook versions a contributor gets from
`pip install -e '.[dev]'`.

inputs:
cache:
description: >
Restore and save the hook environments. Worth it for a job that builds
every hook in prek.toml; for one that builds a single hook the round trip
costs about what the build does.
default: 'true'

runs:
using: composite
steps:
# requirements-dev.txt owns the pin; reading it here keeps CI from drifting
# away from what `.[dev]` installs.
- name: Resolve the pinned prek version
id: pin
shell: bash
run: |
version=$(sed -n 's/^prek==\([^ #]*\).*/\1/p' requirements-dev.txt)
if [[ -z "${version}" ]]; then
echo "::error file=requirements-dev.txt::no 'prek==<version>' pin found"
exit 1
fi
echo "version=${version}" >>"${GITHUB_OUTPUT}"

- uses: ./.github/actions/python

# prek builds one environment per hook repo under its cache root. Keying on
# prek.toml means a bumped `rev` builds fresh environments instead of reusing
# the ones pinned to the old revision, and `restore-keys` then hands that
# build the environments for the hooks that did *not* move -- prek's cache is
# keyed per repo+rev on disk, so a partial restore is additive, never stale.
# Without it, editing one `exclude` line rebuilds all nine.
- uses: actions/cache@v6
if: inputs.cache == 'true'
with:
path: ~/.cache/prek
key: prek-${{ runner.os }}-${{ steps.pin.outputs.version }}-${{ hashFiles('prek.toml') }}
restore-keys: |
prek-${{ runner.os }}-${{ steps.pin.outputs.version }}-

# Through the environment, never interpolated into the script: this value is
# read out of the pull request's own requirements-dev.txt, and `${{ }}`
# expands before bash ever sees it.
# https://docs.github.com/en/actions/reference/security/secure-use
- shell: bash
env:
PREK_VERSION: ${{ steps.pin.outputs.version }}
run: pip install "prek==${PREK_VERSION}"
30 changes: 30 additions & 0 deletions .github/actions/python/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
name: Set up Python
description: >
Install the oldest Python pyproject.toml supports, so every job agrees on one
interpreter and none of them repeats the version.

runs:
using: composite
steps:
# The floor, not `python-version-file: pyproject.toml`. That input resolves a
# range to the *highest* match, and `requires-python` is ">=3.12,<4.0", so it
# would build the extension against whatever 3.x the runner ships. The wheel
# this repo publishes is cp312 -- docker/Dockerfile builds it on
# nvcr.io/nvidia/pytorch, whose python is 3.12 -- and a gate that compiles a
# different ABI than the one shipped is not the gate docs/dev.md promises.
- name: Resolve the requires-python floor
id: floor
shell: bash
run: |
version=$(sed -n 's/^requires-python *= *"[^0-9]*\([0-9]*\.[0-9]*\).*/\1/p' pyproject.toml)
if [[ -z "${version}" ]]; then
echo "::error file=pyproject.toml::no 'requires-python' floor found"
exit 1
fi
echo "version=${version}" >>"${GITHUB_OUTPUT}"

- uses: actions/setup-python@v7
with:
python-version: ${{ steps.floor.outputs.version }}
88 changes: 88 additions & 0 deletions .github/scripts/check-dco.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Enforce the Developer Certificate of Origin on every commit a pull request
# adds: each needs a Signed-off-by trailer carrying the author's own address,
# which is what `git commit -s` writes. See CONTRIBUTING.md.
#
# Usage: check-dco.sh <base-sha> <head-sha>
set -euo pipefail

if (($# != 2)); then
echo "usage: check-dco.sh <base-sha> <head-sha>" >&2
exit 2
fi
base="$1"
head="$2"

# The base of a pull request is the tip of the target branch, which moves on
# without the branch. Only commits after the fork point belong to this PR, so
# ask git where the two diverged rather than diffing against the tip.
if ! merge_base="$(git merge-base "${base}" "${head}")"; then
echo "cannot find a merge base for ${base} and ${head} -- was the branch" \
"checked out with fetch-depth: 0?" >&2
exit 2
fi

# --no-merges: a merge from the target branch carries no contribution of its
# own, and the merge commits GitHub itself writes are never signed off.
#
# Read in a `while` over a process substitution rather than `mapfile`, which
# bash 3.2 -- what macOS still ships, and what a contributor testing this
# locally runs -- does not have.
checked=0
failed=0
while read -r sha; do
checked=$((checked + 1))
author_email="$(git show --no-patch --format='%ae' "${sha}")"
subject="$(git show --no-patch --format='%s' "${sha}")"
# Trailers only. A "Signed-off-by:" written into the middle of a commit body
# is prose, and git does not treat it as a sign-off either.
signoffs="$(git show --no-patch --format='%(trailers:key=Signed-off-by,valueonly)' "${sha}")"
if grep -qiF "<${author_email}>" <<<"${signoffs}"; then
echo "ok ${sha:0:12} ${subject}"
continue
fi
failed=1
echo "FAIL ${sha:0:12} ${subject}"
if [[ -z "${signoffs//[[:space:]]/}" ]]; then
echo " no Signed-off-by trailer"
else
echo " signed off by ${signoffs//$'\n'/, }, but authored by <${author_email}>"
fi
done < <(git rev-list --no-merges "${merge_base}..${head}")

if ((checked == 0)); then
echo "no commits to check between ${merge_base:0:12} and ${head:0:12}"
exit 0
fi
((failed)) || exit 0

cat >&2 <<EOF

Every commit must carry a Signed-off-by trailer matching its author address,
certifying the Developer Certificate of Origin (https://developercertificate.org/).

Set the identity git records, then sign off the whole branch:

git config user.name "Your Name"
git config user.email "your@email.com"
git rebase --signoff ${merge_base:0:12}
git push --force-with-lease

New commits pick it up from \`git commit -s\`. See CONTRIBUTING.md.
EOF
exit 1
73 changes: 73 additions & 0 deletions .github/scripts/check-pr-title.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Check a pull-request title against the Conventional Commits rule prek's
# commit-msg hook applies to commit messages. PRs are squash-merged with
# `squash_merge_commit_title = PR_TITLE`, so this title is the subject of the
# commit that lands on main -- the same gate, moved to where it will be read.
# The repo setting is load-bearing: the `COMMIT_OR_PR_TITLE` default would use
# the branch's own subject whenever a PR carries exactly one commit, and that
# subject is linted only by the commit-msg hook, which is opt-in.
#
# The check is prek itself, so commitizen's version and configuration stay
# single-sourced in prek.toml and pyproject.toml. AGENTS.md allows an optional
# tracker reference in front of the summary; commitizen anchors its pattern at
# the start of the message and would reject one, so strip it first.
#
# Usage: check-pr-title.sh "<title>"
set -euo pipefail

if (($# != 1)); then
echo "usage: check-pr-title.sh <title>" >&2
exit 2
fi
title="$1"

# `[PROJ-123]` (JIRA key) or `[5123456]` (NVBug ID), and the space behind it.
summary="${title}"
if [[ "${summary}" =~ ^\[([A-Za-z][A-Za-z0-9]*-)?[0-9]+\][[:space:]]*(.*)$ ]]; then
summary="${BASH_REMATCH[2]}"
fi

# commitizen reads the message from a file, the way the commit-msg hook feeds it
# .git/COMMIT_EDITMSG.
message_file="$(mktemp)"
trap 'rm -f "${message_file}"' EXIT
printf '%s\n' "${summary}" >"${message_file}"

echo "checking title: ${title}"
if [[ "${summary}" != "${title}" ]]; then
echo "tracker reference stripped, checking: ${summary}"
fi

if prek run commitizen --stage commit-msg --commit-msg-filename "${message_file}"; then
exit 0
fi

cat >&2 <<'EOF'

The pull request title must be a Conventional Commits subject, optionally
preceded by a tracker reference:

feat: add a triangle-attention fallback for sm80
fix(pipeline): stop dropping the last MSA row
[PROJ-123] docs: describe the CUBIN pack layout

Types: build, bump, chore, ci, docs, feat, fix, perf, refactor, revert, style,
test. Append `!` before the colon for a breaking change. See AGENTS.md and
docs/coding.md, and edit the title -- this check re-runs on its own.
EOF
exit 1
Loading