Skip to content

Commit bc3613e

Browse files
authored
Merge pull request #412 from leofang/release_workflow
CI: Add a release workflow
2 parents c04025d + 5c59bc0 commit bc3613e

3 files changed

Lines changed: 256 additions & 10 deletions

File tree

.github/workflows/build-docs.yml

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,26 @@ on:
66
build-ctk-ver:
77
type: string
88
required: true
9+
component:
10+
description: "Component(s) to build docs for"
11+
required: false
12+
default: "all"
13+
type: string
14+
# below are the acceptable options:
15+
# - cuda-core
16+
# - cuda-bindings
17+
# - cuda-python
18+
# - all
19+
git-tag:
20+
description: "Target git tag to build docs for"
21+
required: false
22+
default: ""
23+
type: string
24+
is-release:
25+
description: "Are we building release docs?"
26+
required: false
27+
default: false
28+
type: boolean
929

1030
jobs:
1131
build:
@@ -27,6 +47,7 @@ jobs:
2747
uses: actions/checkout@v4
2848
with:
2949
fetch-depth: 0
50+
ref: ${{ inputs.git-tag }}
3051

3152
# TODO: cache conda env to speed up the workflow once conda-incubator/setup-miniconda#267
3253
# is resolved
@@ -114,23 +135,47 @@ jobs:
114135
115136
pip install cuda_python*.whl
116137
117-
# This step sets the PR_NUMBER env var.
138+
# This step sets the PR_NUMBER/BUILD_LATEST/BUILD_PREVIEW env vars.
118139
- name: Get PR number
140+
if: ${{ !inputs.is-release }}
119141
uses: ./.github/actions/get_pr_number
120142

121-
- name: Build all (latest) docs
122-
id: build
143+
- name: Set up artifact directories
144+
run: |
145+
mkdir -p artifacts/docs
146+
# create an empty folder for removal use
147+
mkdir -p artifacts/empty_docs
148+
149+
- name: Build all docs
150+
if: ${{ inputs.component == 'all' }}
151+
env:
152+
DOC_ACTION: ${{ (inputs.is-release && '') || 'latest-only' }}
123153
run: |
124154
pushd cuda_python/docs/
125-
./build_all_docs.sh latest-only
155+
./build_all_docs.sh $DOC_ACTION
156+
if [[ -z "$DOC_ACTION" ]]; then
157+
# At release time, we don't want to update the latest docs
158+
rm -rf build/html/latest
159+
fi
126160
ls -l build
127161
popd
128-
129-
mkdir -p artifacts/docs
130162
mv cuda_python/docs/build/html/* artifacts/docs/
131163
132-
# create an empty folder for removal use
133-
mkdir -p artifacts/empty_docs
164+
- name: Build component docs
165+
if: ${{ inputs.component != 'all' }}
166+
env:
167+
DOC_ACTION: ${{ (inputs.is-release && '') || 'latest-only' }}
168+
run: |
169+
COMPONENT=$(echo "${{ inputs.component }}" | tr '-' '_')
170+
pushd ${COMPONENT}/docs/
171+
./build_docs.sh $DOC_ACTION
172+
if [[ -z "$DOC_ACTION" ]]; then
173+
# At release time, we don't want to update the latest docs
174+
rm -rf build/html/latest
175+
fi
176+
ls -l build
177+
popd
178+
mv ${COMPONENT}/docs/build/html/* artifacts/docs/
134179
135180
# TODO: Consider removing this step?
136181
- name: Upload doc artifacts
@@ -140,19 +185,20 @@ jobs:
140185
retention-days: 3
141186

142187
- name: Deploy or clean up doc preview
188+
if: ${{ !inputs.is-release }}
143189
uses: ./.github/actions/doc_preview
144190
with:
145191
source-folder: ${{ (github.ref_name != 'main' && 'artifacts/docs') ||
146192
'artifacts/empty_docs' }}
147193
pr-number: ${{ env.PR_NUMBER }}
148194

149195
- name: Deploy doc update
150-
if: ${{ github.ref_name == 'main' }}
196+
if: ${{ github.ref_name == 'main' || inputs.is-release }}
151197
uses: JamesIves/github-pages-deploy-action@v4
152198
with:
153199
git-config-name: cuda-python-bot
154200
git-config-email: cuda-python-bot@users.noreply.github.com
155201
folder: artifacts/docs/
156202
target-folder: docs/
157-
commit-message: "Deploy latest docs: ${{ github.sha }}"
203+
commit-message: "Deploy ${{ (inputs.is-release && 'release') || 'latest' }} docs: ${{ github.sha }}"
158204
clean: false
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: "CI: Upload git archive"
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
git-tag:
7+
type: string
8+
required: true
9+
10+
concurrency:
11+
# Concurrency group that uses the workflow name and PR number if available
12+
# or commit SHA as a fallback. If a new build is triggered under that
13+
# concurrency group while a previous build is running it will be canceled.
14+
# Repeated pushes to a PR will cancel all previous builds, while multiple
15+
# merges to main will not cancel.
16+
group: ${{ github.workflow }}-${{ github.ref_name || github.sha }}
17+
cancel-in-progress: true
18+
19+
permissions:
20+
contents: write
21+
22+
jobs:
23+
# create source archive and upload it to the published release
24+
# URL to the archive: https://github.com/NVIDIA/<repo>/releases/download/<tag>/<repo>-<tag>.tar.gz
25+
upload:
26+
if: ${{ !github.event.repository.fork }}
27+
runs-on: ubuntu-latest
28+
env:
29+
ARCHIVE_NAME: ${{ github.event.repository.name }}-${{ inputs.git-tag }}
30+
steps:
31+
- name: Checkout Source
32+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
33+
34+
- name: Create Release Directory
35+
run: mkdir -p release
36+
37+
- name: Archive Source
38+
run: >
39+
git archive
40+
--format=tar.gz
41+
--prefix="${{ env.ARCHIVE_NAME }}/"
42+
--output="release/${{ env.ARCHIVE_NAME }}.tar.gz"
43+
${{ inputs.git-tag }}
44+
45+
- name: Compute Checksum
46+
run: >
47+
sha256sum "release/${{ env.ARCHIVE_NAME }}.tar.gz"
48+
| awk '{print $1}'
49+
> "release/${{ env.ARCHIVE_NAME }}.tar.gz.sha256sum"
50+
51+
- name: Upload Archive
52+
env:
53+
GH_TOKEN: ${{ github.token }}
54+
run: >
55+
gh release upload
56+
${{ inputs.git-tag }}
57+
release/*
58+
--clobber "${{ github.ref_name }}"
59+
--repo "${{ github.repository }}"

.github/workflows/release.yml

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
name: "CI: Release"
2+
3+
description: Manually-triggered release workflow. Must have a release note in the draft state and the release commit tagged.
4+
5+
on:
6+
workflow_dispatch:
7+
inputs:
8+
component:
9+
description: "Component to release"
10+
required: true
11+
type: choice
12+
options:
13+
- cuda-core
14+
- cuda-bindings
15+
- cuda-python
16+
- all
17+
git-tag:
18+
description: "The release git tag"
19+
required: true
20+
type: string
21+
run-id:
22+
description: "The GHA run ID that generated validated artifacts"
23+
required: true
24+
type: string
25+
build-ctk-ver:
26+
type: string
27+
required: true
28+
wheel-dst:
29+
description: "Which wheel index to publish to?"
30+
required: true
31+
type: choice
32+
options:
33+
- testpypi
34+
- pypi
35+
#print_tags:
36+
# description: 'True to print to STDOUT'
37+
# required: true
38+
# type: boolean
39+
40+
defaults:
41+
run:
42+
shell: bash --noprofile --norc -xeuo pipefail {0}
43+
44+
jobs:
45+
check-tag:
46+
runs-on: ubuntu-latest
47+
steps:
48+
- name: Check if draft exists for the tag
49+
env:
50+
GH_TOKEN: ${{ github.token }}
51+
run: |
52+
tags=
53+
for i in $(gh release list -R ${{ github.repository }} --json tagName --jq '.[]| .tagName'); do
54+
tags+=( $i )
55+
done
56+
is_draft=
57+
for i in $(gh release list -R ${{ github.repository }} --json isDraft --jq '.[]| .isDraft'); do
58+
is_draft+=( $i )
59+
done
60+
61+
found=0
62+
for idx in ${!tags[@]}; do
63+
if [[ "${tags[$idx]}" == "${{ inputs.git-tag }}" ]]; then
64+
echo "found ${{ inputs.git-tag }}"
65+
found=1
66+
if [[ "${is_draft[$idx]}" != "true" ]]; then
67+
echo "the release note is not in draft state"
68+
exit 1
69+
fi
70+
break
71+
fi
72+
done
73+
if [[ "$found" == 0 ]]; then
74+
echo "the release is not yet tagged"
75+
exit 1
76+
fi
77+
78+
doc:
79+
name: Build release docs
80+
if: ${{ github.repository_owner == 'nvidia' }}
81+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
82+
permissions:
83+
id-token: write
84+
contents: write
85+
pull-requests: write
86+
needs:
87+
- check-tag
88+
secrets: inherit
89+
uses:
90+
./.github/workflows/build-docs.yml
91+
with:
92+
build-ctk-ver: ${{ inputs.build-ctk-ver }}
93+
component: ${{ inputs.component }}
94+
git-tag: ${{ inputs.git-tag }}
95+
is-release: true
96+
97+
upload-archive:
98+
name: Upload source archive
99+
permissions:
100+
contents: write
101+
needs:
102+
- check-tag
103+
secrets: inherit
104+
uses:
105+
./.github/workflows/release-upload.yml
106+
with:
107+
git-tag: ${{ inputs.git-tag }}
108+
109+
publish-wheels:
110+
name: Publish wheels
111+
runs-on: ubuntu-latest
112+
needs:
113+
- check-tag
114+
environment:
115+
name: ${{ inputs.wheel-dst }}
116+
url: https://${{ (inputs.wheel-dst == 'testpypi' && 'test.') || '' }}pypi.org/p/${{ inputs.component }}/
117+
permissions:
118+
id-token: write
119+
steps:
120+
- name: Download component wheels
121+
env:
122+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
123+
run: |
124+
gh run download ${{ inputs.run-id }} -p "${{ inputs.component }}*" -R ${{ github.repository }}
125+
mkdir dist
126+
for p in "${{ inputs.component }}*"; do
127+
mv ${p}/*.whl dist/
128+
done
129+
rmdir "${{ inputs.component }}*"
130+
131+
- name: Publish package distributions to PyPI
132+
if: ${{ inputs.wheel-dst == 'pypi' }}
133+
uses: pypa/gh-action-pypi-publish@release/v1
134+
135+
- name: Publish package distributions to TestPyPI
136+
if: ${{ inputs.wheel-dst == 'testpypi' }}
137+
uses: pypa/gh-action-pypi-publish@release/v1
138+
with:
139+
repository-url: https://test.pypi.org/legacy/
140+
141+
# TODO: add another job to make the release leave the draft state?

0 commit comments

Comments
 (0)