Skip to content

Commit f0cbf6f

Browse files
authored
chore(ci): add a tag based release mechanism (#182)
# Summary * Allows tagging publish to occur on release * Will require tweaking for the final PyPI destination
1 parent b79f050 commit f0cbf6f

3 files changed

Lines changed: 80 additions & 15 deletions

File tree

.github/workflows/README.md

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ This directory contains GitHub Actions workflows for CI/CD automation.
1515
| [conventional-commit.yml](conventional-commit.yml) | PRs | Validates PR titles follow conventional commit format |
1616
| [copyright-check.yml](copyright-check.yml) | Push to `main`/`pull-request/*` | Validates NVIDIA copyright headers on Python files |
1717
| [docs.yml](docs.yml) | Push to `main` (docs paths) | Builds and deploys documentation to GitHub Pages |
18-
| [internal-release.yml](internal-release.yml) | Manual dispatch | Builds and publishes wheel to NVIDIA Artifactory |
18+
| [internal-release.yml](internal-release.yml) | Tag push (`v[0-9]*`), manual dispatch | Builds and publishes wheel to Artifactory or PyPI |
1919
| [release.yml](release.yml) | Manual dispatch | Builds and publishes package to PyPI (production) |
2020
| [secrets-detector.yml](secrets-detector.yml) | PRs | Scans for accidentally committed secrets |
2121

@@ -74,12 +74,19 @@ flowchart LR
7474
slackNotify[Slack Notification]
7575
end
7676
77+
subgraph internalRelease [Internal Release]
78+
buildWheelInt[Build Wheel]
79+
publishArtifactory[Publish to Artifactory/PyPI]
80+
end
81+
7782
push --> ci & gpu
7883
cpb --> gpu & copyright
7984
pr --> ci & conventional & secrets
8085
manual --> release
86+
tag[Tag push v[0-9]*] --> internalRelease
8187
8288
buildWheel --> publishPyPI --> ghRelease --> slackNotify
89+
buildWheelInt --> publishArtifactory
8390
8491
conventional -.->|reuses| FW-CI-templates
8592
secrets -.->|reuses| FW-CI-templates
@@ -170,18 +177,35 @@ Validates that Python files have proper NVIDIA copyright headers.
170177

171178
## Internal Release Workflow
172179

173-
The `internal-release.yml` workflow builds a wheel and publishes it to NVIDIA Artifactory. Use this for testing the release process or distributing internal builds.
180+
The `internal-release.yml` workflow builds a wheel and publishes it to NVIDIA Artifactory or PyPI.
181+
182+
### Triggers
183+
184+
**Tag push (automatic):** Pushing a `v[0-9]*` tag (e.g. `git tag v0.2.0 && git push --tags`) automatically builds and publishes to Artifactory. This is the primary release mechanism.
185+
186+
**Manual dispatch:** Go to Actions > Internal Release and run with:
187+
- `release-ref`: Branch, tag, or commit SHA to build (defaults to `main`)
188+
- `publish-target`: `artifactory` (default) or `pypi`
174189

175190
### How to Publish Internally
176191

177-
Via GitHub Actions:
192+
Tag-based (recommended):
193+
194+
```bash
195+
git tag v0.2.0
196+
git push --tags
197+
```
198+
199+
This triggers the workflow automatically and publishes to Artifactory.
200+
201+
Via GitHub Actions (manual):
178202

179203
1. Go to Actions > Internal Release
180204
2. Click Run workflow
181-
3. Enter the branch, tag, or commit SHA to build (defaults to `main`)
182-
4. The workflow builds the wheel, uploads it as an artifact, and publishes to Artifactory
205+
3. Enter the branch, tag, or commit SHA to build
206+
4. Select publish target (`artifactory` or `pypi`)
183207

184-
Requires `ARTIFACTORY_USERNAME`, `ARTIFACTORY_TOKEN`, and `ARTIFACTORY_INTERNAL_URL` secrets to be configured.
208+
Requires `ARTIFACTORY_USERNAME`, `ARTIFACTORY_TOKEN`, and `ARTIFACTORY_INTERNAL_URL` secrets for Artifactory; `TWINE_USERNAME` and `TWINE_PASSWORD` for PyPI.
185209

186210
Locally (via Makefile):
187211

.github/workflows/internal-release.yml

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,54 +13,79 @@
1313
# limitations under the License.
1414

1515
# ---------------------------------------------------------------------------
16-
# Internal release: build a wheel and publish to NVIDIA Artifactory.
16+
# Tag-based release: build a wheel and publish on every v[0-9]* tag push.
17+
# Also available as a manual dispatch with a configurable publish target.
18+
#
19+
# Tag push on a v[0-9]* tag (e.g. `git tag v0.2.0 && git push --tags`):
20+
# - Automatically publishes to NVIDIA Artifactory.
21+
#
22+
# Manual dispatch:
23+
# - publish-target=artifactory (default): publishes to NVIDIA Artifactory.
24+
# - publish-target=pypi: publishes to PyPI (production releases).
25+
#
1726
# Version is determined from git tags via uv-dynamic-versioning.
18-
# Tag a commit (e.g. `git tag v0.2.0`) before running this workflow.
19-
# Production releases to PyPI use release.yml (FW-CI-templates).
27+
# For full production PyPI releases (with GitHub release + Slack), use release.yml.
2028
# ---------------------------------------------------------------------------
2129

2230
name: "Internal Release"
2331

2432
on:
33+
push:
34+
tags:
35+
- 'v[0-9]*'
2536
workflow_dispatch:
2637
inputs:
2738
release-ref:
2839
description: Branch, tag, or full SHA to build
2940
required: true
3041
default: main
3142
type: string
43+
publish-target:
44+
description: Where to publish the wheel
45+
required: true
46+
default: artifactory
47+
type: choice
48+
options:
49+
- artifactory
50+
- pypi
3251

3352
defaults:
3453
run:
3554
shell: bash -x -e -u -o pipefail {0}
3655

3756
jobs:
3857
publish:
39-
name: Build and publish to Artifactory
58+
name: Build and publish wheel
4059
runs-on: linux-amd64-cpu4
41-
env:
42-
TWINE_REPOSITORY_URL: ${{ secrets.ARTIFACTORY_INTERNAL_URL }}
4360
steps:
4461
- name: checkout
4562
uses: actions/checkout@v6
4663
with:
47-
ref: ${{ inputs.release-ref }}
64+
ref: ${{ inputs.release-ref || github.ref }}
4865
fetch-depth: 0
4966

5067
- name: Setup Python environment
5168
uses: ./.github/actions/setup-python-env
5269
with:
53-
ref: ${{ inputs.release-ref }}
70+
ref: ${{ inputs.release-ref || github.ref }}
5471
fetch-depth: 0
5572
bootstrap-tools: "false"
5673

57-
- name: Build and publish
74+
- name: Build and publish to Artifactory
75+
if: github.event_name == 'push' || inputs.publish-target == 'artifactory'
5876
run: make publish-internal
5977
env:
6078
TWINE_REPOSITORY_URL: ${{ secrets.ARTIFACTORY_INTERNAL_URL }}
6179
TWINE_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
6280
TWINE_PASSWORD: ${{ secrets.ARTIFACTORY_TOKEN }}
6381

82+
- name: Build and publish to PyPI
83+
if: github.event_name == 'workflow_dispatch' && inputs.publish-target == 'pypi'
84+
run: make publish-pypi
85+
env:
86+
TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
87+
TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
88+
6489
- name: Show built version
6590
id: version
6691
run: |

Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,22 @@ endif
273273
dist/*.whl
274274
@echo "published: $$(ls dist/*.whl)"
275275

276+
.PHONY: publish-pypi
277+
publish-pypi: build-wheel ## Build and publish wheel to PyPI. Uses TWINE_USERNAME and TWINE_PASSWORD env vars.
278+
ifndef TWINE_USERNAME
279+
$(error TWINE_USERNAME is not set. For PyPI token auth, set TWINE_USERNAME=__token__.)
280+
endif
281+
ifndef TWINE_PASSWORD
282+
$(error TWINE_PASSWORD is not set. For PyPI token auth, set TWINE_PASSWORD=<your-pypi-token>.)
283+
endif
284+
@echo "~~~~~~"
285+
@echo "uploading to PyPI"
286+
uvx twine upload \
287+
--non-interactive \
288+
--verbose \
289+
dist/*.whl
290+
@echo "published: $$(ls dist/*.whl)"
291+
276292

277293
### NMP SYNCHRONIZATION ###
278294

0 commit comments

Comments
 (0)