Skip to content

Fix fresh Windows and Linux runtime setup - #49

Merged
gitcommit90 merged 1 commit into
mainfrom
fix/desktop-runtime-packaging
Aug 1, 2026
Merged

Fix fresh Windows and Linux runtime setup#49
gitcommit90 merged 1 commit into
mainfrom
fix/desktop-runtime-packaging

Conversation

@gitcommit90

@gitcommit90 gitcommit90 commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Outcome

Fixes the two fresh-install failures found during 0.0.32 end-user acceptance:

  • Windows no longer aborts on the expected pre-install wsl.exe --version failure, and elevated host-setup errors are preserved in shared setup status.
  • Linux host archives now include SHA-256-pinned x64 and arm64 Cloudflare tunnel connectors, resolve the running architecture, and fail closed when the connector is missing.

Bumps the synchronized desktop candidate to 0.0.33.

Verification

  • npm run typecheck
  • npm run build
  • npm run test:onboarding-browser (20 passed)
  • npm test (112 passed, 2 documented skips)
  • Focused Windows PowerShell parser check on the Windows 11 acceptance host
  • bash -n site/public/install.sh site/public/update-host.sh
  • git diff --check

Summary by CodeRabbit

  • New Features

    • Added architecture-specific Cloudflare tunnel connectors for Linux x64 and arm64 releases.
    • Installers and updates now verify the matching executable connector is present.
    • Updated the default channel-machine image to version 0.0.33.
  • Bug Fixes

    • Improved Windows WSL setup error handling and status reporting.
    • Added SHA-256 validation for packaged Linux connector binaries.
  • Documentation

    • Updated the changelog, README, and release version to 0.0.33.

Signed-off-by: Joseph Yaksich <gitcommit90@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This release updates v0.0.33 references, improves Windows WSL setup error handling, and adds SHA-256-verified x64 and arm64 Cloudflared binaries. Runtime resolution, installation, updates, and tests now validate the matching architecture-specific connector.

Changes

Release hardening

Layer / File(s) Summary
Release metadata and image pin updates
package.json, README.md, src/server/channel-computers.ts, src/server/db.ts, test/channel-computers.mjs, CHANGELOG.md
Release metadata, channel-machine image defaults, tests, and changelog links now reference v0.0.33.
WSL setup error handling
scripts/install-wsl-runtime.ps1, test/desktop.mjs
WSL probing preserves the exit code and restores the prior error preference. Unexpected elevated setup errors now report through Fail-Setup.
Cloudflared packaging and architecture validation
scripts/package-linux-host.mjs, src/server/connectors.ts, site/public/install.sh, site/public/update-host.sh, test/connectors.mjs, test/site.mjs
The Linux package includes pinned executable Cloudflared binaries for x64 and arm64. Runtime, installer, updater, and integration tests validate the matching architecture asset.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant packageLinuxHost
  participant ReleaseArchive
  participant install.sh
  participant update-host.sh
  participant connectorBinary
  packageLinuxHost->>ReleaseArchive: Add verified executable x64 and arm64 cloudflared assets
  install.sh->>ReleaseArchive: Validate the host-architecture connector
  update-host.sh->>ReleaseArchive: Validate the CONNECTOR_ARCH connector
  connectorBinary->>ReleaseArchive: Resolve the packaged host-architecture connector
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the outcome and verification, but it omits the required change type, release notes, acceptance ledger, and checklist sections. Add the required template sections, select the change type, provide release-note bullets, complete the acceptance ledger, and mark verification items.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the Windows and Linux fresh-install fixes in a concise sentence.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/desktop-runtime-packaging

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

@gitcommit90
gitcommit90 merged commit e5796ec into main Aug 1, 2026
5 of 6 checks passed
@gitcommit90
gitcommit90 deleted the fix/desktop-runtime-packaging branch August 1, 2026 18:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
test/desktop.mjs (1)

194-194: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Bound this assertion to the HostSetup block.

The [\s\S]* segments are unbounded. The script-level try at line 186 and catch at line 300 of scripts/install-wsl-runtime.ps1 already satisfy this pattern. The test therefore still passes if the try/catch inside if ($HostSetup) is removed, so it does not guard the behavior it describes. Anchor the match on exit 0 immediately before the HostSetup catch.

💚 Proposed tighter assertion
-  assert.match(windowsRuntime, /if \(\$HostSetup\)[\s\S]*try \{[\s\S]*catch \{[\s\S]*Fail-Setup \$message/, "unexpected elevated host-setup errors are written to shared status instead of collapsing to an unexplained exit code");
+  assert.match(windowsRuntime, /if \(\$HostSetup\) \{\s*try \{[\s\S]*?\n\s*exit 0\r?\n\s*\} catch \{[\s\S]*?Fail-Setup \$message/, "unexpected elevated host-setup errors are written to shared status instead of collapsing to an unexplained exit code");
🤖 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 `@test/desktop.mjs` at line 194, Update the windowsRuntime assertion in the
desktop test to scope the try/catch match to the if ($HostSetup) block by
requiring exit 0 immediately before its catch. Keep the assertion checking that
the HostSetup catch invokes Fail-Setup $message, while preventing script-level
try/catch blocks from satisfying the pattern.
test/connectors.mjs (1)

8-20: 🔒 Security & Privacy | 🔵 Trivial | 🏗️ Heavy lift

Add behavioral coverage for the packaging and digest contract.

This test checks source text only. It does not prove that both binaries enter the archive, retain executable mode, or fail on a digest mismatch. It also does not exercise resolution from appRoot/resources.

Add a deterministic fixture or mocked packaging test, plus a runtime resolver test for the matching architecture.

🤖 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 `@test/connectors.mjs` around lines 8 - 20, Add behavioral coverage beyond the
source-text assertions in the packaging and resolver tests: use a deterministic
fixture or mocked packaging flow to verify both architecture-specific
cloudflared binaries enter the Linux archive with executable mode and reject
digest mismatches, and add a runtime test exercising connector resolution from
appRoot/resources for the host architecture. Anchor changes around the Linux
packaging entry point and the connector resolver used by the existing test.
🤖 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 `@scripts/install-wsl-runtime.ps1`:
- Around line 171-173: Update the finally cleanup block around $hostTemporary so
Remove-Item is best-effort and cannot replace the original failure under the
script-wide Stop policy. Suppress or locally handle cleanup errors while
retaining the existing Test-Path, recursive, and forced removal behavior,
allowing the original elevated setup error to reach catch and Fail-Setup
unchanged.
- Line 147: Update the Start-Process invocation assigning $installer to
explicitly quote the $msi path in the -ArgumentList passed to msiexec.exe,
matching the quoting approach already used near line 196 so paths containing
spaces install correctly.
- Around line 45-52: Update the WSL invocation block around `$raw` and `$code`
to initialize `$code` to a nonzero failure value before calling `& $wsl`, then
use `$?` to confirm the command launched successfully before accepting
`$LASTEXITCODE`. Preserve the existing exit-code handling for successfully
launched `wsl.exe`, while ensuring missing or blocked executables fail closed
and cannot reuse a stale `$LASTEXITCODE`.

---

Nitpick comments:
In `@test/connectors.mjs`:
- Around line 8-20: Add behavioral coverage beyond the source-text assertions in
the packaging and resolver tests: use a deterministic fixture or mocked
packaging flow to verify both architecture-specific cloudflared binaries enter
the Linux archive with executable mode and reject digest mismatches, and add a
runtime test exercising connector resolution from appRoot/resources for the host
architecture. Anchor changes around the Linux packaging entry point and the
connector resolver used by the existing test.

In `@test/desktop.mjs`:
- Line 194: Update the windowsRuntime assertion in the desktop test to scope the
try/catch match to the if ($HostSetup) block by requiring exit 0 immediately
before its catch. Keep the assertion checking that the HostSetup catch invokes
Fail-Setup $message, while preventing script-level try/catch blocks from
satisfying the pattern.
🪄 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 Plus

Run ID: a5617a05-665e-4bc7-a305-a1324ae378c6

📥 Commits

Reviewing files that changed from the base of the PR and between c232d30 and 26cf3b4.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (14)
  • CHANGELOG.md
  • README.md
  • package.json
  • scripts/install-wsl-runtime.ps1
  • scripts/package-linux-host.mjs
  • site/public/install.sh
  • site/public/update-host.sh
  • src/server/channel-computers.ts
  • src/server/connectors.ts
  • src/server/db.ts
  • test/channel-computers.mjs
  • test/connectors.mjs
  • test/desktop.mjs
  • test/site.mjs

Comment on lines +45 to +52
$previousErrorAction = $ErrorActionPreference
try {
$ErrorActionPreference = "Continue"
$raw = & $wsl @ArgumentList 2>&1 | Out-String
$code = $LASTEXITCODE
} finally {
$ErrorActionPreference = $previousErrorAction
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not trust $LASTEXITCODE when wsl.exe never runs.

$code is set only from $LASTEXITCODE. If & $wsl cannot start (wsl.exe absent from System32, or launch blocked), no native exit code is produced. $LASTEXITCODE then holds a stale value from an earlier native call, or $null on first use. A stale 0 makes the probe report success and makes Get-WslDistributionNames return the error text as distribution names. Default $code to a nonzero value and check $?.

🛡️ Proposed fix to fail closed on launch failures
   $previousErrorAction = $ErrorActionPreference
+  $raw = ""
+  $code = 1
   try {
     $ErrorActionPreference = "Continue"
     $raw = & $wsl `@ArgumentList` 2>&1 | Out-String
-    $code = $LASTEXITCODE
+    $launched = $?
+    $code = $LASTEXITCODE
+    if ($null -eq $code -or (-not $launched -and $code -eq 0)) { $code = 1 }
   } finally {
     $ErrorActionPreference = $previousErrorAction
   }
📝 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.

Suggested change
$previousErrorAction = $ErrorActionPreference
try {
$ErrorActionPreference = "Continue"
$raw = & $wsl @ArgumentList 2>&1 | Out-String
$code = $LASTEXITCODE
} finally {
$ErrorActionPreference = $previousErrorAction
}
$previousErrorAction = $ErrorActionPreference
$raw = ""
$code = 1
try {
$ErrorActionPreference = "Continue"
$raw = & $wsl `@ArgumentList` 2>&1 | Out-String
$launched = $?
$code = $LASTEXITCODE
if ($null -eq $code -or (-not $launched -and $code -eq 0)) { $code = 1 }
} finally {
$ErrorActionPreference = $previousErrorAction
}
🤖 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/install-wsl-runtime.ps1` around lines 45 - 52, Update the WSL
invocation block around `$raw` and `$code` to initialize `$code` to a nonzero
failure value before calling `& $wsl`, then use `$?` to confirm the command
launched successfully before accepting `$LASTEXITCODE`. Preserve the existing
exit-code handling for successfully launched `wsl.exe`, while ensuring missing
or blocked executables fail closed and cannot reuse a stale `$LASTEXITCODE`.

Fail-Setup "Microsoft WSL installer did not have a valid Microsoft Corporation signature."
}
Write-SetupStatus -Status "running" -Step "Installing Microsoft WSL $wslVersion..." -Progress 18
$installer = Start-Process -FilePath "$env:SystemRoot\System32\msiexec.exe" -ArgumentList @("/i", $msi, "/qn", "/norestart") -Wait -PassThru

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Windows PowerShell 5.1 Start-Process ArgumentList array quoting spaces in path

💡 Result:

In Windows PowerShell 5.1, the Start-Process cmdlet's -ArgumentList parameter accepts either a single string or an array of strings [1][2]. When you provide an array, the cmdlet joins the elements into a single string by inserting a space between each element [1][3]. Crucially, Start-Process does not automatically handle quoting for array elements that contain spaces [4][5][6]. If an argument contains spaces, the resulting joined string may cause the target process to interpret the arguments incorrectly [7][5]. To pass arguments containing spaces correctly in PowerShell 5.1, you must manually include escaped double quotes around the specific argument within your string or array element [1][2][8]. Example using an array: Start-Process -FilePath "C:\Path\To\Executable.exe" -ArgumentList "FirstArg", ""C:\Path With Spaces\File.txt"", "ThirdArg" Example using a single string: Start-Process -FilePath "C:\Path\To\Executable.exe" -ArgumentList "/arg1 "C:\Path With Spaces\File.txt" /arg3" Official documentation recommends that for the most reliable results, you should use a single string for -ArgumentList and explicitly manage all necessary quotes and escaping [1][2][8]. This avoids potential issues with the automatic space-joining behavior of the array-based approach [5][6]. When using nested quotes, you can use the backtick (`) to escape the double quotes for the target process [1][8].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- candidate script ---'
sed -n '1,230p' scripts/install-wsl-runtime.ps1
printf '%s\n' '--- PowerShell version references ---'
rg -n -i --glob '!node_modules' --glob '!dist' --glob '!build' 'PowerShell|pwsh|powershell.exe|Windows PowerShell|PSVersion' .
printf '%s\n' '--- installer-related references ---'
rg -n -C 3 'Start-Process|GetTempPath|wsl\.candidate\.msi|Test-PinnedWslRuntime|msiexec' scripts

Repository: gitcommit90/1Helm

Length of output: 19099


🌐 Web query:

Microsoft documentation Windows PowerShell 5.1 Start-Process -ArgumentList joins array elements with spaces does not add quotation marks

💡 Result:

In Windows PowerShell 5.1, the Start-Process cmdlet does not automatically add quotation marks to elements in an ArgumentList array [1][2]. Instead, it flattens the array by joining all elements into a single string, separated by a single space [1][3][2]. Because this process does not preserve the structure of the original array or apply automatic quoting, arguments containing spaces or special characters will be misinterpreted by the target executable unless you manually handle the quoting [1][3]. To ensure that arguments containing spaces are correctly passed to a child process, you must include escaped double quotes around those specific elements within your PowerShell code [3][2]. For example, if you need to pass a file path that contains spaces: # Incorrect: The executable will see 'C:\Program' and 'Files\app.txt' as two separate arguments Start-Process -FilePath "app.exe" -ArgumentList "C:\Program Files\app.txt" # Correct: Escaped quotes ensure the path is treated as a single argument Start-Process -FilePath "app.exe" -ArgumentList ""C:\Program Files\app.txt"" As noted in official documentation, for the most predictable results, you can use a single string for ArgumentList that includes all arguments and any necessary escaped quotes, rather than relying on an array [3][2]. Keep in mind that the backtick (`) is used in PowerShell to escape characters (like double quotes) for the command-line string construction [3][2].

Citations:


Quote the MSI path passed to msiexec.exe.

Windows PowerShell 5.1 joins -ArgumentList elements with spaces and does not add quotes. If the elevated account's temporary path contains spaces, msiexec.exe parses the MSI path as separate arguments and the fresh install fails. Use explicit quotes, as at line 196.

🤖 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/install-wsl-runtime.ps1` at line 147, Update the Start-Process
invocation assigning $installer to explicitly quote the $msi path in the
-ArgumentList passed to msiexec.exe, matching the quoting approach already used
near line 196 so paths containing spaces install correctly.

Comment on lines +171 to 173
} finally {
if (Test-Path -LiteralPath $hostTemporary) { Remove-Item -LiteralPath $hostTemporary -Recurse -Force }
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Make temporary cleanup best-effort so it cannot mask the real error.

The script-wide policy is Stop. If Remove-Item fails, for example because msiexec still holds the MSI, the cleanup error becomes the active exception, reaches the new catch, and Fail-Setup overwrites the status file with the cleanup message. The original elevated failure is then lost in the UI.

♻️ Proposed fix
     } finally {
-      if (Test-Path -LiteralPath $hostTemporary) { Remove-Item -LiteralPath $hostTemporary -Recurse -Force }
+      if (Test-Path -LiteralPath $hostTemporary) {
+        Remove-Item -LiteralPath $hostTemporary -Recurse -Force -ErrorAction SilentlyContinue
+      }
     }
📝 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.

Suggested change
} finally {
if (Test-Path -LiteralPath $hostTemporary) { Remove-Item -LiteralPath $hostTemporary -Recurse -Force }
}
} finally {
if (Test-Path -LiteralPath $hostTemporary) {
Remove-Item -LiteralPath $hostTemporary -Recurse -Force -ErrorAction SilentlyContinue
}
}
🤖 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/install-wsl-runtime.ps1` around lines 171 - 173, Update the finally
cleanup block around $hostTemporary so Remove-Item is best-effort and cannot
replace the original failure under the script-wide Stop policy. Suppress or
locally handle cleanup errors while retaining the existing Test-Path, recursive,
and forced removal behavior, allowing the original elevated setup error to reach
catch and Fail-Setup unchanged.

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.

1 participant