Skip to content

feat(rust): port stack push end-to-end + delete Python push.py#1553

Open
jd wants to merge 1 commit into
devs/jd/feat/rust-stack-new/port-stack-hooks-stack-setup-native-rust--12f4b4affrom
devs/jd/feat/rust-stack-new/port-stack-push-end-end-delete-python-push-py--1b2c3050
Open

feat(rust): port stack push end-to-end + delete Python push.py#1553
jd wants to merge 1 commit into
devs/jd/feat/rust-stack-new/port-stack-hooks-stack-setup-native-rust--12f4b4affrom
devs/jd/feat/rust-stack-new/port-stack-push-end-end-delete-python-push-py--1b2c3050

Conversation

@jd
Copy link
Copy Markdown
Member

@jd jd commented Jun 5, 2026

End-to-end native port of mergify stack push: wires every
leaf module, the orchestrator, and the binary dispatch in one
self-consistent change so mergify stack push works on the
Rust binary and the Python implementation gets deleted in the
same commit.

New mergify-stack modules (each is a faithful port from
mergify_cli/stack/):

  • change_type — patch-id-based rebase-vs-content
    classification + refs/pull/<n>/head fetch helper.
  • stack_comment — the "this PR is part of a stack" sticky
    comment renderer + header recogniser. JSON marker stays
    byte-for-byte compatible with historic comments.
  • replaygit merge-tree + git diff-tree + the HTTP
    upload (POST /git/trees + POST /git/commits) that
    materialise the rebase-aware revision-history compare URL.
  • revision_history — the "Revision history" sticky comment
    with parse + append + render round-tripping byte-for-byte
    against the Python implementation.
  • approvals — the rebase/no-rebase decision: skip the
    rebase when PRs are already approved (so reviews aren't
    dismissed) unless the bottom of the stack has a real merge
    conflict with trunk.
  • notes_pushgit fetch/git push plumbing for
    refs/notes/mergify/stack + the per-PR refspecs that
    stack push lands atomically with --force-with-lease.
  • rebase_log — pure formatters for the three rebase
    narration log lines.
  • push_helpersformat_pull_description (strip
    Change-Id + stale Depends-On, append fresh Depends-On) +
    build_change_tasks (the per-PR dependency graph).
  • pr_upsert — per-PR Create (POST /pulls) and Update
    (PATCH /pulls/) + orphan branch teardown.
  • comment_upsert — per-PR sticky-comment upserters: stack
    comment (skip-when-single-PR) + revision history (parse +
    append + recover-from-corrupt).
  • plan — the layer above classify that applies the
    --next-only / --only-update-existing-pulls overrides
    and resolves dest_branch / base_branch.
  • changes::Action extended with SkipCreate /
    SkipNextOnly so the planner can surface
    would-be-created PRs without opening any.
  • commands::push — the end-to-end orchestrator wiring
    every leaf above. Runs per-PR upserts sequentially
    (typical 2-5 PR stacks make the latency difference
    negligible vs. the GitHub round-trip cost, and the
    simpler code avoids a tokio::sync::Notify graph).

Binary wiring (crates/mergify-cli/src/main.rs):

  • NativeCommand::StackPush(StackPushOpts) variant +
    StackPushCli clap struct mirroring the Python click
    option surface 1:1 (--skip-rebase, --force-rebase,
    --next-only, --dry-run, --draft, --keep-pull- request-title-and-body, --author, --trunk,
    --branch-prefix, --only-update-existing-pulls,
    --no-revision-history, --no-verify).
  • dispatch_stack "push" arm routing through to
    commands::push::run.
  • ("stack", "push") added to NATIVE_COMMANDS.

Python deletion:

  • mergify_cli/stack/push.py (the orchestrator, 1394 LOC).
  • mergify_cli/stack/{sync,approvals,replay,changes}.py
    helpers only imported by push.py and its tests.
  • mergify_cli/tests/stack/test_{push,replay,approvals}.py.
  • mergify_cli/stack/cli.py — the push command + the
    stack_push_mod import. The click group itself stays
    so python -m mergify_cli stack keeps printing help
    until the package is removed wholesale in the follow-up.

Adds chrono (with clock feature) and tokio (with
time feature) + url to mergify-stack's prod deps to
support the revision-history timestamps, the
mergeable-retry sleep, and the wiremock test base-URL
parse.

End-to-end verified against the Python implementation on
real fixtures (stack-comment + revision-history bodies
match byte-for-byte; planner action overrides match the
Python get_changes semantics including the
--next-only × --only-update-existing-pulls interaction
at idx 0).

Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com

Depends-On: #1527

@mergify mergify Bot had a problem deploying to Mergify Merge Protections June 5, 2026 07:01 Failure
@jd
Copy link
Copy Markdown
Member Author

jd commented Jun 5, 2026

This pull request is part of a Mergify stack:

# Pull Request Link
1 feat(rust): port stack reorder + stack move to native Rust #1520
2 feat(rust): port stack squash to native Rust #1521
3 feat(rust): port stack checkout to native Rust #1522
4 feat(rust): port stack sync to native Rust #1523
5 feat(rust): port stack list + stack open to native Rust #1524
6 feat(rust): port stack hooks + stack setup to native Rust #1527
7 feat(rust): port stack push end-to-end + delete Python push.py #1553 👈
8 chore: delete Python tree + simplify wheel/CI for pure-Rust binary #1554
9 refactor(stack): extract shared git helpers into crate::git #1555
10 ci(workflows): align smoke-test-binary on python 3.14 #1557

@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Jun 5, 2026

Merge Protections

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

🔴 ⛓️ Depends-On Requirements

Waiting for

This rule is failing.

Requirement based on the presence of Depends-On in the body of the pull request

🔴 👀 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,})

@mergify mergify Bot requested a review from a team June 5, 2026 07:10
@jd jd marked this pull request as ready for review June 5, 2026 07:41
@jd jd force-pushed the devs/jd/feat/rust-stack-new/port-stack-hooks-stack-setup-native-rust--12f4b4af branch from e5c33cc to d2bd9e8 Compare June 5, 2026 08:13
@jd jd force-pushed the devs/jd/feat/rust-stack-new/port-stack-push-end-end-delete-python-push-py--1b2c3050 branch from 0ed6917 to 9767f5b Compare June 5, 2026 08:13
@jd jd temporarily deployed to func-tests-live June 5, 2026 08:13 — with GitHub Actions Inactive
@jd
Copy link
Copy Markdown
Member Author

jd commented Jun 5, 2026

Revision history

# Type Changes Reason Date
1 initial 0ed6917 2026-06-05 08:13 UTC
2 rebase 0ed6917 → 9767f5b (rebase only) 2026-06-05 08:13 UTC
3 rebase 9767f5b → bcaa5fa (rebase only) 2026-06-05 09:38 UTC
4 rebase bcaa5fa → f74c92d (rebase only) 2026-06-05 12:37 UTC

@mergify mergify Bot had a problem deploying to Mergify Merge Protections June 5, 2026 08:13 Failure
@jd jd force-pushed the devs/jd/feat/rust-stack-new/port-stack-push-end-end-delete-python-push-py--1b2c3050 branch from 9767f5b to bcaa5fa Compare June 5, 2026 09:38
@jd jd force-pushed the devs/jd/feat/rust-stack-new/port-stack-hooks-stack-setup-native-rust--12f4b4af branch from d2bd9e8 to 291e013 Compare June 5, 2026 09:38
@jd jd temporarily deployed to func-tests-live June 5, 2026 09:38 — with GitHub Actions Inactive
@jd jd temporarily deployed to func-tests-live June 5, 2026 09:38 — with GitHub Actions Inactive
@jd jd temporarily deployed to func-tests-live June 5, 2026 09:38 — with GitHub Actions Inactive
@mergify mergify Bot had a problem deploying to Mergify Merge Protections June 5, 2026 09:39 Failure
End-to-end native port of `mergify stack push`: wires every
leaf module, the orchestrator, and the binary dispatch in one
self-consistent change so `mergify stack push` works on the
Rust binary and the Python implementation gets deleted in the
same commit.

New `mergify-stack` modules (each is a faithful port from
`mergify_cli/stack/`):

- `change_type` — patch-id-based rebase-vs-content
  classification + `refs/pull/<n>/head` fetch helper.
- `stack_comment` — the "this PR is part of a stack" sticky
  comment renderer + header recogniser. JSON marker stays
  byte-for-byte compatible with historic comments.
- `replay` — `git merge-tree` + `git diff-tree` + the HTTP
  upload (`POST /git/trees` + `POST /git/commits`) that
  materialise the rebase-aware revision-history compare URL.
- `revision_history` — the "Revision history" sticky comment
  with parse + append + render round-tripping byte-for-byte
  against the Python implementation.
- `approvals` — the rebase/no-rebase decision: skip the
  rebase when PRs are already approved (so reviews aren't
  dismissed) unless the bottom of the stack has a real merge
  conflict with trunk.
- `notes_push` — `git fetch`/`git push` plumbing for
  `refs/notes/mergify/stack` + the per-PR refspecs that
  `stack push` lands atomically with `--force-with-lease`.
- `rebase_log` — pure formatters for the three rebase
  narration log lines.
- `push_helpers` — `format_pull_description` (strip
  Change-Id + stale Depends-On, append fresh Depends-On) +
  `build_change_tasks` (the per-PR dependency graph).
- `pr_upsert` — per-PR Create (POST /pulls) and Update
  (PATCH /pulls/<n>) + orphan branch teardown.
- `comment_upsert` — per-PR sticky-comment upserters: stack
  comment (skip-when-single-PR) + revision history (parse +
  append + recover-from-corrupt).
- `plan` — the layer above `classify` that applies the
  `--next-only` / `--only-update-existing-pulls` overrides
  and resolves `dest_branch` / `base_branch`.
- `changes::Action` extended with `SkipCreate` /
  `SkipNextOnly` so the planner can surface
  would-be-created PRs without opening any.
- `commands::push` — the end-to-end orchestrator wiring
  every leaf above. Runs per-PR upserts sequentially
  (typical 2-5 PR stacks make the latency difference
  negligible vs. the GitHub round-trip cost, and the
  simpler code avoids a `tokio::sync::Notify` graph).

Binary wiring (`crates/mergify-cli/src/main.rs`):

- `NativeCommand::StackPush(StackPushOpts)` variant +
  `StackPushCli` clap struct mirroring the Python click
  option surface 1:1 (`--skip-rebase`, `--force-rebase`,
  `--next-only`, `--dry-run`, `--draft`, `--keep-pull-
  request-title-and-body`, `--author`, `--trunk`,
  `--branch-prefix`, `--only-update-existing-pulls`,
  `--no-revision-history`, `--no-verify`).
- `dispatch_stack` "push" arm routing through to
  `commands::push::run`.
- `("stack", "push")` added to `NATIVE_COMMANDS`.

Python deletion:

- `mergify_cli/stack/push.py` (the orchestrator, 1394 LOC).
- `mergify_cli/stack/{sync,approvals,replay,changes}.py` —
  helpers only imported by push.py and its tests.
- `mergify_cli/tests/stack/test_{push,replay,approvals}.py`.
- `mergify_cli/stack/cli.py` — the `push` command + the
  `stack_push_mod` import. The click group itself stays
  so `python -m mergify_cli stack` keeps printing help
  until the package is removed wholesale in the follow-up.

Adds `chrono` (with `clock` feature) and `tokio` (with
`time` feature) + `url` to `mergify-stack`'s prod deps to
support the revision-history timestamps, the
mergeable-retry sleep, and the wiremock test base-URL
parse.

End-to-end verified against the Python implementation on
real fixtures (stack-comment + revision-history bodies
match byte-for-byte; planner action overrides match the
Python `get_changes` semantics including the
`--next-only` × `--only-update-existing-pulls` interaction
at idx 0).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Change-Id: I1b2c30509153a19071cf495155a03e9a2e616e87
@jd jd force-pushed the devs/jd/feat/rust-stack-new/port-stack-push-end-end-delete-python-push-py--1b2c3050 branch from bcaa5fa to f74c92d Compare June 5, 2026 12:37
@jd jd temporarily deployed to func-tests-live June 5, 2026 12:37 — with GitHub Actions Inactive
@mergify mergify Bot had a problem deploying to Mergify Merge Protections June 5, 2026 12:37 Failure
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.

1 participant