project-auto-wizard 0.9.1 → 0.11.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 (54) hide show
  1. package/README.md +83 -4
  2. package/package.json +1 -1
  3. package/payload/config/breaking-changes.json +24 -1
  4. package/payload/flutter-app/android/fastlane/Fastfile.playstore +86 -0
  5. package/payload/flutter-app/ios/ExportOptions.plist +31 -0
  6. package/payload/flutter-app/ios/fastlane/Fastfile +117 -0
  7. package/payload/scripts/__pycache__/changelog_manager.cpython-314.pyc +0 -0
  8. package/payload/scripts/__pycache__/issue_helper.cpython-314.pyc +0 -0
  9. package/payload/scripts/__pycache__/version_manager.cpython-314.pyc +0 -0
  10. package/payload/scripts/changelog_manager.py +2 -2
  11. package/payload/scripts/version_manager.py +2 -2
  12. package/payload/version.yml.template +1 -0
  13. package/payload/workflows/common/secret-backup/PROJECT-COMMON-SECRET-FILE-UPLOAD.yaml +12 -12
  14. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-FIREBASE-CICD.yaml +48 -20
  15. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +44 -19
  16. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-SELFHOSTED-CICD.yaml +28 -36
  17. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +33 -46
  18. package/payload/workflows/flutter/{PROJECT-FLUTTER-SUH-LAB-APP-BUILD-TRIGGER.yaml → PROJECT-FLUTTER-APP-BUILD-TRIGGER.yaml} +38 -38
  19. package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +123 -32
  20. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +57 -42
  21. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TESTFLIGHT.yaml +61 -40
  22. package/payload/workflows/go/PROJECT-GO-CI.yaml +47 -0
  23. package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +40 -40
  24. package/payload/workflows/next/PROJECT-NEXT-CI.yaml +47 -0
  25. package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +47 -0
  26. package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +40 -40
  27. package/payload/workflows/react/PROJECT-REACT-CI.yaml +47 -0
  28. package/payload/workflows/spring/nexus/PROJECT-SPRING-GITHUB-PACKAGES-PUBLISH.yml +1 -0
  29. package/payload/workflows/spring/nexus/PROJECT-SPRING-NEXUS-CI.yml +47 -0
  30. package/payload/workflows/spring/nexus/PROJECT-SPRING-NEXUS-PUBLISH.yml +1 -0
  31. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +39 -39
  32. package/src/cli/args.js +37 -0
  33. package/src/cli/help.js +4 -0
  34. package/src/commands/doctor.js +55 -2
  35. package/src/commands/dry-run.js +10 -0
  36. package/src/commands/full.js +28 -3
  37. package/src/commands/interactive-flutter.js +95 -0
  38. package/src/commands/interactive.js +51 -5
  39. package/src/commands/status.js +20 -2
  40. package/src/context.js +6 -0
  41. package/src/core/breaking.js +7 -3
  42. package/src/core/copy/flutter-app.js +42 -0
  43. package/src/core/copy/workflows.js +21 -9
  44. package/src/core/detect-fs.js +9 -1
  45. package/src/core/flutter-options.js +118 -0
  46. package/src/core/installed-stores.js +12 -0
  47. package/src/core/verify.js +2 -2
  48. package/src/core/version-yml.js +40 -5
  49. package/src/core/wizard-env.js +26 -4
  50. package/src/index.js +32 -1
  51. package/src/ui/env-plan.js +8 -5
  52. package/src/ui/prompts.js +88 -3
  53. package/src/ui/status-cards.js +13 -1
  54. package/src/ui/summary.js +24 -5
@@ -26,8 +26,8 @@
26
26
  # ENV_FILE 또는 ENV: .env 파일 내용 (둘 중 하나, ENV_FILE 우선)
27
27
  # GOOGLE_SERVICES_JSON: Firebase google-services.json
28
28
  #
29
- # 🪄 빠른 설정: .github/util/flutter/firebase-wizard/firebase-wizard.html을
30
- # 브라우저에서 열어 5단계 마법사로 Firebase 배포를 자동 설정할 수 있습니다.
29
+ # ※ 위 Secrets는 저장소 Settings → Secrets and variables → Actions에 등록하세요.
30
+ # FIREBASE_APP_ID·FIREBASE_TESTER_GROUP은 아래 env 섹션 값을 직접 수정합니다.
31
31
  #
32
32
  # ===================================================================
33
33
  #
@@ -53,6 +53,7 @@ name: PROJECT-FLUTTER-ANDROID-FIREBASE-APPDIST-CICD
53
53
  on:
54
54
  push:
55
55
  branches: ["{{MAIN_BRANCH}}"]
56
+ # @wizard paths-anchor (모노레포일 때 integrator가 paths 필터를 여기 주입)
56
57
  workflow_dispatch:
57
58
 
58
59
  env:
@@ -65,6 +66,10 @@ env:
65
66
  FLUTTER_VERSION: "3.35.5"
66
67
  JAVA_VERSION: "__JAVA_VERSION__" # @wizard ask:17
67
68
  PROJECT_TYPE: "flutter"
69
+ # Flutter 루트 경로(레포 루트 기준). 단일레포면 ".", 모노레포면 "app" 등 — 설치 시 자동 설정
70
+ FLUTTER_PROJECT_DIR: "." # @wizard auto:flutter-root
71
+ # 환경변수 전달 방식 (dart-define | dotenv) — 설치 시 선택값으로 자동 설정
72
+ ENV_MODE: "dart-define" # @wizard auto:flutter-env-mode
68
73
  # Firebase App Distribution 설정
69
74
  FIREBASE_APP_ID: "your-firebase-app-id"
70
75
  FIREBASE_TESTER_GROUP: "testers"
@@ -73,6 +78,9 @@ jobs:
73
78
  prepare-build:
74
79
  name: 환경 설정 및 준비
75
80
  runs-on: ubuntu-latest
81
+ defaults:
82
+ run:
83
+ working-directory: ${{ env.FLUTTER_PROJECT_DIR }}
76
84
  # CHANGELOG 워크플로우가 성공한 경우에만 실행
77
85
  if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name != 'workflow_run' }}
78
86
 
@@ -91,12 +99,19 @@ jobs:
91
99
  - name: Pull latest changes
92
100
  run: git pull origin main
93
101
 
94
- - name: Create .env file
102
+ - name: Prepare env file
95
103
  env:
96
104
  ENV_CONTENT: ${{ secrets.ENV_FILE || secrets.ENV }}
97
105
  run: |
98
- printf '%s\n' "$ENV_CONTENT" > .env
99
- echo ".env file created"
106
+ if [ "$ENV_MODE" = "dotenv" ]; then
107
+ printf '%s\n' "$ENV_CONTENT" > .env
108
+ echo ".env file created"
109
+ elif [ -n "$ENV_CONTENT" ]; then
110
+ DART_DEFINE_FILE="$RUNNER_TEMP/dart-define.env"
111
+ printf '%s\n' "$ENV_CONTENT" > "$DART_DEFINE_FILE"
112
+ echo "DART_DEFINE_FILE=$DART_DEFINE_FILE" >> "$GITHUB_ENV"
113
+ echo "dart-define file prepared"
114
+ fi
100
115
 
101
116
  - name: Set up Flutter
102
117
  uses: subosito/flutter-action@v2
@@ -108,7 +123,7 @@ jobs:
108
123
  uses: actions/cache@v6
109
124
  with:
110
125
  path: ~/.pub-cache
111
- key: ${{ runner.os }}-flutter-pub-${{ hashFiles('**/pubspec.lock') }}
126
+ key: ${{ runner.os }}-flutter-pub-${{ hashFiles(format('{0}/**/pubspec.lock', env.FLUTTER_PROJECT_DIR)) }}
112
127
  restore-keys: ${{ runner.os }}-flutter-pub-
113
128
 
114
129
  - name: Install dependencies
@@ -121,6 +136,7 @@ jobs:
121
136
  # version_manager.py를 사용하여 현재 버전 정보 가져오기
122
137
  - name: 현재 버전 정보 가져오기
123
138
  id: current_version
139
+ working-directory: ${{ github.workspace }} # version_manager.py가 레포 루트 version.yml을 읽어야 함
124
140
  run: |
125
141
  # VERSION 가져오기 (x.y.z 형식)
126
142
  VERSION=$(python3 .github/scripts/version_manager.py get | tail -n 1)
@@ -148,6 +164,7 @@ jobs:
148
164
  # CHANGELOG.json에서 릴리즈 노트 추출 - changelog_manager.py 사용
149
165
  - name: 릴리즈 노트 생성
150
166
  id: release_notes
167
+ working-directory: ${{ github.workspace }} # CHANGELOG.json·changelog_manager.py·final_release_notes.txt(upload 짝)는 레포 루트 기준
151
168
  run: |
152
169
  VERSION="${{ steps.current_version.outputs.version }}"
153
170
 
@@ -192,15 +209,18 @@ jobs:
192
209
  with:
193
210
  name: project-files
194
211
  path: |
195
- pubspec.yaml
196
- lib/
197
- assets/
212
+ ${{ env.FLUTTER_PROJECT_DIR }}/pubspec.yaml
213
+ ${{ env.FLUTTER_PROJECT_DIR }}/lib/
214
+ ${{ env.FLUTTER_PROJECT_DIR }}/assets/
198
215
  retention-days: 1
199
216
 
200
217
  build-android:
201
218
  name: Android AAB 빌드
202
219
  runs-on: ubuntu-latest
203
220
  needs: prepare-build
221
+ defaults:
222
+ run:
223
+ working-directory: ${{ env.FLUTTER_PROJECT_DIR }}
204
224
 
205
225
  steps:
206
226
  - name: Checkout repository
@@ -217,15 +237,22 @@ jobs:
217
237
  uses: actions/download-artifact@v8
218
238
  with:
219
239
  name: project-files
220
- path: .
240
+ path: ${{ env.FLUTTER_PROJECT_DIR }}
221
241
 
222
- # .env 파일 생성 (보안을 위해 아티팩트가 아닌 시크릿에서 생성)
223
- - name: Create .env file
242
+ # 환경변수 준비 (보안을 위해 아티팩트가 아닌 시크릿에서 생성) — ENV_MODE=dotenv면 .env 파일, dart-define이면 임시 파일
243
+ - name: Prepare env file
224
244
  env:
225
245
  ENV_CONTENT: ${{ secrets.ENV_FILE || secrets.ENV }}
226
246
  run: |
227
- printf '%s\n' "$ENV_CONTENT" > .env
228
- echo "✅ .env 파일 생성됨 (크기: $(wc -c < .env) bytes)"
247
+ if [ "$ENV_MODE" = "dotenv" ]; then
248
+ printf '%s\n' "$ENV_CONTENT" > .env
249
+ echo ".env file created"
250
+ elif [ -n "$ENV_CONTENT" ]; then
251
+ DART_DEFINE_FILE="$RUNNER_TEMP/dart-define.env"
252
+ printf '%s\n' "$ENV_CONTENT" > "$DART_DEFINE_FILE"
253
+ echo "DART_DEFINE_FILE=$DART_DEFINE_FILE" >> "$GITHUB_ENV"
254
+ echo "dart-define file prepared"
255
+ fi
229
256
 
230
257
  # Release Keystore 설정
231
258
  - name: Setup Release Keystore
@@ -265,7 +292,7 @@ jobs:
265
292
  uses: actions/cache@v6
266
293
  with:
267
294
  path: ~/.pub-cache
268
- key: ${{ runner.os }}-flutter-pub-${{ hashFiles('**/pubspec.lock') }}
295
+ key: ${{ runner.os }}-flutter-pub-${{ hashFiles(format('{0}/**/pubspec.lock', env.FLUTTER_PROJECT_DIR)) }}
269
296
  restore-keys: ${{ runner.os }}-flutter-pub-
270
297
 
271
298
  - name: Install dependencies
@@ -287,7 +314,7 @@ jobs:
287
314
  path: |
288
315
  ~/.gradle/caches
289
316
  ~/.gradle/wrapper
290
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/build.gradle*', '**/gradle-wrapper.properties') }}
317
+ key: ${{ runner.os }}-gradle-${{ hashFiles(format('{0}/android/**/build.gradle*', env.FLUTTER_PROJECT_DIR), format('{0}/android/**/gradle-wrapper.properties', env.FLUTTER_PROJECT_DIR)) }}
291
318
  restore-keys: |
292
319
  ${{ runner.os }}-gradle-
293
320
 
@@ -374,7 +401,8 @@ jobs:
374
401
  --release \
375
402
  --build-name="$VERSION_NAME" \
376
403
  --build-number="$VERSION_CODE" \
377
- --verbose
404
+ --verbose \
405
+ ${DART_DEFINE_FILE:+--dart-define-from-file="$DART_DEFINE_FILE"}
378
406
 
379
407
  BUILD_EXIT_CODE=$?
380
408
 
@@ -524,7 +552,7 @@ jobs:
524
552
  uses: actions/upload-artifact@v7
525
553
  with:
526
554
  name: android-aab
527
- path: build/app/outputs/bundle/release/app-release.aab
555
+ path: ${{ env.FLUTTER_PROJECT_DIR }}/build/app/outputs/bundle/release/app-release.aab
528
556
  retention-days: 1
529
557
 
530
558
  deploy-firebase:
@@ -544,7 +572,7 @@ jobs:
544
572
  uses: actions/download-artifact@v8
545
573
  with:
546
574
  name: android-aab
547
- path: build/app/outputs/bundle/release/
575
+ path: ${{ env.FLUTTER_PROJECT_DIR }}/build/app/outputs/bundle/release/
548
576
 
549
577
  # 릴리즈 노트 다운로드
550
578
  - name: Download release notes
@@ -575,7 +603,7 @@ jobs:
575
603
  appId: ${{ env.FIREBASE_APP_ID }}
576
604
  serviceCredentialsFile: firebase-service-account.json
577
605
  groups: ${{ env.FIREBASE_TESTER_GROUP }}
578
- file: build/app/outputs/bundle/release/app-release.aab
606
+ file: ${{ env.FLUTTER_PROJECT_DIR }}/build/app/outputs/bundle/release/app-release.aab
579
607
  releaseNotesFile: final_release_notes.txt
580
608
 
581
609
  # Firebase 인증 파일 삭제 (보안)
@@ -16,6 +16,7 @@
16
16
  # RELEASE_KEY_PASSWORD: key 비밀번호
17
17
  # GOOGLE_SERVICES_JSON: Firebase google-services.json
18
18
  # GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_BASE64: Play Console 서비스 계정 (base64)
19
+ # ANDROID_PACKAGE_NAME: 앱 패키지명 (Secret 우선, 없으면 Variable) — fastlane에 PACKAGE_NAME으로 전달
19
20
  # ===================================================================
20
21
 
21
22
  name: PROJECT-FLUTTER-ANDROID-PLAYSTORE-INTERNAL-CICD
@@ -23,6 +24,7 @@ name: PROJECT-FLUTTER-ANDROID-PLAYSTORE-INTERNAL-CICD
23
24
  on:
24
25
  push:
25
26
  branches: ["{{MAIN_BRANCH}}"]
27
+ # @wizard paths-anchor (모노레포일 때 integrator가 paths 필터를 여기 주입)
26
28
  workflow_dispatch:
27
29
  inputs:
28
30
  deploy_mode:
@@ -48,8 +50,10 @@ env:
48
50
  # Flutter 루트 경로(레포 루트 기준). 단일레포면 ".", 모노레포면 "app" 등.
49
51
  # 통합 시점에 integrator의 flutter-root resolver가 project_paths.flutter 값으로 1회 치환.
50
52
  FLUTTER_PROJECT_DIR: "." # @wizard auto:flutter-root
51
- # 배포 모드 (store_only | store_prepare | store_submit)
52
- DEPLOY_MODE: ${{ github.event.inputs.deploy_mode || vars.ANDROID_DEPLOY_MODE || 'store_only' }}
53
+ # 환경변수 전달 방식 (dart-define | dotenv) — 설치 시 선택값으로 자동 설정
54
+ ENV_MODE: "dart-define" # @wizard auto:flutter-env-mode
55
+ # 배포 모드 (store_only | store_prepare | store_submit) — 마지막 폴백값은 설치 시 선택값으로 설정, 변수·수동 입력이 항상 우선
56
+ DEPLOY_MODE: ${{ github.event.inputs.deploy_mode || vars.ANDROID_DEPLOY_MODE || 'store_only' }} # @wizard fallback:android-deploy-mode
53
57
 
54
58
  jobs:
55
59
  prepare-build:
@@ -76,12 +80,19 @@ jobs:
76
80
  - name: Pull latest changes
77
81
  run: git pull origin main
78
82
 
79
- - name: Create .env file
83
+ - name: Prepare env file
80
84
  env:
81
85
  ENV_CONTENT: ${{ secrets.ENV_FILE || secrets.ENV }}
82
86
  run: |
83
- printf '%s\n' "$ENV_CONTENT" > .env
84
- echo ".env file created"
87
+ if [ "$ENV_MODE" = "dotenv" ]; then
88
+ printf '%s\n' "$ENV_CONTENT" > .env
89
+ echo ".env file created"
90
+ elif [ -n "$ENV_CONTENT" ]; then
91
+ DART_DEFINE_FILE="$RUNNER_TEMP/dart-define.env"
92
+ printf '%s\n' "$ENV_CONTENT" > "$DART_DEFINE_FILE"
93
+ echo "DART_DEFINE_FILE=$DART_DEFINE_FILE" >> "$GITHUB_ENV"
94
+ echo "dart-define file prepared"
95
+ fi
85
96
 
86
97
  - name: Set up Flutter
87
98
  uses: subosito/flutter-action@v2
@@ -93,7 +104,7 @@ jobs:
93
104
  uses: actions/cache@v6
94
105
  with:
95
106
  path: ~/.pub-cache
96
- key: ${{ runner.os }}-flutter-pub-${{ hashFiles('**/pubspec.lock') }}
107
+ key: ${{ runner.os }}-flutter-pub-${{ hashFiles(format('{0}/**/pubspec.lock', env.FLUTTER_PROJECT_DIR)) }}
97
108
  restore-keys: ${{ runner.os }}-flutter-pub-
98
109
 
99
110
  - name: Install dependencies
@@ -180,9 +191,9 @@ jobs:
180
191
  with:
181
192
  name: project-files
182
193
  path: |
183
- pubspec.yaml
184
- lib/
185
- assets/
194
+ ${{ env.FLUTTER_PROJECT_DIR }}/pubspec.yaml
195
+ ${{ env.FLUTTER_PROJECT_DIR }}/lib/
196
+ ${{ env.FLUTTER_PROJECT_DIR }}/assets/
186
197
  retention-days: 1
187
198
  if-no-files-found: error
188
199
 
@@ -209,15 +220,22 @@ jobs:
209
220
  uses: actions/download-artifact@v8
210
221
  with:
211
222
  name: project-files
212
- path: .
223
+ path: ${{ env.FLUTTER_PROJECT_DIR }}
213
224
 
214
- # .env 파일 생성 (보안을 위해 아티팩트가 아닌 시크릿에서 생성)
215
- - name: Create .env file
225
+ # 환경변수 준비 (보안을 위해 아티팩트가 아닌 시크릿에서 생성) — ENV_MODE=dotenv면 .env 파일, dart-define이면 임시 파일
226
+ - name: Prepare env file
216
227
  env:
217
228
  ENV_CONTENT: ${{ secrets.ENV_FILE || secrets.ENV }}
218
229
  run: |
219
- printf '%s\n' "$ENV_CONTENT" > .env
220
- echo "✅ .env 파일 생성됨 (크기: $(wc -c < .env) bytes)"
230
+ if [ "$ENV_MODE" = "dotenv" ]; then
231
+ printf '%s\n' "$ENV_CONTENT" > .env
232
+ echo ".env file created"
233
+ elif [ -n "$ENV_CONTENT" ]; then
234
+ DART_DEFINE_FILE="$RUNNER_TEMP/dart-define.env"
235
+ printf '%s\n' "$ENV_CONTENT" > "$DART_DEFINE_FILE"
236
+ echo "DART_DEFINE_FILE=$DART_DEFINE_FILE" >> "$GITHUB_ENV"
237
+ echo "dart-define file prepared"
238
+ fi
221
239
 
222
240
  # Release Keystore 설정
223
241
  - name: Setup Release Keystore
@@ -257,7 +275,7 @@ jobs:
257
275
  uses: actions/cache@v6
258
276
  with:
259
277
  path: ~/.pub-cache
260
- key: ${{ runner.os }}-flutter-pub-${{ hashFiles('**/pubspec.lock') }}
278
+ key: ${{ runner.os }}-flutter-pub-${{ hashFiles(format('{0}/**/pubspec.lock', env.FLUTTER_PROJECT_DIR)) }}
261
279
  restore-keys: ${{ runner.os }}-flutter-pub-
262
280
 
263
281
  - name: Install dependencies
@@ -279,7 +297,7 @@ jobs:
279
297
  path: |
280
298
  ~/.gradle/caches
281
299
  ~/.gradle/wrapper
282
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/build.gradle*', '**/gradle-wrapper.properties') }}
300
+ key: ${{ runner.os }}-gradle-${{ hashFiles(format('{0}/android/**/build.gradle*', env.FLUTTER_PROJECT_DIR), format('{0}/android/**/gradle-wrapper.properties', env.FLUTTER_PROJECT_DIR)) }}
283
301
  restore-keys: |
284
302
  ${{ runner.os }}-gradle-
285
303
 
@@ -366,7 +384,8 @@ jobs:
366
384
  --release \
367
385
  --build-name="$VERSION_NAME" \
368
386
  --build-number="$VERSION_CODE" \
369
- --verbose
387
+ --verbose \
388
+ ${DART_DEFINE_FILE:+--dart-define-from-file="$DART_DEFINE_FILE"}
370
389
 
371
390
  BUILD_EXIT_CODE=$?
372
391
 
@@ -565,8 +584,13 @@ jobs:
565
584
  - name: Install Fastlane
566
585
  working-directory: ${{ env.FLUTTER_PROJECT_DIR }}/android
567
586
  run: |
568
- # multi_json: google-apis transitive 의존성이 선언 누락한 upstream 버그 회피 (gemspec 미선언 → Gem::LoadError)
569
- printf 'source "https://rubygems.org"\ngem "fastlane"\ngem "multi_json"\n' > Gemfile
587
+ # 저장소의 Gemfile에 fastlane이 있으면 그대로 쓴다 (Gemfile.lock 커밋 권장). 없으면 생성한다.
588
+ if [ -f Gemfile ] && grep -Eq "['\"]fastlane['\"]" Gemfile; then
589
+ echo "ℹ️ 저장소의 Gemfile을 사용합니다"
590
+ else
591
+ # multi_json: google-apis transitive 의존성이 선언 누락한 upstream 버그 회피 (gemspec 미선언 → Gem::LoadError)
592
+ printf 'source "https://rubygems.org"\ngem "fastlane"\ngem "multi_json"\n' > Gemfile
593
+ fi
570
594
  bundle install
571
595
  echo "✅ Fastlane 설치 완료 (Bundler)"
572
596
  bundle exec fastlane --version
@@ -585,6 +609,7 @@ jobs:
585
609
  - name: Upload to Play Store Internal Testing
586
610
  env:
587
611
  DEPLOY_MODE: ${{ env.DEPLOY_MODE }}
612
+ PACKAGE_NAME: ${{ secrets.ANDROID_PACKAGE_NAME || vars.ANDROID_PACKAGE_NAME }}
588
613
  run: |
589
614
  echo "=========================================="
590
615
  echo "🚀 Play Store 배포 시작"
@@ -25,6 +25,7 @@ name: PROJECT-Android-SelfHosted-CICD
25
25
  on:
26
26
  push:
27
27
  branches: ["{{MAIN_BRANCH}}"]
28
+ # @wizard paths-anchor (모노레포일 때 integrator가 paths 필터를 여기 주입)
28
29
  workflow_dispatch: # 수동 실행 옵션 추가
29
30
 
30
31
  # ============================================
@@ -35,6 +36,10 @@ env:
35
36
  APP_ARTIFACT_NAME: "__APP_ARTIFACT_NAME__" # @wizard ask:@repo
36
37
  FLUTTER_VERSION: "3.35.5"
37
38
  JAVA_VERSION: "__JAVA_VERSION__" # @wizard ask:17
39
+ # Flutter 루트 경로(레포 루트 기준). 단일레포면 ".", 모노레포면 "app" 등 — 설치 시 자동 설정
40
+ FLUTTER_PROJECT_DIR: "." # @wizard auto:flutter-root
41
+ # 환경변수 전달 방식 (dart-define | dotenv) — 설치 시 선택값으로 자동 설정
42
+ ENV_MODE: "dart-define" # @wizard auto:flutter-env-mode
38
43
  # SMB 서버 설정 (자체 서버 — Synology NAS·Linux 등)
39
44
  SMB_PORT: "44445" # 기본 445
40
45
  SMB_SHARE: "web"
@@ -45,6 +50,9 @@ jobs:
45
50
  runs-on: ubuntu-latest
46
51
  # CHANGELOG 워크플로우가 성공한 경우에만 실행
47
52
  if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name != 'workflow_run' }}
53
+ defaults:
54
+ run:
55
+ working-directory: ${{ env.FLUTTER_PROJECT_DIR }}
48
56
 
49
57
  steps:
50
58
  # Repository 체크아웃 및 목록 출력
@@ -67,14 +75,20 @@ jobs:
67
75
  ls -la ~/.android/
68
76
  keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android || echo "Keytool failed"
69
77
 
70
- # .env 파일 생성
71
- - name: Create .env file from GitHub Secret
78
+ # 환경변수 준비 — ENV_MODE=dotenv면 .env 파일, dart-define이면 프로젝트 밖 임시 파일(--dart-define-from-file)
79
+ - name: Prepare env file
72
80
  env:
73
81
  ENV_CONTENT: ${{ secrets.ENV_FILE || secrets.ENV }}
74
82
  run: |
75
- printf '%s\n' "$ENV_CONTENT" > .env
76
- echo ".env file created"
77
- ls -la
83
+ if [ "$ENV_MODE" = "dotenv" ]; then
84
+ printf '%s\n' "$ENV_CONTENT" > .env
85
+ echo ".env file created"
86
+ elif [ -n "$ENV_CONTENT" ]; then
87
+ DART_DEFINE_FILE="$RUNNER_TEMP/dart-define.env"
88
+ printf '%s\n' "$ENV_CONTENT" > "$DART_DEFINE_FILE"
89
+ echo "DART_DEFINE_FILE=$DART_DEFINE_FILE" >> "$GITHUB_ENV"
90
+ echo "dart-define file prepared"
91
+ fi
78
92
 
79
93
  # Keystore와 key.properties 설정
80
94
  - name: Setup Keystore and key.properties
@@ -117,7 +131,7 @@ jobs:
117
131
  uses: actions/cache@v6
118
132
  with:
119
133
  path: ~/.pub-cache
120
- key: ${{ runner.os }}-flutter-pub-${{ hashFiles('**/pubspec.lock') }}
134
+ key: ${{ runner.os }}-flutter-pub-${{ hashFiles(format('{0}/**/pubspec.lock', env.FLUTTER_PROJECT_DIR)) }}
121
135
  restore-keys: ${{ runner.os }}-flutter-pub-
122
136
 
123
137
  - name: Cache Gradle dependencies
@@ -126,7 +140,7 @@ jobs:
126
140
  path: |
127
141
  ~/.gradle/caches
128
142
  ~/.gradle/wrapper
129
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/build.gradle', '**/gradle-wrapper.properties') }}
143
+ key: ${{ runner.os }}-gradle-${{ hashFiles(format('{0}/android/**/build.gradle', env.FLUTTER_PROJECT_DIR), format('{0}/android/**/gradle-wrapper.properties', env.FLUTTER_PROJECT_DIR)) }}
130
144
  restore-keys: |
131
145
  ${{ runner.os }}-gradle-
132
146
 
@@ -142,7 +156,7 @@ jobs:
142
156
 
143
157
  # Gradle 셋업
144
158
  - name: Setup Gradle
145
- working-directory: android
159
+ working-directory: ${{ env.FLUTTER_PROJECT_DIR }}/android
146
160
  run: |
147
161
  chmod +x gradlew
148
162
  echo "Gradle wrapper permissions set"
@@ -159,27 +173,6 @@ jobs:
159
173
  echo "Java setup completed"
160
174
  java -version
161
175
 
162
- # Ruby 설정 및 확인
163
- - name: Set up Ruby
164
- uses: ruby/setup-ruby@v1
165
- with:
166
- ruby-version: "3.4.1"
167
-
168
- - name: Verify Ruby version
169
- run: |
170
- echo "Ruby setup completed"
171
- ruby -v
172
-
173
- # Fastlane 설치 (Bundler 방식 - gem 충돌 방지)
174
- - name: Install Fastlane
175
- working-directory: android
176
- run: |
177
- # multi_json: google-apis transitive 의존성이 선언 누락한 upstream 버그 회피 (gemspec 미선언 → Gem::LoadError)
178
- printf 'source "https://rubygems.org"\ngem "fastlane"\ngem "multi_json"\n' > Gemfile
179
- bundle install
180
- echo "Fastlane installed (Bundler)"
181
- bundle exec fastlane --version
182
-
183
176
  # 현재 버전 정보 및 짧은 커밋 해시 계산
184
177
  - name: Get version info and calculate short commit hash
185
178
  id: version_info
@@ -197,13 +190,12 @@ jobs:
197
190
  echo "현재 버전: $CURRENT_VERSION"
198
191
  echo "짧은 커밋 해시: $SHORT_COMMIT_HASH"
199
192
 
200
- # Fastlane을 이용하여 APK 빌드 (릴리스 빌드 유지)
201
- - name: Build APK with Fastlane
193
+ # APK 빌드 (릴리스 빌드 유지 — flutter로 직접 빌드)
194
+ - name: Build APK
202
195
  run: |
203
- cd android
204
- bundle exec fastlane build --verbose
205
- ls -la ../build/app/outputs/flutter-apk/ || true
206
- echo "APK built with Fastlane"
196
+ flutter build apk --release ${DART_DEFINE_FILE:+--dart-define-from-file="$DART_DEFINE_FILE"}
197
+ ls -la build/app/outputs/flutter-apk/ || true
198
+ echo "APK built"
207
199
 
208
200
  # APK 파일 이름 변경 및 준비
209
201
  - name: Rename and Prepare APK
@@ -218,7 +210,7 @@ jobs:
218
210
  uses: actions/upload-artifact@v7
219
211
  with:
220
212
  name: ${{ env.APP_ARTIFACT_NAME }}-apk
221
- path: ./android/app/build/outputs/apk/release/${{ env.APP_ARTIFACT_NAME }}-v${{ env.VERSION }}-${{ env.SHORT_COMMIT_HASH }}.apk
213
+ path: ${{ env.FLUTTER_PROJECT_DIR }}/android/app/build/outputs/apk/release/${{ env.APP_ARTIFACT_NAME }}-v${{ env.VERSION }}-${{ env.SHORT_COMMIT_HASH }}.apk
222
214
  retention-days: 1
223
215
 
224
216
  deploy-android:
@@ -39,8 +39,8 @@
39
39
  # 🔥 Firebase App Distribution (선택):
40
40
  # FIREBASE_SERVICE_ACCOUNT_JSON_BASE64: Firebase 서비스 계정 JSON (base64)
41
41
  #
42
- # 🪄 빠른 설정: .github/util/flutter/firebase-wizard/firebase-wizard.html을
43
- # 브라우저에서 열어 5단계 마법사로 Firebase 배포를 자동 설정할 수 있습니다.
42
+ # ※ 위 Secrets는 저장소 Settings → Secrets and variables → Actions에 등록하세요.
43
+ # Firebase 업로드를 쓰려면 아래 env의 FIREBASE_APP_ID·FIREBASE_TESTER_GROUP도 수정합니다.
44
44
  #
45
45
  # ===================================================================
46
46
 
@@ -61,6 +61,11 @@ on:
61
61
  env:
62
62
  FLUTTER_VERSION: "3.35.5"
63
63
  JAVA_VERSION: "__JAVA_VERSION__" # @wizard ask:17
64
+ # Flutter 루트 경로(레포 루트 기준). 단일레포면 ".", 모노레포면 "app" 등 — 설치 시 자동 설정
65
+ FLUTTER_PROJECT_DIR: "." # @wizard auto:flutter-root
66
+ # 환경변수 전달 방식 (dart-define | dotenv) — 설치 시 선택값으로 자동 설정
67
+ ENV_MODE: "dart-define" # @wizard auto:flutter-env-mode
68
+ # dotenv 모드에서 .env를 만들 경로 (Flutter 루트 기준)
64
69
  ENV_FILE_PATH: ".env"
65
70
  FIREBASE_APP_ID: "{FIREBASE_APP_ID}"
66
71
  FIREBASE_TESTER_GROUP: "{TESTER_GROUP}"
@@ -120,7 +125,7 @@ jobs:
120
125
  '',
121
126
  '### 💡 확인 사항',
122
127
  '1. 브랜치가 원격 저장소에 push되었는지 확인하세요',
123
- '2. "Guide by SUH-LAB" 댓글의 브랜치명이 올바른지 확인하세요',
128
+ '2. "Issue Helper" 댓글의 브랜치명이 올바른지 확인하세요',
124
129
  '3. 브랜치명에 오타가 없는지 확인하세요',
125
130
  '',
126
131
  `🔗 [워크플로우 로그](${runUrl})`
@@ -299,6 +304,9 @@ jobs:
299
304
  name: Android 테스트 APK 빌드
300
305
  runs-on: ubuntu-latest
301
306
  needs: prepare-test-build
307
+ defaults:
308
+ run:
309
+ working-directory: ${{ env.FLUTTER_PROJECT_DIR }}
302
310
 
303
311
  steps:
304
312
  - name: Checkout repository
@@ -310,12 +318,20 @@ jobs:
310
318
  - name: Pull latest changes
311
319
  run: git pull origin ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.branch_name || github.ref_name }}
312
320
 
313
- - name: Create .env file
321
+ # 환경변수 준비 — ENV_MODE=dotenv면 .env 파일, dart-define이면 프로젝트 밖 임시 파일(--dart-define-from-file)
322
+ - name: Prepare env file
314
323
  env:
315
324
  ENV_CONTENT: ${{ secrets.ENV_FILE || secrets.ENV }}
316
325
  run: |
317
- printf '%s\n' "$ENV_CONTENT" > ${{ env.ENV_FILE_PATH }}
318
- echo "✅ ${{ env.ENV_FILE_PATH }} file created"
326
+ if [ "$ENV_MODE" = "dotenv" ]; then
327
+ printf '%s\n' "$ENV_CONTENT" > "$ENV_FILE_PATH"
328
+ echo "✅ $ENV_FILE_PATH file created"
329
+ elif [ -n "$ENV_CONTENT" ]; then
330
+ DART_DEFINE_FILE="$RUNNER_TEMP/dart-define.env"
331
+ printf '%s\n' "$ENV_CONTENT" > "$DART_DEFINE_FILE"
332
+ echo "DART_DEFINE_FILE=$DART_DEFINE_FILE" >> "$GITHUB_ENV"
333
+ echo "dart-define file prepared"
334
+ fi
319
335
 
320
336
  - name: Setup Release Keystore
321
337
  env:
@@ -371,7 +387,7 @@ jobs:
371
387
  uses: actions/cache@v6
372
388
  with:
373
389
  path: ~/.pub-cache
374
- key: ${{ runner.os }}-flutter-pub-${{ hashFiles('**/pubspec.lock') }}
390
+ key: ${{ runner.os }}-flutter-pub-${{ hashFiles(format('{0}/**/pubspec.lock', env.FLUTTER_PROJECT_DIR)) }}
375
391
  restore-keys: ${{ runner.os }}-flutter-pub-
376
392
 
377
393
  - name: Cache Gradle dependencies
@@ -380,7 +396,7 @@ jobs:
380
396
  path: |
381
397
  ~/.gradle/caches
382
398
  ~/.gradle/wrapper
383
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/build.gradle', '**/gradle-wrapper.properties') }}
399
+ key: ${{ runner.os }}-gradle-${{ hashFiles(format('{0}/android/**/build.gradle', env.FLUTTER_PROJECT_DIR), format('{0}/android/**/gradle-wrapper.properties', env.FLUTTER_PROJECT_DIR)) }}
384
400
  restore-keys: |
385
401
  ${{ runner.os }}-gradle-
386
402
 
@@ -395,7 +411,7 @@ jobs:
395
411
 
396
412
  # Gradle 셋업
397
413
  - name: Setup Gradle
398
- working-directory: android
414
+ working-directory: ${{ env.FLUTTER_PROJECT_DIR }}/android
399
415
  run: |
400
416
  chmod +x gradlew
401
417
  echo "✅ Gradle wrapper permissions set"
@@ -412,28 +428,6 @@ jobs:
412
428
  echo "✅ Java setup completed"
413
429
  java -version
414
430
 
415
- # Ruby 설정
416
- - name: Set up Ruby
417
- uses: ruby/setup-ruby@v1
418
- with:
419
- ruby-version: "3.4.1"
420
- bundler-cache: true
421
-
422
- - name: Verify Ruby version
423
- run: |
424
- echo "✅ Ruby setup completed"
425
- ruby -v
426
-
427
- # Fastlane 설치 (Bundler 방식 - gem 충돌 방지)
428
- - name: Install Fastlane
429
- working-directory: android
430
- run: |
431
- # multi_json: google-apis transitive 의존성이 선언 누락한 upstream 버그 회피 (gemspec 미선언 → Gem::LoadError)
432
- printf 'source "https://rubygems.org"\ngem "fastlane"\ngem "multi_json"\n' > Gemfile
433
- bundle install
434
- echo "✅ Fastlane installed (Bundler)"
435
- bundle exec fastlane --version
436
-
437
431
  # 진행상황 - 준비 완료
438
432
  - name: 진행상황 - 준비 완료
439
433
  id: progress_step1
@@ -539,18 +533,11 @@ jobs:
539
533
  echo "✅ pubspec.yaml 버전 변경 완료:"
540
534
  grep "^version:" pubspec.yaml
541
535
 
542
- # APK 빌드 (Fastlane 또는 직접 빌드)
536
+ # APK 빌드 (flutter로 직접 빌드)
543
537
  - name: Build APK
544
538
  run: |
545
- # Fastlane Fastfile이 있으면 사용, 없으면 직접 빌드
546
- if [ -f "android/fastlane/Fastfile" ]; then
547
- echo "📦 Fastlane을 사용하여 빌드..."
548
- cd android
549
- bundle exec fastlane build --verbose || flutter build apk --release
550
- else
551
- echo "📦 Flutter 직접 빌드..."
552
- flutter build apk --release
553
- fi
539
+ echo "📦 Flutter 직접 빌드..."
540
+ flutter build apk --release ${DART_DEFINE_FILE:+--dart-define-from-file="$DART_DEFINE_FILE"}
554
541
  ls -la ./build/app/outputs/flutter-apk/ || true
555
542
  echo "✅ APK built"
556
543
 
@@ -693,9 +680,9 @@ jobs:
693
680
  with:
694
681
  name: ${{ steps.apk_filename.outputs.artifact_name }}
695
682
  path: |
696
- ./android/app/build/outputs/apk/release/*.apk
697
- build-info.txt
698
- build-metadata.json
683
+ ${{ env.FLUTTER_PROJECT_DIR }}/android/app/build/outputs/apk/release/*.apk
684
+ ${{ env.FLUTTER_PROJECT_DIR }}/build-info.txt
685
+ ${{ env.FLUTTER_PROJECT_DIR }}/build-metadata.json
699
686
  retention-days: 7
700
687
  if-no-files-found: error
701
688
 
@@ -730,9 +717,9 @@ jobs:
730
717
  uses: wzieba/Firebase-Distribution-Github-Action@v1
731
718
  with:
732
719
  appId: ${{ env.FIREBASE_APP_ID }}
733
- serviceCredentialsFile: firebase-service-account.json
720
+ serviceCredentialsFile: ${{ env.FLUTTER_PROJECT_DIR }}/firebase-service-account.json
734
721
  groups: ${{ env.FIREBASE_TESTER_GROUP }}
735
- file: ./android/app/build/outputs/apk/release/${{ steps.apk_filename.outputs.apk_name }}
722
+ file: ${{ env.FLUTTER_PROJECT_DIR }}/android/app/build/outputs/apk/release/${{ steps.apk_filename.outputs.apk_name }}
736
723
  releaseNotes: |
737
724
  테스트 빌드 #${{ needs.prepare-test-build.outputs.build_number }}
738
725
  브랜치: ${{ needs.prepare-test-build.outputs.branch_name }}