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
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.34] - 2026-08-01

### Fixed

- Fixed fresh Linux collaboration so the systemd service resolves the
architecture-specific Cloudflare connector already shipped inside the
verified host archive.
- Fixed fresh Windows setup so enabling WSL 2 features always stops at the
required reboot boundary, and mapped the Windows VM-compute-not-ready import
response to that same actionable restart state.
- Made Windows retries safely recover an app-owned partial shared-runtime
import left behind when Windows required the feature-activation reboot.

## [0.0.33] - 2026-08-01

### Fixed
Expand Down Expand Up @@ -955,7 +968,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
notarization, stapled tickets, Gatekeeper verification, persistent
Application Support, and isolated Apple container machines.

[Unreleased]: https://github.com/gitcommit90/1Helm/compare/v0.0.33...HEAD
[Unreleased]: https://github.com/gitcommit90/1Helm/compare/v0.0.34...HEAD
[0.0.34]: https://github.com/gitcommit90/1Helm/compare/v0.0.33...v0.0.34
[0.0.33]: https://github.com/gitcommit90/1Helm/compare/v0.0.32...v0.0.33
[0.0.32]: https://github.com/gitcommit90/1Helm/compare/v0.0.31...v0.0.32
[0.0.31]: https://github.com/gitcommit90/1Helm/compare/v0.0.30...v0.0.31
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ A fresh data directory opens first-run setup. The source runtime defaults to
| `PORT` | `8123` | HTTP/WebSocket control-plane port. |
| `CTRL_DATA_DIR` | `./data` | Databases, routing state, uploads, and non-OCI development/Apple workspace mirrors. |
| `HELM_CHANNEL_COMPUTER_BACKEND` | `apple` on macOS, `oci` on Linux and Windows | Host isolation backend; `native` and `mock` are explicit development/test overrides. |
| `HELM_CHANNEL_MACHINE_IMAGE` | `local/1helm-channel-machine:0.0.33` | Versioned channel-machine image contract. |
| `HELM_CHANNEL_MACHINE_IMAGE` | `local/1helm-channel-machine:0.0.34` | Versioned channel-machine image contract. |

### Agent-first JSON CLI

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "1helm",
"productName": "1Helm",
"version": "0.0.33",
"version": "0.0.34",
"private": true,
"type": "module",
"license": "AGPL-3.0-only",
Expand Down
54 changes: 46 additions & 8 deletions scripts/install-wsl-runtime.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ function Test-RestartRequired {
return $value -eq "Required" -or $value -eq "1" -or $value -eq "True"
}

function Test-WslRestartFailure {
param([string]$Text)
return $Text -match 'HCS_E_SERVICE_NOT_AVAILABLE|required feature is not installed'
}

function Require-WindowsRestart {
$message = "WSL 2 features are enabled. Restart Windows once, then retry 1Helm computer setup."
Write-SetupStatus -Status "restart_required" -Step $message -Progress 20 -ErrorMessage "Windows restart required to finish enabling WSL 2."
Write-Host $message
exit 10
}

function Get-WslDistributionNames {
$result = Get-WslText -ArgumentList @("--list", "--quiet")
if ($result.ExitCode -ne 0) { return @() }
Expand Down Expand Up @@ -123,11 +135,16 @@ if ($HostSetup) {
Write-SetupStatus -Status "running" -Step "Enabling Windows WSL features..." -Progress 8
$wslFeature = Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
$vmFeature = Get-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
if ($wslFeature.State -ne "Enabled") { Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -All -NoRestart | Out-Null }
if ($vmFeature.State -ne "Enabled") { Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All -NoRestart | Out-Null }
$enabledWslFeatureNow = $wslFeature.State -ne "Enabled"
$enabledVmFeatureNow = $vmFeature.State -ne "Enabled"
if ($enabledWslFeatureNow) { Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -All -NoRestart | Out-Null }
if ($enabledVmFeatureNow) { Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All -NoRestart | Out-Null }
$wslFeature = Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
$vmFeature = Get-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
$restartRequired = (Test-RestartRequired $wslFeature) -or (Test-RestartRequired $vmFeature)
# DISM's RestartRequired enum can stringify as "Possible" even though its
# numeric value is 1. Enabling either feature in this invocation is itself
# authoritative evidence that Windows must reboot before a WSL 2 VM import.
$restartRequired = $enabledWslFeatureNow -or $enabledVmFeatureNow -or (Test-RestartRequired $wslFeature) -or (Test-RestartRequired $vmFeature)
$hostTemporary = Join-Path ([System.IO.Path]::GetTempPath()) ("1helm-wsl-host-" + [Guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $hostTemporary | Out-Null
try {
Expand Down Expand Up @@ -160,14 +177,20 @@ if ($HostSetup) {
} else {
Write-SetupStatus -Status "running" -Step "Microsoft WSL $wslVersion is already installed." -Progress 18
}
# A feature may already report Enabled before the reboot has registered
# WSL's VM compute service. This is the concrete pre-reboot state that
# otherwise lets setup continue into HCS_E_SERVICE_NOT_AVAILABLE.
if ($null -eq (Get-Service -Name vmcompute -ErrorAction SilentlyContinue)) { $restartRequired = $true }
if ($restartRequired) {
Write-SetupStatus -Status "restart_required" -Step "WSL 2 features are enabled. Restart Windows once, then retry 1Helm computer setup." -Progress 20
exit 10
Require-WindowsRestart
}
if (-not (Test-PinnedWslRuntime)) { Fail-Setup "Microsoft WSL $wslVersion was installed but could not be verified." }
Write-SetupStatus -Status "running" -Step "Setting WSL 2 as the default..." -Progress 22
$defaultVersion = Get-WslText -ArgumentList @("--set-default-version", "2")
if ($defaultVersion.ExitCode -ne 0) { Fail-Setup "WSL could not set version 2 as the default. $($defaultVersion.Text)" }
if ($defaultVersion.ExitCode -ne 0) {
if (Test-WslRestartFailure $defaultVersion.Text) { Require-WindowsRestart }
Fail-Setup "WSL could not set version 2 as the default. $($defaultVersion.Text)"
}
} finally {
if (Test-Path -LiteralPath $hostTemporary) { Remove-Item -LiteralPath $hostTemporary -Recurse -Force }
}
Expand Down Expand Up @@ -242,11 +265,22 @@ try {
$names = @(Get-WslDistributionNames)
$runtimeRoot = Join-Path $env:LOCALAPPDATA "1Helm-Runtime"
$installDirectory = Join-Path $runtimeRoot $RuntimeName
$partialMarker = "$installDirectory.1helm-partial-import"
if ($names -notcontains $RuntimeName) {
if (Test-Path -LiteralPath $installDirectory) {
Fail-Setup "The shared runtime disk directory already exists without a registered runtime. Remove `"$installDirectory`" or unregister the partial distro, then retry."
$entries = @(Get-ChildItem -LiteralPath $installDirectory -Force -ErrorAction SilentlyContinue)
$ownedPartial = (Test-Path -LiteralPath $partialMarker -PathType Leaf) -and ((Get-Content -LiteralPath $partialMarker -Raw).Trim() -eq $RuntimeName)
# v0.0.33 could leave an empty app-owned directory when Windows rejected
# the import before creating its VM. New attempts carry an ownership
# marker so an interrupted partial VHD can also be retried safely.
if ($entries.Count -eq 0 -or $ownedPartial) {
Remove-Item -LiteralPath $installDirectory -Recurse -Force
} else {
Fail-Setup "The shared runtime disk directory already exists without a registered runtime. Remove `"$installDirectory`" or unregister the partial distro, then retry."
}
}
New-Item -ItemType Directory -Path $installDirectory -Force | Out-Null
[System.IO.File]::WriteAllText($partialMarker, $RuntimeName, [System.Text.UTF8Encoding]::new($false))
$rootfs = Join-Path $temporary "ubuntu-noble-wsl.rootfs.tar.gz"
Write-SetupStatus -Status "running" -Step "Downloading shared Linux runtime base..." -Progress 35
Fetch-File -Url $rootfsUrl -Destination $rootfs
Expand All @@ -255,7 +289,11 @@ try {
}
Write-SetupStatus -Status "running" -Step "Importing shared Linux runtime..." -Progress 48
$imported = Get-WslText -ArgumentList @("--import", $RuntimeName, $installDirectory, $rootfs, "--version", "2")
if ($imported.ExitCode -ne 0) { Fail-Setup "The shared 1Helm WSL runtime could not be imported. $($imported.Text)" }
if ($imported.ExitCode -ne 0) {
if (Test-WslRestartFailure $imported.Text) { Require-WindowsRestart }
Fail-Setup "The shared 1Helm WSL runtime could not be imported. $($imported.Text)"
}
Remove-Item -LiteralPath $partialMarker -Force
}

Write-SetupStatus -Status "running" -Step "Installing shared runtime packages (podman, crun, ...)..." -Progress 58
Expand Down
1 change: 1 addition & 0 deletions site/public/install-linux-units.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Environment=NODE_ENV=production
Environment=PORT=8123
Environment=HELM_HOST=0.0.0.0
Environment=CTRL_DATA_DIR=$STATE_ROOT
Environment=HELM_APP_ROOT=$INSTALL_ROOT/current
Environment=HELM_CHANNEL_COMPUTER_BACKEND=oci
Environment=HELM_OCI_HELPER=/usr/libexec/1helm-oci-runtime
Environment=HELM_INSTALL_KIND=linux-systemd
Expand Down
2 changes: 1 addition & 1 deletion src/server/channel-computers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const APPLE_RUNTIME_VERSION = "1.1.0";
export const APPLE_RUNTIME_PACKAGE = `container-${APPLE_RUNTIME_VERSION}-installer-signed.pkg`;
export const APPLE_RUNTIME_URL = `https://github.com/apple/container/releases/download/${APPLE_RUNTIME_VERSION}/${APPLE_RUNTIME_PACKAGE}`;
export const APPLE_RUNTIME_SHA256 = "0ca1c42a2269c2557efb1d82b1b38ac553e6a3a3da1b1179c439bcee1e7d6714";
export const DEFAULT_CHANNEL_IMAGE = process.env.HELM_CHANNEL_MACHINE_IMAGE || "local/1helm-channel-machine:0.0.33";
export const DEFAULT_CHANNEL_IMAGE = process.env.HELM_CHANNEL_MACHINE_IMAGE || "local/1helm-channel-machine:0.0.34";
const CONTAINER_CANDIDATES = [process.env.HELM_CONTAINER_CLI, "/usr/local/bin/container", "/opt/homebrew/bin/container", "container"].filter(Boolean) as string[];
const OCI_RUNTIME_VERSION = "1helm-oci-runtime-v1";
const OCI_HELPER_CANDIDATES = [
Expand Down
13 changes: 9 additions & 4 deletions src/server/connectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ let shuttingDown = false;

function connectorBinary(): string {
const resources = process.env.HELM_RESOURCES_PATH || "";
const appRoot = process.env.HELM_APP_ROOT || "";
// Linux systemd releases run with /opt/1helm/current as their working
// directory. Keep that installed-root contract usable even if an older unit
// omitted HELM_APP_ROOT, while preferring the explicit packaged root.
const appRoots = [...new Set([process.env.HELM_APP_ROOT || "", process.cwd()].filter(Boolean))];
Comment on lines +19 to +22

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

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- src/server/connectors.ts outline ---'
ast-grep outline src/server/connectors.ts --view expanded
printf '%s\n' '--- relevant source ---'
sed -n '1,180p' src/server/connectors.ts
printf '%s\n' '--- connectorBinary references ---'
rg -n -C 3 'connectorBinary|process\.cwd\(|HELM_APP_ROOT' src

Repository: gitcommit90/1Helm

Length of output: 17107


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- process.cwd behavior after directory removal ---'
node - <<'JS'
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");

const parent = fs.mkdtempSync(path.join(os.tmpdir(), "cwd-check-"));
const removed = path.join(parent, "removed");
fs.mkdirSync(removed);
process.chdir(removed);
fs.rmSync(removed, { recursive: true });

try {
  process.cwd();
  console.log("process.cwd: returned");
} catch (error) {
  console.log(`process.cwd: threw ${error.code}: ${error.message}`);
}

process.chdir(parent);
fs.rmSync(parent, { recursive: true });
JS
printf '%s\n' '--- connector availability and launch call paths ---'
rg -n -C 5 'connectorAvailable\(|startTunnelConnector\(|startConfiguredConnectors\(' src

Repository: gitcommit90/1Helm

Length of output: 9771


Guard process.cwd() before building candidates.

If the current directory was removed, process.cwd() throws ENOENT. This prevents connectorAvailable() and connector launches from checking configured or system paths. Read it in a try/catch and omit it when unavailable.

🧰 Tools
🪛 ast-grep (0.45.0)

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn, type ChildProcess } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🤖 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 `@src/server/connectors.ts` around lines 19 - 22, Update the appRoots
initialization near connectorAvailable to read process.cwd() inside a try/catch,
omitting it when the working directory is unavailable or throws ENOENT. Preserve
HELM_APP_ROOT and the existing deduplication/filtering behavior so configured
and system paths remain usable.

const pathSep = process.platform === "win32" ? ";" : ":";
const pathNames = process.platform === "win32" ? ["cloudflared.exe", "cloudflared"] : ["cloudflared"];
const linuxConnector = process.platform === "linux" && (process.arch === "x64" || process.arch === "arm64")
Expand All @@ -28,9 +31,11 @@ function connectorBinary(): string {
// Packaged desktop apps (macOS Resources/cloudflared, Windows resources/cloudflared.exe).
resources ? join(resources, "cloudflared.exe") : "",
resources ? join(resources, "cloudflared") : "",
appRoot ? join(appRoot, "cloudflared.exe") : "",
appRoot ? join(appRoot, "cloudflared") : "",
appRoot && linuxConnector ? join(appRoot, "resources", linuxConnector) : "",
...appRoots.flatMap((appRoot) => [
join(appRoot, "cloudflared.exe"),
join(appRoot, "cloudflared"),
linuxConnector ? join(appRoot, "resources", linuxConnector) : "",
]),
"/opt/homebrew/bin/cloudflared",
"/usr/local/bin/cloudflared",
"/usr/bin/cloudflared",
Expand Down
2 changes: 1 addition & 1 deletion src/server/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,7 @@ export function migrate(): void {
const platformBackend = process.platform === "darwin" ? "apple" : "oci";
const configuredBackend = String(process.env.HELM_CHANNEL_COMPUTER_BACKEND || platformBackend);
const backend = ["apple", "oci", "native", "mock"].includes(configuredBackend) ? configuredBackend : platformBackend;
const image = String(process.env.HELM_CHANNEL_MACHINE_IMAGE || "local/1helm-channel-machine:0.0.33");
const image = String(process.env.HELM_CHANNEL_MACHINE_IMAGE || "local/1helm-channel-machine:0.0.34");
for (const channel of q(`SELECT c.id FROM channels c JOIN agent_channels ac ON ac.channel_id=c.id
WHERE c.kind='channel' AND c.status<>'deleted'`)) {
const channelId = Number(channel.id);
Expand Down
2 changes: 1 addition & 1 deletion test/channel-computers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ test("Apple channel-computer contract preserves isolation, files, wakes, archive
test("runtime digest and packaged image recipe stay pinned", async () => {
assert.equal(computers.APPLE_RUNTIME_SHA256, "0ca1c42a2269c2557efb1d82b1b38ac553e6a3a3da1b1179c439bcee1e7d6714");
assert.match(computers.APPLE_RUNTIME_URL, /\/1\.1\.0\/container-1\.1\.0-installer-signed\.pkg$/);
assert.equal(computers.DEFAULT_CHANNEL_IMAGE, "local/1helm-channel-machine:0.0.33");
assert.equal(computers.DEFAULT_CHANNEL_IMAGE, "local/1helm-channel-machine:0.0.34");
const packaging = await readFile(join(root, "scripts", "package-mac-dmg.cjs"), "utf8");
assert.match(packaging, /container\(\?:\$\|\\\/\)/, "release packaging includes container/ image assets");
const image = await readFile(join(root, "container", "Containerfile"), "utf8");
Expand Down
29 changes: 28 additions & 1 deletion test/connectors.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from "node:assert/strict";
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { readFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
Expand All @@ -17,6 +17,33 @@ test("Linux release packaging ships pinned connectors for every supported host a
assert.match(packageLinux, /cloudflared-linux-\$\{connector\.arch\}/, "the verified binaries enter the Linux release archive");
assert.match(packageLinux, /chmodSync\(destination, 0o755\)/, "packaged Linux connectors retain executable mode");
assert.match(resolver, /cloudflared-linux-\$\{process\.arch\}/, "Linux resolves only the binary matching the running host architecture");
assert.match(resolver, /process\.env\.HELM_APP_ROOT[\s\S]*process\.cwd\(\)/, "an installed Linux service can resolve its bundled connector from its release working directory");
});

test("Linux service working directory resolves the bundled connector without a legacy app-root environment", async (t) => {
const root = await mkdtemp(join(tmpdir(), "1helm-linux-connector-root-"));
const resources = join(root, "resources");
const binary = join(resources, `cloudflared-linux-${process.arch}`);
const originalCwd = process.cwd();
const originalAppRoot = process.env.HELM_APP_ROOT;
const originalResources = process.env.HELM_RESOURCES_PATH;
const originalBinary = process.env.CLOUDFLARED_BIN;
await mkdir(resources);
await writeFile(binary, "#!/bin/sh\nexit 0\n");
await chmod(binary, 0o755);
process.chdir(root);
delete process.env.HELM_APP_ROOT;
delete process.env.HELM_RESOURCES_PATH;
delete process.env.CLOUDFLARED_BIN;
t.after(async () => {
process.chdir(originalCwd);
if (originalAppRoot === undefined) delete process.env.HELM_APP_ROOT; else process.env.HELM_APP_ROOT = originalAppRoot;
if (originalResources === undefined) delete process.env.HELM_RESOURCES_PATH; else process.env.HELM_RESOURCES_PATH = originalResources;
if (originalBinary === undefined) delete process.env.CLOUDFLARED_BIN; else process.env.CLOUDFLARED_BIN = originalBinary;
await rm(root, { recursive: true, force: true });
});
const connectors = await import(`../src/server/connectors.ts?linux-root-test=${Date.now()}`);
assert.equal(connectors.connectorAvailable(), true);
Comment on lines +23 to +46

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- candidate files ---'
git ls-files | rg '(^|/)(connectors\.mjs|connectors\.ts|package\.json|vitest|jest|node:test|test)' | head -200
printf '%s\n' '--- test file outline ---'
ast-grep outline test/connectors.mjs --lang javascript 2>/dev/null || true
printf '%s\n' '--- relevant test section ---'
cat -n test/connectors.mjs | sed -n '1,90p'
printf '%s\n' '--- connector resolver symbols ---'
rg -n -C 8 'connectorBinary|linuxConnector|connectorAvailable|HELM_APP_ROOT|HELM_RESOURCES_PATH|CLOUDFLARED_BIN|process\.cwd|PATH' src test package.json

Repository: gitcommit90/1Helm

Length of output: 50373


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- connector resolver ---'
cat -n src/server/connectors.ts | sed -n '1,75p'
printf '%s\n' '--- package test commands ---'
cat -n package.json | sed -n '1,140p'
printf '%s\n' '--- connector test references and platform guards ---'
rg -n -C 3 'test\(|process\.platform|t\.skip|PATH|HELM_RESOURCES_PATH|CLOUDFLARED_BIN' test/connectors.mjs

Repository: gitcommit90/1Helm

Length of output: 13666


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- test suite runner ---'
cat -n scripts/run-test-suite.mjs | sed -n '1,180p'
printf '%s\n' '--- resolver behavior probe ---'
python3 - <<'PY'
from pathlib import Path
text = Path("src/server/connectors.ts").read_text()
start = text.index("function connectorBinary()")
end = text.index("\n\nconst safeId", start)
print(text[start:end])
PY
node - <<'JS'
const path = require('node:path');
function candidates({platform, arch, env, cwd}) {
  const join = path.posix.join;
  const resources = env.HELM_RESOURCES_PATH || "";
  const appRoots = [...new Set([env.HELM_APP_ROOT || "", cwd].filter(Boolean))];
  const pathSep = platform === "win32" ? ";" : ":";
  const pathNames = platform === "win32" ? ["cloudflared.exe", "cloudflared"] : ["cloudflared"];
  const linuxConnector = platform === "linux" && (arch === "x64" || arch === "arm64")
    ? `cloudflared-linux-${arch}` : "";
  const pathCandidates = String(env.PATH || "").split(pathSep).filter(Boolean)
    .flatMap(directory => pathNames.map(name => join(directory, name)));
  return [
    env.CLOUDFLARED_BIN || "",
    resources ? join(resources, "cloudflared.exe") : "",
    resources ? join(resources, "cloudflared") : "",
    ...appRoots.flatMap(appRoot => [
      join(appRoot, "cloudflared.exe"),
      join(appRoot, "cloudflared"),
      linuxConnector ? join(appRoot, "resources", linuxConnector) : "",
    ]),
    "/opt/homebrew/bin/cloudflared", "/usr/local/bin/cloudflared",
    "/usr/bin/cloudflared", ...pathCandidates,
  ].filter(Boolean);
}
for (const [platform, arch] of [["linux","x64"],["linux","arm64"],["linux","ia32"],["darwin","arm64"],["win32","x64"]]) {
  const list = candidates({platform, arch, env:{}, cwd:"/tmp/root"});
  console.log(platform, arch, list.includes(`/tmp/root/resources/cloudflared-linux-${arch}`), list);
}
JS

Repository: gitcommit90/1Helm

Length of output: 6660


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- workflow platforms and connector test invocation ---'
rg -n -C 3 'npm test|test:|runs-on:|node --test|connectors\.mjs' .github site scripts 2>/dev/null | head -240 || true
printf '%s\n' '--- node test skip API availability ---'
node - <<'JS'
import test from "node:test";
test("skip-api-probe", (t) => {
  console.log({hasSkip: typeof t.skip === "function"});
  t.skip("probe");
});
JS

Repository: gitcommit90/1Helm

Length of output: 2766


Skip this Linux-only fixture on unsupported runners.

connectorBinary() adds the Linux fixture only on Linux x64 and arm64. On other runners, the assertion can fail or pass because of an unrelated system binary. Add the guard before mkdtemp and process-wide state changes.

Proposed fix
 test("Linux service working directory resolves the bundled connector without a legacy app-root environment", async (t) => {
+  if (process.platform !== "linux" || (process.arch !== "x64" && process.arch !== "arm64")) {
+    t.skip("Linux connector fixture requires a supported Linux architecture");
+    return;
+  }
   const root = await mkdtemp(join(tmpdir(), "1helm-linux-connector-root-"));
📝 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
test("Linux service working directory resolves the bundled connector without a legacy app-root environment", async (t) => {
const root = await mkdtemp(join(tmpdir(), "1helm-linux-connector-root-"));
const resources = join(root, "resources");
const binary = join(resources, `cloudflared-linux-${process.arch}`);
const originalCwd = process.cwd();
const originalAppRoot = process.env.HELM_APP_ROOT;
const originalResources = process.env.HELM_RESOURCES_PATH;
const originalBinary = process.env.CLOUDFLARED_BIN;
await mkdir(resources);
await writeFile(binary, "#!/bin/sh\nexit 0\n");
await chmod(binary, 0o755);
process.chdir(root);
delete process.env.HELM_APP_ROOT;
delete process.env.HELM_RESOURCES_PATH;
delete process.env.CLOUDFLARED_BIN;
t.after(async () => {
process.chdir(originalCwd);
if (originalAppRoot === undefined) delete process.env.HELM_APP_ROOT; else process.env.HELM_APP_ROOT = originalAppRoot;
if (originalResources === undefined) delete process.env.HELM_RESOURCES_PATH; else process.env.HELM_RESOURCES_PATH = originalResources;
if (originalBinary === undefined) delete process.env.CLOUDFLARED_BIN; else process.env.CLOUDFLARED_BIN = originalBinary;
await rm(root, { recursive: true, force: true });
});
const connectors = await import(`../src/server/connectors.ts?linux-root-test=${Date.now()}`);
assert.equal(connectors.connectorAvailable(), true);
test("Linux service working directory resolves the bundled connector without a legacy app-root environment", async (t) => {
if (process.platform !== "linux" || (process.arch !== "x64" && process.arch !== "arm64")) {
t.skip("Linux connector fixture requires a supported Linux architecture");
return;
}
const root = await mkdtemp(join(tmpdir(), "1helm-linux-connector-root-"));
const resources = join(root, "resources");
const binary = join(resources, `cloudflared-linux-${process.arch}`);
const originalCwd = process.cwd();
const originalAppRoot = process.env.HELM_APP_ROOT;
const originalResources = process.env.HELM_RESOURCES_PATH;
const originalBinary = process.env.CLOUDFLARED_BIN;
await mkdir(resources);
await writeFile(binary, "#!/bin/sh\nexit 0\n");
await chmod(binary, 0o755);
process.chdir(root);
delete process.env.HELM_APP_ROOT;
delete process.env.HELM_RESOURCES_PATH;
delete process.env.CLOUDFLARED_BIN;
t.after(async () => {
process.chdir(originalCwd);
if (originalAppRoot === undefined) delete process.env.HELM_APP_ROOT; else process.env.HELM_APP_ROOT = originalAppRoot;
if (originalResources === undefined) delete process.env.HELM_RESOURCES_PATH; else process.env.HELM_RESOURCES_PATH = originalResources;
if (originalBinary === undefined) delete process.env.CLOUDFLARED_BIN; else process.env.CLOUDFLARED_BIN = originalBinary;
await rm(root, { recursive: true, force: true });
});
const connectors = await import(`../src/server/connectors.ts?linux-root-test=${Date.now()}`);
assert.equal(connectors.connectorAvailable(), true);
🤖 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 23 - 46, Add an early platform/architecture
guard to this test so it runs only on Linux with process.arch equal to x64 or
arm64. Place the guard before mkdtemp, environment mutations, process.chdir, and
other process-wide setup; leave the existing fixture and assertion unchanged for
supported runners.

});

test("stopping a connector cancels automatic relaunch while preserving its credentials", async (t) => {
Expand Down
4 changes: 4 additions & 0 deletions test/desktop.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ test("desktop entrypoint keeps the renderer sandboxed and data on the Mac", asyn
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, /StatusPath/, "elevated HostSetup receives the shared status path so real errors reach the app");
assert.match(windowsRuntime, /1603[\s\S]*Test-PinnedWslRuntime|Test-PinnedWslRuntime[\s\S]*1603/, "MSI 1603 falls back to re-verifying an already-present pinned WSL runtime");
assert.match(windowsRuntime, /\$enabledWslFeatureNow[\s\S]*\$enabledVmFeatureNow[\s\S]*\$restartRequired/, "features enabled in the current pass force a reboot before WSL import regardless of DISM enum formatting");
assert.match(windowsRuntime, /Get-Service -Name vmcompute[\s\S]*\$restartRequired = \$true/, "an enabled-but-not-registered WSL VM compute service stops setup at the reboot boundary");
assert.match(windowsRuntime, /HCS_E_SERVICE_NOT_AVAILABLE[\s\S]*Require-WindowsRestart|Test-WslRestartFailure[\s\S]*Require-WindowsRestart/, "an unavailable VM compute service is reported as restart-required instead of a broken runtime");

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

Target the restart-routing call sites.

The expression can match Test-WslRestartFailure and the following Require-WindowsRestart function declaration. It does not verify that either failure branch routes to the restart handler. Assert the default-version and import branches separately.

Proposed test update
-  assert.match(windowsRuntime, /HCS_E_SERVICE_NOT_AVAILABLE[\s\S]*Require-WindowsRestart|Test-WslRestartFailure[\s\S]*Require-WindowsRestart/, "an unavailable VM compute service is reported as restart-required instead of a broken runtime");
+  assert.match(windowsRuntime, /if \(Test-WslRestartFailure \$defaultVersion\.Text\) \{ Require-WindowsRestart \}/, "a default-version HCS failure requires a Windows restart");
+  assert.match(windowsRuntime, /if \(Test-WslRestartFailure \$imported\.Text\) \{ Require-WindowsRestart \}/, "an import HCS failure requires a Windows restart");
📝 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
assert.match(windowsRuntime, /HCS_E_SERVICE_NOT_AVAILABLE[\s\S]*Require-WindowsRestart|Test-WslRestartFailure[\s\S]*Require-WindowsRestart/, "an unavailable VM compute service is reported as restart-required instead of a broken runtime");
assert.match(windowsRuntime, /if \(Test-WslRestartFailure \$defaultVersion\.Text\) \{ Require-WindowsRestart \}/, "a default-version HCS failure requires a Windows restart");
assert.match(windowsRuntime, /if \(Test-WslRestartFailure \$imported\.Text\) \{ Require-WindowsRestart \}/, "an import HCS failure requires a Windows restart");
🤖 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 199, Update the runtime assertion in the desktop
test to validate the restart-routing call sites directly: add separate
assertions for the default-version failure branch and the import failure branch,
ensuring each routes to Require-WindowsRestart rather than merely matching its
later declaration. Replace the broad combined regular expression while
preserving the existing restart-required behavior being tested.

assert.match(windowsRuntime, /\.1helm-partial-import[\s\S]*\$ownedPartial[\s\S]*Remove-Item -LiteralPath \$installDirectory/, "an app-owned partial WSL import can recover safely after reboot");
assert.match(windowsRuntime, /\[automount\][\s\S]*enabled=false[\s\S]*\[interop\][\s\S]*enabled=false/, "the shared runtime exposes neither Windows drives nor process interop");
assert.doesNotMatch(windowsRuntime, /--update/);
assert.match(channelComputers, /HELM_WSL_SETUP_STATUS/, "Windows runtime install is tracked through a status file instead of fire-and-forget Start-Process");
Expand Down
1 change: 1 addition & 0 deletions test/site.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ test("installer assets are explicit and syntax-valid", () => {
const linuxUnits = readFileSync(`${root}/site/public/install-linux-units.sh`, "utf8");
const releaseApply = readFileSync(`${root}/site/public/apply-linux-release.sh`, "utf8");
assert.match(updater, /browser_download_url/);
assert.match(linuxUnits, /Environment=HELM_APP_ROOT=\$INSTALL_ROOT\/current/, "Linux explicitly exposes the active packaged root to runtime resource resolvers");
assert.match(updater, /\^sha256:\[a-f0-9\]\{64\}\$/, "the Linux updater requires GitHub's exact SHA-256 asset digest");
assert.match(updater, /sha256sum -c -/);
assert.match(updater, /CONNECTOR_ARCH[\s\S]*resources\/cloudflared-linux-\$CONNECTOR_ARCH/, "Linux updates reject archives without the connector for the current architecture");
Expand Down
Loading