Skip to content

Commit 51bf37e

Browse files
aledbfclaude
andcommitted
test(parity): run the oracle with this process's node
The parity cases run through `/bin/sh -lc`, and a login shell rebuilds PATH from the system profile. On the docker8 fleet that puts the image's node 22 (/usr/local/bin) before setup-node's node 24, so the oracle loaded the reference's node-pty, built for node 24, failed, and printed node-pty's innerError on stderr: read-configuration.compose-path-terminal and read-configuration.missing-required differed on every run there. The oracle's command now names the node on the test process's PATH by its absolute path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent d91df19 commit 51bf37e

3 files changed

Lines changed: 46 additions & 3 deletions

File tree

‎internal/cli/parity_matrix_test.go‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ func TestParityMatrix(t *testing.T) {
222222
}
223223
})
224224

225-
cliTS := envOr("CLI_TS", "node "+filepath.Join(repoRoot, "reference", "devcontainer.js"))
225+
cliTS := envOr("CLI_TS", defaultParityTSCLI(repoRoot))
226226
cliGO := envOr("CLI_GO", filepath.Join(repoRoot, "devcontainer"))
227227
defaultTimeout := 60 * time.Second
228228
// Runtime lane default; overridable via PARITY_RUNTIME_TIMEOUT (e.g. "10m")
@@ -1066,7 +1066,7 @@ func parityEnv(caseID, side, repoRoot string, isolateCompose bool) map[string]st
10661066
// no container → "Dev container not found"). Mirror the cliGO/cliTS defaults
10671067
// (lines above) so setup and the measured command always agree.
10681068
"PARITY_CLI_GO": envOr("CLI_GO", filepath.Join(repoRoot, "devcontainer")),
1069-
"PARITY_CLI_TS": envOr("CLI_TS", "node "+filepath.Join(repoRoot, "reference", "devcontainer.js")),
1069+
"PARITY_CLI_TS": envOr("CLI_TS", defaultParityTSCLI(repoRoot)),
10701070
// Newer BuildKit attaches provenance/SBOM attestations by default, wrapping
10711071
// the feature-content image in an attestation manifest list. That breaks the
10721072
// TS CLI's `COPY --from=dev_containers_feature_content_source ...` feature
@@ -1147,6 +1147,20 @@ func findRepoRoot(t *testing.T) string {
11471147
}
11481148
}
11491149

1150+
// defaultParityTSCLI is the oracle's command line: the node on this process's
1151+
// PATH, by its absolute path, running reference/devcontainer.js. The cases run
1152+
// through `/bin/sh -lc`, and a login shell rebuilds PATH from the system
1153+
// profile: on a runner whose setup-node node is not the system one (the docker8
1154+
// fleet's image has node 22 in /usr/local/bin) a bare `node` would then load the
1155+
// reference's native node-pty, built for the setup-node version, and fail.
1156+
func defaultParityTSCLI(repoRoot string) string {
1157+
node, err := exec.LookPath("node")
1158+
if err != nil {
1159+
node = "node"
1160+
}
1161+
return node + " " + filepath.Join(repoRoot, "reference", "devcontainer.js")
1162+
}
1163+
11501164
func envOr(key, fallback string) string {
11511165
if v := os.Getenv(key); v != "" {
11521166
return v

‎internal/cli/parity_setup_binary_test.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ func TestParitySetupUsesLaneBinary(t *testing.T) {
3434
if got := env["PARITY_CLI_GO"]; got != filepath.Join("/repo", "devcontainer") {
3535
t.Errorf("PARITY_CLI_GO default = %q, want the repo-root binary", got)
3636
}
37-
if got, want := env["PARITY_CLI_TS"], "node "+filepath.Join("/repo", "reference", "devcontainer.js"); got != want {
37+
// The oracle's node is this process's, by absolute path (defaultParityTSCLI).
38+
if got, want := env["PARITY_CLI_TS"], defaultParityTSCLI("/repo"); got != want {
3839
t.Errorf("PARITY_CLI_TS default = %q, want %q", got, want)
3940
}
4041

‎internal/cli/parity_ts_cli_test.go‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package cli
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"strings"
7+
"testing"
8+
)
9+
10+
// The oracle's node is the one on this process's PATH, named by its absolute
11+
// path, so a login shell's PATH cannot swap it for another node.
12+
func TestDefaultParityTSCLIUsesThisProcessNode(t *testing.T) {
13+
dir := t.TempDir()
14+
node := filepath.Join(dir, "node")
15+
if err := os.WriteFile(node, []byte("#!/bin/sh\n"), 0o755); err != nil {
16+
t.Fatal(err)
17+
}
18+
t.Setenv("PATH", dir)
19+
got := defaultParityTSCLI("/repo")
20+
if want := node + " " + filepath.Join("/repo", "reference", "devcontainer.js"); got != want {
21+
t.Errorf("command = %q, want %q", got, want)
22+
}
23+
24+
t.Setenv("PATH", t.TempDir())
25+
if got := defaultParityTSCLI("/repo"); !strings.HasPrefix(got, "node ") {
26+
t.Errorf("without node on PATH the command = %q, want a bare node for the shell to find", got)
27+
}
28+
}

0 commit comments

Comments
 (0)