project-auto-wizard 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.js CHANGED
@@ -20,6 +20,9 @@ import { runVersion } from "./commands/version.js";
20
20
  import { runWorkflows } from "./commands/workflows.js";
21
21
  import { runRevert } from "./commands/revert.js";
22
22
  import { runInteractive } from "./commands/interactive.js";
23
+ import { runStatus, printStatus } from "./commands/status.js";
24
+ import { runDoctor, printDoctorReport } from "./commands/doctor.js";
25
+ import { planDryRun, printDryRun } from "./commands/dry-run.js";
23
26
 
24
27
  // 패키지 버전 읽기 (-v/--version 출력용). src/../package.json.
25
28
  function readPkgVersion() {
@@ -58,6 +61,11 @@ export async function run(argv, { cwd = process.cwd(), payloadRoot, clock } = {}
58
61
 
59
62
  // 대화형 모드 — 인자 없이 실행 or --mode interactive
60
63
  if (opts.mode === "interactive") {
64
+ // --dry-run은 대화형 모드에서 조용히 무시되면 안 됨(실제 설치가 진행돼버림) — 명시 에러로 차단.
65
+ if (opts.dryRun) {
66
+ console.error("--dry-run은 --mode <full|version|workflows|revert>와 함께 사용하세요 (대화형 모드에서는 지원하지 않습니다).");
67
+ return 1;
68
+ }
61
69
  if (!process.stdout.isTTY) {
62
70
  console.error("대화형 입력이 불가능한 환경입니다. --mode <full|version|workflows|revert> 와 --force 를 지정하세요.");
63
71
  return 1;
@@ -67,17 +75,33 @@ export async function run(argv, { cwd = process.cwd(), payloadRoot, clock } = {}
67
75
 
68
76
  // revert 모드 — payload 유래 파일 제거 (감지·질문 불필요, --force 게이트만)
69
77
  if (opts.mode === "revert") {
70
- if (!opts.force && !process.stdout.isTTY) {
78
+ // --dry-run은 파일을 쓰지 않으므로 --force 게이트를 우회한다 (status/doctor와 동일한 안전성).
79
+ if (!opts.force && !opts.dryRun && !process.stdout.isTTY) {
71
80
  console.error("비대화형 환경에서는 --force 옵션이 필요합니다.");
72
81
  return 1;
73
82
  }
83
+ if (opts.dryRun) {
84
+ printDryRun(planDryRun("revert", {}, payload, cwd));
85
+ return 0;
86
+ }
74
87
  const r = runRevert({}, payload, cwd);
75
88
  console.error(`제거됨 — 워크플로우 ${r.workflows.length}개, 스크립트 ${r.scripts.length}개${r.coderabbit ? ", .coderabbit.yaml" : ""}`);
76
89
  console.error("version.yml·README·.gitignore는 보존됩니다 (사용자 데이터).");
77
90
  return 0;
78
91
  }
92
+ // status 모드 — 읽기 전용, TTY/--force 무관하게 항상 동작
93
+ if (opts.mode === "status") {
94
+ printStatus(runStatus(payload, cwd));
95
+ return 0;
96
+ }
97
+ // doctor 모드 — 읽기 전용, TTY/--force 무관하게 항상 동작
98
+ if (opts.mode === "doctor") {
99
+ printDoctorReport(runDoctor(cwd));
100
+ return 0;
101
+ }
79
102
  // 명시 모드인데 --force 없으면 (비대화형 CLI는 --force 필요)
80
- if (!opts.force && !process.stdout.isTTY) {
103
+ // --dry-run은 파일을 쓰지 않으므로 --force 게이트를 우회한다 (status/doctor와 동일한 안전성).
104
+ if (!opts.force && !opts.dryRun && !process.stdout.isTTY) {
81
105
  console.error("비대화형 환경에서는 --force 옵션이 필요합니다.");
82
106
  return 1;
83
107
  }
@@ -107,7 +131,7 @@ export async function run(argv, { cwd = process.cwd(), payloadRoot, clock } = {}
107
131
  });
108
132
  // pr-flow에서 develop이 원격에 없으면 자동 생성+push (--force 비대화형 — 질문 없음).
109
133
  // 원격 목록을 못 읽는 환경(git 없음·origin 없음)은 remoteBranches=[]지만 push 실패를 조용히 보고.
110
- if (branches.mode === "pr-flow") {
134
+ if (branches.mode === "pr-flow" && !opts.dryRun) {
111
135
  const remoteBranches = await detectRemoteBranches(cwd);
112
136
  if (remoteBranches.length && !remoteBranches.includes(branches.develop)) {
113
137
  await ensureDevelopBranch({
@@ -127,6 +151,10 @@ export async function run(argv, { cwd = process.cwd(), payloadRoot, clock } = {}
127
151
  includeNexus: opts.includeNexus ?? existing?.options?.nexus ?? false,
128
152
  includeSecretBackup: opts.includeSecretBackup ?? existing?.options?.secretBackup ?? false,
129
153
  includeCodeRabbit: opts.includeCodeRabbit ?? existing?.options?.coderabbit ?? false,
154
+ // 기존 version.yml이 있는데 semver_auto 키가 아예 없었던 경우(신규 기능 추가 이전 설치·
155
+ // workflows-only 재실행) 조용히 true로 켜지면 애매한 커밋 하나로 major가 승격될 위험이 있다 —
156
+ // 기존 설치는 false로 안전하게 폴백, 완전 신규 설치만 true(기존 설계) 유지.
157
+ includeSemverAuto: opts.includeSemverAuto ?? existing?.options?.semverAuto ?? (existing ? false : true),
130
158
  repoName,
131
159
  // 실 resolver 4종 (.sh resolve_token 등가)
132
160
  resolvers: makeResolvers(cwd, repoName, paths),
@@ -142,6 +170,11 @@ export async function run(argv, { cwd = process.cwd(), payloadRoot, clock } = {}
142
170
  const proceed = await runBreakingCheck({ cwd, payloadRoot: payload, templateVersion: context.templateVersion });
143
171
  if (!proceed) return 0;
144
172
 
173
+ if (opts.dryRun) {
174
+ printDryRun(planDryRun(opts.mode, context, payload, cwd));
175
+ return 0;
176
+ }
177
+
145
178
  let result = null;
146
179
  switch (opts.mode) {
147
180
  case "full": result = runFull(context, payload, cwd); break;