Move the patch series onto fork branches, and pin them by rev - #12
Merged
Merged
Conversation
The series lived twice: as .patch files here, and as whatever a consumer's checkout held after applying them. A second copy can only drift from the first, and the recipe made the drift a consumer's problem — clone two repositories at exact revisions, `git am` twenty-four patches into one and `git apply --3way` five into the other, then wire eleven path overrides. Four steps, every one of which could be got subtly wrong on a machine nobody else could see. The CSP pair had already left for a fork branch, for exactly this reason. The rest have now followed. `tauri-runtime-patches` on copse-dev/servo carries the twenty-four servo commits on `77fccacc`, the revision `servo 0.5.0` was cut from; the same branch on copse-dev/stylo carries the five stylo commits on `67faaab3`. The overrides name those branches by rev, so cargo fetches them like any other git dependency and the four steps collapse into two: paste a block, enable a feature. Verified end to end — `cargo generate-lockfile` against the published block resolves servo 0.5.0 and stylo 0.20.0 from the forks, 816 packages, no path anywhere in the graph. The commits were swept on the way across. Twenty-two of the twenty-four were authored as Claude with Co-Authored-By and session trailers, which is not how work destined for upstream should arrive; all twenty-nine are now authored as the person who has to stand behind them, with the trailers dropped. Nine Americanisms went with them (honor, behavior), and the stylo messages lost their "To try it" postscripts, which described a workflow that no longer exists. CI follows the change in kind, not just in name. There is no series to apply, so `check-patch-series.sh` becomes `check-engine-pins.sh`: for every override the README publishes it reads that crate's manifest at the pinned rev and compares the version against Cargo.lock, because cargo accepts a `[patch]` entry only when the replacement satisfies the requirement it replaces — and reports the mismatch at build time rather than in the manifest. It reads ten files over the API instead of cloning, so the job drops from a couple of minutes to seconds, and a Dependabot bump that outruns the forks still arrives red, which was always the point. That check found something the old one could not have: the graph carries two `selectors`, 0.36.1 for an unrelated dependent and 0.40.0 for stylo. Cargo patches whichever entries the replacement satisfies and leaves the rest, so the check accepts a pin matching any locked version and fails only when it matches none — the case where the override is silently inert. prepare-patched-servo.sh loses its cloning and patching and keeps only the part that mattered: lifting the block out of README.md rather than restating it, so what CI builds is what a consumer is handed.
jonathanKingston
added a commit
to copse-dev/agent-pane
that referenced
this pull request
Aug 25, 2026
…#1939) Pairs with [copse-dev/tauri-runtime-servo#12](copse-dev/tauri-runtime-servo#12), which moves the patch series onto `tauri-runtime-patches` branches of the org's engine forks. This is the consumer side. ## The bug this fixes Servo mode had two defaults that disagreed. `build:servo` wrote a `tauri.html` with its CSP **enforced**, which only a patched engine can satisfy — while the shell's `[patch]` block was commented out and `patched-servo` was off, so cargo built **stock** libservo. Stock Servo gives `tauri://localhost` an opaque origin that CSP `'self'` can never match, so following the README exactly gave you a blank window with every same-origin subresource blocked. Both working configurations were one manual step away; neither was the one you got for free. ## What changes The engine is no longer something you assemble: ```toml [patch.crates-io] servo = { git = "https://github.com/copse-dev/servo", rev = "3cb68676..." } # ... the CSP fork and all eight stylo crates ``` Live, pinned by rev, fetched by cargo. No clone, no `git am`, no path overrides, nothing to uncomment. `patched-servo` becomes a default feature to match, which is safe in the way that matters: enabling it against stock libservo is a **compile error**, not a silent no-op, because the pref it sets is a struct field only the patched tree has. The feature and the overrides cannot drift apart unnoticed, and the enforced CSP is now correct rather than aspirational. ## Engine iteration still works — and is now the cheap path, not the only one Put a checkout at `../servo` or `../stylo` and `build:servo` writes a gitignored `tauri-shell/.cargo/config.toml` redirecting those crates at it. A `[patch]` in a cargo config takes precedence over the manifest's **per crate**, so a checkout of one repository wins for what it provides while the pins keep covering the other. Delete it and the next run removes the file — the case that would otherwise bite, since a config pointing at a directory that has gone leaves cargo reporting the error instead of us. Every run reports which of the three modes it took: ``` servo engine: pinned (no sibling checkout — using the forks pinned in Cargo.toml) servo engine: checkout (../servo and ../stylo — wrote tauri-shell/.cargo/config.toml) servo engine: artifacts-only (COPSE_SERVO_ARTIFACTS_ONLY=1 — engine untouched) ``` ## CI The `servo mode` job sets `COPSE_SERVO_ARTIFACTS_ONLY=1`. It exists to catch the sidecar bundle rotting, never invokes cargo, and resolving an engine there would be pure cost. ## Verified locally - All three modes exercised, including that removing a checkout removes the generated config. - `cargo generate-lockfile` resolves `servo 0.5.0` and `stylo 0.20.0` from the forks; the lockfile here is regenerated against the pins. - `cargo metadata --no-deps` confirms `default = ["patched-servo"] → tauri-runtime-servo/patched-servo`. - typecheck, lint, format, dead-code (801 modules), plain `pnpm build` still servo-free, `build:servo` + sidecar smoke test. - Unit suite 7654/7656. The two failures are `hooks/session-start` and `hooks/after-file-edit`, which pass 6/6 and 10/10 in isolation — timing-sensitive under parallel load, and nowhere near this change. ## Stock-engine builds Still supported, but now both halves are explicit, because getting one right and not the other is exactly what caused the original bug: ```bash COPSE_TAURI_STRIP_CSP=1 pnpm build:servo cd tauri-shell && cargo run --no-default-features ``` ## Merge order Land [tauri-runtime-servo#12](copse-dev/tauri-runtime-servo#12) first if you want the two repos' recipes consistent, though nothing here depends on it: the fork branches already exist and the revs are pinned, so this builds either way. --------- Co-authored-by: Jonathan Kingston <KingstonMailBox@gmail.com>
jonathanKingston
added a commit
to copse-dev/agent-pane
that referenced
this pull request
Aug 31, 2026
…#1939) Pairs with [copse-dev/tauri-runtime-servo#12](copse-dev/tauri-runtime-servo#12), which moves the patch series onto `tauri-runtime-patches` branches of the org's engine forks. This is the consumer side. ## The bug this fixes Servo mode had two defaults that disagreed. `build:servo` wrote a `tauri.html` with its CSP **enforced**, which only a patched engine can satisfy — while the shell's `[patch]` block was commented out and `patched-servo` was off, so cargo built **stock** libservo. Stock Servo gives `tauri://localhost` an opaque origin that CSP `'self'` can never match, so following the README exactly gave you a blank window with every same-origin subresource blocked. Both working configurations were one manual step away; neither was the one you got for free. ## What changes The engine is no longer something you assemble: ```toml [patch.crates-io] servo = { git = "https://github.com/copse-dev/servo", rev = "3cb68676..." } # ... the CSP fork and all eight stylo crates ``` Live, pinned by rev, fetched by cargo. No clone, no `git am`, no path overrides, nothing to uncomment. `patched-servo` becomes a default feature to match, which is safe in the way that matters: enabling it against stock libservo is a **compile error**, not a silent no-op, because the pref it sets is a struct field only the patched tree has. The feature and the overrides cannot drift apart unnoticed, and the enforced CSP is now correct rather than aspirational. ## Engine iteration still works — and is now the cheap path, not the only one Put a checkout at `../servo` or `../stylo` and `build:servo` writes a gitignored `tauri-shell/.cargo/config.toml` redirecting those crates at it. A `[patch]` in a cargo config takes precedence over the manifest's **per crate**, so a checkout of one repository wins for what it provides while the pins keep covering the other. Delete it and the next run removes the file — the case that would otherwise bite, since a config pointing at a directory that has gone leaves cargo reporting the error instead of us. Every run reports which of the three modes it took: ``` servo engine: pinned (no sibling checkout — using the forks pinned in Cargo.toml) servo engine: checkout (../servo and ../stylo — wrote tauri-shell/.cargo/config.toml) servo engine: artifacts-only (COPSE_SERVO_ARTIFACTS_ONLY=1 — engine untouched) ``` ## CI The `servo mode` job sets `COPSE_SERVO_ARTIFACTS_ONLY=1`. It exists to catch the sidecar bundle rotting, never invokes cargo, and resolving an engine there would be pure cost. ## Verified locally - All three modes exercised, including that removing a checkout removes the generated config. - `cargo generate-lockfile` resolves `servo 0.5.0` and `stylo 0.20.0` from the forks; the lockfile here is regenerated against the pins. - `cargo metadata --no-deps` confirms `default = ["patched-servo"] → tauri-runtime-servo/patched-servo`. - typecheck, lint, format, dead-code (801 modules), plain `pnpm build` still servo-free, `build:servo` + sidecar smoke test. - Unit suite 7654/7656. The two failures are `hooks/session-start` and `hooks/after-file-edit`, which pass 6/6 and 10/10 in isolation — timing-sensitive under parallel load, and nowhere near this change. ## Stock-engine builds Still supported, but now both halves are explicit, because getting one right and not the other is exactly what caused the original bug: ```bash COPSE_TAURI_STRIP_CSP=1 pnpm build:servo cd tauri-shell && cargo run --no-default-features ``` ## Merge order Land [tauri-runtime-servo#12](copse-dev/tauri-runtime-servo#12) first if you want the two repos' recipes consistent, though nothing here depends on it: the fork branches already exist and the revs are pinned, so this builds either way. --------- Co-authored-by: Jonathan Kingston <jonathan@copse.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The
servo-patches/*.patchfiles are gone. The patches now live astauri-runtime-patchesbranches on the org's forks, and[patch.crates-io]names them byrev:77fccacc(servo 0.5.0)67faaab3(stylo 0.20.0)05528760Why
The series existed twice — as files here, and as whatever a consumer's checkout held after applying them — and the recipe pushed the reconciliation onto the consumer: clone two repos at exact revisions,
git am24 patches into one,git apply --3way5 into the other, wire eleven path overrides. The CSP pair had already moved to a branch for this reason. The rest have followed, and the four steps collapse to two: paste a block, enable a feature.Verified
cargo generate-lockfileagainst the block the README now publishes resolvesservo 0.5.0andstylo 0.20.0from the forks — 816 packages, no path anywhere in the graph. The newcheck-engine-pins.shpasses against all ten overrides locally.CI
check-patch-series.sh→check-engine-pins.sh. There is no series to apply, so it instead reads each overridden crate's manifest at its pinned rev and compares the version againstCargo.lock— cargo accepts a[patch]entry only when the replacement satisfies the requirement it replaces, and reports the mismatch at build time rather than in the manifest. It reads ten files over the GitHub API rather than cloning (a shallow servo clone is over a gigabyte), so the job drops from minutes to seconds. A Dependabot bump that outruns the forks still arrives red.It also found something the old check could not have: the graph carries two
selectors,0.36.1for an unrelated dependent and0.40.0for stylo. The old script'slocked_version()would have failed outright on that, but it was only ever called for servo, stylo and CSP, so it never saw it. The new one accepts a pin matching any locked version and fails only when it matches none — the case where the override is silently inert.prepare-patched-servo.shloses its cloning and patching and keeps the part that mattered: lifting the block out ofREADME.mdrather than restating it.Reviewer note
The fork branches are the artefact now, so a force-push to either invalidates the pins here —
check-engine-pins.shis what catches that.