Skip to content

Fix Unix installer portability in sandboxed Linux - #93

Merged
calvin-archastro merged 1 commit into
mainfrom
fix/vercel-sandbox-installer
Jul 28, 2026
Merged

Fix Unix installer portability in sandboxed Linux#93
calvin-archastro merged 1 commit into
mainfrom
fix/vercel-sandbox-installer

Conversation

@calvin-archastro

Copy link
Copy Markdown
Contributor

What changed

  • Removed Bash process substitution from binary discovery so the Unix installer no longer requires /dev/fd.
  • Fixed musl detection by capturing ldd output before matching it, avoiding the pipefail and grep -q SIGPIPE interaction that selected the glibc asset on Alpine.
  • Added a digest-pinned Linux end-to-end test that serves a release fixture over HTTP, removes /dev/fd, runs the real installer, and executes the installed CLI.

Scope

CLI tooling only. This changes the Unix installer and its CI coverage; no backend, frontend, API, sample, or release artifact code changes.

Runtime flow

sequenceDiagram
    participant Caller as CLI installer caller
    participant Installer as Unix installer
    participant Runtime as Linux runtime
    participant Server as Release server
    Caller->>Installer: Start installation
    Installer->>Runtime: Inspect ldd output
    alt musl runtime
        Runtime-->>Installer: Report musl
        Installer->>Server: Download x64-musl archive and checksum
    else glibc runtime
        Runtime-->>Installer: Report glibc
        Installer->>Server: Download x64 archive and checksum
    end
    Installer->>Runtime: Extract archive
    Installer->>Runtime: Find binary without dev fd
    Installer->>Runtime: Install and execute binary
    Runtime-->>Caller: Return version output
Loading

Installer structure

classDiagram
    class Installer {
        +String platform
        +String archLabel
        +String binaryName
        +detectRuntime()
        +selectBinary()
        +install()
    }
    class LinuxRuntime {
        +String libc
        +Boolean hasDevFd
    }
    class ReleaseArchive {
        +String assetName
        +String checksum
    }
    class InstalledBinary {
        +String name
        +version()
    }
    Installer --> LinuxRuntime : inspects
    Installer --> ReleaseArchive : downloads
    ReleaseArchive *-- InstalledBinary : contains
    Installer --> InstalledBinary : installs
Loading

Risk assessment

Medium-low. This touches the direct installation path, so a regression could block new CLI installs. The implementation replaces one non-portable discovery loop with standard find and sed, preserves the unnamed-binary fallback, and is covered by the existing macOS/Linux matrix plus the new isolated Linux proof.

User impact

Users can install ArchAgent inside Vercel Sandbox and other Linux environments without /dev/fd. Alpine and other musl users now receive the correct linux-x64-musl artifact instead of the glibc artifact.

Testing

Canonical end-to-end proof

scripts/test-installer-without-dev-fd.sh is the canonical proof.

The script reads top-to-bottom as the user/system story:

  • generates a real archagent-linux-x64-musl.tar.gz fixture and checksum;
  • starts a separate Alpine Linux container and a real HTTP release server;
  • removes /dev/fd and asserts that boundary before invoking install.sh;
  • crosses HTTP, checksum, archive extraction, filesystem installation, and executable process boundaries;
  • asserts the installed binary reports version 0.3.1.

It failed before the fix with /dev/fd/63: No such file or directory after checksum verification, then passed after the fix while explicitly downloading the musl archive.

Focused verification

  • ./scripts/test-installer-without-dev-fd.sh — passed
  • ./scripts/test-installer-default-url.sh — passed
  • bash -n install.sh scripts/create-unix-fixtures.sh scripts/test-installer-without-dev-fd.sh — passed
  • shellcheck -e SC2016 install.sh scripts/create-unix-fixtures.sh scripts/test-installer-without-dev-fd.sh — passed
  • actionlint -shellcheck= .github/workflows/installer-smoke-test.yml — passed
  • git diff --check — passed
  • Independent adversarial review reran the E2E and found no remaining blockers.

The exact curl ... | bash wrapper is not part of the proof; the test executes the same installer file directly after crossing the release HTTP boundary. Existing Ubuntu, macOS, and Windows installer smoke jobs remain the broader CI gate.

Follow-ups and known issues

No deferred installer correctness work is known. The test pins the Alpine image digest; its package installation still depends on Alpine's package network, as the existing installer tests depend on their fixture tooling.

@calvin-archastro
calvin-archastro merged commit 78c9e4c into main Jul 28, 2026
8 checks passed
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