Repository navigation
Catch up with upstream Polly (v8.8.0, 34 commits ahead of our fork point) #28
Description
Activity
Reusable process is now drafted:
- ADR 0003: Upstream Polly Sync Process (status: Proposed) — records the licence-gate-first decision and the D1–D9 rules.
.agent_instructions/upstream_sync.md— the executable runbook (one-timeupstreamremote/polly-upstreambranch setup, the licence-gate command, the diff/triage/port/advance-pointer steps).
Not yet committed — working-tree changes only, pending review.
Correction: the "34 commits behind" figure above was computed against
47e3b41, the ADR 0002 fork commit. A hand-sync already ran on 2026-08-24, before ADR 0003/the runbook existed, carrying the repo to upstream173d6d1d(five Dependabot-only commits, already onmainvia the rename branch). PR #32 corrects the runbook's bootstrap SHA to173d6d1daccordingly.Not a correctness bug — those five would have landed in the auto-skip bucket regardless (ADR 0003, D5) — but the real backlog is five commits smaller than stated above. Rerun Step 1 from the corrected bootstrap once #32 is merged rather than trusting the number in this issue as written.
Sync #1 — 2026-09-25 (runbook Steps 0–3)
Step 0 — licence gate: PASS (checked 2026-09-25)
Upstream
main'sLICENSEis byte-identical to the one at the fork commit47e3b412(BSD-3-Clause, 1501 bytes, empty diff).Step 1 — diff
polly-upstreamat173d6d1d(the corrected bootstrap, #32) →upstream/mainat9a81fdc7: 29 ahead, 0 behind. That replaces the "34" in the issue body: 34 counted from47e3b41, minus the five commits already hand-synced.Step 2 — triage
Port (4)
Upstream What Notes 482bdf82Return null from FaultGeneratorwhen no fault is generated (#3220)Behavioural fix, 1 line in src plus a test 9ad5ae9bFix flaky test (#3231) PooledCancellationTokenSourcePoolchanges fromprivatetointernalnested class. No public API changef35bc00d.NET 11 preparation (#3225) Adds DeterministicTimestampandCheckSdkVulnerabilities, plus smoke specs1a80392bUpdate to xunit v3 (#3131) Tracked separately as #34. Too large for a one-commit port (33 files, replaces coverlet, changes dependencies and src), but must be done to stay aligned with upstream. Affects #14, and I've commented there Skip, with reason (2)
Upstream What Reason 2247db24Update .NET SDK to 10.0.401 (#3222) Dependabot SDK bump in global.json. Fences tracks its owne381630dUpdate CHANGELOG for v8.8.0 (#3232) Upstream's CHANGELOG entry, plus sample references to Polly.*8.8.0. Fences never rewrites Polly's CHANGELOG history, and its entries for ported changes are written in its own voice (runbook Step 4.5)Skip: Dependabot (23)
17 match the runbook's
^Bump .+ from .+ to .+:
16514e3de1b7365edf5395920340c804654715dbf19381eea057350b82f31237e6582c390c29408d5f9fa5899d289ab13c7e2758a1e026e90442ab6f681d9ad59a81fdc76 are Dependabot group bumps ("Bump the … group with N updates"). ADR 0003 D5's pattern doesn't match that wording, so they were reviewed by a person and are skip-with-reason: each is dependency versions only, and Fences tracks its own:
cc882a82f78e6c60791fbaf0a761a8f5a0df17043a466d61Runbook defects found on this first run
- Step 0's
curlcan't run under the project's own.claude/settings.json(Bash(curl:*)is denied). Usegh api 'repos/App-vNext/Polly/contents/LICENSE?ref=main' --jq .content | base64 -d. - Step 1's
gh api …/compare/<sha>...upstream/mainreturns 404, becauseupstream/mainis a local ref. GitHub needsmain. - Step 2's Dependabot pattern misses group bumps. The runbook now says so; widening the automatic pattern itself would amend ADR 0003 D5, so it's left for a separate decision.
- Adding a remote named
upstreammakesghdefault toApp-vNext/Pollyforgh issue,gh prand the rest. Withoutgh repo set-default BrighterCommand/Fences, later steps (including this Step 3 report) would target Polly's repo.
Fixed in #35.
Next
- Step 4: port
482bdf82,9ad5ae9b,f35bc00d(TDD, one PR each, upstream SHA in the commit message). - Step 5: once those are merged, advance
polly-upstreamto9a81fdc7. Port upstream xunit v3 / Microsoft.Testing.Platform v2 migration (App-vNext/Polly@1a80392b) #34 doesn't block the pointer: it's triaged, tracked separately.
- Step 0's
Step 4 progress, sync #1:
482bdf82(FaultGenerator returns null when no fault is generated): ported in Return null from FaultGenerator when no fault is generated #42, merged.9ad5ae9b(flaky pool test gets a dedicated pool): ported in Fix flaky CancellationTokenSourcePool test with a dedicated pool #43, merged.f35bc00d(.NET 11 prep): next, as a partial port covering the build props only. Its Specs edits wait for Port upstream xunit v3 / Microsoft.Testing.Platform v2 migration (App-vNext/Polly@1a80392b) #34.
Decision for this sync: ports don't hand-edit
CHANGELOG.md. It's generated from PR titles at release time, so each port PR's title is its changelog entry.Sync #1 is complete (Step 5).
polly-upstreammoves from173d6d1dto9a81fdc7(Bump codecov/codecov-action from 7.0.0 to 7.1.0 App-vNext/Polly#3234), the last commit this sync triaged. The next sync's Step 1 diff starts there.polly-upstreamis a local branch; if it's lost, recreate it from this comment.- Ported:
482bdf82(Return null from FaultGenerator when no fault is generated #42),9ad5ae9b(Fix flaky CancellationTokenSourcePool test with a dedicated pool #43) andf35bc00d, whose build props went in Prepare the build for .NET 11 (deterministic timestamps, SDK vulnerability check) #44 while its Specs edits wait for Port upstream xunit v3 / Microsoft.Testing.Platform v2 migration (App-vNext/Polly@1a80392b) #34. All three are merged. - Triaged but not yet ported:
1a80392b(xunit v3 / MTP v2), tracked in Port upstream xunit v3 / Microsoft.Testing.Platform v2 migration (App-vNext/Polly@1a80392b) #34. - Process fixes found during this sync: docs: fix upstream sync runbook defects found on first run #35 (runbook, merged) and docs: a port's PR title is its CHANGELOG entry (runbook Step 4.5, ADR 0003 D8) #45 (the PR title is the CHANGELOG entry, in both runbook Step 4.5 and ADR 0003 D8, awaiting review).
Looking ahead: upstream already has 7 commits past
9a81fdc7, and all of them are Dependabot bumps.- added 6 commits that reference this issue
on Oct 3, 2026
Summary
Fences forked from
App-vNext/Pollyat commit47e3b41(~Polly 8.7.x). Upstream is stillBSD-3-Clause and
fork-migration-plan.md§5 (risk R2) already commits us to tracking it —"Keep a read-only
upstreamremote and apolly-upstreamtracking branch. Cherry-picks willneed path/namespace fixups — that is the accepted cost of D1." That remote/branch was never
actually created, and upstream has moved on: Polly 8.8.0 shipped 2026-09-14, and
App-vNext/Polly'smainis now 34 commits ahead of our fork point, 0 behind.While Polly's licence keeps letting us pull these changes (we only have to re-brand them), we
should be doing this on a cadence, with a repeatable process, rather than discovering the drift
ad hoc and re-deriving the triage from scratch each time, as this issue just had to.
What's behind
Checked via
gh api repos/App-vNext/Polly/compare/47e3b41...main(2026-09-20):dotnet,xunit,github-codeql-action,SonarAnalyzer.CSharp,MinVer,Cake.Sdk,zizmor-action,codecov-action,meziantou.framework.nugetpackagevalidation.tool,Refit.HttpClientFactory,azure/login,anchore/sbom-action— we track most of these independently via our own Dependabot config, so likely skip, not port482bdf82— "Return null fromFaultGeneratorwhen no fault is generated" (#3220) — worth porting1a80392b— "Update to xunit v3" (#3131) — evaluate; Fences already diverges from Polly's test conventions (NSubstitute vs FakeItEasy,test/vstests/), so this may not transplant cleanlyf35bc00d— ".NET 11 preparation" (#3225) — evaluate against our ownglobal.json/TFM supporte381630d— "Update CHANGELOG" (the 8.8.0 entry) — useful as a summary of what upstream considers user-visible in this range8 of the 34 commits landed after the
8.8.0tag itself (9ad5ae9b) and are unreleaseddependency bumps on upstream
main.This isn't a simple
git pullPhase 2 of the migration renamed the namespace, assembly names, package IDs, the strong-name key
(
Fences.snkvsPolly.snk), and the onePolly-named public type(
PollyServiceCollectionExtensions→FencesServiceCollectionExtensions). A straight cherry-pickwill conflict on nearly every file it touches. That's the accepted cost recorded in R2 — this
issue is about doing that porting work, not avoiding it.
Proposed approach for this catch-up
LICENSEis still what we based the fork on before doing any diff/triage/port work.upstreamremote (https://github.com/App-vNext/Polly.git) and apolly-upstreamtracking branch pinned at47e3b41, per the R2 mitigation that was plannedbut never executed.
port (behavioural fixes — at minimum #3220), and decide-case-by-case (xunit v3, .NET 11 prep).
SHA in each commit message for traceability.
CHANGELOG.mdentry in Fences' own voice for anything ported — the file itself is neverrewritten (per
CLAUDE.md), only appended to.polly-upstreamto the SHA just triaged, so the next catch-up's diff starts thereinstead of back at
47e3b41.Reusable process
The point of formalising this is to make the next catch-up cheap — most of the cost above was
spent re-deriving "what changed and does it matter", which a repeatable process should do for us.
Step 0 — Licence gate (blocking, runs first, every time). Fetch upstream's current
LICENSEat the tip of
mainand diff it against our recorded baseline (today: BSD-3-Clause, matching ourown
LICENSE, copied at the fork). If it has changed at all, stop — do not run the diff ortriage steps. A licence change is a "should we still be pulling from this repo" decision, not
something to fold into routine triage; it needs explicit maintainer/legal review before any more
upstream code enters Fences. Note this is distinct from the OSMF: OSMF governs App vNext's own
binary distribution and doesn't touch the source licence (see
README.md, the "OSMF" section)— it's the
LICENSEfile text itself we're gating on, not App vNext's pricing policy for theirown packages.
Step 1 — Cheap diff. Compare
polly-upstream(pinned at the last-synced SHA, not the originalfork point) against upstream
main/latest tag, so each run only surfaces what's new since lasttime.
Step 2 — Auto-triage. Bucket commits automatically where possible: commit messages matching
Dependabot's
Bump <dep> from <x> to <y>pattern → default to the skip bucket, since we alreadytrack our own dependencies independently; everything else → needs-human-triage.
Step 3 — Report into one recurring issue, not a fresh write-up. Update a single ongoing
tracking issue with: the licence-gate result, the new commits since last sync, and the
auto-triage buckets, rather than reconstructing the analysis each time.
Step 4 — Port (human). Apply the kept commits with the rename fixups, upstream SHA references,
and a CHANGELOG entry, per steps 3–4 above.
Step 5 — Advance the pointer. Move
polly-upstreamforward to what was just triaged.Where it lives.
.agent_instructions/upstream_sync.mdshould capture steps 0–5 as the durablerunbook — per
CLAUDE.md's "Context Management" guidance, this belongs in a project-owned file,not memory. Whether steps 0–2 are worth automating as a scheduled workflow (vs. a manual runbook
someone runs monthly) is an implementation choice for whoever picks this up; either way the
licence gate must run before the other steps, automated or not. Given the licence gate is a
standing legal-risk control rather than a workflow preference, it's also worth a short ADR (R2
says "record this in ADR 0002", but the merged
docs/adr/0002-fork-polly-as-fences.mdonly coversthe decision to fork, not sync mechanics — this would be a new one).
Acceptance
upstreamremote +polly-upstreamtracking branch exist and are documented.for this catch-up and the next one.
.agent_instructions/upstream_sync.mdand/or anADR, so the next catch-up doesn't re-derive it from scratch.