Skip to content

Commit 8f342d7

Browse files
committed
Add pre-commit CI job and replace artifact-based generated-file checks
The check_generated_files.py pre-commit hook regenerates exports.h, version.h, and __init__.pyi from Python source without needing build artifacts. Add it (along with a version-consistency hook) to .pre-commit-config.yaml and run it in a new lightweight pre-commit CI job in both GitHub Actions and GitLab CI. This replaces the artifact-dependent git-diff checks: - GitHub: remove check-generated-files job, remove stubs check from check-build-docs-output - GitLab: slim check-generated-files down to docs-only, rename to check-generated-docs Move pre-commit hook scripts to tools/pre-commit-hooks/ for discoverability. Signed-off-by: Eric Shi <ershi@nvidia.com>
1 parent 46b1773 commit 8f342d7

File tree

7 files changed

+219
-145
lines changed

7 files changed

+219
-145
lines changed

.github/workflows/ci.yml

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,20 @@ jobs:
243243
docs/api_reference
244244
docs/language_reference
245245
246+
pre-commit:
247+
runs-on: ubuntu-latest
248+
steps:
249+
- name: Checkout repository
250+
uses: actions/checkout@v4
251+
- name: Install uv
252+
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86
253+
with:
254+
version: "0.8.23"
255+
- name: Set up Python
256+
run: uv python install
257+
- name: Run pre-commit
258+
run: uvx pre-commit run --all-files --show-diff-on-failure
259+
246260
check-build-docs-output:
247261
runs-on: ubuntu-latest
248262
needs: build-docs
@@ -260,40 +274,6 @@ jobs:
260274
run: >
261275
git diff --exit-code docs/api_reference docs/language_reference ||
262276
(echo "Please run build_docs.py (or download from $ARTIFACT_URL) and add docs/api_reference and docs/language_reference to your pull request." && false)
263-
- name: Check stubs
264-
env:
265-
ARTIFACT_URL: ${{ needs.build-docs.outputs.artifact-url }}
266-
run: >
267-
git diff --exit-code warp/__init__.pyi ||
268-
(echo "Please run build_docs.py (or download from $ARTIFACT_URL) and add warp/__init__.pyi to your pull request." && false)
269-
270-
check-generated-files:
271-
runs-on: ubuntu-latest
272-
needs: build-warp
273-
steps:
274-
- name: Checkout repository
275-
uses: actions/checkout@v4
276-
- name: Install uv
277-
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86
278-
with:
279-
version: "0.8.23"
280-
- name: Set up Python
281-
run: uv python install
282-
- name: Download native headers
283-
uses: actions/download-artifact@v4
284-
with:
285-
name: native-headers-ubuntu-x86_64
286-
path: warp/native/
287-
- name: Check version consistency
288-
run: uv run --no-project tools/ci/publishing/check_version_consistency.py --verbose
289-
- name: Check exports.h is committed
290-
run: >
291-
git diff --exit-code warp/native/exports.h ||
292-
(echo "Please run build_lib.py and add warp/native/exports.h to your pull request." && false)
293-
- name: Check version.h is committed
294-
run: >
295-
git diff --exit-code warp/native/version.h ||
296-
(echo "Please run build_lib.py and add warp/native/version.h to your pull request." && false)
297277
298278
check-unnamespaced-symbols:
299279
runs-on: ubuntu-latest

.gitlab-ci.yml

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -958,13 +958,12 @@ merge request docs:
958958
after_script:
959959
- echo "View the website at https://$CI_PROJECT_ROOT_NAMESPACE.$CI_PAGES_DOMAIN/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public/index.html"
960960

961-
# Merge requests: Ensure that exports.h, __init__.pyi, and docs reference files have been
961+
# Merge requests: Ensure that docs reference files generated by Sphinx have been
962962
# manually added to the MR if they are changed
963-
check generated files:
963+
check generated docs:
964964
stage: deploy
965965
image: $UV_TRIXIE_IMAGE
966966
needs:
967-
- job: linux-x86_64 build
968967
- job: merge request docs
969968
optional: true
970969
extends:
@@ -976,25 +975,12 @@ check generated files:
976975
when: on_failure
977976
expose_as: "Generated source files"
978977
paths:
979-
- warp/native/exports.h
980-
- warp/native/version.h
981-
- warp/__init__.pyi
982978
- docs/api_reference
983979
- docs/language_reference
984980
script:
985-
# Check version consistency across VERSION.md, config.py, and version.h
986-
- uv run tools/ci/publishing/check_version_consistency.py --verbose
987-
# Check that generated documentation files are committed
988-
- >
989-
git diff --exit-code warp/__init__.pyi docs/api_reference docs/language_reference ||
990-
(echo "Please run build_docs.py (or download from $CI_JOB_URL/artifacts/browse) and add modified files to your merge request." && false)
991-
# Check that generated native files are committed
992-
- >
993-
git diff --exit-code warp/native/exports.h ||
994-
(echo "Please run build_lib.py (or download from $CI_JOB_URL/artifacts/browse) and add warp/native/exports.h to your merge request." && false)
995981
- >
996-
git diff --exit-code warp/native/version.h ||
997-
(echo "Please run build_lib.py (or download from $CI_JOB_URL/artifacts/browse) and add warp/native/version.h to your merge request." && false)
982+
git diff --exit-code docs/api_reference docs/language_reference ||
983+
(echo "Please run build_docs.py (or download from $CI_JOB_URL/artifacts/browse) and add docs/api_reference and docs/language_reference to your merge request." && false)
998984
999985
# Build documentation and publish on GitLab
1000986
# This only runs in the default branch pipeline. The "pages" name is special for GitLab.

.pre-commit-config.yaml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,28 @@ ci:
55
autoupdate_branch: ""
66
autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate"
77
autoupdate_schedule: quarterly
8-
skip: []
8+
skip: [warp-check-generated-files]
99
submodules: false
1010

1111
# See https://pre-commit.com for more information
1212
# See https://pre-commit.com/hooks.html for more hooks
1313
repos:
14+
- repo: local
15+
hooks:
16+
- id: warp-check-generated-files
17+
name: "warp: regenerate generated files"
18+
entry: python tools/pre-commit-hooks/check_generated_files.py
19+
language: python
20+
# NOTE: ruff version must match ruff-pre-commit rev below to avoid formatting drift.
21+
additional_dependencies: [numpy, ruff==0.14.10]
22+
always_run: true
23+
pass_filenames: false
24+
- id: warp-check-version-consistency
25+
name: "warp: check version consistency"
26+
entry: python tools/pre-commit-hooks/check_version_consistency.py --verbose
27+
language: python
28+
always_run: true
29+
pass_filenames: false
1430
- repo: https://github.com/astral-sh/ruff-pre-commit
1531
# Ruff version.
1632
rev: v0.14.10

build_lib.py

Lines changed: 1 addition & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
import build_llvm
3939
import warp._src.build_dll as build_dll
4040
import warp.config as config
41-
from warp._src.context import export_builtins
41+
from warp._src.generated_files import generate_exports_header_file, generate_version_header
4242

4343

4444
def handle_ci_nightly_build(base_path: str) -> str | None:
@@ -92,40 +92,6 @@ def handle_ci_nightly_build(base_path: str) -> str | None:
9292
return dev_version_string
9393

9494

95-
def generate_version_header(base_path: str, version: str) -> None:
96-
"""Generate version.h with WP_VERSION_STRING macro."""
97-
version_header_path = os.path.join(base_path, "warp", "native", "version.h")
98-
current_year = datetime.date.today().year
99-
100-
copyright_notice = f"""/*
101-
* SPDX-FileCopyrightText: Copyright (c) {current_year} NVIDIA CORPORATION & AFFILIATES. All rights reserved.
102-
* SPDX-License-Identifier: Apache-2.0
103-
*
104-
* Licensed under the Apache License, Version 2.0 (the "License");
105-
* you may not use this file except in compliance with the License.
106-
* You may obtain a copy of the License at
107-
*
108-
* http://www.apache.org/licenses/LICENSE-2.0
109-
*
110-
* Unless required by applicable law or agreed to in writing, software
111-
* distributed under the License is distributed on an "AS IS" BASIS,
112-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
113-
* See the License for the specific language governing permissions and
114-
* limitations under the License.
115-
*/
116-
117-
"""
118-
119-
with open(version_header_path, "w") as f:
120-
f.write(copyright_notice)
121-
f.write("#ifndef WP_VERSION_H\n")
122-
f.write("#define WP_VERSION_H\n\n")
123-
f.write(f'#define WP_VERSION_STRING "{version}"\n\n')
124-
f.write("#endif // WP_VERSION_H\n")
125-
126-
print(f"Generated {version_header_path} with version {version}")
127-
128-
12995
def find_cuda_sdk() -> str | None:
13096
# check environment variables
13197
for env in ["WARP_CUDA_PATH", "CUDA_HOME", "CUDA_PATH"]:
@@ -249,45 +215,6 @@ def lib_name(name: str) -> str:
249215
return f"{name}.so"
250216

251217

252-
def generate_exports_header_file(base_path: str) -> None:
253-
"""Generates warp/native/exports.h, which lets built-in functions be callable from outside kernels."""
254-
export_path = os.path.join(base_path, "warp", "native", "exports.h")
255-
os.makedirs(os.path.dirname(export_path), exist_ok=True)
256-
257-
try:
258-
with open(export_path, "w") as f:
259-
copyright_notice = """/*
260-
* SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
261-
* SPDX-License-Identifier: Apache-2.0
262-
*
263-
* Licensed under the Apache License, Version 2.0 (the "License");
264-
* you may not use this file except in compliance with the License.
265-
* You may obtain a copy of the License at
266-
*
267-
* http://www.apache.org/licenses/LICENSE-2.0
268-
*
269-
* Unless required by applicable law or agreed to in writing, software
270-
* distributed under the License is distributed on an "AS IS" BASIS,
271-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
272-
* See the License for the specific language governing permissions and
273-
* limitations under the License.
274-
*/
275-
276-
"""
277-
f.write(copyright_notice)
278-
export_builtins(f)
279-
280-
print(f"Finished writing {export_path}")
281-
except FileNotFoundError:
282-
print(f"Error: The file '{export_path}' was not found.")
283-
except PermissionError:
284-
print(f"Error: Permission denied. Unable to write to '{export_path}'.")
285-
except OSError as e:
286-
print(f"Error: An OS-related error occurred: {e}")
287-
except Exception as e:
288-
print(f"An unexpected error occurred: {e}")
289-
290-
291218
def main(argv: list[str] | None = None) -> int:
292219
parser = argparse.ArgumentParser(
293220
description="Build Warp native libraries with optional CUDA, LLVM, and MathDx support",
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
"""Pre-commit hook that regenerates exports.h, version.h, and __init__.pyi.
17+
18+
These files are derived from warp/_src/context.py, warp/config.py, VERSION.md,
19+
and related source files. When those sources change, the generated files must be
20+
updated to match. This hook regenerates them in place; the pre-commit framework
21+
detects any modifications and blocks the commit so the developer can stage them.
22+
23+
Usage (pre-commit hook):
24+
Configured in .pre-commit-config.yaml with language: python
25+
and additional_dependencies: [numpy, ruff]
26+
"""
27+
28+
from __future__ import annotations
29+
30+
import os
31+
import subprocess
32+
import sys
33+
34+
# Ensure the repo root is on sys.path so warp is importable in the
35+
# pre-commit isolated virtualenv (which only has additional_dependencies).
36+
base_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
37+
sys.path.insert(0, base_path)
38+
39+
import warp # noqa: E402 — populates builtin_functions via builtins.py
40+
import warp.config # noqa: E402
41+
from warp._src.generated_files import export_stubs, generate_exports_header_file, generate_version_header # noqa: E402
42+
43+
44+
def main() -> int:
45+
# Regenerate warp/native/exports.h
46+
generate_exports_header_file(base_path)
47+
48+
# Regenerate warp/native/version.h
49+
generate_version_header(base_path, warp.config.version)
50+
51+
# Regenerate warp/__init__.pyi
52+
stub_path = os.path.join(base_path, "warp", "__init__.pyi")
53+
with open(stub_path, "w", encoding="utf-8") as f:
54+
export_stubs(f)
55+
56+
# Format with ruff so the generated file is stable across hook runs.
57+
# export_stubs() emits trailing whitespace and non-canonical formatting;
58+
# without this step, ruff-format would modify the file on every commit.
59+
# ruff is provided via additional_dependencies in .pre-commit-config.yaml.
60+
from ruff.__main__ import find_ruff_bin # noqa: PLC0415
61+
62+
ruff = find_ruff_bin()
63+
subprocess.run([ruff, "format", stub_path], check=True)
64+
subprocess.run([ruff, "check", "--fix", "--unsafe-fixes", stub_path], check=False)
65+
66+
return 0
67+
68+
69+
if __name__ == "__main__":
70+
raise SystemExit(main())

0 commit comments

Comments
 (0)