Skip to content

ci: auto-patch miden-client dep from PR description marker#65

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

ci: auto-patch miden-client dep from PR description marker#65
WiktorStarczewski merged 3 commits into
mainfrom
wiktor/auto-patch-client-pr-main

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 9649388 into main Apr 30, 2026
53 of 54 checks passed
@WiktorStarczewski WiktorStarczewski deleted the wiktor/auto-patch-client-pr-main branch April 30, 2026 15:21
WiktorStarczewski added a commit that referenced this pull request Apr 30, 2026
…dep retarget

Brings in the auto-patch infrastructure landed in #65 (composite action,
mergeability gate, lefthook guard, dev script, docs). Drops the manual
[patch]-style retarget block we'd added to Cargo.toml: with the linked
'Client PR: #2059' marker in this PR's description, the CI workflow
auto-injects an equivalent in-place rewrite at run time.

This commit is the verification that the auto-patch system works
end-to-end on a real migration PR. Expectations:
  - Cargo.toml diff vs main is now empty (no manual retarget).
  - The Inject linked miden-client PR step reads 'Client PR: #2059' from
    this PR's body, resolves miden-client#2059's head, rewrites the dep
    in place on the runner, and posts a sticky comment summarizing the
    patch (single comment per run, deduped via the linked-client-pr
    sticky header).
  - Build/Test runs against miden-client@wiktor/apply-tx-after-submit-failed
    just like before — but the retarget is implicit, not committed.
WiktorStarczewski added a commit that referenced this pull request Apr 30, 2026
PR #25's verification run surfaced a coverage gap: my initial wiring
in #65 only patched build.yml's build-wasm and test.yml's
build-web-client-dist-folder + verify-release-build. But Clippy WASM
(in lint.yml) and publint + attw (in check-publish.yml) ALSO compile
cargo against the workspace's miden-client dep — without the patch,
they hit canonical crates.io `miden-client = "0.14.5"` and fail
with `error[E0599]: no variant named `ApplyTransactionAfterSubmitFailed``
when the PR depends on an unreleased upstream variant.

Add the action call after checkout in both jobs. Both run with
comment=false (the default); build-wasm remains the single sticky-
comment poster.
WiktorStarczewski added a commit that referenced this pull request Apr 30, 2026
PR #25's verification run surfaced a coverage gap: my initial wiring
in #65 only patched build.yml's build-wasm and test.yml's
build-web-client-dist-folder + verify-release-build. But Clippy WASM
(in lint.yml) and publint + attw (in check-publish.yml) ALSO compile
cargo against the workspace's miden-client dep — without the patch,
they hit canonical crates.io `miden-client = "0.14.5"` and fail
with `error[E0599]: no variant named `ApplyTransactionAfterSubmitFailed``
when the PR depends on an unreleased upstream variant.

Add the action call after checkout in both jobs. Both run with
comment=false (the default); build-wasm remains the single sticky-
comment poster.
WiktorStarczewski added a commit that referenced this pull request Apr 30, 2026
…p manual dep retarget

Brings in the auto-patch infrastructure landed in #65 (composite
action + readiness gate + lefthook guard + dev script). Drops the
manual git+branch retarget on Cargo.toml: the 'Client PR: #2132'
marker on this PR's description now drives the dep injection at
CI runtime.

Cargo.toml + Cargo.lock are now byte-identical to origin/next.
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