From cbb5a6604aeedde7721b8a01aa35b3618e4a8f6a Mon Sep 17 00:00:00 2001 From: richardo2016x Date: Tue, 12 Mar 2024 16:52:05 +0800 Subject: [PATCH] [WIP]build: support github actions. --- .github/workflows/android_alpha.yml | 114 ++++++++++++++++ .github/workflows/ios_alpha.yml | 84 ++++++++++++ .github/workflows/test.yml | 67 ++++++++++ apps/mobile/.gitignore | 5 +- apps/mobile/Gemfile | 3 + apps/mobile/Gemfile.lock | 5 + apps/mobile/android/bundle_sourcemap.sh | 35 +++++ apps/mobile/android/sentry.properties | 5 + apps/mobile/android/upload_sentry_source.sh | 46 ------- apps/mobile/babel.config.js | 2 +- apps/mobile/fastlane/Fastfile | 136 ++++++++++++++++++++ apps/mobile/fastlane/Pluginfile | 6 + apps/mobile/fastlane/README.md | 59 +++++++++ apps/mobile/ios/sentry.properties | 5 + apps/mobile/metro.config.js | 11 +- apps/mobile/package.json | 1 + apps/mobile/scripts/deploy-android.sh | 2 +- apps/mobile/scripts/deploy-ios-adhoc.sh | 2 +- apps/mobile/scripts/fns.sentry.sh | 98 ++++++++++++++ apps/mobile/scripts/fns.sh | 10 +- apps/mobile/src/constant/env.ts | 9 ++ apps/mobile/src/constant/index.ts | 1 + apps/mobile/src/core/sentry.ts | 6 + 23 files changed, 655 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/android_alpha.yml create mode 100644 .github/workflows/ios_alpha.yml create mode 100644 .github/workflows/test.yml create mode 100644 apps/mobile/android/bundle_sourcemap.sh create mode 100644 apps/mobile/android/sentry.properties delete mode 100644 apps/mobile/android/upload_sentry_source.sh create mode 100644 apps/mobile/fastlane/Fastfile create mode 100644 apps/mobile/fastlane/Pluginfile create mode 100644 apps/mobile/fastlane/README.md create mode 100644 apps/mobile/ios/sentry.properties create mode 100644 apps/mobile/scripts/fns.sentry.sh diff --git a/.github/workflows/android_alpha.yml b/.github/workflows/android_alpha.yml new file mode 100644 index 000000000..c0f3fee43 --- /dev/null +++ b/.github/workflows/android_alpha.yml @@ -0,0 +1,114 @@ +name: Build and deploy Android alpha +on: + push: + tags: + - 'android-alpha-*' + branches: + - 'ci/android-alpha-*' + - ci/* + workflow_call: + secrets: + RABBY_MOBILE_ANDROID_KEY_STORE: + required: true + RABBY_MOBILE_ANDROID_KEY_PASSWORD: + required: true + RABBY_MOBILE_ANDROID_KEY_ALIAS: + required: true + RABBY_MOBILE_KR_PWD: + required: true + +# defaults: +# run: +# shell: bash -ieo pipefail {0} +env: + BUILD_TARGET_PLATFORM: android + +jobs: + alpha-build: + name: android-alpha-build + runs-on: + - self-hosted + - mobile + - macOS + steps: + - uses: actions/checkout@v3 + - name: Get Actions Variables + id: actionvars + shell: bash + run: | + echo "{trigger_date}={$(date +'%Y%m%d%H%M%S')}" >> $GITHUB_OUTPUT + flatten_refname=${GITHUB_REF_NAME//\//'_'} + flatten_refname=${GIT_BRANCH//\./'_'} + echo "{flatten_refname}=${flatten_refname}" >> $GITHUB_OUTPUT + + # - name: Setup Nodejs and Yarn + # uses: actions/setup-node@v3 + # with: + # node-version: 18 + + # - name: Setup Ruby & Fastlane + # uses: ruby/setup-ruby@v1 + # with: + # ruby-version: '2.7' + # bundler-cache: true # runs 'bundle install' and caches installed gems automatically + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'zulu' # See 'Supported distributions' for available options + java-version: '17' + + - name: Setup Android SDK + uses: android-actions/setup-android@v2 + + - name: Setup & Install dependencies + run: | + echo "flatten_refname is $flatten_refname"; + echo "trigger_date is $trigger_date"; + yarn --version; + + # yarn setup && yarn postinstall; + yarn install; + cd apps/mobile; + ls -la ./; + bundle install; + env: + flatten_refname: ${{ steps.actionvars.outputs.flatten_refname }} + trigger_date: ${{ steps.actionvars.outputs.trigger_date }} + + # - name: Prepare JSBundle for sourcemap + # run: | + # cd apps/mobile; + # SENTRY_BUNDLE_STAGE=bundle bash ./android/bundle_sourcemap.sh + + - name: Build app + env: + RABBY_MOBILE_BUILD_BUCKET: ${{ secrets.RABBY_MOBILE_BUILD_BUCKET }} + RABBY_MOBILE_KR_PWD: ${{ secrets.RABBY_DESKTOP_KR_PWD }} + RABBY_MOBILE_ANDROID_KEY_STORE: ${{ secrets.RABBY_MOBILE_ANDROID_KEY_STORE }} + RABBY_MOBILE_ANDROID_KEY_PASSWORD: ${{ secrets.RABBY_MOBILE_ANDROID_KEY_PASSWORD }} + RABBY_MOBILE_ANDROID_KEY_ALIAS: ${{ secrets.RABBY_MOBILE_ANDROID_KEY_ALIAS }} + RABBY_MOBILE_SENTRY_AUTH_TOKEN: ${{ secrets.RABBY_MOBILE_SENTRY_AUTH_TOKEN }} + SENTRY_AUTH_TOKEN: ${{ secrets.RABBY_MOBILE_SENTRY_AUTH_TOKEN }} + LARK_CHAT_URL: ${{ secrets.LARK_CHAT_URL }} + LARK_CHAT_SECRET: ${{ secrets.LARK_CHAT_SECRET }} + # see more details on https://docs.github.com/en/actions/learn-github-actions/contexts#github-context + GIT_ACTIONS_JOB_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GIT_COMMIT_URL: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }} + GIT_REF_NAME: ${{ github.ref_name }} + GIT_REF_URL: ${{ github.server_url }}/${{ github.repository }}/tree/${{ github.ref_name }} + GITHUB_REF: ${{ github.ref }} + run: | + cd apps/mobile; + bundle exec fastlane android alpha; + + # - name: Upload app to aws bucket + # run: aws s3 cp ./android/app/build/outputs/apk/release/app-release.apk s3://${RABBY_MOBILE_BUILD_BUCKET}/downloads/debank-app/${APK_NAME}.apk --acl public-read + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: rabbymobile-${{ steps.actionvars.outputs.flatten_refname }}-${{ steps.actionvars.outputs.trigger_date }} + path: | + ./apps/mobile/android/app/build/outputs/apk/release/app-release.apk + retention-days: 90 diff --git a/.github/workflows/ios_alpha.yml b/.github/workflows/ios_alpha.yml new file mode 100644 index 000000000..b72fdd32d --- /dev/null +++ b/.github/workflows/ios_alpha.yml @@ -0,0 +1,84 @@ +name: Build and deploy iOS alpha +on: + push: + tags: + - 'ios-alpha-*' + branches: + - 'ci/ios-alpha-*' + # - ci/* + workflow_dispatch: + workflow_call: + secrets: + MATCH_GIT_PRIVATE_KEY: + required: true + MATCH_PASSWORD: + required: true + NPM_AUTH_TOKEN: + required: true + +defaults: + run: + shell: bash -ieo pipefail {0} + +env: + BUILD_TARGET_PLATFORM: ios + +jobs: + setup: + name: iOS-alpha-build + runs-on: [self-hosted, mobile, macOS] + defaults: + run: + shell: bash -ieo pipefail {0} + steps: + - uses: actions/checkout@v4 + + # - name: Setup Nodejs and Yarn + # uses: actions/setup-node@v3 + # with: + # node-version: 18 + + # - name: Setup Ruby & Fastlane + # uses: ruby/setup-ruby@v1 + # with: + # ruby-version: '2.7' + # bundler-cache: true # runs 'bundle install' and caches installed gems automatically + + - uses: maxim-lobanov/setup-xcode@v1 + id: setup-xcode + with: + # use specific version rather than 'latest-stable' if multiple Xcodes installed + xcode-version: '15.3' + + - name: Install dependencies + run: | + cd ${GITHUB_WORKSPACE}/apps/mobile; + yarn install --frozen-lockfile --check-files + + - name: Install pods + run: | + cd ${GITHUB_WORKSPACE}/apps/mobile/ios; + bundle install && bundle exec pod install; + cd ${GITHUB_WORKSPACE}/apps/mobile; + + # - name: Add github.com to known hosts + # run: sh ./.github/workflows/keyscan.sh + + # - name: Build app + # env: + # MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} + # MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + # CONFIGURATION: release + # TYPE: adhoc + # BUILD_ENV: alpha + # run: | + # cd ${GITHUB_WORKSPACE}/apps/mobile; + # bundle exec fastlane ios alpha + + # - name: copy dest + # run: | + # cp ./ios/Package/dbk.ipa ./ios/outputs/RabbyMobile.ipa + # cp ./ios/Package/manifest.plist ./ios/outputs/manifest.plist + + # - name: Upload app + # run: aws s3 cp ./ios/outputs s3://${BUILD_BUCKET}/downloads/debank-app/ --recursive --acl public-read diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..b36799f69 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,67 @@ +name: Test + +on: + push: + branches: + - dev + - feat* + # - ci/* + +defaults: + run: + shell: bash -ieo pipefail {0} + +jobs: + setup: + name: Build + strategy: + matrix: + host: [macOS] + runs-on: + - self-hosted + - mobile + - ${{ matrix.host }} + env: + NODE_OPTIONS: '--max_old_space_size=4096' + + steps: + - name: Checkout git repo + uses: actions/checkout@v3 + + - name: Env Test + id: env-test + shell: bash + run: | + echo "whoami $(whoami)" + echo "shell is $(echo $0)" + echo "HOME is $HOME" + echo "which node $(which node)" + + - name: Install and build + shell: bash + run: | + npm i -g @debank/cli@latest; + cd apps/mobile; + yarn install; + yarn apply-patch; + yarn prepare-archive; + + security unlock-keychain -p ${{ secrets.KEYCHAIN_PASS }} ~/Library/Keychains/login.keychain-db + + env: + KEYCHAIN_PASS: ${{ secrets.KEYCHAIN_PASS }} + RABBY_MOBILE_BUILD_BUCKET: ${{ secrets.RABBY_MOBILE_BUILD_BUCKET }} + RABBY_MOBILE_KR_PWD: ${{ secrets.RABBY_DESKTOP_KR_PWD }} + RABBY_MOBILE_ANDROID_KEY_STORE: ${{ secrets.RABBY_MOBILE_ANDROID_KEY_STORE }} + RABBY_MOBILE_ANDROID_KEY_PASSWORD: ${{ secrets.RABBY_MOBILE_ANDROID_KEY_PASSWORD }} + RABBY_MOBILE_ANDROID_KEY_ALIAS: ${{ secrets.RABBY_MOBILE_ANDROID_KEY_ALIAS }} + RABBY_MOBILE_SENTRY_AUTH_TOKEN: ${{ secrets.RABBY_MOBILE_SENTRY_AUTH_TOKEN }} + LARK_CHAT_URL: ${{ secrets.LARK_CHAT_URL }} + LARK_CHAT_SECRET: ${{ secrets.LARK_CHAT_SECRET }} + RABBY_REALLY_COPY: ${{ vars.RABBY_REALLY_COPY }} + # see more details on https://docs.github.com/en/actions/learn-github-actions/contexts#github-context + GIT_ACTIONS_JOB_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GIT_COMMIT_URL: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }} + GIT_REF_NAME: ${{ github.ref_name }} + GIT_REF_URL: ${{ github.server_url }}/${{ github.repository }}/tree/${{ github.ref_name }} + GITHUB_REF: ${{ github.ref }} diff --git a/apps/mobile/.gitignore b/apps/mobile/.gitignore index 065965ad0..218baadf5 100644 --- a/apps/mobile/.gitignore +++ b/apps/mobile/.gitignore @@ -25,6 +25,7 @@ ios/.xcode.env.local # Android/IntelliJ # build/ +build4sentry/ .idea .gradle local.properties @@ -84,5 +85,5 @@ scripts/deployments/**/*.aab /android/app/src/main/assets/custom/vconsole.min.js /src/**/vconsole.min.js -android/sentry.properties -ios/sentry.properties +# android/sentry.properties +# ios/sentry.properties diff --git a/apps/mobile/Gemfile b/apps/mobile/Gemfile index 738244026..67986cce0 100644 --- a/apps/mobile/Gemfile +++ b/apps/mobile/Gemfile @@ -6,3 +6,6 @@ ruby ">= 2.6.10" gem 'cocoapods', '~> 1.11', '>= 1.11.2' gem 'activesupport', '>= 6.1.7.3', '< 7.1.0' gem 'fastlane' + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/apps/mobile/Gemfile.lock b/apps/mobile/Gemfile.lock index 3915665f4..db4b37aa9 100644 --- a/apps/mobile/Gemfile.lock +++ b/apps/mobile/Gemfile.lock @@ -156,6 +156,9 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) + fastlane-plugin-sentry (1.20.0) + os (~> 1.1, >= 1.1.4) + fastlane-plugin-versioning_android (0.1.1) ffi (1.16.3) fourflusher (2.3.1) fuzzy_match (2.0.4) @@ -279,6 +282,8 @@ DEPENDENCIES activesupport (>= 6.1.7.3, < 7.1.0) cocoapods (~> 1.11, >= 1.11.2) fastlane + fastlane-plugin-sentry + fastlane-plugin-versioning_android RUBY VERSION ruby 2.6.10p210 diff --git a/apps/mobile/android/bundle_sourcemap.sh b/apps/mobile/android/bundle_sourcemap.sh new file mode 100644 index 000000000..56049d00c --- /dev/null +++ b/apps/mobile/android/bundle_sourcemap.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +set -e + +script_dir="$( cd "$( dirname "$0" )" && pwd )" +android_dir=$script_dir +project_dir=$(dirname $script_dir) + +. $project_dir/scripts/fns.sentry.sh --source-only + +# https://docs.sentry.io/platforms/react-native/manual-setup/hermes/ +# script would be also executed on ../fastlane/ + +sentryfn_setup; +if [[ ! -f $HERMES_BIN ]]; then + echo "[bundle_sourcemap] Hermes compiler not found. Make sure you have hermesc installed correctly." + exit 1 +fi + +if [[ $SENTRY_BUNDLE_STAGE == "bundle" ]]; then + echo "[bundle_sourcemap::bundle] Start to bundle." + + sentryfn_build_sourcemap; +elif [[ $SENTRY_BUNDLE_STAGE == "postbundle" ]]; then + echo "[bundle_sourcemap::postbundle] Start to output & compose sourcemap." + + sentryfn_build_sourcemap; + sentryfn_build_hbc; + sentryfn_compose_sourcemap; +else + echo "[bundle_sourcemap] Unknown SENTRY_BUNDLE_STAGE: $SENTRY_BUNDLE_STAGE" + exit 1 +fi + +echo "[bundle_sourcemap] Done." diff --git a/apps/mobile/android/sentry.properties b/apps/mobile/android/sentry.properties new file mode 100644 index 000000000..252561d76 --- /dev/null +++ b/apps/mobile/android/sentry.properties @@ -0,0 +1,5 @@ +defaults.url=https://sentry.io/ +defaults.org=debank +defaults.project=rabby-mobile +# use environment variable SENTRY_AUTH_TOKEN +# auth.token= diff --git a/apps/mobile/android/upload_sentry_source.sh b/apps/mobile/android/upload_sentry_source.sh deleted file mode 100644 index 0c4141d07..000000000 --- a/apps/mobile/android/upload_sentry_source.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh - -set -e - -script_dir="$( cd "$( dirname "$0" )" && pwd )" -project_dir=$(dirname $script_dir) - -# https://docs.sentry.io/platforms/react-native/manual-setup/hermes/ - -os_name=$(uname -s) - -if [[ "$os_name" = "Darwin" ]]; then - HERMES_OS_BIN="osx-bin" -elif [[ "$os_name" = "Linux" ]]; then - HERMES_OS_BIN="linux64-bin" -else - HERMES_OS_BIN="win64-bin" -fi - -if [[ -f "$project_dir/node_modules/react-native/sdks/hermesc/${HERMES_OS_BIN}/hermesc" ]]; then - # react-native v0.69 or higher (keep only this condition when version is reached) - HERMES_BIN="$project_dir/node_modules/react-native/sdks/hermesc/${HERMES_OS_BIN}/hermesc" -elif [[ -f "$project_dir/node_modules/hermes-engine/${HERMES_OS_BIN}/hermesc" ]]; then - # react-native v0.68 (current) - HERMES_BIN="$project_dir/node_modules/hermes-engine/${HERMES_OS_BIN}/hermesc" -else - echo "Hermes compiler not found." - exit 1; -fi - -JSBUNDLE_NAME="../android/app/src/main/assets/index.android.bundle" - -"${HERMES_BIN}" \ - -O \ - -emit-binary \ - -output-source-map \ - -out="${JSBUNDLE_NAME}.hbc" \ - "${JSBUNDLE_NAME}" - -rm -f "${JSBUNDLE_NAME}" -mv "${JSBUNDLE_NAME}.hbc" "${JSBUNDLE_NAME}" - -node ../node_modules/react-native/scripts/compose-source-maps.js \ - "${JSBUNDLE_NAME}.packager.map" \ - "${JSBUNDLE_NAME}.hbc.map" \ - -o "${JSBUNDLE_NAME}.map" diff --git a/apps/mobile/babel.config.js b/apps/mobile/babel.config.js index 87e2ce6fe..63508180f 100644 --- a/apps/mobile/babel.config.js +++ b/apps/mobile/babel.config.js @@ -22,7 +22,7 @@ module.exports = { { 'process.env.APP_VERSION': version, 'process.env.BUILD_TIME': new Date().toISOString(), - 'process.env.BUILD_ENV': process.env.BUILD_ENV, + 'process.env.BUILD_ENV': process.env.BUILD_ENV || 'development', 'process.env.buildchannel': process.env.buildchannel || 'selfhost-reg', 'process.env.BUILD_GIT_HASH': BUILD_GIT_HASH, }, diff --git a/apps/mobile/fastlane/Fastfile b/apps/mobile/fastlane/Fastfile new file mode 100644 index 000000000..89c6e44b0 --- /dev/null +++ b/apps/mobile/fastlane/Fastfile @@ -0,0 +1,136 @@ +require 'base64' + +platform :ios do + private_lane :prepare_apple_sign do |opts| + # setup_ci + + # enforce configuration + update_code_signing_settings( + use_automatic_signing: false, + sdk: "iphoneos*", + path: './ios/RabbyMobile.xcodeproj', + profile_name: opts[:profile_name], + bundle_identifier: "com.debank.rabby-mobile", + ) + + match( + type: opts[:type], + readonly: true, + shallow_clone: true, + verbose: false, + force_for_new_devices: true, + clone_branch_directly: true) + end + + desc "Release for the iOS alpha" + lane :alpha do + prepare_apple_sign(type: 'adhoc', profile_name: "RabbyMobileAppAdHoc") + gym( + scheme: 'RabbyMobile', + workspace: './ios/RabbyMobile.xcworkspace', + configuration: 'Release', + output_directory: "./ios/Package", + build_path: "./ios/Package", + destination: "generic/platform=iOS", + clean: true, + xcodebuild_formatter: '', + skip_package_pkg: true, + suppress_xcode_output: false, + export_method: 'ad-hoc', + export_options: { + method: 'ad-hoc', + signingStyle: 'manual', + manifest: { + appURL: "https://download.debank.com/downloads/debank-app/RabbyMobile.ipa", + displayImageURL: "https://download.debank.com/downloads/debank-app/debank57.png", + fullSizeImageURL: "https://download.debank.com/downloads/debank-app/debank.png", + } + }) + end + + desc "Release for the iOS production" + lane :release do + prepare_apple_sign(type: 'appstore', profile_name: "RabbyMobileAppStore") + gym( + scheme: 'RabbyMobile', + workspace: './ios/RabbyMobile.xcworkspace', + configuration: 'Release', + output_directory: "./ios/Package", + build_path: "./ios/Package", + destination: "generic/platform=iOS", + skip_profile_detection: true, + clean: true, + skip_package_pkg: true, + export_method: "app-store", + verbose: true, + export_options: { + method: "app-store", + signingStyle: 'manual', + }) + pilot( + apple_id: ENV["PILOT_APPLE_ID"], + username: ENV["PILOT_USERNAME"], + ipa: "./ios/Package/RabbyMobile.ipa", + skip_waiting_for_build_processing: true, + ) + end +end + +platform :android do + private_lane :write_key_store do + # keystore is stored as base64 from environment variable + if !ENV["RABBY_MOBILE_ANDROID_KEY_STORE"].empty? + File.open("../android/app/app-upload-key.keystore", 'w') do |file| + file.write(Base64.decode64(ENV["RABBY_MOBILE_ANDROID_KEY_STORE"])) + end + end + end + + private_lane :build_rabbymobile_app do |opts| + # @see https://github.com/facebook/react-native/issues/35583 + # https://docs.sentry.io/platforms/react-native/manual-setup/hermes/ + # sh "SENTRY_BUNDLE_STAGE=postbundle bash ../android/bundle_sourcemap.sh" + + gradle(tasks: opts[:tasks], project_dir: './android', properties: { + "MYAPP_UPLOAD_STORE_FILE" => "app-upload-key.keystore", + "MYAPP_UPLOAD_STORE_PASSWORD" => ENV['RABBY_MOBILE_ANDROID_KEY_PASSWORD'], + "MYAPP_UPLOAD_KEY_ALIAS" => ENV['RABBY_MOBILE_ANDROID_KEY_ALIAS'], + "MYAPP_UPLOAD_KEY_PASSWORD" => ENV['RABBY_MOBILE_ANDROID_KEY_PASSWORD'] + # if you wanna customize sentry upload, exclude app:bundleReleaseJsAndAssets use js bundle generated by previous step + # }, flags: "-x bundleReleaseJsAndAssets") + }) + + android_version_code = android_get_version_code(gradle_file: "./android/app/build.gradle") + android_version_name = android_get_version_name(gradle_file: "./android/app/build.gradle") + + # sentry_upload_sourcemap( + # auth_token: ENV["RABBY_MOBILE_SENTRY_AUTH_TOKEN"], + # org_slug: 'debank', + # project_slug: 'rabby-mobile', + # version: android_version_name, + # app_identifier: 'com.debank.rabbymobile', + # build: android_version_code, + # dist: android_version_code, + # url_prefix: "app:///", # https://github.com/getsentry/sentry-cli/issues/311 fuck sentry's docs + # sourcemap: [ + # './android/app/build4sentry/generated/assets/index.android.bundle', + # './android/app/build4sentry/generated/assets/index.android.bundle.map' + # ], + # rewrite: true + # ) + end + + desc "Release for the Android alpha" + lane :alpha do + write_key_store + gradle(task: 'clean', project_dir: './android') + build_rabbymobile_app(tasks: ['assembleRelease']) + end + + desc "Release for the Android production" + lane :release do + write_key_store + gradle(task: 'clean', project_dir: './android') + build_rabbymobile_app(tasks: ['assembleRelease', 'bundleRelease']) + end +end diff --git a/apps/mobile/fastlane/Pluginfile b/apps/mobile/fastlane/Pluginfile new file mode 100644 index 000000000..7c4e0c617 --- /dev/null +++ b/apps/mobile/fastlane/Pluginfile @@ -0,0 +1,6 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-versioning_android' +gem 'fastlane-plugin-sentry' diff --git a/apps/mobile/fastlane/README.md b/apps/mobile/fastlane/README.md new file mode 100644 index 000000000..f83488c6d --- /dev/null +++ b/apps/mobile/fastlane/README.md @@ -0,0 +1,59 @@ +## fastlane documentation + +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +```sh +xcode-select --install +``` + +For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) + +# Available Actions + +## iOS + +### ios alpha + +```sh +[bundle exec] fastlane ios alpha +``` + +Release for the iOS alpha + +### ios release + +```sh +[bundle exec] fastlane ios release +``` + +Release for the iOS production + +--- + +## Android + +### android alpha + +```sh +[bundle exec] fastlane android alpha +``` + +Release for the Android alpha + +### android release + +```sh +[bundle exec] fastlane android release +``` + +Release for the Android production + +--- + +This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. + +More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). + +The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/apps/mobile/ios/sentry.properties b/apps/mobile/ios/sentry.properties new file mode 100644 index 000000000..252561d76 --- /dev/null +++ b/apps/mobile/ios/sentry.properties @@ -0,0 +1,5 @@ +defaults.url=https://sentry.io/ +defaults.org=debank +defaults.project=rabby-mobile +# use environment variable SENTRY_AUTH_TOKEN +# auth.token= diff --git a/apps/mobile/metro.config.js b/apps/mobile/metro.config.js index 3adea174f..a9d7455bb 100644 --- a/apps/mobile/metro.config.js +++ b/apps/mobile/metro.config.js @@ -1,6 +1,10 @@ const path = require('path'); const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); +const { + createSentryMetroSerializer, +} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer'); + /** * Metro configuration * https://facebook.github.io/metro/docs/configuration @@ -10,7 +14,12 @@ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); const getAppConfig = function () { const config = getDefaultConfig(__dirname); - const { resolver, transformer } = config; + const { resolver, transformer, serializer } = config; + + config.serializer = { + ...serializer, + customSerializer: createSentryMetroSerializer(), + }; config.transformer = { ...transformer, diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 7d7626a85..6d56d2d2c 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -20,6 +20,7 @@ "syncrnversion:incb": "./node_modules/.bin/react-native-version --never-amend", "syncrnversion": "./node_modules/.bin/react-native-version --never-amend --never-increment-build", "start": "yarn ensure-git-hooks && yarn build:deps && yarn build-inpage && react-native start", + "prepare-archive": "yarn build:deps && yarn build-inpage", "test": "jest", "build-inpage": "sh ./scripts/postinstall.sh", "create-patch": "sh ./scripts/create-patch.sh", diff --git a/apps/mobile/scripts/deploy-android.sh b/apps/mobile/scripts/deploy-android.sh index 88a0d26a2..ba3bff5c0 100755 --- a/apps/mobile/scripts/deploy-android.sh +++ b/apps/mobile/scripts/deploy-android.sh @@ -5,7 +5,7 @@ project_dir=$(dirname $script_dir) . $script_dir/fns.sh --source-only -export targetplatform="android"; +export BUILD_TARGET_PLATFORM="android"; check_s3_params; checkout_s3_pub_deployment_params; diff --git a/apps/mobile/scripts/deploy-ios-adhoc.sh b/apps/mobile/scripts/deploy-ios-adhoc.sh index 35211e36d..a2c513e49 100755 --- a/apps/mobile/scripts/deploy-ios-adhoc.sh +++ b/apps/mobile/scripts/deploy-ios-adhoc.sh @@ -6,7 +6,7 @@ project_dir=$(dirname $script_dir) . $script_dir/fns.sh --source-only export buildchannel="selfhost-reg"; -export targetplatform="ios"; +export BUILD_TARGET_PLATFORM="ios"; check_s3_params; checkout_s3_pub_deployment_params; diff --git a/apps/mobile/scripts/fns.sentry.sh b/apps/mobile/scripts/fns.sentry.sh new file mode 100644 index 000000000..cc85a2350 --- /dev/null +++ b/apps/mobile/scripts/fns.sentry.sh @@ -0,0 +1,98 @@ +RM_OS_NAME=$(uname -s); + +sentryfn_setup() { + if [ -z $project_dir ]; then + echo "project_dir is not set" + exit 1 + fi + + if [[ "$RM_OS_NAME" = "Darwin" ]]; then + export HERMES_OS_BIN="osx-bin" + [ -z $BUILD_TARGET_PLATFORM ] && export BUILD_TARGET_PLATFORM="ios"; + elif [[ "$RM_OS_NAME" = "Linux" ]]; then + export HERMES_OS_BIN="linux64-bin" + [ -z $BUILD_TARGET_PLATFORM ] && export BUILD_TARGET_PLATFORM="android"; + else + export HERMES_OS_BIN="win64-bin" + [ -z $BUILD_TARGET_PLATFORM ] && export BUILD_TARGET_PLATFORM="android"; + fi + + if [[ "$BUILD_TARGET_PLATFORM" == "android" ]]; then + export RMRN_BUNDLE_FILENAME="index.android.bundle" + else + export RMRN_BUNDLE_FILENAME="main.jsbundle" + fi + + if [[ -f "$project_dir/node_modules/hermes-engine/${HERMES_OS_BIN}/hermesc" ]]; then + # react-native v0.68 or lower + export HERMES_BIN="$project_dir/node_modules/hermes-engine/${HERMES_OS_BIN}/hermesc" + else + # react-native v0.69 or higher (keep only this condition when version is reached) + export HERMES_BIN="$project_dir/node_modules/react-native/sdks/hermesc/${HERMES_OS_BIN}/hermesc" + fi + + # the default bundle output directory + export RMRN_BUNDLE_DIR="$project_dir/$BUILD_TARGET_PLATFORM/app/build4sentry/generated" + # You can change it by parameter of `react-native bundle --bundle-output`, but make sure it's parent directory exists + export RMRN_JSBUNDLE_NAME="$RMRN_BUNDLE_DIR/assets/$RMRN_BUNDLE_FILENAME" + export RMRN_OJSBUNDLE_NAME="$RMRN_BUNDLE_DIR/asset-pieces/$RMRN_BUNDLE_FILENAME" + # export RMRN_JSBUNDLE_NAME=$RMRN_BUNDLE_FILENAME + + dirs=("$RMRN_JSBUNDLE_NAME" "$RMRN_OJSBUNDLE_NAME") + for filename in "${dirs[@]}"; do + dir=$(dirname $filename) + rm -rf $dir; + mkdir -p $dir; + done + + # list ALL important variables + echo "HERMES_OS_BIN: $HERMES_OS_BIN" + echo "HERMES_BIN: $HERMES_BIN" + echo "RMRN_BUNDLE_DIR: $RMRN_BUNDLE_DIR" + echo "RMRN_JSBUNDLE_NAME: $RMRN_JSBUNDLE_NAME" + echo "" +} + +sentryfn_build_sourcemap() { + echo "[fns_sentry] Building sourcemap..." + + mkdir -p $RMRN_BUNDLE_DIR; + + $project_dir/node_modules/.bin/react-native bundle \ + --platform $BUILD_TARGET_PLATFORM \ + --reset-cache \ + --dev false \ + --minify false \ + --entry-file index.js \ + --bundle-output ${RMRN_JSBUNDLE_NAME} \ + --assets-dest ${RMRN_BUNDLE_DIR}/res \ + --sourcemap-output ${RMRN_JSBUNDLE_NAME}.packager.map + + cp ${RMRN_JSBUNDLE_NAME} ${RMRN_OJSBUNDLE_NAME} + cp ${RMRN_JSBUNDLE_NAME}.packager.map ${RMRN_OJSBUNDLE_NAME}.packager.map +} + +sentryfn_build_hbc() { + echo "[fns_sentry] Building Hermes Bytecode (HBC)..." + + "${HERMES_BIN}" \ + -O -emit-binary -output-source-map \ + -out="${RMRN_JSBUNDLE_NAME}.hbc" \ + "${RMRN_JSBUNDLE_NAME}" + + rm "${RMRN_JSBUNDLE_NAME}" + mv "${RMRN_JSBUNDLE_NAME}.hbc" "${RMRN_JSBUNDLE_NAME}" +} + +sentryfn_compose_sourcemap() { + echo "[fns_sentry] composing sourcemap..." + + node $project_dir/node_modules/react-native/scripts/compose-source-maps.js \ + "${RMRN_JSBUNDLE_NAME}.packager.map" \ + "${RMRN_JSBUNDLE_NAME}.hbc.map" \ + -o "${RMRN_JSBUNDLE_NAME}.map" + + # node $project_dir/node_modules/@sentry/react-native/scripts/copy-debugid.js \ + # ${RMRN_JSBUNDLE_NAME}.packager.map ${RMRN_JSBUNDLE_NAME}.map + # rm -f ${RMRN_JSBUNDLE_NAME}.packager.map +} diff --git a/apps/mobile/scripts/fns.sh b/apps/mobile/scripts/fns.sh index e96cdf631..fabb96132 100755 --- a/apps/mobile/scripts/fns.sh +++ b/apps/mobile/scripts/fns.sh @@ -15,8 +15,8 @@ check_s3_params() { } checkout_s3_pub_deployment_params() { - if [ -z $targetplatform ]; then - export targetplatform="android" + if [ -z $BUILD_TARGET_PLATFORM ]; then + export BUILD_TARGET_PLATFORM="android" fi if [ -z $buildchannel ]; then export buildchannel="selfhost-reg" @@ -38,7 +38,7 @@ checkout_s3_pub_deployment_params() { ;; esac - if [ $targetplatform == 'ios' ]; then + if [ $BUILD_TARGET_PLATFORM == 'ios' ]; then if [ -z $IOS_PUB_DEPLOYMENT ]; then echo "[buildchannel:$buildchannel] IOS_PUB_DEPLOYMENT is not set" exit 1; @@ -52,12 +52,12 @@ checkout_s3_pub_deployment_params() { export s3_upload_prefix=$(echo "$IOS_PUB_DEPLOYMENT" | sed "s#s3://${RABBY_MOBILE_BUILD_BUCKET}/##g" | cut -d'/' -f2-) # echo "[debug] s3_upload_prefix is $s3_upload_prefix" export cdn_deployment_urlbase="https://download.rabby.io/$s3_upload_prefix" - elif [ $targetplatform == 'android' ]; then + elif [ $BUILD_TARGET_PLATFORM == 'android' ]; then export s3_upload_prefix=$(echo "$ANDROID_PUB_DEPLOYMENT" | sed "s#s3://${RABBY_MOBILE_BUILD_BUCKET}/##g" | cut -d'/' -f2-) # echo "[debug] s3_upload_prefix is $s3_upload_prefix" export cdn_deployment_urlbase="https://download.rabby.io/$s3_upload_prefix" else - echo "Invalid targetplatform: $targetplatform" + echo "Invalid BUILD_TARGET_PLATFORM: $BUILD_TARGET_PLATFORM" exit 1; fi } diff --git a/apps/mobile/src/constant/env.ts b/apps/mobile/src/constant/env.ts index 00d9a48aa..cf39499c6 100644 --- a/apps/mobile/src/constant/env.ts +++ b/apps/mobile/src/constant/env.ts @@ -1,6 +1,15 @@ import { DEV_CONSOLE_URL as DEV_CONSOLE_URL_ } from '@env'; +export const APP_RUNTIME_ENV = + process.env.BUILD_ENV === 'production' ? 'production' : 'development'; + export type AppBuildChannel = 'selfhost' | 'selfhost-reg' | 'appstore'; export const BUILD_CHANNEL = (process.env.buildchannel as AppBuildChannel) || 'selfhost-reg'; export const DEV_CONSOLE_URL = DEV_CONSOLE_URL_; + +export function getSentryEnv() { + return `ch:${BUILD_CHANNEL}|env:${APP_RUNTIME_ENV}`; +} + +export const SENTRY_DEBUG = APP_RUNTIME_ENV === 'development'; diff --git a/apps/mobile/src/constant/index.ts b/apps/mobile/src/constant/index.ts index baf7422cf..be85c3b95 100644 --- a/apps/mobile/src/constant/index.ts +++ b/apps/mobile/src/constant/index.ts @@ -26,6 +26,7 @@ const fromNative = getVersion(); export const APP_VERSIONS = { fromJs, fromNative, + forSentry: fromNative, forCheckUpgrade: __DEV__ ? fromJs : fromNative, }; diff --git a/apps/mobile/src/core/sentry.ts b/apps/mobile/src/core/sentry.ts index 604803c2f..7543a039c 100644 --- a/apps/mobile/src/core/sentry.ts +++ b/apps/mobile/src/core/sentry.ts @@ -1,8 +1,12 @@ import * as Sentry from '@sentry/react-native'; +import { APP_VERSIONS } from '@/constant'; +import { SENTRY_DEBUG, getSentryEnv } from '@/constant/env'; + export function initSentry() { Sentry.init({ dsn: 'https://5dc34e0794776dfb2d4e263b466b5052@o460488.ingest.sentry.io/4506406044696576', + release: APP_VERSIONS.forSentry, ignoreErrors: [ 'Missing or invalid topic field', 'Non-Error exception captured', @@ -11,6 +15,8 @@ export function initSentry() { // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring. // We recommend adjusting this value in production. tracesSampleRate: 0.2, + environment: getSentryEnv(), + debug: SENTRY_DEBUG, _experiments: { // The sampling rate for profiling is relative to TracesSampleRate. // In this case, we'll capture profiles for 100% of transactions.