---
version: 2.1
orbs:
  win: circleci/windows@2.2.0

executors:
  besu_executor_med: # 2cpu, 4G ram
    docker:
      - image: circleci/openjdk:11.0.8-jdk-buster
        auth:
          username: $DOCKER_USER_RO
          password: $DOCKER_PASSWORD_RO
    resource_class: medium
    working_directory: ~/project
    environment:
      GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=2

  besu_executor_xl: # 8cpu, 16G ram
    docker:
      - image: circleci/openjdk:11.0.8-jdk-buster
        auth:
          username: $DOCKER_USER_RO
          password: $DOCKER_PASSWORD_RO
    resource_class: xlarge
    working_directory: ~/project
    environment:
      GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=4

notify:
  webhooks:
    - url: $HUBOT_URL

commands:
  prepare:
    description: "Prepare"
    steps:
      - checkout
      - run:
          name: Install Packages - LibSodium
          command: |
            sudo apt-get update
            sudo apt-get install -y libsodium23 libsodium-dev apt-transport-https
      - restore_cache:
          name: Restore cached gradle dependencies
          keys:
            - deps-{{ checksum "gradle/versions.gradle" }}-{{ .Branch }}-{{ .Revision }}
            - deps-{{ checksum "gradle/versions.gradle" }}
            - deps-

  capture_test_results:
    description: "Capture test results"
    steps:
      - run:
          name: Gather test results
          when: always
          command: |
            FILES=`find . -name test-results`
            for FILE in $FILES
            do
              MODULE=`echo "$FILE" | sed -e 's@./\(.*\)/build/test-results@\1@'`
              TARGET="build/test-results/$MODULE"
              mkdir -p "$TARGET"
              cp -rf ${FILE}/*/* "$TARGET"
            done
      - store_test_results:
          path: build/test-results

  capture_test_logs:
    description: "Capture test logs"
    steps:
      - store_artifacts:
          path: acceptance-tests/tests/build/acceptanceTestLogs
          destination: acceptance-tests-logs
      - store_artifacts:
          path: acceptance-tests/tests/build/jvmErrorLogs

jobs:
  assemble:
    executor: besu_executor_xl
    steps:
      - prepare
      - run:
          name: DCO check
          command: |
            ./scripts/dco_check.sh
      - run:
          name: Assemble
          command: |
            ./gradlew --no-daemon clean spotlessCheck compileJava compileTestJava assemble
      - save_cache:
          name: Caching gradle dependencies
          key: deps-{{ checksum "gradle/versions.gradle" }}-{{ .Branch }}-{{ .Revision }}
          paths:
            - .gradle
            - ~/.gradle
      - persist_to_workspace:
          root: ~/project
          paths:
            - ./
      - store_artifacts:
          name: Distribution artifacts
          path:  build/distributions
          destination: distributions
          when: always
  testWindows:
    executor: win/default
    steps:
      - attach_workspace:
          at: ~/project
      - run:
          name: Unzip Windows build
          no_output_timeout: 20m
          command: |
            cd build/distributions
            unzip besu-*.zip -d besu-tmp
            cd besu-tmp
            mv besu-* ../besu
      - run:
          name: Test Besu Windows executable
          no_output_timeout: 10m
          command: |
            build\distributions\besu\bin\besu.bat --help
            build\distributions\besu\bin\besu.bat --version

  unitTests:
    executor: besu_executor_xl
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Build
          no_output_timeout: 20m
          command: |
            ./gradlew --no-daemon build
      - capture_test_results

  integrationTests:
    executor: besu_executor_xl
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: IntegrationTests
          command: |
            ./gradlew --no-daemon integrationTest
      - run:
          name: Javadoc
          command: |
            ./gradlew --no-daemon javadoc
      - run:
          name: CompileJmh
          command: |
            ./gradlew --no-daemon compileJmh
      - capture_test_results

  referenceTests:
    executor: besu_executor_xl
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: ReferenceTests
          no_output_timeout: 20m
          command: |
            git submodule update --init --recursive
            ./gradlew --no-daemon referenceTest
      - capture_test_results

  acceptanceTests:
    parallelism: 8
    executor: besu_executor_xl
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: AcceptanceTests
          no_output_timeout: 40m
          command: |
            CLASSNAMES=$(circleci tests glob "acceptance-tests/tests/src/test/java/**/*.java" \
              | sed 's@.*/src/test/java/@@' \
              | sed 's@/@.@g' \
              | sed 's/.\{5\}$//' \
              | circleci tests split --split-by=timings --timings-type=classname)
            # Format the arguments to "./gradlew test"
            GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}')
            ./gradlew --no-daemon acceptanceTest $GRADLE_ARGS
      - capture_test_results
      - capture_test_logs

  buildDocker:
    executor: besu_executor_med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - setup_remote_docker
      - run:
          name: hadoLint_openjdk_11
          command: |
            docker run --rm -i hadolint/hadolint < docker/openjdk-11/Dockerfile
      - run:
          name: hadoLint_openjdk_latest
          command: |
            docker run --rm -i hadolint/hadolint < docker/openjdk-latest/Dockerfile
      - run:
          name: hadoLint_graalvm
          command: |
            docker run --rm -i hadolint/hadolint < docker/graalvm/Dockerfile
      - run:
          name: build image
          command: |
            ./gradlew --no-daemon distDocker
      - run:
          name: test image
          command: |
            mkdir -p docker/reports
            curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.9/goss-linux-amd64 -o ./docker/tests/goss-linux-amd64
            ./gradlew --no-daemon testDocker

  publish:
    executor: besu_executor_med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Publish
          command: |
            ./gradlew --no-daemon bintrayUpload

  publishDocker:
    executor: besu_executor_med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - setup_remote_docker
      - run:
          name: Publish Docker
          command: |
            docker login --username "${DOCKER_USER_RW}" --password "${DOCKER_PASSWORD_RW}"
            # temporarily commented out because AWS credentials are broken
            # docker login "${ACR_REPO}" --username "${ACR_USER_RW}" --password "${ACR_PASSWORD_RW}"
            ./gradlew --no-daemon "-Pbranch=${CIRCLE_BRANCH}" dockerUpload

workflows:
  version: 2
  default:
    jobs:
      - assemble
      - unitTests:
          requires:
            - assemble
          context:
            - besu-dockerhub-ro
      - testWindows:
          requires:
            - assemble
      - referenceTests:
          requires:
            - assemble
          context:
            - besu-dockerhub-ro            
      - integrationTests:
          requires:
            - assemble
          context:
            - besu-dockerhub-ro            
      - acceptanceTests:
          requires:
            - assemble
          context:
            - besu-dockerhub-ro            
      - buildDocker:
          requires:
            - unitTests
          context:
            - besu-dockerhub-ro            
      - publish:
          filters:
            branches:
              only:
                - master
                - /^release-.*/
          requires:
            - integrationTests
            - unitTests
            - acceptanceTests
            - referenceTests
            - buildDocker
            - buildDocker
          context:
            - besu-dockerhub-ro
      - publishDocker:
          filters:
            branches:
              only:
                - master
                - /^release-.*/
          requires:
            - integrationTests
            - unitTests
            - acceptanceTests
            - referenceTests
            - buildDocker
          context:
            - besu-dockerhub-ro
            - besu-dockerhub-rw
            - besu-acr-rw

