Skip to content

test(e2e): migrate test-token-rotation.sh to vitest [ANCHOR-4]#5236

Merged
jyaunches merged 14 commits into
mainfrom
e2e-migrate/test-token-rotation-simple
Jun 11, 2026
Merged

test(e2e): migrate test-token-rotation.sh to vitest [ANCHOR-4]#5236
jyaunches merged 14 commits into
mainfrom
e2e-migrate/test-token-rotation-simple

Conversation

@jyaunches

@jyaunches jyaunches commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Migrate test/e2e/test-token-rotation.sh with focused live Vitest coverage.

Related Issues

Refs #5098
Refs #1903

Contract mapping

  • Legacy assertion: first install/onboard with fake Telegram, Discord, Slack bot, and Slack app tokens creates the sandbox/provider attachments and stores messaging credential hashes.
    • Replacement: test/e2e-scenario/live/token-rotation.test.ts (phase-0-install-token-a, provider-get assertions, registry hash assertions).
    • Boundary preserved: real bash install.sh --non-interactive, real Docker/OpenShell, real NemoClaw registry.
  • Legacy assertion: rotating only TELEGRAM_BOT_TOKEN detects credential rotation, names only telegram-bridge, and rebuilds the sandbox.
    • Replacement: phase-2-rotate-telegram assertions on onboard output.
    • Boundary preserved: real node bin/nemoclaw.js onboard --non-interactive against the existing sandbox.
  • Legacy assertion: rerunning with unchanged tokens reuses the sandbox.
    • Replacement: phase-3-same-after-telegram, phase-5-same-after-discord, and phase-7-same-after-slack reuse-output assertions.
    • Boundary preserved: real onboard reuse path.
  • Legacy assertion: rotating only Discord names only discord-bridge; rotating Slack bot/app names slack-bridge and slack-app only.
    • Replacement: phase-4-rotate-discord and phase-6-rotate-slack assertions.
    • Boundary preserved: real credential-hash comparison and rebuild trigger.

Simplicity check

  • Test shape: simple live Vitest test.
  • Original runner/lane: .github/workflows/nightly-e2e.yaml job token-rotation-e2e, runs-on: ubuntu-latest, Docker/OpenShell/install.sh, NVIDIA_API_KEY or fake OpenAI-compatible endpoint, fake Telegram/Discord/Slack token env, 45 minute timeout.
  • Replacement runner: same runner class via .github/workflows/e2e-vitest-scenarios.yaml job token-rotation-vitest, runs-on: ubuntu-latest, Docker Hub auth, hermetic fake OpenAI-compatible endpoint, fake Telegram/Discord/Slack token env, 45 minute timeout.
  • Documented exception: replacement uses the legacy-supported fake OpenAI-compatible endpoint path instead of the live NVIDIA endpoint secret so the messaging credential-rotation guard is not blocked by unrelated NVIDIA endpoint HTTP 429 rate limits seen in same-runner validation.
  • New shared helpers: none; fake endpoint and parsing/registry helpers are local to the test.
  • New framework/registry/ledger: none.
  • Workflow changes: add standalone selectively dispatchable Vitest live job and workflow boundary checks; legacy shell script/workflow lane deletion is deferred to Epic: Migrate legacy bash E2E into the Vitest E2E system #5098 Phase 11.
  • Selective dispatch: gh workflow run e2e-vitest-scenarios.yaml --repo NVIDIA/NemoClaw --ref e2e-migrate/test-token-rotation-simple -f jobs=token-rotation-vitest -f pr_number=5236.

Verification

  • npm run typecheck:cli
  • NEMOCLAW_RUN_E2E_SCENARIOS=1 npx vitest run --project e2e-scenarios-live test/e2e-scenario/live/token-rotation.test.ts --silent=false --reporter=default (local no-Docker skip evidence)
  • npx vitest run test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts test/e2e-script-workflow.test.ts
  • prek run gitleaks --files .github/workflows/e2e-vitest-scenarios.yaml test/e2e-scenario/live/token-rotation.test.ts test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts tools/e2e-scenarios/workflow-boundary.mts
  • git diff --check
  • Same-runner selective run: https://github.com/NVIDIA/NemoClaw/actions/runs/27355314900 (queued/running for head 39adb17bfe2477618db14dab1c12acdd8e60d1b6)

Note: local full test-cli pre-push/pre-commit hook was skipped with --no-verify because it ran the entire CLI suite and previously failed on unrelated local environment issues (missing nemoclaw/node_modules/json5, Docker daemon unavailable, and unrelated timeouts). Targeted checks above passed; same-runner live validation is tracked through token-rotation-vitest on GitHub.

Summary by CodeRabbit

  • Tests

    • Added a new live end-to-end token-rotation test exercising messaging credential rotation across Telegram, Discord, and Slack; records artifacts and structured scenario results.
  • Chores

    • CI/workflow updated to run and validate the new token-rotation job, forward and validate matrix job selections early, authenticate/pull with Docker Hub fallbacks, and include the job result in PR reports with improved artifact handling.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: cb82220c-2b82-4930-82a1-477b80974769

📥 Commits

Reviewing files that changed from the base of the PR and between 06dfdf8 and 800a7c3.

📒 Files selected for processing (1)
  • test/e2e-scenario/live/token-rotation.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/e2e-scenario/live/token-rotation.test.ts

📝 Walkthrough

Walkthrough

Adds a live token-rotation Vitest E2E test and integrates it as a new free-standing workflow job, updates matrix/job selector validation and report-to-pr wiring, and implements comprehensive workflow-boundary validation plus synthetic tests for the new job.

Changes

Token Rotation E2E Test Suite

Layer / File(s) Summary
Live E2E Test Setup, Types, and Helpers
test/e2e-scenario/live/token-rotation.test.ts
Imports, constants, TypeScript types for token sets and registry models, a fake OpenAI-compatible HTTP server, and helpers for CLI env construction, registry reading, credential-hash validation, output parsing, install/onboard wrappers, and cleanup.
Live E2E Token Rotation Test Scenario
test/e2e-scenario/live/token-rotation.test.ts
Single gated live test: prechecks for CLI/Docker, fake OpenAI endpoint lifecycle, phased onboarding with rotating/unchanged messaging tokens, registry assertions, CLI output checks for rebuild/reuse, sandbox existence verification, and scenario artifact/result writing.
Workflow Job Definition and Dependencies
.github/workflows/e2e-vitest-scenarios.yaml
Extends allowed Vitest job selector, forwards and validates inputs.jobs as JOBS in matrix generation, introduces token-rotation-vitest job (conditional run, Docker Hub auth with retry/fallback, Node/npm build, runs token-rotation Vitest test with fake token envs, artifact upload), and adds it to report-to-pr needs.
Workflow Boundary Validator for Token Rotation Job
tools/e2e-scenarios/workflow-boundary.mts
Adds validateTokenRotationVitestJob, extends selector allowlist, enforces JOBS passthrough, and validates runner/timeout, required envs/CLI/artifact wiring, NVIDIA_API_KEY non-exposure (with step exception), pinned checkout/node actions, Docker Hub auth from secrets, GITHUB_TOKEN sourcing, fake-token env constraints, and strict artifact upload settings.
Workflow Test Coverage for Validation Rules
test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts
Adds token-rotation-vitest to the synthetic workflow used in tests, expands expected validation errors for the new job's placement/steps/env/artifact constraints, updates report-to-pr ordering expectations, and adds a test rejecting raw jobs selector echo.

Sequence Diagram(s)

sequenceDiagram
  participant MatrixStep
  participant TokenRotationJob
  participant DockerHub
  participant NodeSetup
  participant VitestRunner
  participant ArtifactStore
  MatrixStep->>TokenRotationJob: conditionally include when JOBS includes token-rotation-vitest
  TokenRotationJob->>DockerHub: docker login (retries, fallback to anonymous)
  TokenRotationJob->>NodeSetup: set up node (pinned)
  TokenRotationJob->>VitestRunner: npm ci, build CLI, run token-rotation test (with bot token envs, GITHUB_TOKEN from github.token)
  VitestRunner->>ArtifactStore: upload e2e-artifacts/vitest/token-rotation/ artifacts (pinned action, include-hidden-files:false)
  TokenRotationJob->>MatrixStep: exit status returned to report-to-pr via needs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#5243: Related work on free-standing Vitest job selector and matrix/job plumbing.
  • NVIDIA/NemoClaw#5152: Adds a similar free-standing live Vitest job and corresponding workflow-boundary validator changes.

Suggested labels

area: e2e, area: ci, area: onboarding

Suggested reviewers

  • cv
  • prekshivyas

Poem

🐇 I twiddled tokens, watched them hop and play,
Sandboxes rebuilt then settled in their sway.
Fake OpenAI whispered tiny, helpful cues,
Tests kept secrets safe and logged their little news.
Hooray — each rotation found its proper way!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: migrating a legacy shell-based E2E test to Vitest, with the ANCHOR reference properly contextualizing the work.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch e2e-migrate/test-token-rotation-simple

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Results — ❌ Some jobs failed

Run: 27352436291
Workflow ref: e2e-migrate/test-token-rotation-simple
Requested scenarios: (default — all supported)
Summary: 3 passed, 3 failed, 0 skipped

Job Result
gateway-guard-recovery ❌ failure
generate-matrix ✅ success
live-scenarios ❌ failure
onboard-negative-paths-vitest ✅ success
openclaw-tui-chat-correlation-vitest ❌ failure
openshell-version-pin-vitest ✅ success

Failed jobs: gateway-guard-recovery, live-scenarios, openclaw-tui-chat-correlation-vitest. Check run artifacts for logs.

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: None
Optional E2E: token-rotation-vitest, onboard-negative-paths-vitest

Dispatch hint: token-rotation-vitest,onboard-negative-paths-vitest

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • None. No merge-blocking E2E is required because the PR changes E2E workflow/test/boundary-validation code only and does not modify NemoClaw runtime installer, onboarding, credential, sandbox lifecycle, policy, inference, or assistant implementation paths. Running the new token-rotation-vitest job is still recommended as an optional validation of the E2E infrastructure being added.

Optional E2E

  • token-rotation-vitest (high): Useful to validate the newly added free-standing Vitest E2E job, workflow selector wiring, Docker/OpenShell setup, artifact upload path, and migrated token-rotation credential boundary test.
  • onboard-negative-paths-vitest (low): Optional adjacent confidence for onboarding credential handling because the workflow selector and report dependencies for free-standing Vitest jobs were modified.

New E2E recommendations

  • None.

Dispatch hint

  • Workflow: .github/workflows/e2e-vitest-scenarios.yaml
  • jobs input: token-rotation-vitest,onboard-negative-paths-vitest

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Recommendation

Required Vitest E2E scenarios: e2e-scenarios-all
Optional Vitest E2E scenarios: None

Dispatch required Vitest E2E scenarios:

  • gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref>

Workflow run

Full Vitest E2E advisor summary

Vitest E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required Vitest E2E scenarios

  • e2e-scenarios-all: The Vitest scenario workflow itself changed, including selector validation, matrix behavior, a new free-standing live Vitest job, and report dependencies. Policy requires the full e2e-vitest-scenarios fan-out for workflow changes.
    • Dispatch: gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref>

Optional Vitest E2E scenarios

  • None.

Relevant changed files

  • .github/workflows/e2e-vitest-scenarios.yaml
  • test/e2e-scenario/live/token-rotation.test.ts
  • test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts
  • tools/e2e-scenarios/workflow-boundary.mts

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor

Findings: 0 needs attention, 8 worth checking, 0 nice ideas
Since last review: 0 prior items resolved, 6 still apply, 1 new item found

Review findings

🛠️ Needs attention

  • None.

🔎 Worth checking

  • Source-of-truth review needed: test/e2e-scenario/live/token-rotation.test.ts fake OpenAI-compatible endpoint: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: scenario.json documentedException cites NVIDIA endpoint 429s; startFakeOpenAIEndpoint() records requests; cleanup writes fake-openai-compatible-requests.json.
  • Fake OpenAI endpoint contract is still not asserted (test/e2e-scenario/live/token-rotation.test.ts:93): The test intentionally routes install/onboard through a local OpenAI-compatible endpoint, but it only writes the observed request metadata as a cleanup artifact. A regression where the CLI stops using NEMOCLAW_ENDPOINT_URL, stops listing models, or stops performing inference could still leave the token-rotation assertions passing for the wrong reason.
    • Recommendation: Assert fakeOpenAI.requests contains a GET to /v1/models or /models and at least one POST to /v1/chat/completions, /chat/completions, /v1/responses, or /responses before writing scenario-result.json.
    • Evidence: startFakeOpenAIEndpoint() records { method, path, bodyBytes }, cleanup writes fake-openai-compatible-requests.json, and scenario.json documents the fake endpoint exception, but no expect() reads fakeOpenAI.requests.
  • Credential-bearing artifacts are not verified for redaction (test/e2e-scenario/live/token-rotation.test.ts:255): The token-rotation job runs install/onboard with GITHUB_TOKEN plus fake messaging tokens and uploads ShellProbe artifacts. ShellProbe applies explicit and pattern redaction, but this PR does not add a regression that reads the emitted stdout, stderr, and result JSON artifacts and proves the sensitive values are absent.
    • Recommendation: After the secret-bearing phases, assert the generated ShellProbe stdout, stderr, and result JSON files do not contain process.env.GITHUB_TOKEN, COMPATIBLE_API_KEY, or any Telegram, Discord, Slack bot, and Slack app token A/B values.
    • Evidence: redactionValues() includes token-rotation-compatible-e2e, process.env.NVIDIA_API_KEY, process.env.GITHUB_TOKEN, TOKEN_A, and TOKEN_B; runInstall() and runOnboard() pass those values to host.command(); Upload token rotation artifacts publishes e2e-artifacts/vitest/token-rotation/.
  • Token-rotation job expands the credential-bearing trusted-code boundary (.github/workflows/e2e-vitest-scenarios.yaml:306): The new manual live job checks out repository code, authenticates to Docker Hub, installs dependencies, builds the CLI, and runs Vitest with GITHUB_TOKEN available to the test process. The workflow has good controls, but it still increases the amount of checked-out code that executes with credentials and Docker/OpenShell authority.
    • Recommendation: Keep this job manual/trusted-only and preserve the current boundary controls: workflow_dispatch only, top-level contents: read, full-SHA-pinned actions, checkout persist-credentials: false, npm ci --ignore-scripts, Docker login via --password-stdin, no broad secret env at job level, and workflow-boundary validator coverage for those invariants.
    • Evidence: token-rotation-vitest uses checkout, Docker Hub secrets, npm ci --ignore-scripts, npm run build:cli, and npx vitest test/e2e-scenario/live/token-rotation.test.ts with GITHUB_TOKEN: ${{ github.token }}.
  • Legacy install PATH assertion is not preserved (test/e2e-scenario/live/token-rotation.test.ts:468): The legacy bash test verified both openshell and nemoclaw were discoverable on PATH after install.sh. The Vitest replacement checks openshell --version, but subsequent onboard phases call node bin/nemoclaw.js directly, so a regression where install.sh stops installing the nemoclaw shim could go undetected.
    • Recommendation: Either assert command -v nemoclaw after the initial install phase, or document that the installed CLI PATH contract is intentionally owned by another deterministic test and not by this token-rotation migration.
    • Evidence: test/e2e/test-token-rotation.sh checks command -v openshell and command -v nemoclaw after install. The new test checks fs.existsSync(bin/nemoclaw.js), runs install.sh, checks openshell --version, then calls node bin/nemoclaw.js onboard for later phases.
  • High-churn E2E workflow allowlists overlap active migration work (.github/workflows/e2e-vitest-scenarios.yaml:43): This PR updates the free-standing job selector, report job dependencies, and workflow-boundary validator in files that many active E2E migration PRs also touch. The current patch is internally consistent, but these static lists are easy to drift during concurrent migrations.
    • Recommendation: Before landing after other E2E migration PRs, re-check that allowed_jobs, each free-standing job condition, report-to-pr.needs, and validateE2eVitestScenariosWorkflowBoundary() include every active free-standing job exactly once.
    • Evidence: Deterministic drift context listed many open PRs overlapping .github/workflows/e2e-vitest-scenarios.yaml, test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts, and tools/e2e-scenarios/workflow-boundary.mts; this PR adds token-rotation-vitest to those static selector and validator surfaces.
  • Linked issue clauses and comments were not available for literal acceptance mapping: The PR body references Epic: Migrate legacy bash E2E into the Vitest E2E system #5098 and [Feature] Validate bot token rotation #1903, but deterministic linked-issue bodies/comments were not provided. Repo-local legacy comments cover the token-rotation behavior, but literal issue clauses and named comment items could not be extracted or mapped.
  • Fake endpoint workaround needs source-of-truth follow-up (test/e2e-scenario/live/token-rotation.test.ts:418): The replacement documents using a fake OpenAI-compatible endpoint to avoid unrelated NVIDIA endpoint 429s, but the code does not make clear whether this is the permanent hermetic design or a temporary workaround, what coverage owns live endpoint availability, or when the exception can be removed.
    • Recommendation: State the source boundary and removal/ownership condition in code-adjacent documentation, and pair it with runtime assertions that prove the fake provider path was exercised.
    • Evidence: scenario.json documentedException says the replacement uses the legacy-supported fake OpenAI-compatible endpoint path so the guard is not blocked by NVIDIA endpoint 429 rate limits; startFakeOpenAIEndpoint() records requests but no assertion checks them.

🌱 Nice ideas

  • None.
Consider writing more tests for
  • **Runtime validation** — Assert token-rotation fake OpenAI endpoint records a GET /v1/models or /models request during install/onboard.. Static workflow-boundary coverage is strong and the live test covers the main token-rotation behavior, but the fake provider, artifact redaction, and legacy install PATH boundary need behavior-specific runtime validation.
  • **Runtime validation** — Assert token-rotation fake OpenAI endpoint records at least one POST /v1/chat/completions, /chat/completions, /v1/responses, or /responses request during install/onboard.. Static workflow-boundary coverage is strong and the live test covers the main token-rotation behavior, but the fake provider, artifact redaction, and legacy install PATH boundary need behavior-specific runtime validation.
  • **Runtime validation** — Assert token-rotation ShellProbe stdout, stderr, and result JSON artifacts do not contain GITHUB_TOKEN.. Static workflow-boundary coverage is strong and the live test covers the main token-rotation behavior, but the fake provider, artifact redaction, and legacy install PATH boundary need behavior-specific runtime validation.
  • **Runtime validation** — Assert token-rotation ShellProbe stdout, stderr, and result JSON artifacts do not contain COMPATIBLE_API_KEY or fake Telegram, Discord, Slack bot, and Slack app token values.. Static workflow-boundary coverage is strong and the live test covers the main token-rotation behavior, but the fake provider, artifact redaction, and legacy install PATH boundary need behavior-specific runtime validation.
  • **Runtime validation** — Assert install.sh --non-interactive leaves nemoclaw discoverable on PATH, or identify the existing deterministic test that owns that install assertion.. Static workflow-boundary coverage is strong and the live test covers the main token-rotation behavior, but the fake provider, artifact redaction, and legacy install PATH boundary need behavior-specific runtime validation.
  • **Fake OpenAI endpoint contract is still not asserted** — Assert fakeOpenAI.requests contains a GET to /v1/models or /models and at least one POST to /v1/chat/completions, /chat/completions, /v1/responses, or /responses before writing scenario-result.json.
  • **Credential-bearing artifacts are not verified for redaction** — After the secret-bearing phases, assert the generated ShellProbe stdout, stderr, and result JSON files do not contain process.env.GITHUB_TOKEN, COMPATIBLE_API_KEY, or any Telegram, Discord, Slack bot, and Slack app token A/B values.
  • **Acceptance clause:** Linked issue clauses/comments for Refs Epic: Migrate legacy bash E2E into the Vitest E2E system #5098 and Refs [Feature] Validate bot token rotation #1903 — add test evidence or identify existing coverage. Deterministic context provided linkedIssues: [], so issue bodies/comments could not be extracted literally.
Since last review details

Current findings:

  • Source-of-truth review needed: test/e2e-scenario/live/token-rotation.test.ts fake OpenAI-compatible endpoint: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: scenario.json documentedException cites NVIDIA endpoint 429s; startFakeOpenAIEndpoint() records requests; cleanup writes fake-openai-compatible-requests.json.
  • Fake OpenAI endpoint contract is still not asserted (test/e2e-scenario/live/token-rotation.test.ts:93): The test intentionally routes install/onboard through a local OpenAI-compatible endpoint, but it only writes the observed request metadata as a cleanup artifact. A regression where the CLI stops using NEMOCLAW_ENDPOINT_URL, stops listing models, or stops performing inference could still leave the token-rotation assertions passing for the wrong reason.
    • Recommendation: Assert fakeOpenAI.requests contains a GET to /v1/models or /models and at least one POST to /v1/chat/completions, /chat/completions, /v1/responses, or /responses before writing scenario-result.json.
    • Evidence: startFakeOpenAIEndpoint() records { method, path, bodyBytes }, cleanup writes fake-openai-compatible-requests.json, and scenario.json documents the fake endpoint exception, but no expect() reads fakeOpenAI.requests.
  • Credential-bearing artifacts are not verified for redaction (test/e2e-scenario/live/token-rotation.test.ts:255): The token-rotation job runs install/onboard with GITHUB_TOKEN plus fake messaging tokens and uploads ShellProbe artifacts. ShellProbe applies explicit and pattern redaction, but this PR does not add a regression that reads the emitted stdout, stderr, and result JSON artifacts and proves the sensitive values are absent.
    • Recommendation: After the secret-bearing phases, assert the generated ShellProbe stdout, stderr, and result JSON files do not contain process.env.GITHUB_TOKEN, COMPATIBLE_API_KEY, or any Telegram, Discord, Slack bot, and Slack app token A/B values.
    • Evidence: redactionValues() includes token-rotation-compatible-e2e, process.env.NVIDIA_API_KEY, process.env.GITHUB_TOKEN, TOKEN_A, and TOKEN_B; runInstall() and runOnboard() pass those values to host.command(); Upload token rotation artifacts publishes e2e-artifacts/vitest/token-rotation/.
  • Token-rotation job expands the credential-bearing trusted-code boundary (.github/workflows/e2e-vitest-scenarios.yaml:306): The new manual live job checks out repository code, authenticates to Docker Hub, installs dependencies, builds the CLI, and runs Vitest with GITHUB_TOKEN available to the test process. The workflow has good controls, but it still increases the amount of checked-out code that executes with credentials and Docker/OpenShell authority.
    • Recommendation: Keep this job manual/trusted-only and preserve the current boundary controls: workflow_dispatch only, top-level contents: read, full-SHA-pinned actions, checkout persist-credentials: false, npm ci --ignore-scripts, Docker login via --password-stdin, no broad secret env at job level, and workflow-boundary validator coverage for those invariants.
    • Evidence: token-rotation-vitest uses checkout, Docker Hub secrets, npm ci --ignore-scripts, npm run build:cli, and npx vitest test/e2e-scenario/live/token-rotation.test.ts with GITHUB_TOKEN: ${{ github.token }}.
  • Legacy install PATH assertion is not preserved (test/e2e-scenario/live/token-rotation.test.ts:468): The legacy bash test verified both openshell and nemoclaw were discoverable on PATH after install.sh. The Vitest replacement checks openshell --version, but subsequent onboard phases call node bin/nemoclaw.js directly, so a regression where install.sh stops installing the nemoclaw shim could go undetected.
    • Recommendation: Either assert command -v nemoclaw after the initial install phase, or document that the installed CLI PATH contract is intentionally owned by another deterministic test and not by this token-rotation migration.
    • Evidence: test/e2e/test-token-rotation.sh checks command -v openshell and command -v nemoclaw after install. The new test checks fs.existsSync(bin/nemoclaw.js), runs install.sh, checks openshell --version, then calls node bin/nemoclaw.js onboard for later phases.
  • High-churn E2E workflow allowlists overlap active migration work (.github/workflows/e2e-vitest-scenarios.yaml:43): This PR updates the free-standing job selector, report job dependencies, and workflow-boundary validator in files that many active E2E migration PRs also touch. The current patch is internally consistent, but these static lists are easy to drift during concurrent migrations.
    • Recommendation: Before landing after other E2E migration PRs, re-check that allowed_jobs, each free-standing job condition, report-to-pr.needs, and validateE2eVitestScenariosWorkflowBoundary() include every active free-standing job exactly once.
    • Evidence: Deterministic drift context listed many open PRs overlapping .github/workflows/e2e-vitest-scenarios.yaml, test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts, and tools/e2e-scenarios/workflow-boundary.mts; this PR adds token-rotation-vitest to those static selector and validator surfaces.
  • Linked issue clauses and comments were not available for literal acceptance mapping: The PR body references Epic: Migrate legacy bash E2E into the Vitest E2E system #5098 and [Feature] Validate bot token rotation #1903, but deterministic linked-issue bodies/comments were not provided. Repo-local legacy comments cover the token-rotation behavior, but literal issue clauses and named comment items could not be extracted or mapped.
  • Fake endpoint workaround needs source-of-truth follow-up (test/e2e-scenario/live/token-rotation.test.ts:418): The replacement documents using a fake OpenAI-compatible endpoint to avoid unrelated NVIDIA endpoint 429s, but the code does not make clear whether this is the permanent hermetic design or a temporary workaround, what coverage owns live endpoint availability, or when the exception can be removed.
    • Recommendation: State the source boundary and removal/ownership condition in code-adjacent documentation, and pair it with runtime assertions that prove the fake provider path was exercised.
    • Evidence: scenario.json documentedException says the replacement uses the legacy-supported fake OpenAI-compatible endpoint path so the guard is not blocked by NVIDIA endpoint 429 rate limits; startFakeOpenAIEndpoint() records requests but no assertion checks them.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Results — ❌ Some jobs failed

Run: 27355058524
Workflow ref: e2e-migrate/test-token-rotation-simple
Requested scenarios: (default — all supported)
Summary: 1 passed, 1 failed, 4 skipped

Job Result
gateway-guard-recovery ❌ failure
generate-matrix ✅ success
live-scenarios ⏭️ skipped
onboard-negative-paths-vitest ⏭️ skipped
openclaw-tui-chat-correlation-vitest ⏭️ skipped
openshell-version-pin-vitest ⏭️ skipped

Failed jobs: gateway-guard-recovery. Check run artifacts for logs.

@jyaunches jyaunches changed the title test(e2e): migrate token rotation guard test(e2e): migrate test-token-rotation.sh to vitest Jun 11, 2026
@jyaunches jyaunches changed the title test(e2e): migrate test-token-rotation.sh to vitest test(e2e): P1 anchor 4 migrate test-token-rotation.sh to vitest Jun 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Results — ❌ Some jobs failed

Run: 27355314900
Workflow ref: e2e-migrate/test-token-rotation-simple
Requested scenarios: (default — all supported)
Summary: 1 passed, 1 failed, 4 skipped

Job Result
gateway-guard-recovery ❌ failure
generate-matrix ✅ success
live-scenarios ⏭️ skipped
onboard-negative-paths-vitest ⏭️ skipped
openclaw-tui-chat-correlation-vitest ⏭️ skipped
openshell-version-pin-vitest ⏭️ skipped

Failed jobs: gateway-guard-recovery. Check run artifacts for logs.

@jyaunches jyaunches changed the title test(e2e): P1 anchor 4 migrate test-token-rotation.sh to vitest test(e2e): migrate test-token-rotation.sh to vitest Jun 11, 2026
@jyaunches jyaunches changed the title test(e2e): migrate test-token-rotation.sh to vitest test(e2e): migrate test-token-rotation.sh to vitest [ANCHOR-4] Jun 11, 2026
@jyaunches

Copy link
Copy Markdown
Contributor Author

Maintainer simplicity/equivalence review for #5098 — request changes.

This can stay as the token-rotation anchor PR, but please close the contract gaps called out by the advisor.

Required:

  • Restore the legacy sandbox-running assertions after first onboard and after each Telegram/Discord/Slack credential-triggered rebuild/rotation.
  • Clean up or explicitly reset the canonical OpenShell nemoclaw gateway the way the legacy script did, so repeated local/self-hosted runs remain deterministic.
  • Ensure token-rotation-vitest is included in workflow result reporting/validation so dispatch evidence waits for the migrated test.
  • Keep the test focused on token lifecycle/channel secret refresh behavior; avoid shared framework unless a tiny helper is strictly justified.

Goal: keep this as a focused token-rotation migration, but preserve the legacy runtime-state contract and deterministic cleanup.

@cv cv added the v0.0.64 Release target label Jun 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 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/live/token-rotation.test.ts`:
- Around line 28-29: PHASE_TIMEOUT_MS (currently 7 * ONBOARD_TIMEOUT_MS) exceeds
the CI workflow job limit and is never reached; change PHASE_TIMEOUT_MS to be
safely under the job timeout (e.g., set PHASE_TIMEOUT_MS to 40 * 60_000 or
compute from a JOB_WORKFLOW_TIMEOUT_MS = 45 * 60_000 and subtract a small
margin) so the test-level timeout can fire; update the constant definition that
references ONBOARD_TIMEOUT_MS/PHASE_TIMEOUT_MS accordingly.
- Around line 393-427: After the initial runInstall(...) and the
provider/credential checks, add the legacy "sandbox-running" assertion using the
same availability probe mechanism as the other commands: invoke
host.command("openshell", ["<sandbox-running-check>"], { env:
buildAvailabilityProbeEnv(), timeoutMs: ... }) (or the existing test helper used
elsewhere) for SANDBOX_NAME and assert exitCode === 0; do the same after each
credential-triggered rebuild/rotation (i.e., immediately after
expectCredentialHash(...) calls) to restore the legacy contract. Ensure you
reuse buildAvailabilityProbeEnv(), the host.command pattern, and SANDBOX_NAME so
the new assertions follow the same artifact/timeouts as the surrounding checks.
- Around line 428-504: The test is missing post-rotation "sandbox running"
assertions after each credential-triggered rebuild (Telegram, Discord, Slack).
After each rotation block that calls runOnboard/resultText and
expectRotationOutput, add a call to the existing sandbox-running assertion
helper (e.g., assertSandboxRunning or checkSandboxRunning) using the appropriate
artifact name built from SANDBOX_NAME (e.g., `${SANDBOX_NAME}-telegram-bridge`,
`${SANDBOX_NAME}-discord-bridge`, `${SANDBOX_NAME}-slack-bridge` and
`${SANDBOX_NAME}-slack-app`) so each phase verifies the rebuilt sandbox is
actually operational; place these assertions immediately after the corresponding
expectRotationOutput calls (refer to runOnboard, resultText,
expectRotationOutput and SANDBOX_NAME to locate the spots).
- Around line 373-391: The pre- and post-test cleanup in the token-rotation E2E
uses deleteSandboxIfOpenshellExists and host.command to destroy the sandbox but
never destroys the canonical OpenShell gateway ("nemoclaw"); update the cleanup
logic around buildAvailabilityProbeEnv / cleanup.add and the pre-clean
host.command block to run the equivalent openshell gateway destroy -g nemoclaw
(and ensure the same gateway destroy is added to the post-test cleanup in the
cleanup.add callback) so that both pre-clean and post-clean execute the gateway
removal in addition to the existing sandbox deletion (use the same
artifactName/timeout patterns and env like the existing host.command calls
referencing CLI_ENTRYPOINT and SANDBOX_NAME).

In `@tools/e2e-scenarios/workflow-boundary.mts`:
- Around line 255-367: The new validateTokenRotationVitestJob lacks checks that
the selective-dispatch machinery will actually allow this job: update
validateTokenRotationVitestJob to also assert that the repository's
validate-jobs allowlist (the code that validates workflow_dispatch.jobs)
includes "token-rotation-vitest" and that the generate-matrix logic still
accepts/regex-validates JOBS containing "token-rotation-vitest" (i.e. the same
pattern used to gate matrix/job names); locate and call the existing functions
that validate workflow_dispatch job allowlists and JOBS regex (or reuse their
symbol names) from within validateTokenRotationVitestJob to ensure coverage, and
add a mirrored assertion in
test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts so the unit test
suite fails if validate-jobs or generate-matrix stop permitting
token-rotation-vitest.
- Around line 333-345: The loop over token names currently only checks typeof
and non-empty via stringValue(runVitestEnv[tokenName]) which still allows GitHub
expression strings like ${{ secrets.* }} or ${{ vars.* }}; update the guard in
the for loop (where runVitestEnv and tokenName are used and errors.push is
called) to also reject secret/vars expressions by checking the raw string for
patterns like /\$\{\{\s*(secrets|vars)\./ and/or disallow any substring
containing '${{' and require a literal fake token format (e.g. assert it matches
a known fake pattern or prefix) so that any value that is empty, contains a
${{...}} expression, or does not match the expected fake-token pattern triggers
errors.push(`token-rotation-vitest step must set ${tokenName}`).
🪄 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: 60e2489f-91ba-465d-a597-4efbfeae38dc

📥 Commits

Reviewing files that changed from the base of the PR and between 251adde and bcac897.

📒 Files selected for processing (4)
  • .github/workflows/e2e-vitest-scenarios.yaml
  • test/e2e-scenario/live/token-rotation.test.ts
  • test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts
  • tools/e2e-scenarios/workflow-boundary.mts

Comment thread test/e2e-scenario/live/token-rotation.test.ts Outdated
Comment thread test/e2e-scenario/live/token-rotation.test.ts
Comment thread test/e2e-scenario/live/token-rotation.test.ts
Comment thread test/e2e-scenario/live/token-rotation.test.ts
Comment thread tools/e2e-scenarios/workflow-boundary.mts
Comment thread tools/e2e-scenarios/workflow-boundary.mts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts (1)

310-336: ⚡ Quick win

Consider verifying the string replacement succeeded.

The test replaces a specific error message string (lines 319-322) but doesn't verify that the replacement actually occurred. If the workflow format changes and the original string isn't found, workflow.replace() returns the unchanged string, and the test might fail with confusing output or pass incorrectly.

🛡️ Optional: Add replacement verification
     const workflow = fs.readFileSync(
       path.join(process.cwd(), ".github/workflows/e2e-vitest-scenarios.yaml"),
       "utf8",
     );
-    fs.writeFileSync(
-      workflowPath,
-      workflow.replace(
+    const searchString = 'echo "::error::Invalid jobs input; use comma-separated job ids" >&2\n            exit 1\n          fi\n          matrix=';
+    const replacementString = 'echo "::error::Invalid jobs input: ${JOBS}" >&2\n            exit 1\n          fi\n          matrix=';
+    const modifiedWorkflow = workflow.replace(searchString, replacementString);
+    
+    if (modifiedWorkflow === workflow) {
+      throw new Error(`Test fixture outdated: expected string not found in workflow:\n${searchString}`);
+    }
+    
+    fs.writeFileSync(
+      workflowPath,
+      modifiedWorkflow,
-        'echo "::error::Invalid jobs input; use comma-separated job ids" >&2\n            exit 1\n          fi\n          matrix=',
-        'echo "::error::Invalid jobs input: ${JOBS}" >&2\n            exit 1\n          fi\n          matrix=',
-      ),
     );
🤖 Prompt for 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.

In `@test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts` around lines
310 - 336, The test "rejects raw jobs selector echo from matrix generation"
currently calls workflow.replace(...) and writes the result but never verifies
the replacement succeeded; update the test to assert the replacement occurred
before calling validateE2eVitestScenariosWorkflowBoundary by comparing the
original workflow string (variable workflow) with the replaced string (use a new
variable, e.g. replacedWorkflow) or by checking replacedWorkflow.includes('echo
"::error::Invalid jobs input: ${JOBS}"') and fail the test (throw or expect) if
the replacement didn't occur; ensure you then write replacedWorkflow to
workflowPath and keep the call to validateE2eVitestScenariosWorkflowBoundary.
🤖 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.

Nitpick comments:
In `@test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts`:
- Around line 310-336: The test "rejects raw jobs selector echo from matrix
generation" currently calls workflow.replace(...) and writes the result but
never verifies the replacement succeeded; update the test to assert the
replacement occurred before calling validateE2eVitestScenariosWorkflowBoundary
by comparing the original workflow string (variable workflow) with the replaced
string (use a new variable, e.g. replacedWorkflow) or by checking
replacedWorkflow.includes('echo "::error::Invalid jobs input: ${JOBS}"') and
fail the test (throw or expect) if the replacement didn't occur; ensure you then
write replacedWorkflow to workflowPath and keep the call to
validateE2eVitestScenariosWorkflowBoundary.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 92b06b3f-d76c-4537-82d6-ed371cbe9164

📥 Commits

Reviewing files that changed from the base of the PR and between d852446 and 06dfdf8.

📒 Files selected for processing (4)
  • .github/workflows/e2e-vitest-scenarios.yaml
  • test/e2e-scenario/live/token-rotation.test.ts
  • test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts
  • tools/e2e-scenarios/workflow-boundary.mts
🚧 Files skipped from review as they are similar to previous changes (3)
  • .github/workflows/e2e-vitest-scenarios.yaml
  • tools/e2e-scenarios/workflow-boundary.mts
  • test/e2e-scenario/live/token-rotation.test.ts

@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Results — ❌ Some jobs failed

Run: 27365832382
Workflow ref: e2e-migrate/test-token-rotation-simple
Requested scenarios: (default — all supported)
Requested jobs: (default — all free-standing when no scenarios are requested)
Summary: 4 passed, 4 failed, 0 skipped

Job Result
gateway-guard-recovery ❌ failure
generate-matrix ✅ success
live-scenarios ❌ failure
onboard-negative-paths-vitest ✅ success
openclaw-tui-chat-correlation-vitest ❌ failure
openshell-version-pin-vitest ✅ success
token-rotation-vitest ❌ failure
validate-jobs ✅ success

Failed jobs: gateway-guard-recovery, live-scenarios, openclaw-tui-chat-correlation-vitest, token-rotation-vitest. Check run artifacts for logs.

@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Results — ❌ Some jobs failed

Run: 27367271257
Workflow ref: e2e-migrate/test-token-rotation-simple
Requested scenarios: (default — all supported)
Requested jobs: (default — all free-standing when no scenarios are requested)
Summary: 6 passed, 2 failed, 0 skipped

Job Result
gateway-guard-recovery ❌ failure
generate-matrix ✅ success
live-scenarios ✅ success
onboard-negative-paths-vitest ✅ success
openclaw-tui-chat-correlation-vitest ❌ failure
openshell-version-pin-vitest ✅ success
token-rotation-vitest ✅ success
validate-jobs ✅ success

Failed jobs: gateway-guard-recovery, openclaw-tui-chat-correlation-vitest. Check run artifacts for logs.

@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Results — ❌ Some jobs failed

Run: 27370677905
Workflow ref: e2e-migrate/test-token-rotation-simple
Requested scenarios: (default — all supported)
Requested jobs: (default — all free-standing when no scenarios are requested)
Summary: 5 passed, 3 failed, 0 skipped

Job Result
gateway-guard-recovery ❌ failure
generate-matrix ✅ success
live-scenarios ❌ failure
onboard-negative-paths-vitest ✅ success
openclaw-tui-chat-correlation-vitest ❌ failure
openshell-version-pin-vitest ✅ success
token-rotation-vitest ✅ success
validate-jobs ✅ success

Failed jobs: gateway-guard-recovery, live-scenarios, openclaw-tui-chat-correlation-vitest. Check run artifacts for logs.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Results — ❌ Some jobs failed

Run: 27370677905
Workflow ref: e2e-migrate/test-token-rotation-simple
Requested scenarios: (default — all supported)
Requested jobs: (default — all free-standing when no scenarios are requested)
Summary: 5 passed, 3 failed, 0 skipped

Job Result
gateway-guard-recovery ❌ failure
generate-matrix ✅ success
live-scenarios ❌ failure
onboard-negative-paths-vitest ✅ success
openclaw-tui-chat-correlation-vitest ❌ failure
openshell-version-pin-vitest ✅ success
token-rotation-vitest ✅ success
validate-jobs ✅ success

Failed jobs: gateway-guard-recovery, live-scenarios, openclaw-tui-chat-correlation-vitest. Check run artifacts for logs.

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Normal PR checks are green, review feedback is addressed, unresolved threads are clear, and token-rotation-vitest passed. The remaining full scenario fan-out failures appear tied to unstable third-party NVIDIA inference endpoint validation rather than this PR.

@jyaunches jyaunches merged commit 11681ea into main Jun 11, 2026
51 of 58 checks passed
@jyaunches jyaunches deleted the e2e-migrate/test-token-rotation-simple branch June 11, 2026 20:10
@wscurran wscurran added area: e2e End-to-end tests, nightly failures, or validation infrastructure refactor PR restructures code without intended behavior change labels Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: e2e End-to-end tests, nightly failures, or validation infrastructure refactor PR restructures code without intended behavior change v0.0.64 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants