version: 2.1

executors:
  golang:
    docker:
      - image: circleci/golang:1.13
  docs:
    docker:
      - image: tendermintdev/docker-website-deployment
    environment:
      AWS_REGION: us-east-1
  protoc:
    docker:
      - image: tendermintdev/docker-protoc

commands:
  make:
    parameters:
      description:
        type: string
      target:
        type: string
    steps:
      - attach_workspace:
          at: /tmp/workspace
      - restore_cache:
          name: "Restore source code cache"
          keys:
            - go-src-v1-{{ .Revision }}
      - checkout
      - restore_cache:
          name: "Restore go modules cache"
          keys:
            - go-mod-v2-{{ checksum "go.sum" }}
      - run:
          name: << parameters.description >>
          command: |
            make << parameters.target >>

jobs:
  build-docs:
    executor: docs
    steps:
      - checkout
      - run:
          name: "Build docs"
          command: make build-docs
      - run:
          name: "Upload docs to S3"
          command: make sync-docs

  setup-dependencies:
    executor: golang
    steps:
      - checkout
      - restore_cache:
          name: "Restore go modules cache"
          keys:
            - go-mod-v2-{{ checksum "go.sum" }}
      - run:
          name: Cache go modules
          command: make go-mod-cache
      - run:
          name: Build
          command: make build
      - run:
          name: Git garbage collection
          command: git gc
      - save_cache:
          name: "Save go modules cache"
          key: go-mod-v2-{{ checksum "go.sum" }}
          paths:
            - "/go/pkg/mod"
      - save_cache:
          name: "Save source code cache"
          key: go-src-v1-{{ .Revision }}
          paths:
            - ".git"
  proto:
    executor: protoc
    steps:
      - make:
          target: protoc-gen-gocosmos
          description: "Generate go plugin for protoc"
      - make:
          target: proto-gen proto-lint proto-check-breaking
          description: "Lint and verify Protocol Buffer definitions"

  test-sim-nondeterminism:
    executor: golang
    steps:
      - make:
          target: test-sim-nondeterminism
          description: "Test individual module simulations"

  test-sim-import-export:
    executor: golang
    steps:
      - make:
          target: test-sim-import-export
          description: "Test application import/export simulation"

  test-sim-after-import:
    executor: golang
    steps:
      - make:
          target: test-sim-after-import
          description: "Test simulation after import"

  test-sim-multi-seed-long:
    executor: golang
    steps:
      - make:
          target: test-sim-multi-seed-long
          description: "Test multi-seed simulation (long)"

  test-sim-multi-seed-short:
    executor: golang
    steps:
      - make:
          target: test-sim-multi-seed-short
          description: "Test multi-seed simulation (short)"

  test-cover:
    executor: golang
    parallelism: 4
    steps:
      - checkout
      - restore_cache:
          keys:
            - go-mod-v2-{{ checksum "go.sum" }}
      - run:
          name: Run tests
          command: |
            export VERSION="$(git describe --tags --long | sed 's/v\(.*\)/\1/')"
            export GO111MODULE=on
            mkdir -p /tmp/logs /tmp/workspace/profiles
            for pkg in $(go list ./... | grep -v '/simulation' | circleci tests split); do
              id=$(echo "$pkg" | sed 's|[/.]|_|g')
              go test -mod=readonly -timeout 8m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic -tags='ledger test_ledger_mock' "$pkg" | tee "/tmp/logs/$id-$RANDOM.log"
            done
      - persist_to_workspace:
          root: /tmp/workspace
          paths:
            - "profiles/*"
      - store_artifacts:
          path: /tmp/logs

  upload-coverage:
    executor: golang
    steps:
      - attach_workspace:
          at: /tmp/workspace
      - checkout
      - run:
          name: gather
          command: |
            echo "--> Concatenating profiles:"
            ls /tmp/workspace/profiles/
            echo "mode: atomic" > coverage.txt
            for prof in $(ls /tmp/workspace/profiles/); do
              tail -n +2 /tmp/workspace/profiles/"$prof" >> coverage.txt
            done
      - run:
          name: filter out DONTCOVER
          command: |
            excludelist="$(find ./ -type f -name '*.go' | xargs grep -l 'DONTCOVER')"
            for filename in ${excludelist}; do
              filename=$(echo $filename | sed 's/^./github.com\/cosmos\/cosmos-sdk/g')
              echo "Excluding ${filename} from coverage report..."
              sed -i.bak "/$(echo $filename | sed 's/\//\\\//g')/d" coverage.txt
            done
      - run:
          name: upload
          command: bash <(curl -s https://codecov.io/bash) -f coverage.txt

  update-swagger-docs:
    executor: golang
    steps:
      - make:
          target: update-swagger-docs
          description: "Check if statik.go is up-to-date"

workflows:
  version: 2
  test-suite:
    jobs:
      - update-swagger-docs:
          requires:
            - setup-dependencies
      - setup-dependencies:
          # This filter enables the job for tags
          filters:
            tags:
              only:
                - /^v.*/
      - proto:
          requires:
            - setup-dependencies                       
      - test-sim-nondeterminism:
          requires:
            - setup-dependencies
      - test-sim-import-export:
          requires:
            - setup-dependencies
      - test-sim-after-import:
          requires:
            - setup-dependencies
      - test-sim-multi-seed-short:
          requires:
            - setup-dependencies
      - test-sim-multi-seed-long:
          requires:
            - setup-dependencies
          # These filters ensure that the long sim only runs during release
          filters:
            branches:
              ignore: /.*/
            tags:
              only:
                - /^v.*/
      - test-cover:
          requires:
            - setup-dependencies
      - upload-coverage:
          requires:
            - test-cover
      - build-docs:
          context: docs-deployment-master
          filters:
            branches:
              only:
                - docs-theme-latest
      - build-docs:
          context: docs-deployment-release
          filters:
            branches:
              only:
                - master
            tags:
              only:
                - /v.*/
