Table of contents :
Overview
GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.
Firebase App Distribution makes distributing your apps to trusted testers painless. By getting your apps onto testers' devices quickly, you can get feedback early and often. And if you use Crashlytics in your apps, you’ll automatically get stability metrics for all your builds, so you know when you’re ready to ship.
Overall CI/CD Script
name: SaFi Mobile App Pipeline on: push: paths: - app/** - .github/workflows/safi-mobile-app-ci.yml - .github/workflows/safi-mobile-analyze-test-ci.yml - .github/workflows/safi-mobile-app-build-android-ci.yml - .github/workflows/safi-mobile-app-build-ios-ci.yml - .github/workflows/safi-mobile-app-upload-android-ci.yml - .github/workflows/safi-mobile-app-upload-ios-ci.yml - .github/workflows/safi-mobile-app-manual-trigger-ci.yml #TODO: change with main branch branches: - main tags: - sma-[0-9]+.[0-9]+.[0-9]+\+[0-9]+ # paths-ignore: # - '**/README.md' pull_request: paths: - app/** - .github/workflows/safi-mobile-app-ci.yml - .github/workflows/safi-mobile-analyze-test-ci.yml - .github/workflows/safi-mobile-app-build-android-ci.yml - .github/workflows/safi-mobile-app-build-ios-ci.yml - .github/workflows/safi-mobile-app-upload-android-ci.yml - .github/workflows/safi-mobile-app-upload-ios-ci.yml - .github/workflows/safi-mobile-app-manual-trigger-ci.yml #TODO: change with main branch branches: - main jobs: mobile_versioning: name: mobile versioning needs: - analyze_test_main_app - analyze_test_feature_account - analyze_test_feature_cards - analyze_test_feature_dashboard - analyze_test_feature_loans - analyze_test_feature_login - analyze_test_feature_mobile_data - analyze_test_feature_onboarding - analyze_test_feature_transactions - analyze_test_feature_transactions_hive_example - analyze_test_generic_analytics - analyze_test_generic_app_config - analyze_test_generic_module_common - analyze_test_generic_monitoring - analyze_test_generic_template - analyze_test_generic_ui - analyze_test_library_device_fingeprint_plugin - analyze_test_library_extensions - analyze_test_library_forgerock_plugin - analyze_test_library_injection - analyze_test_library_iqa_plugin - analyze_test_library_liveness_plugin - analyze_test_library_logger - analyze_test_library_performance_monitoring - analyze_test_library_video_kyc - analyze_test_library_vida - analyze_test_feature_subsctiption #TODO: change with main branch if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: token: "${{ secrets.SMA_GITHUB_TOKEN }}" - uses: actions/setup-java@v3 with: distribution: "zulu" java-version: "11" # There is issue on this action, # so we need to hardcode the version to 2.4.0 # https://github.com/subosito/flutter-action/issues/179#issuecomment-1195120616 - uses: subosito/flutter-action@v2.4.0 with: flutter-version: "3.3.0" - name: update patch version working-directory: ./app/app_safi env: SMA_GITHUB_TAG_PREFIX: "sma" run: | releaseNotes="${{ github.event.head_commit.message }}" git fetch --all --tags githubBumpedVersion=$(git tag --sort=creatordate -l "${SMA_GITHUB_TAG_PREFIX}*" | tail -1 | cut -d'-' -f2) echo githubBumpedVersion:$githubBumpedVersion version=".version=\"${githubBumpedVersion}\"" echo version:$version yq -i "${version}" pubspec.yaml echo updated version in pubspec.yaml:$(yq eval '.version' pubspec.yaml) dart pub global activate cider export PATH="$PATH":"$HOME/.pub-cache/bin" cider bump patch --bump-build bumpedVersion="$(yq eval '.version' pubspec.yaml)" regex="^([0-9]{1,}\.[0-9]{1,}\.[0-9]{1,})\+([0-9]{1,})$" if [[ $bumpedVersion =~ $regex ]]; then VERSION=${BASH_REMATCH[1]} BUILD_NUMBER=${BASH_REMATCH[2]} nextTag="${SMA_GITHUB_TAG_PREFIX}-${VERSION}+${BUILD_NUMBER}" if [ $(git tag --list "${tagName}") ]; then echo "ERROR: The tag ${tagName} already exists..." exit 1 fi git config --global user.email 'ropiudin@dkatalis.com' git config --global user.name 'ropiDK' NEXT_COMMIT_MESSAGE="Bump Version to ${VERSION}+${BUILD_NUMBER} : ${releaseNotes}" git add . git commit -m "${NEXT_COMMIT_MESSAGE}" git tag "${nextTag}" git commit --amend -m "${NEXT_COMMIT_MESSAGE}" git push origin ${nextTag} else echo "ERROR: The version in pubspec.yaml doesn't match the pattern X.Y.Z+W"; exit 1; fi ### -- Analyze Test -- ### analyze_test_main_app: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/app_safi ### -- Feature Analyze Test -- ### analyze_test_feature_account: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/account analyze_test_feature_cards: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/cards analyze_test_feature_dashboard: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/dashboard analyze_test_feature_loans: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/loans analyze_test_feature_login: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/login analyze_test_feature_mobile_data: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/mobile_data analyze_test_feature_onboarding: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/onboarding analyze_test_feature_subsctiption: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/subscription analyze_test_feature_transactions: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/transactions analyze_test_feature_transactions_hive_example: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/feature/transactions_hive_example ### -- End of Feature Analyze Test -- ### ### -- Generic Analyze Test -- ### analyze_test_generic_analytics: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/generic/analytics analyze_test_generic_app_config: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/generic/app_config analyze_test_generic_module_common: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/generic/module_common analyze_test_generic_monitoring: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/generic/monitoring analyze_test_generic_template: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/generic/template analyze_test_generic_ui: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/generic/ui ### -- End of Generic Analyze Test -- ### ### -- Library Analyze Test -- ### analyze_test_library_device_fingeprint_plugin: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/device_fingeprint/device_fingeprint_plugin analyze_test_library_extensions: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/extensions analyze_test_library_forgerock_plugin: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/forgerock/forgerock_plugin analyze_test_library_injection: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/injection analyze_test_library_iqa_plugin: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/iqa/iqa_plugin analyze_test_library_liveness_plugin: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/liveness/liveness_plugin analyze_test_library_logger: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/logger analyze_test_library_performance_monitoring: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/performance_monitoring analyze_test_library_vida: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/vida/vida_plugin analyze_test_library_video_kyc: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/library/video_kyc/vkyc_plugin ### -- End of Library Analyze Test -- ### ### -- End of Analyze Test -- ### ## Dev build_ios_dev: name: Build Ios Dev needs: - analyze_test_main_app - analyze_test_feature_account - analyze_test_feature_cards - analyze_test_feature_dashboard - analyze_test_feature_loans - analyze_test_feature_login - analyze_test_feature_mobile_data - analyze_test_feature_onboarding - analyze_test_feature_transactions - analyze_test_feature_transactions_hive_example - analyze_test_generic_analytics - analyze_test_generic_app_config - analyze_test_generic_module_common - analyze_test_generic_monitoring - analyze_test_generic_template - analyze_test_generic_ui - analyze_test_library_device_fingeprint_plugin - analyze_test_library_extensions - analyze_test_library_forgerock_plugin - analyze_test_library_injection - analyze_test_library_iqa_plugin - analyze_test_library_liveness_plugin - analyze_test_library_logger - analyze_test_library_performance_monitoring - analyze_test_library_video_kyc - analyze_test_library_vida - analyze_test_feature_subsctiption if: startsWith(github.ref, 'refs/tags') uses: ./.github/workflows/safi-mobile-app-build-ios-ci.yml with: fastlane-env: dev environment-variable: nonprod p12-file: // base 64 p12-file generated p12-password: Lyra123 //just for example google-cloud-project-id: //google cloud project id firebase-token: // firebase token using firebase login build_apk_dev: name: Build Android Dev needs: - analyze_test_main_app - analyze_test_feature_account - analyze_test_feature_cards - analyze_test_feature_dashboard - analyze_test_feature_loans - analyze_test_feature_login - analyze_test_feature_mobile_data - analyze_test_feature_onboarding - analyze_test_feature_transactions - analyze_test_feature_transactions_hive_example - analyze_test_generic_analytics - analyze_test_generic_app_config - analyze_test_generic_module_common - analyze_test_generic_monitoring - analyze_test_generic_template - analyze_test_generic_ui - analyze_test_library_device_fingeprint_plugin - analyze_test_library_extensions - analyze_test_library_forgerock_plugin - analyze_test_library_injection - analyze_test_library_iqa_plugin - analyze_test_library_liveness_plugin - analyze_test_library_logger - analyze_test_library_performance_monitoring - analyze_test_library_video_kyc - analyze_test_library_vida - analyze_test_feature_subsctiption if: startsWith(github.ref, 'refs/tags') uses: ./.github/workflows/safi-mobile-app-build-android-ci.yml with: environment-variable: nonprod google-cloud-key: //base 64 google cloud key google-cloud-project-id: // project id firebase-token: // firebase token upload_apk_dev: name: Upload Android Dev to Firebase App Distribution needs: [build_apk_dev] uses: ./.github/workflows/safi-mobile-app-upload-android-ci.yml with: app-id: //app id in firebase environment-variable: nonprod firebase-token: // firebase token groups: "Dkatalis, Testers, Vacuumlabs" upload_ipa_dev: name: Upload Ios Dev to TestFlight needs: [build_ios_dev] uses: ./.github/workflows/safi-mobile-app-upload-ios-ci.yml with: key-id: // key id of apple dev issuer-id: // issuer id key-path: "ios.p8" api-key: //api-key environment-variable: nonprod
Mobile Versioning
mobile_versioning: name: mobile versioning needs: [analyze_test_main_app,analyze_test_analytics,analyze_test_dashboard,analyze_test_injection,analyze_test_iqa_plugin,analyze_test_liveness_plugin,analyze_test_login,analyze_test_onboarding,analyze_test_template,analyze_test_ui,analyze_test_video_kyc] #TODO: change with main branch if: github.ref == 'refs/heads/feature/application-setup' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: token: 'YOUR_PERSONAL_TOKEN' - uses: actions/setup-java@v1 with: java-version: 1.8 - uses: subosito/flutter-action@v1 with: flutter-version: '2.10.5' - name: update patch version working-directory: ./app/app_safi run: | dart pub global activate cider export PATH="$PATH":"$HOME/.pub-cache/bin" cider bump patch --bump-build bumpedVersion="$(yq eval '.version' pubspec.yaml)" regex="^([0-9]{1,}.[0-9]{1,}.[0-9]{1,})\+([0-9]{1,})$" if [[ $bumpedVersion =~ $regex ]]; then VERSION=${BASH_REMATCH[1]} BUILD_NUMBER=${BASH_REMATCH[2]} nextTag="${VERSION}+${BUILD_NUMBER}" if [ $(git tag --list "${tagName}") ]; then echo "ERROR: The tag ${tagName} already exists..." exit 1 fi git config --global user.email 'ropiudin@dkatalis.com' git config --global user.name 'ropiDK' NEXT_COMMIT_MESSAGE="Bump Version to ${VERSION}+${BUILD_NUMBER}" git add . git commit -m "${NEXT_COMMIT_MESSAGE}" git tag "${nextTag}" git commit --amend -m "${NEXT_COMMIT_MESSAGE} [skip ci]" git push git push origin ${nextTag} else echo "ERROR: The version in pubspec.yaml doesn't match the pattern X.Y.Z+W"; exit 1; fi
This code to automatically increment patch and build version using cider.
Generate personal access token
To generetate personal acces token, just follow step bellow :
YOUR_PERSONAL_ACCOUNT for token =
Add CI/CD for Analyzer, Unit Test and Code Coverage
CI/CD Code : Reusable analyze and test workflow (safi-mobile-analyze-test-ci.yml)
name: Reusable test and analyze mobile app on: workflow_call: inputs: working-directory: required: true type: string jobs: analyze_test: name: Analyzer and Test runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 with: distribution: "zulu" java-version: "11" # There is issue on this action, # so we need to hardcode the version to 2.4.0 # https://github.com/subosito/flutter-action/issues/179#issuecomment-1195120616 - uses: subosito/flutter-action@v2.4.0 with: flutter-version: "3.3.0" - name: analyze and test working-directory: .${{ inputs.working-directory }} run: | flutter pub get flutter analyze flutter test --coverage flutter pub run build_runner build --delete-conflicting-outputs || true [[ -z "$(git status --porcelain)" ]] || (echo "Please run scripts/tools/pub_all_modules.sh -gbda and commit\n$(git status --porcelain)" && exit 1) - name: Setup sonarqube uses: warchant/setup-sonar-scanner@v3 - name: Run Sonarqube tests working-directory: .${{ inputs.working-directory }} env: SONARQUBE_URL: //sonar url SONARQUBE_TOKEN: //sonar token run: | SONARQUBE_PROJECT=$(yq '.name' pubspec.yaml) SONARQUBE_PROJECT_VERSION=$(yq '.version' pubspec.yaml) SONARQUBE_PROPERTIES_FILE="${GITHUB_WORKSPACE}/app/sonar-project.properties" echo "This is the path: ${SONARQUBE_PROPERTIES_FILE}" sonar-scanner \ -Dsonar.projectKey=${SONARQUBE_PROJECT} \ -Dsonar.projectVersion=${SONARQUBE_PROJECT_VERSION} \ -Dproject.settings=${SONARQUBE_PROPERTIES_FILE} \ -Dsonar.sources=.
we will reuse this code, in main workflow, like this :
analyze_test_main_app: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/app_safi analyze_test_analytics: uses: ./.github/workflows/safi-mobile-analyze-test-ci.yml with: working-directory: /app/generic/analytics ...etc
Setup Github Actions (Android)
In this section, we will setup CI/CD for build APK and publish to Firebase App Distribution.
Add CI/CD for Build APK
Reusable workflow (safi-mobile-app-build-android-ci.yml
)
name: Reusable android build on: workflow_call: inputs: environment-variable: required: true type: string google-cloud-key: required: true type: string google-cloud-project-id: required: true type: string firebase-token: required: true type: string jobs: build_apk: name: Build Flutter (Android) runs-on: ubuntu-latest env: FIREBASE_TOKEN: ${{ inputs.firebase-token }} steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 16 - uses: actions/setup-java@v3 with: distribution: "zulu" java-version: "11" - uses: subosito/flutter-action@v2.4.0 with: flutter-version: "3.3.0" - name: Build working-directory: ./app/app_safi run: | rm -f ${{ github.workspace }}/app/app_safi/lib/env.dart mv ${{ github.workspace }}/app/scripts/tools/env/env_${{ inputs.environment-variable }}.dart ${{ github.workspace }}/app/app_safi/lib/env.dart flutter clean flutter pub get npm install -g firebase-tools dart pub global activate flutterfire_cli APP_BUNDLE="ph.safibank.app.${{ inputs.environment-variable }}" flutterfire configure -y -t "${{env.FIREBASE_TOKEN}}" "--platforms=ios,android" -p "${{ inputs.google-cloud-project-id }}" -a "${APP_BUNDLE}" -i "${APP_BUNDLE}" -m "${APP_BUNDLE}" export environment=${{ inputs.environment-variable }} bumpedVersion="$(yq eval '.version' pubspec.yaml)" regex="^([0-9]{1,}\.[0-9]{1,}\.[0-9]{1,})\+([0-9]{1,})$" if [[ $bumpedVersion =~ $regex ]]; then BUILD_NUMBER=${BASH_REMATCH[2]} fi flutter build apk --release --build-name=$(echo $GITHUB_REF | sed -e "s#refs/tags/##g") --build-number=$BUILD_NUMBER - name: Upload uses: actions/upload-artifact@v3 with: name: apk-build-${{ inputs.environment-variable }} path: ${{ github.workspace }}/app/app_safi/build/app/outputs/apk/release if-no-files-found: error
This job is to build apk, and will upload to artifacts.
Setup Firebase App Distribution
App ID on Firebase App Distribution
First, To integrate Github Actions and Firebase App Distribution you need App ID of your project on firebase, you can find it on your firebase console on setting, see picture below:
After that, you need firebase token, you can run on your terminal :
firebase login:ci
Register Tester on App Distribution
To resgister tester on the app distribution you can goto firebase console > realease and monitor > app distribution, and you can register the tester on it :
after that, you will received email, and click get started to approve the invitation :
Integrate Firebase App Distribution to Github Actions
After we setup our firebase, we will integrate it to Github actions safi-mobile-app-upload-android-ci.yml
:
name: Reusable upload android on: workflow_call: inputs: app-id: required: true type: string environment-variable: required: true type: string firebase-token: required: true type: string groups: required: true type: string jobs: publish_app_distribution: name: Upload Android to Firebase App Distribution runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 with: distribution: "zulu" java-version: "11" - name: Download Artifact uses: actions/download-artifact@master with: name: apk-build-${{ inputs.environment-variable }} - name: Upload APK uses: wzieba/Firebase-Distribution-Github-Action@v1.3.3 with: appId: ${{ inputs.app-id }} token: ${{ inputs.firebase-token }} groups: ${{ inputs.groups }} releaseNotes: ${{ github.event.head_commit.message }} file: app-release.apk
Build IPA for Ios and publish to TestFlight
Setting Fastfile for ios build
Before we continue to build the CI, we need Google Cloud Keys (you can get it from SRE team), copy the gc_keys.json to ios folder on app_safi
, and setting Fastfile like this :
### ### Disclaimer: Fastlane won't work properly until we have apple account ### default_platform(:ios) platform :ios do groupBundleId = "ph.safibank.app" appDisplayName = "SaFi" desc "Create Dev Build" lane :dev do bundleId = groupBundleId + ".nonprod" appDisplayName += " - Dev" build( variant: "dev", appDisplayName: appDisplayName, baseBundleId: bundleId, appProfile: "match AppStore "+ bundleId, exportMethod: "app-store", teamId: "2368TD7QJ5" ) end desc "Create Stage Build" lane :stage do bundleId = groupBundleId + ".stage" appDisplayName += " - Stage" build( variant: "stage", appDisplayName: appDisplayName, baseBundleId: bundleId, appProfile: "match AppStore "+ bundleId, exportMethod: "app-store", teamId: "2368TD7QJ5" ) end desc "Common build commands for generating an iOS build" lane :build do |options| variant = options[:variant] appDisplayName = options[:appDisplayName] baseBundleId = options[:baseBundleId] appProfile = options[:appProfile] exportMethod = options[:exportMethod] teamId = options[:teamId] update_code_signing_settings( path: "Runner.xcodeproj", profile_name: "#{appProfile}", bundle_identifier: "#{baseBundleId}", ) update_app_identifier( app_identifier: "#{baseBundleId}", plist_path: "Runner/Info.plist" ) update_info_plist( app_identifier: "#{baseBundleId}", plist_path: "Runner/Info.plist", display_name: "#{appDisplayName}" ) update_project_team( path: "Runner.xcodeproj/", teamid: "#{teamId}" ) Dir.chdir("../..") do ENV["environment"]="#{variant}" sh "flutter clean;flutter pub get" Dir.chdir("ios") do if "#{variant}" == "prod" # Do Special treatment for prod here end sh "rm -rf ~/Library/Caches/CocoaPods" sh "rm -rf Pods || true" sh "rm -rf ~/Library/Developer/Xcode/DerivedData/*" sh "pod --version" sh "fastlane --version" sh "pod install" sh "echo '--- Print project.pbxproj for debugging'; cat Runner.xcodeproj/project.pbxproj" sh "echo '--- Print Podfile.lock for debugging'; cat Podfile.lock" end end install_certificates( variant: variant, baseBundleId: baseBundleId, teamId: teamId ) gym( export_method: "#{exportMethod}", xcargs: "-allowProvisioningUpdates APP_PROFILE='#{appProfile}' CODE_SIGN_IDENTITY='iPhone Distribution' CODE_SIGN_STYLE='Manual' TARGETED_DEVICE_FAMILY=\"1\"", scheme: 'Runner', output_name: "SaFi.ipa", export_options: { provisioningProfiles: { "#{baseBundleId}": "#{appProfile}", } } ) end desc "Download, install, and push profiles to repo (set 'readonly: false' to sync with AppStoreConnect)" lane :install_certificates do |options| variant = options[:variant] baseBundleId = options[:baseBundleId] teamId = options[:teamId] bucketName = nil gCloudKeyFile = ENV["GOOGLE_CLOUD_KEY_FILE"] gCloudProjectId = ENV["GOOGLE_CLOUD_PROJECT_ID"] appIdentifiers = [ baseBundleId ] if variant == "prod" bucketName = "mobile_ios_certificates" elsif variant == "stage" bucketName = "safi-stage-mobile-ios-certs" else bucketName = "mobile_ios_certificates" end # if is_ci match( type: "appstore", readonly: true, team_id: teamId, # keychain_password: ENV["KEYCHAIN_PASSWORD"], storage_mode: "google_cloud", app_identifier: appIdentifiers, google_cloud_bucket_name: bucketName, google_cloud_keys_file: gCloudKeyFile, google_cloud_project_id: gCloudProjectId ) end desc "Upload binary to TestFlight" lane :upload do iosKeyId = ENV["IOS_KEY_ID"] iosIssuerId = ENV["IOS_ISSUER_ID"] iosApiKey = ENV["IOS_API_KEY_PATH"] apiKeyDetails = app_store_connect_api_key( key_id: "#{iosKeyId}", issuer_id: "#{iosIssuerId}", key_filepath: "#{iosApiKey}" ) changes = changelog_from_git_commits(commits_count: 1, merge_commit_filtering: "exclude_merges") upload_to_testflight( api_key: apiKeyDetails, changelog: changes, skip_submission: true, groups: ["developers"], skip_waiting_for_build_processing: true ) end end
safi-mobile-app-build-ios-ci.yml
:
name: Reusable ios build on: workflow_call: inputs: environment-variable: required: true type: string fastlane-env: required: true type: string p12-file: required: true type: string p12-password: required: true type: string google-cloud-project-id: required: true type: string google-cloud-key: required: true type: string firebase-token: required: true type: string jobs: build_ios: runs-on: macos-latest env: P12_FILE: ${{ inputs.p12-file }} P12_PASSWORD: ${{ inputs.p12-password }} GOOGLE_CLOUD_PROJECT_ID: ${{ inputs.google-cloud-project-id }} GOOGLE_CLOUD_KEY: ${{ inputs.google-cloud-key }} GOOGLE_CLOUD_KEY_FILE: "./gc_keys.json" FIREBASE_TOKEN: ${{ inputs.firebase-token }} steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 16 - uses: actions/setup-java@v3 with: distribution: "zulu" java-version: "11" - uses: subosito/flutter-action@v2.4.0 with: flutter-version: "3.3.0" - name: Import Code-Signing Certificates uses: Apple-Actions/import-codesign-certs@v1 with: p12-file-base64: ${{env.P12_FILE}} p12-password: ${{env.P12_PASSWORD}} - name: Prepare ios build working-directory: ./app/app_safi run: | rm -f ${{ github.workspace }}/app/app_safi/lib/env.dart mv ${{ github.workspace }}/app/scripts/tools/env/env_${{ inputs.environment-variable }}.dart ${{ github.workspace }}/app/app_safi/lib/env.dart rm -f ${{ github.workspace }}/app/app_safi/ios/Runner/GoogleService-Info.plist mv ${{ github.workspace }}/app/scripts/tools/ios/GoogleService-Info-${{ inputs.environment-variable }}.plist ${{ github.workspace }}/app/app_safi/ios/Runner/GoogleService-Info.plist export environment=${{ inputs.environment-variable }} npm install -g firebase-tools dart pub global activate flutterfire_cli APP_BUNDLE="ph.safibank.app.${{ inputs.environment-variable }}" flutterfire configure -y -t "${{env.FIREBASE_TOKEN}}" "--platforms=ios,android" -p "${{ inputs.google-cloud-project-id }}" -a "${APP_BUNDLE}" -i "${APP_BUNDLE}" -m "${APP_BUNDLE}" - name: Set up ruby env uses: ruby/setup-ruby@v1 with: ruby-version: 2.6.8 bundler-cache: false - name: build ios app working-directory: ./app/app_safi/ios run: | bundle install echo "$GOOGLE_CLOUD_KEY" | base64 --decode > gc_keys.json GOOGLE_CLOUD_KEY_FILE=${{env.GOOGLE_CLOUD_KEY_FILE}} GOOGLE_CLOUD_PROJECT_ID=${{env.GOOGLE_CLOUD_PROJECT_ID}} bundle exec fastlane ${{ inputs.fastlane-env }} - name: Upload app-store ipa and dsyms to artifacts uses: actions/upload-artifact@v3 with: name: app-store-${{ inputs.environment-variable }} path: | ${{ github.workspace }}/app/app_safi/ios/SaFi.ipa ${{ github.workspace }}/app/app_safi/ios/*.app.dSYM.zip
safi-mobile-app-upload-ios-ci.yml
:
name: Reusable upload ios on: workflow_call: inputs: key-id: required: true type: string issuer-id: required: true type: string key-path: required: true type: string api-key: required: true type: string environment-variable: required: true type: string jobs: publish_to_testflight: runs-on: macos-latest env: IOS_KEY_ID: ${{ inputs.key-id }} IOS_ISSUER_ID: ${{ inputs.issuer-id }} IOS_API_KEY_PATH: ${{ inputs.key-path }} IOS_API_KEY: ${{ inputs.api-key }} steps: - uses: actions/checkout@v3 - name: Set up ruby env uses: ruby/setup-ruby@v1 with: ruby-version: 2.6.8 bundler-cache: true - name: Download Artifact uses: actions/download-artifact@master with: name: app-store-${{ inputs.environment-variable }} - name: Publish iOS binary run: | mv SaFi.ipa ${{ github.workspace }}/app/app_safi/ios/SaFi.ipa mv *.app.dSYM.zip ${{ github.workspace }}/app/app_safi/ios/*.app.dSYM.zip cd app/app_safi/ios/ echo "$IOS_API_KEY" | base64 --decode > ios.p8 bundle install IOS_KEY_ID=${{env.IOS_KEY_ID}} IOS_ISSUER_ID=${{env.IOS_ISSUER_ID}} IOS_API_KEY_PATH=${{env.IOS_API_KEY_PATH}} bundle exec fastlane upload
Variable name and description
Variable | Description |
---|---|
fastlane-env | environment that we setup in |
environment-variable | environment that we setup in |
p12-file | base64 of p12 file, to generate p12 file, run fastlane {env}, e.g : before you |
p12-password | change password that you want |
google-cloud-project-id | On Firebase console, goto project setting : and you will get the value : |
google-cloud-key | base64 of google cloud key json. |
firebase-token | you can get token by run command : |
keystore-alias | app package name, e.g : |
keystore-file | base64 of kaystore file (jks), follow this instruction : https://docs.flutter.dev/deployment/android#create-an-upload-keystore |
keystore-password | keystore password on keystore file |
keystore-store-password | keystore store password on keystore file |
app-id | |
groups | tester groups in Firebase App Distribution, e.g : |
key-id | key id of Apple Developer |
issuer-id | issuer id of Apple Developer |
key-path | key path file name just hardcoded to ios.p8 |
api-key | base64 of ios.p8 file (download it on Apple Developer console) |
refferences :
https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions
Attachments:
Screen Shot 2022-04-27 at 11.26.02.png (image/png)
Screen Shot 2022-04-27 at 11.31.19.png (image/png)
Screen Shot 2022-04-27 at 11.37.17.png (image/png)
Screen Shot 2022-07-13 at 18.30.45.png (image/png)
Screen Shot 2022-07-13 at 18.29.21.png (image/png)
Screen Shot 2022-07-13 at 18.31.20.png (image/png)
Screen Shot 2022-07-13 at 18.32.39.png (image/png)
Screen Shot 2022-07-13 at 18.30.17.png (image/png)
Screen Shot 2022-11-30 at 14.21.20.png (image/png)
Screen Shot 2022-11-30 at 14.25.12.png (image/png)
Screen Shot 2022-11-30 at 14.31.16.png (image/png)
Screen Shot 2022-11-30 at 14.40.59.png (image/png)
Screen Shot 2022-11-30 at 14.44.42.png (image/png)
Screen Shot 2022-11-30 at 14.43.43.png (image/png)
Screen Shot 2022-11-30 at 14.57.40.png (image/png)
Screen Shot 2022-11-30 at 14.58.33.png (image/png)