This is an automated email from the ASF dual-hosted git repository.

Seven-Streams pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new 54a51b2d [CI][Rust] Publish crates manually from release tags (#837)
54a51b2d is described below

commit 54a51b2df86a5024dc0c9d8908aab81fd4ecbd71
Author: Linzhang Li <[email protected]>
AuthorDate: Mon Oct 5 19:34:12 2026 -0400

    [CI][Rust] Publish crates manually from release tags (#837)
    
    Add a manually triggered workflow to build, test, package, and publish
    all
    three Rust crates. The required `tag` must already exist in the remote
    repository; the workflow checks out its corresponding commit. Match the
    PyPI matrix: Linux x86_64/aarch64, Windows AMD64, and macOS arm64.
    
    Derive crate and internal dependency versions from the selected Git tag
    (e.g. `v0.1.14`, `v0.1.14-post1`), replacing the development
    placeholders
    in the CI checkout.
    
    Default to `dry_run=true`: run publication checks on every platform and
    retain
    crate artifacts without uploading to crates.io or requiring a token.
    With
    `dry_run=false`, publish in dependency order after all matrix jobs pass,
    using `CARGO_REGISTRY_TOKEN`.
    
    Validation: pre-commit, actionlint, local Linux release builds/tests,
    version
    mapping, crate packaging, and publication dry-runs passed. No live
    upload.
    
    ---------
    
    Signed-off-by: yuchuan <[email protected]>
---
 .github/workflows/publish_crates.yml | 202 +++++++++++++++++++++++++++++++++++
 pyproject.toml                       |   3 +-
 rust/tvm-ffi-macros/Cargo.toml       |   1 +
 rust/tvm-ffi-sys/Cargo.toml          |   1 +
 rust/tvm-ffi/Cargo.toml              |   2 +
 5 files changed, 208 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/publish_crates.yml 
b/.github/workflows/publish_crates.yml
new file mode 100644
index 00000000..a8f0afff
--- /dev/null
+++ b/.github/workflows/publish_crates.yml
@@ -0,0 +1,202 @@
+# 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 crates
+
+on:
+  workflow_dispatch:
+    inputs:
+      tag:
+        description: "Tag to publish (manual run)"
+        required: true
+        type: string
+      dry_run:
+        description: "Build and verify crates without publishing to crates.io"
+        required: true
+        type: boolean
+        default: true
+
+permissions:
+  contents: read
+
+concurrency:
+  group: publish-crates-${{ inputs.tag }}
+  cancel-in-progress: false
+
+env:
+  CARGO_TERM_COLOR: always
+  RELEASE_TAG: ${{ inputs.tag }}
+
+jobs:
+  build_crates:
+    name: ${{ matrix.os }} (${{ matrix.arch }})
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        # Keep the OS/architecture matrix in sync with publish_wheel.yml.
+        include:
+          - {os: ubuntu-latest, arch: x86_64}
+          - {os: ubuntu-24.04-arm, arch: aarch64}
+          - {os: windows-latest, arch: AMD64}
+          - {os: macos-14, arch: arm64}
+
+    steps:
+      - name: Check out release source
+        uses: actions/checkout@v5
+        with:
+          ref: refs/tags/${{ inputs.tag }}
+          submodules: recursive
+          fetch-depth: 0
+          fetch-tags: true
+
+      - name: Set up uv
+        uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7  # 
v10.2.0
+        with:
+          python-version: "3.13"
+          activate-environment: true
+
+      # Workspace publishing and dry-runs require Cargo 1.90 or newer.
+      - name: Set up Rust
+        run: rustup toolchain install stable --profile minimal
+
+      - uses: ./.github/actions/detect-env-vars
+        id: env_vars
+
+      # tvm-ffi-sys locates libtvm_ffi through tvm-ffi-config on PATH.
+      - name: Build and install TVM FFI
+        env:
+          CMAKE_BUILD_PARALLEL_LEVEL: ${{ steps.env_vars.outputs.cpu_count }}
+        run: uv pip install --verbose .
+
+      # Apply the release version after the Python build so setuptools-scm 
sees a clean tree.
+      - name: Set crate versions from Git
+        shell: bash
+        run: &set_crate_versions |
+          # The crate version is the tag without its "v": 0.1.15, 0.1.15-rc0 
or 0.1.14-post1.
+          if [[ ! "$RELEASE_TAG" =~ 
^v[0-9]+\.[0-9]+\.[0-9]+(-(rc|post)[0-9]+)?$ ]]; then
+            echo "::error::unsupported release tag '$RELEASE_TAG': expected 
vX.Y.Z, vX.Y.Z-rcN or vX.Y.Z-postN"
+            exit 1
+          fi
+          export CRATE_VERSION="${RELEASE_TAG#v}"
+          echo "CRATE_VERSION=$CRATE_VERSION" >> "$GITHUB_ENV"
+          uv run --no-project --with tomlkit python - <<'PY'
+          import os
+          from pathlib import Path
+
+          import tomlkit
+
+          version = os.environ["CRATE_VERSION"]
+          crates = ("tvm-ffi", "tvm-ffi-sys", "tvm-ffi-macros")
+          for crate in crates:
+              path = Path("rust") / crate / "Cargo.toml"
+              manifest = tomlkit.parse(path.read_text(encoding="utf-8"))
+              manifest["package"]["version"] = version
+              for section in ("dependencies", "dev-dependencies", 
"build-dependencies"):
+                  for name, dependency in manifest.get(section, {}).items():
+                      if name in crates:
+                          # Exact pin: the three crates ship together.
+                          dependency["version"] = f"={version}"
+              path.write_text(tomlkit.dumps(manifest), encoding="utf-8")
+              print(f"{crate}: {version}")
+          PY
+          # Cargo validates the derived SemVer and the updated dependency 
requirements.
+          cargo +stable metadata --manifest-path rust/Cargo.toml --no-deps 
--format-version 1 > /dev/null
+
+      - name: Test crates
+        working-directory: rust
+        run: cargo +stable test --release --workspace
+
+      # Packages and verifies the crates; only the release-version edits above 
are uncommitted.
+      - name: Dry-run crate publication
+        working-directory: rust
+        run: cargo +stable publish --dry-run --workspace --registry crates-io 
--allow-dirty
+
+      # The dry run keeps its .crate files in a temporary directory; write 
them out again,
+      # without re-verifying, for the artifact upload.
+      - name: Package crates
+        working-directory: rust
+        run: cargo +stable package --workspace --registry crates-io 
--allow-dirty --no-verify
+
+      - name: Upload crate artifacts
+        uses: actions/upload-artifact@v4
+        with:
+          name: crates-${{ matrix.os }}-${{ matrix.arch }}
+          path: rust/target/package/*.crate
+          if-no-files-found: error
+
+  upload_crates:
+    needs: [build_crates]
+    runs-on: ubuntu-latest
+    environment: crates-io
+    if: github.event_name == 'workflow_dispatch' && !inputs.dry_run
+    steps:
+      - name: Check out release source
+        uses: actions/checkout@v5
+        with:
+          ref: refs/tags/${{ inputs.tag }}
+          submodules: recursive
+          fetch-depth: 0
+          fetch-tags: true
+
+      - name: Set up uv
+        uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7  # 
v10.2.0
+        with:
+          python-version: "3.13"
+          activate-environment: true
+
+      - name: Set up Rust
+        run: rustup toolchain install stable --profile minimal
+
+      - uses: ./.github/actions/detect-env-vars
+        id: env_vars
+
+      - name: Build and install TVM FFI
+        env:
+          CMAKE_BUILD_PARALLEL_LEVEL: ${{ steps.env_vars.outputs.cpu_count }}
+        run: uv pip install --verbose .
+
+      - name: Set crate versions from Git
+        shell: bash
+        run: *set_crate_versions
+
+      # Verify all three crates before anything is uploaded; the publishes 
below skip re-verifying.
+      - name: Package and verify crates
+        working-directory: rust
+        run: cargo +stable package --workspace --registry crates-io 
--allow-dirty
+
+      # Publish in dependency order, skipping versions already on crates.io so 
a partial run can be
+      # repeated. Needs a crates.io token with publish access to all three 
crates.
+      - name: Publish crates to crates.io
+        working-directory: rust
+        shell: bash
+        env:
+          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
+        run: |
+          for crate in tvm-ffi-macros tvm-ffi-sys tvm-ffi; do
+            if lookup=$(cargo +stable info --registry crates-io 
"${crate}@${CRATE_VERSION}" 2>&1); then
+              echo "${crate}@${CRATE_VERSION} is already on crates.io; 
skipping."
+              continue
+            elif ! grep -q "could not find" <<< "${lookup}"; then
+              # Only a definite "not found" may fall through to publishing.
+              echo "${lookup}"
+              echo "::error::Could not determine whether 
${crate}@${CRATE_VERSION} is on crates.io"
+              exit 1
+            fi
+            echo "Publishing ${crate}@${CRATE_VERSION}"
+            cargo +stable publish --package "${crate}" --registry crates-io 
--allow-dirty --no-verify
+          done
diff --git a/pyproject.toml b/pyproject.toml
index 68c9480a..105953b2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -73,7 +73,8 @@ dev = [
 ]
 docs = [
   "autodocsumm",
-  "breathe",
+  # 5.0.0 breaks C++ template specializations and constexpr constructors.
+  "breathe!=5.0.0",
   "exhale",
   "linkify-it-py",
   "matplotlib",
diff --git a/rust/tvm-ffi-macros/Cargo.toml b/rust/tvm-ffi-macros/Cargo.toml
index f8d29d40..6c646904 100644
--- a/rust/tvm-ffi-macros/Cargo.toml
+++ b/rust/tvm-ffi-macros/Cargo.toml
@@ -19,6 +19,7 @@
 name = "tvm-ffi-macros"
 description = "Procedural macro crate for tvm-ffi"
 
+# Development placeholder; publish_crates.yml sets the release version from 
the Git tag.
 version = "0.1.0-alpha.0"
 edition = "2021"
 license = "Apache-2.0"
diff --git a/rust/tvm-ffi-sys/Cargo.toml b/rust/tvm-ffi-sys/Cargo.toml
index 5ae2d954..04ad1744 100644
--- a/rust/tvm-ffi-sys/Cargo.toml
+++ b/rust/tvm-ffi-sys/Cargo.toml
@@ -19,6 +19,7 @@
 name = "tvm-ffi-sys"
 description = "Low-level sys crate for tvm-ffi"
 
+# Development placeholder; publish_crates.yml sets the release version from 
the Git tag.
 version = "0.1.0-alpha.0"
 edition = "2021"
 license = "Apache-2.0"
diff --git a/rust/tvm-ffi/Cargo.toml b/rust/tvm-ffi/Cargo.toml
index 3df4eaf9..1fbd1c8a 100644
--- a/rust/tvm-ffi/Cargo.toml
+++ b/rust/tvm-ffi/Cargo.toml
@@ -19,6 +19,7 @@
 name = "tvm-ffi"
 description = "tvm-ffi rust support"
 
+# Development placeholder; publish_crates.yml sets the release version from 
the Git tag.
 version = "0.1.0-alpha.0"
 edition = "2021"
 license = "Apache-2.0"
@@ -30,6 +31,7 @@ crate-type = ["lib"]
 
 [dependencies]
 paste = "1.0"
+# Release CI also updates the internal dependency versions, including 
dev-dependencies.
 tvm-ffi-sys = { version = "0.1.0-alpha.0", path = "../tvm-ffi-sys" }
 tvm-ffi-macros = { version = "0.1.0-alpha.0", path = "../tvm-ffi-macros" }
 

Reply via email to