# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
defaults: &defaults
  working_directory: /tmp/repo
  docker:
    # specify the version you desire here
    - image: circleci/node:15.2.1-browsers
  resource_class: large

run_e2e_and_save_artifacts: &run_e2e_and_save_artifacts
  steps:
    #    - run:
    #        name: "Install yarn at specific version"
    #        command:
    #          sudo npm install --global yarn@1.22.4
    - attach_workspace:
        at: /tmp/
    - run:
        name: "Spin up frontend over ssl if necessary and run end to end tests"
        command: |
          sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev & \
          yarn serveDist & \
          cd end-to-end-test && \
          yarn install --frozen-lockfile && \
          ../scripts/env_vars.sh && \
          eval "$(../scripts/env_vars.sh)" && \
          curl $CBIOPORTAL_URL > /dev/null && \
          sleep 5s && \
          curl $CBIOPORTAL_URL > /dev/null && \
          sleep 5s && \
          curl $CBIOPORTAL_URL > /dev/null && \
          sleep 20s && \
          (curl --insecure https://localhost:3000 || curl http://localhost:3000) > /dev/null && \
          sleep 1s && \
          echo "CBIOPORTAL_URL=$CBIOPORTAL_URL"
          yarn run test-webdriver-manager-remote
        when: always
        environment:
          FRONTEND_TEST_USE_LOCAL_DIST: true
          WEBPACK_PARALLEL: false
    - run:
        name: "Make sure all screenshots are tracked (otherwise the test will always be successful)"
        command: 'for f in end-to-end-test/remote/screenshots/reference/*.png; do git ls-files --error-unmatch $f > /dev/null 2> /dev/null || (echo -e "\033[0;31m $f not tracked \033[0m" && touch screenshots_not_tracked); done; ls screenshots_not_tracked > /dev/null 2> /dev/null && exit 1 || exit 0'
    -  store_artifacts:
         path: /tmp/repo/end-to-end-test/remote/screenshots
         destination: /screenshots
    -  store_artifacts:
         path: /tmp/repo/end-to-end-test/shared/image-compare
         destination: /image-compare
    -  store_artifacts:
         path: /tmp/repo/end-to-end-test/remote/error
         destination: /errorShots
    - store_test_results:
        path: /tmp/repo/end-to-end-test/remote/junit
    - store_artifacts:
        path: /tmp/repo/end-to-end-test/remote/junit
    - store_artifacts:
        path: /tmp/repo/end-to-end-test/shared/imageCompare.html
        destination: /imageCompare.html
    - store_artifacts:
        path: /tmp/repo/end-to-end-test/remote/junit/customReport.json
        destination: /customReport.json
    - store_artifacts:
        path: /tmp/repo/end-to-end-test/remote/junit/errors
        destination: /errors

version: 2
jobs:
  install:
    <<: *defaults
    steps:
      #      - run:
      #          name: "Install yarn at specific version"
      #          command:
      #            sudo npm install --global yarn@1.22.4
      - run:
          name: "Show yarn and node versions"
          command: |
            node --version
            yarn --version
      - checkout
      # cache build artifacts. Use concatenation of all source files as cache
      # key. If there are no changes to src/ and yarn.lock, no need to rebuild
      - run:
          name: "Concatenate all source files to use as hash key for caching dist folder"
          command: "cat yarn.lock $(find src/ -type f | sort) $(find packages/ -type f | sort) webpack.config.js vendor-bundles.webpack.config.js > has_source_changed"
      - restore_cache:
          keys:
            - v8-dependencies-plus-dist-{{ checksum "has_source_changed" }}
            - v8-dependencies-{{ checksum "yarn.lock" }}
      # Download and cache dependencies
      - run: yarn
      - run: yarn buildModules
      #- run:
      #    name: "Make sure lock file is still the same"
      #    command: 'git diff --exit-code yarn.lock > /dev/null || (echo -e "New package lock file at $(cat yarn.lock | curl -F c=@- https://ptpb.pw | grep url) (include this file in your PR to fix this test)"; git diff --exit-code yarn.lock; exit 1)'
      - save_cache:
          paths:
            - node_modules
          key: v8-dependencies-{{ checksum "yarn.lock" }}
      - run:
          name: "Run build if no dist folder"
          command: 'ls dist || yarn run build'
          environment:
            DISABLE_SOURCEMAP: true
            NO_PARALLEL: true
          no_output_timeout: 25m
      - run: cd /tmp/repo/end-to-end-test && (ls node_modules || yarn install --frozen-lockfile)
      - save_cache:
          paths:
            - node_modules
            - dist
            - common-dist
          key: v8-dependencies-plus-dist-{{ checksum "has_source_changed" }}
      - persist_to_workspace:
          root: /tmp
          paths:
            - repo

  api_sync:
    <<: *defaults
    steps:
      - attach_workspace:
          at: /tmp/
      # check that all api responses are still the same
      - run: "bash src/test/check_api_sync.sh"

  unit_tests_main:
    <<: *defaults
    steps:
      #      - run:
      #          name: "Install yarn at specific version"
      #          command:
      #            sudo npm install --global yarn@1.22.4
      - attach_workspace:
          at: /tmp/
      # run tests!
      - run:
          command: "yarn run testMain"
          environment:
            JEST_JUNIT_OUTPUT_DIR: ./junit/unit/main/
            JEST_JUNIT_OUTPUT_NAME: test-results-unit-main.xml
            NODE_OPTIONS: --max-old-space-size=4096
            DISABLE_SOURCEMAP: true
            WEBPACK_PARALLEL: false
          when: always
      - store_test_results:
          path: ./junit/unit/main/

  unit_tests_packages:
    <<: *defaults
    steps:
      #      - run:
      #          name: "Install yarn at specific version"
      #          command:
      #            sudo npm install --global yarn@1.22.4
      - attach_workspace:
          at: /tmp/
      # run tests!
      - run:
          command: "yarn run testPackagesCI"
          environment:
            DISABLE_SOURCEMAP: true
            NODE_OPTIONS: --max-old-space-size=4096
            WEBPACK_PARALLEL: false
          when: always
      - store_test_results:
          path: /tmp/junit/module/

  check_forgotten_spec_only_statements:
    <<: *defaults
    steps:
      - attach_workspace:
          at: /tmp/
      # check that no `.only` statements are still in the tests
      # Ignore doTest.only in oql parser
      - run:
          name: "Check Forgotten `.only` Statements"
          command: "! grep '\\.only' $(find ./src ./end-to-end-test -type f -name '*spec*' | grep -v node_modules) | grep -v 'doTest.only = function' | grep -v expectedParsedResult"

  check_incorrect_import_statements:
    <<: *defaults
    steps:
      - attach_workspace:
          at: /tmp/
      # make sure that there are no relative/incorrect package imports
      - run:
          name: "Check Incorrect Package Import Statements"
          command: yarn run checkIncorrectImportStatements

  end_to_end_tests:
    <<: *defaults
    environment:
      SPEC_FILE_PATTERN: ./remote/specs/**/*.spec.js
      JUNIT_REPORT_PATH: ./remote/junit/
      SCREENSHOT_DIRECTORY: ./remote/screenshots
    <<: *run_e2e_and_save_artifacts

  end_to_end_tests_against_master:
    <<: *defaults
    environment:
      SPEC_FILE_PATTERN: ./remote/specs/**/*.spec.js
      JUNIT_REPORT_PATH: ./remote/junit/
      SCREENSHOT_DIRECTORY: ./remote/screenshots
      CBIOPORTAL_URL: https://master.cbioportal.org
    <<: *run_e2e_and_save_artifacts

  end_to_end_tests_localdb:
    working_directory: /tmp/repo
    machine:
      enabled: true
      image: ubuntu-2004:202201-02
    resource_class: large
    steps:
      - attach_workspace:
          at: /tmp/
#      - run:
#          # needed to get python3 on the path (https://discuss.circleci.com/t/pyenv-pyvenv-command-not-found/4087/2)
#          name: Add python3 to path [corrects bug in circle ci image and may be removed in the future]
#          command: pyenv local 3.6.5 && virtualenv venv
      - run:
          name: Setup python libraries
          command: |
            pip3 install requests pyyaml
      #      - run:
      #          name: Install canvas deps [for screenshot comparison]
      #          command: |
      #              sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev
      - run:
          name: Install dependencies
          command: |
            sudo apt-get update && \
            sudo apt-get install jq unzip
      - run:
          name: Setup e2e-environment
          command: |
            source $PORTAL_SOURCE_DIR/env/custom.sh || true && \
            cd $TEST_HOME/runtime-config && \
            ./setup_environment.sh && ./setup_environment.sh >> $BASH_ENV
      - run:
          name: Check build whether custom backend is needed
          command: |
            echo "$CUSTOM_BACKEND" > /tmp/repo/custom_backend_switch
      - restore_cache:
          # when custom_backend_switch file has '1' a custom backend
          # is used and the more extended set of maven repo's will be attached
          keys:
            - maven-repo-v1-{{ checksum "custom_backend_switch" }}
      - run:
          name: Build custom backend
          command: |
            grep -q 0 /tmp/repo/custom_backend_switch || $TEST_HOME/docker_compose/build.sh
          no_output_timeout: 25m
      - save_cache:
          paths:
            - ~/.m2
          key: maven-repo-v1-{{ checksum "custom_backend_switch" }}
      - run:
          name: Setup docker compose assets
          command: |
            $TEST_HOME/docker_compose/setup.sh
          no_output_timeout: 25m
      - run:
          name: Generate checksum of data that populates the test database
          command: |
            $TEST_HOME/runtime-config/db_content_fingerprint.sh > /tmp/db_data_md5key
          no_output_timeout: 25m
      - run:
          name: Create MySQL data directory
          command: |
            docker volume rm --force cbioportal-docker-compose_cbioportal_mysql_data && mkdir -p $CBIO_DB_DATA_DIR && rm -rf $CBIO_DB_DATA_DIR/*
      - restore_cache:
          keys:
            - v8-cbio-database-files-{{ checksum "/tmp/db_data_md5key" }}
      - restore_cache:
          keys:
            - v8-keycloak-database-files-{{ checksum "e2e-localdb-workspace/keycloak/keycloak-config-generated.json" }}
      - run:
          name: Init database
          command: |
            cd $TEST_HOME/docker_compose && echo $CBIO_DB_DATA_DIR && ls -la $CBIO_DB_DATA_DIR && \
            [ "$(ls -A $CBIO_DB_DATA_DIR)" ] && echo "DB initialization is not needed." || ./initdb.sh
      - run:
          name: Change owner of MySQL database files (needed by cache)
          command: |
            sudo chmod -R 777 $CBIO_DB_DATA_DIR && \
            sudo chown -R circleci:circleci $CBIO_DB_DATA_DIR
      - save_cache:
          paths:
            - /tmp/repo/e2e-localdb-workspace/cbio_db_data
          key: v9-cbio-database-files-{{ checksum "/tmp/db_data_md5key" }}
      - run:
          name: Start cbioportal and other services
          command: |
            $TEST_HOME/docker_compose/start.sh
      - run:
          name: Change owner of keycloak MySQL database files (needed by cache)
          command: |
            if (ls "$KC_DB_DATA_DIR"/* 2> /dev/null > /dev/null); then \
                sudo chmod -R 777 $KC_DB_DATA_DIR && \
                sudo chown -R circleci:circleci $KC_DB_DATA_DIR; \
            fi
      - save_cache:
          paths:
            - /tmp/repo/e2e-localdb-workspace/kc_db_data
          key: v9-keycloak-database-files-{{ checksum "e2e-localdb-workspace/keycloak/keycloak-config-generated.json" }}
      - run:
          name: Run end-2-end tests with studies in local database
          command: |
            cd $PORTAL_SOURCE_DIR && \
            $TEST_HOME/docker_compose/test.sh
      - run:
          name: "Make sure all screenshots are tracked (otherwise the test will always be successful)"
          command: 'for f in $TEST_HOME/screenshots/reference/*.png; do git ls-files --error-unmatch $f > /dev/null 2> /dev/null || (echo -e "\033[0;31m $f not tracked \033[0m" && touch screenshots_not_tracked); done; ls screenshots_not_tracked > /dev/null 2> /dev/null && exit 1 || exit 0'
      -  store_artifacts:
           path: /tmp/repo/end-to-end-test/local/screenshots
           destination: /screenshots
      -  store_artifacts:
           path: /tmp/repo/end-to-end-test/shared/image-compare
           destination: /image-compare
      -  store_artifacts:
           path: /tmp/repo/end-to-end-test/local/errorShots
           destination: /errorShots
      - store_test_results:
          path: /tmp/repo/end-to-end-test/local/junit
      - store_artifacts:
          path: /tmp/repo/end-to-end-test/local/junit
      - store_artifacts:
          path: /tmp/repo/end-to-end-test/shared/imageCompare.html
          destination: /imageCompare.html
      - store_artifacts:
          path: /tmp/repo/end-to-end-test/local/junit/customReport.json
          destination: /customReport.json
      - store_artifacts:
          path: /tmp/repo/end-to-end-test/remote/junit/errors
          destination: /errors

    environment:
      PORTAL_SOURCE_DIR: /tmp/repo
      TEST_HOME: /tmp/repo/end-to-end-test/local
      E2E_WORKSPACE: /tmp/repo/e2e-localdb-workspace
      CBIO_DB_DATA_DIR: /tmp/repo/e2e-localdb-workspace/cbio_db_data
      KC_DB_DATA_DIR: /tmp/repo/e2e-localdb-workspace/kc_db_data

  prettier:
    <<: *defaults
    steps:
      - attach_workspace:
          at: /tmp/
      - run:
          name: 'Check code style with Prettier'
          command: cd /tmp/repo/ && yarn run prettierCheckCircleCI

workflows:
  version: 2
  install_and_test:
    jobs:
      - install
      - prettier:
          requires:
            - install
          filters:
            branches:
              ignore:
                - master
                - release-*
 #               - rc
      - unit_tests_main:
          requires:
            - install
      - unit_tests_packages:
            requires:
              - install
      - end_to_end_tests:
          requires:
            - install
      - end_to_end_tests_localdb:
          requires:
            - install
      - api_sync:
          requires:
            - install
      - check_forgotten_spec_only_statements:
          requires:
            - install
      - check_incorrect_import_statements:
          requires:
            - install
  nightly:
    triggers:
      - schedule:
          cron: "0 22 * * *"
          filters:
            branches:
              only:
                - master
#                - rc
    jobs:
      - install
      - api_sync:
          requires:
            - install
      - unit_tests_main:
          requires:
            - install
      - unit_tests_packages:
          requires:
            - install
      - end_to_end_tests:
          requires:
            - install
      - end_to_end_tests_against_master:
          requires:
            - install
      - end_to_end_tests_localdb:
          requires:
            - install
