Track main at 3f238ff (per-role reasoning_effort, #12), 21 commits past d6627d7 ("1.0.0 (#6)"). cargoHash is unchanged: Cargo.lock is identical across that range, so the vendored tree is byte-for-byte the same. The new tests/test_session_boot.rs spawns the real binary with env_clear(), which drops SSL_CERT_FILE. rustls-native-certs is then left with a fixed list of /etc paths to probe, none of which exist in the Nix sandbox, so the child dies in reqwest::Client::new() and four exit-code assertions observe the panic's 101. The patch forwards the runner's SSL_CERT_FILE to the child and leaves every assertion intact. The underlying defect is upstream's rather than Nix's: src/llm/client.rs builds its client with unwrap_or_default() on a Result<Client, reqwest::Error>, and reqwest's Client::default() is Client::new(), which repeats the same build and .expect()s it. The fallback can therefore never recover; it turns a reportable "no CA certificates" error into a panic. Reproduced on a stock busybox image with no /etc/ssl at all, so it hits any minimal container, not just sandboxed builds. Tested: 1251 tests pass across 31 targets, 0 failures.
This commit is contained in:
@@ -7,26 +7,31 @@
|
|||||||
|
|
||||||
rustPlatform.buildRustPackage rec {
|
rustPlatform.buildRustPackage rec {
|
||||||
pname = "marmel";
|
pname = "marmel";
|
||||||
# Upstream publishes no git tags, so this is pinned to the 1.0.0 release
|
# Upstream publishes no git tags and no GitHub releases, and Cargo.toml still
|
||||||
# commit ("1.0.0 (#6)").
|
# says 1.0.0, so the version is meaningless and the source is tracked by
|
||||||
|
# branch head. Bump with nix-update (see passthru.updateScript).
|
||||||
version = "1.0.0";
|
version = "1.0.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "Na1w";
|
owner = "Na1w";
|
||||||
repo = "marmel";
|
repo = "marmel";
|
||||||
rev = "d6627d7cf3bf509d1e6db0d9d78736116e92e82a";
|
rev = "3f238ff217ee2e1033c937c840bd2d33ec57abc4";
|
||||||
hash = "sha256-UlrSp/n3og0GAQXzISsB24OfK3qOUPE7jYOkEbZ2neI=";
|
hash = "sha256-ijSsUAJom/uIiE09PM1kfXqNVCRqnipAQo72KXlr8sQ=";
|
||||||
};
|
};
|
||||||
|
|
||||||
cargoHash = "sha256-etqW3xcxkiNfkiPxl/Emt5pQCkNnoIhHFkX0Zqfs4rc=";
|
cargoHash = "sha256-etqW3xcxkiNfkiPxl/Emt5pQCkNnoIhHFkX0Zqfs4rc=";
|
||||||
|
|
||||||
nativeCheckInputs = [ cacert ];
|
nativeCheckInputs = [ cacert ];
|
||||||
|
|
||||||
|
patches = [ ./session-boot-trust-store.patch ];
|
||||||
|
|
||||||
# The test suite builds `reqwest::Client`s, and rustls rejects construction
|
# The test suite builds `reqwest::Client`s, and rustls rejects construction
|
||||||
# outright when no system trust store is found ("No CA certificates were
|
# outright when no system trust store is found ("No CA certificates were
|
||||||
# loaded from the system"). The sandbox has no /etc/ssl, so point the tests
|
# loaded from the system"). rustls-native-certs probes only SSL_CERT_FILE,
|
||||||
# at nixpkgs' bundle. Build-time only; the installed binary still uses the
|
# SSL_CERT_DIR and a fixed list of /etc dirs (/etc/ssl, /etc/pki/tls, ...),
|
||||||
# host's trust store at runtime.
|
# none of which exist in the build sandbox, so point the tests at nixpkgs'
|
||||||
|
# bundle. Build-time only; the installed binary still uses the host's trust
|
||||||
|
# store at runtime.
|
||||||
preCheck = ''
|
preCheck = ''
|
||||||
export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
|
export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
|
||||||
'';
|
'';
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
Give the env-cleared child process a trust store.
|
||||||
|
|
||||||
|
run_marmel() wipes the child environment so the binary under test cannot
|
||||||
|
inherit the runner's MARMEL_* variables or its terminal. reqwest's TLS stack
|
||||||
|
is rustls-native-certs, which reads SSL_CERT_FILE / SSL_CERT_DIR and then the
|
||||||
|
well-known /etc paths, so where no system trust store exists at all the child
|
||||||
|
dies inside reqwest::Client::new() ("No CA certificates were loaded from the
|
||||||
|
system") before it ever reads the bundle. Four cases in this file assert the
|
||||||
|
CLI's exit codes and stderr, and they then observe the panic's 101 instead.
|
||||||
|
|
||||||
|
Forward the test runner's SSL_CERT_FILE when it has one. On a normal Linux
|
||||||
|
host the child picks the trust store up from /etc as before, so the assertions
|
||||||
|
themselves are unchanged.
|
||||||
|
|
||||||
|
This is a workaround, not the real fix. The panic should not happen at all:
|
||||||
|
src/llm/client.rs builds the client with unwrap_or_default() on a
|
||||||
|
Result<Client, reqwest::Error>, and reqwest's Client::default() is
|
||||||
|
Client::new(), which repeats the same build and .expect()s it, so the fallback
|
||||||
|
can never recover. Upstream was told; drop this patch once the error is
|
||||||
|
propagated instead of discarded.
|
||||||
|
|
||||||
|
--- a/tests/test_session_boot.rs
|
||||||
|
+++ b/tests/test_session_boot.rs
|
||||||
|
@@ -221,8 +221,17 @@
|
||||||
|
let err_file = std::fs::File::create(&err_path).expect("stderr file");
|
||||||
|
|
||||||
|
let mut cmd = Command::new(env!("CARGO_BIN_EXE_marmel"));
|
||||||
|
- cmd.current_dir(dir)
|
||||||
|
- .env_clear()
|
||||||
|
+ cmd.current_dir(dir).env_clear();
|
||||||
|
+ // rustls-native-certs reads SSL_CERT_FILE / SSL_CERT_DIR, both of which the
|
||||||
|
+ // env_clear() above drops, so when no system trust store can be probed
|
||||||
|
+ // either the child dies inside reqwest::Client::new() ("No CA certificates
|
||||||
|
+ // were loaded from the system") before it ever reaches the bundle, and the
|
||||||
|
+ // exit-code assertions below then see the panic's 101. Forward the runner's
|
||||||
|
+ // value when it has one; the assertions themselves are untouched.
|
||||||
|
+ if let Some(trust_store) = std::env::var("SSL_CERT_FILE").ok().filter(|p| !p.is_empty()) {
|
||||||
|
+ cmd.env("SSL_CERT_FILE", trust_store);
|
||||||
|
+ }
|
||||||
|
+ cmd
|
||||||
|
// A minimal, deterministic environment: the binary must not inherit the
|
||||||
|
// test runner's `MARMEL_*` variables or its terminal.
|
||||||
|
.env("PATH", "/usr/bin:/bin")
|
||||||
Reference in New Issue
Block a user