defaults: &defaults
  working_directory: ~/repo

attach_workspace: &attach_workspace
  at: /tmp

test-install-dependencies: &test-install-dependencies
  name: Install dependencies
  command: |
    wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
    echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google.list
    echo "deb http://repo.mongodb.org/apt/debian stretch/mongodb-org/4.0 main" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list
    sudo apt-get update
    sudo apt-get install -y mongodb-org-shell google-chrome-stable

test-run: &test-run
  name: Run Tests
  command: |
    for i in $(seq 1 5); do mongo rocketchat --eval 'db.dropDatabase()' && npm test && s=0 && break || s=$? && sleep 1; done; (exit $s)

test-npm-install: &test-npm-install
  name: NPM install
  command: |
    npm install

test-store_artifacts: &test-store_artifacts
  path: .screenshots/

test-configure-replicaset: &test-configure-replicaset
  name: Configure Replica Set
  command: |
    mongo --eval 'rs.initiate({_id:"rs0", members: [{"_id":1, "host":"localhost:27017"}]})'
    mongo --eval 'rs.status()'

test-restore-npm-cache: &test-restore-npm-cache
  keys:
    - node-modules-cache-{{ checksum ".circleci/config.yml" }}-{{ checksum "package.json" }}

test-save-npm-cache: &test-save-npm-cache
  key: node-modules-cache-{{ checksum ".circleci/config.yml" }}-{{ checksum "package.json" }}
  paths:
    - ./node_modules

test-docker-image: &test-docker-image
  circleci/node:8.16-stretch-browsers

test-with-oplog: &test-with-oplog
  <<: *defaults
  environment:
    TEST_MODE: "true"
    MONGO_URL: mongodb://localhost:27017/rocketchat
    MONGO_OPLOG_URL: mongodb://localhost:27017/local

  steps:
    - attach_workspace: *attach_workspace
    - checkout
    - run: *test-install-dependencies
    - run: *test-configure-replicaset
    - restore_cache: *test-restore-npm-cache
    - run: *test-npm-install
    - run: *test-run
    - save_cache: *test-save-npm-cache
    - store_artifacts: *test-store_artifacts

version: 2
jobs:
  build:
    <<: *defaults
    docker:
      - image: circleci/node:8.16-stretch
      - image: mongo:3.4

    steps:
      - checkout

      - restore_cache:
          keys:
            - node-modules-cache-{{ checksum ".circleci/config.yml" }}-{{ checksum "package.json" }}

      - restore_cache:
          keys:
            - meteor-{{ checksum ".circleci/config.yml" }}-{{ checksum ".meteor/release" }}

      - run:
          name: Install Meteor
          command: |
            # Restore bin from cache
            set +e
            METEOR_SYMLINK_TARGET=$(readlink ~/.meteor/meteor)
            METEOR_TOOL_DIRECTORY=$(dirname "$METEOR_SYMLINK_TARGET")
            set -e
            LAUNCHER=$HOME/.meteor/$METEOR_TOOL_DIRECTORY/scripts/admin/launch-meteor
            if [ -e $LAUNCHER ]
            then
              echo "Cached Meteor bin found, restoring it"
              sudo cp "$LAUNCHER" "/usr/local/bin/meteor"
            else
              echo "No cached Meteor bin found."
            fi

            # only install meteor if bin isn't found
            command -v meteor >/dev/null 2>&1 || curl https://install.meteor.com | sed s/--progress-bar/-sL/g | /bin/sh

      - run:
          name: Versions
          command: |
            npm --versions
            node -v
            meteor --version
            meteor npm --versions
            meteor node -v
            git version

      - run:
          name: Meteor npm install
          command: |
            # rm -rf node_modules
            # rm -f package-lock.json
            meteor npm install

      - run:
          name: Lint
          command: |
            meteor npm run lint

      - run:
          name: Unit Test
          command: |
            MONGO_URL=mongodb://localhost:27017 meteor npm run testunit

      - restore_cache:
          keys:
            - meteor-cache-{{ checksum ".circleci/config.yml" }}-{{ checksum ".meteor/versions" }}

      # To reduce memory need during actual build, build the packages solely first
      - run:
          name: Build a Meteor cache
          command: |
            # to do this we can clear the main files and it build the rest
            echo "" > server/main.js
            echo "" > client/main.js
            meteor build --server-only --debug --directory /tmp/build-temp
            git checkout -- server/main.js client/main.js

      - run:
          name: Build Rocket.Chat
          environment:
            TOOL_NODE_FLAGS: --max_old_space_size=4096
          command: |
            if [[ $CIRCLE_TAG ]] || [[ $CIRCLE_BRANCH == 'develop' ]]; then
              meteor reset;
            fi

            export CIRCLE_PR_NUMBER="${CIRCLE_PR_NUMBER:-${CIRCLE_PULL_REQUEST##*/}}"
            if [[ -z $CIRCLE_PR_NUMBER ]]; then
              meteor build --server-only --directory /tmp/build-test
            else
              export METEOR_PROFILE=1000
              meteor build --server-only --directory --debug /tmp/build-test
            fi;

      - run:
          name: Prepare build
          command: |
            mkdir /tmp/build/
            cd /tmp/build-test
            tar czf /tmp/build/Rocket.Chat.tar.gz bundle
            cd /tmp/build-test/bundle/programs/server
            npm install

      - save_cache:
          key: node-modules-cache-{{ checksum ".circleci/config.yml" }}-{{ checksum "package.json" }}
          paths:
            - ./node_modules

      - save_cache:
          key: meteor-cache-{{ checksum ".circleci/config.yml" }}-{{ checksum ".meteor/versions" }}
          paths:
            - ./.meteor/local

      - save_cache:
          key: meteor-{{ checksum ".circleci/config.yml" }}-{{ checksum ".meteor/release" }}
          paths:
            - ~/.meteor

      - persist_to_workspace:
          root: /tmp/
          paths:
            - build-test
            - build

      - store_artifacts:
          path: /tmp/build


  test-with-oplog-mongo-3-4:
    <<: *test-with-oplog
    docker:
      - image: *test-docker-image
      - image: mongo:3.4
        command: [mongod, --noprealloc, --smallfiles, --replSet=rs0]

  test-with-oplog-mongo-3-6:
    <<: *test-with-oplog
    docker:
      - image: *test-docker-image
      - image: mongo:3.6
        command: [mongod, --noprealloc, --smallfiles, --replSet=rs0]

  test-with-oplog-mongo-4-0:
    <<: *test-with-oplog
    docker:
      - image: *test-docker-image
      - image: mongo:4.0
        command: [mongod, --noprealloc, --smallfiles, --replSet=rs0]

  deploy:
    <<: *defaults
    docker:
      - image: circleci/node:8.16-stretch

    steps:
      - attach_workspace:
          at: /tmp

      - checkout

      - run:
          name: Install AWS cli
          command: |
            if [[ $CIRCLE_PULL_REQUESTS ]]; then exit 0; fi;

            sudo apt-get -y -qq update
            sudo apt-get -y -qq install python3.5-dev
            curl -O https://bootstrap.pypa.io/get-pip.py
            python3.5 get-pip.py --user
            export PATH=~/.local/bin:$PATH
            pip install awscli --upgrade --user

      - run:
          name: Publish assets
          command: |
            if [[ $CIRCLE_PULL_REQUESTS ]]; then exit 0; fi;

            export PATH=~/.local/bin:$PATH
            export CIRCLE_TAG=${CIRCLE_TAG:=}

            aws s3 cp s3://rocketchat/sign.key.gpg .circleci/sign.key.gpg

            source .circleci/setartname.sh
            source .circleci/setdeploydir.sh
            bash .circleci/setupsig.sh
            bash .circleci/namefiles.sh

            aws s3 cp $ROCKET_DEPLOY_DIR/ s3://download.rocket.chat/build/ --recursive

            bash .circleci/update-releases.sh
            bash .circleci/snap.sh
            bash .circleci/redhat-registry.sh

  image-build:
    <<: *defaults

    docker:
      - image: docker:17.05.0-ce-git

    steps:
      - attach_workspace:
          at: /tmp

      - checkout

      - setup_remote_docker

      - run:
          name: Build Docker image
          command: |
            cd /tmp/build
            tar xzf Rocket.Chat.tar.gz
            rm Rocket.Chat.tar.gz

            export CIRCLE_TAG=${CIRCLE_TAG:=}
            if [[ $CIRCLE_TAG ]]; then
              docker login -u $DOCKER_USER -p $DOCKER_PASS

              echo "Build official Docker image"
              cp ~/repo/.docker/Dockerfile .
              docker build -t rocketchat/rocket.chat:$CIRCLE_TAG .
              docker push rocketchat/rocket.chat:$CIRCLE_TAG

              echo "Build preview Docker image"
              cp ~/repo/.docker-mongo/Dockerfile .
              cp ~/repo/.docker-mongo/entrypoint.sh .
              docker build -t rocketchat/rocket.chat.preview:$CIRCLE_TAG .
              docker push rocketchat/rocket.chat.preview:$CIRCLE_TAG

              if echo "$CIRCLE_TAG" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' ; then
                docker tag rocketchat/rocket.chat:$CIRCLE_TAG rocketchat/rocket.chat:latest
                docker push rocketchat/rocket.chat:latest

                docker tag rocketchat/rocket.chat.preview:$CIRCLE_TAG rocketchat/rocket.chat.preview:latest
                docker push rocketchat/rocket.chat.preview:latest
              elif echo "$CIRCLE_TAG" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$' ; then
                docker tag rocketchat/rocket.chat:$CIRCLE_TAG rocketchat/rocket.chat:release-candidate
                docker push rocketchat/rocket.chat:release-candidate

                docker tag rocketchat/rocket.chat.preview:$CIRCLE_TAG rocketchat/rocket.chat.preview:release-candidate
                docker push rocketchat/rocket.chat.preview:release-candidate
              fi

              exit 0
            fi;

            if [[ $CIRCLE_BRANCH == 'develop' ]]; then
              docker login -u $DOCKER_USER -p $DOCKER_PASS

              echo "Build official Docker image"
              cp ~/repo/.docker/Dockerfile .
              docker build -t rocketchat/rocket.chat:develop .
              docker push rocketchat/rocket.chat:develop

              echo "Build preview Docker image"
              cp ~/repo/.docker-mongo/Dockerfile .
              cp ~/repo/.docker-mongo/entrypoint.sh .
              docker build -t rocketchat/rocket.chat.preview:develop .
              docker push rocketchat/rocket.chat.preview:develop

              exit 0
            fi;

  pr-build:
    <<: *defaults
    docker:
      - image: circleci/node:8.16-stretch

    steps:
      - checkout

      - restore_cache:
          keys:
            - node-modules-cache-{{ checksum ".circleci/config.yml" }}-{{ checksum "package.json" }}

      - restore_cache:
          keys:
            - meteor-{{ checksum ".circleci/config.yml" }}-{{ checksum ".meteor/release" }}

      - run:
          name: Install Meteor
          command: |
            # Restore bin from cache
            set +e
            METEOR_SYMLINK_TARGET=$(readlink ~/.meteor/meteor)
            METEOR_TOOL_DIRECTORY=$(dirname "$METEOR_SYMLINK_TARGET")
            set -e
            LAUNCHER=$HOME/.meteor/$METEOR_TOOL_DIRECTORY/scripts/admin/launch-meteor
            if [ -e $LAUNCHER ]
            then
              echo "Cached Meteor bin found, restoring it"
              sudo cp "$LAUNCHER" "/usr/local/bin/meteor"
            else
              echo "No cached Meteor bin found."
            fi

            # only install meteor if bin isn't found
            command -v meteor >/dev/null 2>&1 || curl https://install.meteor.com | sed s/--progress-bar/-sL/g | /bin/sh

      - run:
          name: Versions
          command: |
            npm --versions
            node -v
            meteor --version
            meteor npm --versions
            meteor node -v
            git version

      - run:
          name: Meteor npm install
          command: |
            # rm -rf node_modules
            # rm -f package-lock.json
            meteor npm install

      - restore_cache:
          keys:
            - meteor-cache-{{ checksum ".circleci/config.yml" }}-{{ checksum ".meteor/versions" }

      - run:
          name: Build Rocket.Chat
          environment:
            TOOL_NODE_FLAGS: --max_old_space_size=3072
          command: |
            meteor build --server-only /tmp/build-pr


      - persist_to_workspace:
          root: /tmp/
          paths:
            - build-pr

      - store_artifacts:
          path: /tmp/build-pr

  pr-image-build:
    <<: *defaults

    docker:
      - image: docker:17.05.0-ce-git

    steps:
      - attach_workspace:
          at: /tmp

      - checkout

      - setup_remote_docker

      - run:
          name: Build Docker image for PRs
          command: |
            export CIRCLE_PR_NUMBER="${CIRCLE_PR_NUMBER:-${CIRCLE_PULL_REQUEST##*/}}"
            if [[ -z $CIRCLE_PR_NUMBER ]]; then
              exit 0
            fi;

            cd /tmp/build-pr
            tar xzf repo.tar.gz
            rm repo.tar.gz

            docker login -u $DOCKER_USER -p $DOCKER_PASS

            echo "Build official Docker image"
            cp ~/repo/.docker/Dockerfile .
            docker build -t rocketchat/rocket.chat:pr-$CIRCLE_PR_NUMBER .
            docker push rocketchat/rocket.chat:pr-$CIRCLE_PR_NUMBER

            #echo "Build preview Docker image"
            #cp ~/repo/.docker-mongo/Dockerfile .
            #cp ~/repo/.docker-mongo/entrypoint.sh .
            #docker build -t rocketchat/rocket.chat.preview:pr-$CIRCLE_PR_NUMBER .
            #docker push rocketchat/rocket.chat.preview:pr-$CIRCLE_PR_NUMBER

workflows:
  version: 2
  build-and-test:
    jobs:
      - hold-all:
        type: approval
        filters:
          branches:
            only: develop
          tags:
            only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
      - build:
          requires:
            - hold-all
          filters:
            tags:
              only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
      - test-with-oplog-mongo-3-4: &test-mongo
          requires:
            - build
          filters:
            tags:
              only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
      - test-with-oplog-mongo-3-6: &test-mongo-no-pr
          requires:
            - build
          filters:
            branches:
              only: develop
            tags:
              only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
      - test-with-oplog-mongo-4-0: *test-mongo
      - deploy:
          requires:
            - test-with-oplog-mongo-3-4
            - test-with-oplog-mongo-3-6
            - test-with-oplog-mongo-4-0
          filters:
            branches:
              only: develop
            tags:
              only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
      - image-build:
          requires:
            - deploy
          filters:
            branches:
              only: develop
            tags:
              only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
      - hold:
          type: approval
          requires:
            - build
          filters:
            branches:
              ignore: develop
            tags:
              only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
      - pr-build:
          requires:
            - hold
          filters:
            branches:
              ignore: develop
            tags:
              only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
      - pr-image-build:
          requires:
            - pr-build
          filters:
            branches:
              ignore: develop
            tags:
              only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
