version: 2.1
orbs:
  owasp: entur/owasp@0.0.10

executors:
  android:
    parameters:
      resource_class:
        default: large
        type: string
    environment:
      NODE_OPTIONS: --max_old_space_size=12000
      NODE_ENV: production
      BABEL_ENV: production
    docker:
      - image: circleci/android:api-29-node
    working_directory: ~/mattermost-mobile
    resource_class: <<parameters.resource_class>>

  ios:
    environment:
      NODE_OPTIONS: --max_old_space_size=12000
      NODE_ENV: production
      BABEL_ENV: production
    macos:
      xcode: "12.1.0"
    working_directory: ~/mattermost-mobile
    shell: /bin/bash --login -o pipefail

commands:
  checkout-private:
    description: "Checkout the private repo with build env vars"
    steps:
      - add_ssh_keys:
          fingerprints:
            - "59:4d:99:5e:1c:6d:30:36:6d:60:76:88:ff:a7:ab:63"
      - run:
          name: Clone the mobile private repo
          command: git clone git@github.com:mattermost/mattermost-mobile-private.git ~/mattermost-mobile-private

  fastlane-dependencies:
    description: "Get Fastlane dependencies"
    parameters:
      for:
        type: string
    steps:
      - restore_cache:
          name: Restore Fastlane cache
          key: v1-gems-<< parameters.for >>-{{ checksum "fastlane/Gemfile.lock" }}-{{ arch }}
      - run:
          working_directory: fastlane
          name: Download Fastlane dependencies
          command: bundle install --path vendor/bundle
      - save_cache:
          name: Save Fastlane cache
          key: v1-gems-<< parameters.for >>-{{ checksum "fastlane/Gemfile.lock" }}-{{ arch }}
          paths:
            - fastlane/vendor/bundle

  gradle-dependencies:
    description: "Get Gradle dependencies"
    steps:
      - restore_cache:
          name: Restore Gradle cache
          key: v1-gradle-{{ checksum "android/build.gradle" }}-{{ checksum  "android/app/build.gradle" }}
      - run:
          working_directory: android
          name: Download Gradle dependencies
          command: ./gradlew dependencies
      - save_cache:
          name: Save Gradle cache
          paths:
            - ~/.gradle
          key: v1-gradle-{{ checksum "android/build.gradle" }}-{{ checksum  "android/app/build.gradle" }}

  assets:
    description: "Generate app assets"
    steps:
      - restore_cache:
          name: Restore assets cache
          key: v1-assets-{{ checksum "assets/base/config.json" }}-{{ arch }}
      - run:
          name: Generate assets
          command: node ./scripts/generate-assets.js
      - save_cache:
          name: Save assets cache
          key: v1-assets-{{ checksum "assets/base/config.json" }}-{{ arch }}
          paths:
            - dist

  npm-dependencies:
    description: "Get JavaScript dependencies"
    steps:
      - restore_cache:
          name: Restore npm cache
          key: v2-npm-{{ checksum "package.json" }}-{{ arch }}
      - run:
          name: Getting JavaScript dependencies
          command: NODE_ENV=development npm install --ignore-scripts
      - save_cache:
          name: Save npm cache
          key: v2-npm-{{ checksum "package.json" }}-{{ arch }}
          paths:
            - node_modules
      - run:
          name: "Patch dependencies"
          command: npx patch-package

  pods-dependencies:
    description: "Get cocoapods dependencies"
    steps:
      - restore_cache:
          name: Restore cocoapods specs and pods
          key: v1-cocoapods-{{ checksum "ios/Podfile.lock" }}-{{ arch }}
      - run:
          name: iOS gems
          command: npm run ios-gems
      - run:
          name: Getting cocoapods dependencies
          command: npm run pod-install
      - save_cache:
          name: Save cocoapods specs and pods cache
          key: v1-cocoapods-{{ checksum "ios/Podfile.lock" }}-{{ arch }}
          paths:
            - ios/Pods
            - ~/.cocoapods

  build-android:
    description: "Build the android app"
    steps:
      - checkout:
          path: ~/mattermost-mobile
      - checkout-private
      - npm-dependencies
      - assets
      - fastlane-dependencies:
          for: android
      - gradle-dependencies
      - run:
          name: Append Keystore to build Android
          command: |
            cp ~/mattermost-mobile-private/android/${STORE_FILE} android/app/${STORE_FILE}
            echo "" | tee -a android/gradle.properties > /dev/null
            echo MATTERMOST_RELEASE_STORE_FILE=${STORE_FILE} | tee -a android/gradle.properties > /dev/null
            echo ${STORE_ALIAS} | tee -a android/gradle.properties > /dev/null
            echo ${STORE_PASSWORD} | tee -a android/gradle.properties > /dev/null
      - run:
          name: Jetify android libraries
          command: ./node_modules/.bin/jetify
      - run:
          working_directory: fastlane
          name: Run fastlane to build android
          no_output_timeout: 30m
          command: export TERM=xterm && bundle exec fastlane android build

  build-ios:
    description: "Build the iOS app"
    steps:
      - checkout:
          path: ~/mattermost-mobile
      - npm-dependencies
      - pods-dependencies
      - assets
      - fastlane-dependencies:
          for: ios
      - run:
          working_directory: fastlane
          name: Run fastlane to build iOS
          no_output_timeout: 30m
          command: |
            HOMEBREW_NO_AUTO_UPDATE=1 brew install watchman
            export TERM=xterm && bundle exec fastlane ios build

  deploy-to-store:
    description: "Deploy build to store"
    parameters:
      task:
        type: string
      target:
        type: string
      file:
        type: string
    steps:
      - attach_workspace:
          at: ~/
      - run:
          name: <<parameters.task>>
          working_directory: fastlane
          command: bundle exec fastlane <<parameters.target>> deploy file:$HOME/mattermost-mobile/<<parameters.file>>

  persist:
    description: "Persist mattermost-mobile directory"
    steps:
      - persist_to_workspace:
          root: ~/
          paths:
            - mattermost-mobile*

  save:
    description: "Save binaries artifacts"
    parameters:
      filename:
        type: string
    steps:
      - run:
          name: Copying artifacts
          command: |
            mkdir /tmp/artifacts;
            cp ~/mattermost-mobile/<<parameters.filename>> /tmp/artifacts;
      - store_artifacts:
          path: /tmp/artifacts

jobs:
  test:
    working_directory: ~/mattermost-mobile
    docker:
      - image: circleci/node:10
    steps:
      - checkout:
          path: ~/mattermost-mobile
      - npm-dependencies
      - assets
      - run:
          name: Check styles
          command: npm run check
      - run:
          name: Running Tests
          command: npm test
      - run:
          name: Check i18n
          command: ./scripts/precommit/i18n.sh

  check-deps:
    parameters:
      cve_data_directory:
        type: string
        default: "~/.owasp/dependency-check-data"
    working_directory: ~/mattermost-mobile
    executor: owasp/default
    environment:
      version_url: "https://jeremylong.github.io/DependencyCheck/current.txt"
      executable_url: "https://dl.bintray.com/jeremy-long/owasp/dependency-check-VERSION-release.zip"
    steps:
      - checkout
      - restore_cache:
          name: Restore npm cache
          key: v2-npm-{{ checksum "package.json" }}-{{ arch }}
      - run:
          name: Checkout config
          command: cd .. && git clone https://github.com/mattermost/security-automation-config
      - run:
          name: Install Go
          command: sudo apt-get update && sudo apt-get install golang
      - owasp/with_commandline:
          steps:
            # Taken from https://github.com/entur/owasp-orb/blob/master/src/%40orb.yml#L349-L361
            - owasp/generate_cache_keys:
                cache_key: commmandline-default-cache-key-v7
            - owasp/restore_owasp_cache
            - run:
                name: Update OWASP Dependency-Check Database
                command: |
                  if ! ~/.owasp/dependency-check/bin/dependency-check.sh --data << parameters.cve_data_directory >> --updateonly; then
                    # Update failed, probably due to a bad DB version; delete cached DB and try again
                    rm -rv ~/.owasp/dependency-check-data/*.db
                    ~/.owasp/dependency-check/bin/dependency-check.sh --data << parameters.cve_data_directory >> --updateonly
                  fi
            - owasp/store_owasp_cache:
                cve_data_directory: <<parameters.cve_data_directory>>
            - run:
                name: Run OWASP Dependency-Check Analyzer
                command: |
                  ~/.owasp/dependency-check/bin/dependency-check.sh \
                    --data << parameters.cve_data_directory >> --format ALL --noupdate --enableExperimental \
                    --propertyfile ../security-automation-config/dependency-check/dependencycheck.properties \
                    --suppression ../security-automation-config/dependency-check/suppression.xml \
                    --suppression ../security-automation-config/dependency-check/suppression.$CIRCLE_PROJECT_REPONAME.xml \
                    --scan './**/*' || true
            - owasp/collect_reports:
                persist_to_workspace: false
      - run:
          name: Post results to Mattermost
          command: go run ../security-automation-config/dependency-check/post_results.go

  build-android-beta:
    executor: android
    steps:
      - build-android
      - persist
      - save:
          filename: "*.apk"

  build-android-release:
    executor: android
    steps:
      - build-android
      - persist
      - save:
          filename: "*.apk"

  build-android-pr:
    executor: android
    environment:
      BRANCH_TO_BUILD: ${CIRCLE_BRANCH}
    steps:
      - build-android
      - save:
          filename: "*.apk"

  build-android-unsigned:
    executor: android
    steps:
      - checkout:
          path: ~/mattermost-mobile
      - npm-dependencies
      - assets
      - fastlane-dependencies:
          for: android
      - gradle-dependencies
      - run:
          name: Jetify Android libraries
          command: ./node_modules/.bin/jetify
      - run:
          working_directory: fastlane
          name: Run fastlane to build unsigned android
          no_output_timeout: 30m
          command: bundle exec fastlane android unsigned
      - persist
      - save:
          filename: "*.apk"

  build-ios-beta:
    executor: ios
    steps:
      - build-ios
      - persist
      - save:
          filename: "*.ipa"

  build-ios-release:
    executor: ios
    steps:
      - build-ios
      - persist
      - save:
          filename: "*.ipa"

  build-ios-pr:
    executor: ios
    environment:
      BRANCH_TO_BUILD: ${CIRCLE_BRANCH}
    steps:
      - build-ios
      - save:
          filename: "*.ipa"

  build-ios-unsigned:
    executor: ios
    steps:
      - checkout:
          path: ~/mattermost-mobile
      - npm-dependencies
      - pods-dependencies
      - assets
      - fastlane-dependencies:
          for: ios
      - run:
          working_directory: fastlane
          name: Run fastlane to build unsigned iOS
          no_output_timeout: 30m
          command: |
            HOMEBREW_NO_AUTO_UPDATE=1 brew install watchman
            bundle exec fastlane ios unsigned
      - persist_to_workspace:
          root: ~/
          paths:
            - mattermost-mobile/*.ipa
      - save:
          filename: "*.ipa"

  build-ios-simulator:
    executor: ios
    steps:
      - checkout:
          path: ~/mattermost-mobile
      - npm-dependencies
      - pods-dependencies
      - assets
      - fastlane-dependencies:
          for: ios
      - run:
          working_directory: fastlane
          name: Run fastlane to build unsigned x86_64 iOS app for iPhone simulator
          no_output_timeout: 30m
          command: |
            HOMEBREW_NO_AUTO_UPDATE=1 brew install watchman
            bundle exec fastlane ios simulator
      - persist_to_workspace:
          root: ~/
          paths:
            - mattermost-mobile/Mattermost-simulator-x86_64.app.zip
      - save:
          filename: "Mattermost-simulator-x86_64.app.zip"

  deploy-android-release:
    executor:
      name: android
      resource_class: medium
    steps:
      - deploy-to-store:
          task: "Deploy to Google Play"
          target: android
          file: "*.apk"

  deploy-android-beta:
    executor:
      name: android
      resource_class: medium
    steps:
      - deploy-to-store:
          task: "Deploy to Google Play"
          target: android
          file: "*.apk"

  deploy-ios-release:
    executor: ios
    steps:
      - deploy-to-store:
          task: "Deploy to TestFlight"
          target: ios
          file: "*.ipa"

  deploy-ios-beta:
    executor: ios
    steps:
      - deploy-to-store:
          task: "Deploy to TestFlight"
          target: ios
          file: "*.ipa"

  github-release:
    executor:
      name: android
      resource_class: medium
    steps:
      - attach_workspace:
          at: ~/
      - run:
          name: Create GitHub release
          working_directory: fastlane
          command: bundle exec fastlane github

workflows:
  version: 2
  build:
    jobs:
      - test
      # - check-deps:
      #     context: sast-webhook
      #     requires:
      #       - test

      - build-android-release:
          context: mattermost-mobile-android-release
          requires:
            - test
          filters:
            branches:
              only:
                - /^build-\d+$/
                - /^build-android-\d+$/
                - /^build-android-release-\d+$/
      - deploy-android-release:
          context: mattermost-mobile-android-release
          requires:
            - build-android-release
          filters:
            branches:
              only:
                - /^build-\d+$/
                - /^build-android-\d+$/
                - /^build-android-release-\d+$/

      - build-android-beta:
          context: mattermost-mobile-android-beta
          requires:
            - test
          filters:
            branches:
              only:
                - /^build-\d+$/
                - /^build-android-\d+$/
                - /^build-android-beta-\d+$/
      - deploy-android-beta:
          context: mattermost-mobile-android-beta
          requires:
            - build-android-beta
          filters:
            branches:
              only:
                - /^build-\d+$/
                - /^build-android-\d+$/
                - /^build-android-beta-\d+$/

      - build-ios-release:
          context: mattermost-mobile-ios-release
          requires:
            - test
          filters:
            branches:
              only:
                - /^build-\d+$/
                - /^build-ios-\d+$/
                - /^build-ios-release-\d+$/
      - deploy-ios-release:
          context: mattermost-mobile-ios-release
          requires:
            - build-ios-release
          filters:
            branches:
              only:
                - /^build-\d+$/
                - /^build-ios-\d+$/
                - /^build-ios-release-\d+$/

      - build-ios-beta:
          context: mattermost-mobile-ios-beta
          requires:
            - test
          filters:
            branches:
              only:
                - /^build-\d+$/
                - /^build-ios-\d+$/
                - /^build-ios-beta-\d+$/
      - deploy-ios-beta:
          context: mattermost-mobile-ios-beta
          requires:
            - build-ios-beta
          filters:
            branches:
              only:
                - /^build-\d+$/
                - /^build-ios-\d+$/
                - /^build-ios-beta-\d+$/

      - build-android-pr:
          context: mattermost-mobile-android-pr
          requires:
            - test
          filters:
            branches:
              only: /^(build|android)-pr-.*/
      - build-ios-pr:
          context: mattermost-mobile-ios-pr
          requires:
            - test
          filters:
            branches:
              only: /^(build|ios)-pr-.*/

      - build-android-unsigned:
          context: mattermost-mobile-unsigned
          requires:
            - test
          filters:
            tags:
              only: /^v(\d+\.)(\d+\.)(\d+)(.*)?$/
            branches:
              only: unsigned
      - build-ios-unsigned:
          context: mattermost-mobile-unsigned
          requires:
            - test
          filters:
            tags:
              only: /^v(\d+\.)(\d+\.)(\d+)(.*)?$/
            branches:
              only: unsigned
      - build-ios-simulator:
          context: mattermost-mobile-unsigned
          requires:
            - test
          filters:
            branches:
              only:
                - /^build-\d+$/
                - /^build-ios-\d+$/
                - /^build-ios-beta-\d+$/
                
      - github-release:
          context: mattermost-mobile-unsigned
          requires:
            - build-android-unsigned
            - build-ios-unsigned
          filters:
            tags:
              only: /^v(\d+\.)(\d+\.)(\d+)(.*)?$/
            branches:
              only: unsigned
