description: run go tests parameters: extra_flags: type: string default: "" log_dir: type: string default: "/tmp/testlogs" cache_dir: type: string default: /tmp/go-cache save_cache: type: boolean default: false go_image: type: string default: "docker.mirror.hashicorp.services/circleci/golang:1.16.7-buster" use_docker: type: boolean default: false arch: type: string # Only supported for use_docker=false, and only other value allowed is 386 default: amd64 # must be 386 or amd64 steps: - configure-git - run: name: Compute test cache key command: | TZ=GMT date '+%Y%m%d' > /tmp/go-cache-key - restore_cache: keys: - go-test-cache-date-v1-{{ checksum "/tmp/go-cache-key" }} - restore_go_mod_cache - run: name: Run Go tests no_output_timeout: 60m environment: GOPRIVATE: 'github.com/hashicorp/*' command: | set -x EXTRA_TAGS= case "<< parameters.extra_flags >>" in *-race*) export VAULT_CI_GO_TEST_RACE=1;; *) EXTRA_TAGS=deadlock;; esac # Install CircleCI CLI curl -sSL \ "https://github.com/CircleCI-Public/circleci-cli/releases/download/v${CIRCLECI_CLI_VERSION}/circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64.tar.gz" \ | sudo tar --overwrite -xz \ -C /usr/local/bin \ "circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64/circleci" USE_DOCKER=0 <<# parameters.use_docker >> USE_DOCKER=1 <> # Check all directories with a go.mod file modules=("." "api" "sdk") all_package_names="" for dir in "${modules[@]}" do pushd "$dir" # Split Go tests by prior test times. If use_docker is true, only run # tests that depend on docker, otherwise only those that don't. # The appended true condition ensures the command will succeed if no packages are found if [ $USE_DOCKER == 1 ]; then package_names=$(go list -test -json ./... | jq -r 'select(.Deps != null) | select(any(.Deps[] ; contains("github.com/hashicorp/vault/helper/testhelpers/docker"))) | .ForTest | select(. != null)' | sort -u | grep -v vault/integ | circleci tests split --split-by=timings --timings-type=classname) || true else package_names=$(go list -test -json ./... | jq -r 'select(.Deps != null) | select(all(.Deps[] ; contains("github.com/hashicorp/vault/helper/testhelpers/docker")|not)) | .ForTest | select(. != null)' | sort -u | grep -v vault/integ | circleci tests split --split-by=timings --timings-type=classname) || true fi # Move back into root directory popd # Append the test packages into the global list, if any are found if [ -n "$package_names" ]; then all_package_names+=" ${package_names}" fi done # After running tests split step, we are now running the following steps # in multiple different containers, each getting a different subset of # the test packages in their package_names variable. Each container # has its own remote docker VM. make prep mkdir -p test-results/go-test # We don't want VAULT_LICENSE set when running Go tests, because that's # not what developers have in their environments and it could break some # tests; it would be like setting VAULT_TOKEN. However some non-Go # CI commands, like the UI tests, shouldn't have to worry about licensing. # So we set VAULT_LICENSE in CI, and here we unset it. Instead of # VAULT_LICENSE, we populate VAULT_LICENSE_CI, so that tests which want # an externally supplied license can opt-in to using it. export VAULT_LICENSE_CI="$VAULT_LICENSE" VAULT_LICENSE= # Create a docker network for our testcontainer if [ $USE_DOCKER == 1 ]; then # Despite the fact that we're using a circleci image (thus getting the # version they chose for the docker cli) and that we're specifying a # docker version to use for the remote docker instances, we occasionally # see "client version too new, max supported version 1.39" errors for # reasons unclear. export DOCKER_API_VERSION=1.39 export TEST_DOCKER_NETWORK_ID=$(docker network list -q -f 'name=vaulttest') if [ -z $TEST_DOCKER_NETWORK_ID ]; then TEST_DOCKER_NETWORK_ID=$(docker network create vaulttest) fi # Start a docker testcontainer to run the tests in docker run -d \ -e TEST_DOCKER_NETWORK_ID \ -e GOPRIVATE \ -e DOCKER_CERT_PATH \ -e DOCKER_HOST \ -e DOCKER_MACHINE_NAME \ -e DOCKER_TLS_VERIFY \ -e NO_PROXY \ -e VAULT_TEST_LOG_DIR=<< parameters.log_dir >> \ --network vaulttest --name \ testcontainer << parameters.go_image >> \ tail -f /dev/null # Run tests test -d << parameters.cache_dir >> && docker cp << parameters.cache_dir >> testcontainer:/tmp/gocache docker exec testcontainer sh -c 'mkdir -p /go/src/github.com/hashicorp/vault' docker cp . testcontainer:/go/src/github.com/hashicorp/vault/ docker cp $DOCKER_CERT_PATH/ testcontainer:$DOCKER_CERT_PATH # Copy the downloaded modules inside the container. docker exec testcontainer sh -c 'mkdir -p /go/pkg' docker cp "$(go env GOPATH)/pkg/mod" testcontainer:/go/pkg/mod docker exec -w /go/src/github.com/hashicorp/vault/ \ -e CIRCLECI -e VAULT_CI_GO_TEST_RACE \ -e GOCACHE=/tmp/gocache \ -e GO_TAGS \ -e GOPROXY="off" \ -e VAULT_LICENSE_CI \ -e GOARCH=<< parameters.arch >> \ testcontainer \ gotestsum --format=short-verbose \ --junitfile test-results/go-test/results.xml \ --jsonfile test-results/go-test/results.json \ -- \ -tags "${GO_TAGS} ${EXTRA_TAGS}" \ -timeout=60m \ -parallel=20 \ << parameters.extra_flags >> \ ${all_package_names} else GOARCH=<< parameters.arch >> \ GOCACHE=<< parameters.cache_dir >> \ gotestsum --format=short-verbose \ --junitfile test-results/go-test/results.xml \ --jsonfile test-results/go-test/results.json \ -- \ -tags "${GO_TAGS} ${EXTRA_TAGS}" \ -timeout=60m \ -parallel=20 \ << parameters.extra_flags >> \ ${all_package_names} fi - when: condition: << parameters.use_docker >> steps: - run: name: Copy test results when: always command: | docker cp testcontainer:/go/src/github.com/hashicorp/vault/test-results . docker cp testcontainer:/tmp/gocache << parameters.cache_dir >> - when: condition: << parameters.save_cache >> steps: - save_cache: when: always key: go-test-cache-date-v1-{{ checksum "/tmp/go-cache-key" }} paths: - << parameters.cache_dir >>