project-auto-wizard 0.13.3 → 0.15.0

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 (115) hide show
  1. package/README.ja.md +2 -0
  2. package/README.ko.md +2 -0
  3. package/README.md +3 -1
  4. package/README.zh-CN.md +2 -0
  5. package/bin/project-auto-wizard.js +18 -4
  6. package/package.json +2 -2
  7. package/payload/config/breaking-changes.json +28 -14
  8. package/payload/config/wizard-prompts.yml +102 -46
  9. package/payload/flutter-app/android/fastlane/Fastfile.playstore +44 -32
  10. package/payload/flutter-app/ios/ExportOptions.plist +8 -8
  11. package/payload/flutter-app/ios/fastlane/Fastfile +57 -43
  12. package/payload/scripts/changelog_manager.py +304 -265
  13. package/payload/scripts/issue_helper.py +54 -50
  14. package/payload/scripts/messages.py +2585 -0
  15. package/payload/scripts/truncate_release_notes.py +7 -6
  16. package/payload/scripts/version_manager.py +110 -107
  17. package/payload/version.yml.template +2 -1
  18. package/payload/workflows/common/PROJECT-COMMON-AI-PR-SUMMARY.yaml +23 -16
  19. package/payload/workflows/common/PROJECT-COMMON-AUTO-CHANGELOG-CONTROL.yaml +106 -63
  20. package/payload/workflows/common/PROJECT-COMMON-ISSUE-HELPER.yaml +17 -15
  21. package/payload/workflows/common/PROJECT-COMMON-README-VERSION-UPDATE.yaml +55 -45
  22. package/payload/workflows/common/PROJECT-COMMON-RELEASE-PUBLISH.yaml +90 -72
  23. package/payload/workflows/common/PROJECT-COMMON-VERSION-CONTROL.yaml +59 -45
  24. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-FIREBASE-CICD.yaml +194 -184
  25. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +226 -213
  26. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-SELFHOSTED-CICD.yaml +46 -42
  27. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +334 -241
  28. package/payload/workflows/flutter/PROJECT-FLUTTER-APP-BUILD-TRIGGER.yaml +152 -128
  29. package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +246 -188
  30. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +353 -238
  31. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TESTFLIGHT.yaml +96 -85
  32. package/payload/workflows/go/PROJECT-GO-CI.yaml +47 -36
  33. package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +945 -508
  34. package/payload/workflows/go/PROJECT-GO-SIMPLE-CICD.yaml +155 -133
  35. package/payload/workflows/next/PROJECT-NEXT-CI.yaml +76 -60
  36. package/payload/workflows/next/PROJECT-NEXT-CICD.yaml +97 -77
  37. package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +62 -47
  38. package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +942 -505
  39. package/payload/workflows/python/PROJECT-PYTHON-SIMPLE-CICD.yaml +148 -126
  40. package/payload/workflows/react/PROJECT-REACT-CI.yaml +86 -70
  41. package/payload/workflows/react/PROJECT-REACT-CICD.yaml +112 -92
  42. package/payload/workflows/spring/PROJECT-SPRING-CI.yml +112 -82
  43. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-NGINX-CICD.yaml +180 -150
  44. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-TRAEFIK-CICD.yaml +161 -131
  45. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +970 -549
  46. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-SIMPLE-CICD.yaml +193 -162
  47. package/src/cli/args.js +98 -52
  48. package/src/cli/help.js +8 -41
  49. package/src/commands/doctor.js +90 -89
  50. package/src/commands/dry-run.js +64 -43
  51. package/src/commands/full.js +79 -77
  52. package/src/commands/install-settings.js +16 -15
  53. package/src/commands/interactive-flutter.js +20 -19
  54. package/src/commands/interactive.js +135 -132
  55. package/src/commands/purge.js +47 -42
  56. package/src/commands/status.js +36 -36
  57. package/src/commands/uninstall.js +43 -41
  58. package/src/context.js +12 -11
  59. package/src/core/assets.js +12 -11
  60. package/src/core/baseline.js +27 -27
  61. package/src/core/branches.js +29 -27
  62. package/src/core/branding.js +7 -6
  63. package/src/core/breaking-check.js +22 -21
  64. package/src/core/breaking.js +15 -8
  65. package/src/core/copy/app-files.js +5 -4
  66. package/src/core/copy/flutter-app.js +8 -8
  67. package/src/core/copy/gitignore.js +58 -50
  68. package/src/core/copy/readme.js +102 -36
  69. package/src/core/copy/simple.js +16 -15
  70. package/src/core/copy/workflows.js +131 -124
  71. package/src/core/deploy-style.js +51 -48
  72. package/src/core/detect-fs.js +57 -57
  73. package/src/core/detect.js +67 -65
  74. package/src/core/errors.js +2 -2
  75. package/src/core/flutter-doctor.js +17 -16
  76. package/src/core/flutter-hooks.js +33 -32
  77. package/src/core/flutter-options.js +34 -33
  78. package/src/core/fsutil.js +12 -12
  79. package/src/core/installed-stores.js +4 -4
  80. package/src/core/logger.js +42 -40
  81. package/src/core/paths-resolve.js +88 -86
  82. package/src/core/paths.js +10 -10
  83. package/src/core/release-options.js +8 -8
  84. package/src/core/removal-exec.js +14 -13
  85. package/src/core/removal-plan.js +37 -37
  86. package/src/core/types.js +47 -47
  87. package/src/core/verify.js +44 -38
  88. package/src/core/version-yml.js +76 -68
  89. package/src/core/wizard-env.js +46 -46
  90. package/src/core/wizard-labels.js +63 -41
  91. package/src/i18n/catalog/en/cli.js +50 -0
  92. package/src/i18n/catalog/en/commands.js +188 -0
  93. package/src/i18n/catalog/en/copy.js +20 -0
  94. package/src/i18n/catalog/en/core.js +74 -0
  95. package/src/i18n/catalog/en/core2.js +15 -0
  96. package/src/i18n/catalog/en/ui.js +221 -0
  97. package/src/i18n/catalog/en.js +12 -0
  98. package/src/i18n/catalog/index.js +5 -0
  99. package/src/i18n/catalog/ko/cli.js +50 -0
  100. package/src/i18n/catalog/ko/commands.js +188 -0
  101. package/src/i18n/catalog/ko/copy.js +20 -0
  102. package/src/i18n/catalog/ko/core.js +74 -0
  103. package/src/i18n/catalog/ko/core2.js +15 -0
  104. package/src/i18n/catalog/ko/ui.js +221 -0
  105. package/src/i18n/catalog/ko.js +10 -0
  106. package/src/i18n/index.js +44 -0
  107. package/src/i18n/languages.js +9 -0
  108. package/src/index.js +132 -97
  109. package/src/ui/ansi.js +7 -7
  110. package/src/ui/banner.js +7 -6
  111. package/src/ui/env-plan.js +82 -81
  112. package/src/ui/prompts.js +97 -122
  113. package/src/ui/readline-engine.js +59 -58
  114. package/src/ui/status-cards.js +37 -31
  115. package/src/ui/summary.js +90 -89
@@ -1,5 +1,5 @@
1
1
  # project-auto-wizard:managed-workflow
2
- # Spring CI 워크플로우
2
+ # Spring CI workflow
3
3
 
4
4
  name: PROJECT-SPRING-CI
5
5
 
@@ -19,13 +19,13 @@ permissions:
19
19
 
20
20
  env:
21
21
  JAVA_VERSION: "__JAVA_VERSION__" # @wizard ask:@jdk
22
- # 모노레포에서 이 프로젝트가 있는 하위 경로 ('.'이면 항상 검증)
22
+ # Subdirectory of this project in a monorepo ('.' = always verify)
23
23
  PROJECT_PATH: "." # @wizard auto:project-path
24
24
 
25
25
  jobs:
26
- # 변경 감지 (모노레포에서 이 프로젝트 경로가 바뀌었는지 판별)
26
+ # Change detection (decides whether this project's path changed in a monorepo)
27
27
  changes:
28
- name: 변경 감지
28
+ name: Detect changes
29
29
  runs-on: ubuntu-latest
30
30
  permissions:
31
31
  contents: read
@@ -36,13 +36,13 @@ jobs:
36
36
  - name: Checkout repository
37
37
  uses: actions/checkout@v7
38
38
 
39
- - name: 프로젝트 경로 변경 여부 판별
39
+ - name: Detect project path changes
40
40
  id: filter
41
41
  if: ${{ github.event_name != 'workflow_dispatch' }}
42
42
  uses: dorny/paths-filter@v4
43
43
  with:
44
- # push는 이번 push 범위(직전 커밋 before 대비)만 본다. 비워 두면 기본 브랜치 대비 누적 diff가 된다.
45
- # 새 브랜치 첫 push(before가 0)와 PR은 빈 값 → 기본 동작(기본 브랜치·PR base 대비)
44
+ # A push only looks at this push's range (against the previous commit, 'before'). Left empty it would diff cumulatively against the default branch.
45
+ # The first push of a new branch (before is 0) and PRs use an empty value -> default behavior (against the default branch / PR base)
46
46
  base: ${{ github.event_name == 'push' && github.event.before != '0000000000000000000000000000000000000000' && github.event.before || '' }}
47
47
  filters: |
48
48
  project:
@@ -53,7 +53,7 @@ jobs:
53
53
  runs-on: ubuntu-latest
54
54
  needs: changes
55
55
  if: ${{ github.event_name == 'workflow_dispatch' || needs.changes.outputs.project == 'true' }}
56
- # 모노레포(--paths)면 그 하위 폴더에서 빌드한다
56
+ # In a monorepo (--paths) build inside that subfolder
57
57
  defaults:
58
58
  run:
59
59
  working-directory: ${{ env.PROJECT_PATH }}
@@ -64,6 +64,9 @@ jobs:
64
64
  with:
65
65
  fetch-depth: 0
66
66
 
67
+ - name: Load messages
68
+ run: echo "PAW_MSG=$(python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" dump wf_spring_ci.)" >> "$GITHUB_ENV"
69
+
67
70
  - name: Setup JDK
68
71
  uses: actions/setup-java@v5
69
72
  with:
@@ -87,7 +90,7 @@ jobs:
87
90
  run: |
88
91
  set +e
89
92
  ./gradlew compileJava compileTestJava 2>&1 | tee compile_output.txt
90
- # $?는 tee의 종료 코드라 gradle 결과는 PIPESTATUS로 읽는다
93
+ # $? is tee's exit code, so read gradle's result from PIPESTATUS
91
94
  echo "compile_exit_code=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT
92
95
  set -e
93
96
  continue-on-error: true
@@ -97,7 +100,7 @@ jobs:
97
100
  run: |
98
101
  set +e
99
102
  ./gradlew test 2>&1 | tee test_output.txt
100
- # $?는 tee의 종료 코드라 gradle 결과는 PIPESTATUS로 읽는다
103
+ # $? is tee's exit code, so read gradle's result from PIPESTATUS
101
104
  echo "test_exit_code=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT
102
105
  set -e
103
106
  continue-on-error: true
@@ -107,7 +110,7 @@ jobs:
107
110
  run: |
108
111
  set +e
109
112
  ./gradlew build -x test 2>&1 | tee build_output.txt
110
- # $?는 tee의 종료 코드라 gradle 결과는 PIPESTATUS로 읽는다
113
+ # $? is tee's exit code, so read gradle's result from PIPESTATUS
111
114
  echo "build_exit_code=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT
112
115
  set -e
113
116
  continue-on-error: true
@@ -116,101 +119,113 @@ jobs:
116
119
  id: report
117
120
  if: always()
118
121
  run: |
119
- COMPILE_STATUS="✅ 성공"
120
- TEST_STATUS="✅ 성공"
121
- BUILD_STATUS="✅ 성공"
122
+ m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
123
+ STATUS_OK="$(m wf_spring_ci.status_ok)"
124
+ STATUS_FAIL="$(m wf_spring_ci.status_fail)"
125
+ COMPILE_STATUS="$STATUS_OK"
126
+ TEST_STATUS="$STATUS_OK"
127
+ BUILD_STATUS="$STATUS_OK"
122
128
 
123
129
  COMPILE_EXIT_CODE="${{ steps.compile.outputs.compile_exit_code }}"
124
130
  if [ "$COMPILE_EXIT_CODE" != "0" ] && [ "$COMPILE_EXIT_CODE" != "" ]; then
125
- COMPILE_STATUS="❌ 실패"
131
+ COMPILE_STATUS="$STATUS_FAIL"
126
132
  fi
127
133
 
128
134
  TEST_EXIT_CODE="${{ steps.test.outputs.test_exit_code }}"
129
135
  if [ "$TEST_EXIT_CODE" != "0" ] && [ "$TEST_EXIT_CODE" != "" ]; then
130
- TEST_STATUS="❌ 실패"
136
+ TEST_STATUS="$STATUS_FAIL"
131
137
  fi
132
138
 
133
139
  BUILD_EXIT_CODE="${{ steps.build.outputs.build_exit_code }}"
134
140
  if [ "$BUILD_EXIT_CODE" != "0" ] && [ "$BUILD_EXIT_CODE" != "" ]; then
135
- BUILD_STATUS="❌ 실패"
141
+ BUILD_STATUS="$STATUS_FAIL"
136
142
  fi
137
143
 
138
- OVERALL_STATUS="✅ 성공"
144
+ OVERALL_STATUS="$STATUS_OK"
145
+ OVERALL_OK=true
139
146
  if [ "$COMPILE_EXIT_CODE" != "0" ] || [ "$TEST_EXIT_CODE" != "0" ] || [ "$BUILD_EXIT_CODE" != "0" ]; then
140
- OVERALL_STATUS="❌ 실패"
147
+ OVERALL_STATUS="$STATUS_FAIL"
148
+ OVERALL_OK=false
141
149
  fi
142
150
 
143
151
  echo "compile_status=$COMPILE_STATUS" >> $GITHUB_OUTPUT
144
152
  echo "test_status=$TEST_STATUS" >> $GITHUB_OUTPUT
145
153
  echo "build_status=$BUILD_STATUS" >> $GITHUB_OUTPUT
146
154
  echo "overall_status=$OVERALL_STATUS" >> $GITHUB_OUTPUT
155
+ # Language-neutral flag for the step conditions below
156
+ echo "overall_ok=$OVERALL_OK" >> $GITHUB_OUTPUT
147
157
 
148
158
  - name: Extract Error Details
149
159
  id: errors
150
160
  if: always()
151
161
  run: |
162
+ m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
152
163
  if [ -f compile_output.txt ] && [ "${{ steps.compile.outputs.compile_exit_code }}" != "0" ]; then
153
164
  echo "compile_errors<<EOF" >> $GITHUB_OUTPUT
154
- echo "## 🚨 컴파일 에러" >> $GITHUB_OUTPUT
165
+ m wf_spring_ci.err_compile_header >> $GITHUB_OUTPUT
155
166
  echo "" >> $GITHUB_OUTPUT
156
167
  echo '```' >> $GITHUB_OUTPUT
157
- grep -A 15 -B 15 "error\|Error\|ERROR\|FAILED\|Failed\|failed" compile_output.txt | head -60 >> $GITHUB_OUTPUT || echo "에러 로그를 찾을 수 없습니다." >> $GITHUB_OUTPUT
168
+ grep -A 15 -B 15 "error\|Error\|ERROR\|FAILED\|Failed\|failed" compile_output.txt | head -60 >> $GITHUB_OUTPUT || m wf_spring_ci.err_compile_missing >> $GITHUB_OUTPUT
158
169
  echo '```' >> $GITHUB_OUTPUT
159
170
  echo "EOF" >> $GITHUB_OUTPUT
160
171
  fi
161
172
 
162
173
  if [ -f test_output.txt ] && [ "${{ steps.test.outputs.test_exit_code }}" != "0" ]; then
163
174
  echo "test_errors<<EOF" >> $GITHUB_OUTPUT
164
- echo "## 🧪 테스트 실패" >> $GITHUB_OUTPUT
175
+ m wf_spring_ci.err_test_header >> $GITHUB_OUTPUT
165
176
  echo "" >> $GITHUB_OUTPUT
166
177
  echo '```' >> $GITHUB_OUTPUT
167
- grep -A 15 -B 15 "FAILED\|Failed\|failed\|error\|Error\|ERROR" test_output.txt | head -60 >> $GITHUB_OUTPUT || echo "테스트 에러 로그를 찾을 수 없습니다." >> $GITHUB_OUTPUT
178
+ grep -A 15 -B 15 "FAILED\|Failed\|failed\|error\|Error\|ERROR" test_output.txt | head -60 >> $GITHUB_OUTPUT || m wf_spring_ci.err_test_missing >> $GITHUB_OUTPUT
168
179
  echo '```' >> $GITHUB_OUTPUT
169
180
  echo "EOF" >> $GITHUB_OUTPUT
170
181
  fi
171
182
 
172
183
  if [ -f build_output.txt ] && [ "${{ steps.build.outputs.build_exit_code }}" != "0" ]; then
173
184
  echo "build_errors<<EOF" >> $GITHUB_OUTPUT
174
- echo "## 📦 빌드 에러" >> $GITHUB_OUTPUT
185
+ m wf_spring_ci.err_build_header >> $GITHUB_OUTPUT
175
186
  echo "" >> $GITHUB_OUTPUT
176
187
  echo '```' >> $GITHUB_OUTPUT
177
- grep -A 15 -B 15 "FAILED\|Failed\|failed\|error\|Error\|ERROR" build_output.txt | head -60 >> $GITHUB_OUTPUT || echo "빌드 에러 로그를 찾을 수 없습니다." >> $GITHUB_OUTPUT
188
+ grep -A 15 -B 15 "FAILED\|Failed\|failed\|error\|Error\|ERROR" build_output.txt | head -60 >> $GITHUB_OUTPUT || m wf_spring_ci.err_build_missing >> $GITHUB_OUTPUT
178
189
  echo '```' >> $GITHUB_OUTPUT
179
190
  echo "EOF" >> $GITHUB_OUTPUT
180
191
  fi
181
192
 
182
193
  - name: Comment on PR (Success)
183
- if: github.event_name == 'pull_request' && steps.report.outputs.overall_status == '✅ 성공'
194
+ if: github.event_name == 'pull_request' && steps.report.outputs.overall_ok == 'true'
184
195
  uses: actions/github-script@v9
185
196
  with:
186
197
  github-token: ${{ secrets.GITHUB_TOKEN }}
187
198
  script: |
199
+ const M = JSON.parse(process.env.PAW_MSG);
200
+ const m = (k, p = {}) => M['wf_spring_ci.' + k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
188
201
  const { data: comments } = await github.rest.issues.listComments({
189
202
  owner: context.repo.owner,
190
203
  repo: context.repo.repo,
191
204
  issue_number: context.issue.number,
192
205
  });
193
206
 
194
- // 기존 봇 댓글 찾기
207
+ // Find the existing bot comment
195
208
  const botComment = comments.find(comment =>
196
209
  comment.user.type === 'Bot' &&
197
210
  comment.body.includes('🔧 CI Build Check')
198
211
  );
199
212
 
200
- const successMessage = `## 🔧 CI Build Check 결과
201
-
202
- ### ✅ 빌드 성공!
203
-
204
- | 단계 | 상태 |
205
- |------|------|
206
- | 컴파일 | ${{ steps.report.outputs.compile_status }} |
207
- | 테스트 | ${{ steps.report.outputs.test_status }} |
208
- | 빌드 | ${{ steps.report.outputs.build_status }} |
209
-
210
- **전체 상태**: ${{ steps.report.outputs.overall_status }}
211
-
212
- ---
213
- *🤖 GitHub Actions에 의해 자동 생성됨 - ${new Date().toLocaleString('ko-KR', { timeZone: 'Asia/Seoul' })}*`;
213
+ const successMessage = [
214
+ m('comment_title'),
215
+ '',
216
+ m('comment_success'),
217
+ '',
218
+ m('table_header'),
219
+ '|------|------|',
220
+ m('row_compile', { status: '${{ steps.report.outputs.compile_status }}' }),
221
+ m('row_test', { status: '${{ steps.report.outputs.test_status }}' }),
222
+ m('row_build', { status: '${{ steps.report.outputs.build_status }}' }),
223
+ '',
224
+ m('overall', { status: '${{ steps.report.outputs.overall_status }}' }),
225
+ '',
226
+ '---',
227
+ m('footer', { time: new Date().toLocaleString(m('date_locale'), { timeZone: 'Asia/Seoul' }) }),
228
+ ].join('\n');
214
229
 
215
230
  if (botComment) {
216
231
  await github.rest.issues.updateComment({
@@ -229,18 +244,20 @@ jobs:
229
244
  }
230
245
 
231
246
  - name: Comment on PR (Failure)
232
- if: github.event_name == 'pull_request' && steps.report.outputs.overall_status == '❌ 실패'
247
+ if: github.event_name == 'pull_request' && steps.report.outputs.overall_ok == 'false'
233
248
  uses: actions/github-script@v9
234
249
  with:
235
250
  github-token: ${{ secrets.GITHUB_TOKEN }}
236
251
  script: |
252
+ const M = JSON.parse(process.env.PAW_MSG);
253
+ const m = (k, p = {}) => M['wf_spring_ci.' + k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
237
254
  const { data: comments } = await github.rest.issues.listComments({
238
255
  owner: context.repo.owner,
239
256
  repo: context.repo.repo,
240
257
  issue_number: context.issue.number,
241
258
  });
242
259
 
243
- // 기존 봇 댓글 찾기
260
+ // Find the existing bot comment
244
261
  const botComment = comments.find(comment =>
245
262
  comment.user.type === 'Bot' &&
246
263
  comment.body.includes('🔧 CI Build Check')
@@ -248,44 +265,46 @@ jobs:
248
265
 
249
266
  let errorDetails = '';
250
267
 
251
- // 컴파일 에러 추가
268
+ // Append compile errors
252
269
  if ('${{ steps.errors.outputs.compile_errors }}') {
253
270
  errorDetails += '${{ steps.errors.outputs.compile_errors }}\n\n';
254
271
  }
255
272
 
256
- // 테스트 에러 추가
273
+ // Append test errors
257
274
  if ('${{ steps.errors.outputs.test_errors }}') {
258
275
  errorDetails += '${{ steps.errors.outputs.test_errors }}\n\n';
259
276
  }
260
277
 
261
- // 빌드 에러 추가
278
+ // Append build errors
262
279
  if ('${{ steps.errors.outputs.build_errors }}') {
263
280
  errorDetails += '${{ steps.errors.outputs.build_errors }}\n\n';
264
281
  }
265
282
 
266
- const failureMessage = `## 🔧 CI Build Check 결과
267
-
268
- ### ❌ 빌드 실패!
269
-
270
- | 단계 | 상태 |
271
- |------|------|
272
- | 컴파일 | ${{ steps.report.outputs.compile_status }} |
273
- | 테스트 | ${{ steps.report.outputs.test_status }} |
274
- | 빌드 | ${{ steps.report.outputs.build_status }} |
275
-
276
- **전체 상태**: ${{ steps.report.outputs.overall_status }}
277
-
278
- ### 📋 에러 상세 정보
279
-
280
- ${errorDetails}
281
-
282
- ### 🔧 해결 방법
283
- - 로컬에서 \`./gradlew clean build\` 명령어로 빌드를 확인해보세요
284
- - 에러 메시지를 참고하여 코드를 수정해주세요
285
- - 테스트가 실패한 경우 \`./gradlew test\` 명령어로 테스트를 실행해보세요
286
-
287
- ---
288
- *🤖 GitHub Actions에 의해 자동 생성됨 - ${new Date().toLocaleString('ko-KR', { timeZone: 'Asia/Seoul' })}*`;
283
+ const failureMessage = [
284
+ m('comment_title'),
285
+ '',
286
+ m('comment_failure'),
287
+ '',
288
+ m('table_header'),
289
+ '|------|------|',
290
+ m('row_compile', { status: '${{ steps.report.outputs.compile_status }}' }),
291
+ m('row_test', { status: '${{ steps.report.outputs.test_status }}' }),
292
+ m('row_build', { status: '${{ steps.report.outputs.build_status }}' }),
293
+ '',
294
+ m('overall', { status: '${{ steps.report.outputs.overall_status }}' }),
295
+ '',
296
+ m('details_header'),
297
+ '',
298
+ errorDetails,
299
+ '',
300
+ m('fix_header'),
301
+ m('fix_build'),
302
+ m('fix_error'),
303
+ m('fix_test'),
304
+ '',
305
+ '---',
306
+ m('footer', { time: new Date().toLocaleString(m('date_locale'), { timeZone: 'Asia/Seoul' }) }),
307
+ ].join('\n');
289
308
 
290
309
  if (botComment) {
291
310
  await github.rest.issues.updateComment({
@@ -309,8 +328,10 @@ jobs:
309
328
  with:
310
329
  github-token: ${{ secrets.GITHUB_TOKEN }}
311
330
  script: |
312
- const conclusion = '${{ steps.report.outputs.overall_status }}' === '✅ 성공' ? 'success' : 'failure';
313
- const summary = `빌드 검증이 ${conclusion === 'success' ? '성공' : '실패'}했습니다.`;
331
+ const M = JSON.parse(process.env.PAW_MSG);
332
+ const m = (k, p = {}) => M['wf_spring_ci.' + k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
333
+ const conclusion = '${{ steps.report.outputs.overall_ok }}' === 'true' ? 'success' : 'failure';
334
+ const summary = m(conclusion === 'success' ? 'check_summary_success' : 'check_summary_failure');
314
335
 
315
336
  await github.rest.checks.create({
316
337
  owner: context.repo.owner,
@@ -322,33 +343,42 @@ jobs:
322
343
  output: {
323
344
  title: '🔧 CI Build Check',
324
345
  summary: summary,
325
- text: `
326
- 컴파일: ${{ steps.report.outputs.compile_status }}
327
- 테스트: ${{ steps.report.outputs.test_status }}
328
- 빌드: ${{ steps.report.outputs.build_status }}
329
- `
346
+ text: '\n ' + m('check_compile', { status: '${{ steps.report.outputs.compile_status }}' }) +
347
+ '\n ' + m('check_test', { status: '${{ steps.report.outputs.test_status }}' }) + ' ' +
348
+ '\n ' + m('check_build', { status: '${{ steps.report.outputs.build_status }}' }) +
349
+ '\n '
330
350
  }
331
351
  });
332
352
 
333
353
  - name: Fail Job on Build Failure
334
- if: steps.report.outputs.overall_status == '❌ 실패'
354
+ if: steps.report.outputs.overall_ok == 'false'
335
355
  run: |
336
- echo "❌ 빌드가 실패했습니다. 위의 에러 메시지를 확인해주세요."
356
+ python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get wf_spring_ci.build_failed
337
357
  exit 1
338
358
 
339
- # CI Gate (required check로 등록할 단일 job)
359
+ # CI Gate (the single job to register as a required check)
340
360
  ci-gate:
341
361
  name: CI Gate
342
362
  if: ${{ always() }}
343
363
  needs: [changes, build-check]
344
364
  runs-on: ubuntu-latest
345
365
  steps:
346
- - name: 결과 집계
366
+ # Sparse checkout: only the message catalog and version.yml (language setting) are needed here
367
+ - name: Checkout message catalog
368
+ uses: actions/checkout@v7
369
+ with:
370
+ sparse-checkout: |
371
+ .github/scripts/messages.py
372
+ version.yml
373
+ sparse-checkout-cone-mode: false
374
+
375
+ - name: Aggregate results
347
376
  env:
348
377
  RESULTS: ${{ toJSON(needs.*.result) }}
349
378
  run: |
350
- echo "needs 결과: $RESULTS"
379
+ m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
380
+ m wf_spring_ci.gate_results results="$RESULTS"
351
381
  if echo "$RESULTS" | grep -Eq '"(failure|cancelled)"'; then
352
- echo "실패하거나 취소된 job이 있습니다."
382
+ m wf_spring_ci.gate_failed
353
383
  exit 1
354
384
  fi