version: 2.1

orbs:
  slack: circleci/slack@3.4.2

references:
  images:
    middleman: &MIDDLEMAN_IMAGE docker.mirror.hashicorp.services/hashicorp/middleman-hashicorp:0.3.44

executors:
  go:
    docker:
      - image: docker.mirror.hashicorp.services/cimg/go:1.17.2
    environment:
      CONSUL_VERSION: 1.7.2
      GOMAXPROCS: 4
      GO111MODULE: "on"
      GOPROXY: https://proxy.golang.org/
      TEST_RESULTS_DIR: &TEST_RESULTS_DIR /tmp/test-results
      ARTIFACTS_DIR: &ARTIFACTS_DIR /tmp/artifacts

jobs:
  go-checks:
    executor:
      name: go
    steps:
      - checkout
      - run: go mod verify
      - run: go install honnef.co/go/tools/cmd/staticcheck
      - run: go install github.com/nishanths/exhaustive/...
      - run: make fmtcheck generate staticcheck exhaustive
      - run:
          name: verify no code was generated
          command: |
            if [[ -z $(git status --porcelain) ]]; then
              echo "Git directory is clean."
            else
              echo "Git is dirty. Run `make fmtcheck` and `make generate` locally and commit any formatting fixes or generated code."
              git status --porcelain
              exit 1
            fi
      - run:
          name: verify go.mod and go.sum are correct
          command: |
            go mod tidy
            git diff --quiet && exit 0
            echo "please run 'go mod tidy' to ensure go.mod and go.sum are up to date"
            exit 1
      - run:
          name: verify that our protobuf stubs are up-to-date
          command: |
            make protobuf
            git diff --quiet && exit 0
            echo "Run 'make protobuf' to ensure that the protobuf stubs are up-to-date."
            exit 1

  go-test:
    executor:
      name: go
    environment:
      TF_CONSUL_TEST: 1
    parallelism: 4
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: install consul
          command: |
            curl -sLo consul.zip https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip
            unzip consul.zip
            mkdir -p ~/bin
            mv consul ~/bin
            echo 'export PATH="~/bin:$PATH"'
      - run: mkdir -p $TEST_RESULTS_DIR
      - run:
          name: Run Go Tests
          command: |
            PACKAGE_NAMES=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname)
            echo "Running $(echo $PACKAGE_NAMES | wc -w) packages"
            echo $PACKAGE_NAMES
            gotestsum --format=short-verbose --junitfile $TEST_RESULTS_DIR/gotestsum-report.xml -- -p 2 -cover -coverprofile=cov_$CIRCLE_NODE_INDEX.part $PACKAGE_NAMES

      # save coverage report parts
      - persist_to_workspace:
          root: .
          paths:
            - cov_*.part

      - store_test_results:
          path: *TEST_RESULTS_DIR
      - store_artifacts:
          path: *TEST_RESULTS_DIR

      - slack/status:
          fail_only: true
          only_for_branches: main

  go-test-e2e:
    executor:
      name: go
    environment:
      TF_ACC: 1
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run: mkdir -p $TEST_RESULTS_DIR
      - run:
          name: Run Go E2E Tests
          command: |
            gotestsum --format=short-verbose --junitfile $TEST_RESULTS_DIR/gotestsum-report.xml -- -p 2 -cover -coverprofile=cov_e2e.part ./internal/command/e2etest 

      # save coverage report parts
      - persist_to_workspace:
          root: .
          paths:
            - cov_*.part

      - store_test_results:
          path: *TEST_RESULTS_DIR
      - store_artifacts:
          path: *TEST_RESULTS_DIR

      - slack/status:
          fail_only: true
          only_for_branches: main

  # build all distros
  build-distros: &build-distros
    executor: go
    environment: &build-env
      TF_RELEASE: 1
    steps:
      - run: go get -u github.com/mitchellh/gox # go get gox before detecting go mod
      - checkout
      - run: ./scripts/build.sh
      - run: mkdir -p $ARTIFACTS_DIR
      - run: cp pkg/*.zip /tmp/artifacts
      # save dev build to CircleCI
      - store_artifacts:
          path: *ARTIFACTS_DIR

  # build all amd64 architecture supported OS binaries
  build-amd64:
    <<: *build-distros
    environment:
      <<: *build-env
      XC_OS: "darwin linux windows"
      XC_ARCH: "amd64"

  # build all arm architecture supported OS binaries
  build-arm:
    <<: *build-distros
    environment:
      <<: *build-env
      XC_OS: "linux"
      XC_ARCH: "arm"

  # build all arm64 architecture supported OS binaries
  build-arm64:
    <<: *build-distros
    environment:
      <<: *build-env
      XC_OS: "darwin"
      XC_ARCH: "arm64"

  test-docker-full:
    executor:
      name: go
    steps:
      - checkout
      - setup_remote_docker
      - run:
          name: test docker build for 'full' image
          command: docker build -t test-docker-full .

workflows:
  version: 2
  test:
    jobs:
      - go-checks
      - go-test:
          requires:
            - go-checks
      - go-test-e2e:
          requires:
            - go-checks
      - test-docker-full:
          filters:
            branches:
              only:
                - main
                - /^v\d+\.\d+$/ # v0.11, v0.12, etc.

  build-distros:
    jobs:
      - build-amd64
      - build-arm
      - build-arm64
