diff --git a/.github/workflows/gpu_ci_trigger.yml b/.github/workflows/gpu_ci_trigger.yml index 7f7a8e7..80d4415 100644 --- a/.github/workflows/gpu_ci_trigger.yml +++ b/.github/workflows/gpu_ci_trigger.yml @@ -63,8 +63,10 @@ jobs: # 3. Add GitLab SSH remote git remote add gitlab git@gitlab.mpcdf.mpg.de:maxlin/cunumpy.git - # 4. Force push (This automatically starts the GitLab Pipeline) - git push -f gitlab "HEAD:refs/heads/$TARGET_BRANCH" + # 4. Force push (This automatically starts the GitLab Pipeline). The pushed branch + # is gpu-test-*, so pass the target branch for the max-models dependencies. + git push -f -o ci.variable="MAX_MODELS_TARGET=${{ github.base_ref || github.ref_name }}" \ + gitlab "HEAD:refs/heads/$TARGET_BRANCH" echo "PUSHED_SHA=$(git rev-parse HEAD)" >> "$GITHUB_ENV" # 5. Provide the direct link diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index b13bab3..388d28f 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -43,6 +43,8 @@ jobs: - name: Install project run: | pip install --upgrade pip + # devel branches of the max-models dependencies, except on runs that target main + if [ "${GITHUB_BASE_REF:-$GITHUB_REF_NAME}" != main ]; then python -m pip install -r requirements-devel.txt; fi pip install ".[test-compiled,metal]" # Hosted macOS runners are virtual machines and usually have no Metal GPU, diff --git a/.github/workflows/pyodide.yml b/.github/workflows/pyodide.yml index dc35744..c431dee 100644 --- a/.github/workflows/pyodide.yml +++ b/.github/workflows/pyodide.yml @@ -6,6 +6,8 @@ on: pull_request: branches: [main, devel] +# PyPI only, also on devel: micropip, which installs the wheel's dependencies in Pyodide, +# cannot install from git. jobs: wheel-test: runs-on: ubuntu-latest diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 02b58a7..ae0eb4d 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -82,6 +82,7 @@ jobs: - name: Docstring sections with numpydoc run: | + if [ "${GITHUB_BASE_REF:-$GITHUB_REF_NAME}" != main ]; then python -m pip install -r requirements-devel.txt; fi pip install . numpydoc python -m numpydoc lint $(git ls-files 'src/cunumpy/*.py' 'src/cunumpy/**/*.py' | grep -v _fake_cupy) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 0f4d562..1676664 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -10,6 +10,8 @@ on: - devel workflow_call: +# Runs that do not target main install the devel branches of the max-models dependencies +# (requirements-devel.txt) before cunumpy; PRs to main and the release use PyPI only. jobs: compiled-fake-cupy: runs-on: ubuntu-latest @@ -22,6 +24,7 @@ jobs: run: | sudo apt-get update sudo apt-get install -y gcc gfortran + if [ "${GITHUB_BASE_REF:-$GITHUB_REF_NAME}" != main ]; then python -m pip install -r requirements-devel.txt; fi python -m pip install ".[test-compiled]" - name: Test compiled host kernels with fake device arrays env: @@ -61,6 +64,7 @@ jobs: - name: Install project run: | pip install --upgrade pip + if [ "${GITHUB_BASE_REF:-$GITHUB_REF_NAME}" != main ]; then python -m pip install -r requirements-devel.txt; fi pip install ".[dev]" - name: Run tests @@ -70,3 +74,18 @@ jobs: - name: Run docstring examples run: | pytest --doctest-modules src/cunumpy + + # PyPI rejects direct references (`name @ git+...`): the wheel's metadata must have none. + no-direct-references: + if: (github.base_ref || github.ref_name) == 'main' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Check the wheel for direct references + run: | + python -m pip install build + python -m build --wheel + ! unzip -p dist/*.whl '*.dist-info/METADATA' | grep -E '^Requires-Dist:.* @ ' diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1d852e4..cba3e93 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,6 +14,13 @@ variables: stages: - test +# Runs that do not target main install the devel branches of the max-models dependencies +# first; main uses PyPI only. The GitHub trigger pushes gpu-test-* branches and passes the +# target branch in MAX_MODELS_TARGET. +.install_devel_dependencies: &install_devel_dependencies + - TARGET="${MAX_MODELS_TARGET:-${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-$CI_COMMIT_BRANCH}}" + - if [ "$TARGET" != main ]; then python3 -m pip install --user -r requirements-devel.txt; fi + .gpu_job_nvidia: stage: test image: ${CUDA_IMAGE} @@ -27,6 +34,7 @@ stages: - nvidia-smi # Keep NVRTC, CUDA libraries and headers on the same toolkit generation. - python3 -m pip install --user "cupy-cuda13x[ctk]${CUPY_PIN}" "cuda-toolkit==13.2.*" + - *install_devel_dependencies - python3 -m pip install --user -e ".[test]" - export PATH="$HOME/.local/bin:$PATH" - python3 -c "import cupy; cupy.show_config()" @@ -49,6 +57,7 @@ stages: - export ROCM_HOME="${ROCM_PATH:-/opt/rocm}" - export CUPY_INSTALL_USE_HIP=1 - python3 -m pip install --user "cupy${CUPY_PIN}" + - *install_devel_dependencies - python3 -m pip install --user -e ".[test]" - export PATH="$HOME/.local/bin:$PATH" - python3 -c "import cupy; cupy.show_config()" diff --git a/docs/src/content/docs/getting-started/installation.md b/docs/src/content/docs/getting-started/installation.md index 5a04447..7653a25 100644 --- a/docs/src/content/docs/getting-started/installation.md +++ b/docs/src/content/docs/getting-started/installation.md @@ -88,6 +88,11 @@ python -m pytest tests/unit Tests that need a GPU are skipped automatically where CuPy is not functional. +On `devel`, cunumpy is developed against the `devel` branches of the other max-models packages +(currently maybempi): `uv sync` picks them up from `[tool.uv.sources]`, and with pip run +`python -m pip install -r requirements-devel.txt` before the install above. CI does the same for +pull requests to `devel`; pull requests to `main` and the PyPI release use PyPI versions only. + ## Environment variables | Variable | Effect | diff --git a/pyproject.toml b/pyproject.toml index f70ac73..34c15e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,11 @@ where = [ "src" ] [tool.setuptools.package-data] cunumpy = [ "py.typed", "*.pyi", "LLM_GUIDE.md", "cuda/include/cunumpy/*.cuh" ] +# PRs to devel test against the devel branches of the max-models packages; PRs to main +# and the release use PyPI only. +[tool.uv.sources] +maybempi = { git = "https://github.com/max-models/maybempi", branch = "devel" } + [tool.ruff] # agent worktrees and scratch scripts are local copies, not part of the project extend-exclude = [ ".claude" ] diff --git a/requirements-devel.txt b/requirements-devel.txt new file mode 100644 index 0000000..ab53722 --- /dev/null +++ b/requirements-devel.txt @@ -0,0 +1,4 @@ +# The devel branches of the max-models packages in cunumpy's dependency tree. CI installs +# them before cunumpy on every run that does not target main; main and the release use PyPI. +# pip install -r requirements-devel.txt +maybempi @ git+https://github.com/max-models/maybempi@devel