---
version: 2.1

executors:
  node_executor:
    docker:
      - image: circleci/node:14-buster
  docker_tests_executor:
    machine:
      image: ubuntu-1604:202004-01 #Ubuntu 16.04, docker 19.03.8, docker-compose 1.25.5
      docker_layer_caching: true
    resource_class: xlarge

commands:
  prepare_docker_machine:
    description: "checkout, install all packages required by Ubuntu Docker machines and handle cache"
    steps:
      - checkout
      - restore_cache:
          keys:
            - node-cache-{{ checksum "package-lock.json" }}
            - node-cache-
      - run:
          name: install base packages
          command: |
            sudo apt-get update
            sudo apt-get install -y git python make gcc g++ bash curl
      - run:
          name: install node
          command: |
            curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
            export NVM_DIR="/opt/circleci/.nvm"
            [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
            nvm install node
      - run:
          name: install node packages
          command: npm ci
      - save_cache:
          paths:
            - ~/.npm
          key: node-cache-{{ checksum "package-lock.json" }}

  prepare_node:
    description: "checkout, install all packages and handle cache"
    steps:
      - checkout
      - restore_cache:
          keys:
            - node-cache-{{ checksum "package-lock.json" }}
            - node-cache-
      - run:
          name: install packages
          command: npm ci
      - save_cache:
          paths:
            - ~/.npm
          key: node-cache-{{ checksum "package-lock.json" }}
jobs:
  lintCheck:
    executor: node_executor
    steps:
      - prepare_node
      - run:
          name: Check linting
          command: npm run lint
  unitTests:
    executor: node_executor
    steps:
      - prepare_node
      - run:
          name: Run unit tests
          command: npm run test:unit
  mockTests:
    executor: node_executor
    steps:
      - prepare_node
      - run:
          name: Run mock tests
          command: npm run test:mock

  integrationTests:
    executor: docker_tests_executor
    steps:
      - prepare_docker_machine
      - run:
          name: Integration tests
          command: npm run test:integration

  onChainTests:
    executor: docker_tests_executor
    steps:
      - prepare_docker_machine
      - run:
          name: On chain tests
          command: npm run test:onchain

  generateDoc:
    executor: node_executor
    steps:
    - prepare_node
    - run:
        name: build doc
        command: npm run generate:doc
    - run:
        name: archive doc
        command: tar -czf web3js-quorum-sdk-doc.tgz ./docs/out/web3js-quorum
    - store_artifacts:
        path: ./web3js-quorum-sdk-doc.tgz
    - run:
        name: organize doc dirs
        command: node .circleci/organise_doc.js --rootdir=$(pwd) --tag="${CIRCLE_TAG}"
    - persist_to_workspace:
        root: ~/project
        paths:
          - ./docs

  publishDoc:
    executor: node_executor
    steps:
    - checkout
    - attach_workspace:
        at: /tmp/workspace
    - add_ssh_keys:
        fingerprints:
          - '6e:8b:ba:78:6d:4a:91:49:29:8a:31:10:03:8b:7f:10'
    - run:
        name: Set Git user params
        command: |
          git config --global user.name $CIRCLE_USERNAME
          git config --global user.email "${CIRCLE_USERNAME}@users.noreply.github.com"
    - deploy:
        name: Commit and push docs changes
        command: |
          # publishing happens by pushing files to gh-pages branch
          # retrieve branch to publish to from CIrcle CI env vars and fallback on test-gh-pages
          # if no var defined
          [ -n "$BRANCH_OVERRIDE" ] && readonly BRANCH="$BRANCH_OVERRIDE" || readonly BRANCH='test-gh-pages'

          # switch to the publishing branch
          git checkout "$BRANCH"

          # copy the content of the docs folder built on the previous job and attached
          # using workspace on temp location
          # cp with T option to override existing content, specially usefull for latest
          cp -aT /tmp/workspace/docs/. .

          # add a readme to make sure devs understand that this publishing branch is generated
          # by CI (use template readme), mv replaces the current readme that is only for source dir
          mv TARGET_README.md README.md

          # add all new copied content of the workspace to git
          git add .

          # commit with infos on the triggering task and branch
          # use [skip ci] to prevent CI from runnning on this branch as no CI is configured
          git commit -m "Automated SDK documentation update" \
                     -m "[ci skip] Circle CI build ${CIRCLE_BUILD_NUM}, see ${CIRCLE_BUILD_URL}" \
                     -m "Branch: ${CIRCLE_BRANCH}, commit: ${CIRCLE_SHA1}, tag:${CIRCLE_TAG-none}"

          # push changes to the Github Pages publishing branch on origin repos
          git push --set-upstream origin $BRANCH
          git push origin

  publishNPM:
    executor: node_executor
    steps:
      - prepare_node
      - deploy:
          name: Publish package on NPM
          command: |
            echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}'>.npmrc
            npm publish --access public
  draftRelease:
    executor: node_executor
    steps:
      - prepare_node
      - deploy:
          name: Draft release notes
          command: |
            git fetch -q --depth=1 origin +refs/tags/*:refs/tags/*
            file="generated-release-notes.md"
            last_version=$(git describe --abbrev=0 --tags $(git rev-list --tags --skip=1 --max-count=1))
            last_release_date=$(git log -1 --format=%cd --date=short $last_version)
            echo "Last version: $last_version on $last_release_date"
            # pulling from git logs
            curl -q -s -H "Accept: application/vnd.github.v3+json" \
              "https://api.github.com/search/issues?q=repo:ConsenSys/web3js-quorum+is:pr+is:merged+merged%3A>=$last_release_date+sort%3Aupdated-desc" | jq -r '"* " + (.items[]|.title + " #" + (.number|tostring))' \
              >>$file
            content=$(cat $file)
            # escape newline and double quote
            content="${content//$'\n'/' \n'}"
            content="${content//$'"'/'\"'}"
            data='{
                "tag_name":"'$CIRCLE_TAG'",
                "name":"'$CIRCLE_TAG'",
                "body":"'${content}'",
                "draft":true
                }'
            curl -X POST \
              -H "Accept: application/vnd.github.v3+json" \
              -H "Authorization: token ${GITHUB_TOKEN}" \
              https://api.github.com/repos/ConsenSys/web3js-quorum/releases \
              -d "$data"
workflows:
  version: 2
  workflow:
    jobs:
      - lintCheck: 
          filters:
            tags:
              only: /^v.*/
            branches:
              only: /.*/
      - unitTests:
          requires:
            - lintCheck 
          filters:
            tags:
              only: /^v.*/
            branches:
              only: /.*/
      - mockTests:
          requires:
            - lintCheck 
          filters:
            tags:
              only: /^v.*/
            branches:
              only: /.*/
      - integrationTests:
          filters:
            tags:
              only: /^v.*/
            branches:
              only: /.*/
      - onChainTests:
          filters:
            tags:
              only: /^v.*/
            branches:
              only: /.*/
      - generateDoc:
          filters:
            tags:
              only: /^v.*/
            branches:
              only: /.*/
      - publishDoc:
          requires:
            - unitTests
            - mockTests
            - integrationTests
            - onChainTests
            - generateDoc
          filters:
            branches:
              only: master
            tags:
              only: /.*/
      - publishNPM:
          requires:
            - unitTests
            - mockTests
            - integrationTests
            - onChainTests
            - generateDoc
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /^v.*/
      - draftRelease:
          requires:
            - unitTests
            - mockTests
            - integrationTests
            - onChainTests
            - generateDoc
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /^v.*/
