mirror of
https://github.com/block/buzz.git
synced 2026-10-27 12:40:30 +00:00
refactor(shell): drop bundled PortableGit, add BUZZ_SHELL override + dialect hint (#1536)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
105
.github/workflows/ci.yml
vendored
105
.github/workflows/ci.yml
vendored
@@ -837,89 +837,38 @@ jobs:
|
||||
- name: Test (buzz-dev-mcp)
|
||||
# The Windows-only bash resolver lives in buzz-dev-mcp; its unit tests
|
||||
# only gate if this crate is tested ON Windows.
|
||||
run: cargo test -p buzz-dev-mcp --target $env:TARGET
|
||||
# The bundled-bash staging (PortableGit download + SFX extract of the WHOLE
|
||||
# tree, including mingw64/) runs only in release.yml on tag — so without this
|
||||
# step the agent's only Windows transport would ship UNEXERCISED until a
|
||||
# tagged release hits users. Stage the tree and spawn the LAUNCHER bash
|
||||
# (bin/bash.exe, the entry the resolver now uses) to prove all of: the SFX
|
||||
# `-o` POSIX-path extraction works; the launcher spawns and sets up
|
||||
# MSYSTEM/PATH; the lazily-loaded MSYS DLL closure survives; and — the whole
|
||||
# point of bundling the full toolchain — git/jq/curl resolve from the bundled
|
||||
# mingw64/bin and git is functional (a real commit round-trips). The launcher
|
||||
# prepending mingw64/bin to PATH under `-c` is the load-bearing behavior that
|
||||
# only a real Windows host can confirm; this gate is where it gets proven.
|
||||
# (End-to-end nostr-SIGNED commits compose build_git_env's GIT_CONFIG_* with
|
||||
# the git-sign-nostr helper — covered by buzz-dev-mcp unit tests + a bare-host
|
||||
# check, not here, since this job stages only empty sidecar placeholders.)
|
||||
- name: Smoke-test bundled bash + git toolchain staging
|
||||
# Serial: windows_resolver_tests mutate process-global env
|
||||
# (BUZZ_SHELL/GIT_BASH/SystemRoot) that SharedState::new reads.
|
||||
run: cargo test -p buzz-dev-mcp --target $env:TARGET -- --test-threads=1
|
||||
# Smoke-test the new host-prereq contract: Git for Windows (which provides
|
||||
# bash) is available on the runner, a shell command round-trips, and bash
|
||||
# does NOT resolve from System32 (so WSL's launcher is never picked up).
|
||||
# windows-latest runners have Git for Windows pre-installed; the unit tests
|
||||
# above exercise the MCP resolver itself. This step verifies the host env.
|
||||
- name: Smoke-test host Git Bash prereq (host env check)
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
stage_dir="$RUNNER_TEMP/git-bash"
|
||||
scripts/stage-windows-bash.sh "$stage_dir"
|
||||
launcher="$stage_dir/bin/bash.exe"
|
||||
[[ -f "$launcher" ]] || { echo "launcher bash missing: $launcher" >&2; exit 1; }
|
||||
# Git for Windows ships bash.exe under its bin/ directory; confirm it
|
||||
# resolves from the standard location the runtime resolver probes first.
|
||||
bash_path=$(command -v bash 2>/dev/null || true)
|
||||
[[ -n "$bash_path" ]] || { echo "ERROR: bash not found on PATH — host Git for Windows missing" >&2; exit 1; }
|
||||
echo "Resolved bash: $bash_path"
|
||||
[[ "$bash_path" != *System32* ]] || { echo "ERROR: resolved bash is WSL's System32 launcher" >&2; exit 1; }
|
||||
|
||||
# Faithfulness to the agent: shell.rs spawns the launcher with PATH set
|
||||
# wholesale to the shim PATH (shim tempdir + the MCP process's inherited
|
||||
# PATH). We strip PATH down to just the Windows system dir before
|
||||
# spawning — stricter than a bare host (ambient PATH stripped to force
|
||||
# resolution through the launcher). This stops the runner's ambient
|
||||
# git/jq from masking the launcher's own mingw64/bin prepend, so anything
|
||||
# that resolves had to come from the launcher itself. The fidelity gap is
|
||||
# benign: the real shim tempdir only ever holds rg/tree/buzz and the two
|
||||
# nostr helpers, never git/jq/curl, so a richer real PATH cannot shadow
|
||||
# mingw64/bin for these three tools.
|
||||
win_root="${SYSTEMROOT:-${SystemRoot:-C:\\Windows}}"
|
||||
bare_path="$win_root\\System32;$win_root"
|
||||
# Run a basic pipeline through the resolved bash (same invocation the
|
||||
# agent uses: bash -c '...').
|
||||
out=$(bash -c 'echo hello | tr a-z A-Z')
|
||||
[[ "$out" == "HELLO" ]] || { echo "bash pipeline failed: got '$out'" >&2; exit 1; }
|
||||
|
||||
# Coreutils pipeline through the launcher (the resolver's entry point).
|
||||
out=$(PATH="$bare_path" "$launcher" -c 'echo hello | tr a-z A-Z')
|
||||
[[ "$out" == "HELLO" ]] || { echo "staged bash pipeline failed: got '$out'" >&2; exit 1; }
|
||||
|
||||
# The full-toolchain payoff: git/jq/curl must resolve from the bundle's
|
||||
# mingw64/bin or usr/bin. Use NON-login `-c` to match the agent's actual
|
||||
# invocation (shell.rs spawns `bash -c`): if the launcher only fixes PATH
|
||||
# under a login shell, `-lc` would pass here while the real agent stays
|
||||
# broken — the exact green-but-broken trap this gate guards.
|
||||
#
|
||||
# Anchor to the ACTUAL staged tree, not a mount-shape: command -v reports
|
||||
# the MSYS mount path (/mingw64/bin/git), so we cygpath -m it back to the
|
||||
# real Windows location and assert it sits under $stage_dir. A bare
|
||||
# `/mingw64/*` shape check would pass for any /mingw64-rooted mount; the
|
||||
# cygpath round-trip proves the tool is literally inside the bundle we
|
||||
# just staged. cygpath ships in the bundle's usr/bin (MSYS2 core, same
|
||||
# tier as the `tr` proven above), so it resolves under the launcher.
|
||||
#
|
||||
# curl is the one tool of the three with a System32 twin
|
||||
# (C:\Windows\System32\curl.exe, on $bare_path) — if a future PortableGit
|
||||
# ever drops curl from mingw64/bin, the launcher would resolve the
|
||||
# System32 twin and this REDs on a non-bug; git/jq have no such twin.
|
||||
stage_m=$("$launcher" -c "cygpath -m '$stage_dir'")
|
||||
for tool in git jq curl; do
|
||||
located=$(PATH="$bare_path" "$launcher" -c "command -v $tool >/dev/null 2>&1 && cygpath -m \"\$(command -v $tool)\"" || true)
|
||||
[[ -n "$located" ]] || { echo "$tool did not resolve in bundled bash" >&2; exit 1; }
|
||||
case "$located" in
|
||||
"$stage_m"/*) ;;
|
||||
*) echo "$tool resolved outside the staged bundle: $located (stage: $stage_m)" >&2; exit 1 ;;
|
||||
esac
|
||||
echo "$tool -> $located"
|
||||
done
|
||||
|
||||
# git is not just present but functional: a real commit round-trips,
|
||||
# again through non-login `-c` with the bare PATH. Single-quoted on
|
||||
# purpose — this script body runs in the launcher's shell, not ours.
|
||||
# shellcheck disable=SC2016
|
||||
PATH="$bare_path" "$launcher" -c '
|
||||
set -euo pipefail
|
||||
repo=$(mktemp -d)
|
||||
cd "$repo"
|
||||
git init -q
|
||||
git -c user.name=ci -c user.email=ci@example.com commit -q --allow-empty -m smoke
|
||||
git log -1 --format=%s | grep -qx smoke
|
||||
' || { echo "bundled git failed a commit round-trip" >&2; exit 1; }
|
||||
echo "staged launcher bash spawned; git/jq/curl resolve from the bundle; git commit works"
|
||||
# Confirm git itself works — agents run git commands frequently.
|
||||
git --version
|
||||
repo=$(mktemp -d)
|
||||
cd "$repo"
|
||||
git init -q
|
||||
git -c user.name=ci -c user.email=ci@example.com commit -q --allow-empty -m smoke
|
||||
git log -1 --format=%s | grep -qx smoke
|
||||
echo "Host bash resolved and functional; git commit round-trip passed"
|
||||
- name: Check (Tauri crate)
|
||||
run: cargo check --manifest-path desktop/src-tauri/Cargo.toml --target $env:TARGET
|
||||
env:
|
||||
|
||||
Reference in New Issue
Block a user