Google Play Store Post-Release Deployment #35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Google Play Store Post-Release Deployment | |
| on: | |
| workflow_dispatch: # Manual trigger for testing | |
| workflow_run: | |
| workflows: ["Release All Platforms"] | |
| types: | |
| - completed | |
| jobs: | |
| deploy-to-internal: | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.workflow == 'Release All Platforms') }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Fetch all history for tags | |
| submodules: false | |
| - name: Get tag name from release workflow | |
| id: get_tag | |
| run: | | |
| # Get the tag name from the release workflow outputs or manual input | |
| echo "Getting tag information..." | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| echo "Manual dispatch - using latest tag" | |
| # Get the latest tag from the repository | |
| LATEST_TAG=$(git describe --tags --abbrev=0) | |
| echo "Latest tag: $LATEST_TAG" | |
| if [[ -n "$LATEST_TAG" && "$LATEST_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| TAG_NAME="$LATEST_TAG" | |
| TAG_VERSION="${TAG_NAME#v}" | |
| # Get the app version from pubspec.yaml | |
| APP_VERSION=$(awk '/^version:/ {print $2}' src/pubspec.yaml) | |
| echo "tag-name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| echo "tag-version=$TAG_VERSION" >> $GITHUB_OUTPUT | |
| echo "app-version=$APP_VERSION" >> $GITHUB_OUTPUT | |
| echo "tag-found=true" >> $GITHUB_OUTPUT | |
| echo "✅ Using latest tag: $TAG_NAME" | |
| else | |
| echo "tag-name=" >> $GITHUB_OUTPUT | |
| echo "tag-found=false" >> $GITHUB_OUTPUT | |
| echo "❌ No valid tag found" | |
| exit 1 | |
| fi | |
| else | |
| # Get the release workflow run ID | |
| RELEASE_RUN_ID="${{ github.event.workflow_run.id }}" | |
| echo "Release workflow run ID: $RELEASE_RUN_ID" | |
| # Get the outputs from the release workflow | |
| TAG_NAME=$(gh run view "$RELEASE_RUN_ID" --json jobs --jq '.jobs[] | select(.name == "release") | .outputs | .["tag-name"]') | |
| TAG_VERSION=$(gh run view "$RELEASE_RUN_ID" --json jobs --jq '.jobs[] | select(.name == "release") | .outputs | .["tag-version"]') | |
| APP_VERSION=$(gh run view "$RELEASE_RUN_ID" --json jobs --jq '.jobs[] | select(.name == "release") | .outputs | .["app-version"]') | |
| echo "Tag name: $TAG_NAME" | |
| echo "Tag version: $TAG_VERSION" | |
| echo "App version: $APP_VERSION" | |
| if [[ -n "$TAG_NAME" && "$TAG_NAME" != "null" ]]; then | |
| echo "tag-name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| echo "tag-version=$TAG_VERSION" >> $GITHUB_OUTPUT | |
| echo "app-version=$APP_VERSION" >> $GITHUB_OUTPUT | |
| echo "tag-found=true" >> $GITHUB_OUTPUT | |
| echo "✅ Successfully retrieved tag information from release workflow" | |
| else | |
| echo "tag-name=" >> $GITHUB_OUTPUT | |
| echo "tag-found=false" >> $GITHUB_OUTPUT | |
| echo "❌ No tag found in release workflow outputs" | |
| echo "Available outputs:" | |
| gh run view "$RELEASE_RUN_ID" --json jobs --jq '.jobs[] | select(.name == "release") | .outputs' | |
| exit 1 | |
| fi | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Checkout main branch (latest fixes) | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: main | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Initialize Submodules | |
| uses: ./.github/actions/setup-repository | |
| - name: Setup Flutter with FVM | |
| uses: ./.github/actions/setup-fvm | |
| with: | |
| cache-key-suffix: "play-store-post-release" | |
| - name: Install Flutter Dependencies | |
| uses: ./.github/actions/install-flutter-deps | |
| - name: Install OpenJDK 17 | |
| run: | | |
| sudo apt-get update -y | |
| sudo apt-get install -y openjdk-17-jdk-headless | |
| - name: Setup Android SDK | |
| uses: android-actions/setup-android@v3 | |
| - name: Setup Ruby and Fastlane | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: '3.2' | |
| bundler-cache: true | |
| working-directory: fastlane | |
| - name: Install Fastlane dependencies | |
| run: | | |
| bundle install | |
| working-directory: fastlane | |
| - name: Setup Keystore | |
| run: | | |
| echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > src/android/app/whph-release.keystore | |
| - name: Update Gradle Properties | |
| run: | | |
| cat << EOF > src/android/key.properties | |
| storePassword=${{ secrets.KEYSTORE_PASSWORD }} | |
| keyPassword=${{ secrets.KEY_PASSWORD }} | |
| keyAlias=${{ secrets.KEY_ALIAS }} | |
| storeFile=whph-release.keystore | |
| EOF | |
| - name: Validate Signing Configuration | |
| run: | | |
| echo "🔐 Validating signing configuration..." | |
| # Check if keystore was created successfully | |
| if [[ ! -f "src/android/app/whph-release.keystore" ]]; then | |
| echo "❌ Keystore file not found" | |
| exit 1 | |
| fi | |
| # Validate keystore file size | |
| KEYSTORE_SIZE=$(stat -c%s "src/android/app/whph-release.keystore") | |
| if [[ $KEYSTORE_SIZE -lt 1024 ]]; then | |
| echo "⚠️ Keystore file seems too small: ${KEYSTORE_SIZE} bytes" | |
| fi | |
| echo "✅ Keystore file validated (${KEYSTORE_SIZE} bytes)" | |
| # Validate key.properties | |
| if [[ ! -f "src/android/key.properties" ]]; then | |
| echo "❌ key.properties file not found" | |
| exit 1 | |
| fi | |
| echo "✅ key.properties file validated" | |
| - name: Setup Google Play Service Account | |
| run: | | |
| echo "${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_KEY }}" | base64 --decode > ./google-play-service-account.json | |
| - name: Set application version from release workflow | |
| id: app_version | |
| run: | | |
| echo "version=${{ steps.get_tag.outputs.app-version }}" >> $GITHUB_OUTPUT | |
| echo "version-number=${{ steps.get_tag.outputs.tag-version }}" >> $GITHUB_OUTPUT | |
| echo "build-number=$(echo "${{ steps.get_tag.outputs.app-version }}" | cut -d'+' -f2)" >> $GITHUB_OUTPUT | |
| - name: Remove non-Android platforms | |
| run: | | |
| cd src | |
| rm -rf ios linux macos web windows | |
| - name: Build Android App Bundle | |
| run: | | |
| echo "🚀 Building Android App Bundle with Flutter..." | |
| cd src | |
| # Clean previous builds to ensure fresh state | |
| echo "🧹 Cleaning previous builds..." | |
| fvm flutter clean | |
| rm -rf android/app/build/ | |
| # Get dependencies | |
| echo "📦 Getting Flutter dependencies..." | |
| fvm flutter pub get | |
| # Display build environment info | |
| echo "📋 Build environment information:" | |
| fvm flutter doctor -v | |
| # Check Android build configuration | |
| echo "🔍 Android build configuration:" | |
| if [[ -f "android/key.properties" ]]; then | |
| echo "✅ key.properties found" | |
| echo "Keystore file: $(grep 'storeFile=' android/key.properties | cut -d'=' -f2)" | |
| echo "Key alias: $(grep 'keyAlias=' android/key.properties | cut -d'=' -f2)" | |
| else | |
| echo "❌ key.properties not found" | |
| exit 1 | |
| fi | |
| # Build with verbose output for debugging | |
| echo "🔨 Building AAB..." | |
| fvm flutter build appbundle --release --verbose \ | |
| --dart-define=DEPLOYMENT_ENVIRONMENT=production \ | |
| --no-tree-shake-icons | |
| # Validate build output | |
| AAB_PATH="build/app/outputs/bundle/release/app-release.aab" | |
| if [[ ! -f "$AAB_PATH" ]]; then | |
| echo "❌ AAB build failed - output file not found: $AAB_PATH" | |
| echo "Build artifacts search results:" | |
| find build -name "*.aab" -o -name "*.apk" 2>/dev/null || echo "No build artifacts found" | |
| echo "Build directory contents:" | |
| find build -type f 2>/dev/null || echo "Build directory is empty" | |
| exit 1 | |
| fi | |
| AAB_SIZE=$(stat -c%s "$AAB_PATH") | |
| echo "✅ AAB build successful: $AAB_PATH (${AAB_SIZE} bytes)" | |
| if [[ $AAB_SIZE -lt 1000000 ]]; then | |
| echo "⚠️ AAB file seems too small: ${AAB_SIZE} bytes" | |
| fi | |
| # Additional validation using aapt2 if available | |
| if command -v aapt2 &> /dev/null; then | |
| echo "🔍 Validating AAB with aapt2..." | |
| aapt2 dump badging "$AAB_PATH" | head -5 || echo "aapt2 validation failed (non-critical)" | |
| fi | |
| - name: Deploy to Internal Testing | |
| run: | | |
| echo "🚀 Preparing to deploy version ${{ steps.app_version.outputs.version }} to internal testing..." | |
| # Set environment variables for Fastlane | |
| export GOOGLE_PLAY_SERVICE_ACCOUNT_KEY="${{ github.workspace }}/google-play-service-account.json" | |
| export KEYSTORE_FILE_PATH="${{ github.workspace }}/src/android/app/whph-release.keystore" | |
| export KEYSTORE_PASSWORD="${{ secrets.KEYSTORE_PASSWORD }}" | |
| export KEY_ALIAS="${{ secrets.KEY_ALIAS }}" | |
| export KEY_PASSWORD="${{ secrets.KEY_PASSWORD }}" | |
| # Validate environment variables | |
| echo "🔍 Validating deployment configuration..." | |
| echo "Service Account: $GOOGLE_PLAY_SERVICE_ACCOUNT_KEY" | |
| echo "Keystore Path: $KEYSTORE_FILE_PATH" | |
| echo "Key Alias: $KEY_ALIAS" | |
| # Validate AAB file exists before deployment | |
| AAB_PATH="../src/build/app/outputs/bundle/release/app-release.aab" | |
| if [[ ! -f "$AAB_PATH" ]]; then | |
| echo "❌ AAB file not found: $AAB_PATH" | |
| echo "Build artifacts:" | |
| find ../src/build -name "*.aab" -o -name "*.apk" 2>/dev/null || echo "No build artifacts found" | |
| exit 1 | |
| fi | |
| AAB_SIZE=$(stat -c%s "$AAB_PATH") | |
| echo "📦 AAB file ready: $AAB_PATH (${AAB_SIZE} bytes)" | |
| # Run Fastlane with detailed output | |
| echo "🚀 Starting Fastlane deployment..." | |
| bundle exec fastlane deploy_internal --verbose | |
| echo "✅ Deployment completed successfully!" | |
| working-directory: fastlane | |
| - name: Debug Information (if failed) | |
| if: failure() | |
| run: | | |
| echo "🐛 Debugging information for failed deployment:" | |
| echo "" | |
| echo "📁 Android build directory:" | |
| find src/android/build -type f 2>/dev/null || echo "No build files found" | |
| echo "" | |
| echo "🔑 Signing configuration:" | |
| if [[ -f "src/android/key.properties" ]]; then | |
| echo "key.properties exists" | |
| echo "Store file: $(grep 'storeFile=' src/android/key.properties | cut -d'=' -f2 || echo 'Not found')" | |
| else | |
| echo "key.properties missing" | |
| fi | |
| echo "" | |
| echo "📦 Keystore file:" | |
| if [[ -f "src/android/app/whph-release.keystore" ]]; then | |
| echo "Keystore exists ($(stat -c%s src/android/app/whph-release.keystore) bytes)" | |
| else | |
| echo "Keystore missing" | |
| fi | |
| echo "" | |
| echo "🏪 Google Play service account:" | |
| if [[ -f "fastlane/google-play-service-account.json" ]]; then | |
| echo "Service account file exists" | |
| else | |
| echo "Service account file missing" | |
| fi | |
| echo "" | |
| echo "📊 Fastlane status:" | |
| cd fastlane && bundle exec fastlane lanes || echo "Could not list Fastlane lanes" | |
| - name: Create post-release deployment summary | |
| run: | | |
| echo "## 🎮 Post-Release Deployment to Internal Testing" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Version:** ${{ steps.app_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Track:** Internal Testing" >> $GITHUB_STEP_SUMMARY | |
| echo "**Trigger:** Release workflow completion (${{ github.event.workflow_run.head_branch }})" >> $GITHUB_STEP_SUMMARY | |
| echo "**Tag:** ${{ steps.get_tag.outputs.tag-name }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### 📱 App Information" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Package:** me.ahmetcetinkaya.whph" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Version Code:** ${{ steps.app_version.outputs.build-number }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Version Name:** ${{ steps.app_version.outputs.version-number }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### 🔄 Next Steps" >> $GITHUB_STEP_SUMMARY | |
| echo "1. ✅ GitHub release created successfully" >> $GITHUB_STEP_SUMMARY | |
| echo "2. ✅ Deployed to Google Play internal testing" >> $GITHUB_STEP_SUMMARY | |
| echo "3. 🔄 Test the app in internal testing" >> $GITHUB_STEP_SUMMARY | |
| echo "4. 🔄 Promote to alpha when ready" >> $GITHUB_STEP_SUMMARY | |
| echo "5. 🔄 Continue through beta to production" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### 📋 Manual Actions Required" >> $GITHUB_STEP_SUMMARY | |
| echo "- Use 'Google Play Store Deployment' workflow to promote to other tracks" >> $GITHUB_STEP_SUMMARY | |
| echo "- Use 'Google Play Store Rollout Management' workflow for production rollouts" >> $GITHUB_STEP_SUMMARY |