MasterJH5574 commented on code in PR #19641: URL: https://github.com/apache/tvm/pull/19641#discussion_r3326586716
########## .github/workflows/publish_wheel.yml: ########## @@ -0,0 +1,286 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Publish TVM wheels + +on: + workflow_dispatch: + inputs: + tag: + description: "Tag, branch, or SHA to build; PyPI publishes require refs/tags/<tag>" + required: true + type: string + publish_repository: + description: "Where to publish after the wheel build succeeds" + required: true + default: "none" + type: choice + options: + - none + - testpypi + - pypi + distribution_name: + description: "Optional package name override, e.g. tvm-yourname-test for TestPyPI" + required: false + default: "" + type: string + distribution_version: + description: "Optional package version override for TestPyPI validation builds" + required: false + default: "" + type: string + cuda_architectures: + description: "CMake CUDA architectures for libtvm_runtime_cuda.so" + required: false + default: "75" + type: string + verify_from_repository: + description: "Install the uploaded package from the selected repository and import-test it" + required: true + default: true + type: boolean + +permissions: + contents: read + +jobs: + build_wheels: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: "Linux x86_64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-latest + arch: x86_64 + build: cp310-manylinux_x86_64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-x86_64-manylinux_2_28 + - name: "Linux aarch64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-24.04-arm + arch: aarch64 + build: cp310-manylinux_aarch64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-aarch64-manylinux_2_28 + - name: "macOS arm64 CPU wheel" + os: macos-14 + arch: arm64 + build: cp310-macosx_arm64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: macos-arm64 + - name: "Windows AMD64 CPU wheel" + os: windows-latest + arch: AMD64 + build: cp310-win_amd64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: windows-amd64 + steps: + - name: Validate publish inputs + shell: bash + env: + TVM_PUBLISH_REPOSITORY: ${{ inputs.publish_repository }} + TVM_PUBLISH_REF: ${{ inputs.tag }} + TVM_VERIFY_FROM_REPOSITORY: ${{ inputs.verify_from_repository }} + TVM_WHEEL_DIST_NAME: ${{ inputs.distribution_name }} + TVM_WHEEL_DIST_VERSION: ${{ inputs.distribution_version }} + run: | + set -eux + if [[ -n "${TVM_WHEEL_DIST_NAME}" && ! "${TVM_WHEEL_DIST_NAME}" =~ ^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$ ]]; then + echo "distribution_name must be a valid Python package name override" >&2 + exit 1 + fi + if [[ -n "${TVM_WHEEL_DIST_VERSION}" && ! "${TVM_WHEEL_DIST_VERSION}" =~ ^[A-Za-z0-9][A-Za-z0-9._!+-]*$ ]]; then + echo "distribution_version must be a valid Python package version override" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_NAME}" ]]; then + echo "distribution_name must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_VERSION}" ]]; then + echo "distribution_version must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_PUBLISH_REF}" != refs/tags/* ]]; then + echo "PyPI publishes must use an immutable refs/tags/<tag> ref" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_VERIFY_FROM_REPOSITORY}" != "true" ]]; then + echo "verify_from_repository must be enabled when publishing to PyPI" >&2 + exit 1 + fi + + - name: Checkout source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 Review Comment: Use tag instead of hash. Same for other places. ########## .github/workflows/publish_wheel.yml: ########## @@ -0,0 +1,286 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Publish TVM wheels + +on: + workflow_dispatch: + inputs: + tag: + description: "Tag, branch, or SHA to build; PyPI publishes require refs/tags/<tag>" + required: true + type: string + publish_repository: + description: "Where to publish after the wheel build succeeds" + required: true + default: "none" + type: choice + options: + - none + - testpypi + - pypi + distribution_name: + description: "Optional package name override, e.g. tvm-yourname-test for TestPyPI" + required: false + default: "" + type: string + distribution_version: + description: "Optional package version override for TestPyPI validation builds" + required: false + default: "" + type: string + cuda_architectures: + description: "CMake CUDA architectures for libtvm_runtime_cuda.so" + required: false + default: "75" + type: string + verify_from_repository: + description: "Install the uploaded package from the selected repository and import-test it" + required: true + default: true + type: boolean + +permissions: + contents: read + +jobs: + build_wheels: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: "Linux x86_64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-latest + arch: x86_64 + build: cp310-manylinux_x86_64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-x86_64-manylinux_2_28 + - name: "Linux aarch64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-24.04-arm + arch: aarch64 + build: cp310-manylinux_aarch64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-aarch64-manylinux_2_28 + - name: "macOS arm64 CPU wheel" + os: macos-14 + arch: arm64 + build: cp310-macosx_arm64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: macos-arm64 + - name: "Windows AMD64 CPU wheel" + os: windows-latest + arch: AMD64 + build: cp310-win_amd64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: windows-amd64 + steps: + - name: Validate publish inputs + shell: bash + env: + TVM_PUBLISH_REPOSITORY: ${{ inputs.publish_repository }} + TVM_PUBLISH_REF: ${{ inputs.tag }} + TVM_VERIFY_FROM_REPOSITORY: ${{ inputs.verify_from_repository }} + TVM_WHEEL_DIST_NAME: ${{ inputs.distribution_name }} + TVM_WHEEL_DIST_VERSION: ${{ inputs.distribution_version }} + run: | + set -eux + if [[ -n "${TVM_WHEEL_DIST_NAME}" && ! "${TVM_WHEEL_DIST_NAME}" =~ ^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$ ]]; then + echo "distribution_name must be a valid Python package name override" >&2 + exit 1 + fi + if [[ -n "${TVM_WHEEL_DIST_VERSION}" && ! "${TVM_WHEEL_DIST_VERSION}" =~ ^[A-Za-z0-9][A-Za-z0-9._!+-]*$ ]]; then + echo "distribution_version must be a valid Python package version override" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_NAME}" ]]; then + echo "distribution_name must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_VERSION}" ]]; then + echo "distribution_version must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_PUBLISH_REF}" != refs/tags/* ]]; then + echo "PyPI publishes must use an immutable refs/tags/<tag> ref" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_VERIFY_FROM_REPOSITORY}" != "true" ]]; then + echo "verify_from_repository must be enabled when publishing to PyPI" >&2 + exit 1 + fi + + - name: Checkout source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ inputs.tag }} + submodules: recursive + fetch-depth: 1 + fetch-tags: true + + - name: Build CUDA runtime + id: build_cuda + uses: ./.github/actions/build-cuda + with: + arch: ${{ matrix.arch }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + + - name: Build TVM wheel + uses: ./.github/actions/build-wheel-for-publish + with: + arch: ${{ matrix.arch }} + build: ${{ matrix.build }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + distribution_name: ${{ inputs.distribution_name }} + distribution_version: ${{ inputs.distribution_version }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + cuda_runtime_path: ${{ steps.build_cuda.outputs.cuda_runtime_path }} + + - name: Upload wheel artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: tvm-wheel-${{ matrix.artifact_suffix }} + path: wheelhouse/*.whl + if-no-files-found: error + + upload_pypi: + name: Upload package distributions + needs: [build_wheels] + if: ${{ inputs.publish_repository != 'none' }} + runs-on: ubuntu-latest + environment: ${{ inputs.publish_repository }} + permissions: + actions: read + contents: read + id-token: write + attestations: write + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: tvm-wheel-* + path: dist + merge-multiple: true + + - name: Check wheel sizes + shell: bash + run: | + set -euo pipefail + limit_bytes=100000000 + shopt -s nullglob + wheels=(dist/*.whl) + if [[ "${#wheels[@]}" -eq 0 ]]; then + echo "No wheel artifacts found under dist/" >&2 + exit 1 + fi + if [[ "${#wheels[@]}" -ne 4 ]]; then + echo "Expected 4 wheel artifacts, found ${#wheels[@]}" >&2 + printf '%s\n' "${wheels[@]}" >&2 + exit 1 + fi + failed=0 + for wheel in "${wheels[@]}"; do + size="$(stat -c '%s' "$wheel")" + printf '%s %s bytes\n' "$wheel" "$size" + if (( size > limit_bytes )); then + echo "Wheel exceeds 100 MB PyPI/TestPyPI upload limit: ${wheel}" >&2 + failed=1 + fi + done + exit "$failed" Review Comment: Do we need to manual check? I assume it will automatically fail at the publish step if the wheel is larger than 100MB? ########## .github/workflows/publish_wheel.yml: ########## @@ -0,0 +1,286 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Publish TVM wheels + +on: + workflow_dispatch: + inputs: + tag: + description: "Tag, branch, or SHA to build; PyPI publishes require refs/tags/<tag>" + required: true + type: string + publish_repository: + description: "Where to publish after the wheel build succeeds" + required: true + default: "none" + type: choice + options: + - none Review Comment: What does "none" mean? If it means a build dryrun, maybe add a brief comment about it. ########## .github/workflows/publish_wheel.yml: ########## @@ -0,0 +1,286 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Publish TVM wheels + +on: + workflow_dispatch: + inputs: + tag: + description: "Tag, branch, or SHA to build; PyPI publishes require refs/tags/<tag>" + required: true + type: string + publish_repository: + description: "Where to publish after the wheel build succeeds" + required: true + default: "none" + type: choice + options: + - none + - testpypi + - pypi + distribution_name: + description: "Optional package name override, e.g. tvm-yourname-test for TestPyPI" + required: false + default: "" + type: string + distribution_version: + description: "Optional package version override for TestPyPI validation builds" + required: false + default: "" + type: string + cuda_architectures: + description: "CMake CUDA architectures for libtvm_runtime_cuda.so" + required: false + default: "75" + type: string + verify_from_repository: + description: "Install the uploaded package from the selected repository and import-test it" + required: true + default: true + type: boolean + +permissions: + contents: read + +jobs: + build_wheels: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: "Linux x86_64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-latest + arch: x86_64 + build: cp310-manylinux_x86_64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-x86_64-manylinux_2_28 + - name: "Linux aarch64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-24.04-arm + arch: aarch64 + build: cp310-manylinux_aarch64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-aarch64-manylinux_2_28 + - name: "macOS arm64 CPU wheel" + os: macos-14 + arch: arm64 + build: cp310-macosx_arm64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: macos-arm64 + - name: "Windows AMD64 CPU wheel" + os: windows-latest + arch: AMD64 + build: cp310-win_amd64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: windows-amd64 + steps: + - name: Validate publish inputs + shell: bash + env: + TVM_PUBLISH_REPOSITORY: ${{ inputs.publish_repository }} + TVM_PUBLISH_REF: ${{ inputs.tag }} + TVM_VERIFY_FROM_REPOSITORY: ${{ inputs.verify_from_repository }} + TVM_WHEEL_DIST_NAME: ${{ inputs.distribution_name }} + TVM_WHEEL_DIST_VERSION: ${{ inputs.distribution_version }} + run: | + set -eux + if [[ -n "${TVM_WHEEL_DIST_NAME}" && ! "${TVM_WHEEL_DIST_NAME}" =~ ^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$ ]]; then + echo "distribution_name must be a valid Python package name override" >&2 + exit 1 + fi + if [[ -n "${TVM_WHEEL_DIST_VERSION}" && ! "${TVM_WHEEL_DIST_VERSION}" =~ ^[A-Za-z0-9][A-Za-z0-9._!+-]*$ ]]; then + echo "distribution_version must be a valid Python package version override" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_NAME}" ]]; then + echo "distribution_name must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_VERSION}" ]]; then + echo "distribution_version must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_PUBLISH_REF}" != refs/tags/* ]]; then + echo "PyPI publishes must use an immutable refs/tags/<tag> ref" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_VERIFY_FROM_REPOSITORY}" != "true" ]]; then + echo "verify_from_repository must be enabled when publishing to PyPI" >&2 + exit 1 + fi + + - name: Checkout source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ inputs.tag }} + submodules: recursive + fetch-depth: 1 + fetch-tags: true + + - name: Build CUDA runtime + id: build_cuda + uses: ./.github/actions/build-cuda + with: + arch: ${{ matrix.arch }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + + - name: Build TVM wheel + uses: ./.github/actions/build-wheel-for-publish + with: + arch: ${{ matrix.arch }} + build: ${{ matrix.build }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + distribution_name: ${{ inputs.distribution_name }} + distribution_version: ${{ inputs.distribution_version }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + cuda_runtime_path: ${{ steps.build_cuda.outputs.cuda_runtime_path }} + + - name: Upload wheel artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: tvm-wheel-${{ matrix.artifact_suffix }} + path: wheelhouse/*.whl + if-no-files-found: error + + upload_pypi: + name: Upload package distributions + needs: [build_wheels] + if: ${{ inputs.publish_repository != 'none' }} + runs-on: ubuntu-latest + environment: ${{ inputs.publish_repository }} + permissions: + actions: read + contents: read + id-token: write + attestations: write Review Comment: Are the permissions necessary? ########## .github/workflows/publish_wheel.yml: ########## @@ -0,0 +1,286 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Publish TVM wheels + +on: + workflow_dispatch: + inputs: + tag: + description: "Tag, branch, or SHA to build; PyPI publishes require refs/tags/<tag>" + required: true + type: string + publish_repository: + description: "Where to publish after the wheel build succeeds" + required: true + default: "none" + type: choice + options: + - none + - testpypi + - pypi + distribution_name: + description: "Optional package name override, e.g. tvm-yourname-test for TestPyPI" + required: false + default: "" + type: string + distribution_version: + description: "Optional package version override for TestPyPI validation builds" + required: false + default: "" + type: string + cuda_architectures: + description: "CMake CUDA architectures for libtvm_runtime_cuda.so" + required: false + default: "75" + type: string + verify_from_repository: + description: "Install the uploaded package from the selected repository and import-test it" + required: true + default: true + type: boolean + +permissions: + contents: read + +jobs: + build_wheels: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: "Linux x86_64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-latest + arch: x86_64 + build: cp310-manylinux_x86_64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-x86_64-manylinux_2_28 + - name: "Linux aarch64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-24.04-arm + arch: aarch64 + build: cp310-manylinux_aarch64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-aarch64-manylinux_2_28 + - name: "macOS arm64 CPU wheel" + os: macos-14 + arch: arm64 + build: cp310-macosx_arm64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: macos-arm64 + - name: "Windows AMD64 CPU wheel" + os: windows-latest + arch: AMD64 + build: cp310-win_amd64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: windows-amd64 + steps: + - name: Validate publish inputs + shell: bash + env: + TVM_PUBLISH_REPOSITORY: ${{ inputs.publish_repository }} + TVM_PUBLISH_REF: ${{ inputs.tag }} + TVM_VERIFY_FROM_REPOSITORY: ${{ inputs.verify_from_repository }} + TVM_WHEEL_DIST_NAME: ${{ inputs.distribution_name }} + TVM_WHEEL_DIST_VERSION: ${{ inputs.distribution_version }} + run: | + set -eux + if [[ -n "${TVM_WHEEL_DIST_NAME}" && ! "${TVM_WHEEL_DIST_NAME}" =~ ^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$ ]]; then + echo "distribution_name must be a valid Python package name override" >&2 + exit 1 + fi + if [[ -n "${TVM_WHEEL_DIST_VERSION}" && ! "${TVM_WHEEL_DIST_VERSION}" =~ ^[A-Za-z0-9][A-Za-z0-9._!+-]*$ ]]; then + echo "distribution_version must be a valid Python package version override" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_NAME}" ]]; then + echo "distribution_name must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_VERSION}" ]]; then + echo "distribution_version must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_PUBLISH_REF}" != refs/tags/* ]]; then + echo "PyPI publishes must use an immutable refs/tags/<tag> ref" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_VERIFY_FROM_REPOSITORY}" != "true" ]]; then + echo "verify_from_repository must be enabled when publishing to PyPI" >&2 + exit 1 + fi + + - name: Checkout source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ inputs.tag }} + submodules: recursive + fetch-depth: 1 + fetch-tags: true + + - name: Build CUDA runtime + id: build_cuda + uses: ./.github/actions/build-cuda + with: + arch: ${{ matrix.arch }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + + - name: Build TVM wheel + uses: ./.github/actions/build-wheel-for-publish + with: + arch: ${{ matrix.arch }} + build: ${{ matrix.build }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + distribution_name: ${{ inputs.distribution_name }} + distribution_version: ${{ inputs.distribution_version }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + cuda_runtime_path: ${{ steps.build_cuda.outputs.cuda_runtime_path }} + + - name: Upload wheel artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: tvm-wheel-${{ matrix.artifact_suffix }} + path: wheelhouse/*.whl + if-no-files-found: error + + upload_pypi: + name: Upload package distributions + needs: [build_wheels] + if: ${{ inputs.publish_repository != 'none' }} + runs-on: ubuntu-latest + environment: ${{ inputs.publish_repository }} + permissions: + actions: read + contents: read + id-token: write + attestations: write + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: tvm-wheel-* + path: dist + merge-multiple: true + + - name: Check wheel sizes + shell: bash + run: | + set -euo pipefail + limit_bytes=100000000 + shopt -s nullglob + wheels=(dist/*.whl) + if [[ "${#wheels[@]}" -eq 0 ]]; then + echo "No wheel artifacts found under dist/" >&2 + exit 1 + fi + if [[ "${#wheels[@]}" -ne 4 ]]; then + echo "Expected 4 wheel artifacts, found ${#wheels[@]}" >&2 + printf '%s\n' "${wheels[@]}" >&2 + exit 1 + fi + failed=0 + for wheel in "${wheels[@]}"; do + size="$(stat -c '%s' "$wheel")" + printf '%s %s bytes\n' "$wheel" "$size" + if (( size > limit_bytes )); then + echo "Wheel exceeds 100 MB PyPI/TestPyPI upload limit: ${wheel}" >&2 + failed=1 + fi + done + exit "$failed" + + - name: Generate artifact attestation for wheels + uses: actions/attest-build-provenance@v1 + with: + subject-path: dist/* Review Comment: I was wondering what this is used for. ########## .github/workflows/publish_wheel.yml: ########## @@ -0,0 +1,286 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Publish TVM wheels + +on: + workflow_dispatch: + inputs: + tag: + description: "Tag, branch, or SHA to build; PyPI publishes require refs/tags/<tag>" + required: true + type: string + publish_repository: + description: "Where to publish after the wheel build succeeds" + required: true + default: "none" + type: choice + options: + - none + - testpypi + - pypi + distribution_name: + description: "Optional package name override, e.g. tvm-yourname-test for TestPyPI" + required: false + default: "" + type: string + distribution_version: + description: "Optional package version override for TestPyPI validation builds" + required: false + default: "" + type: string + cuda_architectures: + description: "CMake CUDA architectures for libtvm_runtime_cuda.so" + required: false + default: "75" + type: string + verify_from_repository: + description: "Install the uploaded package from the selected repository and import-test it" + required: true + default: true + type: boolean + +permissions: + contents: read + +jobs: + build_wheels: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: "Linux x86_64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-latest + arch: x86_64 + build: cp310-manylinux_x86_64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-x86_64-manylinux_2_28 + - name: "Linux aarch64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-24.04-arm + arch: aarch64 + build: cp310-manylinux_aarch64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-aarch64-manylinux_2_28 + - name: "macOS arm64 CPU wheel" + os: macos-14 + arch: arm64 + build: cp310-macosx_arm64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: macos-arm64 + - name: "Windows AMD64 CPU wheel" + os: windows-latest + arch: AMD64 + build: cp310-win_amd64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: windows-amd64 + steps: + - name: Validate publish inputs + shell: bash + env: + TVM_PUBLISH_REPOSITORY: ${{ inputs.publish_repository }} + TVM_PUBLISH_REF: ${{ inputs.tag }} + TVM_VERIFY_FROM_REPOSITORY: ${{ inputs.verify_from_repository }} + TVM_WHEEL_DIST_NAME: ${{ inputs.distribution_name }} + TVM_WHEEL_DIST_VERSION: ${{ inputs.distribution_version }} + run: | + set -eux + if [[ -n "${TVM_WHEEL_DIST_NAME}" && ! "${TVM_WHEEL_DIST_NAME}" =~ ^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$ ]]; then + echo "distribution_name must be a valid Python package name override" >&2 + exit 1 + fi + if [[ -n "${TVM_WHEEL_DIST_VERSION}" && ! "${TVM_WHEEL_DIST_VERSION}" =~ ^[A-Za-z0-9][A-Za-z0-9._!+-]*$ ]]; then + echo "distribution_version must be a valid Python package version override" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_NAME}" ]]; then + echo "distribution_name must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_VERSION}" ]]; then + echo "distribution_version must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_PUBLISH_REF}" != refs/tags/* ]]; then + echo "PyPI publishes must use an immutable refs/tags/<tag> ref" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_VERIFY_FROM_REPOSITORY}" != "true" ]]; then + echo "verify_from_repository must be enabled when publishing to PyPI" >&2 + exit 1 + fi + + - name: Checkout source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ inputs.tag }} + submodules: recursive + fetch-depth: 1 + fetch-tags: true + + - name: Build CUDA runtime + id: build_cuda + uses: ./.github/actions/build-cuda + with: + arch: ${{ matrix.arch }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + + - name: Build TVM wheel + uses: ./.github/actions/build-wheel-for-publish + with: + arch: ${{ matrix.arch }} + build: ${{ matrix.build }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + distribution_name: ${{ inputs.distribution_name }} + distribution_version: ${{ inputs.distribution_version }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + cuda_runtime_path: ${{ steps.build_cuda.outputs.cuda_runtime_path }} + + - name: Upload wheel artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: tvm-wheel-${{ matrix.artifact_suffix }} + path: wheelhouse/*.whl + if-no-files-found: error + + upload_pypi: + name: Upload package distributions + needs: [build_wheels] + if: ${{ inputs.publish_repository != 'none' }} + runs-on: ubuntu-latest + environment: ${{ inputs.publish_repository }} + permissions: + actions: read + contents: read + id-token: write + attestations: write + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: tvm-wheel-* + path: dist + merge-multiple: true + + - name: Check wheel sizes + shell: bash + run: | + set -euo pipefail + limit_bytes=100000000 + shopt -s nullglob + wheels=(dist/*.whl) + if [[ "${#wheels[@]}" -eq 0 ]]; then + echo "No wheel artifacts found under dist/" >&2 + exit 1 + fi + if [[ "${#wheels[@]}" -ne 4 ]]; then + echo "Expected 4 wheel artifacts, found ${#wheels[@]}" >&2 + printf '%s\n' "${wheels[@]}" >&2 + exit 1 + fi + failed=0 + for wheel in "${wheels[@]}"; do + size="$(stat -c '%s' "$wheel")" + printf '%s %s bytes\n' "$wheel" "$size" + if (( size > limit_bytes )); then + echo "Wheel exceeds 100 MB PyPI/TestPyPI upload limit: ${wheel}" >&2 + failed=1 + fi + done + exit "$failed" + + - name: Generate artifact attestation for wheels + uses: actions/attest-build-provenance@v1 + with: + subject-path: dist/* + + - name: Publish package distributions to TestPyPI + if: ${{ inputs.publish_repository == 'testpypi' }} + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + attestations: true + verbose: true + repository-url: https://test.pypi.org/legacy/ + + - name: Publish package distributions to PyPI + if: ${{ inputs.publish_repository == 'pypi' }} + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + attestations: true + verbose: true + + verify_pypi: + name: Verify uploaded package + needs: [upload_pypi] + if: ${{ inputs.publish_repository != 'none' && inputs.verify_from_repository }} + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + steps: + - name: Check out source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ inputs.tag }} + submodules: recursive + fetch-depth: 0 + fetch-tags: true + + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: tvm-wheel-linux-x86_64-manylinux_2_28 + path: wheelhouse + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Verify package from TestPyPI + if: ${{ inputs.publish_repository == 'testpypi' }} + env: + TVM_PYTHON: python + TVM_TEST_INDEX_URL: https://test.pypi.org/simple/ + TVM_EXTRA_INDEX_URL: https://pypi.org/simple + TVM_EXPECT_LLVM_ENABLED: "1" + TVM_EXPECT_STATIC_LLVM: "1" + TVM_EXPECT_CUDA_RUNTIME: "1" + run: ci/scripts/package/tvm_wheel_helper.sh verify-pypi + + - name: Verify package from PyPI + if: ${{ inputs.publish_repository == 'pypi' }} + env: + TVM_PYTHON: python + TVM_TEST_INDEX_URL: https://pypi.org/simple/ + TVM_EXTRA_INDEX_URL: https://pypi.org/simple + TVM_EXPECT_LLVM_ENABLED: "1" + TVM_EXPECT_STATIC_LLVM: "1" + TVM_EXPECT_CUDA_RUNTIME: "1" + run: ci/scripts/package/tvm_wheel_helper.sh verify-pypi Review Comment: I wonder if it's possible to merge these two as well. ########## .github/workflows/publish_wheel.yml: ########## @@ -0,0 +1,286 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Publish TVM wheels + +on: + workflow_dispatch: + inputs: + tag: + description: "Tag, branch, or SHA to build; PyPI publishes require refs/tags/<tag>" + required: true + type: string + publish_repository: + description: "Where to publish after the wheel build succeeds" + required: true + default: "none" + type: choice + options: + - none + - testpypi + - pypi + distribution_name: + description: "Optional package name override, e.g. tvm-yourname-test for TestPyPI" + required: false + default: "" + type: string + distribution_version: + description: "Optional package version override for TestPyPI validation builds" + required: false + default: "" + type: string + cuda_architectures: + description: "CMake CUDA architectures for libtvm_runtime_cuda.so" + required: false + default: "75" + type: string + verify_from_repository: + description: "Install the uploaded package from the selected repository and import-test it" + required: true + default: true + type: boolean + +permissions: + contents: read + +jobs: + build_wheels: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: "Linux x86_64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-latest + arch: x86_64 + build: cp310-manylinux_x86_64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-x86_64-manylinux_2_28 + - name: "Linux aarch64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-24.04-arm + arch: aarch64 + build: cp310-manylinux_aarch64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-aarch64-manylinux_2_28 + - name: "macOS arm64 CPU wheel" + os: macos-14 + arch: arm64 + build: cp310-macosx_arm64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: macos-arm64 + - name: "Windows AMD64 CPU wheel" + os: windows-latest + arch: AMD64 + build: cp310-win_amd64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: windows-amd64 + steps: + - name: Validate publish inputs + shell: bash + env: + TVM_PUBLISH_REPOSITORY: ${{ inputs.publish_repository }} + TVM_PUBLISH_REF: ${{ inputs.tag }} + TVM_VERIFY_FROM_REPOSITORY: ${{ inputs.verify_from_repository }} + TVM_WHEEL_DIST_NAME: ${{ inputs.distribution_name }} + TVM_WHEEL_DIST_VERSION: ${{ inputs.distribution_version }} + run: | + set -eux + if [[ -n "${TVM_WHEEL_DIST_NAME}" && ! "${TVM_WHEEL_DIST_NAME}" =~ ^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$ ]]; then + echo "distribution_name must be a valid Python package name override" >&2 + exit 1 + fi + if [[ -n "${TVM_WHEEL_DIST_VERSION}" && ! "${TVM_WHEEL_DIST_VERSION}" =~ ^[A-Za-z0-9][A-Za-z0-9._!+-]*$ ]]; then + echo "distribution_version must be a valid Python package version override" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_NAME}" ]]; then + echo "distribution_name must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_VERSION}" ]]; then + echo "distribution_version must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_PUBLISH_REF}" != refs/tags/* ]]; then + echo "PyPI publishes must use an immutable refs/tags/<tag> ref" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_VERIFY_FROM_REPOSITORY}" != "true" ]]; then + echo "verify_from_repository must be enabled when publishing to PyPI" >&2 + exit 1 + fi + + - name: Checkout source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ inputs.tag }} + submodules: recursive + fetch-depth: 1 + fetch-tags: true + + - name: Build CUDA runtime + id: build_cuda + uses: ./.github/actions/build-cuda + with: + arch: ${{ matrix.arch }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + + - name: Build TVM wheel + uses: ./.github/actions/build-wheel-for-publish + with: + arch: ${{ matrix.arch }} + build: ${{ matrix.build }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + distribution_name: ${{ inputs.distribution_name }} + distribution_version: ${{ inputs.distribution_version }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + cuda_runtime_path: ${{ steps.build_cuda.outputs.cuda_runtime_path }} + + - name: Upload wheel artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: tvm-wheel-${{ matrix.artifact_suffix }} + path: wheelhouse/*.whl + if-no-files-found: error + + upload_pypi: + name: Upload package distributions + needs: [build_wheels] + if: ${{ inputs.publish_repository != 'none' }} + runs-on: ubuntu-latest + environment: ${{ inputs.publish_repository }} + permissions: + actions: read + contents: read + id-token: write + attestations: write + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: tvm-wheel-* + path: dist + merge-multiple: true + + - name: Check wheel sizes + shell: bash + run: | + set -euo pipefail + limit_bytes=100000000 + shopt -s nullglob + wheels=(dist/*.whl) + if [[ "${#wheels[@]}" -eq 0 ]]; then + echo "No wheel artifacts found under dist/" >&2 + exit 1 + fi + if [[ "${#wheels[@]}" -ne 4 ]]; then + echo "Expected 4 wheel artifacts, found ${#wheels[@]}" >&2 + printf '%s\n' "${wheels[@]}" >&2 + exit 1 + fi + failed=0 + for wheel in "${wheels[@]}"; do + size="$(stat -c '%s' "$wheel")" + printf '%s %s bytes\n' "$wheel" "$size" + if (( size > limit_bytes )); then + echo "Wheel exceeds 100 MB PyPI/TestPyPI upload limit: ${wheel}" >&2 + failed=1 + fi + done + exit "$failed" + + - name: Generate artifact attestation for wheels + uses: actions/attest-build-provenance@v1 + with: + subject-path: dist/* + + - name: Publish package distributions to TestPyPI + if: ${{ inputs.publish_repository == 'testpypi' }} + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + attestations: true + verbose: true + repository-url: https://test.pypi.org/legacy/ + + - name: Publish package distributions to PyPI + if: ${{ inputs.publish_repository == 'pypi' }} + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + attestations: true + verbose: true + + verify_pypi: + name: Verify uploaded package + needs: [upload_pypi] + if: ${{ inputs.publish_repository != 'none' && inputs.verify_from_repository }} + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + steps: + - name: Check out source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ inputs.tag }} + submodules: recursive + fetch-depth: 0 + fetch-tags: true + + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: tvm-wheel-linux-x86_64-manylinux_2_28 + path: wheelhouse Review Comment: Do we need checkout and artifact download here? ########## .github/workflows/publish_wheel.yml: ########## @@ -0,0 +1,286 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Publish TVM wheels + +on: + workflow_dispatch: + inputs: + tag: + description: "Tag, branch, or SHA to build; PyPI publishes require refs/tags/<tag>" + required: true + type: string + publish_repository: + description: "Where to publish after the wheel build succeeds" + required: true + default: "none" + type: choice + options: + - none + - testpypi + - pypi + distribution_name: + description: "Optional package name override, e.g. tvm-yourname-test for TestPyPI" + required: false + default: "" + type: string + distribution_version: + description: "Optional package version override for TestPyPI validation builds" + required: false + default: "" + type: string + cuda_architectures: + description: "CMake CUDA architectures for libtvm_runtime_cuda.so" + required: false + default: "75" + type: string + verify_from_repository: + description: "Install the uploaded package from the selected repository and import-test it" + required: true + default: true + type: boolean + +permissions: + contents: read + +jobs: + build_wheels: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: "Linux x86_64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-latest + arch: x86_64 + build: cp310-manylinux_x86_64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-x86_64-manylinux_2_28 + - name: "Linux aarch64 wheel with CUDA runtime (manylinux_2_28)" + os: ubuntu-24.04-arm + arch: aarch64 + build: cp310-manylinux_aarch64 + linux_image: manylinux_2_28 + linux_image_tag: "2026.01.04-1" + include_cuda_runtime: "true" + artifact_suffix: linux-aarch64-manylinux_2_28 + - name: "macOS arm64 CPU wheel" + os: macos-14 + arch: arm64 + build: cp310-macosx_arm64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: macos-arm64 + - name: "Windows AMD64 CPU wheel" + os: windows-latest + arch: AMD64 + build: cp310-win_amd64 + linux_image: "" + linux_image_tag: "" + include_cuda_runtime: "false" + artifact_suffix: windows-amd64 + steps: + - name: Validate publish inputs + shell: bash + env: + TVM_PUBLISH_REPOSITORY: ${{ inputs.publish_repository }} + TVM_PUBLISH_REF: ${{ inputs.tag }} + TVM_VERIFY_FROM_REPOSITORY: ${{ inputs.verify_from_repository }} + TVM_WHEEL_DIST_NAME: ${{ inputs.distribution_name }} + TVM_WHEEL_DIST_VERSION: ${{ inputs.distribution_version }} + run: | + set -eux + if [[ -n "${TVM_WHEEL_DIST_NAME}" && ! "${TVM_WHEEL_DIST_NAME}" =~ ^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$ ]]; then + echo "distribution_name must be a valid Python package name override" >&2 + exit 1 + fi + if [[ -n "${TVM_WHEEL_DIST_VERSION}" && ! "${TVM_WHEEL_DIST_VERSION}" =~ ^[A-Za-z0-9][A-Za-z0-9._!+-]*$ ]]; then + echo "distribution_version must be a valid Python package version override" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_NAME}" ]]; then + echo "distribution_name must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && -n "${TVM_WHEEL_DIST_VERSION}" ]]; then + echo "distribution_version must be empty when publishing to PyPI" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_PUBLISH_REF}" != refs/tags/* ]]; then + echo "PyPI publishes must use an immutable refs/tags/<tag> ref" >&2 + exit 1 + fi + if [[ "${TVM_PUBLISH_REPOSITORY}" == "pypi" && "${TVM_VERIFY_FROM_REPOSITORY}" != "true" ]]; then + echo "verify_from_repository must be enabled when publishing to PyPI" >&2 + exit 1 + fi + + - name: Checkout source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ inputs.tag }} + submodules: recursive + fetch-depth: 1 + fetch-tags: true + + - name: Build CUDA runtime + id: build_cuda + uses: ./.github/actions/build-cuda + with: + arch: ${{ matrix.arch }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + + - name: Build TVM wheel + uses: ./.github/actions/build-wheel-for-publish + with: + arch: ${{ matrix.arch }} + build: ${{ matrix.build }} + linux_image: ${{ matrix.linux_image }} + linux_image_tag: ${{ matrix.linux_image_tag }} + distribution_name: ${{ inputs.distribution_name }} + distribution_version: ${{ inputs.distribution_version }} + cuda_architectures: ${{ inputs.cuda_architectures }} + include_cuda_runtime: ${{ matrix.include_cuda_runtime }} + cuda_runtime_path: ${{ steps.build_cuda.outputs.cuda_runtime_path }} + + - name: Upload wheel artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: tvm-wheel-${{ matrix.artifact_suffix }} + path: wheelhouse/*.whl + if-no-files-found: error + + upload_pypi: + name: Upload package distributions + needs: [build_wheels] + if: ${{ inputs.publish_repository != 'none' }} + runs-on: ubuntu-latest + environment: ${{ inputs.publish_repository }} + permissions: + actions: read + contents: read + id-token: write + attestations: write + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: tvm-wheel-* + path: dist + merge-multiple: true + + - name: Check wheel sizes + shell: bash + run: | + set -euo pipefail + limit_bytes=100000000 + shopt -s nullglob + wheels=(dist/*.whl) + if [[ "${#wheels[@]}" -eq 0 ]]; then + echo "No wheel artifacts found under dist/" >&2 + exit 1 + fi + if [[ "${#wheels[@]}" -ne 4 ]]; then + echo "Expected 4 wheel artifacts, found ${#wheels[@]}" >&2 + printf '%s\n' "${wheels[@]}" >&2 + exit 1 + fi + failed=0 + for wheel in "${wheels[@]}"; do + size="$(stat -c '%s' "$wheel")" + printf '%s %s bytes\n' "$wheel" "$size" + if (( size > limit_bytes )); then + echo "Wheel exceeds 100 MB PyPI/TestPyPI upload limit: ${wheel}" >&2 + failed=1 + fi + done + exit "$failed" + + - name: Generate artifact attestation for wheels + uses: actions/attest-build-provenance@v1 + with: + subject-path: dist/* + + - name: Publish package distributions to TestPyPI + if: ${{ inputs.publish_repository == 'testpypi' }} + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + attestations: true + verbose: true + repository-url: https://test.pypi.org/legacy/ + + - name: Publish package distributions to PyPI + if: ${{ inputs.publish_repository == 'pypi' }} + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + attestations: true + verbose: true Review Comment: Not sure if it's possible to merge these two branches. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
