From 7b8c46cd84fb0e4b88da171c966e25636e81e9dd Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 27 Apr 2026 09:12:47 -0700 Subject: [PATCH 1/3] docs(pathfinder): prepare 1.5.4 release notes Add cuda-pathfinder 1.5.4 release notes and register 1.5.4 in nv-versions so the published docs include the new version entry. Made-with: Cursor --- cuda_pathfinder/docs/nv-versions.json | 4 ++++ .../docs/source/release/1.5.4-notes.rst | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 cuda_pathfinder/docs/source/release/1.5.4-notes.rst diff --git a/cuda_pathfinder/docs/nv-versions.json b/cuda_pathfinder/docs/nv-versions.json index 161f612d7b..379c772ebe 100644 --- a/cuda_pathfinder/docs/nv-versions.json +++ b/cuda_pathfinder/docs/nv-versions.json @@ -3,6 +3,10 @@ "version": "latest", "url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/latest/" }, + { + "version": "1.5.4", + "url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/1.5.4/" + }, { "version": "1.5.3", "url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/1.5.3/" diff --git a/cuda_pathfinder/docs/source/release/1.5.4-notes.rst b/cuda_pathfinder/docs/source/release/1.5.4-notes.rst new file mode 100644 index 0000000000..97853be7f3 --- /dev/null +++ b/cuda_pathfinder/docs/source/release/1.5.4-notes.rst @@ -0,0 +1,21 @@ +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-License-Identifier: Apache-2.0 + +.. py:currentmodule:: cuda.pathfinder + +``cuda-pathfinder`` 1.5.4 Release notes +======================================= + +Highlights +---------- + +* Add ``find_bitcode_lib("nccl_device")`` support. + (`PR #1975 `_) + +Internal maintenance +-------------------- + +* On Linux, make the ``.so`` glob fallback prefer the newest matching library + when an exact SONAME match is unavailable. This improves internal consistency + in rare fallback cases and is not expected to affect most users. + (`PR #1966 `_) From fd31eb24265e9f240bfc396cfc14e76487041f10 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 27 Apr 2026 10:18:28 -0700 Subject: [PATCH 2/3] fix(ci): harden backport run lookup for artifact downloads Backport artifact downloads were relying on `gh run list -w ci.yml -s success`, which can fail to return runs even when the branch has successful CI artifacts. Move the lookup into a shared helper that queries completed `CI` runs and filters for successful results explicitly, so Linux and Windows workflows resolve prior-branch bindings artifacts reliably. Made-with: Cursor --- .github/workflows/build-wheel.yml | 16 ++---- .github/workflows/test-wheel-linux.yml | 18 +++--- .github/workflows/test-wheel-windows.yml | 36 ++++++------ ci/tools/lookup-run-id-by-branch | 70 ++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 41 deletions(-) create mode 100644 ci/tools/lookup-run-id-by-branch diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index fbb8d092b0..f84e5f7670 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -401,18 +401,14 @@ jobs: OLD_BRANCH=$(yq '.backport_branch' ci/versions.yml) OLD_BASENAME="cuda-bindings-python${PYTHON_VERSION_FORMATTED}-cuda*-${{ inputs.host-platform }}*" - LATEST_PRIOR_RUN_ID=$(gh run list -b ${OLD_BRANCH} -L 1 -w "ci.yml" -s success -R NVIDIA/cuda-python --json databaseId | jq '.[]| .databaseId') - if [[ "$LATEST_PRIOR_RUN_ID" == "" ]]; then - echo "LATEST_PRIOR_RUN_ID not found!" - exit 1 - fi + LATEST_PRIOR_RUN_ID=$(bash ./ci/tools/lookup-run-id-by-branch "${OLD_BRANCH}" "${{ github.repository }}") - gh run download $LATEST_PRIOR_RUN_ID -p ${OLD_BASENAME} -R NVIDIA/cuda-python - rm -rf ${OLD_BASENAME}-tests # exclude cython test artifacts - ls -al $OLD_BASENAME + gh run download "${LATEST_PRIOR_RUN_ID}" -p "${OLD_BASENAME}" -R "${{ github.repository }}" + rm -rf "${OLD_BASENAME}-tests" # exclude cython test artifacts + ls -al "${OLD_BASENAME}" mkdir -p "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" - mv $OLD_BASENAME/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" - rmdir $OLD_BASENAME + mv "${OLD_BASENAME}"/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" + rmdir "${OLD_BASENAME}" - name: Build cuda.core wheel uses: pypa/cibuildwheel@ee02a1537ce3071a004a6b08c41e72f0fdc42d9a # v3.4.0 diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index 35c5e6c373..89adab3057 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -160,20 +160,16 @@ jobs: OLD_BRANCH=${{ needs.compute-matrix.outputs.OLD_BRANCH }} OLD_BASENAME="cuda-bindings-python${PYTHON_VERSION_FORMATTED}-cuda*-${{ inputs.host-platform }}*" - LATEST_PRIOR_RUN_ID=$(gh run list -b ${OLD_BRANCH} -L 1 -w "ci.yml" -s success -R NVIDIA/cuda-python --json databaseId | jq '.[]| .databaseId') - if [[ "$LATEST_PRIOR_RUN_ID" == "" ]]; then - echo "LATEST_PRIOR_RUN_ID not found!" - exit 1 - fi + LATEST_PRIOR_RUN_ID=$(bash ./ci/tools/lookup-run-id-by-branch "${OLD_BRANCH}" "${{ github.repository }}") - gh run download $LATEST_PRIOR_RUN_ID -p ${OLD_BASENAME} -R NVIDIA/cuda-python - rm -rf ${OLD_BASENAME}-tests # exclude cython test artifacts - ls -al $OLD_BASENAME + gh run download "${LATEST_PRIOR_RUN_ID}" -p "${OLD_BASENAME}" -R "${{ github.repository }}" + rm -rf "${OLD_BASENAME}-tests" # exclude cython test artifacts + ls -al "${OLD_BASENAME}" mkdir -p "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" - mv $OLD_BASENAME/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}"/ - rmdir $OLD_BASENAME + mv "${OLD_BASENAME}"/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}"/ + rmdir "${OLD_BASENAME}" - gh run download $LATEST_PRIOR_RUN_ID -p cuda-python-wheel -R NVIDIA/cuda-python + gh run download "${LATEST_PRIOR_RUN_ID}" -p cuda-python-wheel -R "${{ github.repository }}" ls -al cuda-python-wheel mv cuda-python-wheel/*.whl . rmdir cuda-python-wheel diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 765823c6bf..084d3a7c89 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -142,27 +142,23 @@ jobs: if: ${{ env.USE_BACKPORT_BINDINGS == '1' }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash --noprofile --norc -xeuo pipefail {0} run: | - $OLD_BRANCH = yq '.backport_branch' ci/versions.yml - $OLD_BASENAME = "cuda-bindings-python${env:PYTHON_VERSION_FORMATTED}-cuda*-${{ inputs.host-platform }}*" - $runData = gh run list -b $OLD_BRANCH -L 1 -w "ci.yml" -s success -R NVIDIA/cuda-python --json databaseId | ConvertFrom-Json - if (-not $runData -or $runData.Length -eq 0 -or -not $runData[0].databaseId -or [string]::IsNullOrEmpty($runData[0].databaseId)) { - Write-Host "LATEST_PRIOR_RUN_ID not found!" - exit 1 - } - $LATEST_PRIOR_RUN_ID = $runData[0].databaseId - - gh run download $LATEST_PRIOR_RUN_ID -p $OLD_BASENAME -R NVIDIA/cuda-python - Remove-Item -Recurse -Force "${OLD_BASENAME}-tests" # exclude cython test artifacts - Get-ChildItem -Path $OLD_BASENAME - New-Item -Path "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" -ItemType Directory -Force - Move-Item -Path "$OLD_BASENAME/*.whl" -Destination "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" - Remove-Item -Path $OLD_BASENAME -Force - - gh run download $LATEST_PRIOR_RUN_ID -p cuda-python-wheel -R NVIDIA/cuda-python - Get-ChildItem -Path cuda-python-wheel - Move-Item -Path "cuda-python-wheel/*.whl" -Destination . - Remove-Item -Path cuda-python-wheel -Force + OLD_BRANCH=$(yq '.backport_branch' ci/versions.yml) + OLD_BASENAME="cuda-bindings-python${PYTHON_VERSION_FORMATTED}-cuda*-${{ inputs.host-platform }}*" + LATEST_PRIOR_RUN_ID=$(bash ./ci/tools/lookup-run-id-by-branch "${OLD_BRANCH}" "${{ github.repository }}") + + gh run download "${LATEST_PRIOR_RUN_ID}" -p "${OLD_BASENAME}" -R "${{ github.repository }}" + rm -rf "${OLD_BASENAME}-tests" # exclude cython test artifacts + ls -al "${OLD_BASENAME}" + mkdir -p "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" + mv "${OLD_BASENAME}"/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" + rmdir "${OLD_BASENAME}" + + gh run download "${LATEST_PRIOR_RUN_ID}" -p cuda-python-wheel -R "${{ github.repository }}" + ls -al cuda-python-wheel + mv cuda-python-wheel/*.whl . + rmdir cuda-python-wheel - name: Display structure of downloaded cuda-python artifacts run: | diff --git a/ci/tools/lookup-run-id-by-branch b/ci/tools/lookup-run-id-by-branch new file mode 100644 index 0000000000..84f4b81844 --- /dev/null +++ b/ci/tools/lookup-run-id-by-branch @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +# Find the latest successful workflow run for a branch. +# +# This intentionally queries completed runs for the workflow name and filters +# for success in jq. In CI, `gh run list --status success` and workflow file +# selectors such as `ci.yml` have proven brittle for this lookup (see PR #1981). + +set -euo pipefail + +if [[ $# -lt 2 || $# -gt 3 ]]; then + echo "Usage: $0 [workflow-name]" >&2 + echo " branch: The git branch to find the latest successful run for" >&2 + echo " repository: The GitHub repository (e.g., NVIDIA/cuda-python)" >&2 + echo " workflow-name: Optional workflow name to filter by (default: CI)" >&2 + exit 1 +fi + +BRANCH="${1}" +REPOSITORY="${2}" +WORKFLOW_NAME="${3:-CI}" + +if ! command -v jq >/dev/null 2>&1; then + echo "Error: jq is required but not installed" >&2 + exit 1 +fi + +if ! command -v gh >/dev/null 2>&1; then + echo "Error: GitHub CLI (gh) is required but not installed" >&2 + exit 1 +fi + +echo "Looking up latest successful '${WORKFLOW_NAME}' run on branch '${BRANCH}' in repository '${REPOSITORY}'" >&2 + +RUN_DATA=$(gh run list \ + --repo "${REPOSITORY}" \ + --branch "${BRANCH}" \ + --workflow "${WORKFLOW_NAME}" \ + --status completed \ + --json databaseId,workflowName,status,conclusion,headBranch,createdAt,url \ + --limit 50) + +if [[ -z "${RUN_DATA}" || "${RUN_DATA}" == "[]" ]]; then + echo "Error: No completed '${WORKFLOW_NAME}' workflow runs found for branch '${BRANCH}'." >&2 + exit 1 +fi + +RUN_ID=$(echo "${RUN_DATA}" | jq -r --arg branch "${BRANCH}" --arg workflow "${WORKFLOW_NAME}" ' + map(select( + .headBranch == $branch and + .workflowName == $workflow and + .conclusion == "success" + )) + | sort_by(.createdAt) + | reverse + | .[0].databaseId // empty +') + +if [[ -z "${RUN_ID}" ]]; then + echo "Error: No successful completed '${WORKFLOW_NAME}' workflow runs found for branch '${BRANCH}'." >&2 + echo "Completed runs returned by gh:" >&2 + echo "${RUN_DATA}" | jq -r '.[] | "\(.databaseId): branch=\(.headBranch // "null"), conclusion=\(.conclusion // "null"), status=\(.status // "null"), createdAt=\(.createdAt // "null"), url=\(.url // "null")"' >&2 + exit 1 +fi + +echo "${RUN_ID}" From 8113d02060d9f2cafac9e3c4000fc5ec36c940a2 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 27 Apr 2026 10:37:13 -0700 Subject: [PATCH 3/3] Revert "fix(ci): harden backport run lookup for artifact downloads" This reverts commit fd31eb24265e9f240bfc396cfc14e76487041f10. --- .github/workflows/build-wheel.yml | 16 ++++-- .github/workflows/test-wheel-linux.yml | 18 +++--- .github/workflows/test-wheel-windows.yml | 36 ++++++------ ci/tools/lookup-run-id-by-branch | 70 ------------------------ 4 files changed, 41 insertions(+), 99 deletions(-) delete mode 100644 ci/tools/lookup-run-id-by-branch diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index f84e5f7670..fbb8d092b0 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -401,14 +401,18 @@ jobs: OLD_BRANCH=$(yq '.backport_branch' ci/versions.yml) OLD_BASENAME="cuda-bindings-python${PYTHON_VERSION_FORMATTED}-cuda*-${{ inputs.host-platform }}*" - LATEST_PRIOR_RUN_ID=$(bash ./ci/tools/lookup-run-id-by-branch "${OLD_BRANCH}" "${{ github.repository }}") + LATEST_PRIOR_RUN_ID=$(gh run list -b ${OLD_BRANCH} -L 1 -w "ci.yml" -s success -R NVIDIA/cuda-python --json databaseId | jq '.[]| .databaseId') + if [[ "$LATEST_PRIOR_RUN_ID" == "" ]]; then + echo "LATEST_PRIOR_RUN_ID not found!" + exit 1 + fi - gh run download "${LATEST_PRIOR_RUN_ID}" -p "${OLD_BASENAME}" -R "${{ github.repository }}" - rm -rf "${OLD_BASENAME}-tests" # exclude cython test artifacts - ls -al "${OLD_BASENAME}" + gh run download $LATEST_PRIOR_RUN_ID -p ${OLD_BASENAME} -R NVIDIA/cuda-python + rm -rf ${OLD_BASENAME}-tests # exclude cython test artifacts + ls -al $OLD_BASENAME mkdir -p "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" - mv "${OLD_BASENAME}"/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" - rmdir "${OLD_BASENAME}" + mv $OLD_BASENAME/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" + rmdir $OLD_BASENAME - name: Build cuda.core wheel uses: pypa/cibuildwheel@ee02a1537ce3071a004a6b08c41e72f0fdc42d9a # v3.4.0 diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index 89adab3057..35c5e6c373 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -160,16 +160,20 @@ jobs: OLD_BRANCH=${{ needs.compute-matrix.outputs.OLD_BRANCH }} OLD_BASENAME="cuda-bindings-python${PYTHON_VERSION_FORMATTED}-cuda*-${{ inputs.host-platform }}*" - LATEST_PRIOR_RUN_ID=$(bash ./ci/tools/lookup-run-id-by-branch "${OLD_BRANCH}" "${{ github.repository }}") + LATEST_PRIOR_RUN_ID=$(gh run list -b ${OLD_BRANCH} -L 1 -w "ci.yml" -s success -R NVIDIA/cuda-python --json databaseId | jq '.[]| .databaseId') + if [[ "$LATEST_PRIOR_RUN_ID" == "" ]]; then + echo "LATEST_PRIOR_RUN_ID not found!" + exit 1 + fi - gh run download "${LATEST_PRIOR_RUN_ID}" -p "${OLD_BASENAME}" -R "${{ github.repository }}" - rm -rf "${OLD_BASENAME}-tests" # exclude cython test artifacts - ls -al "${OLD_BASENAME}" + gh run download $LATEST_PRIOR_RUN_ID -p ${OLD_BASENAME} -R NVIDIA/cuda-python + rm -rf ${OLD_BASENAME}-tests # exclude cython test artifacts + ls -al $OLD_BASENAME mkdir -p "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" - mv "${OLD_BASENAME}"/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}"/ - rmdir "${OLD_BASENAME}" + mv $OLD_BASENAME/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}"/ + rmdir $OLD_BASENAME - gh run download "${LATEST_PRIOR_RUN_ID}" -p cuda-python-wheel -R "${{ github.repository }}" + gh run download $LATEST_PRIOR_RUN_ID -p cuda-python-wheel -R NVIDIA/cuda-python ls -al cuda-python-wheel mv cuda-python-wheel/*.whl . rmdir cuda-python-wheel diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 084d3a7c89..765823c6bf 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -142,23 +142,27 @@ jobs: if: ${{ env.USE_BACKPORT_BINDINGS == '1' }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash --noprofile --norc -xeuo pipefail {0} run: | - OLD_BRANCH=$(yq '.backport_branch' ci/versions.yml) - OLD_BASENAME="cuda-bindings-python${PYTHON_VERSION_FORMATTED}-cuda*-${{ inputs.host-platform }}*" - LATEST_PRIOR_RUN_ID=$(bash ./ci/tools/lookup-run-id-by-branch "${OLD_BRANCH}" "${{ github.repository }}") - - gh run download "${LATEST_PRIOR_RUN_ID}" -p "${OLD_BASENAME}" -R "${{ github.repository }}" - rm -rf "${OLD_BASENAME}-tests" # exclude cython test artifacts - ls -al "${OLD_BASENAME}" - mkdir -p "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" - mv "${OLD_BASENAME}"/*.whl "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" - rmdir "${OLD_BASENAME}" - - gh run download "${LATEST_PRIOR_RUN_ID}" -p cuda-python-wheel -R "${{ github.repository }}" - ls -al cuda-python-wheel - mv cuda-python-wheel/*.whl . - rmdir cuda-python-wheel + $OLD_BRANCH = yq '.backport_branch' ci/versions.yml + $OLD_BASENAME = "cuda-bindings-python${env:PYTHON_VERSION_FORMATTED}-cuda*-${{ inputs.host-platform }}*" + $runData = gh run list -b $OLD_BRANCH -L 1 -w "ci.yml" -s success -R NVIDIA/cuda-python --json databaseId | ConvertFrom-Json + if (-not $runData -or $runData.Length -eq 0 -or -not $runData[0].databaseId -or [string]::IsNullOrEmpty($runData[0].databaseId)) { + Write-Host "LATEST_PRIOR_RUN_ID not found!" + exit 1 + } + $LATEST_PRIOR_RUN_ID = $runData[0].databaseId + + gh run download $LATEST_PRIOR_RUN_ID -p $OLD_BASENAME -R NVIDIA/cuda-python + Remove-Item -Recurse -Force "${OLD_BASENAME}-tests" # exclude cython test artifacts + Get-ChildItem -Path $OLD_BASENAME + New-Item -Path "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" -ItemType Directory -Force + Move-Item -Path "$OLD_BASENAME/*.whl" -Destination "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" + Remove-Item -Path $OLD_BASENAME -Force + + gh run download $LATEST_PRIOR_RUN_ID -p cuda-python-wheel -R NVIDIA/cuda-python + Get-ChildItem -Path cuda-python-wheel + Move-Item -Path "cuda-python-wheel/*.whl" -Destination . + Remove-Item -Path cuda-python-wheel -Force - name: Display structure of downloaded cuda-python artifacts run: | diff --git a/ci/tools/lookup-run-id-by-branch b/ci/tools/lookup-run-id-by-branch deleted file mode 100644 index 84f4b81844..0000000000 --- a/ci/tools/lookup-run-id-by-branch +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash - -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 - -# Find the latest successful workflow run for a branch. -# -# This intentionally queries completed runs for the workflow name and filters -# for success in jq. In CI, `gh run list --status success` and workflow file -# selectors such as `ci.yml` have proven brittle for this lookup (see PR #1981). - -set -euo pipefail - -if [[ $# -lt 2 || $# -gt 3 ]]; then - echo "Usage: $0 [workflow-name]" >&2 - echo " branch: The git branch to find the latest successful run for" >&2 - echo " repository: The GitHub repository (e.g., NVIDIA/cuda-python)" >&2 - echo " workflow-name: Optional workflow name to filter by (default: CI)" >&2 - exit 1 -fi - -BRANCH="${1}" -REPOSITORY="${2}" -WORKFLOW_NAME="${3:-CI}" - -if ! command -v jq >/dev/null 2>&1; then - echo "Error: jq is required but not installed" >&2 - exit 1 -fi - -if ! command -v gh >/dev/null 2>&1; then - echo "Error: GitHub CLI (gh) is required but not installed" >&2 - exit 1 -fi - -echo "Looking up latest successful '${WORKFLOW_NAME}' run on branch '${BRANCH}' in repository '${REPOSITORY}'" >&2 - -RUN_DATA=$(gh run list \ - --repo "${REPOSITORY}" \ - --branch "${BRANCH}" \ - --workflow "${WORKFLOW_NAME}" \ - --status completed \ - --json databaseId,workflowName,status,conclusion,headBranch,createdAt,url \ - --limit 50) - -if [[ -z "${RUN_DATA}" || "${RUN_DATA}" == "[]" ]]; then - echo "Error: No completed '${WORKFLOW_NAME}' workflow runs found for branch '${BRANCH}'." >&2 - exit 1 -fi - -RUN_ID=$(echo "${RUN_DATA}" | jq -r --arg branch "${BRANCH}" --arg workflow "${WORKFLOW_NAME}" ' - map(select( - .headBranch == $branch and - .workflowName == $workflow and - .conclusion == "success" - )) - | sort_by(.createdAt) - | reverse - | .[0].databaseId // empty -') - -if [[ -z "${RUN_ID}" ]]; then - echo "Error: No successful completed '${WORKFLOW_NAME}' workflow runs found for branch '${BRANCH}'." >&2 - echo "Completed runs returned by gh:" >&2 - echo "${RUN_DATA}" | jq -r '.[] | "\(.databaseId): branch=\(.headBranch // "null"), conclusion=\(.conclusion // "null"), status=\(.status // "null"), createdAt=\(.createdAt // "null"), url=\(.url // "null")"' >&2 - exit 1 -fi - -echo "${RUN_ID}"