Skip to content

build(packaging): switch wheel build to maturin, ship Rust binary alongside Python source#1321

Open
jd wants to merge 1 commit intomainfrom
devs/jd/worktree-rust-port/switch-wheel-build-maturin-ship-rust-binary--8f6aa397
Open

build(packaging): switch wheel build to maturin, ship Rust binary alongside Python source#1321
jd wants to merge 1 commit intomainfrom
devs/jd/worktree-rust-port/switch-wheel-build-maturin-ship-rust-binary--8f6aa397

Conversation

@jd
Copy link
Copy Markdown
Member

@jd jd commented Apr 30, 2026

Replaces hatchling with maturin so the Python wheel ships both the
existing mergify_cli/ package and the new Rust binary as a
bindings = "bin" console-script. The two installs side-by-side in
the same venv layout pip already produces:

<venv>/bin/mergify              # Rust binary (this commit's
                                # entry point)
<venv>/bin/python3              # interpreter pip set up
<venv>/lib/.../site-packages/   # Python source + deps

The shim no longer has to embed the Python source or bootstrap a
Python interpreter — pip already installed both alongside the
binary. mergify-py-shim shrinks from ~250 lines (include_dir +
atomic file-locked extraction + cache management) to ~130 lines:
locate the sibling python3, exec python3 -m mergify_cli, return
the exit code. Drops dirs, fs2, include_dir deps.

A new MERGIFY_PYTHON_EXE env var lets cargo build developers
point at any Python interpreter that has the package on sys.path;
the no-sibling-python failure mode now produces a targeted
PythonNotFound with the exact path it tried.

This unlocks the "delete the Python copy when porting to Rust" rule:
each future port PR removes its Python implementation in the same
change, so there's never two parallel copies of the same command.
Drift goes from "watch for it" to "structurally impossible" — no
compat-test snapshot maintenance, no flag-by-flag mirroring.

Phase 6 (curl-installable static binary, no Python at all) drops
this crate entirely.

Trade-offs:

  • Wheels are now platform-tagged (per maturin bindings = "bin").
    The release workflow must build a per-platform matrix; the
    existing uv build single-platform path will need an update
    before the next PyPI publish (separate PR).
  • Version handling: dynamic = ["version"] flows from
    crates/mergify-cli/Cargo.toml's [package] version instead of
    hatch-vcs reading git tags. Release tooling must bump the Cargo
    version to match the tag (also addressed in the release-workflow
    follow-up).

Verified locally: uvx maturin build --release produces
target/wheels/mergify_cli-*-macosx_*.whl. Installing into a fresh
uv venv lands mergify at <venv>/bin/mergify (Mach-O arm64) and
the Python source under site-packages/mergify_cli/. Both
mergify --help (shimmed → Python click help) and mergify config validate (native → Rust impl) work.

Copilot AI review requested due to automatic review settings April 30, 2026 08:23
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 30, 2026 08:23 Failure
@jd
Copy link
Copy Markdown
Member Author

jd commented Apr 30, 2026

This pull request is part of a Mergify stack:

# Pull Request Link
1 build(packaging): switch wheel build to maturin, ship Rust binary alongside Python source #1321 👈
2 chore(python): drop config validate/simulate Python code, now native in Rust #1322
3 feat(rust): port ci scopes-send to native Rust (Phase 1.4) #1300
4 feat(rust): port queue pause and unpause to native Rust (Phase 1.5) #1301
5 feat(rust): port ci git-refs and ci queue-info to native Rust (Phase 1.6) #1302

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes the packaging/build pipeline to produce a maturin-built wheel that includes both the existing mergify_cli/ Python package and a Rust mergify binary, with the Rust binary delegating to python -m mergify_cli for unported subcommands.

Changes:

  • Switches the Python build backend from hatchling/hatch-vcs to maturin (bindings = "bin") to ship a Rust binary inside the wheel alongside Python sources.
  • Refactors mergify-py-shim to stop embedding/extracting Python sources and instead locate a sibling venv Python interpreter (or use MERGIFY_PYTHON_EXE).
  • Removes shim dependencies used for extraction/caching and updates the lockfile accordingly.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
pyproject.toml Replaces hatchling with maturin configuration for a binary-in-wheel distribution.
crates/mergify-py-shim/src/lib.rs Simplifies shim logic to locate and exec a venv Python interpreter; updates errors/tests.
crates/mergify-py-shim/Cargo.toml Drops extraction-related dependencies; adds temp-env for tests.
Cargo.lock Removes now-unused crates from the dependency graph.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pyproject.toml
Comment thread crates/mergify-py-shim/src/lib.rs Outdated
@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Apr 30, 2026

Merge Protections

Your pull request matches the following merge protections and will not be merged until they are valid.

🔴 👀 Review Requirements

Waiting for:

  • #approved-reviews-by>=2
This rule is failing.
  • any of:
    • #approved-reviews-by>=2
    • author = dependabot[bot]
    • author = mergify-ci-bot
    • author = renovate[bot]

🔴 🔎 Reviews

Waiting for:

  • #review-requested = 0
This rule is failing.
  • #review-requested = 0
  • #changes-requested-reviews-by = 0
  • #review-threads-unresolved = 0

🟢 🤖 Continuous Integration

Wonderful, this rule succeeded.
  • all of:
    • check-success=ci-gate

🟢 Enforce conventional commit

Wonderful, this rule succeeded.

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert|ui)(?:\(.+\))?:

🟢 📕 PR description

Wonderful, this rule succeeded.
  • body ~= (?ms:.{48,})

@jd jd force-pushed the devs/jd/worktree-rust-port/switch-wheel-build-maturin-ship-rust-binary--8f6aa397 branch from 0d9b6f9 to e5530f7 Compare April 30, 2026 09:29
@jd
Copy link
Copy Markdown
Member Author

jd commented Apr 30, 2026

Revision history

# Type Changes Reason Date
1 initial 0d9b6f9 2026-04-30 09:29 UTC
2 content 0d9b6f9 → e5530f7 2026-04-30 09:29 UTC
3 content e5530f7 → 31628c9 2026-04-30 12:09 UTC
4 content 31628c9 → b6420ce 2026-04-30 13:08 UTC
5 content b6420ce → f4c7454 2026-04-30 13:30 UTC
6 content f4c7454 → d7dfb31 2026-04-30 14:06 UTC

@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 30, 2026 09:31 Failure
@jd jd marked this pull request as ready for review April 30, 2026 09:38
@jd jd force-pushed the devs/jd/worktree-rust-port/switch-wheel-build-maturin-ship-rust-binary--8f6aa397 branch from e5530f7 to 31628c9 Compare April 30, 2026 12:09
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 30, 2026 12:09 Failure
@jd jd force-pushed the devs/jd/worktree-rust-port/switch-wheel-build-maturin-ship-rust-binary--8f6aa397 branch from 31628c9 to b6420ce Compare April 30, 2026 13:08
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 30, 2026 13:08 Failure
@jd jd force-pushed the devs/jd/worktree-rust-port/switch-wheel-build-maturin-ship-rust-binary--8f6aa397 branch from b6420ce to f4c7454 Compare April 30, 2026 13:30
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 30, 2026 13:31 Failure
…ngside Python source

Replaces hatchling with maturin so the Python wheel ships *both* the
existing `mergify_cli/` package and the new Rust binary as a
`bindings = "bin"` console-script. The two installs side-by-side in
the same venv layout pip already produces:

    <venv>/bin/mergify              # Rust binary (this commit's
                                    # entry point)
    <venv>/bin/python3              # interpreter pip set up
    <venv>/lib/.../site-packages/   # Python source + deps

The shim no longer has to embed the Python source or bootstrap a
Python interpreter — pip already installed both alongside the
binary. `mergify-py-shim` shrinks from ~250 lines (include_dir +
atomic file-locked extraction + cache management) to ~130 lines:
locate the sibling `python3`, exec `python3 -m mergify_cli`, return
the exit code. Drops `dirs`, `fs2`, `include_dir` deps.

A new `MERGIFY_PYTHON_EXE` env var lets `cargo build` developers
point at any Python interpreter that has the package on `sys.path`;
the no-sibling-python failure mode now produces a targeted
`PythonNotFound` with the exact path it tried.

This unlocks the "delete the Python copy when porting to Rust" rule:
each future port PR removes its Python implementation in the same
change, so there's never two parallel copies of the same command.
Drift goes from "watch for it" to "structurally impossible" — no
compat-test snapshot maintenance, no flag-by-flag mirroring.

Phase 6 (curl-installable static binary, no Python at all) drops
this crate entirely.

Trade-offs:
- Wheels are now platform-tagged (per maturin `bindings = "bin"`).
  The release workflow must build a per-platform matrix; the
  existing `uv build` single-platform path will need an update
  before the next PyPI publish (separate PR).
- Version handling: `dynamic = ["version"]` flows from
  `crates/mergify-cli/Cargo.toml`'s `[package] version` instead of
  hatch-vcs reading git tags. Release tooling must bump the Cargo
  version to match the tag (also addressed in the release-workflow
  follow-up).

Verified locally: `uvx maturin build --release` produces
`target/wheels/mergify_cli-*-macosx_*.whl`. Installing into a fresh
`uv venv` lands `mergify` at `<venv>/bin/mergify` (Mach-O arm64) and
the Python source under `site-packages/mergify_cli/`. Both
`mergify --help` (shimmed → Python click help) and `mergify config
validate` (native → Rust impl) work.

Change-Id: I8f6aa397e8736aa9313c033e19e5244c34038512
@jd jd force-pushed the devs/jd/worktree-rust-port/switch-wheel-build-maturin-ship-rust-binary--8f6aa397 branch from f4c7454 to d7dfb31 Compare April 30, 2026 14:06
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 30, 2026 14:07 Failure
@mergify mergify Bot requested a review from a team April 30, 2026 14:19
@mergify mergify Bot requested a review from a team April 30, 2026 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants