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 {
|
||||
pname = "marmel";
|
||||
# Upstream publishes no git tags, so this is pinned to the 1.0.0 release
|
||||
# commit ("1.0.0 (#6)").
|
||||
# Upstream publishes no git tags and no GitHub releases, and Cargo.toml still
|
||||
# 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";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Na1w";
|
||||
repo = "marmel";
|
||||
rev = "d6627d7cf3bf509d1e6db0d9d78736116e92e82a";
|
||||
hash = "sha256-UlrSp/n3og0GAQXzISsB24OfK3qOUPE7jYOkEbZ2neI=";
|
||||
rev = "3f238ff217ee2e1033c937c840bd2d33ec57abc4";
|
||||
hash = "sha256-ijSsUAJom/uIiE09PM1kfXqNVCRqnipAQo72KXlr8sQ=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-etqW3xcxkiNfkiPxl/Emt5pQCkNnoIhHFkX0Zqfs4rc=";
|
||||
|
||||
nativeCheckInputs = [ cacert ];
|
||||
|
||||
patches = [ ./session-boot-trust-store.patch ];
|
||||
|
||||
# The test suite builds `reqwest::Client`s, and rustls rejects construction
|
||||
# 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
|
||||
# at nixpkgs' bundle. Build-time only; the installed binary still uses the
|
||||
# host's trust store at runtime.
|
||||
# loaded from the system"). rustls-native-certs probes only SSL_CERT_FILE,
|
||||
# SSL_CERT_DIR and a fixed list of /etc dirs (/etc/ssl, /etc/pki/tls, ...),
|
||||
# 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 = ''
|
||||
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