From c6dc789e25083d841d8035641a170878f831d726 Mon Sep 17 00:00:00 2001 From: Derek Nola Date: Mon, 8 May 2023 12:46:51 -0700 Subject: [PATCH] Add support for `-cover` + integration test code coverage (#7415) * Add support for -cover in k3s server * Update codecov reporting * Sigterm in StopK3sServer Signed-off-by: Derek Nola --- .github/workflows/build-k3s.yaml | 2 +- .github/workflows/integration.yaml | 14 ++++++++++++- .github/workflows/unitcoverage.yaml | 2 +- Dockerfile.dapper | 2 +- pkg/server/cover.go | 32 +++++++++++++++++++++++++++++ pkg/server/no_cover.go | 7 +++++++ pkg/server/server.go | 2 +- scripts/build | 8 ++++++-- tests/integration/integration.go | 9 ++++++-- 9 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 pkg/server/cover.go create mode 100644 pkg/server/no_cover.go diff --git a/.github/workflows/build-k3s.yaml b/.github/workflows/build-k3s.yaml index 9233b782ec..95891af49c 100644 --- a/.github/workflows/build-k3s.yaml +++ b/.github/workflows/build-k3s.yaml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v3 - name: Build K3s binary run: | - DOCKER_BUILDKIT=1 SKIP_AIRGAP=1 SKIP_VALIDATE=1 make + DOCKER_BUILDKIT=1 SKIP_AIRGAP=1 SKIP_VALIDATE=1 GOCOVER=1 make - name: bundle repo if: inputs.upload-repo == true diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index a6196d62d1..1d3199ba57 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -22,6 +22,9 @@ on: permissions: contents: read + +env: + GOCOVERDIR: /tmp/k3scov jobs: build: @@ -53,8 +56,17 @@ jobs: - name: Run Integration Tests run: | chmod +x ./dist/artifacts/k3s - sudo -E env "PATH=$PATH" go test -v ./tests/integration/... -run Integration + mkdir -p $GOCOVERDIR + sudo -E env "PATH=$PATH" go test -v -timeout=30m ./tests/integration/... -run Integration - name: On Failure, Launch Debug Session if: ${{ failure() }} uses: mxschmitt/action-tmate@v3 timeout-minutes: 5 + - name: Generate coverage report + run: go tool covdata textfmt -i $GOCOVERDIR -o coverage.out + - name: Upload Results To Codecov + uses: codecov/codecov-action@v3 + with: + files: ./coverage.out + flags: inttests # optional + verbose: true # optional (default = false) \ No newline at end of file diff --git a/.github/workflows/unitcoverage.yaml b/.github/workflows/unitcoverage.yaml index d7da7b4bd2..5f8e03c1ea 100644 --- a/.github/workflows/unitcoverage.yaml +++ b/.github/workflows/unitcoverage.yaml @@ -56,7 +56,7 @@ jobs: uses: mxschmitt/action-tmate@v3 timeout-minutes: 5 - name: Upload Results To Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 with: files: ./coverage.out flags: unittests # optional diff --git a/Dockerfile.dapper b/Dockerfile.dapper index c39397c5be..fdd4a8d112 100644 --- a/Dockerfile.dapper +++ b/Dockerfile.dapper @@ -44,7 +44,7 @@ ARG SELINUX=true ENV SELINUX $SELINUX ENV DAPPER_RUN_ARGS --privileged -v k3s-cache:/go/src/github.com/k3s-io/k3s/.cache -v trivy-cache:/root/.cache/trivy -ENV DAPPER_ENV REPO TAG DRONE_TAG IMAGE_NAME SKIP_VALIDATE SKIP_AIRGAP AWS_SECRET_ACCESS_KEY AWS_ACCESS_KEY_ID GITHUB_TOKEN GOLANG DEBUG +ENV DAPPER_ENV REPO TAG DRONE_TAG IMAGE_NAME SKIP_VALIDATE SKIP_AIRGAP AWS_SECRET_ACCESS_KEY AWS_ACCESS_KEY_ID GITHUB_TOKEN GOLANG GOCOVER DEBUG ENV DAPPER_SOURCE /go/src/github.com/k3s-io/k3s/ ENV DAPPER_OUTPUT ./bin ./dist ./build/out ./build/static ./pkg/static ./pkg/deploy diff --git a/pkg/server/cover.go b/pkg/server/cover.go new file mode 100644 index 0000000000..8290db0633 --- /dev/null +++ b/pkg/server/cover.go @@ -0,0 +1,32 @@ +//go:build cover + +package server + +import ( + "context" + "os" + "runtime/coverage" + "time" + + "github.com/sirupsen/logrus" +) + +// writeCoverage checks if GOCOVERDIR is set on startup and writes coverage files to that directory +// every 20 seconds. This is done to ensure that the coverage files are written even if the process is killed. +func writeCoverage(ctx context.Context) { + if k, ok := os.LookupEnv("GOCOVERDIR"); ok { + for { + select { + case <-ctx.Done(): + if err := coverage.WriteCountersDir(k); err != nil { + logrus.Warn(err) + } + return + case <-time.After(20 * time.Second): + if err := coverage.WriteCountersDir(k); err != nil { + logrus.Warn(err) + } + } + } + } +} diff --git a/pkg/server/no_cover.go b/pkg/server/no_cover.go new file mode 100644 index 0000000000..7cfc44c297 --- /dev/null +++ b/pkg/server/no_cover.go @@ -0,0 +1,7 @@ +//go:build !cover + +package server + +import "context" + +func writeCoverage(ctx context.Context) {} diff --git a/pkg/server/server.go b/pkg/server/server.go index e1020b7081..1c240ca4aa 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -77,7 +77,7 @@ func StartServer(ctx context.Context, config *Config, cfg *cmds.Server) error { return errors.Wrap(err, "startup hook") } } - + go writeCoverage(ctx) go startOnAPIServerReady(ctx, config) if err := printTokens(&config.ControlConfig); err != nil { diff --git a/scripts/build b/scripts/build index 5f06cf7940..916133e2e9 100755 --- a/scripts/build +++ b/scripts/build @@ -54,7 +54,6 @@ VERSIONFLAGS=" -X ${PKG_ETCD}/api/version.GitSHA=HEAD " - if [ -n "${DEBUG}" ]; then GCFLAGS="-N -l" else @@ -81,6 +80,11 @@ else TAGS="static_build libsqlite3 $TAGS" fi +if [ -n "${GOCOVER}" ]; then + BLDFLAGS="-cover" + TAGS="cover $TAGS" +fi + mkdir -p bin if [ ${ARCH} = armv7l ] || [ ${ARCH} = arm ]; then @@ -128,7 +132,7 @@ if [ ! -x ${INSTALLBIN}/cni ]; then fi echo Building k3s -CGO_ENABLED=1 "${GO}" build -tags "$TAGS" -gcflags="all=${GCFLAGS}" -ldflags "$VERSIONFLAGS $LDFLAGS $STATIC" -o bin/k3s ./cmd/server/main.go +CGO_ENABLED=1 "${GO}" build $BLDFLAGS -tags "$TAGS" -gcflags="all=${GCFLAGS}" -ldflags "$VERSIONFLAGS $LDFLAGS $STATIC" -o bin/k3s ./cmd/server/main.go ln -s k3s ./bin/k3s-agent ln -s k3s ./bin/k3s-server ln -s k3s ./bin/k3s-token diff --git a/tests/integration/integration.go b/tests/integration/integration.go index 02dd77015b..28a1ca7beb 100644 --- a/tests/integration/integration.go +++ b/tests/integration/integration.go @@ -12,6 +12,7 @@ import ( "os/user" "strings" "syscall" + "time" "github.com/k3s-io/k3s/pkg/flock" "github.com/pkg/errors" @@ -263,11 +264,15 @@ func K3sStopServer(server *K3sServer) error { if server.log != nil { server.log.Close() } + if err := server.cmd.Process.Signal(syscall.SIGTERM); err != nil { + return err + } + time.Sleep(10 * time.Second) if err := server.cmd.Process.Kill(); err != nil { - return errors.Wrap(err, "failed to kill k3s process") + return err } if _, err := server.cmd.Process.Wait(); err != nil { - return errors.Wrap(err, "failed to wait for k3s process exit") + return err } return nil }