Skip to content

fix(install.sh): dry-run exits 0 when platform asset missing#877

Merged
senamakel merged 5 commits intotinyhumansai:mainfrom
obchain:fix/install-dryrun-linux-missing-asset
Apr 24, 2026
Merged

fix(install.sh): dry-run exits 0 when platform asset missing#877
senamakel merged 5 commits intotinyhumansai:mainfrom
obchain:fix/install-dryrun-linux-missing-asset

Conversation

@obchain
Copy link
Copy Markdown
Contributor

@obchain obchain commented Apr 24, 2026

Summary

  • install.sh --dry-run on linux/x86_64 no longer hard-fails when the
    latest release ships without a Linux asset. Two stacked bugs fixed in
    the dry-run handler (see below); real installs still exit 1.
  • installer-smoke.yml matrix re-enables ubuntu-22.04 so the Linux
    dry-run path is covered on every PR.
  • New scripts/validate-release-assets.sh — standalone regression guard
    that checks a release exposes every supported platform on both
    latest.json and the release assets list. Runnable locally;
    release.yml wiring left as a maintainer call.

Problem

bash scripts/install.sh --dry-run --verbose on linux/x86_64 exits 1
with x Could not resolve a compatible asset for linux/x86_64 whenever
the latest release lacks a Linux artifact. The documented install path
is broken for Linux users on those releases, and the installer-smoke
matrix has hidden ubuntu-22.04 behind a temporarily disabled comment
for the same reason.

Two bugs stack:

  1. resolve_from_release_api returns rc=2 on "no compatible asset",
    but the bare call under set -euo pipefail aborts the script on
    most bash builds before resolve_rc=$? can capture it. The
    dedicated dry-run handler below was unreachable.
  2. Even when the handler did fire, it re-exited 1 under CI=true /
    GITHUB_ACTIONS=true with the comment "Preserve failure signal
    for automation."
    — directly contradicting the dry-run contract.

Solution

  • Wrap resolve_from_release_api in
    if resolve_from_release_api; then resolve_rc=0; else resolve_rc=$?; fi
    so the rc is always read.
  • Drop the CI / GITHUB_ACTIONS override. Any resolver failure under
    --dry-run now warns + exits 0 with a platform-aware diagnostic.
    Real installs still hard-fail with a releases/latest pointer.
  • Put ubuntu-22.04 back in the installer-smoke matrix now that the
    Linux dry-run path is safe.
  • Ship scripts/validate-release-assets.sh as a standalone regression
    guard so maintainers can verify locally (or in a follow-up CI step)
    that a release covers every supported platform — closing the gap that
    let a Linux-less release ship in the first place.

Submission Checklist

  • Unit tests — N/A (shell); exercised the 4-cell matrix with a
    PATH-shimmed curl / uname harness:
    - linux dry-run + no asset → exit 0 + warn
    - linux real install + no asset → exit 1 + error
    - CI=true GITHUB_ACTIONS=true dry-run → exit 0 (was exit 1)
    - macOS dry-run happy path → exit 0 (unchanged)
  • Integration / smokeubuntu-22.04 re-enabled in
    installer-smoke; fix is now covered on every PR.
  • Validator verifiedscripts/validate-release-assets.sh
    against v0.52.26 correctly reports
    Missing from latest.json: linux-x86_64 and
    Missing release assets: linux-x86_64; full-release synthetic
    fixture exits 0.
  • Doc comments — rationale for the if-guard inline in the
    script; header on the validator explains inputs, exit codes, and
    the supported-platform source-of-truth.
  • Inline comments — dry-run handler commented where the
    contract reasoning lives.

Impact

  • Runtime: Linux install.sh --dry-run becomes exit 0 on
    no-asset. Real installs unchanged. macOS and Windows paths unchanged.
  • CI: installer-smoke now runs on both macOS and Ubuntu; fail-fast
    is already disabled so one lane going red doesn't mask the other.
  • Release: no workflow changes in release.yml /
    release-packages.yml — integration of validate-release-assets.sh
    into the publish gate is intentionally left as a follow-up (needs a
    maintainer call on whether missing Linux should block a release or
    stay informational).
  • Compat: no interface changes; the new script is opt-in.

Related

Closes #785

Summary by CodeRabbit

  • Tests

    • Installation verification now covers additional operating systems to ensure broader compatibility.
  • Bug Fixes

    • Improved installer error messaging when releases are unavailable for your platform.
    • Enhanced error handling during package resolution failures.
  • Chores

    • Added automated validation to ensure release packages meet quality and platform compatibility standards.

obchain added 3 commits April 24, 2026 17:10
Fixes two bugs in the dry-run handler in `scripts/install.sh`:
- `resolve_from_release_api` call → wrapped in `if ... then rc=0 else rc=$? fi`
  so `set -euo pipefail` no longer aborts before `resolve_rc=$?` captures
  rc=2
- `CI=true` / `GITHUB_ACTIONS=true` override → removed (re-exited 1 against
  the dry-run contract)
- dry-run rc ≠ 0 branch → warn + exit 0 with platform-aware diagnostic
- real-install rc ≠ 0 branch → still exit 1, now with a `releases/latest`
  pointer line

Verified via shimmed `curl`/`uname`: linux/x86_64 dry-run = exit 0 + warn
(was exit 1); real install = exit 1; CI env dry-run = exit 0.
Touches `.github/workflows/installer-smoke.yml`:
- `matrix.os` → `[macos-latest, ubuntu-22.04]`
- comment → references tinyhumansai#785 instead of "temporarily disabled — no Linux
  release asset published yet"

Safe now that `install.sh --dry-run` warns + exits 0 when no Linux asset
is published; the Linux lane covers future regressions on every PR.
New `scripts/validate-release-assets.sh`:
- input → `release.json` (GitHub API shape) + `latest.json` (Tauri updater
  manifest)
- supported matrix → `darwin-aarch64`, `darwin-x86_64`, `linux-x86_64`,
  `windows-x86_64`
- asset patterns → `aarch64.app.tar.gz|aarch64.dmg`,
  `x64.app.tar.gz|x64.dmg`, `.AppImage`, `x64.msi|x64-setup.exe`
- exit 0 → every supported platform present in both sources
- exit 1 → any platform missing, with `Missing from latest.json` /
  `Missing release assets` diagnostics on stderr
- exit 2 → misuse (bad argv) or unparseable JSON

No `release.yml` wiring in this PR — that is a maintainer call on whether
missing Linux should block a release or stay informational.

Against the current `v0.52.26`: reports `Missing from latest.json:
linux-x86_64` + `Missing release assets: linux-x86_64`.
@obchain obchain requested a review from a team April 24, 2026 11:54
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

Warning

Rate limit exceeded

@obchain has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 28 minutes and 6 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 28 minutes and 6 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7ca8d5ed-9250-4ea6-b8ba-df522823238e

📥 Commits

Reviewing files that changed from the base of the PR and between 51f0e24 and 098027e.

📒 Files selected for processing (2)
  • scripts/release/publish-updater-manifest.sh
  • scripts/validate-release-assets.sh
📝 Walkthrough

Walkthrough

The changes introduce a new asset validation script, modify the installer to gracefully handle missing platform artifacts in dry-run mode (exit 0 with warnings) while failing real installs, and expand the smoke test workflow to include Linux platform testing.

Changes

Cohort / File(s) Summary
Workflow Configuration
.github/workflows/installer-smoke.yml
OS matrix expanded from macOS to include ubuntu-22.04. Comment updated to reflect new dry-run behavior when Linux assets are unavailable.
Installation Script
scripts/install.sh
Fallback logic now captures return code from resolve_from_release_api before early exit. Dry-run mode emits warnings and exits 0 when no compatible asset found; real installs exit 1 with direct link to releases/latest page.
Asset Validation
scripts/validate-release-assets.sh
New script validates that latest.json and GitHub release assets include all supported platforms (darwin-aarch64, darwin-x86_64, linux-x86_64, windows-x86_64) with matching installer artifact patterns. Exits 0 on success, 1 on missing assets, 2 on errors.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A hop through releases so fine,
Validating assets in a line,
When Linux is lost, no more despair—
Dry runs now skip with graceful care!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly reflects the main fix: dry-run behavior change to exit 0 when platform assets are missing, which is the core change described in the PR objectives.
Linked Issues check ✅ Passed All coding requirements from issue #785 are met: install.sh dry-run exits 0 with warnings on missing assets [#785], release asset validation is implemented [#785], ubuntu-22.04 is re-enabled in CI [#785].
Out of Scope Changes check ✅ Passed The validator script is mentioned as opt-in with no release.yml integration in this PR; all changes align with issue #785 objectives for dry-run behavior, CI coverage, and release validation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
scripts/install.sh (1)

320-322: Minor: "Could not reach release metadata (rc=1)" is slightly misleading.

resolve_from_release_api returns 1 for three distinct conditions: curl failure, python3 missing (line 194-197), and python3 parse failure (line 249 || return 1). The "Could not reach" wording only fits the first. Consider generalizing the message, since this only affects the dry-run diagnostic output:

✏️ Proposed tweak
         *)
-          log_warn "Could not reach release metadata (rc=${resolve_rc}) for ${OS}/${ARCH}."
+          log_warn "Could not resolve release metadata (rc=${resolve_rc}) for ${OS}/${ARCH}."
           ;;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/install.sh` around lines 320 - 322, The log message in the default
case for resolve_from_release_api is misleading because resolve_rc can be 1 for
curl failure, missing python3, or parse failure; update the warning emitted by
log_warn (where resolve_rc is used) to be more general (e.g., "Could not obtain
or parse release metadata (rc=${resolve_rc}) for ${OS}/${ARCH}") so it
accurately covers all failure modes; locate the switch/default handling that
uses resolve_rc and replace the "Could not reach release metadata" text with a
generalized message referencing resolve_rc, OS and ARCH.
scripts/validate-release-assets.sh (2)

67-72: Consider also validating that latest.json itself is published as a release asset.

The inline release-pipeline check referenced in the PR context (.github/workflows/release.yml lines ~876-904) treats /^latest\.json$/ as a required asset because "without this, installed clients can't discover new releases via plugins.updater.endpoints." This validator accepts latest.json as input but doesn't assert it is present in release.assets[], so a release that forgets to upload the manifest would silently pass here (as long as the local file you feed in is valid).

Low priority since release.yml already catches this, but including it would make the script a complete standalone regression guard as described in the header.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/validate-release-assets.sh` around lines 67 - 72, The validator
currently defines ASSET_PATTERNS but doesn't assert that the release actually
includes the literal "latest.json" asset; update the script to explicitly check
the release asset list for an entry named "latest.json" (in addition to existing
pattern checks). Locate the ASSET_PATTERNS variable and the function or block
that iterates over release.assets (the code that validates assets) and add a
guard that fails if no asset with the exact name "latest.json" is present,
returning a non-zero exit code and a clear error message.

75-80: Nit: use with open(...) for JSON loads.

Minor hygiene — avoids leaked file handles and is the idiomatic pattern, matching how the similar blocks in install.sh (lines 169, 203, 282) open files.

♻️ Proposed tweak
 try:
-    release = json.load(open(release_path))
-    latest  = json.load(open(latest_path))
+    with open(release_path, "r", encoding="utf-8") as f:
+        release = json.load(f)
+    with open(latest_path, "r", encoding="utf-8") as f:
+        latest = json.load(f)
 except json.JSONDecodeError as e:
     print(f"validate-release-assets: invalid JSON: {e}", file=sys.stderr)
     sys.exit(2)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/validate-release-assets.sh` around lines 75 - 80, Replace the direct
json.load(open(...)) calls with context managers to avoid leaking file handles:
open release_path and latest_path using "with open(release_path) as f:" / "with
open(latest_path) as f:" and call json.load on the file objects to assign to
release and latest respectively, keeping the existing try/except
json.JSONDecodeError handling and the same error message/exit behavior; locate
the two json.load(open(...)) usages for variables release and latest to make
this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/validate-release-assets.sh`:
- Around line 82-89: The manifest generator is missing logic to resolve the
linux-x86_64 AppImage so add a branch in publish-updater-manifest.sh alongside
the existing darwin-aarch64, darwin-x86_64, and windows-x86_64 handling: call
find_asset to locate the linux AppImage (matching the documented AppImage naming
convention) and then call add_platform with the key "linux-x86_64" and the found
asset name; mirror the pattern used for the other platforms (the functions
find_asset and add_platform) so linux-x86_64 is included in latest.json.

---

Nitpick comments:
In `@scripts/install.sh`:
- Around line 320-322: The log message in the default case for
resolve_from_release_api is misleading because resolve_rc can be 1 for curl
failure, missing python3, or parse failure; update the warning emitted by
log_warn (where resolve_rc is used) to be more general (e.g., "Could not obtain
or parse release metadata (rc=${resolve_rc}) for ${OS}/${ARCH}") so it
accurately covers all failure modes; locate the switch/default handling that
uses resolve_rc and replace the "Could not reach release metadata" text with a
generalized message referencing resolve_rc, OS and ARCH.

In `@scripts/validate-release-assets.sh`:
- Around line 67-72: The validator currently defines ASSET_PATTERNS but doesn't
assert that the release actually includes the literal "latest.json" asset;
update the script to explicitly check the release asset list for an entry named
"latest.json" (in addition to existing pattern checks). Locate the
ASSET_PATTERNS variable and the function or block that iterates over
release.assets (the code that validates assets) and add a guard that fails if no
asset with the exact name "latest.json" is present, returning a non-zero exit
code and a clear error message.
- Around line 75-80: Replace the direct json.load(open(...)) calls with context
managers to avoid leaking file handles: open release_path and latest_path using
"with open(release_path) as f:" / "with open(latest_path) as f:" and call
json.load on the file objects to assign to release and latest respectively,
keeping the existing try/except json.JSONDecodeError handling and the same error
message/exit behavior; locate the two json.load(open(...)) usages for variables
release and latest to make this change.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4be878e7-3757-41db-ba29-021339b839e1

📥 Commits

Reviewing files that changed from the base of the PR and between b329e45 and 51f0e24.

📒 Files selected for processing (3)
  • .github/workflows/installer-smoke.yml
  • scripts/install.sh
  • scripts/validate-release-assets.sh

Comment thread scripts/validate-release-assets.sh
obchain added 2 commits April 24, 2026 17:55
…sent

Addresses CodeRabbit primary finding on tinyhumansai#877. Touches
`scripts/release/publish-updater-manifest.sh`:

- `LIN_X86_64` → `find_asset "^OpenHuman(_| ).*amd64\.AppImage(\.tar\.gz)?$"`
  matching the AppImage naming convention already documented in the
  script header (line 94)
- `[updater] Resolved updater bundles` → adds `linux-x86_64 = <missing>`
  log line alongside darwin/windows
- `add_platform "linux-x86_64" "$LIN_X86_64"` → slotted between
  darwin-x86_64 and windows-x86_64 in the platform list

Safe-by-default: `add_platform` early-returns on empty `name`
(`[ -z "$name" ] && return 0`, line 119). Current releases ship no
AppImage → `LIN_X86_64` stays empty → linux-x86_64 key absent from
manifest, same as today. Once a Linux AppImage is published, the entry
wires automatically without a follow-up change.
…acks

Addresses CodeRabbit secondary note on tinyhumansai#877. Touches
`scripts/validate-release-assets.sh`:

- new `_has_platform(key)` helper → accepts bare `key`,
  `f"{key}-appimage"`, or `f"{key}-app"` variants
- `missing_latest` → uses `_has_platform` instead of the bare
  `key in latest_platforms` membership test

Mirrors the three-step fallback `scripts/install.sh` already uses when
looking up `latest.json` platforms (line 173). Without this the
validator false-fails a release that correctly ships under
`linux-x86_64-appimage` or `linux-x86_64-app`.

Verified locally: real `v0.52.26` still fails with `Missing from
latest.json: linux-x86_64` (linux genuinely missing); synthetic release
with `linux-x86_64-appimage` key now passes (rc=0).
@senamakel
Copy link
Copy Markdown
Member

@obchain brother, so happy to see you again :D really great to see you contribute to the project. there are some build/typecheck issues. just resolve those and clear to merge.

@senamakel
Copy link
Copy Markdown
Member

actually nvm its from some other code issue.. merging this now.

@senamakel senamakel merged commit 1d0c820 into tinyhumansai:main Apr 24, 2026
7 of 13 checks passed
@obchain
Copy link
Copy Markdown
Contributor Author

obchain commented Apr 24, 2026

Thanks Brother @senamakel , Never Late to contribute to something great 😄

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.

[Bug] install.sh --dry-run fails on linux/x86_64 when the latest release has no Linux asset

2 participants