-
Notifications
You must be signed in to change notification settings - Fork 1k
fix(cli): respect --no-interactive flag in validate command #395
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The validate command's spinner was starting regardless of the --no-interactive flag, causing hangs in pre-commit hooks. Changes: - Pass noInteractive option to runBulkValidation - Handle Commander.js --no-* flag syntax (sets interactive=false) - Only start ora spinner when in interactive mode - Add CI environment variable check to isInteractive() for industry standard compliance
WalkthroughAdds CLI handling for --no-interactive via a new resolveNoInteractive export; threads a noInteractive flag into ValidateCommand.runBulkValidation and spinner logic; isInteractive now short-circuits to non-interactive when CI env is detected. Tests added for CLI flag and interactive utilities. Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as CLI (commander)
participant Validate as ValidateCommand
participant Utils as interactive utils
participant Spinner as Spinner/Renderer
CLI->>Validate: parse options (includes --no-interactive / interactive)
Validate->>Utils: resolveNoInteractive(options, env)
note right of Utils `#f8f3d7`: resolveNoInteractive\nchecks explicit flags,\nOPEN_SPEC_INTERACTIVE,\nCI, stdin.isTTY
Utils-->>Validate: boolean noInteractive
Validate->>Validate: decide bulk run path
alt noInteractive or json
Validate->>Spinner: suppress spinner rendering
Spinner-->>Validate: no spinner shown
else interactive allowed
Validate->>Spinner: show spinner during bulk validation
Spinner-->>Validate: spinner updates
end
Validate->>Validate: runBulkValidation(..., noInteractive)
Validate-->>CLI: exit code / output
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Export resolveNoInteractive() helper for reuse - Add InteractiveOptions type export for testing - Refactor validate.ts to use resolveNoInteractive() - Add 17 unit tests for isInteractive() and resolveNoInteractive() - Add CLI integration test for --no-interactive flag This prevents future regressions where Commander.js --no-* flag parsing is not properly handled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
test/utils/interactive.test.ts (1)
40-80: Comprehensive test coverage for resolveNoInteractive.The tests cover all input shapes (object with noInteractive/interactive, boolean, undefined) and correctly verify the OR logic.
Optional: Clarify the "prioritize" comment
The comment at line 74 says "should prioritize noInteractive over interactive when both set," but the function uses OR logic (
noInteractive === true || interactive === false), so both test cases returntrue. Consider rephrasing:- it('should prioritize noInteractive over interactive when both set', () => { - // noInteractive: true should win + it('should return true when either condition for non-interactive is met', () => { + // Either noInteractive: true OR interactive: false triggers non-interactive mode expect(resolveNoInteractive({ noInteractive: true, interactive: true })).toBe(true); - // If noInteractive is false, check interactive expect(resolveNoInteractive({ noInteractive: false, interactive: false })).toBe(true); });The current assertions are correct; this just clarifies the intent.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/commands/validate.tssrc/utils/interactive.tstest/commands/validate.test.tstest/utils/interactive.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/utils/interactive.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Run `openspec validate [change-id] --strict` before requesting approval
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Run `openspec validate [change-id] --strict` before requesting approval
Applied to files:
src/commands/validate.ts
🧬 Code graph analysis (3)
test/commands/validate.test.ts (1)
test/helpers/run-cli.ts (1)
runCLI(75-137)
test/utils/interactive.test.ts (1)
src/utils/interactive.ts (2)
resolveNoInteractive(17-20)isInteractive(22-28)
src/commands/validate.ts (1)
src/utils/interactive.ts (1)
resolveNoInteractive(17-20)
🔇 Additional comments (7)
test/commands/validate.test.ts (1)
134-146: LGTM! Excellent test coverage for the CLI flag.The test correctly verifies that
--no-interactiveprevents the command from hanging and prompting. The comment explaining Commander.js behavior is helpful, and explicitly unsettingOPEN_SPEC_INTERACTIVEensures the test validates the flag itself rather than environment-derived behavior.test/utils/interactive.test.ts (2)
1-38: LGTM! Clean environment isolation.The setup and teardown properly preserve and restore environment variables and
stdin.isTTY, ensuring test isolation.
82-124: LGTM! Thorough coverage of isInteractive behavior.The tests validate all the short-circuit conditions (explicit flags,
OPEN_SPEC_INTERACTIVE,CIenv var,stdin.isTTY) and confirm the fallback to TTY detection.src/commands/validate.ts (4)
4-4: LGTM! Correct import for the fix.
18-18: LGTM! Matches Commander.js --no- convention.*The comment correctly documents that Commander.js sets
interactive = false(notnoInteractive = true) for the--no-interactiveflag.
39-39: LGTM! Correctly threads noInteractive into bulk validation.Using
resolveNoInteractive(options)properly handles both Commander.js style (interactive: false) and direct noInteractive flags.
184-185: LGTM! Spinner is correctly gated for non-interactive mode.The spinner only starts when both conditions are met:
- Not in JSON output mode
- Not in non-interactive mode
This prevents the hang reported in pre-commit hooks. All subsequent spinner usages (lines 217, 250, 272) safely handle
undefinedvia optional chaining or conditionals.
* feat(cli): add openspec config command for global configuration management (Fission-AI#382) * feat(cli): add openspec config command for global configuration management Implements the `openspec config` command with subcommands: - `path`: Show config file location - `list [--json]`: Show all current settings - `get <key>`: Get a specific value (raw output for scripting) - `set <key> <value> [--string]`: Set a value with auto type coercion - `unset <key>`: Remove a key (revert to default) - `reset --all [-y]`: Reset configuration to defaults - `edit`: Open config in $EDITOR/$VISUAL Key features: - Dot notation for nested key access (e.g., featureFlags.someFlag) - Auto type coercion (true/false → boolean, numbers → number) - --string flag to force string storage - Zod schema validation with unknown field passthrough - Reserved --scope flag for future project-local config - Windows-compatible editor spawning with proper path quoting - Shell completion registry integration * test(config): add additional unit tests for validation and coercion - Add tests for unknown fields with various types - Add test to verify error message path for featureFlags - Add test for number values rejection in featureFlags - Add config set simulation tests to verify full coerce → set → validate flow * fix(config): avoid shell parsing in config edit to handle paths with spaces Use spawn with shell: false and pass configPath as an argument instead of building a shell command string. This correctly handles spaces in both the EDITOR path and config file path on all platforms. * chore(openspec): archive add-config-command and create cli-config spec Move completed change to archive and apply spec deltas to create the cli-config specification documenting the config command interface. * Validate config keys on set * Add changeset for config command and shell completions (Fission-AI#388) * chore(release): version packages (Fission-AI#389) * Version Packages * chore: trigger CI --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tabish Bidiwale <[email protected]> * feat(ci): migrate to npm OIDC trusted publishing (Fission-AI#390) Replace classic npm token authentication with OIDC trusted publishing: - Add `id-token: write` permission for OIDC token generation - Upgrade to Node 24 (includes npm 11.5.1+ required for OIDC) - Remove NPM_TOKEN/NODE_AUTH_TOKEN env vars (OIDC replaces them) This eliminates the need for rotating npm access tokens and provides cryptographically verified publisher identity with automatic provenance attestation. Requires configuring trusted publisher on npmjs.com: - Organization: Fission-AI - Repository: OpenSpec - Workflow: release-prepare.yml * fix(cli): use dynamic import for @inquirer/prompts in config command (Fission-AI#392) * fix(cli): use dynamic import for @inquirer/prompts in config command The config command (added in Fission-AI#382) reintroduced the pre-commit hook hang issue that was fixed in Fission-AI#380. The static import of @inquirer/prompts at module load time causes stdin event listeners to be registered even when running non-interactive commands, preventing clean process exit when stdin is piped (as pre-commit does). Convert the static import to a dynamic import that only loads inquirer when the `config reset` command is actually used interactively. Fixes Fission-AI#367 * chore: add ESLint with no-restricted-imports rule for @InQuirer Add ESLint configuration that prevents static imports of @inquirer/* modules. This prevents future regressions of the pre-commit hook hang issue fixed in this PR. The rule shows a helpful error message pointing to issue Fission-AI#367 for context. init.ts is exempted since it's already dynamically imported from the CLI. * ci: add ESLint step to lint job Run `pnpm lint` in CI to enforce the no-restricted-imports rule that prevents static @InQuirer imports. * Add changeset for config command dynamic import fix (Fission-AI#393) * chore(release): version packages (Fission-AI#394) * Version Packages * chore: trigger CI --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tabish Bidiwale <[email protected]> * fix(cli): respect --no-interactive flag in validate command (Fission-AI#395) * fix(cli): respect --no-interactive flag in validate command The validate command's spinner was starting regardless of the --no-interactive flag, causing hangs in pre-commit hooks. Changes: - Pass noInteractive option to runBulkValidation - Handle Commander.js --no-* flag syntax (sets interactive=false) - Only start ora spinner when in interactive mode - Add CI environment variable check to isInteractive() for industry standard compliance * test: add unit tests for interactive utilities and CLI flag - Export resolveNoInteractive() helper for reuse - Add InteractiveOptions type export for testing - Refactor validate.ts to use resolveNoInteractive() - Add 17 unit tests for isInteractive() and resolveNoInteractive() - Add CLI integration test for --no-interactive flag This prevents future regressions where Commander.js --no-* flag parsing is not properly handled. * Add changeset for --no-interactive flag fix (Fission-AI#396) * chore(release): version packages (Fission-AI#397) * Version Packages * chore: trigger CI --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tabish Bidiwale <[email protected]> * docs: add artifact POC analysis document (Fission-AI#398) Add internal documentation for the artifact-based approach to OpenSpec core. This document outlines design decisions, terminology, and the philosophy behind treating dependencies as enablers rather than gates. * fix(archive): allow REMOVED requirements when creating new spec files (Fission-AI#403) (Fission-AI#404) When creating a new spec file, REMOVED requirements are now ignored with a warning instead of causing archive to fail. This enables refactoring scenarios where old fields are removed while documenting a capability for the first time. Fixes Fission-AI#403 --------- Co-authored-by: Tabish Bidiwale <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tabish Bidiwale <[email protected]> Co-authored-by: Eunsong-Park <[email protected]>
…AI#395) * fix(cli): respect --no-interactive flag in validate command The validate command's spinner was starting regardless of the --no-interactive flag, causing hangs in pre-commit hooks. Changes: - Pass noInteractive option to runBulkValidation - Handle Commander.js --no-* flag syntax (sets interactive=false) - Only start ora spinner when in interactive mode - Add CI environment variable check to isInteractive() for industry standard compliance * test: add unit tests for interactive utilities and CLI flag - Export resolveNoInteractive() helper for reuse - Add InteractiveOptions type export for testing - Refactor validate.ts to use resolveNoInteractive() - Add 17 unit tests for isInteractive() and resolveNoInteractive() - Add CLI integration test for --no-interactive flag This prevents future regressions where Commander.js --no-* flag parsing is not properly handled.
…AI#395) * fix(cli): respect --no-interactive flag in validate command The validate command's spinner was starting regardless of the --no-interactive flag, causing hangs in pre-commit hooks. Changes: - Pass noInteractive option to runBulkValidation - Handle Commander.js --no-* flag syntax (sets interactive=false) - Only start ora spinner when in interactive mode - Add CI environment variable check to isInteractive() for industry standard compliance * test: add unit tests for interactive utilities and CLI flag - Export resolveNoInteractive() helper for reuse - Add InteractiveOptions type export for testing - Refactor validate.ts to use resolveNoInteractive() - Add 17 unit tests for isInteractive() and resolveNoInteractive() - Add CLI integration test for --no-interactive flag This prevents future regressions where Commander.js --no-* flag parsing is not properly handled.
Summary
--no-interactiveflag--no-*flag syntax (setsinteractive=false, notnoInteractive=true)CIenvironment variable check for industry standard complianceRoot Cause
When using
--no-interactive, Commander.js setsoptions.interactive = false, NOToptions.noInteractive = true. TherunBulkValidationmethod was:--jsonflag)Test plan
openspec validate --specs --strict --no-interactivedirectly - completes without hangingpre-commit run openspec-validate -a- completes without hanging🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.