From 86214a85e1c5553618b8f83592b3548e6b0aeb1f Mon Sep 17 00:00:00 2001 From: Timothy Messier Date: Thu, 23 Feb 2023 14:58:40 -0500 Subject: [PATCH] ci: Run go tests in github action (#2997) This runs the make targets: - make test - make test-api - make test-sdk The go tests in the main module are split by package and run in parallel in a matrix build with GOMAXPROCS=1. This is done primarily to work around an issue that is only seen on the github runners. When running at a higher GOMAXPROCS tests that use vault instances in docker containers start to intermitently fail with errors from vault, usually either a 400, 403, or TLS error. It is not clear what the cause of this is, since the same tests run fine on self hosted runners and on CircleCI. Co-authored-by: Sarah Thompson Co-authored-by: Daniel Kimsey --- .github/scripts/set-test-package-matrix.sh | 7 + .github/workflows/test.yml | 190 +++++++++++++++++++++ Makefile | 11 +- scripts/build.sh | 2 +- 4 files changed, 207 insertions(+), 3 deletions(-) create mode 100755 .github/scripts/set-test-package-matrix.sh create mode 100644 .github/workflows/test.yml diff --git a/.github/scripts/set-test-package-matrix.sh b/.github/scripts/set-test-package-matrix.sh new file mode 100755 index 0000000000..ce98487537 --- /dev/null +++ b/.github/scripts/set-test-package-matrix.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail + +# set matrix var to list of unique packages containing tests +matrix="$(go list -json="ImportPath,TestGoFiles" ./... | jq --compact-output '. | select(.TestGoFiles != null) | .ImportPath' | jq --slurp --compact-output '.')" + +echo "matrix=${matrix}" | tee -a "${GITHUB_OUTPUT}" \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000..a2046b7e82 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,190 @@ +name: test + +on: + - workflow_dispatch + - push + - workflow_call + +permissions: + contents: read + +jobs: + setup: + outputs: + go-version: ${{ steps.get-go-version.outputs.go-version }} + cache-go-build: ${{ steps.go-cache-paths.outputs.go-build }} + cache-go-mod: ${{ steps.go-cache-paths.outputs.go-mod }} + cache-go-bin: ${{ steps.go-cache-paths.outputs.go-bin }} + go-cache-key: ${{ steps.go-cache-key.outputs.key }} + plugin-cache-path: ${{ steps.plugin-cache-paths.outputs.path }} + plugin-cache-key: ${{ steps.plugin-cache-key.outputs.key }} + runs-on: ${{ fromJSON(vars.RUNNER) }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: '0' + - name: Determine Go version + id: get-go-version + # We use .go-version as our source of truth for current Go + # version, because "goenv" can react to it automatically. + run: | + echo "Building with Go $(cat .go-version)" + echo "go-version=$(cat .go-version)" >> $GITHUB_OUTPUT + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: "${{ steps.get-go-version.outputs.go-version }}" + - name: Determine go cache key + id: go-cache-key + run: | + echo "key=${{ runner.os }}-go-${{ hashFiles('**/go.sum', './Makefile', './tools/tools.go') }}" >> $GITHUB_OUTPUT + - name: Determine Go cache paths + id: go-cache-paths + run: | + echo "go-build=$(go env GOCACHE)" >> $GITHUB_OUTPUT + echo "go-mod=$(go env GOMODCACHE)" >> $GITHUB_OUTPUT + echo "go-bin=$(go env GOPATH)/bin" >> $GITHUB_OUTPUT + - name: Set up Go modules cache + uses: actions/cache@v3 + with: + path: | + ${{ steps.go-cache-paths.outputs.go-build }} + ${{ steps.go-cache-paths.outputs.go-mod }} + ${{ steps.go-cache-paths.outputs.go-bin }} + key: ${{ steps.go-cache-key.outputs.key }} + restore-keys: | + ${{ runner.os }}-go + - name: Install Tools + run: | + go mod download + make tools + - name: Determine plugin cache key + id: plugin-cache-key + run: | + echo "key=${{ runner.os }}-plugins-${{ hashFiles('plugins/**/*.go', 'plugins/**/go.sum', './Makefile', './scripts/plugins.sh') }}" >> $GITHUB_OUTPUT + - name: Determin plugin cache path + id: plugin-cache-paths + run: | + echo "path=plugins/**/assets/*.gz" >> $GITHUB_OUTPUT + - name: Set up plugin cache + id: plugin-cache + uses: actions/cache@v3 + with: + path: | + ${{ steps.plugin-cache-paths.outputs.path }} + key: ${{ steps.plugin-cache-key.outputs.key }} + restore-keys: | + ${{ runner.os }}-plugin + - name: Build Plugins + if: steps.plugin-cache.outputs.cache-hit != 'true' + run: | + make build-plugins + test-modules: + needs: + - setup + runs-on: ${{ fromJSON(vars.RUNNER) }} + strategy: + matrix: + module: ["api", "sdk"] + steps: + - uses: actions/checkout@v3 + - name: Set up go + uses: actions/setup-go@v3 + with: + go-version: "${{ needs.setup.outputs.go-version }}" + - name: Set up Go modules cache + uses: actions/cache@v3 + with: + path: | + ${{ needs.setup.outputs.cache-go-build }} + ${{ needs.setup.outputs.cache-go-mod }} + ${{ needs.setup.outputs.cache-go-bin }} + key: ${{ needs.setup.outputs.go-cache-key }} + restore-keys: | + ${{ runner.os }}-go + - name: Test ${{ matrix.module }} Module + run: | + make test-${{ matrix.module }} + + set-test-package-matrix: + runs-on: ${{ fromJSON(vars.RUNNER) }} + needs: + - setup + outputs: + package-matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v3 + - name: Set up go + uses: actions/setup-go@v3 + with: + go-version: "${{ needs.setup.outputs.go-version }}" + - name: Set up Go modules cache + uses: actions/cache@v3 + with: + path: | + ${{ needs.setup.outputs.cache-go-build }} + ${{ needs.setup.outputs.cache-go-mod }} + ${{ needs.setup.outputs.cache-go-bin }} + key: ${{ needs.setup.outputs.go-cache-key }} + restore-keys: | + ${{ runner.os }}-go + - id: set-matrix + run: ./.github/scripts/set-test-package-matrix.sh + + test: + needs: + - setup + - set-test-package-matrix + runs-on: ${{ fromJSON(vars.RUNNER) }} + strategy: + fail-fast: false + matrix: + package: ${{ fromJson(needs.set-test-package-matrix.outputs.package-matrix) }} + steps: + - name: ulimit + run: | + echo "Soft limits" + ulimit -Sa + echo "Hard limits" + ulimit -Ha + - uses: actions/checkout@v3 + - name: Set up go + uses: actions/setup-go@v3 + with: + go-version: "${{ needs.setup.outputs.go-version }}" + - name: Set up Go modules cache + uses: actions/cache@v3 + with: + path: | + ${{ needs.setup.outputs.cache-go-build }} + ${{ needs.setup.outputs.cache-go-mod }} + ${{ needs.setup.outputs.cache-go-bin }} + key: ${{ needs.setup.outputs.go-cache-key }} + restore-keys: | + ${{ runner.os }}-go + - name: Set up plugin cache + id: plugin-cache + uses: actions/cache@v3 + with: + path: | + ${{ needs.setup.outputs.plugin-cache-path }} + key: ${{ needs.setup.outputs.plugin-cache-key }} + restore-keys: | + ${{ runner.os }}-plugin + - name: Initialize Test Database + run: | + which pg_isready || sudo apt-get update && sudo apt-get install -y postgresql-client + make DOCKER_ARGS='-d' PG_OPTS='-c shared_buffers=256MB -c max_connections=200000' -C testing/dbtest/docker database-up + until pg_isready -h 127.0.0.1; do docker container inspect boundary-sql-tests &> /dev/null || exit -1; sleep 1; done + - name: Test + env: + TEST_PACKAGE: "${{ matrix.package }}" + GOMAXPROCS: ${{ vars.TEST_GOMAXPROCS }} + TESTARGS: -v + TEST_TIMEOUT: 120m + run: | + make test + - name: Cleanup + if: always() + run: | + make -C testing/dbtest/docker clean diff --git a/Makefile b/Makefile index 1626c0f8a3..25021217fd 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,9 @@ THIS_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) TMP_DIR := $(shell mktemp -d) REPO_PATH := github.com/hashicorp/boundary +TEST_PACKAGE ?= ./... +TEST_TIMEOUT ?= 30m + CGO_ENABLED?=0 GO_PATH = $(shell go env GOPATH) @@ -115,6 +118,10 @@ build-ui: fi; \ ./scripts/build-ui.sh +.PHONY: build-plugins +build-plugins: + @CGO_ENABLED=$(CGO_ENABLED) BUILD_TAGS='$(BUILD_TAGS)' sh -c "'$(CURDIR)/scripts/plugins.sh'" + .PHONY: clean-ui clean-ui: rm -rf ${UI_CLONE_DIR} @@ -283,7 +290,7 @@ generate-database-dumps: test-ci: export CI_BUILD=1 test-ci: CGO_ENABLED=$(CGO_ENABLED) BUILD_TAGS='$(BUILD_TAGS)' sh -c "'$(CURDIR)/scripts/build.sh'" - ~/.go/bin/go test ./... -v $(TESTARGS) -json -cover -timeout 120m | tparse -follow + go test "$(TEST_PACKAGE)" -v $(TESTARGS) -json -cover -timeout 120m | tparse -follow .PHONY: test-sql test-sql: @@ -291,7 +298,7 @@ test-sql: .PHONY: test test: - go test ./... -timeout 30m -json -cover | tparse -follow + go test "$(TEST_PACKAGE)" $(TESTARGS) -json -cover -timeout $(TEST_TIMEOUT) | tparse -follow .PHONY: test-sdk test-sdk: diff --git a/scripts/build.sh b/scripts/build.sh index d8601b538c..a4d4bd7ae7 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -17,7 +17,7 @@ DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" cd "$DIR" if [ "${CI_BUILD}x" != "x" ]; then - source /home/circleci/.bashrc + [[ -f /home/circleci/.bashrc ]] && source /home/circleci/.bashrc fi # Set build tags