project-auto-wizard 0.12.2 → 0.13.1

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.
Files changed (91) hide show
  1. package/README.ja.md +165 -0
  2. package/README.ko.md +165 -0
  3. package/README.md +107 -286
  4. package/README.zh-CN.md +165 -0
  5. package/bin/project-auto-wizard.js +1 -2
  6. package/package.json +9 -3
  7. package/payload/config/breaking-changes.json +24 -0
  8. package/payload/config/wizard-prompts.yml +45 -0
  9. package/payload/scripts/changelog_manager.py +141 -46
  10. package/payload/scripts/issue_helper.py +34 -5
  11. package/payload/scripts/version_manager.py +482 -107
  12. package/payload/version.yml.template +5 -2
  13. package/payload/workflows/common/PROJECT-COMMON-AI-PR-SUMMARY.yaml +39 -9
  14. package/payload/workflows/common/PROJECT-COMMON-AUTO-CHANGELOG-CONTROL.yaml +165 -38
  15. package/payload/workflows/common/PROJECT-COMMON-README-VERSION-UPDATE.yaml +14 -5
  16. package/payload/workflows/common/PROJECT-COMMON-RELEASE-PUBLISH.yaml +220 -6
  17. package/payload/workflows/common/PROJECT-COMMON-VERSION-CONTROL.yaml +89 -3
  18. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-FIREBASE-CICD.yaml +78 -16
  19. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +72 -16
  20. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-SELFHOSTED-CICD.yaml +62 -20
  21. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +51 -13
  22. package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +75 -11
  23. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +52 -3
  24. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TESTFLIGHT.yaml +60 -11
  25. package/payload/workflows/go/PROJECT-GO-CI.yaml +10 -1
  26. package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +148 -28
  27. package/payload/workflows/go/PROJECT-GO-SIMPLE-CICD.yaml +45 -4
  28. package/payload/workflows/next/PROJECT-NEXT-CI.yaml +25 -3
  29. package/payload/workflows/next/PROJECT-NEXT-CICD.yaml +83 -9
  30. package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +70 -6
  31. package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +148 -28
  32. package/payload/workflows/python/PROJECT-PYTHON-SIMPLE-CICD.yaml +45 -4
  33. package/payload/workflows/react/PROJECT-REACT-CI.yaml +25 -3
  34. package/payload/workflows/react/PROJECT-REACT-CICD.yaml +84 -10
  35. package/payload/workflows/spring/PROJECT-SPRING-CI.yml +13 -3
  36. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-NGINX-CICD.yaml +47 -5
  37. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-TRAEFIK-CICD.yaml +47 -5
  38. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +153 -30
  39. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-SIMPLE-CICD.yaml +47 -5
  40. package/src/cli/args.js +33 -24
  41. package/src/cli/help.js +16 -4
  42. package/src/commands/doctor.js +26 -60
  43. package/src/commands/dry-run.js +59 -5
  44. package/src/commands/full.js +135 -55
  45. package/src/commands/install-settings.js +51 -0
  46. package/src/commands/interactive-flutter.js +1 -1
  47. package/src/commands/interactive.js +135 -69
  48. package/src/commands/purge.js +50 -21
  49. package/src/commands/status.js +18 -12
  50. package/src/commands/uninstall.js +22 -22
  51. package/src/context.js +5 -5
  52. package/src/core/baseline.js +20 -5
  53. package/src/core/branches.js +19 -1
  54. package/src/core/branding.js +1 -1
  55. package/src/core/breaking-check.js +14 -19
  56. package/src/core/breaking.js +7 -3
  57. package/src/core/copy/app-files.js +28 -0
  58. package/src/core/copy/gitignore.js +20 -12
  59. package/src/core/copy/readme.js +24 -5
  60. package/src/core/copy/simple.js +52 -13
  61. package/src/core/copy/workflows.js +133 -111
  62. package/src/core/deploy-style.js +83 -11
  63. package/src/core/detect-fs.js +127 -24
  64. package/src/core/detect.js +177 -47
  65. package/src/core/errors.js +3 -0
  66. package/src/core/flutter-doctor.js +49 -0
  67. package/src/core/flutter-hooks.js +29 -0
  68. package/src/core/flutter-options.js +4 -3
  69. package/src/core/fsutil.js +23 -6
  70. package/src/core/logger.js +55 -19
  71. package/src/core/paths-resolve.js +50 -47
  72. package/src/core/paths.js +26 -1
  73. package/src/core/release-options.js +23 -0
  74. package/src/core/removal-exec.js +67 -0
  75. package/src/core/removal-plan.js +75 -19
  76. package/src/core/types.js +136 -0
  77. package/src/core/verify.js +85 -19
  78. package/src/core/version-yml.js +42 -8
  79. package/src/core/wizard-env.js +21 -14
  80. package/src/core/wizard-labels.js +34 -25
  81. package/src/index.js +128 -60
  82. package/src/ui/ansi.js +3 -1
  83. package/src/ui/banner.js +12 -8
  84. package/src/ui/env-plan.js +68 -44
  85. package/src/ui/prompts.js +22 -12
  86. package/src/ui/readline-engine.js +109 -22
  87. package/src/ui/status-cards.js +10 -5
  88. package/src/ui/summary.js +71 -33
  89. package/payload/scripts/__pycache__/changelog_manager.cpython-314.pyc +0 -0
  90. package/payload/scripts/__pycache__/issue_helper.cpython-314.pyc +0 -0
  91. package/payload/scripts/__pycache__/version_manager.cpython-314.pyc +0 -0
package/src/ui/summary.js CHANGED
@@ -1,16 +1,24 @@
1
- // 완료 요약 출력 (.sh print_summary 등가). 전부 stderr.
2
- // ctx: { mode, types:[], version, copiedFiles:[], branches?, gitignoreUpdated? }
1
+ // 완료 요약 출력. 전부 stderr.
2
+ // ctx: { mode, types:[], version, copiedFiles:[], branches?, gitignoreUpdated?, readme?, scripts? }
3
3
  import { WORKFLOW_PREFIX, WORKFLOW_COMMON_PREFIX } from "../core/paths.js";
4
4
  import { paint, A, colorEnabled } from "./ansi.js";
5
+ import { EITHER_SEP } from "../core/verify.js";
6
+ import { BUILD_NUMBER_TYPES } from "../core/types.js";
7
+ import { SCRIPT_NAMES } from "../core/copy/simple.js";
5
8
 
6
9
  const SEPARATOR = "────────────────────────────────────────";
7
10
 
8
11
  export function printSummary(ctx) {
9
- const { mode, types = [], version = "", versionCode = null, copiedFiles = [], branches = null, gitignoreUpdated = false,
12
+ const { mode, types = [], version = "", versionCode = null, copiedFiles = [], autoUpdated = [], branches = null, gitignoreUpdated = false,
13
+ // pr-flow인데 원격에 develop을 만들지 못한 경우 — 구성 줄만 보면 이미 준비된 것처럼 보이므로 따로 알린다.
14
+ developMissing = false,
10
15
  // 설치 후 검증·기록
11
- answers = [], unresolved = [], secrets = new Map(), logPath = "", legacyMdLogs = false, cleanup = null,
16
+ answers = [], unresolved = [], secrets = new Map(), optionalSecrets = new Map(), logPath = "", legacyMdLogs = false, cleanup = null,
12
17
  // Flutter 스토어 배포 — 앱 파일 생성/유지와 스토어 선택 해제 정리 결과
13
- flutterApp = null, storeCleanup = null } = ctx || {};
18
+ flutterApp = null, storeCleanup = null,
19
+ // 이번 실행의 실제 결과 — README 버전 섹션 처리 상태(addVersionSectionToReadme 반환값)와 스크립트별 결과.
20
+ // 고정 문구로 찍으면 README.md가 없어 아무것도 하지 않은 실행도 "추가됨"으로 보고하게 된다.
21
+ readme = null, scripts = null } = ctx || {};
14
22
  const err = (s = "") => process.stderr.write(`${s}\n`);
15
23
  // 색상은 ansi.js의 공용 가드로 통일 (NO_COLOR + stderr TTY 여부)
16
24
  const enabled = colorEnabled(process.stderr);
@@ -24,24 +32,16 @@ export function printSummary(ctx) {
24
32
  err("");
25
33
  err("통합된 기능:");
26
34
 
27
- // 모드별 체크리스트
28
- switch (mode) {
29
- case "full":
30
- err(" ✅ 버전 관리 시스템 (version.yml)");
31
- err(" ✅ README.md 자동 버전 업데이트");
32
- err(" ✅ GitHub Actions 워크플로우 (릴리스 자동화 포함)");
33
- if (gitignoreUpdated) err(" ✅ .gitignore 백업 파일 제외 항목 (*.bak/*.template.yaml)");
34
- break;
35
- case "version":
36
- err(" ✅ 버전 관리 시스템 (version.yml)");
37
- err(" ✅ README.md 자동 버전 업데이트");
38
- break;
39
- case "workflows":
40
- err(" ✅ GitHub Actions 워크플로우 (릴리스 자동화 포함)");
41
- break;
42
- }
43
-
44
- // 브랜치 모드 + 릴리스 요약 엔진 안내 (DESIGN-SPEC §4~5)
35
+ // README 버전 섹션이 실제로 있는 경우(이번에 추가했거나 원래 있던 경우)에만 자동 업데이트를 안내한다.
36
+ const readmeTracked = readme === "added" || readme === "skip-marker" || readme === "skip-version-line";
37
+ if (mode === "full") {
38
+ err(" ✅ 버전 관리 시스템 (version.yml)");
39
+ if (readmeTracked) err(" ✅ README.md 자동 버전 업데이트");
40
+ err(" ✅ GitHub Actions 워크플로우 (릴리스 자동화 포함)");
41
+ if (gitignoreUpdated) err(" ✅ .gitignore 백업 파일 제외 항목 (*.bak/*.template.yaml)");
42
+ }
43
+
44
+ // 브랜치 모드 + 릴리스 요약 엔진 안내
45
45
  if (branches) {
46
46
  err("");
47
47
  err("브랜치 구성:");
@@ -49,6 +49,10 @@ export function printSummary(ctx) {
49
49
  err(` 🌿 ${branches.main} 단일 브랜치 (trunk-based) — RELEASE-PUBLISH 하나가 버전확정→체인지로그→tag→Release를 순차 처리`);
50
50
  } else {
51
51
  err(` 🌿 개발 ${branches.develop} → 릴리스 ${branches.main} (pr-flow) — 릴리스 PR에서 버전확정·체인지로그·automerge`);
52
+ if (developMissing) {
53
+ err(` ⚠️ '${branches.develop}' 브랜치가 아직 원격에 없습니다 — 만들기 전에는 개발 브랜치 워크플로우가 동작하지 않습니다`);
54
+ err(` → 설치 파일을 커밋해 ${branches.main}을 push한 뒤: git push origin ${branches.main}:${branches.develop}`);
55
+ }
52
56
  }
53
57
  }
54
58
  if (mode === "full" || mode === "workflows") {
@@ -60,21 +64,27 @@ export function printSummary(ctx) {
60
64
  err("");
61
65
  err("추가된 파일:");
62
66
  err(` 📄 version.yml (버전: ${version}, 타입: ${types.join(",")})`);
63
- const BUILD_NUMBER_TYPES = new Set(["flutter", "react-native", "react-native-expo"]);
64
67
  if (versionCode != null && types.some((t) => BUILD_NUMBER_TYPES.has(t))) {
65
68
  err(` 빌드 번호: ${versionCode}`);
66
69
  }
67
- err(" 📝 README.md (버전 섹션 추가)");
70
+ if (readme === "added") err(" 📝 README.md (버전 섹션 추가)");
71
+ if (readme === "skip-no-readme") {
72
+ err(" ℹ️ README.md가 없어 버전 섹션을 추가하지 않았습니다");
73
+ err(" → README.md를 만든 뒤 다시 실행하면 추가됩니다 (그 전까지 README 버전 갱신 워크플로우는 건너뜁니다)");
74
+ }
68
75
  err("");
69
76
  err("추가된 워크플로우:");
70
77
 
71
78
  // 실제로 이번 실행에서 복사된 파일만 분류한다 (copyWorkflows()가 반환한 copiedFiles —
72
79
  // 디렉터리 재스캔은 재실행 시 skip된 파일까지 "새로 설치됨"으로 보여주는 결함이 있었다).
80
+ // 자동 갱신분(사용자 미수정 파일을 최신으로 교체)도 copiedFiles에 들어 있다 — 새로 설치한 것과 나눠 보여준다.
81
+ const updated = new Set(autoUpdated);
73
82
  const commonWorkflows = [];
74
83
  const typeWorkflows = [];
75
84
  const typePrefixes = types.map((t) => `${WORKFLOW_PREFIX}-${t.toUpperCase()}-`);
76
85
  for (const filename of copiedFiles) {
77
86
  if (!filename.startsWith(`${WORKFLOW_PREFIX}-`)) continue; // PROJECT-*만
87
+ if (updated.has(filename)) continue;
78
88
  if (filename.startsWith(`${WORKFLOW_COMMON_PREFIX}-`)) {
79
89
  commonWorkflows.push(filename);
80
90
  } else if (typePrefixes.some((p) => filename.startsWith(p))) {
@@ -87,13 +97,17 @@ export function printSummary(ctx) {
87
97
  for (const wf of commonWorkflows) err(` 📌 ${wf}`);
88
98
  for (const wf of typeWorkflows) err(` 🎯 ${wf}`);
89
99
  }
100
+ if (updated.size > 0) {
101
+ err(` 🔄 업데이트됨 (${updated.size}개, 수정하지 않은 파일을 최신으로 교체):`);
102
+ for (const wf of updated) err(` • ${wf}`);
103
+ }
90
104
 
91
105
  err("");
92
106
  err(" 🔧 .github/scripts/");
93
- err(" ├─ version_manager.py");
94
- err(" ├─ changelog_manager.py");
95
- err(" ├─ truncate_release_notes.py");
96
- err(" └─ issue_helper.py");
107
+ const scriptRows = scripts
108
+ ? scripts.map(({ name, action }) => (action === "overwrite" ? `${name} ${paint("(기존 파일을 새 버전으로 덮어씀)", A.dim, enabled)}` : name))
109
+ : SCRIPT_NAMES;
110
+ scriptRows.forEach((row, i) => err(` ${i === scriptRows.length - 1 ? "└─" : "├─"} ${row}`));
97
111
  err("");
98
112
 
99
113
  // 입력한 환경설정 값 — 마지막으로 눈으로 검산할 기회. 종전에는 답변이 워크플로우
@@ -162,12 +176,34 @@ export function printSummary(ctx) {
162
176
 
163
177
  // 설치된 워크플로우가 실제로 요구하는 Secret — 종전에는 하나도 안내되지 않아
164
178
  // "설치 성공"인데 배포는 돌지 않는 상태로 끝났다.
179
+ // "A 또는 B"는 둘 중 하나만 등록하면 되는 폴백 쌍이라 한 항목으로 센다.
165
180
  if (secrets.size) {
166
181
  err(` ${num()} 아래 GitHub Secret을 등록해야 배포 워크플로우가 동작합니다 (${secrets.size}개)`);
167
182
  err(" → Settings > Secrets and variables > Actions");
168
183
  for (const [name, users] of secrets) {
169
- err(` → ${paint(name, A.bold, enabled)} ${paint(users.join(", "), A.dim, enabled)}`);
184
+ const either = name.includes(EITHER_SEP) ? paint(" (둘 중 하나)", A.dim, enabled) : "";
185
+ err(` → ${paint(name, A.bold, enabled)}${either} ${paint(users.join(", "), A.dim, enabled)}`);
186
+ }
187
+ err("");
188
+ }
189
+ // 기본값이 있거나 없어도 동작하는 secret — 필수 개수에 섞지 않고 따로 알린다.
190
+ if (optionalSecrets.size) {
191
+ err(` ${paint("ℹ️", A.dim, enabled)} 선택 Secret (없어도 동작합니다 — 필요할 때 등록, ${optionalSecrets.size}개)`);
192
+ for (const [name, users] of optionalSecrets) {
193
+ err(` · ${name} ${paint(users.join(", "), A.dim, enabled)}`);
194
+ }
195
+ err("");
196
+ }
197
+
198
+ // 설치 파일은 아직 커밋 전이다. develop을 이번 실행에서 만들었다면 설치 전 커밋 기준이라 워크플로우가 없다 —
199
+ // 한쪽 브랜치에만 커밋하면 다른 쪽에는 VERSION-CONTROL 등이 빠진 채로 남는다.
200
+ if (branches) {
201
+ err(` ${num()} 설치된 파일을 커밋해 ${branches.main}에 push하세요`);
202
+ if (branches.mode !== "trunk-based") {
203
+ err(` → ${branches.develop}에도 같은 파일이 있어야 합니다 — 한쪽에 커밋한 뒤 다른 쪽에 병합하세요`);
204
+ err(` 예) git checkout ${branches.develop} && git merge ${branches.main} && git push`);
170
205
  }
206
+ err(" → README의 '전체 버전 기록 보기'(CHANGELOG.md) 링크는 첫 릴리스에서 CHANGELOG가 생성된 뒤부터 열립니다");
171
207
  err("");
172
208
  }
173
209
 
@@ -175,10 +211,12 @@ export function printSummary(ctx) {
175
211
  err(" → Repository Settings > Secrets > Actions");
176
212
  err(" → Secret Name: WORKFLOW_PAT (Scopes: repo, workflow)");
177
213
  err(" → 등록 시 개인 계정이 아닌 조직 bot/machine 계정으로 발급하세요");
178
- err(" → 없어도 자동 복구되며, 있으면 병합~Release 반영이 조금 더 빠릅니다");
214
+ err(" → 없어도 태그·Release 발행과 배포 워크플로우 실행까지 자동으로 이어지며, 있으면 조금 더 빠릅니다");
179
215
  err("");
180
- err(` ${num()} GitHub Actions 권한 확인`);
181
- err(" → Settings > Actions > Workflow permissions: Read and write");
216
+ // 설치 워크플로우는 필요한 권한을 각자 선언한다 — doctor 안내와 같은 기준으로 알린다.
217
+ err(` ${num()} GitHub Actions 권한 (변경 불필요)`);
218
+ err(" → Workflow permissions가 기본값 Read여도 설치된 워크플로우는 그대로 동작합니다");
219
+ err(" → 직접 추가한 워크플로우가 permissions 선언 없이 쓰기 작업을 할 때만 Read and write로 올리세요");
182
220
  err("");
183
221
  err(SEPARATOR);
184
222
  err("");