Keep seeded installer artifacts latest stable only#26
Conversation
- Restrict the Unraid release-lock updater to the stable release channel.\n- Previously, release candidates or other metadata channels could be considered if they appeared in USB Creator metadata with a ZIP URL.\n- That risked publishing bundled installer artifacts for non-stable or unintended older release lines.\n- The lock now records its channel, the updater only selects stable releases, and seeded image builds validate that the lock and URL are stable.\n- After publishing the latest stable release, the automation removes bundled seeded IMG assets from older Installer-* releases while leaving their online installer assets available.\n- Documentation now states that only the latest stable release keeps a bundled seeded image.
📝 WalkthroughWalkthroughThis PR extends the Unraid release lock system to enforce stable channel pinning. The updater script now accepts ChangesChannel-aware Stable Release Pinning
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 1 warning)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/update-unraid-release-lock.yml:
- Around line 273-276: The gh release list call that populates release_tags is
capped by "--limit 100", causing older releases to be missed; remove the
"--limit 100" and use gh's pagination (e.g. add "--paginate") so the command: gh
release list --paginate --json tagName,isDraft,isPrerelease --jq '... |
.tagName' returns all releases for the subsequent Installer-* filtering; update
the invocation that sets release_tags accordingly (referencing the release_tags
assignment and the gh release list invocation).
In `@scripts/update-unraid-release-lock.py`:
- Around line 96-99: The code currently swallows ValueError from
validate_release_url(url, version, channel) which allows malformed stable
candidates to be ignored; change the except handler so that if the candidate is
a stable entry (detect via channel == "stable" or url containing "/dl/stable/")
you do not continue silently but surface the error (re-raise the ValueError or
log and exit) including the url, version and channel in the message, otherwise
keep the existing continue behavior for non-stable channels; update the
try/except around validate_release_url to implement this logic so malformed
stable metadata fails fast instead of quietly keeping an older release.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro (Legacy)
Run ID: bb3b884b-8f1b-47e1-9b66-3f219f1481fa
📒 Files selected for processing (6)
.github/workflows/update-unraid-release-lock.ymlbuild/unraid-release-lock.jsondocs/USER_COMMANDS.mddocs/user-build.mdscripts/build-usb-native.shscripts/update-unraid-release-lock.py
| release_tags="$(gh release list \ | ||
| --limit 100 \ | ||
| --json tagName,isDraft,isPrerelease \ | ||
| --jq '.[] | select(.isDraft == false and .isPrerelease == false) | .tagName')" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n .github/workflows/update-unraid-release-lock.yml | sed -n '260,290p'Repository: unraid/unraid-installer
Length of output: 1499
🏁 Script executed:
# Get the full context around the cleanup function
wc -l .github/workflows/update-unraid-release-lock.ymlRepository: unraid/unraid-installer
Length of output: 120
🏁 Script executed:
# Find the cleanup function and understand what it does
grep -n "Installer-\|release_tags\|--limit" .github/workflows/update-unraid-release-lock.yml | head -20Repository: unraid/unraid-installer
Length of output: 715
🏁 Script executed:
# Check if there are many releases in the repo
git ls-files | grep -i releaseRepository: unraid/unraid-installer
Length of output: 268
🏁 Script executed:
# Look at the full cleanup section to understand context
sed -n '250,300p' .github/workflows/update-unraid-release-lock.yml | cat -nRepository: unraid/unraid-installer
Length of output: 2629
🏁 Script executed:
# Count total releases in the repository
gh release list --limit 1000 | wc -lRepository: unraid/unraid-installer
Length of output: 69
🏁 Script executed:
# Check if there are Installer-* releases beyond what gh release list shows
gh api repos/{GITHUB_REPOSITORY}/releases --paginate --jq '.[] | .tag_name' 2>/dev/null | grep -c "^Installer-" || echo "Query check"Repository: unraid/unraid-installer
Length of output: 81
🏁 Script executed:
# Verify the field names for gh release list vs gh api
gh release list --limit 1 --json tagName,isDraft,isPrerelease | head -5Repository: unraid/unraid-installer
Length of output: 136
Eliminate the arbitrary 100-release limit to ensure complete cleanup.
The --limit 100 cap applies before the Installer-* filter, so older installer tags will eventually fall out of scope as the repository grows beyond 100 total releases, leaving their bundled seeded assets permanently. Use pagination to scan all releases.
Suggested fix
- release_tags="$(gh release list \
- --limit 100 \
- --json tagName,isDraft,isPrerelease \
- --jq '.[] | select(.isDraft == false and .isPrerelease == false) | .tagName')"
+ release_tags="$(gh api "repos/${GITHUB_REPOSITORY}/releases" --paginate \
+ --jq '.[] | select(.draft == false and .prerelease == false) | .tag_name')"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| release_tags="$(gh release list \ | |
| --limit 100 \ | |
| --json tagName,isDraft,isPrerelease \ | |
| --jq '.[] | select(.isDraft == false and .isPrerelease == false) | .tagName')" | |
| release_tags="$(gh api "repos/${GITHUB_REPOSITORY}/releases" --paginate \ | |
| --jq '.[] | select(.draft == false and .prerelease == false) | .tag_name')" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/update-unraid-release-lock.yml around lines 273 - 276, The
gh release list call that populates release_tags is capped by "--limit 100",
causing older releases to be missed; remove the "--limit 100" and use gh's
pagination (e.g. add "--paginate") so the command: gh release list --paginate
--json tagName,isDraft,isPrerelease --jq '... | .tagName' returns all releases
for the subsequent Installer-* filtering; update the invocation that sets
release_tags accordingly (referencing the release_tags assignment and the gh
release list invocation).
| try: | ||
| filename, sha256 = validate_release_url(url, version, channel) | ||
| except ValueError: | ||
| continue |
There was a problem hiding this comment.
Don't silently fall back past a malformed stable candidate.
Once an entry already targets /dl/stable/..., swallowing validate_release_url(...) failures lets the updater quietly keep an older stable release instead of surfacing that the newest stable metadata changed shape. That breaks the "latest stable" guarantee and can stall lock updates without any signal.
💡 Suggested direction
version = find_version(name)
if not version or version_tuple(version) < minimum or ".zip" not in url:
continue
- try:
- filename, sha256 = validate_release_url(url, version, channel)
- except ValueError:
+ parsed = urllib.parse.urlsplit(url)
+ path_parts = [part for part in parsed.path.split("/") if part]
+ if len(path_parts) < 2 or path_parts[:2] != ["dl", channel]:
continue
+ filename, sha256 = validate_release_url(url, version, channel)
candidates.append((version_tuple(version), entry, version, filename, sha256))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/update-unraid-release-lock.py` around lines 96 - 99, The code
currently swallows ValueError from validate_release_url(url, version, channel)
which allows malformed stable candidates to be ignored; change the except
handler so that if the candidate is a stable entry (detect via channel ==
"stable" or url containing "/dl/stable/") you do not continue silently but
surface the error (re-raise the ValueError or log and exit) including the url,
version and channel in the message, otherwise keep the existing continue
behavior for non-stable channels; update the try/except around
validate_release_url to implement this logic so malformed stable metadata fails
fast instead of quietly keeping an older release.
Summary
channel: stablein the release lock and enforce it during seeded image buildsInstaller-*releasesWhy
We only want to publish bundled Unraid OS installer images for the current stable release. Older releases should remain available through the online installer path, and non-stable metadata entries must not trigger public bundled image artifacts.
Validation
python3 -m json.tool build/unraid-release-lock.jsonpython3 -m py_compile scripts/update-unraid-release-lock.py.github/workflows/update-unraid-release-lock.ymlshellcheck scripts/build-usb-native.shgit diff --checkSummary by CodeRabbit
New Features
Chores
Documentation