project-auto-wizard 0.11.0 → 0.12.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 (78) hide show
  1. package/README.md +24 -21
  2. package/package.json +2 -2
  3. package/payload/config/breaking-changes.json +1 -1
  4. package/payload/scripts/__pycache__/changelog_manager.cpython-314.pyc +0 -0
  5. package/payload/scripts/__pycache__/issue_helper.cpython-314.pyc +0 -0
  6. package/payload/scripts/__pycache__/version_manager.cpython-314.pyc +0 -0
  7. package/payload/scripts/changelog_manager.py +84 -31
  8. package/payload/scripts/version_manager.py +2 -2
  9. package/payload/version.yml.template +4 -2
  10. package/payload/workflows/common/PROJECT-COMMON-AI-PR-SUMMARY.yaml +30 -10
  11. package/payload/workflows/common/PROJECT-COMMON-AUTO-CHANGELOG-CONTROL.yaml +37 -12
  12. package/payload/workflows/common/PROJECT-COMMON-ISSUE-HELPER.yaml +3 -6
  13. package/payload/workflows/common/PROJECT-COMMON-README-VERSION-UPDATE.yaml +0 -12
  14. package/payload/workflows/common/PROJECT-COMMON-RELEASE-PUBLISH.yaml +27 -6
  15. package/payload/workflows/common/PROJECT-COMMON-VERSION-CONTROL.yaml +3 -7
  16. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-FIREBASE-CICD.yaml +7 -34
  17. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +2 -25
  18. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-SELFHOSTED-CICD.yaml +2 -20
  19. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +5 -30
  20. package/payload/workflows/flutter/PROJECT-FLUTTER-APP-BUILD-TRIGGER.yaml +0 -4
  21. package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +7 -51
  22. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +5 -29
  23. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TESTFLIGHT.yaml +9 -29
  24. package/payload/workflows/go/PROJECT-GO-CI.yaml +5 -28
  25. package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +19 -99
  26. package/payload/workflows/go/PROJECT-GO-SIMPLE-CICD.yaml +18 -89
  27. package/payload/workflows/next/PROJECT-NEXT-CI.yaml +11 -41
  28. package/payload/workflows/next/PROJECT-NEXT-CICD.yaml +9 -45
  29. package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +1 -27
  30. package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +14 -97
  31. package/payload/workflows/python/PROJECT-PYTHON-SIMPLE-CICD.yaml +14 -92
  32. package/payload/workflows/react/PROJECT-REACT-CI.yaml +11 -40
  33. package/payload/workflows/react/PROJECT-REACT-CICD.yaml +9 -43
  34. package/payload/workflows/spring/{nexus/PROJECT-SPRING-NEXUS-CI.yml → PROJECT-SPRING-CI.yml} +2 -25
  35. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-NGINX-CICD.yaml +19 -63
  36. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-TRAEFIK-CICD.yaml +19 -59
  37. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +23 -86
  38. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-SIMPLE-CICD.yaml +20 -80
  39. package/src/cli/args.js +8 -15
  40. package/src/cli/help.js +2 -3
  41. package/src/commands/doctor.js +9 -8
  42. package/src/commands/dry-run.js +1 -1
  43. package/src/commands/full.js +9 -10
  44. package/src/commands/interactive-flutter.js +1 -1
  45. package/src/commands/interactive.js +34 -46
  46. package/src/commands/purge.js +2 -2
  47. package/src/commands/status.js +5 -6
  48. package/src/commands/uninstall.js +3 -4
  49. package/src/context.js +5 -6
  50. package/src/core/assets.js +2 -2
  51. package/src/core/baseline.js +1 -1
  52. package/src/core/branches.js +3 -3
  53. package/src/core/breaking-check.js +1 -1
  54. package/src/core/breaking.js +1 -1
  55. package/src/core/copy/flutter-app.js +2 -2
  56. package/src/core/copy/gitignore.js +8 -8
  57. package/src/core/copy/workflows.js +24 -69
  58. package/src/core/deploy-style.js +2 -2
  59. package/src/core/detect-fs.js +11 -11
  60. package/src/core/detect.js +7 -7
  61. package/src/core/flutter-options.js +1 -1
  62. package/src/core/installed-stores.js +1 -1
  63. package/src/core/logger.js +1 -1
  64. package/src/core/paths-resolve.js +1 -1
  65. package/src/core/removal-plan.js +4 -4
  66. package/src/core/verify.js +4 -4
  67. package/src/core/version-yml.js +27 -34
  68. package/src/core/wizard-env.js +4 -4
  69. package/src/index.js +14 -14
  70. package/src/ui/banner.js +2 -2
  71. package/src/ui/env-plan.js +10 -16
  72. package/src/ui/prompts.js +9 -14
  73. package/src/ui/status-cards.js +10 -12
  74. package/src/ui/summary.js +13 -13
  75. package/payload/workflows/common/secret-backup/PROJECT-COMMON-SECRET-FILE-UPLOAD.yaml +0 -210
  76. package/payload/workflows/spring/nexus/PROJECT-SPRING-GITHUB-PACKAGES-PUBLISH.yml +0 -92
  77. package/payload/workflows/spring/nexus/PROJECT-SPRING-NEXUS-PUBLISH.yml +0 -70
  78. package/src/core/options-ask.js +0 -102
package/src/ui/summary.js CHANGED
@@ -7,9 +7,9 @@ const SEPARATOR = "────────────────────
7
7
 
8
8
  export function printSummary(ctx) {
9
9
  const { mode, types = [], version = "", versionCode = null, copiedFiles = [], branches = null, gitignoreUpdated = false,
10
- // 설치 후 검증·기록 (#79, #80, #81)
10
+ // 설치 후 검증·기록
11
11
  answers = [], unresolved = [], secrets = new Map(), logPath = "", legacyMdLogs = false, cleanup = null,
12
- // Flutter 스토어 배포 (이슈 #131) — 앱 파일 생성/유지와 스토어 선택 해제 정리 결과
12
+ // Flutter 스토어 배포 — 앱 파일 생성/유지와 스토어 선택 해제 정리 결과
13
13
  flutterApp = null, storeCleanup = null } = ctx || {};
14
14
  const err = (s = "") => process.stderr.write(`${s}\n`);
15
15
  // 색상은 ansi.js의 공용 가드로 통일 (NO_COLOR + stderr TTY 여부)
@@ -29,7 +29,7 @@ export function printSummary(ctx) {
29
29
  case "full":
30
30
  err(" ✅ 버전 관리 시스템 (version.yml)");
31
31
  err(" ✅ README.md 자동 버전 업데이트");
32
- err(" ✅ GitHub Actions 워크플로우 (AI 릴리스 자동화 포함)");
32
+ err(" ✅ GitHub Actions 워크플로우 (릴리스 자동화 포함)");
33
33
  if (gitignoreUpdated) err(" ✅ .gitignore 백업 파일 제외 항목 (*.bak/*.template.yaml)");
34
34
  break;
35
35
  case "version":
@@ -37,7 +37,7 @@ export function printSummary(ctx) {
37
37
  err(" ✅ README.md 자동 버전 업데이트");
38
38
  break;
39
39
  case "workflows":
40
- err(" ✅ GitHub Actions 워크플로우 (AI 릴리스 자동화 포함)");
40
+ err(" ✅ GitHub Actions 워크플로우 (릴리스 자동화 포함)");
41
41
  break;
42
42
  }
43
43
 
@@ -48,13 +48,13 @@ export function printSummary(ctx) {
48
48
  if (branches.mode === "trunk-based") {
49
49
  err(` 🌿 ${branches.main} 단일 브랜치 (trunk-based) — RELEASE-PUBLISH 하나가 버전확정→체인지로그→tag→Release를 순차 처리`);
50
50
  } else {
51
- err(` 🌿 개발 ${branches.develop} → 릴리스 ${branches.main} (pr-flow) — 릴리스 PR에서 버전확정·AI 체인지로그·automerge`);
51
+ err(` 🌿 개발 ${branches.develop} → 릴리스 ${branches.main} (pr-flow) — 릴리스 PR에서 버전확정·체인지로그·automerge`);
52
52
  }
53
53
  }
54
54
  if (mode === "full" || mode === "workflows") {
55
55
  err("");
56
56
  err("릴리스 노트 요약 엔진:");
57
- err(" 🤖 AI_API_KEY(선택) → GitHub Models(기본·무료·API 키 불필요) → 규칙 fallback — 릴리스는 절대 막히지 않음");
57
+ err(" 🤖 AI_API_KEY(선택) → Copilot(선택·AI Credits 소비, 기본 꺼짐) → 규칙 fallback — 릴리스는 절대 막히지 않음");
58
58
  }
59
59
 
60
60
  err("");
@@ -69,7 +69,7 @@ export function printSummary(ctx) {
69
69
  err("추가된 워크플로우:");
70
70
 
71
71
  // 실제로 이번 실행에서 복사된 파일만 분류한다 (copyWorkflows()가 반환한 copiedFiles —
72
- // 디렉터리 재스캔은 재실행 시 skip된 파일까지 "새로 설치됨"으로 보여주는 결함이 있었다, issue #19).
72
+ // 디렉터리 재스캔은 재실행 시 skip된 파일까지 "새로 설치됨"으로 보여주는 결함이 있었다).
73
73
  const commonWorkflows = [];
74
74
  const typeWorkflows = [];
75
75
  const typePrefixes = types.map((t) => `${WORKFLOW_PREFIX}-${t.toUpperCase()}-`);
@@ -96,7 +96,7 @@ export function printSummary(ctx) {
96
96
  err(" └─ issue_helper.py");
97
97
  err("");
98
98
 
99
- // 입력한 환경설정 값 (#80) — 마지막으로 눈으로 검산할 기회. 종전에는 답변이 워크플로우
99
+ // 입력한 환경설정 값 — 마지막으로 눈으로 검산할 기회. 종전에는 답변이 워크플로우
100
100
  // YAML 안으로만 사라져, 오타를 내도 배포가 실패한 뒤에야 알 수 있었다.
101
101
  if (answers.length) {
102
102
  err(" ⚙️ 적용된 환경설정:");
@@ -106,11 +106,11 @@ export function printSummary(ctx) {
106
106
  }
107
107
  err("");
108
108
  }
109
- // 배포 방식을 바꿔 재설치한 경우, 이전 CD를 어떻게 처리했는지 알린다 (#80).
109
+ // 배포 방식을 바꿔 재설치한 경우, 이전 CD를 어떻게 처리했는지 알린다.
110
110
  printCleanup(err, enabled, "이전 배포 방식 정리", cleanup);
111
- // 스토어 배포 대상을 해제한 경우도 같은 규칙으로 정리한 결과를 알린다 (#131).
111
+ // 스토어 배포 대상을 해제한 경우도 같은 규칙으로 정리한 결과를 알린다.
112
112
  printCleanup(err, enabled, "선택 해제한 스토어 배포 정리", storeCleanup);
113
- // Fastfile·ExportOptions.plist는 사용자 소유라 없을 때만 만든다 — 만든 것과 그대로 둔 것을 나눠 보여준다 (#131).
113
+ // Fastfile·ExportOptions.plist는 사용자 소유라 없을 때만 만든다 — 만든 것과 그대로 둔 것을 나눠 보여준다.
114
114
  const { created: appCreated = [], kept: appKept = [] } = flutterApp || {};
115
115
  if (appCreated.length || appKept.length) {
116
116
  err(" 📱 Flutter 스토어 배포 파일:");
@@ -151,7 +151,7 @@ export function printSummary(ctx) {
151
151
  let step = 0;
152
152
  const num = () => ["1️⃣ ", "2️⃣ ", "3️⃣ ", "4️⃣ ", "5️⃣ "][step++] || " •";
153
153
 
154
- // 미치환 플레이스홀더 (#81) — 이 상태로는 해당 워크플로우가 동작하지 않으므로 제일 먼저 알린다.
154
+ // 미치환 플레이스홀더 — 이 상태로는 해당 워크플로우가 동작하지 않으므로 제일 먼저 알린다.
155
155
  if (unresolved.length) {
156
156
  err(` ${num()} ${paint("값이 채워지지 않은 항목이 있습니다 — 직접 채워야 동작합니다", A.red, enabled)}`);
157
157
  for (const u of unresolved) {
@@ -160,7 +160,7 @@ export function printSummary(ctx) {
160
160
  err("");
161
161
  }
162
162
 
163
- // 설치된 워크플로우가 실제로 요구하는 Secret (#80) — 종전에는 하나도 안내되지 않아
163
+ // 설치된 워크플로우가 실제로 요구하는 Secret — 종전에는 하나도 안내되지 않아
164
164
  // "설치 성공"인데 배포는 돌지 않는 상태로 끝났다.
165
165
  if (secrets.size) {
166
166
  err(` ${num()} 아래 GitHub Secret을 등록해야 배포 워크플로우가 동작합니다 (${secrets.size}개)`);
@@ -1,210 +0,0 @@
1
- # project-auto-wizard:managed-workflow
2
- # ===================================================================
3
- # PROJECT-COMMON-SECRET-FILE-UPLOAD.yaml
4
- # GitHub Secret 파일 서버(SSH) 자동 업로드
5
- # ===================================================================
6
- #
7
- # GitHub Secrets에 저장된 설정 파일들을 서버(SSH 접속 가능한 호스트)에
8
- # 자동 업로드하여 변경 이력을 추적합니다.
9
- # 타임스탬프 기반 백업으로 변경 히스토리를 보존합니다.
10
- #
11
- # ===================================================================
12
- # 🤖 AI 에이전트 커스텀 가이드
13
- # ===================================================================
14
- # 이 워크플로우를 프로젝트에 맞게 수정하려면,
15
- # 아래 프롬프트를 AI 에이전트에게 전달하세요:
16
- #
17
- # 📋 프롬프트:
18
- # "PROJECT-COMMON-SECRET-FILE-UPLOAD.yaml을
19
- # 프로젝트에 맞게 수정해줘.
20
- # - 프로젝트명: {프로젝트명}
21
- # - 역할(ROLE): {backend/frontend 등}
22
- # - 서버 저장 경로: {서버 저장 경로}
23
- # - SSH 포트: {포트번호}
24
- # - 업로드할 GitHub Secrets:
25
- # SECRET_KEY → 저장할_파일명.확장자
26
- # 기존 파일 목록 섹션에 추가하고,
27
- # 없는 Secret은 스킵하도록 해줘."
28
- #
29
- # 💡 예시:
30
- # "- APPLICATION_PROD_YML → application-prod.yml
31
- # - FIREBASE_KEY_JSON → firebase-admin-sdk.json
32
- # - VERTEX_SA_KEY → vertex-sa-key.json
33
- # - ENV_FILE → .env
34
- # - ADMIN_YML → admin.yml"
35
- # ===================================================================
36
- #
37
- # ===================================================================
38
- # 🔑 필수 GitHub Secrets
39
- # ===================================================================
40
- # SERVER_HOST: 서버 호스트(SSH 접속 주소)
41
- # SERVER_USER: SSH 사용자명
42
- # SERVER_PASSWORD: SSH 비밀번호
43
- # ===================================================================
44
- #
45
- # 🔧 환경변수 설정 (env 섹션에서 설정)
46
- # ===================================================================
47
- #
48
- # 📦 프로젝트 설정:
49
- # PROJECT_NAME: 프로젝트명 (서버 경로에 사용)
50
- # ROLE: 역할 구분 (backend, frontend 등)
51
- # SERVER_BASE_PATH: 서버 기본 경로 (기본: /volume1/projects, 예: AWS EC2 /home/ubuntu/projects)
52
- #
53
- # 🔌 SSH 연결:
54
- # SSH_PORT: SSH 포트 (기본: 2022)
55
- # ===================================================================
56
-
57
- name: PROJECT-COMMON-SECRET-FILE-UPLOAD
58
-
59
- # ===================================================================
60
- # 트리거 설정
61
- # ===================================================================
62
- # {{MAIN_BRANCH}} 브랜치에 push할 때 자동 실행됩니다.
63
- # workflow_dispatch로 수동 실행도 가능합니다.
64
- on:
65
- push:
66
- branches:
67
- - "{{DEVELOP_BRANCH}}"
68
- workflow_dispatch:
69
-
70
- concurrency:
71
- group: secret-file-upload-${{ github.ref }}
72
- cancel-in-progress: true
73
-
74
- # ===================================================================
75
- # 환경 변수 설정
76
- # ===================================================================
77
- env:
78
- # 🔧 프로젝트 설정 - 마법사가 설치 시 채웁니다
79
- PROJECT_NAME: "__PROJECT_NAME__" # @wizard ask:@repo
80
- ROLE: "backend"
81
- SERVER_BASE_PATH: "__SERVER_BASE_PATH__" # @wizard ask:/volume1/projects
82
- SSH_PORT: "__SSH_PORT__" # @wizard ask:2022
83
-
84
- jobs:
85
- upload-secret-files:
86
- name: Secret 파일 업로드
87
- runs-on: ubuntu-latest
88
- # [skip ci] 커밋 메시지가 포함된 경우 실행하지 않음
89
- if: "!contains(github.event.head_commit.message, '[skip ci]')"
90
-
91
- steps:
92
- - name: 타임스탬프 및 커밋 정보 생성
93
- run: |
94
- export TZ='Asia/Seoul'
95
- TIMESTAMP=$(date '+%Y-%m-%d_%H-%M-%S')
96
- echo "TIMESTAMP=$TIMESTAMP" >> $GITHUB_ENV
97
- echo "BUILD_DATE=$(date '+%Y-%m-%d %H:%M')" >> $GITHUB_ENV
98
- echo "SHORT_COMMIT_HASH=$(echo "${{ github.sha }}" | cut -c1-7)" >> $GITHUB_ENV
99
- echo "생성된 타임스탬프: $TIMESTAMP"
100
-
101
- - name: Secret 파일 업로드
102
- uses: appleboy/ssh-action@v1.0.3
103
- with:
104
- host: ${{ secrets.SERVER_HOST }}
105
- username: ${{ secrets.SERVER_USER }}
106
- password: ${{ secrets.SERVER_PASSWORD }}
107
- port: ${{ env.SSH_PORT }}
108
- script: |
109
- set -e
110
-
111
- # GitHub Actions 환경변수 직접 설정
112
- PROJECT_NAME="${{ env.PROJECT_NAME }}"
113
- ROLE="${{ env.ROLE }}"
114
- SERVER_BASE_PATH="${{ env.SERVER_BASE_PATH }}"
115
- TIMESTAMP="${{ env.TIMESTAMP }}"
116
- SHORT_COMMIT_HASH="${{ env.SHORT_COMMIT_HASH }}"
117
- BUILD_DATE="${{ env.BUILD_DATE }}"
118
-
119
- # 경로 설정
120
- BASE_DIR="${SERVER_BASE_PATH}/${PROJECT_NAME}/github_secret/${ROLE}"
121
-
122
- echo "=== Secret 파일 업로드 시작 ==="
123
- echo "프로젝트: ${PROJECT_NAME} (${ROLE})"
124
- echo "경로: ${BASE_DIR}"
125
- echo "타임스탬프: ${TIMESTAMP}"
126
-
127
- # 디렉토리 생성
128
- export PW="${{ secrets.SERVER_PASSWORD }}"
129
- echo "$PW" | sudo -S mkdir -p "${BASE_DIR}/${TIMESTAMP}"
130
-
131
- # ============================================
132
- # 📦 파일 업로드 섹션
133
- # Secret이 비어있으면 자동 스킵됩니다.
134
- # AI 에이전트로 이 섹션에 파일을 추가하세요.
135
- # ============================================
136
-
137
- # --- ENV_FILE → .env ---
138
- cat << '__WIZARD_SECRET_CHECK_EOF__' > /tmp/_secret_check
139
- ${{ secrets.ENV_FILE }}
140
- __WIZARD_SECRET_CHECK_EOF__
141
- if [ -s /tmp/_secret_check ] && [ -n "$(tr -d '[:space:]' < /tmp/_secret_check)" ]; then
142
- echo "ENV_FILE → .env 업로드 중..."
143
- cat << '__WIZARD_FILE_CONTENT_EOF__' | sudo tee "${BASE_DIR}/.env" > /dev/null
144
- ${{ secrets.ENV_FILE }}
145
- __WIZARD_FILE_CONTENT_EOF__
146
- cat << '__WIZARD_FILE_CONTENT_EOF__' | sudo tee "${BASE_DIR}/${TIMESTAMP}/.env" > /dev/null
147
- ${{ secrets.ENV_FILE }}
148
- __WIZARD_FILE_CONTENT_EOF__
149
- echo ".env 업로드 완료"
150
- else
151
- echo "ENV_FILE 스킵 (Secret 미설정)"
152
- fi
153
- rm -f /tmp/_secret_check
154
-
155
- # --- APPLICATION_PROD_YML → application-prod.yml ---
156
- cat << '__WIZARD_SECRET_CHECK_EOF__' > /tmp/_secret_check
157
- ${{ secrets.APPLICATION_PROD_YML }}
158
- __WIZARD_SECRET_CHECK_EOF__
159
- if [ -s /tmp/_secret_check ] && [ -n "$(tr -d '[:space:]' < /tmp/_secret_check)" ]; then
160
- echo "APPLICATION_PROD_YML → application-prod.yml 업로드 중..."
161
- cat << '__WIZARD_FILE_CONTENT_EOF__' | sudo tee "${BASE_DIR}/application-prod.yml" > /dev/null
162
- ${{ secrets.APPLICATION_PROD_YML }}
163
- __WIZARD_FILE_CONTENT_EOF__
164
- cat << '__WIZARD_FILE_CONTENT_EOF__' | sudo tee "${BASE_DIR}/${TIMESTAMP}/application-prod.yml" > /dev/null
165
- ${{ secrets.APPLICATION_PROD_YML }}
166
- __WIZARD_FILE_CONTENT_EOF__
167
- echo "application-prod.yml 업로드 완료"
168
- else
169
- echo "APPLICATION_PROD_YML 스킵 (Secret 미설정)"
170
- fi
171
- rm -f /tmp/_secret_check
172
-
173
- # ============================================
174
- # 📋 메타데이터 JSON 생성
175
- # ============================================
176
- cat << EOF | sudo tee "${BASE_DIR}/${TIMESTAMP}/cicd-gitignore-file.json" > /dev/null
177
- {
178
- "build_info": {
179
- "timestamp": "$TIMESTAMP",
180
- "workflow": "Secret 파일 자동 업로드",
181
- "run_id": "${{ github.run_id }}",
182
- "run_number": "${{ github.run_number }}",
183
- "event": "${{ github.event_name }}",
184
- "repository": "${{ github.repository }}",
185
- "branch": "${{ github.ref_name }}",
186
- "commit_hash": "${{ github.sha }}",
187
- "short_hash": "$SHORT_COMMIT_HASH",
188
- "commit_url": "https://github.com/${{ github.repository }}/commit/${{ github.sha }}",
189
- "actor": "${{ github.actor }}",
190
- "build_date": "$BUILD_DATE"
191
- },
192
- "files": [
193
- {
194
- "secret_name": "ENV_FILE",
195
- "file_name": ".env",
196
- "last_updated": "$BUILD_DATE"
197
- },
198
- {
199
- "secret_name": "APPLICATION_PROD_YML",
200
- "file_name": "application-prod.yml",
201
- "last_updated": "$BUILD_DATE"
202
- }
203
- ]
204
- }
205
- EOF
206
-
207
- # 타임스탬프 인덱스 업데이트
208
- echo "{\"last_updated\": \"${TIMESTAMP}\", \"commit\": \"${SHORT_COMMIT_HASH}\", \"actor\": \"${{ github.actor }}\", \"status\": \"completed\"}" | sudo tee "${BASE_DIR}/timestamp_index.json" > /dev/null
209
-
210
- echo "=== 모든 파일 업로드 완료 ==="
@@ -1,92 +0,0 @@
1
- # project-auto-wizard:managed-workflow
2
- # ===================================================================
3
- # Spring GitHub Packages 라이브러리 배포 워크플로우
4
- # ===================================================================
5
- #
6
- # Java 라이브러리 모듈을 GitHub Packages(Maven repo)에 자동 배포합니다.
7
- # Nexus 없이 GitHub만으로 의존성 호스팅이 가능합니다.
8
- #
9
- # ⚠️ Java 라이브러리 모듈 배포 전용 CICD입니다.
10
- # Spring Boot 애플리케이션 배포가 아닙니다.
11
- #
12
- # ===================================================================
13
- # 🛠️ build.gradle 요구사항
14
- # ===================================================================
15
- # publishing.repositories.maven 블록에 GitHub Packages 항목 추가:
16
- #
17
- # maven {
18
- # name = "GitHubPackages"
19
- # url = uri("https://maven.pkg.github.com/${System.getenv('GITHUB_REPOSITORY')}")
20
- # credentials {
21
- # username = System.getenv("GITHUB_ACTOR")
22
- # password = System.getenv("GITHUB_TOKEN")
23
- # }
24
- # }
25
- #
26
- # 💡 Free 계정 제한 (Private repo 기준):
27
- # - 월 500MB 저장 + 1GB 전송 무료
28
- # - Public repo는 무제한 무료
29
- # ===================================================================
30
-
31
- name: PROJECT-SPRING-GITHUB-PACKAGES-PUBLISH
32
-
33
- on:
34
- push:
35
- branches: ["{{MAIN_BRANCH}}"]
36
- tags:
37
- - 'v*.*.*'
38
- # @wizard paths-anchor (모노레포일 때 integrator가 paths 필터를 여기 주입)
39
- workflow_dispatch:
40
-
41
- concurrency:
42
- group: github-packages-publish-${{ github.ref }}
43
- cancel-in-progress: false
44
-
45
- permissions:
46
- contents: read
47
- packages: write
48
-
49
- # ===================================================================
50
- # 환경 변수 설정
51
- # ===================================================================
52
- env:
53
- JAVA_VERSION: "__JAVA_VERSION__" # @wizard ask:@jdk
54
-
55
- jobs:
56
- publish:
57
- runs-on: ubuntu-latest
58
- steps:
59
- - uses: actions/checkout@v7
60
-
61
- - name: Set up JDK
62
- uses: actions/setup-java@v5
63
- with:
64
- java-version: ${{ env.JAVA_VERSION }}
65
- distribution: 'temurin'
66
-
67
- - name: Setup Gradle
68
- uses: gradle/actions/setup-gradle@v4
69
-
70
- - name: Get version
71
- id: get_version
72
- run: |
73
- if [[ "${{ github.ref }}" == refs/tags/* ]]; then
74
- TAG_NAME=${GITHUB_REF#refs/tags/}
75
- VERSION=${TAG_NAME#v}
76
- echo "🏷️ 태그에서 버전 추출: $VERSION"
77
- else
78
- VERSION=$(python3 .github/scripts/version_manager.py get | tail -n 1)
79
- echo "📄 version.yml에서 버전 추출: $VERSION"
80
- fi
81
- echo "version=$VERSION" >> $GITHUB_OUTPUT
82
- echo "Publishing version $VERSION"
83
-
84
- - name: Publish to GitHub Packages
85
- env:
86
- GITHUB_ACTOR: ${{ github.actor }}
87
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
88
- GITHUB_REPOSITORY: ${{ github.repository }}
89
- run: |
90
- VERSION="${{ steps.get_version.outputs.version }}"
91
- echo "🚀 Publishing version $VERSION to GitHub Packages"
92
- ./gradlew publishMavenPublicationToGitHubPackagesRepository -Pversion=$VERSION
@@ -1,70 +0,0 @@
1
- # project-auto-wizard:managed-workflow
2
- # ===================================================================
3
- # Spring Nexus 라이브러리 배포 워크플로우
4
- # ===================================================================
5
- #
6
- # 🔑 필수 GitHub Secrets
7
- # ===================================================================
8
- # GRADLE_PROPERTIES: gradle.properties 파일 내용 (Nexus 인증 정보 포함)
9
- # ===================================================================
10
-
11
- name: PROJECT-SPRING-NEXUS-PUBLISH
12
-
13
- on:
14
- push:
15
- branches: ["{{MAIN_BRANCH}}"]
16
- tags:
17
- - 'v*.*.*'
18
- # @wizard paths-anchor (모노레포일 때 integrator가 paths 필터를 여기 주입)
19
-
20
- concurrency:
21
- group: nexus-publish-${{ github.ref }}
22
- cancel-in-progress: false
23
-
24
- permissions:
25
- contents: read
26
-
27
- env:
28
- JAVA_VERSION: "__JAVA_VERSION__" # @wizard ask:@jdk
29
-
30
- jobs:
31
- publish:
32
- runs-on: ubuntu-latest
33
- steps:
34
- - uses: actions/checkout@v7
35
-
36
- - name: Set up JDK
37
- uses: actions/setup-java@v5
38
- with:
39
- java-version: ${{ env.JAVA_VERSION }}
40
- distribution: 'temurin'
41
-
42
- - name: Setup Gradle
43
- uses: gradle/gradle-build-action@v2
44
-
45
- - name: Create gradle.properties from secret
46
- run: |
47
- echo -e "${{ secrets.GRADLE_PROPERTIES }}" > gradle.properties
48
-
49
- - name: Get version
50
- id: get_version
51
- run: |
52
- if [[ "${{ github.ref }}" == refs/tags/* ]]; then
53
- # 태그에서 버전 추출
54
- TAG_NAME=${GITHUB_REF#refs/tags/}
55
- VERSION=${TAG_NAME#v}
56
- echo "🏷️ 태그에서 버전 추출: $VERSION"
57
- else
58
- # {{MAIN_BRANCH}} 브랜치에서 version.yml로부터 버전 추출
59
- VERSION=$(python3 .github/scripts/version_manager.py get | tail -n 1)
60
- echo "📄 version.yml에서 버전 추출: $VERSION"
61
- fi
62
- echo "version=$VERSION" >> $GITHUB_OUTPUT
63
- echo "Publishing version $VERSION"
64
-
65
- - name: Publish to Nexus
66
- run: |
67
- VERSION="${{ steps.get_version.outputs.version }}"
68
- echo "🚀 Publishing version $VERSION to Nexus Repository"
69
- ./gradlew publish -Pversion=$VERSION
70
-
@@ -1,102 +0,0 @@
1
- // 선택(opt-in) 워크플로우 포함 여부 질문 (.sh ask_optional_workflow L2651~2702 /
2
- // ask_all_optional_workflows L2708~2732 등가). Nexus publish + Secret 서버 백업.
3
- //
4
- // io 주입 계약(readline-engine 시그니처):
5
- // io.confirm({message, initialValue}) → bool | CANCEL(symbol)
6
- // io.log(line) → 안내 출력 (없으면 stderr)
7
- import { existsSync, readFileSync } from "node:fs";
8
- import { join } from "node:path";
9
- import { listYamlFiles } from "./fsutil.js";
10
- import { PATHS, PAYLOAD } from "./paths.js";
11
- import { parseTemplateOptions } from "./version-yml.js";
12
-
13
- // 재노출 — 파서 본체는 version-yml.js에 있다 (순환 import 방지: options-ask → version-yml 방향만 허용)
14
- export { parseTemplateOptions };
15
-
16
- const isCancel = (v) => typeof v === "symbol";
17
-
18
- // 옵션 1종 질문 (.sh ask_optional_workflow 등가).
19
- // 반환: true/false/null(폴더 없음·파일 0개로 질문 자체 생략 → 현재값 유지).
20
- async function askOptionalWorkflow({ dir, icon, short, desc, current, force, tty, io, forceAsk, say }) {
21
- // 폴더가 없거나 yaml이 0개면 조용히 건너뜀 (.sh L2664~2669) — 질문 자체가 성립 안 함
22
- if (!existsSync(dir)) return current;
23
- const files = listYamlFiles(dir);
24
- if (files.length === 0) return current;
25
-
26
- // 이미 값이 설정돼 있고 force-ask 아니면 유지 (CLI/version.yml 우선, .sh L2672~2674)
27
- if (!forceAsk && (current === true || current === false)) return current;
28
-
29
- // 비대화형(--force 또는 TTY 없음)이면 기본 제외 (.sh L2677~2679)
30
- if (force || !tty) return false;
31
-
32
- say("");
33
- say(`${icon} ${short} 워크플로우를 발견했습니다. (${files.length}개 파일)`);
34
- say(` ${desc}`);
35
- say("");
36
- say(" 포함되는 워크플로우:");
37
- for (const f of files) say(` • ${f}`);
38
- say("");
39
-
40
- const ans = await io.confirm({ message: `${short} 워크플로우를 포함할까요?`, initialValue: false });
41
- // ESC(취소)는 '아니오'와 동일 취급 (.sh ask_yes_no 비-0 반환 등가)
42
- const include = ans === true && !isCancel(ans);
43
- say(include
44
- ? `${short} 워크플로우를 포함합니다 — GitHub Actions에 추가됩니다`
45
- : `${short} 워크플로우를 제외합니다 (나중에 옵션으로 추가 가능)`);
46
- return include;
47
- }
48
-
49
- // 모든 opt-in 워크플로우를 순서대로 질문 (.sh ask_all_optional_workflows 등가).
50
- // payloadRoot: 패키지 payload/ 루트 — 타입 폴더는 {payloadRoot}/workflows/<type>
51
- // (copyWorkflows와 동일 규약)
52
- // current: { nexus: bool|null, secretBackup: bool|null } — CLI(--nexus 등) 명시값
53
- // 반환: { nexus: bool, secretBackup: bool } (미결정 null은 false로 확정)
54
- export async function askAllOptionalWorkflows({
55
- payloadRoot, types = [], current = {}, targetRoot = ".",
56
- force = false, tty = true, io = {}, forceAsk = false,
57
- }) {
58
- const say = io.log || ((m) => process.stderr.write(`${m}\n`));
59
- let nexus = current.nexus ?? null;
60
- let secretBackup = current.secretBackup ?? null;
61
-
62
- // ① --force-ask가 아니면 version.yml 저장값을 먼저 읽어 재질문을 건너뛴다 (.sh L2715~2717).
63
- // CLI 명시값(current)이 이미 있으면 그쪽이 우선 — 저장값은 빈 자리만 채운다.
64
- if (!forceAsk) {
65
- const vy = join(targetRoot, PATHS.versionFile);
66
- if (existsSync(vy)) {
67
- const saved = parseTemplateOptions(readFileSync(vy, "utf8"));
68
- if (nexus === null && saved.nexus !== null) {
69
- nexus = saved.nexus;
70
- say(`Nexus 옵션: version.yml 저장값(${nexus}) 유지 — 재질문 생략`);
71
- }
72
- if (secretBackup === null && saved.secretBackup !== null) {
73
- secretBackup = saved.secretBackup;
74
- say(`Secret 백업 옵션: version.yml 저장값(${secretBackup}) 유지 — 재질문 생략`);
75
- }
76
- }
77
- }
78
-
79
- // 타입 폴더 루트 — payload/workflows (copyWorkflows와 동일 규약)
80
- const ptDir = join(payloadRoot, PAYLOAD.workflowsDir);
81
-
82
- // ② Nexus: 각 타입의 nexus/ 폴더 (현재 spring만 존재, .sh L2719~2725)
83
- for (const t of types) {
84
- nexus = await askOptionalWorkflow({
85
- // GitHub Packages publish도 같은 '라이브러리 배포' 계열이라 이 질문이 함께 관장한다 (이슈 #80).
86
- // 종전에는 Nexus만 묻고 GitHub Packages는 무조건 설치돼, "라이브러리 배포 필요 없다"고
87
- // 답한 사용자에게 라이브러리 배포 워크플로우가 깔렸다.
88
- dir: join(ptDir, t, "nexus"), icon: "📦", short: "라이브러리 publish (Nexus · GitHub Packages)",
89
- desc: "라이브러리/모듈을 Maven 저장소(Nexus)나 GitHub Packages에 배포하는 워크플로우입니다. 일반 서버 배포가 아니라 라이브러리 프로젝트에만 필요합니다. 포함하면 서버 배포 워크플로우는 설치되지 않습니다.",
90
- current: nexus, force, tty, io, forceAsk, say,
91
- });
92
- }
93
- // ③ Secret 백업: 공통 폴더 (.sh L2726~2729)
94
- secretBackup = await askOptionalWorkflow({
95
- dir: join(ptDir, "common", "secret-backup"), icon: "🔐", short: "Secret 서버 백업",
96
- desc: "GitHub Secret에 저장한 설정 파일을 SSH로 서버에 업로드·이력관리하는 워크플로우입니다.",
97
- current: secretBackup, force, tty, io, forceAsk, say,
98
- });
99
-
100
- // ④ 미결정(null)은 false로 확정 — .sh에서 빈 INCLUDE_* 가 이후 false 취급되는 것과 동일
101
- return { nexus: nexus === true, secretBackup: secretBackup === true };
102
- }