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.
- package/README.md +83 -4
- package/package.json +1 -1
- package/payload/config/breaking-changes.json +24 -1
- package/payload/flutter-app/android/fastlane/Fastfile.playstore +86 -0
- package/payload/flutter-app/ios/ExportOptions.plist +31 -0
- package/payload/flutter-app/ios/fastlane/Fastfile +117 -0
- package/payload/scripts/__pycache__/changelog_manager.cpython-314.pyc +0 -0
- package/payload/scripts/__pycache__/issue_helper.cpython-314.pyc +0 -0
- package/payload/scripts/__pycache__/version_manager.cpython-314.pyc +0 -0
- package/payload/scripts/changelog_manager.py +2 -2
- package/payload/scripts/version_manager.py +2 -2
- package/payload/version.yml.template +1 -0
- package/payload/workflows/common/secret-backup/PROJECT-COMMON-SECRET-FILE-UPLOAD.yaml +12 -12
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-FIREBASE-CICD.yaml +48 -20
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +44 -19
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-SELFHOSTED-CICD.yaml +28 -36
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +33 -46
- package/payload/workflows/flutter/{PROJECT-FLUTTER-SUH-LAB-APP-BUILD-TRIGGER.yaml → PROJECT-FLUTTER-APP-BUILD-TRIGGER.yaml} +38 -38
- package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +123 -32
- package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +57 -42
- package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TESTFLIGHT.yaml +61 -40
- package/payload/workflows/go/PROJECT-GO-CI.yaml +47 -0
- package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +40 -40
- package/payload/workflows/next/PROJECT-NEXT-CI.yaml +47 -0
- package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +47 -0
- package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +40 -40
- package/payload/workflows/react/PROJECT-REACT-CI.yaml +47 -0
- package/payload/workflows/spring/nexus/PROJECT-SPRING-GITHUB-PACKAGES-PUBLISH.yml +1 -0
- package/payload/workflows/spring/nexus/PROJECT-SPRING-NEXUS-CI.yml +47 -0
- package/payload/workflows/spring/nexus/PROJECT-SPRING-NEXUS-PUBLISH.yml +1 -0
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +39 -39
- package/src/cli/args.js +37 -0
- package/src/cli/help.js +4 -0
- package/src/commands/doctor.js +55 -2
- package/src/commands/dry-run.js +10 -0
- package/src/commands/full.js +28 -3
- package/src/commands/interactive-flutter.js +95 -0
- package/src/commands/interactive.js +51 -5
- package/src/commands/status.js +20 -2
- package/src/context.js +6 -0
- package/src/core/breaking.js +7 -3
- package/src/core/copy/flutter-app.js +42 -0
- package/src/core/copy/workflows.js +21 -9
- package/src/core/detect-fs.js +9 -1
- package/src/core/flutter-options.js +118 -0
- package/src/core/installed-stores.js +12 -0
- package/src/core/verify.js +2 -2
- package/src/core/version-yml.js +40 -5
- package/src/core/wizard-env.js +26 -4
- package/src/index.js +32 -1
- package/src/ui/env-plan.js +8 -5
- package/src/ui/prompts.js +88 -3
- package/src/ui/status-cards.js +13 -1
- 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
|
-
#
|
|
30
|
-
#
|
|
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:
|
|
102
|
+
- name: Prepare env file
|
|
95
103
|
env:
|
|
96
104
|
ENV_CONTENT: ${{ secrets.ENV_FILE || secrets.ENV }}
|
|
97
105
|
run: |
|
|
98
|
-
|
|
99
|
-
|
|
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('
|
|
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
|
-
#
|
|
223
|
-
- name:
|
|
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
|
-
|
|
228
|
-
|
|
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('
|
|
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('
|
|
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
|
-
#
|
|
52
|
-
|
|
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:
|
|
83
|
+
- name: Prepare env file
|
|
80
84
|
env:
|
|
81
85
|
ENV_CONTENT: ${{ secrets.ENV_FILE || secrets.ENV }}
|
|
82
86
|
run: |
|
|
83
|
-
|
|
84
|
-
|
|
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('
|
|
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
|
-
#
|
|
215
|
-
- name:
|
|
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
|
-
|
|
220
|
-
|
|
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('
|
|
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('
|
|
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
|
-
#
|
|
569
|
-
|
|
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:
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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('
|
|
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('
|
|
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
|
-
#
|
|
201
|
-
- name: Build APK
|
|
193
|
+
# APK 빌드 (릴리스 빌드 유지 — flutter로 직접 빌드)
|
|
194
|
+
- name: Build APK
|
|
202
195
|
run: |
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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:
|
|
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
|
-
#
|
|
43
|
-
#
|
|
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. "
|
|
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
|
-
|
|
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
|
-
|
|
318
|
-
|
|
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('
|
|
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('
|
|
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 빌드 (
|
|
536
|
+
# APK 빌드 (flutter로 직접 빌드)
|
|
543
537
|
- name: Build APK
|
|
544
538
|
run: |
|
|
545
|
-
|
|
546
|
-
|
|
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
|
-
|
|
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:
|
|
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 }}
|