defaults: &defaults working_directory: ~/repo macos: &macos macos: xcode: "11.5.0" bash-env: &bash-env BASH_ENV: "~/.nvm/nvm.sh" version: 2.1 # EXECUTORS executors: mac-env: <<: *macos environment: <<: *bash-env # COMMANDS commands: detox-test: parameters: folder: type: string steps: - checkout - restore-npm-cache-mac - restore-brew-cache - restore-app-cache - install-node - install-apple-sim-utils - install-npm-modules - rebuild-detox - run: name: Test command: | npx detox test << parameters.folder >> --configuration ios.sim.release --cleanup when: always - store_artifacts: path: ./artifacts install-npm-modules: description: Install NPM modules steps: - run: yarn restore-npm-cache-linux: description: Restore NPM cache steps: - restore_cache: key: node-modules-{{ checksum "yarn.lock" }} save-npm-cache-linux: description: Save NPM cache steps: - save_cache: key: node-modules-{{ checksum "yarn.lock" }} paths: - ./node_modules restore-npm-cache-mac: description: Restore NPM cache steps: - restore_cache: key: node-v1-mac-{{ checksum "yarn.lock" }} save-npm-cache-mac: description: Save NPM cache steps: - save_cache: key: node-v1-mac-{{ checksum "yarn.lock" }} paths: - ./node_modules install-node: description: Install Node steps: - run: command: | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash source ~/.nvm/nvm.sh INSTALLED_NODE=`nvm which current` echo "export PATH=\"${INSTALLED_NODE%%/node}:\$PATH\"" >> ~/.bash_profile source ~/.bash_profile restore-gems-cache: description: Restore gems cache steps: - restore_cache: key: bundle-v1-{{ checksum "ios/Gemfile.lock" }} save-gems-cache: description: Save gems cache steps: - save_cache: key: bundle-v1-{{ checksum "ios/Gemfile.lock" }} paths: - vendor/bundle update-fastlane-ios: description: Update Fastlane steps: - run: command: | echo "ruby-2.6.4" > ~/.ruby-version bundle install working_directory: ios update-fastlane-android: description: Update Fastlane steps: - run: command: | echo "ruby-2.6.4" > ~/.ruby-version bundle install working_directory: android restore-gradle-cache: description: Restore gradle cache steps: - restore_cache: key: android-{{ checksum "android/build.gradle" }}-{{ checksum "android/app/build.gradle" }} save-gradle-cache: description: Save gradle cache steps: - save_cache: key: android-{{ checksum "android/build.gradle" }}-{{ checksum "android/app/build.gradle" }} paths: - ~/.gradle restore-brew-cache: description: Restore Brew cache steps: - restore_cache: key: brew-mac save-brew-cache: description: Save brew cache steps: - save_cache: key: brew-mac paths: - ~/Library/Caches/Homebrew - /usr/local/Homebrew/Library/Taps/ install-apple-sim-utils: description: Install appleSimUtils steps: - run: command: | export HOMEBREW_NO_AUTO_UPDATE=1 export HOMEBREW_NO_INSTALL_CLEANUP=1 brew tap wix/brew brew install wix/brew/applesimutils rebuild-detox: description: Rebuild Detox framework cache steps: - run: command: | npx detox clean-framework-cache npx detox build-framework-cache save-app-cache: description: Restore previously built app steps: - run: name: Generate cache key for app source command: | echo $(git rev-parse HEAD:app) > "./app-git-revision.txt" - save_cache: key: iOSDetoxRelease-v3-{{ checksum "yarn.lock" }}-{{ checksum "ios/Podfile.lock" }}-{{ checksum "./app-git-revision.txt" }} paths: - ios/build/Build/Products/Release-iphonesimulator/RocketChatRN.app restore-app-cache: description: Save built app to cache steps: - run: name: Generate cache key for app source command: | echo $(git rev-parse HEAD:app) > "./app-git-revision.txt" - restore_cache: key: iOSDetoxRelease-v3-{{ checksum "yarn.lock" }}-{{ checksum "ios/Podfile.lock" }}-{{ checksum "./app-git-revision.txt" }} did-restore-app-cache: description: Tests to see if an app was restored from the restore-app-cache job steps: - run: name: if cache exists exit command: | FILE=/Users/distiller/project/ios/build/Build/Products/Release-iphonesimulator/RocketChatRN.app if [ -e "$FILE" ]; then echo "App restored from cache. Halting build." circleci step halt else echo "Suitable app not cached. Continuing build." fi # JOBS jobs: lint-testunit: <<: *defaults docker: - image: circleci/node:10 environment: CODECOV_TOKEN: caa771ab-3d45-4756-8e2a-e1f25996fef6 steps: - checkout - restore-npm-cache-linux - install-npm-modules - run: name: Lint command: | yarn lint - run: name: Test command: | yarn test - run: name: Codecov command: | yarn codecov - save-npm-cache-linux # E2E e2e-build: executor: mac-env steps: - checkout - restore-app-cache - did-restore-app-cache - restore-npm-cache-mac - restore-brew-cache - install-node - install-npm-modules - rebuild-detox - run: name: Build command: | npx detox build --configuration ios.sim.release - save-npm-cache-mac - save-brew-cache - save-app-cache e2e-test-onboarding: executor: mac-env steps: - detox-test: folder: "./e2e/tests/onboarding" e2e-test-room: executor: mac-env steps: - detox-test: folder: "./e2e/tests/room" e2e-test-assorted: executor: mac-env steps: - detox-test: folder: "./e2e/tests/assorted" # Android builds android-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 - install-node - restore-npm-cache-linux - install-npm-modules - update-fastlane-android - 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.33.1" >> ./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 fi echo -e "VERSIONCODE=$CIRCLE_BUILD_NUM" >> ./gradle.properties echo -e "BugsnagAPIKey=$BUGSNAG_KEY" >> ./gradle.properties working_directory: android - run: name: Set Google Services command: | cp google-services.prod.json google-services.json working_directory: android/app - run: name: Config variables command: | echo -e "export default { BUGSNAG_API_KEY: '$BUGSNAG_KEY' };" > ./config.js - run: name: Build Android App command: | if [[ $KEYSTORE ]]; then bundle exec fastlane android release else bundle exec fastlane android build fi working_directory: android - run: name: Upload sourcemaps to Bugsnag command: | if [[ $BUGSNAG_KEY ]]; then yarn generate-source-maps-android upload \ --api-key=$BUGSNAG_KEY \ --app-version=$CIRCLE_BUILD_NUM \ --minifiedFile=android/app/build/generated/assets/react/release/app.bundle \ --source-map=android/app/build/generated/sourcemaps/react/release/app.bundle.map \ --minified-url=app.bundle \ --upload-sources fi - store_artifacts: path: android/app/build/outputs - save-npm-cache-linux - save-gradle-cache - persist_to_workspace: root: . paths: - android/fastlane/report.xml - android/app/build/outputs android-google-play-alpha: <<: *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 - update-fastlane-android - run: name: Fastlane Play Store Upload command: bundle exec fastlane android alpha working_directory: android # iOS builds ios-build: executor: mac-env steps: - checkout - restore-gems-cache - restore-npm-cache-mac - install-node - install-npm-modules - update-fastlane-ios - run: name: Set Google Services command: | cp GoogleService-Info.prod.plist GoogleService-Info.plist working_directory: ios - run: name: Upload sourcemaps to Bugsnag command: | if [[ $BUGSNAG_KEY ]]; then yarn generate-source-maps-ios curl https://upload.bugsnag.com/react-native-source-map \ -F apiKey=$BUGSNAG_KEY \ -F appBundleVersion=$CIRCLE_BUILD_NUM \ -F dev=false \ -F platform=ios \ -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 [[ $MATCH_KEYCHAIN_NAME ]]; then bundle exec fastlane ios release else export MATCH_KEYCHAIN_NAME="temp" export MATCH_KEYCHAIN_PASSWORD="temp" bundle exec fastlane ios build fi working_directory: ios - save-npm-cache-mac - save-gems-cache - store_artifacts: path: ios/RocketChatRN.ipa - persist_to_workspace: root: . paths: - ios/*.ipa - ios/fastlane/report.xml ios-testflight: executor: mac-env steps: - checkout - attach_workspace: at: ios - restore-gems-cache - update-fastlane-ios - run: name: Fastlane Tesflight Upload command: | bundle exec fastlane ios beta working_directory: ios - save-gems-cache workflows: build-and-test: jobs: - lint-testunit - e2e-hold: type: approval requires: - lint-testunit - e2e-build: requires: - e2e-hold - e2e-test-onboarding: requires: - e2e-build - e2e-test-room: requires: - e2e-build - e2e-test-assorted: requires: - e2e-build - ios-build: requires: - lint-testunit - ios-hold-testflight: type: approval requires: - ios-build - ios-testflight: requires: - ios-hold-testflight - android-build: requires: - lint-testunit - android-hold-google-play-alpha: type: approval requires: - android-build - android-google-play-alpha: requires: - android-hold-google-play-alpha