Give the manifest env() helper an injectable env seam (#484) - #501
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Summary
Closes Verification
WalkthroughUse an injectable ChangesManifest environment injection
Sequence Diagram(s)sequenceDiagram
participant Caller
participant ManifestParser
participant Jinja
participant EnvReader
Caller->>ManifestParser: Call from_str_with_env(yaml, reader)
ManifestParser->>Jinja: Register env() with reader
Jinja->>EnvReader: Request variable name
EnvReader-->>Jinja: Return value or mapped error
Jinja-->>Caller: Return parsed manifest or diagnostic
Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 20✅ Passed checks (20 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Reviewer's GuideInjects an environment-reading seam into the manifest env() helper by introducing env_var_with, updating env_var to delegate through it, and adding focused tests that exercise all Jinja error paths without mutating the process environment. Sequence diagram for manifest env() helper with injectable env seamsequenceDiagram
title Manifest env helper resolution via env_var_with
actor TemplateAuthor
participant Template as template
participant EnvHelper as env
participant EnvVar as env_var
participant EnvVarWith as env_var_with
participant ReadEnv as read_env_closure
TemplateAuthor->>Template: render_manifest
Template->>EnvHelper: env("FOO")
EnvHelper->>EnvVar: env_var("FOO")
EnvVar->>EnvVarWith: env_var_with("FOO", read_env_closure)
EnvVarWith->>ReadEnv: read_env_closure("FOO")
alt [value present]
ReadEnv-->>EnvVarWith: Ok(String)
EnvVarWith-->>EnvVar: Ok(String)
EnvVar-->>EnvHelper: Ok(String)
EnvHelper-->>Template: "FOO" value
else [variable missing]
ReadEnv-->>EnvVarWith: Err(VarError::NotPresent)
EnvVarWith-->>EnvVar: Err(ErrorKind::UndefinedError)
EnvVar-->>EnvHelper: Err(ErrorKind::UndefinedError)
else [value not utf8]
ReadEnv-->>EnvVarWith: Err(VarError::NotUnicode)
EnvVarWith-->>EnvVar: Err(ErrorKind::TemplateRuntimeError)
EnvVar-->>EnvHelper: Err(ErrorKind::TemplateRuntimeError)
end
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/manifest/mod.rs`:
- Around line 73-74: Update the manifest parsing flow around from_str and
env_var to accept a mockable::Env dependency, register env() with it, and
replace direct std::env::var access with the injected reader. Use
mockable::DefaultEnv in production and mockable::MockEnv in tests, preserving
existing environment lookup behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: b0c043b2-8934-4085-9bd9-462f2dfcfd04
📒 Files selected for processing (3)
src/manifest/mod.rssrc/manifest/tests/env_function.rssrc/manifest/tests/mod.rs
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/rstest-bdd(auto-detected)leynos/ortho-config(auto-detected)leynos/shared-actions(auto-detected)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 48c1b8f7e7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Addresses the review findings on #501. CodeRabbit and Codex both identified the same gap, correctly: the seam reached only the leaf mapper, while `from_str_named` still registered the hard-wired `env_var`. Tests of the actual Jinja registration therefore still needed `VarGuard` and `serial_test`, so the PR claimed to remove a mandate violation it had not removed. `from_str_named` now takes an `EnvReader` — a shared `Fn(&str) -> Result<String, VarError>`, `Send + Sync` because minijinja requires registered functions to be — and the registered `env()` closure captures it. `from_str` supplies `process_env_reader()`; `from_str_with_env` takes one explicitly. `tests/manifest_env_tests.rs` now drives the real registration path with an injected reader. It is no longer `#[serial]` and no longer uses `VarGuard`. The non-UTF-8 case drops its `OsStringExt` surgery and its `#[cfg(unix)]` gate, so it runs everywhere. Two consequences of the threading, each handled rather than suppressed: `from_str_named` reached five arguments, so the three that travel together are bundled into a `ManifestParse` struct; and `manifest::mod` passed 400 lines, so the reader type, its process-backed default, and the failure mapping move to `manifest::env_reader`. Codex also asked for the helper's reuse policy to be recorded per AGENTS.md; the developers' guide gains a "Manifest `env()` reader" section covering ownership, permitted call sites, and composition. Refs #484, #496. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/developers-guide.md`:
- Around line 541-546: The developer guide paragraph incorrectly retains
isolation requirements for manifest environment tests. Update the discussion
around the “Test isolation utilities” section to exclude
tests/manifest_env_tests.rs from EnvLock, EnvVarGuard, CwdGuard, and #[serial]
guidance, limiting those requirements to binaries that still mutate
process-global state or documenting a separate valid coverage exception.
In `@src/manifest/env_reader.rs`:
- Around line 27-33: Mark the Rust doctest fence in the process_env_reader
documentation as no_run, changing the existing rust fence to rust,no_run while
preserving the example content.
- Around line 46-50: Replace the stale [`env_var`] intra-doc link in the
surrounding documentation with plain text or a valid symbol reference, ensuring
rustdoc no longer attempts to resolve the removed helper while preserving the
description of the three outcomes tested by the helper.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 70a6ec0c-c5bc-46a7-9db9-b0e694c737da
📒 Files selected for processing (11)
docs/adr-006-adopt-polonius-nightly-toolchain.mddocs/developers-guide.mddocs/netsuke-design.mddocs/polonius.mddocs/snapshot-testing-in-netsuke-using-insta.mddocs/users-guide.mdsrc/manifest/env_reader.rssrc/manifest/mod.rssrc/manifest/tests/env_function.rssrc/manifest/tests/mod.rstests/manifest_env_tests.rs
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/rstest-bdd(auto-detected)leynos/ortho-config(auto-detected)leynos/shared-actions(auto-detected)
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai Have the following now been resolved? docs/developers-guide.md (1)
🤖 Detailed instructionsVerify each finding against current code. Fix only still-valid issues, skip the In |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/users-guide.md`:
- Around line 470-472: Remove the contributor-focused paragraph from the user
guide, including the reference to the developers' guide and the Manifest env()
reader section. Keep the surrounding user and embedding workflow documentation
unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 10708772-63f0-4bd5-a2eb-6fb3aa945aa1
📒 Files selected for processing (1)
docs/users-guide.md
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/rstest-bdd(auto-detected)leynos/ortho-config(auto-detected)leynos/whitaker(auto-detected)leynos/shared-actions(auto-detected)
Round feedback on #501, each point verified against manifest/mod.rs. The users' guide loses its contributor-facing pointer — that audience is the developers' guide's, and the section must stay embedder-facing. The developers' guide's ownership bullet claimed from_str_named owns the reader; in fact the caller owns it, from_str_named borrows it via ManifestParse and Arc::clones it into the registered closure, which therefore co-owns the Arc. The design document's §4.4 bullet still described env() as reading the system directly; it now names the EnvReader boundary, the process-backed default, and the caller-supplied alternative. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@coderabbitai Have the following now been resolved? tests/makefile_test_target.rs (1)
below 400 lines. Add a As per path instructions, “Files must not exceed 400 lines.” Proposed module boundary+#[path = "makefile_test_target/rustflags_contract.rs"]
+mod rustflags_contract;
+
-const RUSTFLAGS_PREFIX: &str = "RUSTFLAGS=\"";
-// Move the RustflagsCase helpers and Rustflags contract tests to the new module.🤖 Detailed instructionsVerify each finding against current code. Fix only still-valid issues, skip the In Sources: Coding guidelines, Path instructions, Learnings |
This comment was marked as resolved.
This comment was marked as resolved.
|
@coderabbitai Have the following failed checks now been resolved? If further work is required, please provide an AI agent prompt for the remaining work to be done to address these failures. Do not treat warnings as optional or aspirational. Where a change is out of scope for this PR, propose a GitHub issue unless one exists already. (Treat o11y, code safety, documentation and validation coverage as in scope). Assessment against linked issues
|
This comment was marked as resolved.
This comment was marked as resolved.
|
On the pre-merge table's Developer Documentation warning: that row predates dce4728, which already updated netsuke-design.md §4.4 (it now describes Separately, the makefile_test_target decomposition requested against this PR now lives in #526, stacked on this branch, closing #524. |
|
@coderabbitai review |
✅ Action performedReview finished.
|
`env_var` read the process environment directly, so the `env()` Jinja helper's three outcomes could only be exercised by mutating global state. One was unreachable in practice: fabricating a non-UTF-8 value in the live environment needs platform-specific OsString surgery, so the NotUnicode branch and its distinct Jinja error kind had no coverage at all. The AGENTS.md testing mandate now forbids the mutation regardless. Split the resolution into `env_var_with`, taking a `read_env` closure, consistent with the seams in runner::process::ninja_program and the two added for #486 and #487. A closure rather than a trait object: this is a keyed lookup with one caller, and the mandate permits a narrow closure where a trait object would be disproportionate. The stale doc example advertising a mutating `test_support::env::VarGuard` goes with it. Adds six cases, including that an empty value is returned rather than treated as missing, and that the missing and non-UTF-8 failures keep distinct error kinds — a missing variable is a template authoring error, whereas a non-UTF-8 value is an environment problem the author cannot fix in the template, and collapsing them would misdirect whoever reads the failure. Closes #484. Refs #496. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Addresses the review findings on #501. CodeRabbit and Codex both identified the same gap, correctly: the seam reached only the leaf mapper, while `from_str_named` still registered the hard-wired `env_var`. Tests of the actual Jinja registration therefore still needed `VarGuard` and `serial_test`, so the PR claimed to remove a mandate violation it had not removed. `from_str_named` now takes an `EnvReader` — a shared `Fn(&str) -> Result<String, VarError>`, `Send + Sync` because minijinja requires registered functions to be — and the registered `env()` closure captures it. `from_str` supplies `process_env_reader()`; `from_str_with_env` takes one explicitly. `tests/manifest_env_tests.rs` now drives the real registration path with an injected reader. It is no longer `#[serial]` and no longer uses `VarGuard`. The non-UTF-8 case drops its `OsStringExt` surgery and its `#[cfg(unix)]` gate, so it runs everywhere. Two consequences of the threading, each handled rather than suppressed: `from_str_named` reached five arguments, so the three that travel together are bundled into a `ManifestParse` struct; and `manifest::mod` passed 400 lines, so the reader type, its process-backed default, and the failure mapping move to `manifest::env_reader`. Codex also asked for the helper's reuse policy to be recorded per AGENTS.md; the developers' guide gains a "Manifest `env()` reader" section covering ownership, permitted call sites, and composition. Refs #484, #496. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CodeRabbit noted the developers' guide still required EnvLock and `#[serial]` for manifest environment tests. The prose was stale, but so was the configuration behind it. `manifest_env_tests` was a member of the `serial-env` nextest group and named in the guide as mutating process-global state. Since it moved to an injected reader it mutates nothing, so it was being serialized for no reason. Removed from `.config/nextest.toml`, from the guide, and from the test that pins the group's membership. That guard test now also asserts the binary stays *out*, so the configuration cannot silently reacquire a constraint it no longer has. The guide gains the general rule: a binary migrated to an injected seam leaves the group and drops its `#[serial]` markers in the same change. Also from the same review: the `process_env_reader` doctest is marked `no_run`, since asserting a variable is absent makes the doctest a hostage to whatever CI exports; and the intra-doc link to the removed `env_var` is replaced. Refs #484, #496. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CodeRabbit: the developers' guide claims `serial-env` covers exactly two
binaries, but the test only checked that the two expected ones appear and
that `manifest_env_tests` does not. A third could have joined unnoticed,
silently serializing tests that need not be, while the guide carried on
claiming otherwise.
The filter's members are now parsed and compared as a set, so the guide's
claim is enforced rather than weakened to "including". Verified by adding
a third binary, which fails and names the intruder:
serial-env should cover exactly the two PATH- and NINJA_ENV-mutating
binaries; found ["env_path_tests", "intruder_tests", "ninja_env_tests"]
This also subsumes the previous absence check: a binary that stops
mutating process state must leave the group, or the configuration
outlives the constraint it describes.
Also reverts markdown reflow that `make fmt` had carried into five
unrelated documents; #512 fixes that at the source.
Refs #484, #496.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The branch predated #512, which normalized the whole docs tree to the mdtablefix 0.5.0 standard. Rebasing onto main therefore carried the branch's older line wrapping and table padding back over five documents the env-seam work never meant to touch. Restore main's version of those five. Only docs/developers-guide.md keeps a diff, and only for the sections this branch actually documents: the serial-env group membership and the manifest env() reader seam. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The guide claimed nothing but the public entry points constructs an `EnvReader`, and that tests must not reach past `from_str_with_env` to the leaf mapper. Both are false. `tests/manifest_env_tests.rs` builds readers with `Arc::new`, which is the point of the seam, and `src/manifest/tests/env_function.rs` drives `env_var_with` directly. Describe the split that actually exists, because the two layers cover different things: integration tests exercise registration — that the reader reaches the `env()` function Jinja calls — while unit tests cover error mapping at the leaf, where the non-UTF-8 branch is reachable without platform-specific `OsString` surgery. Rename the section's `Composition rules` heading, which collided with the one at line 503 under MD024. Discard the doctest's `Result` with `drop(...)` rather than `let _ =`. Addresses CodeRabbit findings on #501.
An accepted pre-merge item on #501: the guide named env()'s failure behaviour but not the seam behind it, so embedders and test authors had no user-facing pointer to from_str_with_env, EnvReader, or process_env_reader. The new subsection states what the seam is for, names the three entry points, and mirrors the executable doctest rather than pretending the guide snippet is run by the YAML harness. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Round feedback on #501, each point verified against manifest/mod.rs. The users' guide loses its contributor-facing pointer — that audience is the developers' guide's, and the section must stay embedder-facing. The developers' guide's ownership bullet claimed from_str_named owns the reader; in fact the caller owns it, from_str_named borrows it via ManifestParse and Arc::clones it into the registered closure, which therefore co-owns the Arc. The design document's §4.4 bullet still described env() as reading the system directly; it now names the EnvReader boundary, the process-backed default, and the caller-supplied alternative. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CI caught what the local docs gates could not: every fence in the
scanned guides must carry a tested-example marker, and the new
env-reader snippet had none, failing every documentation scenario at
load. The fence is now marked and registered, and a pin asserts the
snippet keeps naming the entry points it mirrors — from_str_with_env,
EnvReader, and the env('PROFILE') read — so the guide copy cannot
drift from the doctest silently.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
e0e1acd to
5446272
Compare
Summary
env_var— backing theenv()Jinja helper — read the process environment directly:Its three outcomes could only be reached by mutating global state, which the AGENTS.md testing mandate no longer permits. One was unreachable in practice regardless: fabricating a non-UTF-8 value in the live environment needs platform-specific
OsStringsurgery, so theNotUnicodebranch and its distinct Jinja error kind had no coverage at all.The function's doc comment also advertised a
test_support::env::VarGuardexample that mutates global state; that goes with it.Approach
Split resolution into
env_var_with, taking aread_envclosure — consistent with the existing seam inrunner::process::ninja_programand the two added in #486 and #487. A closure rather than a trait object: keyed lookup, one caller, and the mandate permits a narrow closure where a trait object would be disproportionate.Coverage
Six cases, none mutating anything:
Checked against upstream RFCs
ortho-config RFC 0001 governs field-level environment aliases for configuration structs. It has no bearing on the manifest
env()helper, which is Netsuke's own template surface, so the closure seam here is not in tension with theEnvSourceabstraction being added upstream.Verification
All gates pass:
check-fmt,lint,typecheck,test(1194 nextest),markdownlint,nixie. CodeScene delta: no issues.Closes #484.
Refs #496.
🤖 Generated with Claude Code
Summary by Sourcery
Introduce an injectable environment lookup seam for the manifest env() helper to enable full testing of all resolution outcomes without mutating process state.
Enhancements:
Tests: