Unverified Commit cd76dd99 authored by Diego Mello's avatar Diego Mello Committed by GitHub
Browse files

[CHORE] Build official apps on CI (#2701)



* Duplicated target and changed Bridging Header

* Display name

* Unnecessary dumb swift file removed

* Buildable name

* Reorder Info.plist

* Rename Official target's bundle id

* Ignore .mobileprovision

* Fix provisioning of official app

* Starting signing

* stash fastfile

* starting official ci iOS

* Uncomment Fastfile keychain

* Fix CI config

* allowProvisioningUpdates

* Changing AppIcon and Splash Screen

* Remove unnecessary folder inside of Images.xcassets

* Reorder notificationservice and shareextension plists

* Fix signing

* Manual signing style for official

* Split official signing

* Update project provisioning

* Use ENV as profile

* Output match

* Keys

* TestFlight refactor

* Setting up android

* android-official-play-build job

* Start removing unnecessary fastlane tasks on Android

* Trying to refactor Android jobs

* android-env

* Remove foss build for now

* Fork

* Fix if conditions

* Fix push

* ios-build command

* Rename Android builds

* Upload dSYMs

* Refactoring workflow

* Reorder upload-to-testflight

* upload-to-google-play-beta command

* Fix ci

* Fix android fork build

* Fix keystore

* Fix options on fastlane android

* Fix keystore

* Check isOfficial on iOS

* Check isOfficial on db

* Remove unused imports

* Database names on Android

* Tag fix

* Minor fixes

* Set IS_OFFICIAL on CI

* Fix detox

* follow review suggestions

Co-authored-by: default avatarDjorkaeff Alexandre <djorkaeff.unb@gmail.com>
parent c9c8bdec
......@@ -8,6 +8,11 @@ macos: &macos
bash-env: &bash-env
BASH_ENV: "~/.nvm/nvm.sh"
android-env: &android-env
JAVA_OPTS: '-Xms512m -Xmx2g'
GRADLE_OPTS: '-Xmx3g -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx2g -XX:+HeapDumpOnOutOfMemoryError"'
TERM: dumb
install-npm-modules: &install-npm-modules
name: Install NPM modules
command: yarn
......@@ -75,61 +80,11 @@ restore_cache: &restore-gradle-cache
name: Restore gradle cache
key: android-{{ checksum "android/build.gradle" }}-{{ checksum "android/app/build.gradle" }}
version: 2.1
# EXECUTORS
executors:
mac-env:
<<: *macos
environment:
<<: *bash-env
# JOBS
jobs:
lint-testunit:
<<: *defaults
docker:
- image: circleci/node:10
environment:
CODECOV_TOKEN: caa771ab-3d45-4756-8e2a-e1f25996fef6
steps:
- checkout
- restore_cache: *restore-npm-cache-linux
- run: *install-npm-modules
- run:
name: Lint
command: |
yarn lint
- run:
name: Test
command: |
yarn test
- run:
name: Codecov
command: |
yarn codecov
- save_cache: *save-npm-cache-linux
# Android builds
android-play-build:
<<: *defaults
docker:
- image: circleci/android:api-28-node
environment:
JAVA_OPTS: '-Xms512m -Xmx2g'
GRADLE_OPTS: '-Xmx3g -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx2g -XX:+HeapDumpOnOutOfMemoryError"'
TERM: dumb
<<: *bash-env
# COMMANDS
commands:
android-build:
description: "Build Android app"
steps:
- checkout
......@@ -139,8 +94,6 @@ jobs:
- run: *install-npm-modules
- run: *update-fastlane-android
- restore_cache: *restore-gradle-cache
- run:
......@@ -151,11 +104,19 @@ jobs:
echo -e "android.useAndroidX=true" >> ./gradle.properties
echo -e "android.enableJetifier=true" >> ./gradle.properties
echo -e "FLIPPER_VERSION=0.51.0" >> ./gradle.properties
echo -e "APPLICATION_ID=chat.rocket.reactnative" >> ./gradle.properties
echo -e "VERSIONCODE=$CIRCLE_BUILD_NUM" >> ./gradle.properties
echo -e "BugsnagAPIKey=$BUGSNAG_KEY" >> ./gradle.properties
if [[ $KEYSTORE ]]; then
if [[ $CIRCLE_JOB == "android-build-official" ]]; then
echo -e "APPLICATION_ID=chat.rocket.android" >> ./gradle.properties
echo -e "BugsnagAPIKey=$BUGSNAG_KEY_OFFICIAL" >> ./gradle.properties
echo $CHAT_ROCKET_ANDROID_STORE_FILE_BASE64_JKS | base64 --decode > ./app/$KEYSTORE_OFFICIAL
echo -e "KEYSTORE=$KEYSTORE_OFFICIAL" >> ./gradle.properties
echo -e "KEYSTORE_PASSWORD=$CHAT_ROCKET_ANDROID_STORE_PASSWORD" >> ./gradle.properties
echo -e "KEY_ALIAS=$CHAT_ROCKET_ANDROID_KEY_ALIAS" >> ./gradle.properties
echo -e "KEY_PASSWORD=$CHAT_ROCKET_ANDROID_KEY_PASSWORD" >> ./gradle.properties
else
echo -e "APPLICATION_ID=chat.rocket.reactnative" >> ./gradle.properties
echo -e "BugsnagAPIKey=$BUGSNAG_KEY" >> ./gradle.properties
echo $KEYSTORE_BASE64 | base64 --decode > ./app/$KEYSTORE
echo -e "KEYSTORE=$KEYSTORE" >> ./gradle.properties
echo -e "KEYSTORE_PASSWORD=$KEYSTORE_PASSWORD" >> ./gradle.properties
......@@ -170,97 +131,52 @@ jobs:
if [[ $KEYSTORE ]]; then
echo $GOOGLE_SERVICES_ANDROID | base64 --decode > google-services.json
fi
working_directory: android/app/src/play
working_directory: android/app
- run:
name: Config variables
command: |
echo -e "export default { BUGSNAG_API_KEY: '$BUGSNAG_KEY' };" > ./config.js
if [[ $CIRCLE_JOB == "android-build-official" ]]; then
echo -e "export default { BUGSNAG_API_KEY: '$BUGSNAG_KEY_OFFICIAL' };" > ./config.js
else
echo -e "export default { BUGSNAG_API_KEY: '$BUGSNAG_KEY' };" > ./config.js
fi
- run:
name: Build Android Play App
name: Build App
command: |
if [[ $KEYSTORE ]]; then
bundle exec fastlane android playRelease
else
bundle exec fastlane android playBuild
if [[ $CIRCLE_JOB == "android-build-official" ]]; then
./gradlew bundleOfficialPlayRelease
fi
if [[ $CIRCLE_JOB == "android-build-experimental" ]]; then
./gradlew bundleExperimentalPlayRelease
fi
if [[ ! $KEYSTORE ]]; then
./gradlew assembleExperimentalPlayDebug
fi
working_directory: android
- run:
name: Upload sourcemaps to Bugsnag
command: |
if [[ $BUGSNAG_KEY ]]; then
if [[ $CIRCLE_JOB == "android-build-official" ]]; then
yarn generate-source-maps-android upload \
--api-key=$BUGSNAG_KEY \
--api-key=$BUGSNAG_KEY_OFFICIAL \
--app-version=$CIRCLE_BUILD_NUM \
--minifiedFile=android/app/build/generated/assets/react/play/release/app.bundle \
--source-map=android/app/build/generated/sourcemaps/react/play/release/app.bundle.map \
--minifiedFile=android/app/build/generated/assets/react/officialPlay/release/app.bundle \
--source-map=android/app/build/generated/sourcemaps/react/officialPlay/release/app.bundle.map \
--minified-url=app.bundle \
--upload-sources
fi
- store_artifacts:
path: android/app/build/outputs
- save_cache: *save-npm-cache-linux
- save_cache: *save-gradle-cache
- persist_to_workspace:
root: .
paths:
- android/fastlane/report.xml
- android/app/build/outputs
android-foss-build:
<<: *defaults
docker:
- image: circleci/android:api-28-node
environment:
JAVA_OPTS: '-Xms512m -Xmx2g'
GRADLE_OPTS: '-Xmx3g -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx2g -XX:+HeapDumpOnOutOfMemoryError"'
TERM: dumb
<<: *bash-env
steps:
- checkout
- run: *install-node
- restore_cache: *restore-npm-cache-linux
- run: *install-npm-modules
- run: *update-fastlane-android
- restore_cache: *restore-gradle-cache
- run:
name: Configure Gradle
command: |
echo -e "" > ./gradle.properties
# echo -e "android.enableAapt2=false" >> ./gradle.properties
echo -e "android.useAndroidX=true" >> ./gradle.properties
echo -e "android.enableJetifier=true" >> ./gradle.properties
echo -e "FLIPPER_VERSION=0.51.0" >> ./gradle.properties
echo -e "VERSIONCODE=$CIRCLE_BUILD_NUM" >> ./gradle.properties
echo -e "APPLICATION_ID=chat.rocket.android" >> ./gradle.properties
if [[ $KEYSTORE ]]; then
echo $KEYSTORE_BASE64 | base64 --decode > ./app/$KEYSTORE
echo -e "KEYSTORE=$KEYSTORE" >> ./gradle.properties
echo -e "KEYSTORE_PASSWORD=$KEYSTORE_PASSWORD" >> ./gradle.properties
echo -e "KEY_ALIAS=$KEY_ALIAS" >> ./gradle.properties
echo -e "KEY_PASSWORD=$KEYSTORE_PASSWORD" >> ./gradle.properties
if [[ $CIRCLE_JOB == "android-build-experimental" ]]; then
yarn generate-source-maps-android upload \
--api-key=$BUGSNAG_KEY \
--app-version=$CIRCLE_BUILD_NUM \
--minifiedFile=android/app/build/generated/assets/react/experimentalPlay/release/app.bundle \
--source-map=android/app/build/generated/sourcemaps/react/experimentalPlay/release/app.bundle.map \
--minified-url=app.bundle \
--upload-sources
fi
working_directory: android
- run:
name: Build Android Foss App
command: bundle exec fastlane android fossRelease
working_directory: android
- store_artifacts:
path: android/app/build/outputs
......@@ -272,61 +188,38 @@ jobs:
- persist_to_workspace:
root: .
paths:
- android/fastlane/report.xml
- android/app/build/outputs
android-google-play-beta:
<<: *defaults
docker:
- image: circleci/android:api-28-node
steps:
- checkout
- attach_workspace:
at: android
- run:
name: Store the google service account key
command: echo "$FASTLANE_GOOGLE_SERVICE_ACCOUNT" | base64 --decode > service_account.json
working_directory: android
- run: *update-fastlane-android
- run:
name: Fastlane Play Store Upload
command: bundle exec fastlane android beta
working_directory: android
# iOS builds
ios-build:
executor: mac-env
description: "Build iOS app"
steps:
- checkout
- restore_cache: *restore-gems-cache
- restore_cache: *restore-npm-cache-mac
- run: *install-node
- run: *install-npm-modules
- run: *update-fastlane-ios
- run:
name: Set Google Services
command: |
if [[ $KEYSTORE ]]; then
echo $GOOGLE_SERVICES_REACTNATIVE | base64 --decode > GoogleService-Info.plist
echo $GOOGLE_SERVICES_IOS | base64 --decode > GoogleService-Info.plist
fi
working_directory: ios
- run:
name: Upload sourcemaps to Bugsnag
command: |
if [[ $BUGSNAG_KEY ]]; then
if [[ $CIRCLE_JOB == "ios-build-official" ]]; then
yarn generate-source-maps-ios
curl https://upload.bugsnag.com/react-native-source-map \
-F apiKey=$BUGSNAG_KEY_OFFICIAL \
-F appBundleVersion=$CIRCLE_BUILD_NUM \
-F dev=false \
-F platform=ios \
-F sourceMap=@ios-release.bundle.map \
-F bundle=@ios-release.bundle
fi
if [[ $CIRCLE_JOB == "ios-build-experimental" ]]; then
yarn generate-source-maps-ios
curl https://upload.bugsnag.com/react-native-source-map \
-F apiKey=$BUGSNAG_KEY \
......@@ -336,87 +229,244 @@ jobs:
-F sourceMap=@ios-release.bundle.map \
-F bundle=@ios-release.bundle
fi
- run:
name: Fastlane Build
no_output_timeout: 1200
command: |
agvtool new-version -all $CIRCLE_BUILD_NUM
/usr/libexec/PlistBuddy -c "Set BugsnagAPIKey $BUGSNAG_KEY" ./RocketChatRN/Info.plist
if [[ $CIRCLE_JOB == "ios-build-official" ]]; then
/usr/libexec/PlistBuddy -c "Set BugsnagAPIKey $BUGSNAG_KEY_OFFICIAL" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./RocketChatRN/Info.plist
else
/usr/libexec/PlistBuddy -c "Set BugsnagAPIKey $BUGSNAG_KEY" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./RocketChatRN/Info.plist
fi
if [[ $APP_STORE_CONNECT_API_KEY ]]; then
echo $APP_STORE_CONNECT_API_KEY | base64 --decode > ./fastlane/app_store_connect_api_key.p8
bundle exec fastlane ios release
else
bundle exec fastlane ios build_fork
if [[ $CIRCLE_JOB == "ios-build-official" ]]; then
bundle exec fastlane ios build_official
else
if [[ $KEYSTORE ]]; then
bundle exec fastlane ios release # TODO: rename
else
bundle exec fastlane ios build_fork
fi
fi
fi
working_directory: ios
- save_cache: *save-npm-cache-mac
- save_cache: *save-gems-cache
- store_artifacts:
path: ios/RocketChatRN.ipa
path: ios/Rocket.Chat.ipa
- store_artifacts:
path: ios/Rocket.Chat.app.dSYM.zip
- persist_to_workspace:
root: .
paths:
- ios/*.ipa
- ios/fastlane/report.xml
ios-testflight:
executor: mac-env
- ios/*.zip
upload-to-google-play-beta:
description: "Upload to Google Play beta"
parameters:
official:
type: boolean
steps:
- checkout
- attach_workspace:
at: android
- run:
name: Store the google service account key
command: echo "$FASTLANE_GOOGLE_SERVICE_ACCOUNT" | base64 --decode > service_account.json
working_directory: android
- run: *update-fastlane-android
- run:
name: Fastlane Play Store Upload
command: bundle exec fastlane android beta official:<< parameters.official >>
working_directory: android
upload-to-testflight:
description: "Upload to TestFlight"
parameters:
official:
type: boolean
steps:
- checkout
- attach_workspace:
at: ios
- restore_cache: *restore-gems-cache
- run: *update-fastlane-ios
- run:
name: Fastlane Tesflight Upload
command: |
echo $APP_STORE_CONNECT_API_KEY | base64 --decode > ./fastlane/app_store_connect_api_key.p8
bundle exec fastlane ios beta
bundle exec fastlane ios beta official:<< parameters.official >>
working_directory: ios
- save_cache: *save-gems-cache
version: 2.1
# EXECUTORS
executors:
mac-env:
<<: *macos
environment:
<<: *bash-env
# JOBS
jobs:
lint-testunit:
<<: *defaults
docker:
- image: circleci/node:10
environment:
CODECOV_TOKEN: caa771ab-3d45-4756-8e2a-e1f25996fef6
steps:
- checkout
- restore_cache: *restore-npm-cache-linux
- run: *install-npm-modules
- run:
name: Lint
command: |
yarn lint
- run:
name: Test
command: |
yarn test
- run:
name: Codecov
command: |
yarn codecov
- save_cache: *save-npm-cache-linux
# Android builds
android-build-experimental:
<<: *defaults
docker:
- image: circleci/android:api-28-node
environment:
<<: *android-env
<<: *bash-env
steps:
- android-build
android-build-official:
<<: *defaults
docker:
- image: circleci/android:api-28-node
environment:
<<: *android-env
<<: *bash-env
steps:
- android-build
android-google-play-beta-experimental:
<<: *defaults
docker:
- image: circleci/android:api-28-node
steps:
- upload-to-google-play-beta:
official: false
android-google-play-beta-official:
<<: *defaults
docker:
- image: circleci/android:api-28-node
steps:
- upload-to-google-play-beta:
official: true
# iOS builds
ios-build-experimental:
executor: mac-env
steps:
- ios-build
ios-build-official:
executor: mac-env
steps:
- ios-build
ios-testflight-experimental:
executor: mac-env
steps:
- upload-to-testflight:
official: false
ios-testflight-official:
executor: mac-env
steps:
- upload-to-testflight:
official: true
workflows:
build-and-test:
jobs:
- lint-testunit
- ios-build:
# iOS Experimental
- ios-build-experimental:
requires:
- lint-testunit
- ios-hold-testflight:
- ios-hold-testflight-experimental:
type: approval
requires:
- ios-build
- ios-testflight:
- ios-build-experimental
- ios-testflight-experimental:
requires:
- ios-hold-testflight
- ios-hold-testflight-experimental
- android-play-build:
# iOS Official
- ios-hold-build-official:
type: approval
requires:
- lint-testunit
- android-hold-google-play-beta:
- ios-build-official:
requires:
- ios-hold-build-official
- ios-hold-testflight-official:
type: approval
requires:
- android-play-build
- android-google-play-beta:
- ios-build-official
- ios-testflight-official:
requires:
- android-hold-google-play-beta
- android-hold-foss-build:
- ios-hold-testflight-official
# Android Experimental
- android-build-experimental:
requires:
- lint-testunit
- android-hold-google-play-beta-experimental:
type: approval
requires:
- android-build-experimental
- android-google-play-beta-experimental:
requires:
- android-hold-google-play-beta-experimental
# Android Official
- android-hold-build-official:
type: approval
requires:
- lint-testunit
- android-foss-build:
- android-build-official:
requires:
- android-hold-build-official
- android-hold-google-play-beta-official:
type: approval
requires:
- android-build-official
- android-google-play-beta-official:
requires:
- android-hold-foss-build
- android-hold-google-play-beta-official
......@@ -21,6 +21,7 @@ DerivedData
*.ipa
*.xcuserstate
project.xcworkspace
*.mobileprovision
# Android/IntelliJ
#
......
def taskRequests = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase()
def isPlay = !taskRequests.contains("foss")
def isFoss = taskRequests.contains("foss")
apply plugin: "com.android.application"
apply plugin: 'kotlin-android'
if (isPlay) {
if (!isFoss) {
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.bugsnag.android.gradle'
}
......@@ -146,7 +146,7 @@ android {
versionCode VERSIONCODE as Integer
versionName "4.13.0"
vectorDrawables.useSupportLibrary = true
if (isPlay) {
if (!isFoss) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60" // See note below!
}
......@@ -176,7 +176,7 @@ android {
minifyEnabled enableProguardInReleaseBuilds
setProguardFiles([getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'])
signingConfig signingConfigs.release
if (isPlay) {
if (!isFoss) {
firebaseCrashlytics {
nativeSymbolUploadEnabled true
}
......@@ -193,10 +193,17 @@ android {
// applicationVariants are e.g. debug, release
flavorDimensions "type"
flavorDimensions "app", "type"
productFlavors {
official {
dimension = "app"
buildConfigField "boolean", "IS_OFFICIAL", "true"
}
experimental {
dimension = "app"