diff --git a/.github/workflows/android_deploy_production.yml b/.github/workflows/android_deploy_production.yml index 0d948330..0a7725f7 100644 --- a/.github/workflows/android_deploy_production.yml +++ b/.github/workflows/android_deploy_production.yml @@ -46,7 +46,7 @@ jobs: env: ENV: ${{ secrets.ENV }} run: | - echo "$ENV" > .env + echo -e "$ENV" > .env # App Bundle requires Firebase connected to Play Store to upload https://appdistribution.page.link/KPoa - name: Build Android apk diff --git a/.github/workflows/android_deploy_production_to_playstore.yml b/.github/workflows/android_deploy_production_to_playstore.yml index cdeb2f09..5f9fadb2 100644 --- a/.github/workflows/android_deploy_production_to_playstore.yml +++ b/.github/workflows/android_deploy_production_to_playstore.yml @@ -46,7 +46,7 @@ jobs: env: ENV: ${{ secrets.ENV }} run: | - echo "$ENV" > .env + echo -e "$ENV" > .env - name: Set up release signing configs env: diff --git a/.github/workflows/android_deploy_staging.yml b/.github/workflows/android_deploy_staging.yml index d5915c41..3261228f 100644 --- a/.github/workflows/android_deploy_staging.yml +++ b/.github/workflows/android_deploy_staging.yml @@ -46,7 +46,7 @@ jobs: env: ENV: ${{ secrets.ENV }} run: | - echo "$ENV" > .env.staging + echo -e "$ENV" > .env.staging # App Bundle requires Firebase connected to Play Store to upload https://appdistribution.page.link/KPoa - name: Build Android apk diff --git a/.github/workflows/ios_deploy_staging_to_firebase.yml b/.github/workflows/ios_deploy_staging_to_firebase.yml index ac7f4d66..e56615e4 100644 --- a/.github/workflows/ios_deploy_staging_to_firebase.yml +++ b/.github/workflows/ios_deploy_staging_to_firebase.yml @@ -53,7 +53,7 @@ jobs: env: ENV: ${{ secrets.ENV }} run: | - echo "$ENV" > .env.staging + echo -e "$ENV" > .env.staging - name: Run code generator run: flutter packages pub run build_runner build --delete-conflicting-outputs diff --git a/.github/workflows/ios_deploy_to_app_store.yml b/.github/workflows/ios_deploy_to_app_store.yml new file mode 100644 index 00000000..b2da332c --- /dev/null +++ b/.github/workflows/ios_deploy_to_app_store.yml @@ -0,0 +1,97 @@ +name: ios-deploy-production-to-app-store +on: + # Trigger the workflow on push action + push: + branches: + - main + +jobs: + build_and_upload_to_app_store: + name: Build And Upload iOS Application Production To AppStore + runs-on: macOS-latest + environment: production + timeout-minutes: 30 + env: + TEAM_ID: ${{ secrets.TEAM_ID }} + FASTLANE_USER: ${{ secrets.FASTLANE_USER }} + FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }} + FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }} + FASTLANE_SESSION: ${{ secrets.FASTLANE_SESSION }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + APP_STORE_KEY_ID: ${{ secrets.APP_STORE_KEY_ID }} + APP_STORE_ISSUER_ID: ${{ secrets.APP_STORE_ISSUER_ID }} + APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Install SSH key + uses: webfactory/ssh-agent@v0.7.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Set up Flutter environment + uses: subosito/flutter-action@v2 + with: + channel: 'stable' + flutter-version: '3.10.5' + + - name: Generate new project + run: | + dart pub global activate mason_cli + mason get + mason make template -c mason-config.json + # Move the generated project to the root directory for next steps & cleanup to not affect static code analysis + rsync -av --remove-source-files flutter_templates/ ./ + rm -rf bricks sample + + - name: Get Flutter dependencies + run: flutter pub get + + - name: Set up Production env + env: + ENV: ${{ secrets.ENV }} + run: | + echo -e "$ENV" >> .env + + - name: Run code generator + run: flutter packages pub run build_runner build --delete-conflicting-outputs + + - name: Cache Ruby gems + uses: actions/cache@v3 + id: bunlderCache + with: + path: ios/vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: ${{ runner.os }}-gems- + + - name: Cache Pods + uses: actions/cache@v3 + id: cocoapodCache + with: + path: ios/Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: ${{ runner.os }}-pods- + + - name: Bundle install + run: cd ./ios && bundle install + + - name: Pod install + run: cd ./ios && pod install + + - name: Update fastlane + run: cd ./ios && bundle update fastlane + + - name: Update plugins + run: cd ./ios && bundle exec fastlane update_plugins + + - name: Match AppStore + run: cd ./ios && bundle exec fastlane sync_appstore_production_signing + env: + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER + + - name: Deploy to AppStore + run: | + cd ./ios && bundle exec fastlane build_and_upload_production_app_store_connect_app diff --git a/.github/workflows/ios_deploy_to_testflight.yml b/.github/workflows/ios_deploy_to_testflight.yml new file mode 100644 index 00000000..52ac52ae --- /dev/null +++ b/.github/workflows/ios_deploy_to_testflight.yml @@ -0,0 +1,97 @@ +name: ios-deploy-production-to-testflight +on: + # Trigger the workflow on push action + push: + branches: + - main + +jobs: + build_and_upload_to_testflight: + name: Build And Upload iOS Application Production To TestFlight + runs-on: macOS-latest + environment: production + timeout-minutes: 30 + env: + TEAM_ID: ${{ secrets.TEAM_ID }} + FASTLANE_USER: ${{ secrets.FASTLANE_USER }} + FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }} + FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }} + FASTLANE_SESSION: ${{ secrets.FASTLANE_SESSION }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + APP_STORE_KEY_ID: ${{ secrets.APP_STORE_KEY_ID }} + APP_STORE_ISSUER_ID: ${{ secrets.APP_STORE_ISSUER_ID }} + APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Install SSH key + uses: webfactory/ssh-agent@v0.7.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Set up Flutter environment + uses: subosito/flutter-action@v2 + with: + channel: 'stable' + flutter-version: '3.10.5' + + - name: Generate new project + run: | + dart pub global activate mason_cli + mason get + mason make template -c mason-config.json + # Move the generated project to the root directory for next steps & cleanup to not affect static code analysis + rsync -av --remove-source-files flutter_templates/ ./ + rm -rf bricks sample + + - name: Get Flutter dependencies + run: flutter pub get + + - name: Set up Production env + env: + ENV: ${{ secrets.ENV }} + run: | + echo -e "$ENV" >> .env + + - name: Run code generator + run: flutter packages pub run build_runner build --delete-conflicting-outputs + + - name: Cache Ruby gems + uses: actions/cache@v3 + id: bunlderCache + with: + path: ios/vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: ${{ runner.os }}-gems- + + - name: Cache Pods + uses: actions/cache@v3 + id: cocoapodCache + with: + path: ios/Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: ${{ runner.os }}-pods- + + - name: Bundle install + run: cd ./ios && bundle install + + - name: Pod install + run: cd ./ios && pod install + + - name: Update fastlane + run: cd ./ios && bundle update fastlane + + - name: Update plugins + run: cd ./ios && bundle exec fastlane update_plugins + + - name: Match AppStore + run: cd ./ios && bundle exec fastlane sync_appstore_production_signing + env: + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER + + - name: Deploy to TestFlight + run: | + cd ./ios && bundle exec fastlane build_and_upload_testflight_production_app diff --git a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_production.yml b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_production.yml index 1cb8daa7..f73c2c71 100644 --- a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_production.yml +++ b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_production.yml @@ -37,7 +37,7 @@ jobs: env: ENV: ${{#mustacheCase}}secrets.ENV{{/mustacheCase}} run: | - echo "$ENV" > .env + echo -e "$ENV" > .env # App Bundle requires Firebase connected to Play Store to upload https://appdistribution.page.link/KPoa - name: Build Android apk diff --git a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_production_to_playstore.yml b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_production_to_playstore.yml index 5b9d4190..fa85666b 100644 --- a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_production_to_playstore.yml +++ b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_production_to_playstore.yml @@ -37,7 +37,7 @@ jobs: env: ENV: ${{#mustacheCase}}secrets.ENV{{/mustacheCase}} run: | - echo "$ENV" > .env + echo -e "$ENV" > .env - name: Set up release signing configs env: diff --git a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_staging.yml b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_staging.yml index d318a132..175eaee1 100644 --- a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_staging.yml +++ b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/android_deploy_staging.yml @@ -37,7 +37,7 @@ jobs: env: ENV: ${{#mustacheCase}}secrets.ENV{{/mustacheCase}} run: | - echo "$ENV" > .env.staging + echo -e "$ENV" > .env.staging # App Bundle requires Firebase connected to Play Store to upload https://appdistribution.page.link/KPoa - name: Build Android apk diff --git a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_staging_to_firebase.yml b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_staging_to_firebase.yml index 4a232a86..fd5e6b08 100644 --- a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_staging_to_firebase.yml +++ b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_staging_to_firebase.yml @@ -44,7 +44,7 @@ jobs: env: ENV: ${{#mustacheCase}}secrets.ENV{{/mustacheCase}} run: | - echo "$ENV" > .env.staging + echo -e "$ENV" > .env.staging - name: Run code generator run: flutter packages pub run build_runner build --delete-conflicting-outputs diff --git a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_to_app_store.yml b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_to_app_store.yml index ffc30f95..73329426 100644 --- a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_to_app_store.yml +++ b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_to_app_store.yml @@ -1,15 +1,15 @@ -name: ios-deploy-to-app-store +name: ios-deploy-production-to-app-store on: # Trigger the workflow on push action push: branches: - - develop + - main jobs: build_and_upload_to_app_store: - name: Build And Upload iOS Application To AppStore + name: Build And Upload iOS Application Production To AppStore runs-on: macOS-latest - environment: staging + environment: production timeout-minutes: 30 env: TEAM_ID: ${{#mustacheCase}}secrets.TEAM_ID{{/mustacheCase}} @@ -19,37 +19,70 @@ jobs: FASTLANE_SESSION: ${{#mustacheCase}}secrets.FASTLANE_SESSION{{/mustacheCase}} MATCH_PASSWORD: ${{#mustacheCase}}secrets.MATCH_PASSWORD{{/mustacheCase}} KEYCHAIN_PASSWORD: ${{#mustacheCase}}secrets.KEYCHAIN_PASSWORD{{/mustacheCase}} - GITHUB_RUN_NUMBER: $secrets.GITHUB_RUN_NUMBER + APP_STORE_KEY_ID: ${{#mustacheCase}}secrets.APP_STORE_KEY_ID{{/mustacheCase}} + APP_STORE_ISSUER_ID: ${{#mustacheCase}}secrets.APP_STORE_ISSUER_ID{{/mustacheCase}} + APP_STORE_CONNECT_API_KEY_BASE64: ${{#mustacheCase}}secrets.APP_STORE_CONNECT_API_KEY_BASE64{{/mustacheCase}} + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER steps: - - name: Check out - uses: actions/checkout@v3 + - name: Check out + uses: actions/checkout@v3 - - name: Install SSH key - uses: webfactory/ssh-agent@v0.4.1 - with: - ssh-private-key: ${{#mustacheCase}}secrets.SSH_PRIVATE_KEY{{/mustacheCase}} + - name: Install SSH key + uses: webfactory/ssh-agent@v0.7.0 + with: + ssh-private-key: ${{#mustacheCase}}secrets.SSH_PRIVATE_KEY{{/mustacheCase}} - - name: Set up Flutter environment - uses: subosito/flutter-action@v2 - with: - channel: 'stable' - flutter-version: '3.10.5' + - name: Set up Flutter environment + uses: subosito/flutter-action@v2 + with: + channel: 'stable' + flutter-version: '3.10.5' - - name: Get Flutter dependencies - run: flutter pub get + - name: Get Flutter dependencies + run: flutter pub get - - name: Run code generator - run: flutter packages pub run build_runner build --delete-conflicting-outputs + - name: Set up Production env + env: + ENV: ${{#mustacheCase}}secrets.ENV{{/mustacheCase}} + run: | + echo -e "$ENV" >> .env - - name: Bundle install - run: cd ./ios && bundle install + - name: Run code generator + run: flutter packages pub run build_runner build --delete-conflicting-outputs - - name: Pod install - run: cd ./ios && pod install + - name: Cache Ruby gems + uses: actions/cache@v3 + id: bunlderCache + with: + path: ios/vendor/bundle + key: ${{#mustacheCase}}runner.os{{/mustacheCase}}-gems-${{#mustacheCase}}hashFiles('**/Gemfile.lock'){{/mustacheCase}} + restore-keys: ${{#mustacheCase}}runner.os{{/mustacheCase}}-gems- - - name: Match AppStore - run: cd ./ios && bundle exec fastlane sync_appstore_staging_signing + - name: Cache Pods + uses: actions/cache@v3 + id: cocoapodCache + with: + path: ios/Pods + key: ${{#mustacheCase}}runner.os{{/mustacheCase}}-pods-${{#mustacheCase}}hashFiles('**/Podfile.lock'){{/mustacheCase}} + restore-keys: ${{#mustacheCase}}runner.os{{/mustacheCase}}-pods- - - name: Deploy to AppStore - run: | - cd ./ios && bundle exec fastlane build_and_upload_app_store_connect_app + - name: Bundle install + run: cd ./ios && bundle install + + - name: Pod install + run: cd ./ios && pod install + + - name: Update fastlane + run: cd ./ios && bundle update fastlane + + - name: Update plugins + run: cd ./ios && bundle exec fastlane update_plugins + + - name: Match AppStore + run: cd ./ios && bundle exec fastlane sync_appstore_production_signing + env: + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER + + - name: Deploy to AppStore + run: | + cd ./ios && bundle exec fastlane build_and_upload_production_app_store_connect_app diff --git a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_to_testflight.yml b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_to_testflight.yml index 2734e4bd..3b9a98ba 100644 --- a/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_to_testflight.yml +++ b/bricks/template/__brick__/{{project_name.snakeCase()}}/.github/workflows/ios_deploy_to_testflight.yml @@ -1,15 +1,15 @@ -name: ios-deploy-to-testflight +name: ios-deploy-production-to-testflight on: # Trigger the workflow on push action push: branches: - - develop + - main jobs: build_and_upload_to_testflight: - name: Build And Upload iOS Application To TestFlight + name: Build And Upload iOS Application Production To TestFlight runs-on: macOS-latest - environment: staging + environment: production timeout-minutes: 30 env: TEAM_ID: ${{#mustacheCase}}secrets.TEAM_ID{{/mustacheCase}} @@ -19,37 +19,70 @@ jobs: FASTLANE_SESSION: ${{#mustacheCase}}secrets.FASTLANE_SESSION{{/mustacheCase}} MATCH_PASSWORD: ${{#mustacheCase}}secrets.MATCH_PASSWORD{{/mustacheCase}} KEYCHAIN_PASSWORD: ${{#mustacheCase}}secrets.KEYCHAIN_PASSWORD{{/mustacheCase}} - GITHUB_RUN_NUMBER: $secrets.GITHUB_RUN_NUMBER + APP_STORE_KEY_ID: ${{#mustacheCase}}secrets.APP_STORE_KEY_ID{{/mustacheCase}} + APP_STORE_ISSUER_ID: ${{#mustacheCase}}secrets.APP_STORE_ISSUER_ID{{/mustacheCase}} + APP_STORE_CONNECT_API_KEY_BASE64: ${{#mustacheCase}}secrets.APP_STORE_CONNECT_API_KEY_BASE64{{/mustacheCase}} + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER steps: - - name: Check out - uses: actions/checkout@v3 + - name: Check out + uses: actions/checkout@v3 - - name: Install SSH key - uses: webfactory/ssh-agent@v0.4.1 - with: - ssh-private-key: ${{#mustacheCase}}secrets.SSH_PRIVATE_KEY{{/mustacheCase}} + - name: Install SSH key + uses: webfactory/ssh-agent@v0.7.0 + with: + ssh-private-key: ${{#mustacheCase}}secrets.SSH_PRIVATE_KEY{{/mustacheCase}} - - name: Set up Flutter environment - uses: subosito/flutter-action@v2 - with: - channel: 'stable' - flutter-version: '3.10.5' + - name: Set up Flutter environment + uses: subosito/flutter-action@v2 + with: + channel: 'stable' + flutter-version: '3.10.5' - - name: Get Flutter dependencies - run: flutter pub get + - name: Get Flutter dependencies + run: flutter pub get - - name: Run code generator - run: flutter packages pub run build_runner build --delete-conflicting-outputs + - name: Set up Production env + env: + ENV: ${{#mustacheCase}}secrets.ENV{{/mustacheCase}} + run: | + echo -e "$ENV" >> .env - - name: Bundle install - run: cd ./ios && bundle install + - name: Run code generator + run: flutter packages pub run build_runner build --delete-conflicting-outputs - - name: Pod install - run: cd ./ios && pod install + - name: Cache Ruby gems + uses: actions/cache@v3 + id: bunlderCache + with: + path: ios/vendor/bundle + key: ${{#mustacheCase}}runner.os{{/mustacheCase}}-gems-${{#mustacheCase}}hashFiles('**/Gemfile.lock'){{/mustacheCase}} + restore-keys: ${{#mustacheCase}}runner.os{{/mustacheCase}}-gems- - - name: Match AppStore - run: cd ./ios && bundle exec fastlane sync_appstore_staging_signing + - name: Cache Pods + uses: actions/cache@v3 + id: cocoapodCache + with: + path: ios/Pods + key: ${{#mustacheCase}}runner.os{{/mustacheCase}}-pods-${{#mustacheCase}}hashFiles('**/Podfile.lock'){{/mustacheCase}} + restore-keys: ${{#mustacheCase}}runner.os{{/mustacheCase}}-pods- - - name: Deploy to TestFlight - run: | - cd ./ios && bundle exec fastlane build_and_upload_testflight_app + - name: Bundle install + run: cd ./ios && bundle install + + - name: Pod install + run: cd ./ios && pod install + + - name: Update fastlane + run: cd ./ios && bundle update fastlane + + - name: Update plugins + run: cd ./ios && bundle exec fastlane update_plugins + + - name: Match AppStore + run: cd ./ios && bundle exec fastlane sync_appstore_production_signing + env: + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER + + - name: Deploy to TestFlight + run: | + cd ./ios && bundle exec fastlane build_and_upload_testflight_production_app diff --git a/bricks/template/__brick__/{{project_name.snakeCase()}}/ios/fastlane/Constants/Environments.rb b/bricks/template/__brick__/{{project_name.snakeCase()}}/ios/fastlane/Constants/Environments.rb index 49c68679..2900ccd5 100644 --- a/bricks/template/__brick__/{{project_name.snakeCase()}}/ios/fastlane/Constants/Environments.rb +++ b/bricks/template/__brick__/{{project_name.snakeCase()}}/ios/fastlane/Constants/Environments.rb @@ -15,6 +15,18 @@ def self.TEAM_ID ENV['TEAM_ID'] end + def self.APP_STORE_KEY_ID + ENV['APP_STORE_KEY_ID'] + end + + def self.APP_STORE_ISSUER_ID + ENV['APP_STORE_ISSUER_ID'] + end + + def self.APP_STORE_CONNECT_API_KEY_BASE64 + ENV['APP_STORE_CONNECT_API_KEY_BASE64'] + end + ################# ### Firebase ### ################# diff --git a/bricks/template/__brick__/{{project_name.snakeCase()}}/ios/fastlane/Fastfile b/bricks/template/__brick__/{{project_name.snakeCase()}}/ios/fastlane/Fastfile index 4d0c62ab..71bf3415 100644 --- a/bricks/template/__brick__/{{project_name.snakeCase()}}/ios/fastlane/Fastfile +++ b/bricks/template/__brick__/{{project_name.snakeCase()}}/ios/fastlane/Fastfile @@ -43,6 +43,11 @@ platform :ios do match_manager.sync_adhoc_signing(app_identifier: [Constants.BUNDLE_ID_STAGING]) end + desc 'Sync AppStore Production match signing' + lane :sync_appstore_production_signing do + match_manager.sync_app_store_signing(app_identifier: [Constants.BUNDLE_ID_PRODUCTION]) + end + desc 'Register new devices' lane :register_new_device do device_name = prompt(text: 'Enter the device name: ') @@ -76,6 +81,28 @@ platform :ios do ) end + desc 'Build and upload Production app to Test Flight' + lane :build_and_upload_testflight_production_app do + set_app_version + bump_build + builder.build_app_store( + Constants.SCHEME_NAME_PRODUCTION, + Constants.PRODUCT_NAME_PRODUCTION, + Constants.BUNDLE_ID_PRODUCTION, + false + ) + set_app_store_connect_api_key + upload_production_build_to_testflight + end + + desc 'Upload Production build to Test Flight' + private_lane :upload_production_build_to_testflight do + distribution_manager.upload_to_testflight( + product_name: Constants.PRODUCT_NAME_PRODUCTION, + bundle_identifier: Constants.BUNDLE_ID_PRODUCTION, + ) + end + # AppStore desc 'Build and upload Staging app to App Store Connect' @@ -99,6 +126,28 @@ platform :ios do ) end + desc 'Build and upload Production app to App Store Connect' + lane :build_and_upload_production_app_store_connect_app do + set_app_version + bump_build + builder.build_app_store( + Constants.SCHEME_NAME_PRODUCTION, + Constants.PRODUCT_NAME_PRODUCTION, + Constants.BUNDLE_ID_PRODUCTION, + false + ) + set_app_store_connect_api_key + upload_build_to_production_app_store_connect + end + + desc 'upload production build to App Store Connect' + private_lane :upload_build_to_production_app_store_connect do + distribution_manager.upload_to_app_store_connect( + product_name: Constants.PRODUCT_NAME_PRODUCTION, + bundle_identifier: Constants.BUNDLE_ID_PRODUCTION + ) + end + # Firebase desc 'Build and upload Staging app to Firebase' lane :build_and_upload_staging_app do @@ -126,6 +175,16 @@ platform :ios do ) end + desc 'Set App Store Connect API key' + lane :set_app_store_connect_api_key do + app_store_connect_api_key( + key_id: Environments.APP_STORE_KEY_ID, + issuer_id: Environments.APP_STORE_ISSUER_ID, + key_content: Environments.APP_STORE_CONNECT_API_KEY_BASE64, + is_key_content_base64: true + ) + end + # Private helper lanes desc 'check if any specific version number in build environment' diff --git a/sample/.github/workflows/android_deploy_production.yml b/sample/.github/workflows/android_deploy_production.yml index 0fe0d6b9..c05c3fa0 100644 --- a/sample/.github/workflows/android_deploy_production.yml +++ b/sample/.github/workflows/android_deploy_production.yml @@ -37,7 +37,7 @@ jobs: env: ENV: ${{ secrets.ENV }} run: | - echo "$ENV" > .env + echo -e "$ENV" > .env # App Bundle requires Firebase connected to Play Store to upload https://appdistribution.page.link/KPoa - name: Build Android apk diff --git a/sample/.github/workflows/android_deploy_production_to_playstore.yml b/sample/.github/workflows/android_deploy_production_to_playstore.yml index 0a18534e..3725357b 100644 --- a/sample/.github/workflows/android_deploy_production_to_playstore.yml +++ b/sample/.github/workflows/android_deploy_production_to_playstore.yml @@ -37,7 +37,7 @@ jobs: env: ENV: ${{ secrets.ENV }} run: | - echo "$ENV" > .env + echo -e "$ENV" > .env - name: Set up release signing configs env: diff --git a/sample/.github/workflows/android_deploy_staging.yml b/sample/.github/workflows/android_deploy_staging.yml index 351f3792..c4c64aea 100644 --- a/sample/.github/workflows/android_deploy_staging.yml +++ b/sample/.github/workflows/android_deploy_staging.yml @@ -37,7 +37,7 @@ jobs: env: ENV: ${{ secrets.ENV }} run: | - echo "$ENV" > .env.staging + echo -e "$ENV" > .env.staging # App Bundle requires Firebase connected to Play Store to upload https://appdistribution.page.link/KPoa - name: Build Android apk diff --git a/sample/.github/workflows/ios_deploy_staging_to_firebase.yml b/sample/.github/workflows/ios_deploy_staging_to_firebase.yml index 3bc27e76..9fbc3f57 100644 --- a/sample/.github/workflows/ios_deploy_staging_to_firebase.yml +++ b/sample/.github/workflows/ios_deploy_staging_to_firebase.yml @@ -44,7 +44,7 @@ jobs: env: ENV: ${{ secrets.ENV }} run: | - echo "$ENV" > .env.staging + echo -e "$ENV" > .env.staging - name: Run code generator run: flutter packages pub run build_runner build --delete-conflicting-outputs diff --git a/sample/.github/workflows/ios_deploy_to_app_store.yml b/sample/.github/workflows/ios_deploy_to_app_store.yml index 7ceb4d03..62eec025 100644 --- a/sample/.github/workflows/ios_deploy_to_app_store.yml +++ b/sample/.github/workflows/ios_deploy_to_app_store.yml @@ -1,15 +1,15 @@ -name: ios-deploy-to-app-store +name: ios-deploy-production-to-app-store on: # Trigger the workflow on push action push: branches: - - develop + - main jobs: build_and_upload_to_app_store: - name: Build And Upload iOS Application To AppStore + name: Build And Upload iOS Application Production To AppStore runs-on: macOS-latest - environment: staging + environment: production timeout-minutes: 30 env: TEAM_ID: ${{ secrets.TEAM_ID }} @@ -19,37 +19,70 @@ jobs: FASTLANE_SESSION: ${{ secrets.FASTLANE_SESSION }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} - GITHUB_RUN_NUMBER: $secrets.GITHUB_RUN_NUMBER + APP_STORE_KEY_ID: ${{ secrets.APP_STORE_KEY_ID }} + APP_STORE_ISSUER_ID: ${{ secrets.APP_STORE_ISSUER_ID }} + APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER steps: - - name: Check out - uses: actions/checkout@v3 + - name: Check out + uses: actions/checkout@v3 - - name: Install SSH key - uses: webfactory/ssh-agent@v0.4.1 - with: - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + - name: Install SSH key + uses: webfactory/ssh-agent@v0.7.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - - name: Set up Flutter environment - uses: subosito/flutter-action@v2 - with: - channel: 'stable' - flutter-version: '3.10.5' + - name: Set up Flutter environment + uses: subosito/flutter-action@v2 + with: + channel: 'stable' + flutter-version: '3.10.5' - - name: Get Flutter dependencies - run: flutter pub get + - name: Get Flutter dependencies + run: flutter pub get - - name: Run code generator - run: flutter packages pub run build_runner build --delete-conflicting-outputs + - name: Set up Production env + env: + ENV: ${{ secrets.ENV }} + run: | + echo -e "$ENV" >> .env - - name: Bundle install - run: cd ./ios && bundle install + - name: Run code generator + run: flutter packages pub run build_runner build --delete-conflicting-outputs - - name: Pod install - run: cd ./ios && pod install + - name: Cache Ruby gems + uses: actions/cache@v3 + id: bunlderCache + with: + path: ios/vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: ${{ runner.os }}-gems- - - name: Match AppStore - run: cd ./ios && bundle exec fastlane sync_appstore_staging_signing + - name: Cache Pods + uses: actions/cache@v3 + id: cocoapodCache + with: + path: ios/Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: ${{ runner.os }}-pods- - - name: Deploy to AppStore - run: | - cd ./ios && bundle exec fastlane build_and_upload_app_store_connect_app + - name: Bundle install + run: cd ./ios && bundle install + + - name: Pod install + run: cd ./ios && pod install + + - name: Update fastlane + run: cd ./ios && bundle update fastlane + + - name: Update plugins + run: cd ./ios && bundle exec fastlane update_plugins + + - name: Match AppStore + run: cd ./ios && bundle exec fastlane sync_appstore_production_signing + env: + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER + + - name: Deploy to AppStore + run: | + cd ./ios && bundle exec fastlane build_and_upload_production_app_store_connect_app diff --git a/sample/.github/workflows/ios_deploy_to_testflight.yml b/sample/.github/workflows/ios_deploy_to_testflight.yml index 6b25d87a..f0a7fdf8 100644 --- a/sample/.github/workflows/ios_deploy_to_testflight.yml +++ b/sample/.github/workflows/ios_deploy_to_testflight.yml @@ -1,15 +1,15 @@ -name: ios-deploy-to-testflight +name: ios-deploy-production-to-testflight on: # Trigger the workflow on push action push: branches: - - develop + - main jobs: build_and_upload_to_testflight: - name: Build And Upload iOS Application To TestFlight + name: Build And Upload iOS Application Production To TestFlight runs-on: macOS-latest - environment: staging + environment: production timeout-minutes: 30 env: TEAM_ID: ${{ secrets.TEAM_ID }} @@ -19,37 +19,70 @@ jobs: FASTLANE_SESSION: ${{ secrets.FASTLANE_SESSION }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} - GITHUB_RUN_NUMBER: $secrets.GITHUB_RUN_NUMBER + APP_STORE_KEY_ID: ${{ secrets.APP_STORE_KEY_ID }} + APP_STORE_ISSUER_ID: ${{ secrets.APP_STORE_ISSUER_ID }} + APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER steps: - - name: Check out - uses: actions/checkout@v3 + - name: Check out + uses: actions/checkout@v3 - - name: Install SSH key - uses: webfactory/ssh-agent@v0.4.1 - with: - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + - name: Install SSH key + uses: webfactory/ssh-agent@v0.7.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - - name: Set up Flutter environment - uses: subosito/flutter-action@v2 - with: - channel: 'stable' - flutter-version: '3.10.5' + - name: Set up Flutter environment + uses: subosito/flutter-action@v2 + with: + channel: 'stable' + flutter-version: '3.10.5' - - name: Get Flutter dependencies - run: flutter pub get + - name: Get Flutter dependencies + run: flutter pub get - - name: Run code generator - run: flutter packages pub run build_runner build --delete-conflicting-outputs + - name: Set up Production env + env: + ENV: ${{ secrets.ENV }} + run: | + echo -e "$ENV" >> .env - - name: Bundle install - run: cd ./ios && bundle install + - name: Run code generator + run: flutter packages pub run build_runner build --delete-conflicting-outputs - - name: Pod install - run: cd ./ios && pod install + - name: Cache Ruby gems + uses: actions/cache@v3 + id: bunlderCache + with: + path: ios/vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: ${{ runner.os }}-gems- - - name: Match AppStore - run: cd ./ios && bundle exec fastlane sync_appstore_staging_signing + - name: Cache Pods + uses: actions/cache@v3 + id: cocoapodCache + with: + path: ios/Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: ${{ runner.os }}-pods- - - name: Deploy to TestFlight - run: | - cd ./ios && bundle exec fastlane build_and_upload_testflight_app + - name: Bundle install + run: cd ./ios && bundle install + + - name: Pod install + run: cd ./ios && pod install + + - name: Update fastlane + run: cd ./ios && bundle update fastlane + + - name: Update plugins + run: cd ./ios && bundle exec fastlane update_plugins + + - name: Match AppStore + run: cd ./ios && bundle exec fastlane sync_appstore_production_signing + env: + GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER + + - name: Deploy to TestFlight + run: | + cd ./ios && bundle exec fastlane build_and_upload_testflight_production_app diff --git a/sample/ios/fastlane/Constants/Environments.rb b/sample/ios/fastlane/Constants/Environments.rb index 49c68679..2900ccd5 100644 --- a/sample/ios/fastlane/Constants/Environments.rb +++ b/sample/ios/fastlane/Constants/Environments.rb @@ -15,6 +15,18 @@ def self.TEAM_ID ENV['TEAM_ID'] end + def self.APP_STORE_KEY_ID + ENV['APP_STORE_KEY_ID'] + end + + def self.APP_STORE_ISSUER_ID + ENV['APP_STORE_ISSUER_ID'] + end + + def self.APP_STORE_CONNECT_API_KEY_BASE64 + ENV['APP_STORE_CONNECT_API_KEY_BASE64'] + end + ################# ### Firebase ### ################# diff --git a/sample/ios/fastlane/Fastfile b/sample/ios/fastlane/Fastfile index 4d0c62ab..71bf3415 100644 --- a/sample/ios/fastlane/Fastfile +++ b/sample/ios/fastlane/Fastfile @@ -43,6 +43,11 @@ platform :ios do match_manager.sync_adhoc_signing(app_identifier: [Constants.BUNDLE_ID_STAGING]) end + desc 'Sync AppStore Production match signing' + lane :sync_appstore_production_signing do + match_manager.sync_app_store_signing(app_identifier: [Constants.BUNDLE_ID_PRODUCTION]) + end + desc 'Register new devices' lane :register_new_device do device_name = prompt(text: 'Enter the device name: ') @@ -76,6 +81,28 @@ platform :ios do ) end + desc 'Build and upload Production app to Test Flight' + lane :build_and_upload_testflight_production_app do + set_app_version + bump_build + builder.build_app_store( + Constants.SCHEME_NAME_PRODUCTION, + Constants.PRODUCT_NAME_PRODUCTION, + Constants.BUNDLE_ID_PRODUCTION, + false + ) + set_app_store_connect_api_key + upload_production_build_to_testflight + end + + desc 'Upload Production build to Test Flight' + private_lane :upload_production_build_to_testflight do + distribution_manager.upload_to_testflight( + product_name: Constants.PRODUCT_NAME_PRODUCTION, + bundle_identifier: Constants.BUNDLE_ID_PRODUCTION, + ) + end + # AppStore desc 'Build and upload Staging app to App Store Connect' @@ -99,6 +126,28 @@ platform :ios do ) end + desc 'Build and upload Production app to App Store Connect' + lane :build_and_upload_production_app_store_connect_app do + set_app_version + bump_build + builder.build_app_store( + Constants.SCHEME_NAME_PRODUCTION, + Constants.PRODUCT_NAME_PRODUCTION, + Constants.BUNDLE_ID_PRODUCTION, + false + ) + set_app_store_connect_api_key + upload_build_to_production_app_store_connect + end + + desc 'upload production build to App Store Connect' + private_lane :upload_build_to_production_app_store_connect do + distribution_manager.upload_to_app_store_connect( + product_name: Constants.PRODUCT_NAME_PRODUCTION, + bundle_identifier: Constants.BUNDLE_ID_PRODUCTION + ) + end + # Firebase desc 'Build and upload Staging app to Firebase' lane :build_and_upload_staging_app do @@ -126,6 +175,16 @@ platform :ios do ) end + desc 'Set App Store Connect API key' + lane :set_app_store_connect_api_key do + app_store_connect_api_key( + key_id: Environments.APP_STORE_KEY_ID, + issuer_id: Environments.APP_STORE_ISSUER_ID, + key_content: Environments.APP_STORE_CONNECT_API_KEY_BASE64, + is_key_content_base64: true + ) + end + # Private helper lanes desc 'check if any specific version number in build environment'