Skip to content

Merge remote-tracking branch 'origin/main' into deploy #13

Merge remote-tracking branch 'origin/main' into deploy

Merge remote-tracking branch 'origin/main' into deploy #13

name: PROJECT-FLUTTER-ANDROID-PLAYSTORE-INTERNAL-CICD
on:
push:
branches: ["deploy"]
workflow_run:
workflows: ["CHANGELOG 자동 업데이트"]
types: [completed]
branches: [main]
workflow_dispatch:
# ============================================
# 🔧 프로젝트별 설정 (아래 값들을 수정하세요)
# ============================================
env:
# 프로젝트 이름
PROJECT_NAME: "your-project"
# Flutter/Java 버전
FLUTTER_VERSION: "3.35.5"
JAVA_VERSION: "17"
PROJECT_TYPE: "flutter"
jobs:
prepare-build:
name: 환경 설정 및 준비
runs-on: ubuntu-latest
# CHANGELOG 워크플로우가 성공한 경우에만 실행
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name != 'workflow_run' }}
outputs:
version: ${{ steps.current_version.outputs.version }}
version_code: ${{ steps.current_version.outputs.version_code }}
project_type: ${{ steps.current_version.outputs.project_type }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: deploy
fetch-depth: 0
- name: Pull latest changes
run: git pull origin deploy
- name: Create .env file
run: |
echo "${{ secrets.ENV_FILE }}" > .env
echo ".env file created"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Cache Flutter dependencies
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: ${{ runner.os }}-flutter-pub-${{ hashFiles('**/pubspec.lock') }}
restore-keys: ${{ runner.os }}-flutter-pub-
- name: Install dependencies
run: flutter pub get
# 버전 관리 스크립트 권한 설정
- name: 버전 관리 스크립트 권한 설정
run: |
chmod +x ./.github/scripts/version_manager.sh
chmod +x ./.github/scripts/changelog_manager.py
# version_manager.sh를 사용하여 현재 버전 정보 가져오기
- name: 현재 버전 정보 가져오기
id: current_version
run: |
# VERSION 가져오기 (x.y.z 형식)
VERSION=$(./.github/scripts/version_manager.sh get | tail -n 1)
# VERSION_CODE 가져오기 (version.yml에서 관리되는 단순 증가 번호)
VERSION_CODE=$(./.github/scripts/version_manager.sh get-code)
# 결과 출력
echo "✅ VERSION: $VERSION"
echo "✅ VERSION_CODE: $VERSION_CODE"
echo "🔧 프로젝트 타입: ${{ env.PROJECT_TYPE }}"
# GitHub outputs 설정
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "version_code=$VERSION_CODE" >> $GITHUB_OUTPUT
echo "project_type=${{ env.PROJECT_TYPE }}" >> $GITHUB_OUTPUT
# 환경변수로도 설정 (스크립트에서 사용)
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "VERSION_CODE=$VERSION_CODE" >> $GITHUB_ENV
echo "TODAY=$(date '+%Y-%m-%d')" >> $GITHUB_ENV
echo "TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')" >> $GITHUB_ENV
echo "PROJECT_TYPE=${{ env.PROJECT_TYPE }}" >> $GITHUB_ENV
# CHANGELOG.json에서 릴리즈 노트 추출 - changelog_manager.py 사용
- name: 릴리즈 노트 생성
id: release_notes
run: |
VERSION="${{ steps.current_version.outputs.version }}"
if [ -f "CHANGELOG.json" ]; then
echo "📄 CHANGELOG.json에서 v$VERSION 릴리즈 노트 추출 중..."
# CHANGELOG.md 생성
python3 ./.github/scripts/changelog_manager.py generate-md
# changelog_manager.py export로 릴리즈 노트 추출
python3 ./.github/scripts/changelog_manager.py export --version $VERSION --output final_release_notes.txt
if [ -s final_release_notes.txt ]; then
echo "✅ 릴리즈 노트 추출 성공!"
echo "📋 추출된 릴리즈 노트:"
echo "----------------------------------------"
cat final_release_notes.txt
echo "----------------------------------------"
echo "RELEASE_NOTES_FOUND=true" >> $GITHUB_ENV
else
echo "❌ 릴리즈 노트 추출 실패"
echo "RELEASE_NOTES_FOUND=false" >> $GITHUB_ENV
echo "v$VERSION 업데이트" > final_release_notes.txt
fi
else
echo "⚠️ CHANGELOG.json 파일이 없습니다. 기본 릴리즈 노트를 사용합니다."
echo "RELEASE_NOTES_FOUND=false" >> $GITHUB_ENV
echo "v$VERSION 업데이트" > final_release_notes.txt
fi
# 릴리즈 노트를 아티팩트로 업로드
- name: Upload release notes
uses: actions/upload-artifact@v4
with:
name: release-notes
path: final_release_notes.txt
retention-days: 1
# 프로젝트 파일들을 아티팩트로 업로드
# .env는 보안상 아티팩트에 포함하지 않고, 각 job에서 secrets로 재생성
- name: Upload project files
uses: actions/upload-artifact@v4
with:
name: project-files
path: |
pubspec.yaml
lib/
assets/
retention-days: 1
build-android:
name: Android AAB 빌드
runs-on: ubuntu-latest
needs: prepare-build
timeout-minutes: 45
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: deploy
fetch-depth: 0
- name: Pull latest changes
run: git pull origin deploy
# 프로젝트 파일들 다운로드
- name: Download project files
uses: actions/download-artifact@v4
with:
name: project-files
path: .
# .env 파일 생성 (보안을 위해 아티팩트가 아닌 시크릿에서 생성)
- name: Create .env file
run: |
echo "${{ secrets.ENV_FILE }}" > .env
echo "✅ .env 파일 생성됨 (크기: $(wc -c < .env) bytes)"
# Release Keystore 설정
# build.gradle.kts에서 rootProject.file()을 사용하므로 android/ 기준으로 경로 설정
- name: Setup Release Keystore
run: |
mkdir -p android/app/keystore
echo "${{ secrets.RELEASE_KEYSTORE_BASE64 }}" | base64 -d > android/app/keystore/key.jks
echo "✅ Release Keystore 생성 완료"
ls -la android/app/keystore/
# key.properties 생성 (Release 서명 정보)
- name: Create key.properties
run: |
cat > android/key.properties << EOF
storeFile=app/keystore/key.jks
storePassword=${{ secrets.RELEASE_KEYSTORE_PASSWORD }}
keyAlias=${{ secrets.RELEASE_KEY_ALIAS }}
keyPassword=${{ secrets.RELEASE_KEY_PASSWORD }}
EOF
echo "✅ key.properties 생성 완료"
cat android/key.properties
# Google-services.json 생성
- name: Create Google-services.json
run: |
cat << 'EOF' > android/app/google-services.json
${{ secrets.GOOGLE_SERVICES_JSON }}
EOF
echo "✅ Google-services.json 생성 완료"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Cache Flutter dependencies
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: ${{ runner.os }}-flutter-pub-${{ hashFiles('**/pubspec.lock') }}
restore-keys: ${{ runner.os }}-flutter-pub-
- name: Install dependencies
run: flutter pub get
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: ${{ env.JAVA_VERSION }}
- name: Cache Gradle dependencies
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
~/.gradle/buildOutputCleanup
key: ${{ runner.os }}-gradle-8.12-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', '**/gradle.properties') }}
restore-keys: |
${{ runner.os }}-gradle-8.12-
${{ runner.os }}-gradle-
# Android build.gradle.kts 수정 (release 서명 설정)
- name: Configure Android build for release
run: |
# build.gradle.kts에 release 서명 설정이 없으면 추가
if ! grep -q "signingConfigs" android/app/build.gradle.kts; then
echo "⚠️ build.gradle.kts에 서명 설정 추가 필요"
# 서명 설정은 이미 되어있다고 가정 (수동으로 미리 설정해야 함)
fi
echo "✅ Android 빌드 설정 확인 완료"
# pubspec.yaml은 x.y.z 형식 그대로 유지
# Flutter build 명령어의 --build-name, --build-number 플래그가 pubspec.yaml을 오버라이드함
# Flutter build appbundle (AAB 생성)
- name: Build Android App Bundle (AAB)
run: |
VERSION_NAME="${{ needs.prepare-build.outputs.version }}"
VERSION_CODE="${{ needs.prepare-build.outputs.version_code }}"
echo "=========================================="
echo "🚀 AAB 빌드 시작"
echo "=========================================="
echo "🎯 빌드 버전: $VERSION_NAME"
echo "🎯 빌드 코드: $VERSION_CODE"
# 입력 검증
if [ -z "$VERSION_NAME" ] || [ -z "$VERSION_CODE" ]; then
echo "❌ VERSION_NAME 또는 VERSION_CODE가 비어있습니다!"
exit 1
fi
# Flutter 환경 정보 출력
echo "🔍 Flutter 환경 정보:"
flutter --version
flutter doctor -v | head -20
# 빌드 디렉토리 정리
echo "🧹 이전 빌드 결과물 정리..."
rm -rf build/app/outputs/bundle/release/
mkdir -p build/app/outputs/bundle/release/
# Flutter clean 및 pub get
echo "🔄 Flutter clean 및 의존성 재설치..."
flutter clean
flutter pub get
# Gradle 네트워크 연결 테스트
echo "🔍 Gradle 서버 연결 테스트..."
if ! curl -I --max-time 30 https://services.gradle.org/distributions/gradle-8.12-all.zip 2>&1 | grep -q "200\|302"; then
echo "⚠️ Gradle 서버 응답 느림 또는 실패, 재시도 중..."
sleep 5
if ! curl -I --max-time 30 https://services.gradle.org/distributions/gradle-8.12-all.zip 2>&1 | grep -q "200\|302"; then
echo "❌ Gradle 서버 접근 실패, 하지만 계속 진행..."
else
echo "✅ Gradle 서버 연결 성공 (재시도)"
fi
else
echo "✅ Gradle 서버 연결 정상"
fi
# Gradle wrapper 권한 및 사전 준비
echo "🔧 Gradle wrapper 준비..."
chmod +x android/gradlew
# Gradle 버전 확인 (Gradle 다운로드 트리거, 타임아웃 포함)
echo "📦 Gradle 다운로드 및 초기화 중..."
cd android
timeout 300s ./gradlew --version --no-daemon --info || {
EXIT_CODE=$?
if [ $EXIT_CODE -eq 124 ]; then
echo "⚠️ Gradle 초기화 타임아웃 (300초), 재시도 중..."
timeout 300s ./gradlew --version --no-daemon --info || {
echo "❌ Gradle 초기화 재시도 실패"
exit 1
}
else
echo "❌ Gradle 초기화 실패 (Exit code: $EXIT_CODE)"
exit 1
fi
}
cd ..
echo "✅ Gradle 다운로드 및 초기화 완료"
# local.properties에 버전 정보 추가 (Flutter 플래그가 무시되는 문제 해결)
echo "🔧 local.properties에 버전 정보 설정..."
# 기존 local.properties가 있으면 버전 정보 제거
if [ -f "android/local.properties" ]; then
grep -v "flutter.versionName\|flutter.versionCode" android/local.properties > android/local.properties.tmp || true
mv android/local.properties.tmp android/local.properties
else
touch android/local.properties
fi
# 버전 정보 추가
echo "flutter.versionName=$VERSION_NAME" >> android/local.properties
echo "flutter.versionCode=$VERSION_CODE" >> android/local.properties
echo "✅ local.properties 업데이트 완료"
echo "📋 버전 정보: VERSION_NAME=$VERSION_NAME, VERSION_CODE=$VERSION_CODE"
# Gradle 성능 최적화 설정
export GRADLE_OPTS="-Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=4"
export JAVA_OPTS="-Xmx4g"
echo "✅ Gradle 최적화 설정 완료"
# Flutter build 명령어에 버전 정보 전달
# --build-name과 --build-number 플래그가 pubspec.yaml의 version을 오버라이드함
# pubspec.yaml은 x.y.z 형식 유지, VERSION_CODE는 version.yml에서 자동 관리
echo "🔨 Flutter build 실행..."
echo "📋 명령어: flutter build appbundle --release --build-name=$VERSION_NAME --build-number=$VERSION_CODE --verbose"
echo "⏱️ 빌드 시작 시간: $(date '+%Y-%m-%d %H:%M:%S')"
flutter build appbundle \
--release \
--build-name="$VERSION_NAME" \
--build-number="$VERSION_CODE" \
--verbose
BUILD_EXIT_CODE=$?
if [ $BUILD_EXIT_CODE -ne 0 ]; then
echo "❌ Flutter build 실패! Exit code: $BUILD_EXIT_CODE"
echo "🔍 빌드 디렉토리 상태:"
find build/ -name "*.aab" -o -name "*.apk" 2>/dev/null || echo "AAB/APK 파일을 찾을 수 없습니다"
exit 1
fi
echo "✅ Flutter build 성공!"
# 빌드 결과 확인
echo "🔍 빌드 결과 확인:"
ls -lah build/app/outputs/bundle/release/
# AAB 파일 존재 확인
AAB_FILE="build/app/outputs/bundle/release/app-release.aab"
if [ ! -f "$AAB_FILE" ]; then
echo "❌ AAB 파일이 생성되지 않았습니다!"
echo "🔍 전체 빌드 디렉토리 내용:"
find build/ -type f -name "*.aab" -o -name "*.apk" 2>/dev/null || echo "AAB/APK 파일을 찾을 수 없습니다"
echo "🔍 outputs 디렉토리 구조:"
find build/app/outputs/ -type f 2>/dev/null || echo "outputs 디렉토리가 없습니다"
exit 1
fi
echo "✅ AAB 파일 생성 확인"
echo "📱 AAB 파일 크기: $(du -h "$AAB_FILE" | cut -f1)"
echo "📋 AAB 파일 정보: $(ls -lah "$AAB_FILE")"
# bundletool 다운로드 및 설치
echo "📦 bundletool 다운로드 중..."
BUNDLETOOL_VERSION="1.15.6"
BUNDLETOOL_URL="https://github.com/google/bundletool/releases/download/${BUNDLETOOL_VERSION}/bundletool-all-${BUNDLETOOL_VERSION}.jar"
echo "📋 다운로드 URL: $BUNDLETOOL_URL"
wget -q "$BUNDLETOOL_URL" -O bundletool.jar
if [ ! -f "bundletool.jar" ]; then
echo "❌ bundletool 다운로드 실패"
echo "🔄 대체 URL로 재시도..."
wget -q "https://github.com/google/bundletool/releases/latest/download/bundletool-all-1.15.6.jar" -O bundletool.jar
if [ ! -f "bundletool.jar" ]; then
echo "❌ bundletool 다운로드 완전 실패"
exit 1
fi
fi
echo "✅ bundletool 다운로드 완료"
echo "📋 bundletool 파일 크기: $(du -h bundletool.jar | cut -f1)"
# Java 환경 확인
echo "🔍 Java 환경 확인:"
java -version
# AAB 파일 내부의 실제 버전 정보 확인
# Flutter CLI 플래그로 전달한 VERSION_CODE가 제대로 적용되었는지 검증
echo "=========================================="
echo "🔍 AAB 파일 내부 버전 정보 검증"
echo "=========================================="
# AndroidManifest.xml에서 버전 정보 추출
echo "📋 AAB에서 실제 버전 정보 추출 중..."
echo "📋 실행할 명령어: java -jar bundletool.jar dump manifest --bundle='$AAB_FILE'"
MANIFEST_OUTPUT=$(java -jar bundletool.jar dump manifest --bundle="$AAB_FILE" 2>&1)
MANIFEST_EXIT_CODE=$?
echo "📋 bundletool 실행 결과 (Exit code: $MANIFEST_EXIT_CODE):"
echo "$MANIFEST_OUTPUT"
if [ $MANIFEST_EXIT_CODE -eq 0 ]; then
echo "✅ Manifest 추출 성공"
# 실제 버전 코드와 버전 이름 추출
ACTUAL_VERSION_CODE=$(echo "$MANIFEST_OUTPUT" | grep -o 'android:versionCode="[0-9]*"' | grep -o '[0-9]*' | head -1)
ACTUAL_VERSION_NAME=$(echo "$MANIFEST_OUTPUT" | grep -o 'android:versionName="[^"]*"' | sed 's/android:versionName="//;s/"//' | head -1)
echo "🎯 버전 정보 비교:"
echo " 예상 VERSION_CODE: '$VERSION_CODE'"
echo " 실제 VERSION_CODE: '$ACTUAL_VERSION_CODE'"
echo " 예상 VERSION_NAME: '$VERSION_NAME'"
echo " 실제 VERSION_NAME: '$ACTUAL_VERSION_NAME'"
# VERSION_CODE 검증 - version.yml에서 관리되는 단순 증가 번호
if [ -z "$ACTUAL_VERSION_CODE" ]; then
echo "❌ 치명적 오류: AAB에서 VERSION_CODE를 추출할 수 없습니다!"
echo "🔍 전체 Manifest 내용:"
echo "$MANIFEST_OUTPUT"
exit 1
elif [ "$ACTUAL_VERSION_CODE" != "$VERSION_CODE" ]; then
echo "❌ 치명적 오류: AAB의 VERSION_CODE가 예상과 다릅니다!"
echo " 이는 Google Play에서 '이미 사용된 버전 코드' 오류를 발생시킵니다."
echo ""
echo "🔍 디버깅 정보:"
echo " version.yml의 VERSION_CODE: $VERSION_CODE"
echo " AAB 파일 내부의 VERSION_CODE: $ACTUAL_VERSION_CODE"
echo ""
echo " Flutter build 명령어에 전달된 플래그:"
echo " --build-name='$VERSION_NAME'"
echo " --build-number='$VERSION_CODE'"
echo ""
echo " 전체 Manifest 내용:"
echo "$MANIFEST_OUTPUT" | grep -E "versionCode|versionName|package"
exit 1
else
echo "✅ VERSION_CODE 검증 성공: $ACTUAL_VERSION_CODE"
fi
# 버전 이름도 확인 (경고만)
if [ -z "$ACTUAL_VERSION_NAME" ]; then
echo "⚠️ 경고: AAB에서 VERSION_NAME을 추출할 수 없습니다"
elif [ "$ACTUAL_VERSION_NAME" != "$VERSION_NAME" ]; then
echo "⚠️ 경고: VERSION_NAME이 예상과 다릅니다 (치명적이지 않음)"
echo " 예상: '$VERSION_NAME', 실제: '$ACTUAL_VERSION_NAME'"
else
echo "✅ VERSION_NAME 검증 성공: $ACTUAL_VERSION_NAME"
fi
else
echo "❌ bundletool로 Manifest 추출 실패"
echo "🔄 대체 방법으로 검증 시도..."
# unzip으로 직접 확인 시도
echo "📋 unzip을 사용한 직접 추출 시도..."
UNZIP_OUTPUT=$(unzip -p "$AAB_FILE" base/manifest/AndroidManifest.xml 2>/dev/null | strings | grep -E "versionCode|versionName")
if [ -n "$UNZIP_OUTPUT" ]; then
echo "✅ unzip으로 버전 정보 추출 성공:"
echo "$UNZIP_OUTPUT"
else
echo "❌ unzip을 사용한 직접 추출도 실패"
echo "⚠️ AAB 검증을 건너뛰고 계속 진행합니다."
fi
fi
echo "=========================================="
echo "✅ AAB 빌드 및 검증 완료"
echo "🎯 최종 AAB: $AAB_FILE"
echo "📱 파일 크기: $(du -h "$AAB_FILE" | cut -f1)"
echo "=========================================="
# AAB 파일을 아티팩트로 업로드
- name: Upload AAB artifact
uses: actions/upload-artifact@v4
with:
name: android-aab
path: build/app/outputs/bundle/release/app-release.aab
retention-days: 1
deploy-playstore:
name: Play Store 내부 테스트 배포
runs-on: ubuntu-latest
needs: [prepare-build, build-android]
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: deploy
fetch-depth: 0
# Service Account JSON 설정
- name: Setup Google Play Service Account
run: |
mkdir -p ~/.config/gcloud
echo "${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_BASE64 }}" | base64 --decode > ~/.config/gcloud/service-account.json
echo "✅ Service Account JSON 설정 완료"
# AAB 파일 다운로드
- name: Download AAB artifact
uses: actions/download-artifact@v4
with:
name: android-aab
path: build/app/outputs/bundle/release/
# 릴리즈 노트 다운로드
- name: Download release notes
uses: actions/download-artifact@v4
with:
name: release-notes
path: .
# Ruby 및 Fastlane 설치
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.4.1"
- name: Install Fastlane
run: |
gem install fastlane
echo "✅ Fastlane 설치 완료"
fastlane --version
# Fastfile 복사 (Play Store 배포용)
# android/fastlane/Fastfile.playstore를 사용하여 일관성 유지
- name: Copy Fastfile for Play Store
run: |
mkdir -p android/fastlane
cp android/fastlane/Fastfile.playstore android/fastlane/Fastfile
echo "✅ Fastfile 복사 완료 (Fastfile.playstore → Fastfile)"
echo "📋 Fastfile 내용:"
cat android/fastlane/Fastfile
# Play Store에 업로드
- name: Upload to Play Store Internal Testing
run: |
echo "=========================================="
echo "🚀 Play Store 배포 시작"
echo "=========================================="
echo "🕐 배포 시작 시간: $(date '+%Y-%m-%d %H:%M:%S')"
echo "🔍 GitHub Run Number: ${{ github.run_number }}"
echo "🔍 GitHub SHA: ${{ github.sha }}"
# 환경 변수 초기화 및 검증
VERSION_CODE="${{ needs.prepare-build.outputs.version_code }}"
VERSION_NAME="${{ needs.prepare-build.outputs.version }}"
echo "📋 배포 대상 버전 정보:"
echo " VERSION_NAME: '$VERSION_NAME'"
echo " VERSION_CODE: '$VERSION_CODE'"
# 입력 검증
if [ -z "$VERSION_NAME" ] || [ -z "$VERSION_CODE" ]; then
echo "❌ 치명적 오류: VERSION_NAME 또는 VERSION_CODE가 비어있습니다!"
echo "VERSION_NAME: '$VERSION_NAME'"
echo "VERSION_CODE: '$VERSION_CODE'"
echo "이는 prepare-build 작업에서 출력이 제대로 전달되지 않았음을 의미합니다."
exit 1
fi
# AAB 파일 절대 경로 찾기
AAB_PATH=$(realpath build/app/outputs/bundle/release/app-release.aab)
echo "📦 AAB 파일 경로: $AAB_PATH"
if [ ! -f "$AAB_PATH" ]; then
echo "❌ AAB 파일을 찾을 수 없습니다!"
echo "🔍 빌드 디렉토리 내용:"
ls -la build/app/outputs/bundle/release/ || echo "디렉토리가 존재하지 않습니다"
echo "🔍 전체 빌드 디렉토리 구조:"
find build/ -name "*.aab" -o -name "*.apk" 2>/dev/null || echo "AAB/APK 파일을 찾을 수 없습니다"
exit 1
fi
echo "✅ AAB 파일 존재 확인"
echo "📋 AAB 파일 정보: $(ls -lah "$AAB_PATH")"
echo "📱 AAB 파일 크기: $(du -h "$AAB_PATH" | cut -f1)"
# 배포 전 AAB 버전 검증
echo "=========================================="
echo "🔍 AAB 버전 검증 중..."
echo "=========================================="
# bundletool 다운로드
if [ ! -f "bundletool.jar" ]; then
wget -q "https://github.com/google/bundletool/releases/download/1.15.6/bundletool-all-1.15.6.jar" -O bundletool.jar
fi
if [ -f "bundletool.jar" ]; then
MANIFEST_OUTPUT=$(java -jar bundletool.jar dump manifest --bundle="$AAB_PATH" 2>&1)
if [ $? -eq 0 ]; then
FINAL_VERSION_CODE=$(echo "$MANIFEST_OUTPUT" | grep -o 'android:versionCode="[0-9]*"' | grep -o '[0-9]*' | head -1)
FINAL_VERSION_NAME=$(echo "$MANIFEST_OUTPUT" | grep -o 'android:versionName="[^"]*"' | sed 's/android:versionName="//;s/"//' | head -1)
echo "📋 AAB 버전: $FINAL_VERSION_NAME (코드: $FINAL_VERSION_CODE)"
# VERSION_CODE 검증
if [ "$FINAL_VERSION_CODE" != "$VERSION_CODE" ]; then
echo "❌ 오류: AAB 버전 코드가 예상과 다릅니다! (예상: $VERSION_CODE, 실제: $FINAL_VERSION_CODE)"
exit 1
fi
echo "✅ 버전 검증 성공"
else
echo "⚠️ 버전 검증 실패, 배포 계속 진행"
fi
fi
# Release notes 준비
CHANGELOG_DIR="android/fastlane/metadata/android/ko-KR/changelogs"
mkdir -p "$CHANGELOG_DIR"
if [ -f "final_release_notes.txt" ]; then
cp final_release_notes.txt "$CHANGELOG_DIR/${VERSION_CODE}.txt"
echo "✅ Changelog 준비 완료 (버전 코드: $VERSION_CODE)"
else
echo "v$VERSION_NAME 업데이트" > "$CHANGELOG_DIR/${VERSION_CODE}.txt"
echo "⚠️ 기본 Changelog 생성 (버전 코드: $VERSION_CODE)"
fi
# Service Account JSON 파일 확인
GOOGLE_PLAY_JSON_KEY="$HOME/.config/gcloud/service-account.json"
if [ ! -f "$GOOGLE_PLAY_JSON_KEY" ]; then
echo "❌ Service Account JSON 파일을 찾을 수 없습니다"
exit 1
fi
# 환경변수 설정
export AAB_PATH="$AAB_PATH"
export GOOGLE_PLAY_JSON_KEY="$GOOGLE_PLAY_JSON_KEY"
export VERSION_NAME="$VERSION_NAME"
export VERSION_CODE="$VERSION_CODE"
# 배포 실행
echo "=========================================="
echo "🚀 Play Store 배포 실행"
echo "🎯 버전: $VERSION_NAME (코드: $VERSION_CODE)"
echo "=========================================="
cd android
fastlane deploy_internal
# 성공 알림
- name: Notify Play Store Upload Success
if: success()
run: |
echo "✅ Play Store 내부 테스트 배포 성공!"
echo "버전: ${{ needs.prepare-build.outputs.version }} (${{ needs.prepare-build.outputs.version_code }})"
echo "커밋: ${{ github.sha }}"
echo ""
echo "📱 테스터 확인 방법:"
echo "1. Play Console → 테스트 및 출시 → 내부 테스트"
echo "2. 테스터에게 테스트 링크 공유"
# Play Console URL은 프로젝트별로 다르므로 별도 설정 필요
- name: Notify on Failure
if: failure()
run: |
echo "❌ Play Store 배포 실패!"
echo "로그를 확인해주세요."