test(e2e): add scenario fixture context#4965
Conversation
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (8)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds an E2E test framework: confined artifact sink, secret-store redaction, cleanup registry, trusted ShellProbe (validation, timeout/abort escalation, redacted artifacts), Vitest fixture wiring, and tests + probe-evidence utilities. ChangesE2E Test Framework
Sequence DiagramsequenceDiagram
participant Vitest
participant ShellProbe
participant ChildProcess
participant ArtifactSink
Vitest->>ShellProbe: run(trustedCommand, options)
ShellProbe->>ChildProcess: spawn(detached, cwd, env)
ChildProcess-->>ShellProbe: stdout/stderr/events
ShellProbe->>ShellProbe: enforce timeout/abort (SIGTERM -> SIGKILL)
ShellProbe->>ArtifactSink: writeText(redacted stdout)
ShellProbe->>ArtifactSink: writeText(redacted stderr)
ShellProbe->>ArtifactSink: writeJson(redacted result)
ShellProbe-->>Vitest: return ShellProbeResult
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
E2E Advisor RecommendationRequired E2E: Dispatch hint: Full advisor summaryE2E Recommendation AdvisorBase: Required E2E
Optional E2E
New E2E recommendations
Dispatch hint
|
E2E Scenario Advisor RecommendationRequired scenario E2E: Dispatch required scenario E2E:
Full scenario advisor summaryE2E Scenario AdvisorBase: Required scenario E2E
Optional scenario E2E
Relevant changed files
|
PR Review AdvisorFindings: 0 needs attention, 8 worth checking, 1 nice ideas Review findings🛠️ Needs attention
🔎 Worth checking
🌱 Nice ideas
Consider writing more tests for
Since last review detailsCurrent findings:
This is an automated advisory review. A human maintainer must make the final merge decision. |
# Conflicts: # test/e2e-scenario/framework-tests/e2e-live-project-config.test.ts # test/e2e-scenario/framework/live-project-gate.ts # vitest.config.ts
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
|
Addressed the PR review advisor feedback in |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
|
Addressed the remaining PR review advisor item in |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
|
Addressed the PR review advisor fixture API finding in |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
|
Addressed the remaining ShellProbe advisor items 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 `@test/e2e-scenario/framework/shell-probe.ts`:
- Around line 170-175: ShellProbe.run() currently attaches an "abort" listener
to this.signal without checking if this.signal.aborted first, so a pre-aborted
AbortSignal can skip immediate termination; update ShellProbe.run() to check
this.signal.aborted before adding the listener and call the existing
abort/terminate logic immediately if true (referencing ShellProbe.run(),
this.signal, the abort handler, timeout/terminate logic), keep the existing
setTimeout fallback, and ensure the listener is still added only when not
already aborted; additionally add an e2e test that constructs a pre-aborted
AbortSignal and passes it to ShellProbe.run() to verify immediate termination
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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 7e3216a3-ba1a-46ea-94cd-1a87acbe7589
📒 Files selected for processing (6)
test/e2e-scenario/framework-tests/e2e-fixture-context.test.tstest/e2e-scenario/framework/artifacts.tstest/e2e-scenario/framework/cleanup.tstest/e2e-scenario/framework/e2e-test.tstest/e2e-scenario/framework/secrets.tstest/e2e-scenario/framework/shell-probe.ts
jyaunches
left a comment
There was a problem hiding this comment.
Thanks for landing the foundation — the Vitest fixture model is the right target architecture and the chained stack (#4965 → #4969) is a clean way to ship it. But before this foundation lands, three of the five new modules reimplement infrastructure that #4380 just hardened, and two of those reimplementations are weaker than the existing typed-shell-runner code. Calling these out as a Request Changes so we don't ship two parallel spawn boundaries / two redaction layers / two artifact layouts in test/e2e-scenario/.
Concrete duplications
1. framework/shell-probe.ts reimplements scenarios/orchestrators/phase.ts:executeStep + scenarios/probes/util.ts:spawnBash/runHostCmd
Both spawn a child, capture stdout/stderr, enforce a timeout, write artifacts. The differences are regressions:
- Timeout reaping:
shell-probe.tsdoes SIGTERM → grace → SIGKILL on the leader pid only. The existingphase.tsuses a detached process group + negative-pid SIGTERM specifically to reap orphan grandchildren (bash + sleepis the canonical example). On a wedged sandbox-exec the new fixture leaves the inner process running. - Input validation contract:
probes/util.tshas a NUL-byte rejector + anlgtm[js/shell-command-injection-from-environment]justification we just landed in #4380 (commitsbd4d3ce0b,7887adb92,70df0519b) to clear CodeQL alerts 715/792/793.shell-probe.tshas no equivalent contract; it'll trip the same alerts as soon as a fixture runs against an untrusted-shape input. - Sandbox-exec transport:
runSandboxCmdroutes throughvalidation_suites/sandbox-exec.shso ssh-config-preferred / openshell-exec-fallback lives in one place.shell-probe.tsdoesn't have a sandbox-exec story yet, which is fine for host commands but means scenarios that need to enter the sandbox can't use it without re-importing the existing helper.
2. framework/secrets.ts reimplements scenarios/orchestrators/redaction.ts — with weaker coverage
This one is a real correctness regression:
- Existing:
redaction.tsimportsTOKEN_PREFIX_PATTERNSandCONTEXT_PATTERNSdirectly fromsrc/lib/security/secret-patterns.ts(the canonical product source).framework-tests/e2e-redaction-parity.test.ts(landed in #4380) locks the framework mirror to the product source via fingerprint comparison. Adding a new token shape insecret-patterns.tsautomatically protects the framework path. framework/secrets.ts: usesSENSITIVE_NAME_PATTERN = /(api[_-]?key|token|secret|password|credential)/iagainst env var names, then substring-replaces the values it found. Tokens that appear in output without a matching env-var name (e.g. annvapi-...echoed from a help string) are not redacted at all.
The new framework participates in zero parity contract with secret-patterns.ts. Adding a new token shape upstream will silently leak through framework/.
3. framework/artifacts.ts reimplements phase.ts:writeEvidence + probes/util.ts:writeProbeEvidence — with one improvement
ArtifactSink.pathFor()rejects absolute paths and escape paths via prefix check. The existingwriteProbeEvidencedoes plainmkdirSync+writeFileSync— no path validation. That part offramework/is genuinely better and we should backport it toprobes/util.ts.- The artifact layouts are incompatible:
framework/writes<base>.stdout.txt/<base>.stderr.txt/<base>.result.jsonrooted at.e2e/vitest/<test-slug>/, the existing typed-shell-runner writes.e2e/logs/<step-id>.log+.e2e/actions/<action-id>.log+.e2e/<phase>.result.json. Two layouts under the same.e2e/root will fragment the artifact-bundle redaction allowlist ine2e-scenarios.yaml.
4 + 5: Genuinely new
framework/cleanup.ts: per-test cleanup-registry pattern. The existingScenarioRunnerdoes imperative phase teardown without a registry. New, fine.framework/e2e-test.ts: Vitesttest.extendfixture composition. This is the architectural shift the migration exists for, not duplication.
What I'd ask before merging
Either of these works:
Option A — consume shared infrastructure (preferred).
Extract the existing typed-shell-runner spawn/redact/evidence code into a shared test/e2e-scenario/framework-infra/ module that both scenarios/orchestrators/ and framework/ consume. The Vitest fixtures inherit:
- the parity-tested redaction patterns,
- the NUL-validated + lgtm-justified spawn contract,
- the detached-pgid timeout reaping.
Option B — explicitly bridge-only + backport.
Mark framework/secrets.ts and framework/shell-probe.ts as bridge-only in their doc comments, file follow-up issues to consolidate (one per module), and:
- update
framework/secrets.tsto import the canonical regex sets soe2e-redaction-parity.test.tscovers both layers, or add a separate parity test forframework/secrets.tsagainstsecret-patterns.ts, - backport
artifacts.ts:pathForpath-traversal check toprobes/util.ts:writeProbeEvidence.
Without one of those, this PR ships test/e2e-scenario/ with two spawn boundaries, two redaction layers, and two artifact layouts — and two of the three are weaker than what we just hardened to land #4380.
Happy to pair on Option A if it'd help — extracting framework-infra/spawn.ts + framework-infra/redact.ts + framework-infra/artifacts.ts is mostly mechanical, and we'd land #4380's hardening on the new fixture path for free.
Refs: #4380, parity test in test/e2e-scenario/framework-tests/e2e-redaction-parity.test.ts, spawn safety contract in test/e2e-scenario/scenarios/probes/util.ts:spawnBash.
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
|
Addressed the CodeRabbit pre-aborted AbortSignal finding in a013e04: ShellProbe now checks signal.aborted before registering the abort listener and immediately runs the same terminate path for pre-aborted signals. Added a regression test that proves a pre-aborted signal terminates the child promptly without waiting for the timeout. |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
|
Addressed the changes-requested review in 929efde. What changed:
|
Summary
Adds the core Vitest fixture context for E2E scenarios, including artifacts, cleanup, secret redaction, and shell probing. Also hardens cleanup/probe behavior based on advisor feedback.
Related Issue
Refs #4941.
Changes
test/e2e-scenario/framework/artifacts.ts.ShellProbehelpers with trusted command descriptors, explicit environment passing, redacted artifacts, timeout/abort SIGKILL escalation, and spawn-error cleanup handling.framework/e2e-test.tsusing Vitest object fixtures.Type of Change
Verification
npx prek run --all-filespassesnpm testpassesnpm run docsbuilds without warnings (doc changes only)Signed-off-by: Carlos Villela cvillela@nvidia.com
Summary by CodeRabbit