Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions .github/workflows/renovate-hash-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ on:
types: [opened, synchronize]
paths:
- "configs/mister_de10nano_defconfig"
# The kernel-only defconfig copies the main one's kernel stanza, so a
# 6.18 bump touches BOTH files (one Renovate PR, same depName). Listed
# here so a bump is still picked up if a future change ever moves the
# kernel version into the copy alone. configs/mister_rt.fragment is
# deliberately absent: its -rc hash cannot be auto-refreshed (no signed
# manifest upstream; see the kernel step's own note), so triggering this
# workflow for it would do nothing but burn a runner.
- "configs/mister_kernel_defconfig"
- "package/rtl8812au/rtl8812au.mk"
- "package/rtl8814au-morrownr/rtl8814au-morrownr.mk"
- "package/rtl8821au-morrownr/rtl8821au-morrownr.mk"
Expand Down Expand Up @@ -279,21 +287,45 @@ jobs:

newhash=$(echo "$matchline" | awk '{print $1}')
newline="sha256 ${newhash} linux-${kver}.tar.xz"
# Match the RELEASE tarball line SPECIFICALLY (sha256 ... linux-<ver>.tar.xz),
# never "the first sha256 line": linux.hash now also carries entries this
# step must NOT manage -- e.g. the RT beta's -rc cgit snapshot
# (linux-*.tar.gz, no signed manifest exists; see the hash file's own -rc
# block for its provenance rules). A first-line match would clobber
# whichever entry happened to be on top; the filename-anchored match is
# order-independent and leaves foreign lines alone. An RT kernel bump
# (configs/mister_rt.fragment) therefore always needs its hash refreshed
# BY HAND per the hash file's documented TOFU procedure.
oldline=$(grep -m1 -E '^sha256 .* linux-[0-9][0-9.]*\.tar\.xz$' "$linuxhash" || true)
# Match the RELEASE tarball line SPECIFICALLY, never "the first sha256
# line": linux.hash also carries entries this step must NOT manage --
# notably the RT beta's kernel (configs/mister_rt.fragment). A
# first-line match would clobber whichever entry happened to be on top.
#
# Scope the match to THIS pin's major series (linux-<major>.*.tar.xz).
# An extension-only match (linux-*.tar.xz) is not enough: it is
# sufficient only while the RT pin is an -rc, because Buildroot fetches
# -rc as a cgit snapshot (.tar.gz). The moment that pin reaches a
# stable mainline release it becomes linux-7.2.tar.xz -- which the old
# pattern also matched. Verified: with the RT line first, a 6.18 bump
# OVERWROTE it and left the stale 6.18 line intact, producing two 6.18
# entries and no RT entry at all. The major-scoped match keeps the two
# pins on their own lines regardless of order.
#
# An RT kernel bump still always needs its hash refreshed BY HAND, per
# the hash file's documented TOFU procedure -- this step never touches
# that line either way.
major="${kver%%.*}"
release_re="^sha256 .* linux-${major}\.[0-9][0-9.]*\.tar\.xz\$"

# If two lines somehow match, do not guess which one this pin owns.
nmatch=$(grep -c -E "$release_re" "$linuxhash" || true)
if [ "${nmatch:-0}" -gt 1 ]; then
echo "::error::$linuxhash has $nmatch lines matching the ${major}.x release pattern -- refusing to guess which one belongs to this pin." >&2
grep -n -E "$release_re" "$linuxhash" >&2 || true
exit 1
fi

oldline=$(grep -m1 -E "$release_re" "$linuxhash" || true)

if [ "$oldline" != "$newline" ]; then
awk -v newline="$newline" '
# Replace by EXACT string match on the line we found, not by
# re-deriving a regex inside awk -- passing a regex through `awk -v`
# would have its backslash escapes eaten, silently turning `\.` into
# "any character".
awk -v oldline="$oldline" -v newline="$newline" '
BEGIN { done = 0 }
/^sha256 .* linux-[0-9][0-9.]*\.tar\.xz$/ && !done { print newline; done = 1; next }
$0 == oldline && !done { print newline; done = 1; next }
{ print }
' "$linuxhash" > "$linuxhash.tmp"
mv "$linuxhash.tmp" "$linuxhash"
Expand Down
31 changes: 27 additions & 4 deletions docs/renovate.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ for the specific pieces most likely to need a fix on the first live run.
| Pin | File(s) | Mechanism | Hash companion |
|---|---|---|---|
| Buildroot release | `Makefile` (`BUILDROOT_VERSION`) | `customManagers` regex, `github-tags` datasource, `allowedVersions` locked to `2026.02.x` | `BUILDROOT_SHA256` — **manual**, see below |
| Kernel | `configs/mister_de10nano_defconfig` (`BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE`) | `customManagers` regex + a `customDatasources` entry over `kernel.org/releases.json`, filtered to `moniker=longterm` and the `6.18.` prefix; `allowedVersions` locked to `6.18.y` as defense in depth | `board/mister/de10nano/patches/linux/linux.hash` — auto-refreshed by `renovate-hash-sync.yml` from kernel.org's signed `sha256sums.asc` |
| Kernel (6.18.y longterm) | **both** `configs/mister_de10nano_defconfig` *and* `configs/mister_kernel_defconfig` (`BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE`) | one `customManagers` regex listing both files + a `customDatasources` entry over `kernel.org/releases.json`, filtered to `moniker=longterm` and the `6.18.` prefix; `allowedVersions` locked to `6.18.y` as defense in depth. Same `depName` for both files, so Renovate emits **one PR touching both** | `board/mister/de10nano/patches/linux/linux.hash` — auto-refreshed by `renovate-hash-sync.yml` from kernel.org's signed `sha256sums.asc` |
| Kernel (RT/beta, mainline `-rc`) | `configs/mister_rt.fragment` (same symbol, different line) | a **separate** `customManagers` regex + its own `kernelMainline` datasource (`moniker=mainline`); `allowedVersions` locked to `7.x`. Labeled `rt-kernel-pin` + `needs-manual-hash` + `needs-manual-version-check` | **always manual** — the hash-sync kernel step reads its version from the DE10-Nano defconfig and rewrites only that pin's line, so it never touches this one. The PR stays red until a human writes it. Provenance depends on which side of the `-rc` boundary the pin is on: TOFU for a cgit `.tar.gz` snapshot (kernel.org signs no `-rc` manifest), or the signed `sha256sums.asc`/`.sign` once it reaches a stable release |
| 9 driver commit-SHA pins | `package/{rtl8812au,rtl8814au-morrownr,rtl8821au-morrownr,rtl8821cu-morrownr,rtl8188fu,rtl8188eu-aircrack-ng,rtl88x2bu,xone,midilink}/*.mk` | `customManagers` regex per package, `git-refs` datasource tracking the upstream default branch's HEAD via `currentDigest` | matching `.hash` file — auto-refreshed by `renovate-hash-sync.yml` |
| munt tag pin | `package/munt/munt.mk` | `github-tags` datasource, custom `regex:` versioning for the `munt_MAJOR_MINOR_PATCH` tag scheme | `package/munt/munt.hash` — auto-refreshed |
| bcm20702-firmware tag pin | `package/bcm20702-firmware/bcm20702-firmware.mk` | `github-tags` datasource, `loose` versioning (flagged `needs-manual-version-check` — see caveat below) | `package/bcm20702-firmware/bcm20702-firmware.hash` — auto-refreshed |
Expand All @@ -49,12 +50,34 @@ for the specific pieces most likely to need a fix on the first live run.
| CI container digests | `ubuntu:26.04@sha256:...` in `build.yml`, `release.yml`, `reproducibility.yml`'s `container:` blocks | Renovate's built-in `github-actions` manager, `docker` datasource, `pinDigests: true` | n/a — digest updates carry their own content-hash |
| GitHub Actions | every SHA-pinned `uses:` line (with a `# vX.Y.Z` comment) across `build.yml`, `release.yml`, `reproducibility.yml`, `publish-db.yml` | Renovate's built-in `github-actions` manager (no custom config needed — it already understands "SHA-pinned + trailing semver comment" and updates both together) | n/a |

That is **18 customManagers entries** (Buildroot, kernel, 9 driver commits,
munt, bcm20702-firmware, libchdr, lzma-sdk, and the 3 sdcard payload pins)
plus the two built-in managers
That is **19 customManagers entries** (Buildroot, the 6.18 kernel, the RT/beta
kernel, 9 driver commits, munt, bcm20702-firmware, libchdr, lzma-sdk, and the 3
sdcard payload pins) plus the two built-in managers
(`docker` digests, `github-actions`), covering every version/commit/digest pin
this repository maintains by hand except the four listed below.

### Why the two kernel pins are separate managers

`configs/mister_rt.fragment` carries the **identical Kconfig symbol** as the two
defconfigs, but pins a different upstream line (mainline, currently `7.2-rc3` and headed for
7.2 final) with different cadence, provenance, and review bar. A single manager
covering all three files would hand the longterm datasource a `-rc`
`currentValue` and the mainline datasource a `6.18.x` one. So there are two
managers with two datasources and two `depName`s, and each file pattern names
its files explicitly — no globbing over `configs/`, which would silently
re-couple them.

Conversely, the two 6.18 files are deliberately in the **same** manager:
`mister_kernel_defconfig` copies the main defconfig's kernel/toolchain stanza
(see its header and `scripts/check-kernel-defconfig-sync.sh`), so they must move
together. Verified against a real Renovate run with both files held back: two
extracted upgrades, exactly **one** branch
(`renovate/kernel-longterm-6.18-6.x`) covering both.

That lockstep check is what caught the 6.18.38 → 6.18.39 bump landing in only
one of the two files, back when the manager listed just
`mister_de10nano_defconfig`.

## What is deliberately NOT managed, and why

- **`package/xow-firmware`** — pins two Microsoft Windows Update driver
Expand Down
41 changes: 39 additions & 2 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@
"transformTemplates": [
"{\"releases\": [$map($filter(releases, function($r) { $r.moniker = \"longterm\" and $contains($r.version, \"6.18.\") }), function($r) { {\"version\": $r.version} })]}"
]
},
"kernelMainline": {
"description": "kernel.org's releases.json filtered to the CURRENT MAINLINE release -- the line the RT/beta kernel variant tracks (configs/mister_rt.fragment, docs/rt-beta-kernel.md). This is normally a -rc (e.g. 7.2-rc3), which is exactly why it is a separate datasource from kernelLongterm618: the two pins track different upstream lines with different cadence, different provenance, and different review bars, and must never be able to update each other. The outer [ ] is required for the same reason documented above -- releases.json carries exactly one mainline entry, and JSONata would collapse a single-element sequence into a bare object, which Renovate rejects as `no-result` silently.",
"defaultRegistryUrlTemplate": "https://www.kernel.org/releases.json",
"format": "json",
"transformTemplates": [
"{\"releases\": [$map($filter(releases, function($r) { $r.moniker = \"mainline\" }), function($r) { {\"version\": $r.version} })]}"
]
}
},
"customManagers": [
Expand All @@ -75,9 +83,10 @@
},
{
"customType": "regex",
"description": "Bump the pinned kernel (BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE) in the DE10-Nano defconfig, constrained to the current 6.18.y longterm line by the custom datasource above. The companion tarball hash (board/mister/de10nano/patches/linux/linux.hash) is NOT updated here -- it comes from kernel.org's own signed sha256sums.asc; see .github/workflows/renovate-hash-sync.yml, which handles this specific case automatically (unlike Buildroot's hash, above, kernel.org's manifest IS fetchable and parseable without a GPG keyring step beyond what the project's own manual process already does). CI (build.yml, pull_request-triggered) then proves the 24 carried Linux patches still apply against the bumped source -- see docs/renovate.md and PLAN.md \u00a713.",
"description": "Bump the pinned 6.18.y kernel (BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE) EVERYWHERE it appears, constrained to the current longterm line by the custom datasource above. BOTH defconfigs are listed on purpose: configs/mister_kernel_defconfig deliberately copies the main defconfig's kernel/toolchain stanza (see its header and scripts/check-kernel-defconfig-sync.sh), so a manager covering only the main one bumps half the repo and leaves the copy behind -- which is exactly what happened on the 6.18.38 -> 6.18.39 bump and is caught, loudly, by the lockstep check. Because both files carry the same depName, Renovate emits ONE PR touching both. configs/mister_rt.fragment carries the same SYMBOL but is deliberately NOT matched here: it pins the mainline -rc line and has its own manager below. The companion tarball hash (board/mister/de10nano/patches/linux/linux.hash) is NOT updated here -- it comes from kernel.org's own signed sha256sums.asc; see .github/workflows/renovate-hash-sync.yml. CI (build.yml, pull_request-triggered) then proves the carried Linux patches still apply against the bumped source -- see docs/renovate.md and PLAN.md \u00a713.",
"managerFilePatterns": [
"/^configs/mister_de10nano_defconfig$/"
"/^configs/mister_de10nano_defconfig$/",
"/^configs/mister_kernel_defconfig$/"
],
"matchStrings": [
"BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=\"(?<currentValue>[\\d.]+)\""
Expand All @@ -86,6 +95,19 @@
"datasourceTemplate": "custom.kernelLongterm618",
"versioningTemplate": "loose"
},
{
"customType": "regex",
"description": "Bump the RT/beta kernel pin (BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE in configs/mister_rt.fragment), which tracks the mainline -rc line rather than 6.18.y -- see docs/rt-beta-kernel.md and ADR 0021. Kept as a SEPARATE manager from the 6.18 one above, with its own datasource and its own depName, because the two must never be able to propose each other's version: the fragment carries the identical Kconfig symbol, so a single shared manager would hand the longterm datasource a -rc currentValue (and vice versa). The matchString accepts BOTH an -rc and a plain mainline version (7.2-rc3 and 7.2), because 7.2 final IS the intended destination of this pin -- docs/rt-beta-kernel.md picks 7.2 precisely because PREEMPT_RT landed for ARM in 7.1, so the variant follows that line through its -rc series and out the other side. IMPORTANT -- the companion hash is NEVER auto-refreshed for this pin, unlike the 6.18 one: renovate-hash-sync.yml's kernel step reads its version from the DE10-Nano defconfig and only ever rewrites that pin's own line, so it leaves this one alone in every case. An RT bump PR is therefore EXPECTED to be red at the kernel download (\"No hash found for linux-<ver>...\", because BR2_DOWNLOAD_FORCE_CHECK_HASHES empties Buildroot's BR_NO_CHECK_HASH_FOR exemption) until a human refreshes it by hand. That is the intended, safe failure mode -- the same shape as the Buildroot hash above. NOTE that the artifact changes shape across the -rc boundary, and so does the provenance a human should demand: while on an -rc, Buildroot fetches a cgit-generated snapshot (linux-<ver>.tar.gz from git.kernel.org) for which kernel.org publishes NO signed manifest, so the value is TOFU per linux.hash's own -rc block; once this pin reaches a stable mainline release it becomes an ordinary linux-<ver>.tar.xz, which IS covered by kernel.org's signed sha256sums.asc and by a maintainer .sign, and should be transcribed from those rather than TOFU-pinned.",
"managerFilePatterns": [
"/^configs/mister_rt\\.fragment$/"
],
"matchStrings": [
"BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=\"(?<currentValue>\\d+\\.\\d+(?:-rc\\d+)?)\""
],
Comment on lines +104 to +106
"depNameTemplate": "kernel-mainline-rt",
"datasourceTemplate": "custom.kernelMainline",
"versioningTemplate": "loose"
},
{
"customType": "regex",
"description": "RTL8812AU driver commit pin (morrownr/8812au-20210820, main branch). Hash: package/rtl8812au/rtl8812au.hash, refreshed by renovate-hash-sync.yml.",
Expand Down Expand Up @@ -335,6 +357,21 @@
"kernel-pin"
]
},
{
"description": "RT/beta kernel pin (configs/mister_rt.fragment), tracking mainline -rc. Constrained to the 7.x line as defense in depth, mirroring the 6.18 rule above: a jump to a new MAJOR is a deliberate decision about what the beta variant tracks, not routine automation. Labeled distinctly from kernel-pin so a reviewer is never in doubt about WHICH kernel a PR moves -- the two carry the identical Kconfig symbol and otherwise look alike in a diff. needs-manual-hash is not decorative: this PR cannot go green until a human writes the new hash into linux.hash by hand. The hash-sync workflow never touches this line -- and how the value should be obtained depends on which side of the -rc boundary the pin is on (TOFU for a cgit -rc snapshot, kernel.org's signed manifest for a stable release). See the manager description. needs-manual-version-check is carried for the same reason bcm20702-firmware is: `loose` versioning's ordering of a -rcN suffix is not something to trust blindly.",
"matchManagers": [
"custom.regex"
],
"matchDepNames": [
"kernel-mainline-rt"
],
"allowedVersions": "/^7\\./",
"addLabels": [
"rt-kernel-pin",
"needs-manual-hash",
"needs-manual-version-check"
]
},
{
"description": "Driver/firmware commit and tag pins -- label distinctly so a reviewer knows these change out-of-tree kernel-module source, not just a build tool version.",
"matchManagers": [
Expand Down
Loading