Skip to content
Open
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
28 changes: 6 additions & 22 deletions .github/RELEASE-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,8 @@ Pushing the tag triggers a CI run automatically. Monitor it in the

## Upload wheels to PyPI

This is a two-stage process: first publish to TestPyPI, verify, then
publish to PyPI.

### Stage 1: TestPyPI
This is a single `CI: Release` workflow run with two sequential stages:
publish to TestPyPI, then publish the same wheel set to PyPI.

1. Go to **Actions > CI: Release** and run the workflow with:
- **Component**: `cuda-core`
Expand All @@ -138,26 +136,12 @@ publish to PyPI.
— the run ID is `123456789`).
- **build-ctk-ver**: the `cuda.build.version` from
[`ci/versions.yml`](../ci/versions.yml) (e.g. `13.1.1`)
- **Which wheel index to publish to**: `testpypi`

2. Wait for the workflow to complete.

3. Verify the TestPyPI upload by installing and running tests from a
checked-out copy of the repository:

```bash
pip install -i https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
cuda-core==0.6.0
cd cuda_core/tests && pytest
```

### Stage 2: PyPI

Once TestPyPI verification passes, rerun the same workflow with:
- **Which wheel index to publish to**: `pypi`
2. Wait for the workflow to complete. It will:
- publish the selected wheels to TestPyPI
- publish the same wheel set to PyPI

After completion, verify:
3. After completion, verify the final PyPI upload:

```bash
pip install cuda-core==0.6.0
Expand Down
68 changes: 40 additions & 28 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

name: "CI: Release"

# Manually-triggered release workflow. Creates a release draft if one doesn't exist for the given tag, or uses existing draft.
# Manually-triggered release workflow. Creates a release draft if one doesn't exist
# for the given tag, or uses an existing draft, then publishes the selected wheels
# to TestPyPI followed by PyPI.

on:
workflow_dispatch:
Expand All @@ -31,13 +33,6 @@ on:
build-ctk-ver:
type: string
required: true
wheel-dst:
description: "Which wheel index to publish to?"
required: true
type: choice
options:
- testpypi
- pypi

defaults:
run:
Expand All @@ -62,12 +57,12 @@ jobs:
run: |
if [[ -n "${{ inputs.run-id }}" ]]; then
echo "Using provided run ID: ${{ inputs.run-id }}"
echo "run-id=${{ inputs.run-id }}" >> $GITHUB_OUTPUT
echo "run-id=${{ inputs.run-id }}" >> "$GITHUB_OUTPUT"
else
echo "Auto-detecting successful tag-triggered run ID for tag: ${{ inputs.git-tag }}"
RUN_ID=$(./ci/tools/lookup-run-id "${{ inputs.git-tag }}" "${{ github.repository }}")
echo "Auto-detected run ID: $RUN_ID"
echo "run-id=$RUN_ID" >> $GITHUB_OUTPUT
echo "run-id=$RUN_ID" >> "$GITHUB_OUTPUT"
fi

check-tag:
Expand All @@ -82,17 +77,11 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: |
tags=
for i in $(gh release list -R ${{ github.repository }} --json tagName --jq '.[]| .tagName'); do
tags+=( $i )
done
is_draft=
for i in $(gh release list -R ${{ github.repository }} --json isDraft --jq '.[]| .isDraft'); do
is_draft+=( $i )
done
mapfile -t tags < <(gh release list -R "${{ github.repository }}" --json tagName --jq '.[] | .tagName')
mapfile -t is_draft < <(gh release list -R "${{ github.repository }}" --json isDraft --jq '.[] | .isDraft')

found=0
for idx in ${!tags[@]}; do
for idx in "${!tags[@]}"; do
if [[ "${tags[$idx]}" == "${{ inputs.git-tag }}" ]]; then
echo "found existing release for ${{ inputs.git-tag }}"
found=1
Expand Down Expand Up @@ -143,16 +132,16 @@ jobs:
run-id: ${{ needs.determine-run-id.outputs.run-id }}
component: ${{ inputs.component }}

publish-wheels:
name: Publish wheels
publish-testpypi:
name: Publish wheels to TestPyPI
runs-on: ubuntu-latest
needs:
- check-tag
- determine-run-id
- doc
environment:
name: ${{ inputs.wheel-dst }}
url: https://${{ (inputs.wheel-dst == 'testpypi' && 'test.') || '' }}pypi.org/p/${{ inputs.component }}/
name: testpypi
url: https://test.pypi.org/${{ inputs.component != 'all' && format('p/{0}/', inputs.component) || '' }}
permissions:
id-token: write
steps:
Expand All @@ -169,14 +158,37 @@ jobs:
run: |
./ci/tools/validate-release-wheels "${{ inputs.git-tag }}" "${{ inputs.component }}" "dist"

- name: Publish package distributions to PyPI
if: ${{ inputs.wheel-dst == 'pypi' }}
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0

- name: Publish package distributions to TestPyPI
if: ${{ inputs.wheel-dst == 'testpypi' }}
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with:
repository-url: https://test.pypi.org/legacy/

publish-pypi:
name: Publish wheels to PyPI
runs-on: ubuntu-latest
needs:
- determine-run-id
- publish-testpypi
environment:
name: pypi
url: https://pypi.org/${{ inputs.component != 'all' && format('p/{0}/', inputs.component) || '' }}
permissions:
id-token: write
steps:
- name: Checkout Source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Download component wheels
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
./ci/tools/download-wheels "${{ needs.determine-run-id.outputs.run-id }}" "${{ inputs.component }}" "${{ github.repository }}" "dist"

- name: Validate wheel versions for release tag
run: |
./ci/tools/validate-release-wheels "${{ inputs.git-tag }}" "${{ inputs.component }}" "dist"

- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0

# TODO: add another job to make the release leave the draft state?
Loading