diff --git a/gitnexus/src/cli/i18n/en.ts b/gitnexus/src/cli/i18n/en.ts index dfa5ec3c6..cef84f8d3 100644 --- a/gitnexus/src/cli/i18n/en.ts +++ b/gitnexus/src/cli/i18n/en.ts @@ -167,8 +167,9 @@ export const en = { 'help.option.ciSetup.ci': 'CI/CD system: github-actions, azure-devops, or both', 'help.option.ciSetup.deploy': 'Deploy target: docker, azure-container-app, or both', 'help.option.ciSetup.port': 'Host port to bind (container always runs on 4747)', - 'help.option.ciSetup.auth': 'Auth mode: token (Caddy proxy) or none', - 'help.option.ciSetup.branchStrategy': 'Index strategy: pr-scoped or main-only', + 'help.option.ciSetup.auth': 'Auth mode: token (Caddy proxy) or none (defaults to token)', + 'help.option.ciSetup.branchStrategy': + 'Index strategy: pr-scoped or main-only (defaults to pr-scoped)', 'help.option.ciSetup.dryRun': 'Print generated files without writing (default when no mode flag given)', 'help.option.ciSetup.apply': 'Write files with per-file confirmation gates', diff --git a/gitnexus/src/cli/i18n/zh-CN.ts b/gitnexus/src/cli/i18n/zh-CN.ts index 612ae8156..2d5794bc2 100644 --- a/gitnexus/src/cli/i18n/zh-CN.ts +++ b/gitnexus/src/cli/i18n/zh-CN.ts @@ -159,8 +159,8 @@ export const zhCN = { 'help.option.ciSetup.ci': 'CI/CD 系统:github-actions、azure-devops 或 both', 'help.option.ciSetup.deploy': '部署目标:docker、azure-container-app 或 both', 'help.option.ciSetup.port': '绑定的主机端口(容器始终运行在 4747)', - 'help.option.ciSetup.auth': '认证模式:token(Caddy 代理)或 none', - 'help.option.ciSetup.branchStrategy': '索引策略:pr-scoped 或 main-only', + 'help.option.ciSetup.auth': '认证模式:token(Caddy 代理)或 none(默认 token)', + 'help.option.ciSetup.branchStrategy': '索引策略:pr-scoped 或 main-only(默认 pr-scoped)', 'help.option.ciSetup.dryRun': '打印生成的文件而不写入(未指定模式标志时的默认行为)', 'help.option.ciSetup.apply': '写入文件,每个文件有独立确认步骤', 'help.option.ciSetup.yes': '跳过逐文件确认提示(与 --apply 配合使用)', diff --git a/gitnexus/src/cli/index.ts b/gitnexus/src/cli/index.ts index f02c15dab..c96adaccf 100644 --- a/gitnexus/src/cli/index.ts +++ b/gitnexus/src/cli/index.ts @@ -58,8 +58,8 @@ program .option('--ci ', 'CI/CD system: github-actions, azure-devops, or both') .option('--deploy ', 'Deploy target: docker, azure-container-app, or both') .option('--port ', 'gitnexus serve port', '4747') - .option('--auth ', 'Auth mode: token (Caddy proxy) or none', 'token') - .option('--branch-strategy ', 'Index strategy: pr-scoped or main-only', 'pr-scoped') + .option('--auth ', 'Auth mode: token (Caddy proxy) or none') + .option('--branch-strategy ', 'Index strategy: pr-scoped or main-only') .option('--dry-run', 'Print generated files without writing (default when no mode flag given)') .option('--apply', 'Write files with per-file confirmation gates') .option('--yes', 'Skip per-file confirmation prompts (use with --apply)') diff --git a/gitnexus/test/unit/ci-setup.test.ts b/gitnexus/test/unit/ci-setup.test.ts index 7b653b6d5..f51c83735 100644 --- a/gitnexus/test/unit/ci-setup.test.ts +++ b/gitnexus/test/unit/ci-setup.test.ts @@ -1,4 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { select } from '@inquirer/prompts'; import fs from 'fs/promises'; import os from 'os'; import path from 'path'; @@ -188,3 +189,48 @@ describe('ciSetupCommand', () => { expect(entries).toHaveLength(0); }); }); + +describe('resolveOptions (U1: interactive prompts reachable)', () => { + const detect = { + gitRoot: '/tmp/repo', + detectedCi: null, + hasDocker: false, + portAvailable: true, + primaryLanguage: 'TypeScript', + }; + let originalTTY: boolean | undefined; + + beforeEach(() => { + vi.clearAllMocks(); + originalTTY = process.stdin.isTTY; + }); + + afterEach(() => { + Object.defineProperty(process.stdin, 'isTTY', { value: originalTTY, configurable: true }); + }); + + it('TTY with no auth/branch flags prompts for them (prompts are not dead code)', async () => { + Object.defineProperty(process.stdin, 'isTTY', { value: true, configurable: true }); + const { resolveOptions } = await import('../../src/cli/ci-setup/prompts.js'); + await resolveOptions(detect, { dryRun: true }); + // select() is the prompt primitive for all four questions; reaching it proves + // promptAuth/promptBranchStrategy are no longer short-circuited by a commander default. + expect(vi.mocked(select)).toHaveBeenCalled(); + }); + + it('non-TTY falls back to token/pr-scoped without prompting', async () => { + Object.defineProperty(process.stdin, 'isTTY', { value: false, configurable: true }); + const { resolveOptions } = await import('../../src/cli/ci-setup/prompts.js'); + const resolved = await resolveOptions(detect, { dryRun: true }); + expect(resolved.auth).toBe('token'); + expect(resolved.branchStrategy).toBe('pr-scoped'); + expect(vi.mocked(select)).not.toHaveBeenCalled(); + }); + + it('explicit auth flag wins over the prompt', async () => { + Object.defineProperty(process.stdin, 'isTTY', { value: true, configurable: true }); + const { resolveOptions } = await import('../../src/cli/ci-setup/prompts.js'); + const resolved = await resolveOptions(detect, { auth: 'none', dryRun: true }); + expect(resolved.auth).toBe('none'); + }); +});