ci(release): stop the macOS preview updater bundle colliding with itself - #1281
Conversation
…arding it Four of the open low-VRAM reports (#1240, #1246, #1248 on 4 GB cards; #1277 on 6 GB) share one shape: the user generates, waits out the entire 300s compute budget, and is then told the job "was too heavy for the available compute". The warning existed the whole time. Routing computes it (#1226's `_caveat`: "…has 4.0 GB VRAM; this engine wants about 6 GB. It will run, but expect slow generations that may time out"), and `/engines/select` echoes it in `routing_reason` — but notifyEngineSelected only surfaced a reason when `routing_status === 'cpu_fallback'`. The VRAM caveat rides on an ACCELERATED verdict, so it fell through to the green "switched" success toast and was thrown away. The user was told everything was fine, then waited five minutes to find out it wasn't. Now any caveat on the echo raises a warn-tone toast naming it, with a longer duration since it lists the ways around the limit. This covers the kernel-risk caveat on the same path. Deliberately still ADVISORY, not blocking — matching the routing layer's documented contract (the driver can page to system RAM, and short inputs fit where long ones don't). The engine is still selected; the user just finds out now instead of after the timeout. This is the first-run path too: the wizard's library step shares notifyEngineSelected. Fail-before verified: both new tests fail against the previous version. Known remaining gap: a user whose engine is already selected sees this only when they re-pick. A generate-time preflight would close that, but it needs a "once per session, not per generate" design — filed as follow-up rather than guessed at here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The nightly preview run has failed on both macOS legs since early July:
Uploading OmniVoice Studio_x64.app.tar.gz...
##[error]Validation Failed: {"resource":"ReleaseAsset",
"code":"already_exists","field":"name"}
`preview` is a ROLLING release, reused every night, and macOS updater
artifacts are the only ones Tauri names without the version:
OmniVoice Studio_0.4.1-103_x64.dmg unique per run — uploads fine
OmniVoice Studio_x64.app.tar.gz constant — collides on run 2+
Consequences, verified against the live release: the macOS updater bundles on
`preview` were last written 2026-07-04 (x64) and 2026-07-05 (aarch64), and
latest.json 2026-07-13 — three weeks stale as of today. Preview-channel macOS
users had no working update path. The failure also lands AFTER the dmg
upload, so each run looked partly successful while going red.
Deletes this arch's updater bundle before the upload. Matches the STORED
asset name by querying the release rather than guessing the spelling — GitHub
rewrites spaces to dots, so "OmniVoice Studio_x64.app.tar.gz" is stored as
"OmniVoice.Studio_x64.app.tar.gz" and a literal delete-asset by the uploaded
name would silently no-op.
Scoped to the preview path (a v* tag creates a fresh release with nothing to
collide with) and to the job's own arch, so the parallel aarch64/x64 legs
can't touch each other's assets. Verified the filter against all 209 live
preview assets: it matches exactly the 4 colliding updater files and no
versioned artifact.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
| Filename | Overview |
|---|---|
| .github/workflows/release.yml | Adds preview-only, architecture-scoped cleanup of stale macOS updater assets before the Tauri release upload. |
| tests/test_release_preview_asset_cleanup.py | Exercises the workflow shell body against stubbed GitHub CLI responses, including missing assets, authorization failures, and architecture filtering. |
Reviews (3): Last reviewed commit: "Merge branch 'main' into fix/preview-mac..." | Re-trigger Greptile
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe workflow removes stale architecture-specific macOS updater assets from preview releases. The frontend adds localized caveat messages and changes engine-selection notifications to show warning toasts when routing reasons are returned, with tests for VRAM and kernel-risk cases. ChangesPreview release asset cleanup
Engine caveat notifications
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 6 | ❌ 3❌ Failed checks (3 warnings)
✅ Passed checks (6 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 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/release.yml:
- Around line 554-568: Update the preview cleanup commands around gh release
view and gh release delete-asset to distinguish expected missing release/asset
responses from authentication, permission, network, and transient failures.
Continue successfully only when the release or target asset is genuinely absent;
otherwise propagate the gh failure so the workflow stops before the Tauri
upload. Do not use unconditional || true or failure-swallowing fallbacks for
these API calls.
In `@frontend/src/i18n/locales/pl.json`:
- Line 582: Replace the selectWithCaveat value with natural, locale-specific
wording in frontend/src/i18n/locales/pl.json#L582-L582,
frontend/src/i18n/locales/pt.json#L582-L582,
frontend/src/i18n/locales/ru.json#L582-L582,
frontend/src/i18n/locales/sv.json#L582-L582,
frontend/src/i18n/locales/th.json#L582-L582,
frontend/src/i18n/locales/tr.json#L582-L582,
frontend/src/i18n/locales/uk.json#L582-L582,
frontend/src/i18n/locales/vi.json#L582-L582,
frontend/src/i18n/locales/zh-CN.json#L541-L541, and
frontend/src/i18n/locales/zh-TW.json#L582-L582, while preserving the {{engine}}
and {{reason}} placeholders.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: c33faa79-2795-4953-8084-7056a3d07829
📒 Files selected for processing (24)
.github/workflows/release.ymlfrontend/src/i18n/locales/ar.jsonfrontend/src/i18n/locales/de.jsonfrontend/src/i18n/locales/en.jsonfrontend/src/i18n/locales/es.jsonfrontend/src/i18n/locales/fr.jsonfrontend/src/i18n/locales/hi.jsonfrontend/src/i18n/locales/id.jsonfrontend/src/i18n/locales/it.jsonfrontend/src/i18n/locales/ja.jsonfrontend/src/i18n/locales/ko.jsonfrontend/src/i18n/locales/nl.jsonfrontend/src/i18n/locales/pl.jsonfrontend/src/i18n/locales/pt.jsonfrontend/src/i18n/locales/ru.jsonfrontend/src/i18n/locales/sv.jsonfrontend/src/i18n/locales/th.jsonfrontend/src/i18n/locales/tr.jsonfrontend/src/i18n/locales/uk.jsonfrontend/src/i18n/locales/vi.jsonfrontend/src/i18n/locales/zh-CN.jsonfrontend/src/i18n/locales/zh-TW.jsonfrontend/src/test/engineSelectToast.test.jsfrontend/src/utils/engineSelectToast.js
The cleanup step treated every `gh` failure as "nothing to clear" — 401, 403, 429 and network errors included. That reintroduces the outage it was written to fix, with the evidence removed: the stale bundle survives, the Tauri upload dies with `already_exists`, and the one step that could have explained why is green. Three weeks of broken macOS Preview updates started exactly this way. Only an absent release/asset is benign now. A 404 on view means "no preview release yet" (GH_TOKEN is scoped to this repo, so 404 really is absence); a 404 on delete means someone already removed it, which satisfies the goal. Every other failure fails the step with the reason printed. An unexpected arch is also fatal rather than a silent skip — same class of blind spot. Adds tests/test_release_preview_asset_cleanup.py, which extracts this step's real shell body from release.yml (so it cannot drift) and runs it against a stubbed `gh`: 6 of the 8 cases fail against the previous version. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
# Conflicts: # frontend/src/i18n/locales/ar.json # frontend/src/i18n/locales/de.json # frontend/src/i18n/locales/en.json # frontend/src/i18n/locales/es.json # frontend/src/i18n/locales/fr.json # frontend/src/i18n/locales/hi.json # frontend/src/i18n/locales/id.json # frontend/src/i18n/locales/it.json # frontend/src/i18n/locales/ja.json # frontend/src/i18n/locales/ko.json # frontend/src/i18n/locales/nl.json # frontend/src/i18n/locales/pl.json # frontend/src/i18n/locales/pt.json # frontend/src/i18n/locales/ru.json # frontend/src/i18n/locales/sv.json # frontend/src/i18n/locales/th.json # frontend/src/i18n/locales/tr.json # frontend/src/i18n/locales/uk.json # frontend/src/i18n/locales/vi.json # frontend/src/i18n/locales/zh-CN.json # frontend/src/i18n/locales/zh-TW.json # frontend/src/test/engineSelectToast.test.js # frontend/src/utils/engineSelectToast.js
… code (#1290) * ci(windows): make the ffmpeg retry test the outcome, not choco's exit code The chocolatey feed 503'd; choco printed "Unable to find package 'ffmpeg'" and "installed 0/0 packages" — then exited 0. The retry loop added on 2026-07-20 for this exact class was `choco install ... && break`, so it broke out on attempt 1, no backoff ran, and the job died one line later on `ffmpeg: command not found`. It took #1281 red on an unrelated change. A retry that trusts a lying exit code is not a retry. The loop now exits on `command -v ffmpeg` and still fails the job loudly when ffmpeg never arrives. Tests extract the real step body from ci.yml and run it against a stubbed choco; 2 of the 4 fail against the previous loop. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(ci): pin PATH to the stub dir so the retry test can't false-green The harness inherited the ambient PATH, so a real ffmpeg satisfied `command -v` and the loop exited on attempt 1 — every assertion passed against a broken workflow. It happened twice: /opt/homebrew/bin locally, then /usr/bin on the Linux runner, which is what took this PR red. PATH is now the stub dir alone, with the few real tools the stubs need symlinked in, and stub shebangs are absolute (`/usr/bin/env bash` cannot resolve bash when PATH is one directory). test_harness_actually_hides_ffmpeg asserts the sandbox is a sandbox, so the next leak fails loudly instead of quietly passing. 2 of 5 fail against the old `&& break` loop. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ci: give the Windows smoke leg its own timeout, per-leg not shared Smoke (Windows) has been dying at 10m08s inside `uv sync`, and the shared 10-minute budget made it self-perpetuating: the leg is killed before the post-step saves the uv cache, so the next run starts cold and dies the same way. Nothing primes the cache, so it never gets faster. Measured on run 30385710466 — Linux 65s, macOS 65s, Windows still installing torch when the job was killed. Windows now gets 25 minutes, priced for one cold install to finish and populate the cache; warm runs land nowhere near it. Per-leg rather than raising the shared value, so a genuine hang on Linux or macOS still fails fast instead of inheriting Windows' allowance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ci(windows): skip the backoff after the final attempt; tighten the tests CodeRabbit, both valid: - The loop announced "retrying in 90s" and slept after attempt 3, though no fourth attempt exists — 90s added to an already-doomed job. - The retry tests asserted `attempts >= N`, so a regression that kept going after ffmpeg appeared would still pass. Pinned to exact counts, plus a case asserting the final attempt announces no retry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The nightly preview run has been failing on both macOS legs since early July, and nobody noticed because the failure lands after the dmg upload — so each run looked partly successful while going red.
Cause
previewis a rolling release, reused every night. macOS updater artifacts are the only ones Tauri names without the version:OmniVoice Studio_0.4.1-103_x64.dmgOmniVoice Studio_x64.app.tar.gzWindows
.msiand Linux.AppImageare version-stamped too, so only macOS is affected.Impact (verified against the live release)
OmniVoice.Studio_x64.app.tar.gzOmniVoice.Studio_aarch64.app.tar.gzlatest.jsonThree weeks stale as of today. Preview-channel macOS users have had no working update path, which per CLAUDE.md is a release-channel bug to fix immediately rather than backlog.
Fix
Delete this arch's updater bundle before uploading the new one.
OmniVoice Studio_x64.app.tar.gzis stored asOmniVoice.Studio_x64.app.tar.gz, andgh release delete-assetwith the uploaded name would silently no-op. That subtlety is why the naive version of this fix wouldn't have worked.v*tag creates a fresh release with nothing to collide with.Verified the filter against all 209 live preview assets: it matches exactly the 4 colliding updater files and no versioned artifact.
Not addressed here
Those 209 assets are themselves a problem — every night's dmg/msi/AppImage accumulates on the rolling release forever. Worth a retention sweep, but that's a separate change with its own blast radius.
Updated the nightly macOS
release.ymlworkflow to, on rollingpreviewruns, query the existingpreviewprerelease assets and delete any matching stale architecture-specific updater bundle.app.tar.gz(and optional.sig) before uploading, failing only on unexpectedgherrors (authorization/rate limits/network/arch issues) while treating missing releases/assets as benign. This prevents updater bundle name collisions that caused preview release failures after earlier partial uploads. Also added caveat-aware engine-selection warning toasts (engines.selectWithCaveat) with updated localized strings and corresponding test coverage; please review the preview-only asset deletion matching scope/patterns and the new “routing_reason → warning toast and exit” behavior for correctness.