@@ -103,6 +103,7 @@ jobs:
103103 test_bindings : ${{ steps.compose.outputs.test_bindings }}
104104 test_core : ${{ steps.compose.outputs.test_core }}
105105 test_pathfinder : ${{ steps.compose.outputs.test_pathfinder }}
106+ pr_merge_base : ${{ steps.filter.outputs.merge_base }}
106107 steps :
107108 - name : Checkout repository
108109 uses : actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -156,6 +157,7 @@ jobs:
156157 echo "python_meta=$(has_match '^cuda_python/')"
157158 echo "test_helpers=$(has_match '^cuda_python_test_helpers/')"
158159 echo "shared=$(has_match '^(\.github/|ci/|scripts/|toolshed/|conftest\.py$|pyproject\.toml$|pixi\.(toml|lock)$|pytest\.ini$|ruff\.toml$)')"
160+ echo "merge_base=${base}"
159161 } >> "$GITHUB_OUTPUT"
160162
161163 - name : Compose gating outputs
@@ -228,6 +230,89 @@ jobs:
228230 echo "test_pathfinder=${test_pathfinder}"
229231 } >> "$GITHUB_OUTPUT"
230232
233+ api-check-core-vs-release :
234+ name : API check (cuda_core vs. latest release)
235+ if : >-
236+ ${{ !fromJSON(needs.should-skip.outputs.skip) &&
237+ fromJSON(needs.detect-changes.outputs.core) }}
238+ runs-on : ubuntu-latest
239+ needs :
240+ - should-skip
241+ - detect-changes
242+ permissions :
243+ contents : read
244+ steps :
245+ - name : Checkout repository
246+ uses : actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
247+ with :
248+ fetch-depth : 1
249+ filter : blob:none
250+
251+ - name : Find latest release tag
252+ id : latest-tag
253+ shell : bash --noprofile --norc -euo pipefail {0}
254+ env :
255+ GH_TOKEN : ${{ github.token }}
256+ run : |
257+ # --paginate fetches all pages; jq outputs one name per line per page;
258+ # head -1 takes the first (newest) match since GitHub returns tags
259+ # newest-first. Fails hard if no cuda-core-v* tag is found.
260+ tag="$(gh api "repos/$GITHUB_REPOSITORY/tags" --paginate \
261+ --jq '.[] | select(.name | startswith("cuda-core-v")) | .name' \
262+ | head -1)"
263+ if [[ -z "${tag}" ]]; then
264+ echo "::error::No cuda-core-v* tag found in the repository." >&2
265+ exit 1
266+ fi
267+ echo "tag=${tag}" >> "$GITHUB_OUTPUT"
268+
269+ - name : Fetch release tag
270+ shell : bash --noprofile --norc -euo pipefail {0}
271+ run : |
272+ git fetch --depth=1 --filter=blob:none origin \
273+ "refs/tags/${{ steps.latest-tag.outputs.tag }}:refs/tags/${{ steps.latest-tag.outputs.tag }}"
274+
275+ - name : Check cuda_core public API
276+ id : griffe
277+ uses : ./.github/actions/griffe-api-check
278+ with :
279+ package-name : cuda.core
280+ package-dir : cuda_core
281+ merge-base : ${{ steps.latest-tag.outputs.tag }}
282+
283+ api-check-core-vs-base :
284+ name : API check (cuda_core vs. merge base)
285+ if : >-
286+ ${{ startsWith(github.ref_name, 'pull-request/') &&
287+ !fromJSON(needs.should-skip.outputs.skip) &&
288+ fromJSON(needs.detect-changes.outputs.core) }}
289+ runs-on : ubuntu-latest
290+ needs :
291+ - should-skip
292+ - detect-changes
293+ permissions :
294+ contents : read
295+ steps :
296+ - name : Checkout repository
297+ uses : actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
298+ with :
299+ fetch-depth : 1
300+ filter : blob:none
301+
302+ - name : Fetch merge base commit
303+ shell : bash --noprofile --norc -euo pipefail {0}
304+ run : |
305+ git fetch --depth=1 --filter=blob:none origin \
306+ "${{ needs.detect-changes.outputs.pr_merge_base }}"
307+
308+ - name : Check cuda_core public API
309+ id : griffe
310+ uses : ./.github/actions/griffe-api-check
311+ with :
312+ package-name : cuda.core
313+ package-dir : cuda_core
314+ merge-base : ${{ needs.detect-changes.outputs.pr_merge_base }}
315+
231316 # NOTE: Build jobs are intentionally split by platform rather than using a single
232317 # matrix. This allows each test job to depend only on its corresponding build,
233318 # so faster platforms can proceed through build & test without waiting for slower
0 commit comments