project-auto-wizard 0.13.3 → 0.14.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 (112) hide show
  1. package/README.md +1 -1
  2. package/bin/project-auto-wizard.js +18 -4
  3. package/package.json +2 -2
  4. package/payload/config/breaking-changes.json +28 -14
  5. package/payload/config/wizard-prompts.yml +102 -46
  6. package/payload/flutter-app/android/fastlane/Fastfile.playstore +44 -32
  7. package/payload/flutter-app/ios/ExportOptions.plist +8 -8
  8. package/payload/flutter-app/ios/fastlane/Fastfile +57 -43
  9. package/payload/scripts/changelog_manager.py +296 -257
  10. package/payload/scripts/issue_helper.py +54 -50
  11. package/payload/scripts/messages.py +2279 -0
  12. package/payload/scripts/truncate_release_notes.py +7 -6
  13. package/payload/scripts/version_manager.py +64 -61
  14. package/payload/version.yml.template +2 -1
  15. package/payload/workflows/common/PROJECT-COMMON-AI-PR-SUMMARY.yaml +17 -12
  16. package/payload/workflows/common/PROJECT-COMMON-AUTO-CHANGELOG-CONTROL.yaml +59 -34
  17. package/payload/workflows/common/PROJECT-COMMON-ISSUE-HELPER.yaml +17 -15
  18. package/payload/workflows/common/PROJECT-COMMON-README-VERSION-UPDATE.yaml +17 -10
  19. package/payload/workflows/common/PROJECT-COMMON-RELEASE-PUBLISH.yaml +54 -44
  20. package/payload/workflows/common/PROJECT-COMMON-VERSION-CONTROL.yaml +24 -17
  21. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-FIREBASE-CICD.yaml +194 -184
  22. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +226 -213
  23. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-SELFHOSTED-CICD.yaml +46 -42
  24. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +334 -241
  25. package/payload/workflows/flutter/PROJECT-FLUTTER-APP-BUILD-TRIGGER.yaml +152 -128
  26. package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +246 -188
  27. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +353 -238
  28. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TESTFLIGHT.yaml +96 -85
  29. package/payload/workflows/go/PROJECT-GO-CI.yaml +47 -36
  30. package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +945 -508
  31. package/payload/workflows/go/PROJECT-GO-SIMPLE-CICD.yaml +155 -133
  32. package/payload/workflows/next/PROJECT-NEXT-CI.yaml +76 -60
  33. package/payload/workflows/next/PROJECT-NEXT-CICD.yaml +97 -77
  34. package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +62 -47
  35. package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +942 -505
  36. package/payload/workflows/python/PROJECT-PYTHON-SIMPLE-CICD.yaml +148 -126
  37. package/payload/workflows/react/PROJECT-REACT-CI.yaml +86 -70
  38. package/payload/workflows/react/PROJECT-REACT-CICD.yaml +112 -92
  39. package/payload/workflows/spring/PROJECT-SPRING-CI.yml +112 -82
  40. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-NGINX-CICD.yaml +180 -150
  41. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-TRAEFIK-CICD.yaml +161 -131
  42. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +970 -549
  43. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-SIMPLE-CICD.yaml +193 -162
  44. package/src/cli/args.js +98 -52
  45. package/src/cli/help.js +8 -41
  46. package/src/commands/doctor.js +85 -89
  47. package/src/commands/dry-run.js +63 -43
  48. package/src/commands/full.js +79 -77
  49. package/src/commands/install-settings.js +16 -15
  50. package/src/commands/interactive-flutter.js +20 -19
  51. package/src/commands/interactive.js +135 -132
  52. package/src/commands/purge.js +47 -42
  53. package/src/commands/status.js +36 -36
  54. package/src/commands/uninstall.js +43 -41
  55. package/src/context.js +12 -11
  56. package/src/core/assets.js +12 -11
  57. package/src/core/baseline.js +27 -27
  58. package/src/core/branches.js +29 -27
  59. package/src/core/branding.js +7 -6
  60. package/src/core/breaking-check.js +22 -21
  61. package/src/core/breaking.js +15 -8
  62. package/src/core/copy/app-files.js +5 -4
  63. package/src/core/copy/flutter-app.js +8 -8
  64. package/src/core/copy/gitignore.js +58 -50
  65. package/src/core/copy/readme.js +45 -35
  66. package/src/core/copy/simple.js +16 -15
  67. package/src/core/copy/workflows.js +131 -124
  68. package/src/core/deploy-style.js +51 -48
  69. package/src/core/detect-fs.js +57 -57
  70. package/src/core/detect.js +67 -65
  71. package/src/core/errors.js +2 -2
  72. package/src/core/flutter-doctor.js +17 -16
  73. package/src/core/flutter-hooks.js +33 -32
  74. package/src/core/flutter-options.js +34 -33
  75. package/src/core/fsutil.js +12 -12
  76. package/src/core/installed-stores.js +4 -4
  77. package/src/core/logger.js +42 -40
  78. package/src/core/paths-resolve.js +88 -86
  79. package/src/core/paths.js +10 -10
  80. package/src/core/release-options.js +8 -8
  81. package/src/core/removal-exec.js +14 -13
  82. package/src/core/removal-plan.js +37 -37
  83. package/src/core/types.js +47 -47
  84. package/src/core/verify.js +44 -38
  85. package/src/core/version-yml.js +76 -68
  86. package/src/core/wizard-env.js +46 -46
  87. package/src/core/wizard-labels.js +63 -41
  88. package/src/i18n/catalog/en/cli.js +50 -0
  89. package/src/i18n/catalog/en/commands.js +187 -0
  90. package/src/i18n/catalog/en/copy.js +19 -0
  91. package/src/i18n/catalog/en/core.js +74 -0
  92. package/src/i18n/catalog/en/core2.js +15 -0
  93. package/src/i18n/catalog/en/ui.js +221 -0
  94. package/src/i18n/catalog/en.js +12 -0
  95. package/src/i18n/catalog/index.js +5 -0
  96. package/src/i18n/catalog/ko/cli.js +50 -0
  97. package/src/i18n/catalog/ko/commands.js +187 -0
  98. package/src/i18n/catalog/ko/copy.js +19 -0
  99. package/src/i18n/catalog/ko/core.js +74 -0
  100. package/src/i18n/catalog/ko/core2.js +15 -0
  101. package/src/i18n/catalog/ko/ui.js +221 -0
  102. package/src/i18n/catalog/ko.js +10 -0
  103. package/src/i18n/index.js +44 -0
  104. package/src/i18n/languages.js +9 -0
  105. package/src/index.js +128 -94
  106. package/src/ui/ansi.js +7 -7
  107. package/src/ui/banner.js +7 -6
  108. package/src/ui/env-plan.js +82 -81
  109. package/src/ui/prompts.js +97 -122
  110. package/src/ui/readline-engine.js +59 -58
  111. package/src/ui/status-cards.js +37 -31
  112. package/src/ui/summary.js +89 -88
@@ -1,56 +1,56 @@
1
1
  # project-auto-wizard:managed-workflow
2
- # Flutter iOS TestFlight 자동 배포 워크플로우
2
+ # Flutter iOS TestFlight deploy workflow
3
3
  #
4
- # 이 워크플로우는 Flutter iOS 앱을 빌드하여 TestFlight에 자동 배포합니다.
4
+ # Builds the Flutter iOS app and deploys it to TestFlight automatically.
5
5
  #
6
- # 설정 파일(ios/fastlane/Fastfile, ios/ExportOptions.plist)은 project-auto-wizard가
7
- # 없을 때만 설치하며, 이미 있으면 덮어쓰지 않습니다.
6
+ # The config files (ios/fastlane/Fastfile, ios/ExportOptions.plist) are installed by
7
+ # project-auto-wizard only when missing; existing files are never overwritten.
8
8
  #
9
- # 빌드 파이프라인:
10
- # 1. flutter build ios --no-codesign (Flutter 빌드)
11
- # 2. xcodebuild archive (Xcode 아카이브 생성)
12
- # 3. xcodebuild -exportArchive (IPA 생성, ExportOptions.plist 사용)
13
- # 4. fastlane deploy (ios/fastlane/Fastfile 사용, DEPLOY_MODE에 따라 TestFlight/심사 제출)
9
+ # Build pipeline:
10
+ # 1. flutter build ios --no-codesign (Flutter build)
11
+ # 2. xcodebuild archive (create the Xcode archive)
12
+ # 3. xcodebuild -exportArchive (create the IPA using ExportOptions.plist)
13
+ # 4. fastlane deploy (uses ios/fastlane/Fastfile; TestFlight or review submission depending on DEPLOY_MODE)
14
14
  #
15
- # 필수 GitHub Secrets
15
+ # Required GitHub Secrets
16
16
  #
17
- # Apple 인증서 & 프로비저닝 프로파일:
18
- # APPLE_CERTIFICATE_BASE64: .p12 인증서 (base64 인코딩)
19
- # APPLE_CERTIFICATE_PASSWORD: .p12 인증서 비밀번호
20
- # APPLE_PROVISIONING_PROFILE_BASE64: .mobileprovision 파일 (base64 인코딩)
21
- # IOS_PROVISIONING_PROFILE_NAME: 프로비저닝 프로파일 이름
17
+ # Apple certificate & provisioning profile:
18
+ # APPLE_CERTIFICATE_BASE64: .p12 certificate (base64 encoded)
19
+ # APPLE_CERTIFICATE_PASSWORD: .p12 certificate password
20
+ # APPLE_PROVISIONING_PROFILE_BASE64: .mobileprovision file (base64 encoded)
21
+ # IOS_PROVISIONING_PROFILE_NAME: provisioning profile name
22
22
  #
23
23
  # App Store Connect API:
24
- # APP_STORE_CONNECT_API_KEY_ID: API Key ID (10자리)
25
- # APP_STORE_CONNECT_ISSUER_ID: Issuer ID (UUID 형식)
26
- # APP_STORE_CONNECT_API_KEY_BASE64: AuthKey_XXXXXX.p8 파일 (base64 인코딩)
27
- # IOS_BUNDLE_ID (Secret 우선, 없으면 Variable): 앱 번들 ID —
28
- # store_prepare/store_submit을 쓰면 필수(비어 있으면 Fastfile이 명확한 오류로 중단)
24
+ # APP_STORE_CONNECT_API_KEY_ID: API Key ID (10 characters)
25
+ # APP_STORE_CONNECT_ISSUER_ID: Issuer ID (UUID format)
26
+ # APP_STORE_CONNECT_API_KEY_BASE64: AuthKey_XXXXXX.p8 file (base64 encoded)
27
+ # IOS_BUNDLE_ID (Secret first, otherwise Variable): app bundle ID —
28
+ # required when using store_prepare/store_submit (the Fastfile stops with a clear error if empty)
29
29
  #
30
- # 환경 설정 (선택):
31
- # ENV_FILE (선택): .env 파일 내용
32
- # SECRETS_XCCONFIG (선택): ios/Flutter/Secrets.xcconfig 내용
30
+ # Environment settings (optional):
31
+ # ENV_FILE (optional): contents of the .env file
32
+ # SECRETS_XCCONFIG (optional): contents of ios/Flutter/Secrets.xcconfig
33
33
  #
34
- # 초기 설정 방법
34
+ # Initial setup
35
35
  #
36
- # 1. GitHub Secrets 설정 (위 목록 참고)
36
+ # 1. Configure the GitHub Secrets (see the list above)
37
37
  #
38
- # 2. ios/ExportOptions.plist의 플레이스홀더(팀 ID·번들 ID·프로비저닝 프로파일 이름)를 채워 커밋:
38
+ # 2. Fill in the placeholders in ios/ExportOptions.plist (team ID, bundle ID, provisioning profile name) and commit:
39
39
  # git add ios/
40
- # git commit -m "chore: iOS TestFlight 배포 설정"
40
+ # git commit -m "chore: add iOS TestFlight deploy settings"
41
41
  #
42
- # 3. {{MAIN_BRANCH}} 브랜치로 푸시하여 배포 시작
42
+ # 3. Push to the {{MAIN_BRANCH}} branch to start a deploy
43
43
 
44
44
  name: PROJECT-iOS-TestFlight-Deploy
45
45
 
46
46
  on:
47
47
  push:
48
48
  branches: ["{{MAIN_BRANCH}}"]
49
- # @wizard paths-anchor (모노레포일 때 integrator가 paths 필터를 여기 주입)
49
+ # @wizard paths-anchor (in a monorepo the installer injects a paths filter here)
50
50
  workflow_dispatch:
51
51
  inputs:
52
52
  deploy_mode:
53
- description: "배포 모드 (store_only=TestFlight까지 / store_prepare=ASC 제출직전 / store_submit=심사 자동제출)"
53
+ description: "Deploy mode (store_only=up to TestFlight / store_prepare=right before ASC submission / store_submit=auto-submit for review)"
54
54
  required: false
55
55
  default: "store_only" # @wizard auto:ios-deploy-mode
56
56
  type: choice
@@ -59,30 +59,30 @@ on:
59
59
  - store_prepare
60
60
  - store_submit
61
61
 
62
- # 프로젝트별 설정 (아래 값들을 수정하세요)
62
+ # Project settings (edit the values below)
63
63
  env:
64
64
  FLUTTER_PROJECT_DIR: "." # @wizard auto:flutter-root
65
- # 환경변수 전달 방식 (dart-define | dotenv) — 설치 시 선택값으로 자동 설정
65
+ # How env vars are passed (dart-define | dotenv) — set automatically from the value chosen at install
66
66
  ENV_MODE: "dart-define" # @wizard auto:flutter-env-mode
67
- # Flutter SDK 버전 — 비워 두면 stable 채널 최신을 쓴다(최신 flutter create 프로젝트의 SDK 제약과 맞음).
68
- # 특정 버전에 고정하려면 "3.38.9"처럼 적는다. pubspec.yaml의 environment.sdk 범위를 만족해야 한다.
67
+ # Flutter SDK version — leave empty to use the latest stable channel (matches the SDK constraint of a fresh flutter create project).
68
+ # To pin a version, write it like "3.38.9". It must satisfy environment.sdk in pubspec.yaml.
69
69
  FLUTTER_VERSION: ""
70
70
  XCODE_VERSION: "26.0"
71
71
  PROJECT_TYPE: "flutter"
72
72
 
73
- # 환경 파일 설정
74
- # dotenv 모드에서 .env 파일을 만들 경로 (Flutter 루트 기준)
73
+ # Env file settings
74
+ # Where to create the .env file in dotenv mode (relative to the Flutter root)
75
75
  ENV_FILE_PATH: ".env"
76
76
 
77
- # TestFlight Changelog 설정
77
+ # TestFlight changelog settings
78
78
  SKIP_WAITING_FOR_BUILD_PROCESSING: "false"
79
79
 
80
- # 배포 모드 (store_only | store_prepare | store_submit)
80
+ # Deploy mode (store_only | store_prepare | store_submit)
81
81
  DEPLOY_MODE: ${{ github.event.inputs.deploy_mode || vars.IOS_DEPLOY_MODE || 'store_only' }} # @wizard fallback:ios-deploy-mode
82
82
 
83
83
  jobs:
84
84
  prepare-build:
85
- name: 환경 설정 및 준비
85
+ name: Set up environment
86
86
  runs-on: macos-26
87
87
  defaults:
88
88
  run:
@@ -104,8 +104,8 @@ jobs:
104
104
  - name: Pull latest changes
105
105
  run: git pull origin {{MAIN_BRANCH}}
106
106
 
107
- # 인증서 import·빌드 전에 설정 누락을 한 번에 알려 준다 — 없으면 macOS 러너에서 한참 빌드한 뒤에야 엉뚱한 단계에서 실패한다
108
- - name: 배포 설정 사전 검증
107
+ # Report every missing setting up front, before importing certificates or building — otherwise the macOS runner builds for a long time and fails at an unrelated step
108
+ - name: Validate deploy settings
109
109
  env:
110
110
  APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
111
111
  APPLE_PROVISIONING_PROFILE_BASE64: ${{ secrets.APPLE_PROVISIONING_PROFILE_BASE64 }}
@@ -114,6 +114,7 @@ jobs:
114
114
  APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
115
115
  APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }}
116
116
  run: |
117
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
117
118
  FAILED=0
118
119
  MISSING=""
119
120
  for name in APPLE_CERTIFICATE_BASE64 APPLE_PROVISIONING_PROFILE_BASE64 IOS_PROVISIONING_PROFILE_NAME \
@@ -121,23 +122,23 @@ jobs:
121
122
  [ -n "${!name}" ] || MISSING="$MISSING $name"
122
123
  done
123
124
  if [ -n "$MISSING" ]; then
124
- echo "::error::필수 GitHub Secret이 비어 있습니다:$MISSING (워크플로우 상단 주석 참고)"
125
+ echo "::error::$(m ios_testflight.secrets_missing missing="$MISSING")"
125
126
  FAILED=1
126
127
  fi
127
128
  if [ ! -f ios/ExportOptions.plist ]; then
128
- echo "::error::ios/ExportOptions.plist가 없습니다 — 저장소에 추가(커밋)하세요."
129
+ echo "::error::$(m ios_testflight.export_options_missing)"
129
130
  FAILED=1
130
131
  elif grep -Eq '__[A-Z][A-Z0-9_]*__' ios/ExportOptions.plist; then
131
- echo "::error::ios/ExportOptions.plist에 채워지지 않은 플레이스홀더가 남아 있습니다 — 팀 ID·번들 ID·프로비저닝 프로파일 이름으로 바꿔 커밋하세요."
132
+ echo "::error::$(m ios_testflight.export_options_placeholders)"
132
133
  grep -En '__[A-Z][A-Z0-9_]*__' ios/ExportOptions.plist
133
134
  FAILED=1
134
135
  fi
135
136
  if [ ! -f ios/fastlane/Fastfile ]; then
136
- echo "::error::ios/fastlane/Fastfile이 없습니다 — 저장소에 추가(커밋)하세요."
137
+ echo "::error::$(m ios_testflight.fastfile_missing_error)"
137
138
  FAILED=1
138
139
  fi
139
140
  [ "$FAILED" -eq 0 ] || exit 1
140
- echo "✅ 배포 설정 확인 완료"
141
+ m ios_testflight.preflight_ok
141
142
 
142
143
  - name: Select Xcode version
143
144
  run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer
@@ -195,18 +196,20 @@ jobs:
195
196
 
196
197
  - name: Install CocoaPods
197
198
  run: |
198
- # 플러그인이 없는 기본 프로젝트는 Podfile이 없다 — 플러그인이 생기면 flutter build가 Podfile을 만든다
199
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
200
+ # A default project without plugins has no Podfile — flutter build creates one once a plugin is added
199
201
  if [ -f ios/Podfile ]; then
200
202
  gem install cocoapods
201
203
  (cd ios && pod install)
202
204
  else
203
- echo "ℹ️ ios/Podfile이 없어 pod install을 건너뜁니다 (CocoaPods 플러그인 없음)"
205
+ m ios_testflight.podfile_skip
204
206
  fi
205
207
 
206
- - name: 현재 버전 정보 가져오기
208
+ - name: Get current version
207
209
  id: current_version
208
- working-directory: ${{ github.workspace }} # version_manager.py가 레포 루트 version.yml을 읽어야 함
210
+ working-directory: ${{ github.workspace }} # version_manager.py must read version.yml at the repo root
209
211
  run: |
212
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
210
213
  VERSION=$(python3 .github/scripts/version_manager.py get | tail -n 1)
211
214
  BUILD_NUMBER=$(python3 .github/scripts/version_manager.py get-code | tail -n 1)
212
215
 
@@ -214,12 +217,13 @@ jobs:
214
217
  echo "build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT
215
218
  echo "project_type=${{ env.PROJECT_TYPE }}" >> $GITHUB_OUTPUT
216
219
 
217
- echo "📋 버전: $VERSION (빌드번호: $BUILD_NUMBER)"
220
+ m ios_testflight.version_info version="$VERSION" build="$BUILD_NUMBER"
218
221
 
219
- - name: 릴리즈 노트 생성
222
+ - name: Generate release notes
220
223
  id: release_notes
221
- working-directory: ${{ github.workspace }} # CHANGELOG.json·changelog_manager.py·final_release_notes.txt(upload 짝)는 레포 루트 기준
224
+ working-directory: ${{ github.workspace }} # CHANGELOG.json, changelog_manager.py and final_release_notes.txt (paired with the upload step) are relative to the repo root
222
225
  run: |
226
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
223
227
  VERSION="${{ steps.current_version.outputs.version }}"
224
228
 
225
229
  if [ -f "CHANGELOG.json" ]; then
@@ -230,11 +234,11 @@ jobs:
230
234
  echo "RELEASE_NOTES_FOUND=true" >> $GITHUB_ENV
231
235
  else
232
236
  echo "RELEASE_NOTES_FOUND=false" >> $GITHUB_ENV
233
- echo "v$VERSION 업데이트" > final_release_notes.txt
237
+ m ios_testflight.default_notes version="$VERSION" > final_release_notes.txt
234
238
  fi
235
239
  else
236
240
  echo "RELEASE_NOTES_FOUND=false" >> $GITHUB_ENV
237
- echo "v$VERSION 업데이트" > final_release_notes.txt
241
+ m ios_testflight.default_notes version="$VERSION" > final_release_notes.txt
238
242
  fi
239
243
 
240
244
  - name: Upload release notes
@@ -257,9 +261,9 @@ jobs:
257
261
  retention-days: 1
258
262
  if-no-files-found: error
259
263
 
260
- # iOS 빌드 (xcodebuild 직접 사용)
264
+ # iOS build (uses xcodebuild directly)
261
265
  build-ios:
262
- name: iOS 앱 빌드
266
+ name: Build iOS app
263
267
  runs-on: macos-26
264
268
  defaults:
265
269
  run:
@@ -281,7 +285,7 @@ jobs:
281
285
 
282
286
  - name: Install iOS device platform
283
287
  env:
284
- # xcode-select만으로는 서브프로세스에 전파되지 않아 명시적으로 지정
288
+ # xcode-select alone does not propagate to subprocesses, so set it explicitly
285
289
  DEVELOPER_DIR: /Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer
286
290
  run: |
287
291
  echo "=== iPhoneOS.platform check ==="
@@ -345,12 +349,13 @@ jobs:
345
349
 
346
350
  - name: Install CocoaPods
347
351
  run: |
348
- # 플러그인이 없는 기본 프로젝트는 Podfile이 없다 — 플러그인이 생기면 flutter build가 Podfile을 만든다
352
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
353
+ # A default project without plugins has no Podfile — flutter build creates one once a plugin is added
349
354
  if [ -f ios/Podfile ]; then
350
355
  gem install cocoapods
351
356
  (cd ios && pod install)
352
357
  else
353
- echo "ℹ️ ios/Podfile이 없어 pod install을 건너뜁니다 (CocoaPods 플러그인 없음)"
358
+ m ios_testflight.podfile_skip
354
359
  fi
355
360
 
356
361
  - name: Import Code-Signing Certificates
@@ -369,21 +374,22 @@ jobs:
369
374
 
370
375
  - name: Verify ExportOptions.plist
371
376
  run: |
377
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
372
378
  cd ios
373
379
  if [ ! -f "ExportOptions.plist" ]; then
374
380
  exit 1
375
381
  fi
376
- # 설치기가 만든 템플릿의 플레이스홀더를 채우지 않으면 xcodebuild가 이해하기 어려운 오류로 끝난다
382
+ # If the placeholders in the installer-generated template are not filled in, xcodebuild ends with a hard-to-read error
377
383
  if grep -Eq '__[A-Z][A-Z0-9_]*__' ExportOptions.plist; then
378
- echo "❌ ios/ExportOptions.plist에 채워지지 않은 플레이스홀더가 남아 있습니다:"
384
+ m ios_testflight.plist_placeholders
379
385
  grep -En '__[A-Z][A-Z0-9_]*__' ExportOptions.plist
380
- echo "팀 ID·번들 ID·프로비저닝 프로파일 이름으로 바꿔 커밋한 뒤 다시 실행하세요."
386
+ m ios_testflight.plist_placeholders_hint
381
387
  exit 1
382
388
  fi
383
389
 
384
390
  - name: Flutter build (no codesign)
385
391
  env:
386
- # xcode-select만으로는 서브프로세스에 전파되지 않아 명시적으로 지정
392
+ # xcode-select alone does not propagate to subprocesses, so set it explicitly
387
393
  DEVELOPER_DIR: /Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer
388
394
  run: |
389
395
  flutter build ios --release --no-codesign \
@@ -394,7 +400,7 @@ jobs:
394
400
  - name: Create Archive
395
401
  env:
396
402
  IOS_PROVISIONING_PROFILE_NAME: ${{ secrets.IOS_PROVISIONING_PROFILE_NAME }}
397
- # xcode-select만으로는 서브프로세스에 전파되지 않아 명시적으로 지정
403
+ # xcode-select alone does not propagate to subprocesses, so set it explicitly
398
404
  DEVELOPER_DIR: /Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer
399
405
  run: |
400
406
  cd ios
@@ -423,9 +429,9 @@ jobs:
423
429
  retention-days: 1
424
430
  if-no-files-found: error
425
431
 
426
- # TestFlight 배포 (ios/fastlane/Fastfile 사용)
432
+ # TestFlight deploy (uses ios/fastlane/Fastfile)
427
433
  deploy-testflight:
428
- name: TestFlight 배포
434
+ name: Deploy to TestFlight
429
435
  runs-on: macos-26
430
436
  defaults:
431
437
  run:
@@ -458,21 +464,23 @@ jobs:
458
464
 
459
465
  - name: Verify Fastfile exists
460
466
  run: |
467
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
461
468
  if [ ! -f "ios/fastlane/Fastfile" ]; then
462
- echo "❌ ios/fastlane/Fastfile이 없습니다!"
463
- echo "ios/fastlane/Fastfile을 저장소에 추가(커밋)하세요. 필요한 Secrets는 워크플로우 상단 주석을 참고하세요."
469
+ m ios_testflight.fastfile_missing
470
+ m ios_testflight.fastfile_missing_hint
464
471
  exit 1
465
472
  fi
466
- echo "✅ Fastfile 확인됨: ios/fastlane/Fastfile"
473
+ m ios_testflight.fastfile_ok
467
474
 
468
475
  - name: Install Fastlane
469
476
  working-directory: ${{ env.FLUTTER_PROJECT_DIR }}/ios
470
477
  run: |
471
- # 저장소의 Gemfile에 fastlane이 있으면 그대로 쓴다 (Gemfile.lock 커밋 권장). 없으면 생성한다.
478
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
479
+ # Use the repository's Gemfile as-is if it lists fastlane (committing Gemfile.lock is recommended). Otherwise generate one.
472
480
  if [ -f Gemfile ] && grep -Eq "['\"]fastlane['\"]" Gemfile; then
473
- echo "ℹ️ 저장소의 Gemfile을 사용합니다"
481
+ m ios_testflight.gemfile_repo
474
482
  else
475
- # multi_json: google-apis transitive 의존성이 선언 누락한 upstream 버그 회피 (gemspec 미선언 → Gem::LoadError)
483
+ # multi_json: works around an upstream bug where a google-apis transitive dependency omits it from its gemspec (Gem::LoadError)
476
484
  printf 'source "https://rubygems.org"\ngem "fastlane"\ngem "multi_json"\n' > Gemfile
477
485
  fi
478
486
  bundle install
@@ -484,24 +492,25 @@ jobs:
484
492
  APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
485
493
  SKIP_WAITING_FOR_BUILD_PROCESSING: ${{ env.SKIP_WAITING_FOR_BUILD_PROCESSING }}
486
494
  run: |
487
- # IPA 절대경로 탐색
495
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
496
+ # Find the IPA by absolute path
488
497
  IPA_PATH=$(find "$GITHUB_WORKSPACE/${FLUTTER_PROJECT_DIR}/ios/build/ipa" -name "*.ipa" | head -1)
489
498
  echo "📦 Found IPA at: $IPA_PATH"
490
499
 
491
500
  if [ ! -f "$IPA_PATH" ]; then
492
- echo "❌ IPA 파일을 찾을 수 없습니다!"; ls -la ios/build/ipa/ || true; exit 1
501
+ m ios_testflight.ipa_missing; ls -la ios/build/ipa/ || true; exit 1
493
502
  fi
494
503
 
495
- # Release notes 준비 (final_release_notes.txt·truncate 스크립트는 레포 루트 기준 — working-directory가 FLUTTER_PROJECT_DIR이므로 절대경로 사용)
504
+ # Prepare release notes (final_release_notes.txt and the truncate script are relative to the repo root — use absolute paths since working-directory is FLUTTER_PROJECT_DIR)
496
505
  if [ -f "$GITHUB_WORKSPACE/final_release_notes.txt" ]; then
497
- # App Store Connect "What to Test" 한도(4000 바이트)에 맞춰 절단 (마진 두어 3800byte)
506
+ # Truncate to the App Store Connect "What to Test" limit (4000 bytes), with a margin (3800 bytes)
498
507
  python3 "$GITHUB_WORKSPACE/.github/scripts/truncate_release_notes.py" "$GITHUB_WORKSPACE/final_release_notes.txt" 3800 byte
499
508
  RELEASE_NOTES=$(cat "$GITHUB_WORKSPACE/final_release_notes.txt")
500
509
  echo "📝 Release Notes:"
501
510
  echo "$RELEASE_NOTES"
502
511
  else
503
- RELEASE_NOTES="v${{ needs.prepare-build.outputs.version }} 업데이트"
504
- echo "📝 기본 Release Notes: $RELEASE_NOTES"
512
+ RELEASE_NOTES="$(m ios_testflight.default_notes version="${{ needs.prepare-build.outputs.version }}")"
513
+ m ios_testflight.default_notes_echo notes="$RELEASE_NOTES"
505
514
  fi
506
515
 
507
516
  export APP_STORE_CONNECT_API_KEY_ID="${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}"
@@ -521,13 +530,15 @@ jobs:
521
530
  - name: Notify TestFlight Upload Success
522
531
  if: success()
523
532
  run: |
524
- echo "✅ TestFlight 업로드 성공!"
525
- echo "📱 버전: ${{ needs.prepare-build.outputs.version }}"
526
- echo "🔢 빌드번호: ${{ needs.prepare-build.outputs.build_number }}"
527
- echo "📝 커밋: ${{ github.sha }}"
533
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
534
+ m ios_testflight.upload_ok
535
+ m ios_testflight.upload_version version="${{ needs.prepare-build.outputs.version }}"
536
+ m ios_testflight.upload_build build="${{ needs.prepare-build.outputs.build_number }}"
537
+ m ios_testflight.upload_commit sha="${{ github.sha }}"
528
538
 
529
539
  - name: Notify on Failure
530
540
  if: failure()
531
541
  run: |
532
- echo "❌ TestFlight 업로드 실패!"
533
- echo "로그를 확인해주세요."
542
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
543
+ m ios_testflight.upload_failed
544
+ m ios_testflight.check_logs
@@ -1,30 +1,30 @@
1
1
  # project-auto-wizard:managed-workflow
2
- # Go 빌드 검증 워크플로우 (CI Only)
3
- # - {{DEVELOP_BRANCH}} 브랜치에 push/PR 시 go build/vet/test/lint로 검증
4
- # - Dockerfile이 필요 없어 CLI 도구·라이브러리 등 배포하지 않는 Go 프로젝트도 사용 가능
5
- # - go.mod의 go 지시자 버전을 자동으로 사용 (버전 하드코딩 없음)
2
+ # Go build verification workflow (CI only)
3
+ # - Verifies with go build/vet/test/lint on push/PR to the {{DEVELOP_BRANCH}} branch
4
+ # - Needs no Dockerfile, so it also works for Go projects that are not deployed (CLI tools, libraries, ...)
5
+ # - Uses the go directive version from go.mod automatically (no hardcoded version)
6
6
 
7
7
  name: PROJECT-GO-CI
8
8
 
9
9
  on:
10
10
  push:
11
11
  branches:
12
- - "{{DEVELOP_BRANCH}}" # {{DEVELOP_BRANCH}} 브랜치 push 시 빌드 검증
12
+ - "{{DEVELOP_BRANCH}}" # build verification on push to the {{DEVELOP_BRANCH}} branch
13
13
  pull_request:
14
14
  branches:
15
- - "{{DEVELOP_BRANCH}}" # {{DEVELOP_BRANCH}} 브랜치로의 PR 시 빌드 검증
16
- workflow_dispatch: # 수동 실행 허용
15
+ - "{{DEVELOP_BRANCH}}" # build verification on PRs to the {{DEVELOP_BRANCH}} branch
16
+ workflow_dispatch: # allow manual runs
17
17
 
18
18
  env:
19
- # 프로젝트 고유 식별자
19
+ # Unique project identifier
20
20
  PROJECT_NAME: "__PROJECT_NAME__" # @wizard ask:@repo
21
- # 모노레포에서 이 프로젝트가 있는 하위 경로 ('.'이면 항상 검증)
21
+ # Subdirectory of this project in a monorepo ('.' means always verify)
22
22
  PROJECT_PATH: "." # @wizard auto:project-path
23
23
 
24
24
  jobs:
25
- # 변경 감지 (모노레포에서 이 프로젝트 경로가 바뀌었는지 판별)
25
+ # Change detection (in a monorepo, checks whether this project's path changed)
26
26
  changes:
27
- name: 변경 감지
27
+ name: Detect changes
28
28
  runs-on: ubuntu-latest
29
29
  permissions:
30
30
  contents: read
@@ -35,81 +35,92 @@ jobs:
35
35
  - name: Checkout repository
36
36
  uses: actions/checkout@v7
37
37
 
38
- - name: 프로젝트 경로 변경 여부 판별
38
+ - name: Check whether the project path changed
39
39
  id: filter
40
40
  if: ${{ github.event_name != 'workflow_dispatch' }}
41
41
  uses: dorny/paths-filter@v4
42
42
  with:
43
- # push는 이번 push 범위(직전 커밋 before 대비)만 본다. 비워 두면 기본 브랜치 대비 누적 diff가 된다.
44
- # 새 브랜치 첫 push(before가 0)와 PR은 빈 값 → 기본 동작(기본 브랜치·PR base 대비)
43
+ # A push only looks at this push's range (against the previous commit, 'before'). Left empty it would be the cumulative diff against the default branch.
44
+ # The first push of a new branch (before is 0) and PRs get an empty value -> default behavior (against the default branch / PR base)
45
45
  base: ${{ github.event_name == 'push' && github.event.before != '0000000000000000000000000000000000000000' && github.event.before || '' }}
46
46
  filters: |
47
47
  project:
48
48
  - '${{ env.PROJECT_PATH == '.' && '**' || format('{0}/**', env.PROJECT_PATH) }}'
49
49
 
50
- # Job: 빌드 검증
50
+ # Job: build verification
51
51
  build-check:
52
- name: Go 빌드 검증
52
+ name: Go build verification
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 }}
60
60
 
61
61
  steps:
62
- - name: 코드 체크아웃
62
+ - name: Checkout repository
63
63
  uses: actions/checkout@v7
64
64
 
65
- # go.mod의 go 지시자 버전 자동 사용
66
- - name: Go 설정
65
+ # Automatically use the go directive version from go.mod
66
+ - name: Set up Go
67
67
  uses: actions/setup-go@v7
68
68
  with:
69
69
  go-version-file: ${{ env.PROJECT_PATH }}/go.mod
70
70
  cache-dependency-path: ${{ env.PROJECT_PATH }}/go.sum
71
71
  cache: true
72
72
 
73
- - name: go build 검증
73
+ - name: Verify go build
74
74
  run: go build ./...
75
75
 
76
- - name: go vet 검증
76
+ - name: Verify go vet
77
77
  run: go vet ./...
78
78
 
79
- - name: go test 실행
79
+ - name: Run go test
80
80
  run: go test ./...
81
81
 
82
- # golangci-lint v8은 golangci-lint v2 계열을 요구 — .golangci.yml이 v1 형식이면
83
- # 프로젝트에서 별도 조정 필요. version: latest는 v2 최신 패치를 자동으로 받는다
82
+ # golangci-lint-action v8 requires golangci-lint v2; if .golangci.yml is in the v1 format
83
+ # the project has to adjust it. version: latest picks up the newest v2 patch automatically
84
84
  - name: golangci-lint
85
85
  uses: golangci/golangci-lint-action@v8
86
86
  with:
87
87
  version: latest
88
88
  working-directory: ${{ env.PROJECT_PATH }}
89
89
 
90
- - name: 빌드 검증 완료
90
+ - name: Build verification complete
91
91
  run: |
92
- echo "✅ Go 빌드 검증이 성공적으로 완료되었습니다!"
92
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
93
+ m cibuild.go_done
93
94
  echo ""
94
- echo "📋 빌드 정보:"
95
- echo " 🎯 프로젝트: ${{ env.PROJECT_NAME }}"
96
- echo " 🌿 브랜치: ${{ github.ref_name }}"
97
- echo " 📝 커밋: ${{ github.sha }}"
98
- echo " ⏰ 검증 시간: $(date '+%Y-%m-%d %H:%M:%S')"
95
+ m cibuild.info_title
96
+ m cibuild.info_project project="${{ env.PROJECT_NAME }}"
97
+ m cibuild.info_branch branch="${{ github.ref_name }}"
98
+ m cibuild.info_commit sha="${{ github.sha }}"
99
+ m cibuild.info_time time="$(date '+%Y-%m-%d %H:%M:%S')"
99
100
 
100
- # Job: CI Gate (required check로 등록할 단일 job)
101
+ # Job: CI Gate (the single job to register as a required check)
101
102
  ci-gate:
102
103
  name: CI Gate
103
104
  if: ${{ always() }}
104
105
  needs: [changes, build-check]
105
106
  runs-on: ubuntu-latest
106
107
  steps:
107
- - name: 결과 집계
108
+ # Only the message catalog is needed here, so check out just that
109
+ - name: Checkout message catalog
110
+ uses: actions/checkout@v7
111
+ with:
112
+ sparse-checkout: |
113
+ .github/scripts/messages.py
114
+ version.yml
115
+ sparse-checkout-cone-mode: false
116
+
117
+ - name: Aggregate results
108
118
  env:
109
119
  RESULTS: ${{ toJSON(needs.*.result) }}
110
120
  run: |
111
- echo "needs 결과: $RESULTS"
121
+ m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
122
+ m cibuild.gate_results results="$RESULTS"
112
123
  if echo "$RESULTS" | grep -Eq '"(failure|cancelled)"'; then
113
- echo "실패하거나 취소된 job이 있습니다."
124
+ m cibuild.gate_failed
114
125
  exit 1
115
126
  fi