Skip to content

ci: add the fork-sync backport queue - #28

Merged
mcfbytes merged 2 commits into
masterfrom
feat/fork-sync-queue
Jul 16, 2026
Merged

ci: add the fork-sync backport queue#28
mcfbytes merged 2 commits into
masterfrom
feat/fork-sync-queue

Conversation

@mcfbytes

Copy link
Copy Markdown
Owner

Why

This repo is the source of truth for the MiSTer kernel, but MiSTer-devel/Linux-Kernel_MiSTer is a live repo other people commit to. Anything landing there after our last reconciliation is something we don't have and nobody has decided about — and nothing ever forces that question.

That's not hypothetical. The fork sat on 5.15.1 through 210 stable releases partly because no moment ever said "these N commits are unaccounted for". And this session alone produced two stale-baseline bugs — one of which nearly shipped an auto-overclocking kernel to upstream.

The sync point did exist before this PR, as prose in docs/patch-provenance.md's header (HEAD f0fb626acadd…). Prose can't be diffed against anything.

What

docs/kernel-recon/fork-sync.conf last reconciled commit per fork branch
scripts/check-fork-sync.sh diffs it against the fork's live HEADs
.github/workflows/fork-sync.yml weekly + dispatch; opens/updates one issue

Watches both branches. MiSTer-v6.18 is the one that matters most: once #75 merges, commits landing there are changes made to our series by other people — and they have to flow back into linux-patches/ or the next regeneration silently erases them. That's the failure this prevents.

Cost

Two compare API calls, no clone, seconds per run. It deliberately doesn't check out the kernel (~300MB) or build anything — "what's new upstream" needs neither. That's what makes a weekly schedule affordable at all; contrast build.yml, whose cold path is ~3h.

Weekly is matched to how fast the fork actually moves (11 commits across 2026 so far). Daily would just re-post the same list six more times before anyone acted on it.

Three deliberate design choices

  • One issue, edited in place, closed when the queue empties. A weekly job that files a fresh issue is a job people mute — and a muted queue is the same as no queue.
  • Exit 1 (commits to triage) does not fail the job. A red X every week trains people to ignore it. Only exit 2 — missing branch, malformed conf — fails, because that means the file now describes something that doesn't exist.
  • gh issue create has no --json/--jq; it prints a URL. The number comes off the URL rather than from a || fallback around a second create, which is how you end up filing two issues.

The one way this breaks

Advancing fork-sync.conf to silence the issue, without dispositioning what it skips. Then the file stops meaning reconciled and starts meaning seen — which is exactly what it exists to prevent. The header says so explicitly.

Verification

  • Reconciled today: reports both branches clean, exit 0.
  • Detects drift: rewinding the v5.15 pointer to the old recon baseline f0fb626ac correctly flags 794e6f002 "New driver for RTL8821CU", exit 1, and renders the markdown issue body.
  • YAML parses, both embedded run blocks pass bash -n, shellcheck clean.

I'll dispatch it once merged to confirm a real run goes green (it should report "fully reconciled" and create nothing).

Follow-up

export-kernel-tree.sh --fork-sync (on #25) should default to reading this file once #25 lands, so the sync point has one home rather than two.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings July 16, 2026 17:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an automated “fork sync / backport queue” mechanism to track unreconciled commits in MiSTer-devel/Linux-Kernel_MiSTer and surface them via a single, continuously-updated GitHub issue.

Changes:

  • Add docs/kernel-recon/fork-sync.conf to record the last reconciled commit per watched fork branch.
  • Add scripts/check-fork-sync.sh to compare those sync points against live fork HEADs via the GitHub compare API (no clone) and emit text/markdown reports.
  • Add .github/workflows/fork-sync.yml to run weekly/on-demand and open/update/close a single labeled issue based on drift.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
scripts/check-fork-sync.sh New CLI script that queries GitHub’s compare API for each watched branch and prints drift reports.
docs/kernel-recon/fork-sync.conf New config file defining the branch→“last reconciled SHA” sync points plus update guidance.
.github/workflows/fork-sync.yml New scheduled workflow that runs the check and manages a single “backport queue” issue.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/check-fork-sync.sh
Comment thread scripts/check-fork-sync.sh
Comment thread .github/workflows/fork-sync.yml Outdated
Comment thread .github/workflows/fork-sync.yml Outdated
mcfbytes added a commit that referenced this pull request Jul 16, 2026
Four review findings on #28, all valid. One of them was worse than reported.

`ahead_by` was used unguarded. Bash arithmetic treats a bare word as an unset
variable, so BOTH `[[ null -eq 0 ]]` and `[[ "" -eq 0 ]]` evaluate TRUE -- verified.
The review said an unexpected response could produce a bogus triage report; it is
the opposite and worse. Any response that parsed but had no ahead_by (auth failure,
rate limit, partial body) made the script print "nothing new" and exit 0: a silent
all-clear. A tool whose entire purpose is to stop commits going unaccounted for had
a path where it silently said all-clear because it could not tell. Now the value
must match ^[0-9]+$ or it exits 2. Verified with a stand-in `gh` returning
{"message":"Bad credentials"}: exits 2 naming the branch, instead of reporting
reconciled.

jq was invoked three times and checked zero. Now checked alongside gh, so a missing
dep is exit 2 with context rather than 127 from somewhere inside a pipeline.

The workflow called the script TWICE -- plain for the log, --markdown for the issue
body with `|| true` to swallow the expected exit 1. Wrong twice over: `|| true`
also swallows exit 2, so a broken run could file an issue with an empty body and
still go green; and two invocations are two sets of API calls that can disagree if
one hits a transient failure. Now one --markdown invocation feeds both, with the
exit code routed through a case (0 clean / 1 triage / 2 fail), and an explicit
assertion that the body is non-empty before it can be posted -- which is the
failure the single invocation exists to close, so it is checked rather than
assumed. Halves the API calls as a side effect.

`gh issue list` now passes --limit 1: only the first match is used, and the default
page of 30 is API work nobody looks at.

Verified: shellcheck clean, YAML parses, both run blocks pass `bash -n`, the normal
path still reports fully-reconciled (exit 0), and the markdown body renders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mcfbytes and others added 2 commits July 16, 2026 12:55
This repo is the source of truth for the MiSTer kernel, but the fork is a live
repo other people commit to. Anything landing there after our last reconciliation
is something we do not have and nobody has decided about -- and nothing ever forces
that question. That is not hypothetical: the fork sat on 5.15.1 through 210 stable
releases partly because no moment ever said "these N commits are unaccounted for",
and this session alone hit two stale-baseline bugs, one of which nearly shipped an
auto-overclocking kernel.

Three pieces:

- docs/kernel-recon/fork-sync.conf -- the last RECONCILED commit per fork branch.
  Previously this existed only as prose in docs/patch-provenance.md's header
  ("HEAD f0fb626acadd..."), which cannot be diffed against anything. Recorded at
  794e6f002 (v5.15) and d9ac12a691 (v6.18); the header spells out that advancing a
  line without dispositioning what it skips is the one thing that breaks the
  mechanism -- it would stop meaning "reconciled" and start meaning "seen".

- scripts/check-fork-sync.sh -- diffs that file against the fork's live HEADs via
  the compare API. One call per branch, no clone: the kernel repo is ~300MB and
  answering "what is new" does not need it. Exit 0 reconciled / 1 triage / 2 error.

- .github/workflows/fork-sync.yml -- weekly, plus dispatch. Seconds per run, no
  build, no checkout of the kernel; far below the noise floor of build.yml's ~3h
  cold path, which is what makes a schedule affordable here at all.

Watches BOTH branches. MiSTer-v6.18 is the one that matters most: once #75 merges,
commits landing there are changes made to OUR series by other people, and they must
flow back into linux-patches/ or the next regeneration silently erases them.

Design points that are deliberate, not incidental:

- ONE issue, edited in place, closed when the queue empties. A weekly job that
  files a fresh issue is a job people mute, and a muted queue is the same as no
  queue.
- Exit 1 (commits to triage) does NOT fail the job -- a red X every week trains
  people to ignore it. Only exit 2 (missing branch, malformed conf) fails.
- `gh issue create` prints a URL and has no --json/--jq; the number comes off the
  URL rather than from a `||` fallback around a second create, which is how you
  file two issues.

Verified: reports "fully reconciled" today (exit 0); rewinding the v5.15 pointer to
the old recon baseline f0fb626ac correctly flags 794e6f002 "New driver for
RTL8821CU" (exit 1) and renders the markdown issue body. YAML parses, both embedded
run blocks pass `bash -n`, shellcheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Four review findings on #28, all valid. One of them was worse than reported.

`ahead_by` was used unguarded. Bash arithmetic treats a bare word as an unset
variable, so BOTH `[[ null -eq 0 ]]` and `[[ "" -eq 0 ]]` evaluate TRUE -- verified.
The review said an unexpected response could produce a bogus triage report; it is
the opposite and worse. Any response that parsed but had no ahead_by (auth failure,
rate limit, partial body) made the script print "nothing new" and exit 0: a silent
all-clear. A tool whose entire purpose is to stop commits going unaccounted for had
a path where it silently said all-clear because it could not tell. Now the value
must match ^[0-9]+$ or it exits 2. Verified with a stand-in `gh` returning
{"message":"Bad credentials"}: exits 2 naming the branch, instead of reporting
reconciled.

jq was invoked three times and checked zero. Now checked alongside gh, so a missing
dep is exit 2 with context rather than 127 from somewhere inside a pipeline.

The workflow called the script TWICE -- plain for the log, --markdown for the issue
body with `|| true` to swallow the expected exit 1. Wrong twice over: `|| true`
also swallows exit 2, so a broken run could file an issue with an empty body and
still go green; and two invocations are two sets of API calls that can disagree if
one hits a transient failure. Now one --markdown invocation feeds both, with the
exit code routed through a case (0 clean / 1 triage / 2 fail), and an explicit
assertion that the body is non-empty before it can be posted -- which is the
failure the single invocation exists to close, so it is checked rather than
assumed. Halves the API calls as a side effect.

`gh issue list` now passes --limit 1: only the first match is used, and the default
page of 30 is API work nobody looks at.

Verified: shellcheck clean, YAML parses, both run blocks pass `bash -n`, the normal
path still reports fully-reconciled (exit 0), and the markdown body renders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mcfbytes
mcfbytes force-pushed the feat/fork-sync-queue branch from 44ec573 to 57a6779 Compare July 16, 2026 17:55
@mcfbytes
mcfbytes merged commit fb130c1 into master Jul 16, 2026
0 of 2 checks passed
@mcfbytes
mcfbytes deleted the feat/fork-sync-queue branch July 16, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants