Skip to content

ci: auto-patch miden-client dep from PR description marker (next)#66

Merged
WiktorStarczewski merged 3 commits into
nextfrom
wiktor/auto-patch-client-pr-next
Apr 30, 2026
Merged

ci: auto-patch miden-client dep from PR description marker (next)#66
WiktorStarczewski merged 3 commits into
nextfrom
wiktor/auto-patch-client-pr-next

Conversation

@WiktorStarczewski
Copy link
Copy Markdown
Collaborator

@WiktorStarczewski WiktorStarczewski commented Apr 30, 2026

Summary

Add an "auto-patch" system that lets a web-sdk PR pin its CI build against an in-flight miden-client PR by adding a single line to its description:

Client PR: #<NUM>

A composite action (.github/actions/inject-linked-client-pr) parses the marker, resolves the linked PR's head ref, and rewrites web-sdk's miden-client (and miden-client-sqlite-store) dep in place — only on the runner, never committed. Replaces the manual [patch] / branch-edit dance every cross-repo migration PR has been carrying.

What's in this PR

Path Purpose
.github/actions/inject-linked-client-pr/action.yml Composite action: parse, resolve, validate, rewrite, comment.
.github/workflows/build.yml, test.yml Wire the action into the cargo-compiling jobs. build-wasm is the single sticky-comment poster (every other invocation has comment: false).
.github/workflows/check-linked-client-pr.yml Mergeability gate. Keeps a linked-client-pr-ready check pending until the linked client PR is merged-and-reachable from the target branch's canonical refs. Re-evaluates every 15 min via cron.
scripts/dev-with-client-pr.sh Local-dev mirror: applies the same rewrite to your working tree. --clear restores byte-for-byte.
lefthook.yml Pre-commit guard: refuses any commit while the marker block is present.
CLAUDE.md Docs: marker convention, local script, mergeability gate.

Why in-place rewrite, not [patch.crates-io] / [patch."<url>"]

Web-sdk's next pins miden-client to git=…miden-client.git, branch=next. Cargo's [patch."<url>"] errors with patches must point to different sources when the patch source URL matches the original — so we can't redirect the same URL to a different branch via [patch]. [patch.crates-io] doesn't apply on next either (the dep isn't a crates.io source there). In-place rewrite covers both main (crates.io) and next (git+branch) uniformly. The rewritten line is wrapped in marker comments preserving the original verbatim, so --clear (and the auto-cleanup if the marker is removed from the PR body) restores byte-for-byte.

Comment lifecycle

Strict 0-or-1 comment per PR:

  • Marker present → sticky upsert via header: linked-client-pr (re-runs update in place, never duplicate).
  • Marker removed → action deletes the stale comment.
  • Closed-without-merge linked PR → workflow fails loudly with a clear summary; no comment posted (the failure surfaces in the run).

Test plan

  • Open this PR — no marker; CI runs against canonical deps; no comment posted.
  • Open a separate test PR with Client PR: #N in the body where #N is an open miden-client PR; verify:
    • Sticky comment appears once, summarizing the patch (head ref, sha, state, merged).
    • Cargo.toml on the runner has the rewrite (visible in build logs as branch = "<linked>").
    • Cargo.lock resolves to the linked PR's head sha.
    • The committed Cargo.toml on the branch is unchanged (no rewrite shipped).
  • Edit the PR description to remove the marker; verify the sticky comment is deleted on the next run.
  • Edit the PR description to point at a closed-without-merge PR; verify the run fails with the closed-PR error.
  • On a linked PR that's merged-and-released: verify linked-client-pr-ready check goes green.

Migrations

Once this lands, the existing migration PRs (#23, #25, #26, #27, #29, #30, #31) can drop their hand-rolled [patch] / branch= edits in Cargo.toml and use the marker instead — see the description-only example I'll attach to one of them as the verification step.

When a web-sdk PR description contains:

    Client PR: #1234
    Client PR: 0xMiden/miden-client#1234   (cross-repo / fork form)

a new composite action (.github/actions/inject-linked-client-pr) parses
the marker, resolves the linked PR's head ref, and rewrites web-sdk's
miden-client (and miden-client-sqlite-store) dep in place to point at
that branch — only on the runner, never committed. The build then runs
against the unreleased upstream code, while the committed Cargo.toml
diff stays clean. Replaces the manual '[patch]' / branch-edit dance
that this session has been carrying on every migration PR.

Why in-place rewrite instead of [patch.crates-io] / [patch."<url>"]?
Web-sdk's 'next' pins miden-client at git+url=...miden-client.git+
branch=next; pointing the same URL at a different branch via [patch]
errors with 'patches must point to different sources'. In-place
rewrite covers both 'main' (crates.io dep) and 'next' (git dep)
uniformly — the rewritten line is wrapped in marker comments that
preserve the original verbatim so a cleanup step can restore it.

Components:

  .github/actions/inject-linked-client-pr/action.yml
    Composite action: parse marker, resolve head, validate state
    (closed-without-merge fails the run loudly), patch Cargo.toml +
    refresh Cargo.lock, post a sticky PR comment summarizing the
    patch. Strict 0-or-1 comment invariant: only fires when called
    with comment=true (one designated job per workflow run), and
    deletes the prior comment if the marker is later removed.

  .github/workflows/build.yml + test.yml
    Wired the action into the cargo-compiling jobs (build-wasm,
    build-web-client-dist-folder, verify-release-build). build-wasm
    is the single comment-poster (comment=true).

  .github/workflows/check-linked-client-pr.yml
    Mergeability gate: keeps a 'linked-client-pr-ready' check on the
    PR. Stays pending while the linked client PR isn't merged-and-
    reachable from the target branch's canonical refs (miden-client
    next for next-targeted PRs, latest miden-client release tag for
    main-targeted). Re-evaluates every 15 min so the check goes green
    automatically once upstream catches up — no need to re-push.
    Configure branch protection to require it.

  scripts/dev-with-client-pr.sh
    Local-dev mirror: applies the same in-place dep rewrite to your
    working tree. Idempotent. '--clear' restores the originals
    byte-for-byte from the marker block.

  lefthook.yml
    Pre-commit guard: refuses any commit while the marker block is
    present in Cargo.toml. So a forgotten 'apply' can't accidentally
    leak into a commit.

  CLAUDE.md
    Documents the marker convention, the local script, and the
    mergeability gate.
@WiktorStarczewski WiktorStarczewski added the no changelog PR doesn't need a CHANGELOG entry (trivial / non-user-visible) label Apr 30, 2026
GNU grep on the runner balked with 'repetition-operator operand invalid'
on the \s* in the regex. \s is a Perl-extension class that grep -E
doesn't recognize in POSIX-extended mode; the * after it ends up
applying to nothing, hence the error. Replace with [[:space:]]* across
the composite action, the dev script, and the readiness gate workflow.
Without the ^[[:space:]]* prefix, doc examples or table cells in the
PR body that mention 'Client PR:' inline (e.g. inside backticks for a
test-plan checklist) are picked up as if they were real markers — the
action then tries to fetch a fake miden-client PR and fails with
'Failed to fetch'. Anchoring requires the marker to start its own
line, so inline mentions in surrounding prose stay decorative. Doc
examples that use placeholders like #<NUM> instead of #N (a literal
number) are also rejected by the existing #[0-9]+ requirement.

Pairs with the PR-body cleanup that replaces the literal example
'Client PR: #1234' with 'Client PR: #<NUM>' so it's clearly a template.
@WiktorStarczewski WiktorStarczewski merged commit 14ca314 into next Apr 30, 2026
32 checks passed
@WiktorStarczewski WiktorStarczewski deleted the wiktor/auto-patch-client-pr-next branch April 30, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no changelog PR doesn't need a CHANGELOG entry (trivial / non-user-visible)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant