Use default setuptools-scm tag parsing #82
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # | |
| # SPDX-License-Identifier: Apache-2.0 | |
| # Fails when a committed pixi.lock is out of date with its pixi.toml, or when | |
| # its bytes are not what the pinned pixi version generates. | |
| # Remediation for both: regenerate and commit the lockfile with that pixi | |
| # version, e.g. | |
| # pixi lock --manifest-path <path> | |
| # Keep this check advisory during its initial rollout. Before making it | |
| # required, expose a stable aggregate check, account for the path filters, and | |
| # record the decision in #2804 after the workflow has operational history. | |
| # See #2298. | |
| name: "CI: pixi lockfile freshness check" | |
| concurrency: | |
| # Keyed on the event as well as the ref so a manual dispatch and a push to | |
| # the same branch do not cancel each other. | |
| group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} | |
| cancel-in-progress: true | |
| on: | |
| pull_request: | |
| # `pyproject.toml` is a lockfile input too: the manifests consume sibling | |
| # packages (including cuda_python_test_helpers) as path dependencies, so | |
| # their metadata can stale a lock without any pixi.toml edit. Matched by | |
| # glob rather than by name so the filter cannot drift as packages move. | |
| paths: &lockfile_inputs | |
| - "**/pixi.toml" | |
| - "**/pixi.lock" | |
| - "**/pyproject.toml" | |
| - "ci/tools/list_pixi_workspaces.py" | |
| - "ci/pixi-version.env" | |
| - ".github/actions/setup-pixi/action.yml" | |
| - ".github/workflows/ci-pixi-lockfile-freshness-check.yml" | |
| push: | |
| # `pull_request` already covers PRs, including those from forks: this check | |
| # needs no secrets or GPU runner. Watching copy-pr-bot's `pull-request/N` | |
| # mirror too would run the whole check a second time per PR. | |
| branches: | |
| - "main" | |
| paths: *lockfile_inputs | |
| workflow_dispatch: {} | |
| defaults: | |
| run: | |
| shell: bash --noprofile --norc -xeuo pipefail {0} | |
| env: | |
| REFRESH_WORKFLOW_URL: "https://github.com/NVIDIA/cuda-python/actions/workflows/ci-pixi-lockfile-refresh.yml" | |
| permissions: {} | |
| jobs: | |
| lockfile-fresh: | |
| name: pixi lock --check (all workspaces) | |
| if: ${{ github.repository_owner == 'nvidia' }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 135 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout ${{ github.event.repository.name }} | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Setup pixi | |
| id: setup-pixi | |
| uses: ./.github/actions/setup-pixi | |
| # `pixi lock --check` exits 0 on a semantically current lock even when it | |
| # rewrites the file into the pinned version's canonical form (lockfile | |
| # format upgrades, platform alias renames). Without this guard that drift | |
| # is invisible: the check prints "Updated lock file" and still passes, | |
| # while every later pixi run keeps rewriting the committed file (#2298). | |
| - name: Check all lockfiles | |
| env: | |
| PIXI_VERSION: ${{ steps.setup-pixi.outputs.pixi-version }} | |
| WORKSPACE_TIMEOUT: 20m | |
| run: | | |
| workspaces="$(python3 ci/tools/list_pixi_workspaces.py)" | |
| workspace_rows="$( | |
| jq -ce ' | |
| if type != "array" or length == 0 then | |
| error("workspace inventory must be a non-empty array") | |
| elif any(.[]; | |
| type != "object" | |
| or (.manifest | type != "string") | |
| or (.lockfile | type != "string") | |
| or .manifest == "" | |
| or .lockfile == "" | |
| ) then | |
| error("each workspace must have non-empty string manifest and lockfile fields") | |
| else | |
| .[] | |
| end | |
| ' <<<"${workspaces}" | |
| )" | |
| failed=0 | |
| while IFS= read -r workspace; do | |
| manifest="$(jq -r '.manifest' <<<"${workspace}")" | |
| lockfile="$(jq -r '.lockfile' <<<"${workspace}")" | |
| echo "::group::pixi lock --check (${manifest})" | |
| check_status=0 | |
| timeout --kill-after=1m "${WORKSPACE_TIMEOUT}" \ | |
| pixi lock --check --manifest-path "${manifest}" \ | |
| || check_status=$? | |
| if ((check_status == 124 || check_status == 137)); then | |
| echo "::error::Timed out after ${WORKSPACE_TIMEOUT} while checking '${manifest}'." | |
| failed=1 | |
| elif ((check_status != 0)); then | |
| echo "::error::Lockfile is stale for '${manifest}'. Regenerate with: pixi lock --manifest-path ${manifest}. For default-branch dependency drift, maintainers can run ${REFRESH_WORKFLOW_URL}" | |
| failed=1 | |
| elif ! git diff --exit-code -- "${lockfile}"; then | |
| echo "::error::pixi ${PIXI_VERSION} rewrote ${lockfile} during the check, so the committed bytes are not what it generates. Regenerate with pixi ${PIXI_VERSION}: pixi lock --manifest-path ${manifest}. For default-branch dependency drift, maintainers can run ${REFRESH_WORKFLOW_URL}" | |
| failed=1 | |
| fi | |
| echo "::endgroup::" | |
| done <<<"${workspace_rows}" | |
| exit "${failed}" |