feat: add sync-upstream reusable workflow - #255
Conversation
Add a `sync-upstream.yml` workflow_call reusable workflow that keeps a fork current with the upstream project it was cut from. A scheduled run merges the configured upstream branch into a fork-owned automation branch and opens a PR when the merge brings changes, preserving the fork's own changes. - `git merge --squash` does a real three-way merge without entering a MERGE_HEAD state, so the shared open-sync-pr composite's `git switch -C` works and only upstream's changes since the last common commit are applied. - Clean merge -> mergeable PR; conflict -> commit the markers for manual resolution (or set fail-on-conflict to fail the run instead). - Reuses the open-sync-pr composite, alongside bump-submodule and sync-shared-fragments. Ships the full doc set: caller stub, website reference page, README and workflows.qmd table rows / content-sync section, and a changelog fragment. New capability -> pins @v2 (postdates the @v1 freeze). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UreoJrFPfJ5m9MNeCxX45w
The reference page's "See examples" footer pointed at blob/main/examples/sync-upstream.yml, which 404s in link-check until this PR merges (the file isn't on main yet). Match request-dependabot-review.qmd's form and link the stable tree/main/examples directory instead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UreoJrFPfJ5m9MNeCxX45w
Codecov Report✅ All modified and coverable lines are covered by tests. 🚀 New features to boost your workflow:
|
| `request-dependabot-review.yml` only ever shipped at `@v2` too (it postdates | ||
| the freeze — see [gha#252](https://github.com/d-morrison/gha/issues/252)). | ||
| the freeze — see [gha#252](https://github.com/d-morrison/gha/issues/252)), as | ||
| does `sync-upstream.yml` (added after the freeze — see |
There was a problem hiding this comment.
This correctly adds sync-upstream.yml to the ## Versioning section's @v2 list, but the sibling ### Pinning third-party actions subsection's equivalent list (further down this same file, ~line 340: "...request-dependabot-review.yml at @v2 — see the Versioning section above") still doesn't mention sync-upstream.yml. website/versioning.qmd has the identical pair of lists and isn't touched by this PR at all.
Per CLAUDE.md:
the same versioning convention gets restated in multiple, independently-worded spots: not just once per file, but in separate sections of the same file (e.g.
README.md's## Versioningsection and its nested### Pinning third-party actionssubsection both needed the same@v1/@v2exception clause), and across sibling pages that all describe the tag scheme (website/index.qmd's nav blurb,website/versioning.qmd,website/workflows.qmd,CLAUDE.md's own "About this repo")... gha#181 took six review rounds to fully sweep this exact pattern... because each fix only searched the files already in the diff.
This is exactly that pattern recurring. Please also add sync-upstream.yml to:
README.md's "Pinning third-party actions"@v2list (~line 340)website/versioning.qmd's top summary list (~lines 9–15)website/versioning.qmd's own "Pinning third-party actions" list (~lines 67–76)
|
Code review Reviewed the Bug scan (2 independent Opus passes) + security/logic pass: no significant bugs. Inputs/secrets are all declared and consumed correctly, the Confirmed CLAUDE.md violation (posted inline on README.md:284): this PR correctly adds
This is exactly the multi-site versioning-prose drift pattern Non-blocking observations (not flagged as findings — documented/precedented tradeoffs):
Verdict |
|
Claude finished review — View run Review complete. Summary of findings for PR #255 ( Confirmed issue (posted inline + in summary):
No significant bugs found by either of the two independent Opus bug/security passes — inputs/secrets all correctly declared and consumed, Non-blocking observations (design tradeoffs, not flagged as defects): a conflicting merge (with Posted one inline comment (README.md:284) and a top-level summary comment on the PR. VerdictNeeds more work — fix the confirmed |
The initial commit added sync-upstream.yml to README.md's ## Versioning list and workflows.qmd, but missed the sibling restatements the CLAUDE.md whole-repo versioning-sweep rule covers: - README.md's "Pinning third-party actions" @v2 list - website/versioning.qmd's top summary list and its own "Pinning third-party actions" list (this file wasn't touched before) - website/permissions.qmd's PR-opening workflows list (bump-submodule / sync-shared-fragments / sync-upstream) Verified via a repo-wide grep that sync-upstream now appears everywhere request-dependabot-review does in these lists. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UreoJrFPfJ5m9MNeCxX45w
|
Addressed (adb143d). Added
Verified via Generated by Claude Code |
Document that the @v2 pin resolves only after Morrison-Lab/gha#255 merges and the major tag advances, so a manual dispatch before then failing with "workflow not found" is expected. Addresses review feedback on the unresolved dependency. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UreoJrFPfJ5m9MNeCxX45w
Code reviewRe-reviewed after the follow-up commit ( One new, small finding turned up in this round, which I wasn't able to post as an inline comment because the affected lines aren't part of this PR's diff (they're unchanged context, so GitHub rejects an inline anchor there — not a permission error, just an unreachable line for the review-comment API):
This PR updates the "Several workflows have no corresponding root composite" bullet ( That bullet still omits Suggested fix — update the bullet to: No other issues found: the bug/security review pass (token handling, command-injection surface, conflict-detection exit-code logic, permissions scope, VerdictNeeds more work — one small, easily-fixed same-file doc inconsistency ( |
|
Claude finished review — View run Posted. Summary of this review round for PR #255:
VerdictNeeds more work — one small doc fix remaining. |
The Layout section restates "which workflows call open-sync-pr" in two bullets; the initial commit updated the later one (L41-46) but left the earlier "action-only" bullet listing only bump-submodule and sync-shared-fragments. sync-upstream.yml's "Open PR if upstream brought changes" step calls open-sync-pr@v2, so it belongs in both. Same-file restated-fact drift per this file's own re-grep-the-whole-repo guidance. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UreoJrFPfJ5m9MNeCxX45w
|
Addressed (ba21813). Added Per the same "re-grep the whole repo" guidance, I swept every spot that enumerates Generated by Claude Code |
2026-07-16 00:47 UTC |
|
Claude finished review — View run Code reviewThis is a re-review of PR #255 after the latest commit ( Prior finding — confirmed fixed. The previous round's finding was that exactly matching the suggested fix. Whole-repo re-sweep. Per this PR's own precedent (and No new issues. The only change since the last-reviewed commit ( VerdictReady for merge — the one outstanding finding from the previous round is confirmed fixed, a full re-sweep of the versioning/caller-list prose turned up nothing further, and no new issues were introduced by the latest commit. |
Closes #254.
Adds a
sync-upstream.ymlworkflow_callreusable workflow that keeps a fork current with the upstream project it was cut from — the fork-tracking direction that the existing content-sync family (bump-submodule,sync-shared-fragments) doesn't cover.What it does
A scheduled run:
upstream-repo,upstream-branch; optionalUPSTREAM_TOKENfor a private upstream), without recording a token-bearing remote URL.git merge --squashes upstream into the fork's working tree — a real three-way merge (so the fork's own files are preserved and only upstream's changes since the last common commit are applied) that stays out of aMERGE_HEADstate, so the sharedopen-sync-prcomposite'sgit switch -Cworks.open-sync-prto commit the merge to a reused automation branch and open/update one PR (a no-op when the merge brings nothing).Clean merge → mergeable PR. Conflict → by default the conflict markers are committed so the drift surfaces as a visible PR for manual resolution;
fail-on-conflict: truefails the run instead.Files
.github/workflows/sync-upstream.yml— the reusable workflow.examples/sync-upstream.yml— caller stub (weekly schedule +workflow_dispatch), pinned@v2.website/reference/sync-upstream.qmd— reference page;website/_quarto.ymlsidebar entry.README.md/website/workflows.qmd— table rows, permissions bullet, content-sync section, versioning note (@v2-only, postdates the@v1freeze).changelog.d/add-sync-upstream.added.md— changelog fragment.CLAUDE.md— Layout + pin-list entries.Testing / bootstrapping
Following the
bump-submodule/sync-shared-fragmentsprecedent, there's no end-to-end selftest (the workflow opens PRs / has write side effects); the sharedopen-sync-prcomposite it reuses is already exercised by thesync-prselftest job's no-op test. The caller stub pins@v2, which only resolves once this merges andslide-major-tag.ymladvances the tag.Consumer
d-morrison/altdocadopts it to tracketiennebacher/altdocweekly (companion PR).🤖 Generated with Claude Code
https://claude.ai/code/session_01UreoJrFPfJ5m9MNeCxX45w
Generated by Claude Code