redbadger/pride-london-app

View on GitHub
.circleci/config.yml

Summary

Maintainability
Test Coverage
yarn-key: &yarn-key
  v1-dependencies-{{ checksum "yarn.lock" }}
yarn-key-macos: &yarn-key-macos
  v3-dependencies-macos-{{ checksum "/Users/distiller/project/yarn.lock" }}
gradle-key: &gradle-key
  v1-jars-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
gems-key: &gems-key
  v1-gems-{{ checksum "Gemfile.lock" }}
brew-key: &brew-key
  v1-brew-{{ checksum "BrewFile" }}
nightly-key: &nightly-key
  v0.1-nightly-{{ checksum "~/.pride-nightly/last-commit" }}
android-artifacts-path: &android-artifacts-path
  $HOME/project/android/app/build/outputs
artifacts-path-macos: &artifacts-path-macos
  /Users/distiller/project/output

get-yarn-cache: &get-yarn-cache
  restore_cache:
    key: *yarn-key
save-yarn-cache: &save-yarn-cache
  save_cache:
    paths:
      - node_modules
    key: *yarn-key

# macOS machine builds have different paths and arch
get-yarn-cache-macos: &get-yarn-cache-macos
  restore_cache:
    key: *yarn-key-macos
save-yarn-cache-macos: &save-yarn-cache-macos
  save_cache:
    paths:
      - /Users/distiller/project/node_modules
    key: *yarn-key-macos

restore-gradle-cache: &restore-gradle-cache
  restore_cache:
    key: *gradle-key
save-gradle-cache: &save-gradle-cache
  save_cache:
    key: *gradle-key
    paths:
      - ~/.gradle
      - ~/.m2

restore-gems-cache: &restore-gems-cache
  restore_cache:
    key: *gems-key
save-gems-cache: &save-gems-cache
  save_cache:
    key: *gems-key
    paths:
      - vendor/bundle

restore-brew-cache: &restore-brew-cache
  restore_cache:
    key: *brew-key
save-brew-cache: &save-brew-cache
  save_cache:
    key: *brew-key
    paths:
      - /usr/local/Homebrew

restore-nightly-cache: &restore-nightly-cache
  restore_cache:
    key: *nightly-key
save-nightly-cache: &save-nightly-cache
  save_cache:
    key: *nightly-key
    paths:
      - ~/.pride-nightly/cache

yarn-dependencies: &yarn-dependencies
  run:
    name: Install dependencies
    command: yarn install

yarn-dependencies-macos: &yarn-dependencies-macos
  run:
    name: Install dependencies with Yarn
    command: yarn install
    working_directory: /Users/distiller/project

ruby-dependencies: &ruby-dependencies
  run:
    name: Download Ruby Dependencies
    command: bundle install --path vendor/bundle

android-dependencies: &android-dependencies
  run:
    name: Download Android Dependencies
    command: ./gradlew androidDependencies

brew-depdendencies: &brew-depdendencies
  run:
    name: Install HomeBrew dependencies
    command: |
      brew tap homebrew/bundle
      brew bundle

android-secrets: &android-secrets
  run:
    command: |
      git clone git@github.com:redbadger/pride-android-secrets.git
      mkdir -p .gradle
      echo -e "keystore=$ANDROID_KEYSTORE_PATH\nkeystore.alias=$ANDROID_KEYSTORE_ALIAS\nkeystore.password=$ANDROID_KEYSTORE_PASSWORD\nkeystore.keypass=$ANDROID_KEYSTORE_PASSWORD\nversionCode=$CIRCLE_BUILD_NUM" > .gradle/gradle.properties
android-release-secrets: &android-release-secrets
  run:
    command: |
      git clone git@github.com:redbadger/pride-android-secrets.git
      mkdir -p .gradle
      echo -e "keystore=$ANDROID_RELEASE_KEYSTORE_PATH\nkeystore.alias=$ANDROID_RELEASE_KEYSTORE_ALIAS\nkeystore.password=$ANDROID_RELEASE_KEYSTORE_PASSWORD\nkeystore.keypass=$ANDROID_RELEASE_KEYSTORE_PASSWORD\nversionCode=$CIRCLE_BUILD_NUM" > .gradle/gradle.properties

fabric-secrets-android: &fabric-secrets-android
  run:
    name: Set Fabric secret
    command: |
      echo -e "apiSecret=$FABRIC_BUILD_SECRET\napiKey=$FABRIC_API_KEY" >> ./app/fabric.properties
fabric-secrets-ios: &fabric-secrets-ios
  run:
    name: Set Fabric secret
    command: echo -e "$FABRIC_API_KEY\n$FABRIC_BUILD_SECRET" >> /Users/distiller/project/ios/PrideLondonApp/fabric.properties

job-defaults-docker: &job-defaults-docker
  working_directory: ~/project/android
  docker:
    - image: circleci/android:api-27-node8-alpha

env-docker: &env-docker
  TERM: dumb
  LC_ALL: en_US.UTF-8
  LANG: en_US.UTF-8

checkout-docker: &checkout-docker
  checkout:
    path: ~/project

workspace-docker: &workspace-docker
  attach_workspace:
    at: ~/project

store-artifacts-docker: &store-artifacts-docker
  store_artifacts:
    path: ~/project/android/app/build/outputs

job-defaults-macos: &job-defaults-macos
  macos:
    xcode: "10.1.0"
  shell: /bin/bash --login -o pipefail

env-macos: &env-macos
  FL_OUTPUT_DIR: /Users/distiller/project/output

checkout-macos: &checkout-macos
  checkout:
    path: /Users/distiller/project

set-ruby-version-macos: &set-ruby-version-macos
  run:
    name: Set Ruby Version
    command:  echo "ruby-2.4" > ~/.ruby-version

set-node-version-macos: &set-node-version-macos
  run:
    name: Set node version
    command: |
      yarn global add n
      sudo n 9.3

generate-env: &generate-env
  run:
    name: Generate .env
    command: node ./scripts/generate-dotenv.js
    working_directory: ~/project

generate-env-macos: &generate-env-macos
  run:
    name: Generate .env
    command: node ./scripts/generate-dotenv.js
    working_directory: /Users/distiller/project

release-api-keys: &release-api-keys
  run:
    name: Set release API keys
    command: |
      echo 'export CONTENTFUL_SPACE_ID=$RELEASE_CONTENTFUL_SPACE_ID' >> $BASH_ENV
      echo 'export CONTENTFUL_API_KEY=$RELEASE_CONTENTFUL_API_KEY' >> $BASH_ENV
      echo 'export GOOGLE_MAPS_API_KEY=$RELEASE_GOOGLE_MAPS_API_KEY' >> $BASH_ENV
      source $BASH_ENV

bugsnag-upload-sourcemaps-android: &bugsnag-upload-sourcemaps-android
  run:
    name: Generate js sourcemaps and upload to Bugsnag
    command: |
        ./scripts/upload-sourcemaps.sh \
        android \
        $BUGSNAG_API_KEY
    working_directory: ~/project

bugsnag-upload-sourcemaps-ios: &bugsnag-upload-sourcemaps-ios
  run:
    name: Generate js sourcemaps and upload to Bugsnag
    command: |
        ./scripts/upload-sourcemaps.sh \
        ios \
        $BUGSNAG_API_KEY
    working_directory: /Users/distiller/project

generate-nightly-file: &generate-nightly-file
  run:
    name: Generate Nightly Last Commit File
    command: |
        mkdir -p ~/.pride-nightly
        git rev-parse HEAD > ~/.pride-nightly/last-commit

generate-nightly-cache: &generate-nightly-cache
  run:
    name: Generate Nightly Cache
    command: |
        mkdir -p ~/.pride-nightly/cache
        cp ~/.pride-nightly/last-commit ~/.pride-nightly/cache/

version: 2
jobs:
  # build is a reserved job name for running circleci locally
  build:
    docker:
      - image: circleci/node:9.3
    working_directory: ~/project
    steps:
      - checkout
      - <<: *get-yarn-cache
      - run:
          name: Test reporter status
          command: |
              curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
              chmod +x ./cc-test-reporter
              ./cc-test-reporter before-build
      - <<: *yarn-dependencies
      - <<: *save-yarn-cache
      - run:
          name: Lint source
          command: yarn lint
      - run:
          name: Type check
          command: yarn flow
      - run:
          name: Unit test
          command: |
              yarn test
              ./cc-test-reporter after-build
      - persist_to_workspace:
          root: ~/project
          paths:
            - node_modules

  alpha-android:
    <<: *job-defaults-docker
    environment:
      <<: *env-docker
      APK_PATH: "./app/build/outputs/apk/alpha/release/app-alpha-release.apk"
    steps:
      - <<: *checkout-docker
      - <<: *workspace-docker
      - <<: *android-secrets
      - <<: *fabric-secrets-android
      - <<: *restore-gems-cache
      - <<: *ruby-dependencies
      - <<: *save-gems-cache
      - <<: *restore-gradle-cache
      - <<: *android-dependencies
      - <<: *save-gradle-cache
      - <<: *generate-env
      - run:
            name: Build Alpha binary and upload for distribution
            command: |
                bundle exec fastlane alpha \
                submit:true \
                apk_path:$APK_PATH \
                api_token:$HOCKEY_APP_TOKEN \
                app_id:$HOCKEY_APP_ANDROID_ALPHA_APP_ID \
                fabric_api_token:$FABRIC_API_KEY \
                fabric_build_secret:$FABRIC_BUILD_SECRET \
                fabric_groups:$FABRIC_GROUPS \
                commit_sha:$CIRCLE_SHA1
      - <<: *store-artifacts-docker

  beta-android:
    <<: *job-defaults-docker
    environment:
      <<: *env-docker
      APK_PATH: "./app/build/outputs/apk/beta/release/app-beta-release.apk"
      RELEASE_STAGE: "beta"
    steps:
      - <<: *checkout-docker
      - <<: *workspace-docker
      - <<: *android-secrets
      - <<: *fabric-secrets-android
      - <<: *restore-gems-cache
      - <<: *ruby-dependencies
      - <<: *save-gems-cache
      - <<: *restore-gradle-cache
      - <<: *android-dependencies
      - <<: *save-gradle-cache
      - <<: *generate-env
      - run:
            name: Build Beta binary and upload for distribution
            command: |
                bundle exec fastlane beta \
                submit:true \
                apk_path:$APK_PATH \
                api_token:$HOCKEY_APP_TOKEN \
                app_id:$HOCKEY_APP_ANDROID_BETA_APP_ID \
                fabric_api_token:$FABRIC_API_KEY \
                fabric_build_secret:$FABRIC_BUILD_SECRET \
                fabric_groups:$FABRIC_GROUPS \
                commit_sha:$CIRCLE_SHA1
      - <<: *bugsnag-upload-sourcemaps-android
      - <<: *store-artifacts-docker

  release-android:
    <<: *job-defaults-docker
    environment:
      <<: *env-docker
      APK_PATH: "./app/build/outputs/apk/production/release/app-production-release.apk"
      RELEASE_STAGE: "release"
    steps:
      - <<: *checkout-docker
      - <<: *workspace-docker
      - <<: *android-release-secrets
      - <<: *fabric-secrets-android
      - <<: *restore-gems-cache
      - <<: *ruby-dependencies
      - <<: *save-gems-cache
      - <<: *restore-gradle-cache
      - <<: *android-dependencies
      - <<: *save-gradle-cache
      - <<: *release-api-keys
      - <<: *generate-env
      - run:
            name: Build Release binary and upload for distribution
            command: |
                bundle exec fastlane release \
                submit:true \
                apk_path:$APK_PATH \
                upload_key:$PLAY_STORE_UPLOAD_KEY_PATH \
                ci_build_num:$CIRCLE_BUILD_NUM \
                slack_webhook:$SLACK_WEBHOOK
      - <<: *bugsnag-upload-sourcemaps-android

  alpha-ios:
    <<: *job-defaults-macos
    working_directory: /Users/distiller/project/ios
    environment:
      <<: *env-macos
    steps:
      - <<: *checkout-macos
      - <<: *set-ruby-version-macos
      # Not using a workspace here as Node and Yarn versions
      # differ between the macOS image and the Docker containers above.
      - <<: *fabric-secrets-ios
      - <<: *restore-gems-cache
      - <<: *ruby-dependencies
      - <<: *save-gems-cache
      - <<: *set-node-version-macos
      - <<: *get-yarn-cache-macos
      - <<: *yarn-dependencies-macos
      - <<: *save-yarn-cache-macos
      - <<: *generate-env-macos
      - run:
            name: Build Alpha binary and upload for distribution
            command: |
                bundle exec fastlane alpha \
                submit:true \
                api_token:$HOCKEY_APP_TOKEN \
                app_id:$HOCKEY_APP_IOS_ALPHA_APP_ID \
                fabric_api_token:$FABRIC_API_KEY \
                fabric_build_secret:$FABRIC_BUILD_SECRET \
                fabric_groups:$FABRIC_GROUPS \
                ci_build_num:$CIRCLE_BUILD_NUM \
                commit_sha:$CIRCLE_SHA1
      - store_artifacts:
          path: /Users/distiller/project/output

  beta-ios:
    <<: *job-defaults-macos
    working_directory: /Users/distiller/project/ios
    environment:
      <<: *env-macos
      RELEASE_STAGE: "beta"
    steps:
      - <<: *checkout-macos
      - <<: *set-ruby-version-macos
      # Not using a workspace here as Node and Yarn versions
      # differ between the macOS image and the Docker containers above.
      - <<: *fabric-secrets-ios
      - <<: *restore-gems-cache
      - <<: *ruby-dependencies
      - <<: *save-gems-cache
      - <<: *set-node-version-macos
      - <<: *get-yarn-cache-macos
      - <<: *yarn-dependencies-macos
      - <<: *save-yarn-cache-macos
      - <<: *generate-env-macos
      - run:
            name: Build Beta binary and upload for distribution
            command: |
                bundle exec fastlane beta \
                submit:true \
                api_token:$HOCKEY_APP_TOKEN \
                app_id:$HOCKEY_APP_IOS_BETA_APP_ID \
                fabric_api_token:$FABRIC_API_KEY \
                fabric_build_secret:$FABRIC_BUILD_SECRET \
                fabric_groups:$FABRIC_GROUPS \
                ci_build_num:$CIRCLE_BUILD_NUM \
                commit_sha:$CIRCLE_SHA1 \
                release_stage:$RELEASE_STAGE \
                bugsnag_api_key:$BUGSNAG_API_KEY
      - <<: *bugsnag-upload-sourcemaps-ios
      - store_artifacts:
          path: /Users/distiller/project/output

  release-ios:
    <<: *job-defaults-macos
    working_directory: /Users/distiller/project/ios
    environment:
      <<: *env-macos
      RELEASE_STAGE: "release"
    steps:
      - <<: *checkout-macos
      - <<: *set-ruby-version-macos
      # Not using a workspace here as Node and Yarn versions
      # differ between the macOS image and the Docker containers above.
      - <<: *fabric-secrets-ios
      - <<: *restore-gems-cache
      - <<: *ruby-dependencies
      - <<: *save-gems-cache
      - <<: *set-node-version-macos
      - <<: *get-yarn-cache-macos
      - <<: *yarn-dependencies-macos
      - <<: *save-yarn-cache-macos
      - <<: *release-api-keys
      - <<: *generate-env-macos
      - run:
            name: Build Release binary and upload for distribution
            command: |
                bundle exec fastlane release \
                submit:true \
                ci_build_num:$CIRCLE_BUILD_NUM \
                release_stage:$RELEASE_STAGE \
                bugsnag_api_key:$BUGSNAG_API_KEY \
                slack_webhook:$SLACK_WEBHOOK
      - <<: *bugsnag-upload-sourcemaps-ios

  e2e-ios:
    <<: *job-defaults-macos
    working_directory: /Users/distiller/project
    environment:
      <<: *env-macos
    steps:
      - <<: *checkout-macos
      - <<: *set-ruby-version-macos
      - run:
          name: Install xcpretty
          command: |
            gem install xcpretty
      # Not using a workspace here as Node and Yarn versions
      # differ between the macOS image and the Docker containers above.
      - <<: *fabric-secrets-ios
      - run:
          name: Pre-start simulator
          command: xcrun simctl boot "iPhone 7" || true
      - <<: *fabric-secrets-ios
      - <<: *restore-brew-cache
      - run:
          name: Install HomeBrew dependencies
          command: |
              brew tap homebrew/bundle
              brew bundle
      - <<: *save-brew-cache
      - <<: *set-node-version-macos
      - run:
          name: Install global npm dependencies
          command: |
              npm i -g detox-cli
              npm i -g react-native-cli
      - <<: *get-yarn-cache-macos
      - <<: *yarn-dependencies-macos
      - <<: *save-yarn-cache-macos
      - <<: *generate-env-macos
      - run: npx detox clean-framework-cache && npx detox build-framework-cache
      - run: yarn test:e2e:release
      - store_artifacts:
          path: artifacts/

  test-nightly:
    <<: *job-defaults-macos
    working_directory: /Users/distiller/project/ios
    environment:
      <<: *env-macos
    steps:
      - <<: *checkout-macos
      - <<: *generate-nightly-file
      - <<: *restore-nightly-cache
      - run:
          name: Run if not run before
          command: |
              if [ ! -f ~/.pride-nightly/cache/last-commit ]; then
                echo "run build..."
              else
                echo "build not needed..."
              fi
      - <<: *generate-nightly-cache
      - <<: *save-nightly-cache

workflows:
  version: 2
  node-android-ios:
    jobs:
      - build
      # - e2e-ios
      - alpha-android:
          requires:
            - build
          filters:
            branches:
              ignore:
                - master
      - alpha-ios:
          filters:
            branches:
              ignore:
                - master
      - beta-android:
          requires:
            - build
          filters:
            branches:
              only:
                - master
      - beta-ios:
          filters:
            branches:
              only:
                - master
      - release-android:
          requires:
            - build
          filters:
            branches:
              only:
                - master
      - release-ios:
          filters:
            branches:
              only:
                - master
  # nightly-release:
  #   triggers:
  #     - schedule:
  #         cron: "0 7 * * *"
  #         filters:
  #           branches:
  #             only:
  #               - master
  #   jobs:
  #     - test-nightly