version: 2.1

# --------------------------------
# common : orbs
# --------------------------------

orbs:
  node: circleci/node@4.2.1
  aws-cli: circleci/aws-cli@1.4.0
  ruby: circleci/ruby@1.1.2

# --------------------------------
# common : executors
# --------------------------------

executors:
  node:
    docker:
      - image: circleci/node:14.16.0-stretch
    working_directory: ~/project
  android:
    docker:
      - image: circleci/android:api-29-node
    resource_class: large
    working_directory: ~/project
  ios:
    macos:
      xcode: '12.5.1'
    working_directory: ~/project

# --------------------------------
# common : commands
# --------------------------------

commands:
  audit:
    description: Audit NPM Dependencies
    steps:
      - run:
          name: Audit NPM Dependencies
          command: npm run audit
  test:
    description: Run tests
    steps:
      - run:
          name: Run Tests
          command: npm run _ci:test
  lint:
    description: Lint The Project
    steps:
      - run:
          name: Lint The Project
          command: npm run lint
  bundle:
    description: Bundle The Javascript Code With Specified Platform
    parameters:
      platform:
        type: string
    steps:
      - run:
          name: Bundle << parameters.platform >> js
          command: npm run bundle:<< parameters.platform >>
  install-nvm:
    description: Install NVM
    steps:
      - run:
          name: Install NVM
          command: |
            set +e
            touch $BASH_ENV
            curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.37.2/install.sh | bash
            echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV
            echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV
  setup-node:
    description: Setup the node environment
    steps:
      - node/install:
          npm-version: 6.14.11
          node-version: 14.16.0
      - node/install-packages:
          cache-version: v1-{{ arch }}
  setup-ruby:
    description: Setup Ruby and Install Packages
    steps:
      - ruby/install-deps:
          key: gems-v1-{{ arch }}
  install-cocoapods:
    description: Install Cocoapods
    steps:
      - run:
          name: Install Cocoapods
          command: |
            cd ios
            bundle exec pod install
            cd ..
  ios-set-ruby-version:
    description: Set Ruby Version to 2.6
    steps:
      - run:
          name: 'Set Ruby Version'
          command: echo 'chruby ruby-2.6' >> ~/.bash_profile
  create-app-environment-variables:
    description: 'Create In App Environment'
    parameters:
      stage:
        type: string
    steps:
      - run:
          name: 'In App Environment Variables'
          command: |
            npm run env:<< parameters.stage >>
  android-keystore-environment-variables:
    description: 'Android Keystore Environment Variables'
    parameters:
      stage:
        type: string
    steps:
      - run:
          name: 'Android Keystore Environment Variables'
          command: |
            echo 'export S3_URL=s3://$ANDROID_KEYSTORE_BUCKET/<< parameters.stage >>/' >> $BASH_ENV
            echo 'export KEY_FILE=nonatemplate-<< parameters.stage >>' >> $BASH_ENV
            echo 'export KEY_ALIAS=nonatemplate-<< parameters.stage >>' >> $BASH_ENV
            echo 'export KEY_PASSWORD=$ANDROID_KEYSTORE_PASSWORD' >> $BASH_ENV
            source $BASH_ENV
  android-set-gradle-options:
    description: 'Android Set Gradle Options'
    steps:
      - run:
          name: 'Set Gradle Options And React Native Options For Memory Usage'
          command: |
            echo 'GRADLE_OPTS=-Dkotlin.compiler.execution.strategy=in-process' >> $BASH_ENV
            echo 'REACT_NATIVE_MAX_WORKERS=1' >> $BASH_ENV
  fastlane-deploy:
    description: Fastlane Deploy
    parameters:
      platform:
        type: string
      lane:
        type: string
      stage:
        type: string
    steps:
      - run:
          name: Deploy << parameters.platform >> << parameters.stage >>
          command: |
            cd << parameters.platform >>
            bundle exec fastlane << parameters.lane >>
            cd ..
  store-build-artifacts:
    description: Store Build Artifacts
    parameters:
      platform:
        type: string
    steps:
      - when:
          condition:
            equal: [android, << parameters.platform >>]
          steps:
            - store_artifacts:
                path: android/app/build/outputs/bundle/
                destination: /outputs/
  android-fix-gnupg-permissions:
    description: Fix Ownership of GNUPG Vonfig on Android
    steps:
      - run:
          name: Fix Ownership of GNUPG Vonfig on Android
          command: sudo chown -R circleci:circleci ~/.gnupg
  semantic-release:
    description: Run Semantic Release
    steps:
      - run:
          name: Run Semantic Release
          command: npx semantic-release
  generate-latest-release-notes:
    description: Generate Latest Release Notes
    steps:
      - run:
          name: Generate Latest Release Notes
          command: npm run latest-release-notes:generate

# --------------------------------
# jobs
# --------------------------------

jobs:
  lint-test:
    executor: node
    environment:
      SKIP_POSTINSTALL: 'true'
      HUSKY: '0'
    steps:
      - checkout
      - aws-cli/setup
      - setup-node
      - create-app-environment-variables:
          stage: 'development'
      - audit
      - lint
      - test
      - semantic-release
  bundle:
    executor: node
    environment:
      SKIP_POSTINSTALL: 'true'
      HUSKY: '0'
    parameters:
      platform:
        type: string
    steps:
      - checkout
      - aws-cli/setup
      - setup-node
      - create-app-environment-variables:
          stage: 'development'
      - bundle:
          platform: << parameters.platform >>
  release:
    executor: node
    environment:
      SKIP_POSTINSTALL: 'true'
      HUSKY: '0'
    steps:
      - checkout
      - setup-node
      - semantic-release
  android-deploy:
    description: Builds and deploys Android application to Google Play
    parameters:
      stage:
        description: 'The stage to deploy to'
        default: 'staging'
        type: string
      keystore:
        description: 'The keystore to use'
        default: 'alpha'
        type: string
      fastlane-deploy-lane:
        description: 'The fastlane deploy lane to use'
        default: 'alpha_deploy'
        type: string
    executor: android
    environment:
      HUSKY: '0'
    steps:
      - android-fix-gnupg-permissions
      - checkout
      - aws-cli/setup
      - setup-node
      - setup-ruby
      - generate-latest-release-notes
      - create-app-environment-variables:
          stage: << parameters.stage >>
      - android-set-gradle-options
      - android-keystore-environment-variables:
          stage: << parameters.keystore >>
      - fastlane-deploy:
          platform: 'android'
          stage: << parameters.stage >>
          lane: << parameters.fastlane-deploy-lane >>
      - store-build-artifacts:
          platform: 'android'
  ios-deploy:
    description: Builds and deploys iOS application to Testflight or Appstore
    parameters:
      stage:
        description: 'The stage to deploy to'
        default: 'stagint'
        type: string
      fastlane-deploy-lane:
        description: 'The fastlane deploy lane to use'
        default: 'testflight_deploy'
        type: string
    executor: ios
    environment:
      HUSKY: '0'
    steps:
      - install-nvm
      - checkout
      - aws-cli/setup
      - ios-set-ruby-version
      - setup-node
      - setup-ruby
      - generate-latest-release-notes
      - install-cocoapods
      - create-app-environment-variables:
          stage: << parameters.stage >>
      - fastlane-deploy:
          platform: 'ios'
          stage: << parameters.stage >>
          lane: << parameters.fastlane-deploy-lane >>

# --------------------------------
# workflows
# --------------------------------

workflows:
  version: 2
  push-checks:
    jobs:
      - lint-test:
          filters:
            branches:
              ignore:
                - develop
                - master
      - bundle:
          matrix:
            parameters:
              platform: ['ios', 'android']
          filters:
            branches:
              ignore:
                - develop
                - master
  semantic-release:
    jobs:
      - release:
          filters:
            branches:
              only:
                - develop
  staging-deploy:
    jobs:
      - android-deploy:
          name: android-staging-deploy
          stage: 'staging'
          keystore: 'production'
          fastlane-deploy-lane: 'alpha_deploy'
          # Ignore all branches and only act on new tags
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /^v.*/
      - ios-deploy:
          name: ios-staging-deploy
          stage: 'staging'
          fastlane-deploy-lane: 'testflight_deploy'
          # Ignore all branches and only act on new tags
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /^v.*/
  production-deploy:
    jobs:
      - android-deploy:
          name: android-production-deploy
          stage: 'production'
          keystore: 'production'
          fastlane-deploy-lane: 'production_deploy'
          filters:
            branches:
              only:
                - master
      - ios-deploy:
          name: ios-production-deploy
          stage: 'production'
          fastlane-deploy-lane: 'production_deploy'
          filters:
            branches:
              only:
                - master
