mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 20:25:56 +00:00
Keep macOS native utilities unchanged around timeout bootstrap
Expose only the installed GNU gtimeout as timeout through a new runner-owned directory. Keep native BSD utilities on their original PATH so installing the missing dependency cannot silently change the other platform checks. The connected workflow test verifies the symlink identity and that the directory contains no other utilities. Contract-Neutral: Narrow the native CI dependency PATH and its proof; no shipped installer or runtime contract changes. Change-source: pulse-maintainer
This commit is contained in:
@@ -90,10 +90,12 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
brew install coreutils
|
||||
coreutils_bin="$(brew --prefix coreutils)/libexec/gnubin"
|
||||
test -x "$coreutils_bin/timeout"
|
||||
"$coreutils_bin/timeout" --version | grep -q 'GNU coreutils'
|
||||
printf '%s\n' "$coreutils_bin" >> "$GITHUB_PATH"
|
||||
gnu_timeout="$(brew --prefix coreutils)/bin/gtimeout"
|
||||
test -x "$gnu_timeout"
|
||||
"$gnu_timeout" --version | grep -q 'GNU coreutils'
|
||||
timeout_bin="$(mktemp -d "$RUNNER_TEMP/pulse-guidance-tools.XXXXXX")"
|
||||
ln -s "$gnu_timeout" "$timeout_bin/timeout"
|
||||
printf '%s\n' "$timeout_bin" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Verify native Unix timeout prerequisite
|
||||
if: matrix.unix
|
||||
|
||||
@@ -65,8 +65,8 @@ func TestNativeGuidanceToolsSupplyAndVerifyRealGNUTimeout(t *testing.T) {
|
||||
t.Run(scenario, func(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
bin, prefix := filepath.Join(root, "bin"), filepath.Join(root, "coreutils with spaces")
|
||||
gnuBin := filepath.Join(prefix, "libexec", "gnubin")
|
||||
for _, dir := range []string{bin, gnuBin} {
|
||||
coreutilsBin, runnerTemp := filepath.Join(prefix, "bin"), filepath.Join(root, "runner temp")
|
||||
for _, dir := range []string{bin, coreutilsBin, runnerTemp} {
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -84,7 +84,7 @@ esac
|
||||
if err := os.WriteFile(filepath.Join(bin, "brew"), []byte(brew), 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tool := filepath.Join(gnuBin, "timeout")
|
||||
tool := filepath.Join(coreutilsBin, "gtimeout")
|
||||
switch scenario {
|
||||
case "real GNU tool", "install failure":
|
||||
if err := os.Symlink(realTimeout, tool); err != nil {
|
||||
@@ -101,7 +101,7 @@ esac
|
||||
installExit = "23"
|
||||
}
|
||||
env := append(os.Environ(), "PATH="+bin+":"+os.Getenv("PATH"), "GITHUB_PATH="+pathFile,
|
||||
"COREUTILS_PREFIX="+prefix, "BREW_CALLS="+callsFile, "BREW_EXIT="+installExit)
|
||||
"COREUTILS_PREFIX="+prefix, "BREW_CALLS="+callsFile, "BREW_EXIT="+installExit, "RUNNER_TEMP="+runnerTemp)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(ctx, "bash", "-c", bootstrap.Run)
|
||||
@@ -128,15 +128,26 @@ esac
|
||||
t.Fatalf("GNU prerequisite failed: %v: %s", runErr, output)
|
||||
}
|
||||
path, err := os.ReadFile(pathFile)
|
||||
if err != nil || string(path) != gnuBin+"\n" {
|
||||
t.Fatal("bootstrap did not export the exact installed gnubin path")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
timeoutBin := strings.TrimSuffix(string(path), "\n")
|
||||
if filepath.Dir(timeoutBin) != runnerTemp || !strings.HasPrefix(filepath.Base(timeoutBin), "pulse-guidance-tools.") {
|
||||
t.Fatal("bootstrap did not export its newly owned timeout directory")
|
||||
}
|
||||
entries, err := os.ReadDir(timeoutBin)
|
||||
if err != nil || len(entries) != 1 || entries[0].Name() != "timeout" {
|
||||
t.Fatal("bootstrap must not replace native macOS utilities other than timeout")
|
||||
}
|
||||
if target, err := os.Readlink(filepath.Join(timeoutBin, "timeout")); err != nil || target != tool {
|
||||
t.Fatal("timeout must resolve to the exact installed GNU executable")
|
||||
}
|
||||
calls, err := os.ReadFile(callsFile)
|
||||
if err != nil || string(calls) != "install coreutils\n--prefix coreutils\n" {
|
||||
t.Fatal("bootstrap changed its fixed Homebrew dependency")
|
||||
}
|
||||
cmd = exec.CommandContext(ctx, "bash", "-c", verify.Run)
|
||||
cmd.Env = append(env, "PATH="+strings.TrimSpace(string(path))+":"+os.Getenv("PATH"))
|
||||
cmd.Env = append(env, "PATH="+timeoutBin+":"+os.Getenv("PATH"))
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("next workflow step cannot use supplied GNU timeout: %v: %s", err, output)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user