version: 2.1

parameters:
  check-legacy-node-version:
    type: boolean
    default: false
  legacy-node-version:
    type: string
    default: '14.21.3'
  maintenance-node-version:
    type: string
    default: '16.20'
  active-node-version:
    type: string
    default: '18.17'
  current-node-version:
    type: string
    default: '20.5'

aliases:
  - &restore-cache
    restore_cache:
      key: dependency-cache-{{ checksum "package.json" }}
  - &save-cache
    save_cache:
      key: dependency-cache-{{ checksum "package.json" }}
      paths:
        - ./node_modules
  - &install-deps
    run:
      name: Install dependencies
      command: npm ci --legacy-peer-deps
  - &build-packages
    run:
      name: Build
      command: npm run build
  - &run-unit-tests
    run:
      name: Test
      command: npm run test

jobs:
  build:
    working_directory: ~/nest
    docker:
      - image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
    steps:
      - checkout
      - run:
          name: Update NPM version
          command: 'sudo npm install -g npm@^9'
      - *restore-cache
      - *install-deps
      - *save-cache
      - *build-packages

  test:
    parameters:
      node-version:
        type: string
    working_directory: ~/nest
    docker:
      - image: cimg/node:<< parameters.node-version >>
    steps:
      - when:
          condition:
            and:
              - equal:
                  [
                    '<< parameters.node-version >>',
                    '<< pipeline.parameters.legacy-node-version >>',
                  ]
              - not: << pipeline.parameters.check-legacy-node-version >>
          steps:
            - run:
                name: Skip
                command: |
                  echo Skipping
      - when:
          condition:
            or:
              - not:
                  equal:
                    [
                      '<< parameters.node-version >>',
                      '<< pipeline.parameters.legacy-node-version >>',
                    ]
              - << pipeline.parameters.check-legacy-node-version >>
          steps:
            - checkout
            - *restore-cache
            - *install-deps
            - *build-packages
            - when:
                condition:
                  equal:
                    [
                      '<< parameters.node-version >>',
                      '<< pipeline.parameters.maintenance-node-version >>',
                    ]
                steps:
                  - run:
                      name: Test (coverage)
                      command: npm run test:cov
                  - run:
                      name: Collect coverage
                      command: npm run coverage
                  - store_artifacts:
                      path: coverage
            - when:
                condition:
                  not:
                    equal:
                      [
                        '<< parameters.node-version >>',
                        '<< pipeline.parameters.maintenance-node-version >>',
                      ]
                steps:
                  - *run-unit-tests

  lint:
    working_directory: ~/nest
    docker:
      - image: cimg/node:<< pipeline.parameters.current-node-version >>
    steps:
      - checkout
      - *restore-cache
      - *install-deps
      - run:
          name: Lint
          command: npm run lint

  integration_tests:
    working_directory: ~/nest
    machine: true
    steps:
      - checkout
      - run:
          name: Prepare nvm
          command: |
            echo 'export NVM_DIR="/opt/circleci/.nvm"' >> $BASH_ENV
            echo ' [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV
      - run:
          name: Upgrade Node.js
          command: |
            nvm install << pipeline.parameters.maintenance-node-version >>
            node -v
            nvm alias default << pipeline.parameters.maintenance-node-version >>
      - run:
          name: Install Docker Compose
          command: |
            curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` > ~/docker-compose
            chmod +x ~/docker-compose
            sudo mv ~/docker-compose /usr/local/bin/docker-compose
      - *install-deps
      - run:
          name: Prepare tests
          command: |
            bash ./scripts/prepare.sh
            sleep 10
      - run:
          name: List containers
          command: docker ps
      - run:
          name: Integration tests
          command: npm run test:integration

  codechecks_benchmarks:
    working_directory: ~/nest
    docker:
      - image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
    steps:
      - checkout
      - *restore-cache
      - *install-deps
      - *build-packages
      - run:
          name: Install native wrk
          command: .circleci/install-wrk.sh
      - run:
          name: Run codechecks with benchmarks
          command: yarn codechecks:benchmarks

  samples:
    working_directory: ~/nest
    docker:
      - image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
    environment:
      DISABLE_OPENCOLLECTIVE: 'true'
    steps:
      - checkout
      - *restore-cache
      - *install-deps
      - run:
          name: Build all samples
          command: npm run build:samples

workflows:
  build-and-test:
    jobs:
      - build
      - test:
          requires:
            - build
          matrix:
            parameters:
              node-version:
                [
                  '<< pipeline.parameters.legacy-node-version >>',
                  '<< pipeline.parameters.maintenance-node-version >>',
                  '<< pipeline.parameters.active-node-version >>',
                  '<< pipeline.parameters.current-node-version >>',
                ]
      - lint:
          requires:
            - build
      - integration_tests:
          requires:
            - build
      - samples:
          requires:
            - build
      - codechecks_benchmarks:
          requires:
            - build
