發布流程¶
專案以三個彼此獨立的 PyPI distribution 發布:
| Distribution | 內容 | 使用者是否需要編譯 |
|---|---|---|
renewable-huber |
公開 Python API 與 NumPy backend | 否 |
renewable-huber-native-cpu |
Rust/Rayon CPU extension | 否;從對應平台 wheel 安裝 |
renewable-huber-native-cuda |
Rust/CUDA 12 extension | 否;發布 Windows x86-64 與 Linux x86-64(manylinux_2_28)wheels |
三個 distribution 在同一次 release 使用相同版本。Native wheel 會以精確相依條件
renewable-huber==X.Y.Z 鎖定 base package,避免 Python API、checkpoint 或 native ABI
不相容的組合被 pip 解析在一起。scripts/native/validate_release_artifacts.py 會在 CI
同時驗證來源 metadata 與最終 wheels。
v0.6.0 tag 曾用於未完成的發布流程,沒有成為正式 PyPI release。既有 tag 一律不可變,
不移動、不重用。本次發布使用 v0.7.1;GitHub Release notes 從上一個正式 release
v0.7.0 開始產生(release.yml 的 --notes-start-tag),每次發布都要把它改成上一個
正式 release 的 tag。
Wheel 支援範圍¶
CPU release matrix:
- CPython 3.10、3.11、3.12、3.13。
- manylinux2014 x86-64 與 aarch64。
- Windows x86-64。
- macOS x86-64 與 Apple Silicon arm64。
CUDA 12 release matrix 為 CPython 3.10–3.13 × Windows x86-64 與 Linux x86-64
(manylinux_2_28),共 8 個 wheels。Release fat binary 包含 SM 75、80、86、89、
90、120 SASS,並只為最高的 SM 120 保留 PTX,因此建置固定使用 CUDA Toolkit 12.9
(最低需 12.8 才能編譯 SM 120)。使用者安裝 wheel 時不需要 Rust、CMake、Visual
Studio 或 nvcc。Wheel 不封裝 NVIDIA 函式庫;cudart、cuBLAS/cuBLASLt、cuSOLVER、
cuSPARSE、nvJitLink runtime closure 以 nvidia-*-cu12 相依套件安裝,匯入時由
renewable_huber._cuda_runtime 載入;該組不完整時才退回系統 toolkit。
Linux CUDA wheels 在 quay.io/pypa/manylinux_2_28_x86_64 container 內由
scripts/native/build_linux_cuda_wheel.sh 建置,因此 wheel 宣告的 glibc 2.28 tag
對 binary 成立。腳本以 --auditwheel skip 刻意不 vendor NVIDIA 函式庫,並在
container 內用 cuobjdump 檢查 SASS/PTX,另拒絕宣告 runtime closure 以外的
NEEDED。兩個 workflow 以同一個 digest 固定這個 image;Dependabot 看不到 run:
步驟裡的 image,更新時需手動把兩處 digest 一起換掉。一般 PR CI 的 native-cuda-linux-wheel job 執行同一支腳本(縮小的
架構清單)並在無 GPU runner 上乾淨安裝、匯入,因此 release 路徑在 tag 前就已被
驗證。
CUDA wheels 在固定的 GitHub-hosted windows-2022 runner(Visual Studio 2022)
安裝 CUDA 12.9 build-only toolchain 後編譯;不用 windows-latest,因為它已移至
CUDA 12.9 尚未支援的 Visual Studio 2026。該 runner 沒有 GPU,也不執行 CUDA
runtime 測試。Pull request
與一般開發不使用 GitHub Actions GPU runner;correctness、profiling、乾淨安裝與
performance 驗證都在維護者的固定本機 GPU 主機執行。
macOS CPU wheels 使用 macos-15-intel(x86-64)與 macos-15(Apple Silicon);
不要恢復已停止支援、會永久排隊的 macos-13 標籤。
Release gate¶
- 更新
src/renewable_huber/_version.py,並同步兩個 nativepyproject.toml的版本及 精確 base dependency。 - 把
CHANGELOG.md的 Unreleased 內容移到該版本,確認授權與引用資訊。 - 在固定本機 GPU 主機完成 correctness、C ABI smoke 與 performance gates,保存
commit、環境指紋和 JSON 證據;合併至
main後等待一般 CI 與 CPU wheel clean-install 通過。 - 在 WSL2/Linux 本機先執行 metadata 與 required-profile dry-run:
.venv/bin/python scripts/native/validate_release_artifacts.py --source-only
.venv/bin/python scripts/run_test_profile.py --check
.venv/bin/python scripts/run_test_profile.py core --verbose
.venv/bin/python scripts/run_test_profile.py performance --verbose
- 在 GitHub 對
main手動執行release.yml。這是 build-only rehearsal:建置並 驗證完整 30 個 artifacts(base wheel 與 sdist、20 個 CPU wheels、8 個 CUDA wheels),但不建立 GitHub Release,也不發布到 PyPI/TestPyPI。 - 從已通過一般 CI 與 build-only rehearsal 的精確
maintip 建立vX.Y.Zannotated tag;若維護環境已有可信任簽章金鑰,則改用 signed tag。Release workflow 會拒絕版本不一致或不是目前maintip 的 tag。 - Workflow 建置 base wheel/sdist、20 個 CPU wheels(4 個 CPython × 5 個
OS/architecture targets)、8 個 CUDA wheels(4 個 CPython × Windows x86-64 與
Linux x86-64
manylinux_2_28),並執行 Twine、metadata、artifact-set、CUDA SASS/PTX 實體檢查,以及無 GPU 的 clean install/import ABI capability smoke;GPU correctness 與效能不在 GitHub Actions 執行,採用第 3 步的本機證據。 - 完整 artifact set 通過後才建立 GitHub Release。人工核准 PyPI 前,下載實際 CUDA artifacts 至固定 GPU 主機,對 artifact hash 執行最後 smoke。
- 三個 PyPI publish jobs 分別等待對應 GitHub Environment 的人工核准,再透過
Trusted Publishing/OIDC 發布;不儲存長效 API token。Native wheels 精確依賴同版
base,因此
pypi-native-cpu與pypi-native-cuda兩個 jobs 要等pypi(base) 發布成功後才會開始等待核准。
Release tag 範例:
git switch main
git pull --ff-only
git tag -a vX.Y.Z -m "renewable-huber vX.Y.Z"
git push origin vX.Y.Z
若已設定可信任的 Git signing key,可將 -a 改為 -s。
PyPI Trusted Publishing¶
三個 PyPI project 必須各自建立 pending publisher,並精確設定 repository、workflow 與 environment:
| PyPI project | Workflow | GitHub environment |
|---|---|---|
renewable-huber |
release.yml |
pypi |
renewable-huber-native-cpu |
release.yml |
pypi-native-cpu |
renewable-huber-native-cuda |
release.yml |
pypi-native-cuda |
三個 environment 均應啟用 required reviewer。即使有人誤推 tag,artifact 仍不會在未經 核准時上傳 PyPI。GitHub Release 可先建立供維護者下載與人工驗證。
TestPyPI workflow只 rehearsal base distribution;完整三套 distribution 的建置驗證
以 release.yml 的手動 build-only run 為準。正式 tag 前必須確認三個 PyPI pending
publisher(或既有 project publisher)的 owner、repository、workflow 與 environment
完全匹配,且 Environment tag rules 允許目標 tag。
安裝後驗證¶
CPU 使用者:
python -m pip install renewable-huber-native-cpu==0.7.1
python -c "from renewable_huber import RenewableHuberRegressor; print(RenewableHuberRegressor(backend='native_cpu', n_jobs=-1))"
CUDA 12 使用者:
python -m pip install renewable-huber-native-cuda==0.7.1
python -c "from renewable_huber import _native_cuda; print(_native_cuda.version()); print(_native_cuda.is_available())"
若 native distribution 已存在於 PyPI,禁止重新使用相同版本覆寫 wheel;修正版本與 changelog 後發布新的 patch release。