Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/release-upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ on:
git-tag:
type: string
required: true
run-id:
description: "The GHA run ID that generated validated artifacts"
type: string
required: true
component:
description: "Component to download wheels for"
type: string
required: true

concurrency:
# Concurrency group that uses the workflow name and PR number if available
Expand Down Expand Up @@ -63,3 +71,16 @@ jobs:
--clobber "${{ inputs.git-tag }}"
--repo "${{ github.repository }}"
release/*

- name: Download and Upload Wheels
env:
GH_TOKEN: ${{ github.token }}
run: |
# Use the shared script to download wheels
./ci/tools/download-wheels "${{ inputs.run-id }}" "${{ inputs.component }}" "${{ github.repository }}" "release/wheels"

# Upload wheels to the release
if [[ -d "release/wheels" && $(ls -A release/wheels 2>/dev/null | wc -l) -gt 0 ]]; then
echo "Uploading wheels to release ${{ inputs.git-tag }}"
gh release upload --clobber "${{ inputs.git-tag }}" --repo "${{ github.repository }}" release/wheels/*
fi
32 changes: 16 additions & 16 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

name: "CI: Release"

description: Manually-triggered release workflow. Must have a release note in the draft state and the release commit tagged.
description: Manually-triggered release workflow. Creates a release draft if one doesn't exist for the given tag, or uses existing draft.

on:
workflow_dispatch:
Expand Down Expand Up @@ -46,7 +46,12 @@ jobs:
check-tag:
runs-on: ubuntu-latest
steps:
- name: Check if draft exists for the tag
- name: Checkout Source
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0

- name: Check or create draft release for the tag
env:
GH_TOKEN: ${{ github.token }}
run: |
Expand All @@ -62,7 +67,7 @@ jobs:
found=0
for idx in ${!tags[@]}; do
if [[ "${tags[$idx]}" == "${{ inputs.git-tag }}" ]]; then
echo "found ${{ inputs.git-tag }}"
echo "found existing release for ${{ inputs.git-tag }}"
found=1
if [[ "${is_draft[$idx]}" != "true" ]]; then
echo "the release note is not in draft state"
Expand All @@ -72,8 +77,8 @@ jobs:
fi
done
if [[ "$found" == 0 ]]; then
echo "the release is not yet tagged"
exit 1
echo "no release found for ${{ inputs.git-tag }}, creating draft release"
gh release create "${{ inputs.git-tag }}" --draft --repo "${{ github.repository }}" --title "Release ${{ inputs.git-tag }}" --notes "Release ${{ inputs.git-tag }}"
fi

doc:
Expand Down Expand Up @@ -105,6 +110,8 @@ jobs:
uses: ./.github/workflows/release-upload.yml
with:
git-tag: ${{ inputs.git-tag }}
run-id: ${{ inputs.run-id }}
component: ${{ inputs.component }}

publish-wheels:
name: Publish wheels
Expand All @@ -117,21 +124,14 @@ jobs:
permissions:
id-token: write
steps:
- name: Checkout Source
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- name: Download component wheels
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh run download ${{ inputs.run-id }} -p "${{ inputs.component }}*" -R ${{ github.repository }}
mkdir dist
for p in ${{ inputs.component }}*
do
# exclude cython test artifacts
if [[ "${p}" == *-tests ]]; then
continue
fi
mv ${p}/*.whl dist/
done
rm -rf ${{ inputs.component }}*
./ci/tools/download-wheels "${{ inputs.run-id }}" "${{ inputs.component }}" "${{ github.repository }}" "dist"

- name: Publish package distributions to PyPI
if: ${{ inputs.wheel-dst == 'pypi' }}
Expand Down
75 changes: 75 additions & 0 deletions ci/tools/download-wheels
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env bash

# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0

# A utility script to download component wheels from GitHub Actions artifacts.
# This script reuses the same logic that was in release.yml to maintain consistency.

set -euo pipefail

# Check required arguments
if [[ $# -lt 3 ]]; then
echo "Usage: $0 <run-id> <component> <repository> [output-dir]" >&2
echo " run-id: The GitHub Actions run ID containing the artifacts" >&2
echo " component: The component name pattern to download (e.g., cuda-core, cuda-bindings)" >&2
echo " repository: The GitHub repository (e.g., NVIDIA/cuda-python)" >&2
echo " output-dir: Optional output directory (default: ./dist)" >&2
exit 1
fi

RUN_ID="$1"
COMPONENT="$2"
REPOSITORY="$3"
OUTPUT_DIR="${4:-./dist}"

# Ensure we have a GitHub token
if [[ -z "${GH_TOKEN:-}" ]]; then
echo "Error: GH_TOKEN environment variable is required"
exit 1
fi

echo "Downloading wheels for component: $COMPONENT from run: $RUN_ID"

# Download component wheels using the same logic as release.yml
if [[ "$COMPONENT" == "all" ]]; then
# Download all component patterns
gh run download "$RUN_ID" -p "cuda-*" -R "$REPOSITORY"
else
gh run download "$RUN_ID" -p "${COMPONENT}*" -R "$REPOSITORY"
fi

# Create output directory
mkdir -p "$OUTPUT_DIR"

# Process downloaded artifacts
for p in cuda-*
do
if [[ ! -d "$p" ]]; then
continue
fi

# exclude cython test artifacts
if [[ "${p}" == *-tests ]]; then
echo "Skipping test artifact: $p"
continue
fi

# If we're not downloading "all", only process matching component
if [[ "$COMPONENT" != "all" && "$p" != ${COMPONENT}* ]]; then
continue
fi

echo "Processing artifact: $p"
# Move wheel files to output directory
if [[ -d "$p" ]]; then
find "$p" -name "*.whl" -exec mv {} "$OUTPUT_DIR/" \;
fi
done

# Clean up artifact directories
rm -rf cuda-*

echo "Downloaded wheels to: $OUTPUT_DIR"
ls -la "$OUTPUT_DIR"