version: 2

main_steps: &main_steps
  steps:
    - checkout

    - run:
        name: Install dependencies
        command: npm ci
        environment:
          # https://docs.cypress.io/guides/getting-started/installing-cypress.html#Skipping-installation
          # We don't need to install the Cypress binary in jobs that aren't actually running Cypress.
          CYPRESS_INSTALL_BINARY: 0

    - run:
        name: Linter
        when: always
        command: npm run lint

    - run:
        name: Core tests
        when: always
        environment:
          mocha_reporter: mocha-junit-reporter
          MOCHA_FILE: junit/core/results.xml
        command: npm run test:core

    - run:
        name: Entrypoint tests
        when: always
        environment:
          mocha_reporter: mocha-junit-reporter
          MOCHA_FILE: junit/entrypoint/results.xml
        command: npm run test:entrypoint

    - store_test_results:
        path: junit

    - run:
        name: 'Prettier check (quick fix: `npm run prettier`)'
        when: always
        command: npm run prettier:check

integration_steps: &integration_steps
  steps:
    - checkout

    - run:
        name: Install dependencies
        command: npm ci
        environment:
          CYPRESS_INSTALL_BINARY: 0

    - run:
        name: Integration tests
        when: always
        environment:
          mocha_reporter: mocha-junit-reporter
          MOCHA_FILE: junit/integration/results.xml
        command: npm run test:integration

    - store_test_results:
        path: junit

services_steps: &services_steps
  steps:
    - checkout

    - run:
        name: Install dependencies
        command: npm ci
        environment:
          CYPRESS_INSTALL_BINARY: 0

    - run:
        name: Identify services tagged in the PR title
        command: npm run test:services:pr:prepare

    - run:
        name: Run tests for tagged services
        environment:
          mocha_reporter: mocha-junit-reporter
          MOCHA_FILE: junit/services/results.xml
        command: RETRY_COUNT=3 npm run test:services:pr:run

    - store_test_results:
        path: junit

package_steps: &package_steps
  steps:
    - checkout

    - run:
        name: Install node and npm
        command: |
          set +e
          export NVM_DIR="/opt/circleci/.nvm"
          [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
          nvm install v12
          nvm use v12
          npm install -g npm

    # Run the package tests on each currently supported node version. See:
    # https://github.com/badges/shields/blob/master/badge-maker/README.md#node-version-support
    # https://nodejs.org/en/about/releases/

    - run:
        environment:
          mocha_reporter: mocha-junit-reporter
          MOCHA_FILE: junit/badge-maker/v10/results.xml
          NODE_VERSION: v10
          CYPRESS_INSTALL_BINARY: 0
        name: Run package tests on Node 10
        command: scripts/run_package_tests.sh

    - run:
        environment:
          mocha_reporter: mocha-junit-reporter
          MOCHA_FILE: junit/badge-maker/v12/results.xml
          NODE_VERSION: v12
          CYPRESS_INSTALL_BINARY: 0
        name: Run package tests on Node 12
        command: scripts/run_package_tests.sh

    - run:
        environment:
          mocha_reporter: mocha-junit-reporter
          MOCHA_FILE: junit/badge-maker/v14/results.xml
          NODE_VERSION: v14
          CYPRESS_INSTALL_BINARY: 0
        name: Run package tests on Node 14
        command: scripts/run_package_tests.sh

    - store_test_results:
        path: junit

jobs:
  main:
    docker:
      - image: circleci/node:12

    <<: *main_steps

  main@node-14:
    docker:
      - image: circleci/node:14

    <<: *main_steps

  integration:
    docker:
      - image: circleci/node:12
      - image: redis

    <<: *integration_steps

  integration@node-14:
    docker:
      - image: circleci/node:14
      - image: redis

    <<: *integration_steps

  danger:
    docker:
      - image: circleci/node:12
    steps:
      - checkout

      - run:
          name: Install dependencies
          command: npm ci
          environment:
            CYPRESS_INSTALL_BINARY: 0

      - run:
          name: Danger
          when: always
          environment:
            # https://github.com/gatsbyjs/gatsby/pull/11555
            NODE_ENV: test
          command: npm run danger ci

  frontend:
    docker:
      - image: circleci/node:12
    steps:
      - checkout

      - run:
          name: Install dependencies
          command: npm ci
          environment:
            CYPRESS_INSTALL_BINARY: 0

      - run:
          name: Prepare frontend tests
          command: npm run defs && npm run features

      - run:
          name: Check types
          command: npm run check-types:frontend

      - run:
          name: Frontend unit tests
          environment:
            mocha_reporter: mocha-junit-reporter
            MOCHA_FILE: junit/frontend/results.xml
          when: always
          command: npm run test:frontend

      - store_test_results:
          path: junit

      - run:
          name: Frontend build completes successfully
          when: always
          command: npm run build

  package:
    machine: true

    <<: *package_steps

  services:
    docker:
      - image: circleci/node:12

    <<: *services_steps

  services@node-14:
    docker:
      - image: circleci/node:14

    <<: *services_steps

  e2e:
    docker:
      - image: cypress/base:12
    steps:
      - checkout

      - restore_cache:
          name: Restore Cypress binary
          keys:
            - v2-cypress-dependencies-{{ checksum "package-lock.json" }}

      - run:
          name: Install dependencies
          command: npm ci

      - run:
          name: Frontend build
          command: GATSBY_BASE_URL=http://localhost:8080 npm run build

      - run:
          name: Run tests
          environment:
            CYPRESS_REPORTER: junit
            MOCHA_FILE: junit/e2e/results.xml
          command: npm run e2e-on-build

      - store_test_results:
          path: junit

      - store_artifacts:
          path: cypress/videos

      - store_artifacts:
          path: cypress/screenshots

      - save_cache:
          name: Cache Cypress binary
          paths:
            # https://docs.cypress.io/guides/getting-started/installing-cypress.html#Binary-cache
            - ~/.cache/Cypress
          key: v2-cypress-dependencies-{{ checksum "package-lock.json" }}

workflows:
  version: 2

  on-commit:
    jobs:
      - main:
          filters:
            branches:
              ignore: gh-pages
      - main@node-14:
          filters:
            branches:
              ignore: gh-pages
      - integration@node-14:
          filters:
            branches:
              ignore: gh-pages
      - frontend:
          filters:
            branches:
              ignore: gh-pages
      - package:
          filters:
            branches:
              ignore: gh-pages
      - services:
          filters:
            branches:
              ignore:
                - master
                - gh-pages
      - services@node-14:
          filters:
            branches:
              ignore:
                - master
                - gh-pages
      - danger:
          filters:
            branches:
              ignore:
                - master
                - gh-pages
                - /dependabot\/.*/
      - e2e:
          filters:
            branches:
              ignore: gh-pages
  # on-commit-with-cache:
  #   jobs:
  #     - npm-install:
  #         filters:
  #           branches:
  #             ignore: gh-pages
  #     - main:
  #         requires:
  #           - npm-install
  #     - main@node-latest:
  #         requires:
  #           - npm-install
  #     - frontend:
  #         requires:
  #           - npm-install
  #     - services:
  #         requires:
  #           - npm-install
  #         filters:
  #           branches:
  #             ignore: master
  #     - services@node-latest:
  #         requires:
  #           - npm-install
  #         filters:
  #           branches:
  #             ignore: master
  #     - danger:
  #         requires:
  #           - npm-install
  #         filters:
  #           branches:
  #             ignore: /dependabot\/.*/
