ci: comment Go coverage report on PR

Signed-off-by: Paul Meyer <49727155+katexochen@users.noreply.github.com>
This commit is contained in:
Paul Meyer 2023-08-23 18:52:46 +02:00
parent 5272e7c86f
commit 11efc8d512
8 changed files with 723 additions and 24 deletions

View File

@ -24,11 +24,29 @@ on:
jobs: jobs:
test-unittest: test-unittest:
runs-on: [self-hosted, bazel-cached] runs-on: [self-hosted, bazel-cached]
permissions:
id-token: write
contents: read
pull-requests: write
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with: with:
ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }}
fetch-depth: 0
- name: Install AWS cli
run: |
curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
rm -rf awscliv2.zip aws
- name: Login to AWS (IAM role)
uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
with:
role-to-assume: arn:aws:iam::795746500882:role/GithubActionGocoverage
aws-region: eu-central-1
- name: Setup bazel - name: Setup bazel
uses: ./.github/actions/setup_bazel uses: ./.github/actions/setup_bazel
@ -40,3 +58,25 @@ jobs:
env: env:
TMPDIR: ${{ runner.temp }} TMPDIR: ${{ runner.temp }}
run: bazel test //... --test_output=errors --config=nostamp run: bazel test //... --test_output=errors --config=nostamp
- name: Coverage
id: coverage
run: |
bazel run //bazel/ci:gocoverage_diff
lines=$(wc -l < coverage_diff.md)
uploadable=$([[ ${lines} -gt 3 ]] && echo "true" || echo "false")
echo "uploadable=$uploadable" | tee -a "$GITHUB_OUTPUT"
- name: Comment coverage
if: steps.coverage.outputs.uploadable == 'true' && github.event_name == 'pull_request'
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd # v2.8.0
with:
header: coverage
path: coverage_diff.md
- name: Upload coverage
if: github.ref_name == 'main'
run: |
cat coverage_result.json
aws s3 cp coverage_result.json s3://constellation-ci/gocoverage/coverage_main.json
echo "coverage uploaded to s3://constellation-ci/gocoverage/coverage_main.json"

View File

@ -25,6 +25,7 @@
/hack/clidocgen @thomasten /hack/clidocgen @thomasten
/hack/configapi @elchead /hack/configapi @elchead
/hack/fetch-broken-e2e @katexochen /hack/fetch-broken-e2e @katexochen
/hack/gocoverage @katexochen
/hack/oci-pin @malt3 /hack/oci-pin @malt3
/hack/pseudo-version @malt3 /hack/pseudo-version @malt3
/hack/qemu-metadata-api @daniel-weisse /hack/qemu-metadata-api @daniel-weisse

View File

@ -450,6 +450,19 @@ sh_template(
template = "unused_gh_actions.sh.in", template = "unused_gh_actions.sh.in",
) )
sh_template(
name = "gocoverage_diff",
data = [
"//hack/gocoverage",
"@go_sdk//:bin/go",
],
substitutions = {
"@@GO@@": "$(rootpath @go_sdk//:bin/go)",
"@@GOCOVERAGE@@": "$(rootpath //hack/gocoverage:gocoverage)",
},
template = "gocoverage_diff.sh.in",
)
multirun( multirun(
name = "tidy", name = "tidy",
commands = [ commands = [

View File

@ -0,0 +1,96 @@
#!/usr/bin/env bash
###### script header ######
lib=$(realpath @@BASE_LIB@@) || exit 1
stat "${lib}" >> /dev/null || exit 1
# shellcheck source=../sh/lib.bash
if ! source "${lib}"; then
echo "Error: could not find import"
exit 1
fi
go=$(realpath @@GO@@)
stat "${go}" >> /dev/null
gocoverage=$(realpath @@GOCOVERAGE@@)
stat "${gocoverage}" >> /dev/null
cd "${BUILD_WORKSPACE_DIRECTORY}"
###### script body ######
readonly coverageResultPath="coverage_result.json"
readonly coverageMainBucketPath="s3://constellation-ci/gocoverage/coverage_main.json"
readonly coverageMainPath="coverage_main.json"
readonly diffMdPath="coverage_diff.md"
function goTestCover() {
local path=${1-.}
testResult=0
testout=$(CGO_ENABLED=0 ${go} test -C "${path}" -cover "./...") || testResult=$?
if [[ ${testResult} -ne 0 ]]; then
echo "go test failed with exit code ${testResult}:"
echo "${testout}"
exit "${testResult}"
fi
echo "${testout}"
}
function goTestCoverAllMods() {
readarray -t <<< "$(${go} list -f '{{.Dir}}' -m)"
modules=("${MAPFILE[@]}")
excludeMods=(
"hack/tools"
)
for exclude in "${excludeMods[@]}"; do
for i in "${!modules[@]}"; do
if [[ ${modules[i]} == "${BUILD_WORKSPACE_DIRECTORY}/${exclude}" ]]; then
unset 'modules[i]'
fi
done
done
out=""
for mod in "${modules[@]}"; do
out="${out}$(goTestCover "${mod}")\n"
done
echo "${out}"
}
function fetchMainReport() {
if ! aws s3 cp "${coverageMainBucketPath}" "${coverageMainPath}" > /dev/null; then
echo "Could not fetch main coverage report from ${coverageMainBucketPath}"
exit 1
fi
}
function findDiffPaths() {
diff=$(git diff --name-only origin/main...HEAD)
if [[ -z ${diff} ]]; then
echo "No diff found between main and HEAD"
exit 0
fi
echo "${diff}" | xargs dirname | sort | uniq | tr '\n' ','
}
function generateCoverageDiff() {
echo "Running go test with coverage for all modules..."
out=$(goTestCoverAllMods)
echo "Generating coverage report..."
${gocoverage} > "${coverageResultPath}" <<< "${out}"
echo "Fetch latest report from main..."
fetchMainReport
echo "Find package paths that changed..."
diffPaths=$(findDiffPaths)
echo "Generating diff report..."
${gocoverage} \
-touched "${diffPaths}" \
-diff "${coverageMainPath}" "${coverageResultPath}" \
> "${diffMdPath}"
}
generateCoverageDiff

View File

@ -27,31 +27,23 @@ excludeMods=(
"hack/tools" "hack/tools"
) )
check() { echo "The following Go modules are excluded and won't be linted with golangci-lint:"
echo "The following Go modules are excluded and won't be linted with golangci-lint:" for exclude in "${excludeMods[@]}"; do
for exclude in "${excludeMods[@]}"; do for i in "${!modules[@]}"; do
for i in "${!modules[@]}"; do if [[ ${modules[i]} == "${BUILD_WORKSPACE_DIRECTORY}/${exclude}" ]]; then
if [[ ${modules[i]} == "${BUILD_WORKSPACE_DIRECTORY}/${exclude}" ]]; then echo " ${modules[i]}"
echo " ${modules[i]}" unset 'modules[i]'
unset 'modules[i]' fi
fi
done
done done
done
statuscode=0 statuscode=0
echo "Linting the following Go modules with golangci-lint:" echo "Linting the following Go modules with golangci-lint:"
for mod in "${modules[@]}"; do for mod in "${modules[@]}"; do
echo " ${mod}" echo " ${mod}"
PATH="$(dirname "${go}"):${PATH}" GOROOT=$(${go} env GOROOT) GOPATH=$(${go} env GOPATH) GOCACHE=$(${go} env GOCACHE) CGO_ENABLED=0 ${golangcilint} run --timeout=15m "${mod}/..." >&2 PATH="$(dirname "${go}"):${PATH}" GOROOT=$(${go} env GOROOT) GOPATH=$(${go} env GOPATH) GOCACHE=$(${go} env GOCACHE) CGO_ENABLED=0 ${golangcilint} run --timeout=15m "${mod}/..." >&2
statuscode=$? statuscode=$?
done done
exit "${statuscode}" exit "${statuscode}"
}
if test -v SILENT; then
check > /dev/null
else
check
fi

View File

@ -0,0 +1,26 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
load("//bazel/go:go_test.bzl", "go_test")
go_library(
name = "gocoverage_lib",
srcs = ["main.go"],
importpath = "github.com/edgelesssys/constellation/v2/hack/gocoverage",
visibility = ["//visibility:private"],
deps = ["@org_golang_x_exp//slices"],
)
go_binary(
name = "gocoverage",
embed = [":gocoverage_lib"],
visibility = ["//visibility:public"],
)
go_test(
name = "gocoverage_test",
srcs = ["main_test.go"],
embed = [":gocoverage_lib"],
deps = [
"@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require",
],
)

238
hack/gocoverage/main.go Normal file
View File

@ -0,0 +1,238 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
gocoverage parses 'go test -cover' output and generates a simple coverage report in JSON format.
It can also be used to create a diff of two reports, filter for packages that were touched in
a PR, and print a markdown table with the diff.
*/
package main
import (
"bufio"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"log"
"os"
"sort"
"strconv"
"strings"
"time"
"golang.org/x/exp/slices"
)
type packageCoverage struct {
Coverage float64
Notest bool
Nostmt bool
}
func (c *packageCoverage) String() string {
switch {
case c == nil: // is nil if pkg was removed/added
return fmt.Sprintf("%.2f%%", 0.0)
case c.Notest:
return "[no test files]"
case c.Nostmt:
return "[no statements]"
default:
return fmt.Sprintf("%.2f%%", c.Coverage)
}
}
type metadata struct {
Created string
}
type report struct {
Metadate metadata
Coverage map[string]*packageCoverage
}
func main() {
dodiff := flag.Bool("diff", false, "diff reports")
touched := flag.String("touched", "", "list of touched packages, comma separated")
flag.Parse()
switch {
case *dodiff:
if err := diff(flag.Arg(0), flag.Arg(1), *touched); err != nil {
log.Fatal(err)
}
case len(flag.Args()) == 0:
if err := parseStreaming(os.Stdin, os.Stdout); err != nil {
log.Fatal(err)
}
default:
fmt.Fprintln(os.Stderr, "gocoverage - generate coverage report from go test output and diff reports")
fmt.Fprintln(os.Stderr, "usage:")
fmt.Fprintln(os.Stderr, " go test -coverage ./... | gocoverage > report.json")
fmt.Fprintln(os.Stderr, " gocoverage -touched pkgs/foo,pkg/bar -diff old.json new.json > diff.md")
}
}
func parseStreaming(in io.Reader, out io.Writer) error {
rep, err := parseTestOutput(in)
if err != nil {
return err
}
return json.NewEncoder(out).Encode(rep)
}
func parseTestOutput(r io.Reader) (report, error) {
rep := report{
Metadate: metadata{Created: time.Now().UTC().Format(time.RFC3339)},
Coverage: make(map[string]*packageCoverage),
}
scanner := bufio.NewScanner(r)
for scanner.Scan() {
pkg, cov, err := parseTestLine(scanner.Text())
if err != nil {
return report{}, err
}
rep.Coverage[pkg] = &cov
}
return rep, nil
}
func parseTestLine(line string) (string, packageCoverage, error) {
fields := strings.Fields(line)
coverage := packageCoverage{}
var pkg string
for i := 0; i < len(fields); i++ {
f := fields[i]
switch {
case f == "FAIL":
return "", packageCoverage{}, errors.New("test failed")
case strings.HasPrefix(f, "github.com/"):
pkg = f
case f == "coverage:" && fields[i+1] != "[no":
covStr := strings.TrimSuffix(fields[i+1], "%")
cov, err := strconv.ParseFloat(covStr, 64)
if err != nil {
return "", packageCoverage{}, fmt.Errorf("parsing coverage: %v", err)
}
coverage.Coverage = cov
case f == "[no":
switch fields[i+1] {
case "test": // [no test files]
coverage.Notest = true
case "statements]": // [no statements]
coverage.Nostmt = true
// ignoring [no tests to run], as it also prints coverage 0%
}
default:
continue
}
}
return pkg, coverage, nil
}
func diff(old, new, touched string) error {
oldf, err := os.Open(old)
if err != nil {
return err
}
defer oldf.Close()
var oldRep, newReport report
if err := json.NewDecoder(oldf).Decode(&oldRep); err != nil {
return err
}
newf, err := os.Open(new)
if err != nil {
return err
}
defer newf.Close()
if err := json.NewDecoder(newf).Decode(&newReport); err != nil {
return err
}
diffs, err := diffCoverage(oldRep, newReport)
if err != nil {
return err
}
touchedPkgs := strings.Split(touched, ",")
return diffsToMd(diffs, os.Stdout, touchedPkgs)
}
type coverageDiff struct {
old *packageCoverage
new *packageCoverage
}
func diffCoverage(old, new report) (map[string]coverageDiff, error) {
allPkgs := make(map[string]struct{})
for pkg := range old.Coverage {
allPkgs[pkg] = struct{}{}
}
for pkg := range new.Coverage {
allPkgs[pkg] = struct{}{}
}
diffs := make(map[string]coverageDiff)
for pkg := range allPkgs {
diffs[pkg] = coverageDiff{old: old.Coverage[pkg], new: new.Coverage[pkg]}
if diffs[pkg].old == nil && diffs[pkg].new == nil {
return nil, fmt.Errorf("both old and new coverage are nil for pkg %s", pkg)
}
}
return diffs, nil
}
const pkgPrefix = "github.com/edgelesssys/constellation/v2/"
func diffsToMd(diffs map[string]coverageDiff, out io.Writer, touchedPkgs []string) error {
pkgs := make([]string, 0, len(diffs))
for pkg := range diffs {
pkgs = append(pkgs, pkg)
}
sort.Strings(pkgs)
fmt.Fprintln(out, "### Coverage report")
fmt.Fprintln(out, "| Package | Old | New | Trend |")
fmt.Fprintln(out, "| ------- | ---- | ---- | ----- |")
for _, pkg := range pkgs {
diff := diffs[pkg]
var tendency string
switch {
case len(touchedPkgs) != 0 && !slices.Contains(touchedPkgs, strings.TrimPrefix(pkg, pkgPrefix)):
continue // pkg was not touched
case diff.old == nil && (diff.new.Notest || diff.new.Nostmt):
tendency = ":rotating_light:" // new pkg, no tests
case diff.old == nil:
tendency = ":new:" // pkg is new
case diff.new == nil:
continue // pkg was removed
case (diff.new.Nostmt || diff.new.Notest) && (diff.old.Notest || diff.old.Nostmt):
tendency = ":construction:" // this is bad, but not worse than before
case (diff.new.Nostmt || diff.new.Notest) && !(diff.old.Coverage > 0.0):
tendency = ":rotating_light:" // tests were removed
case diff.old.Coverage == diff.new.Coverage && diff.new.Coverage == 0.0:
tendency = ":construction:" // no tests before, no tests now - do something about it!
case diff.old.Coverage == diff.new.Coverage && diff.new.Coverage < 50.0:
tendency = ":construction:" // heuristically still bad - you touch it, you own it.
case diff.old.Coverage < diff.new.Coverage:
tendency = ":arrow_upper_right:"
case diff.old.Coverage > diff.new.Coverage:
tendency = ":arrow_lower_right:"
case diff.old.Coverage == diff.new.Coverage:
tendency = ":left_right_arrow:"
default:
return fmt.Errorf("unexpected case: old: %v, new: %v", diff.old, diff.new)
}
oldCov := diff.old.String()
newCov := diff.new.String()
fmt.Fprintf(out, "| %s | %s | %s | %s |\n", strings.TrimPrefix(pkg, pkgPrefix), oldCov, newCov, tendency)
}
return nil
}

View File

@ -0,0 +1,293 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package main
import (
"bytes"
"encoding/json"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const goTestCoverOutput = `
ok github.com/edgelesssys/constellation/v2/bazel/release/artifacts (cached) coverage: [no statements]
? github.com/edgelesssys/constellation/v2/bootstrapper/cmd/bootstrapper [no test files]
? github.com/edgelesssys/constellation/v2/bootstrapper/initproto [no test files]
? github.com/edgelesssys/constellation/v2/bootstrapper/internal/certificate [no test files]
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/clean (cached) coverage: 100.0% of statements
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/diskencryption (cached) coverage: 76.9% of statements
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/initserver (cached) coverage: 73.7% of statements
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/joinclient (cached) coverage: 89.3% of statements
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/journald (cached) coverage: 42.1% of statements
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes (cached) coverage: 70.7% of statements
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes/k8sapi (cached) coverage: 8.9% of statements
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes/k8sapi/resources (cached) coverage: 22.2% of statements
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes/kubewaiter (cached) coverage: 100.0% of statements
? github.com/edgelesssys/constellation/v2/build/metad-analyst [no test files]
? github.com/edgelesssys/constellation/v2/bootstrapper/internal/logging [no test files]
ok github.com/edgelesssys/constellation/v2/bootstrapper/internal/nodelock (cached) coverage: 75.0% of statements
? github.com/edgelesssys/constellation/v2/cli [no test files]
? github.com/edgelesssys/constellation/v2/cli/cmd [no test files]
ok github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd (cached) coverage: 69.1% of statements
ok github.com/edgelesssys/constellation/v2/cli/internal/clusterid (cached) coverage: 56.2% of statements
? github.com/edgelesssys/constellation/v2/cli/internal/cmd/pathprefix [no test files]
ok github.com/edgelesssys/constellation/v2/cli/internal/cmd (cached) coverage: 54.3% of statements
? github.com/edgelesssys/constellation/v2/cli/internal/featureset [no test files]
? github.com/edgelesssys/constellation/v2/cli/internal/helm/imageversion [no test files]
? github.com/edgelesssys/constellation/v2/cli/internal/libvirt [no test files]
? github.com/edgelesssys/constellation/v2/debugd/cmd/cdbg [no test files]
ok github.com/edgelesssys/constellation/v2/cli/internal/helm (cached) coverage: 36.0% of statements
ok github.com/edgelesssys/constellation/v2/cli/internal/kubernetes (cached) coverage: 40.4% of statements
ok github.com/edgelesssys/constellation/v2/cli/internal/terraform (cached) coverage: 70.8% of statements
ok github.com/edgelesssys/constellation/v2/cli/internal/upgrade (cached) coverage: 66.7% of statements
ok github.com/edgelesssys/constellation/v2/csi/cryptmapper (cached) coverage: 79.2% of statements
ok github.com/edgelesssys/constellation/v2/csi/kms (cached) coverage: 70.0% of statements
? github.com/edgelesssys/constellation/v2/debugd/cmd/debugd [no test files]
? github.com/edgelesssys/constellation/v2/debugd/internal/cdbg/cmd [no test files]
? github.com/edgelesssys/constellation/v2/debugd/internal/debugd [no test files]
? github.com/edgelesssys/constellation/v2/debugd/service [no test files]
ok github.com/edgelesssys/constellation/v2/debugd/internal/debugd/deploy (cached) coverage: 83.6% of statements
ok github.com/edgelesssys/constellation/v2/debugd/internal/debugd/info (cached) coverage: 95.5% of statements
ok github.com/edgelesssys/constellation/v2/debugd/internal/debugd/logcollector (cached) coverage: 15.0% of statements
ok github.com/edgelesssys/constellation/v2/debugd/internal/debugd/metadata (cached) coverage: 92.9% of statements
ok github.com/edgelesssys/constellation/v2/debugd/internal/debugd/metadata/cloudprovider (cached) coverage: 75.9% of statements
ok github.com/edgelesssys/constellation/v2/debugd/internal/debugd/metadata/fallback (cached) coverage: 80.0% of statements
ok github.com/edgelesssys/constellation/v2/debugd/internal/debugd/server (cached) coverage: 71.7% of statements
ok github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer (cached) coverage: 100.0% of statements
ok github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer/streamer (cached) coverage: 90.9% of statements
? github.com/edgelesssys/constellation/v2/disk-mapper/cmd [no test files]
? github.com/edgelesssys/constellation/v2/disk-mapper/internal/diskencryption [no test files]
ok github.com/edgelesssys/constellation/v2/disk-mapper/internal/recoveryserver (cached) coverage: 89.1% of statements
ok github.com/edgelesssys/constellation/v2/disk-mapper/internal/rejoinclient (cached) coverage: 91.8% of statements
ok github.com/edgelesssys/constellation/v2/disk-mapper/internal/setup (cached) coverage: 68.9% of statements
? github.com/edgelesssys/constellation/v2/disk-mapper/recoverproto [no test files]
ok github.com/edgelesssys/constellation/v2/disk-mapper/internal/systemd (cached) coverage: 25.8% of statements
? github.com/edgelesssys/constellation/v2/e2e [no test files]
? github.com/edgelesssys/constellation/v2/e2e/internal/kubectl [no test files]
? github.com/edgelesssys/constellation/v2/e2e/internal/lb [no test files]
? github.com/edgelesssys/constellation/v2/e2e/internal/upgrade [no test files]
? github.com/edgelesssys/constellation/v2/image/upload [no test files]
? github.com/edgelesssys/constellation/v2/image/upload/internal/cmd [no test files]
? github.com/edgelesssys/constellation/v2/internal/api/client [no test files]
ok github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi (cached) coverage: 59.2% of statements
? github.com/edgelesssys/constellation/v2/internal/api/fetcher [no test files]
? github.com/edgelesssys/constellation/v2/internal/api/versionsapi/cli [no test files]
ok github.com/edgelesssys/constellation/v2/internal/api/versionsapi (cached) coverage: 69.8% of statements
? github.com/edgelesssys/constellation/v2/internal/attestation/aws [no test files]
? github.com/edgelesssys/constellation/v2/internal/attestation/azure [no test files]
ok github.com/edgelesssys/constellation/v2/internal/atls (cached) coverage: 78.6% of statements
ok github.com/edgelesssys/constellation/v2/internal/attestation (cached) coverage: 66.7% of statements
ok github.com/edgelesssys/constellation/v2/internal/attestation/aws/nitrotpm (cached) coverage: 43.2% of statements
ok github.com/edgelesssys/constellation/v2/internal/attestation/aws/snp (cached) coverage: 43.2% of statements
ok github.com/edgelesssys/constellation/v2/internal/attestation/azure/snp (cached) coverage: 10.6% of statements
ok github.com/edgelesssys/constellation/v2/internal/attestation/azure/trustedlaunch (cached) coverage: 4.3% of statements
ok github.com/edgelesssys/constellation/v2/internal/attestation/choose (cached) coverage: 85.0% of statements
ok github.com/edgelesssys/constellation/v2/internal/attestation/gcp (cached) coverage: 76.1% of statements
ok github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest (cached) coverage: 75.0% of statements
ok github.com/edgelesssys/constellation/v2/internal/attestation/initialize (cached) coverage: 10.7% of statements
? github.com/edgelesssys/constellation/v2/internal/attestation/qemu [no test files]
? github.com/edgelesssys/constellation/v2/internal/attestation/simulator [no test files]
ok github.com/edgelesssys/constellation/v2/internal/attestation/measurements (cached) coverage: 82.8% of statements
? github.com/edgelesssys/constellation/v2/internal/attestation/tdx [no test files]
? github.com/edgelesssys/constellation/v2/internal/attestation/variant [no test files]
? github.com/edgelesssys/constellation/v2/internal/cloud [no test files]
ok github.com/edgelesssys/constellation/v2/internal/attestation/measurements/measurement-generator (cached) coverage: 0.0% of statements [no tests to run]
ok github.com/edgelesssys/constellation/v2/internal/attestation/vtpm (cached) coverage: 22.4% of statements
ok github.com/edgelesssys/constellation/v2/internal/cloud/aws (cached) coverage: 82.6% of statements
ok github.com/edgelesssys/constellation/v2/internal/cloud/azure (cached) coverage: 71.4% of statements
ok github.com/edgelesssys/constellation/v2/internal/cloud/azureshared (cached) coverage: 95.6% of statements
ok github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider (cached) coverage: 92.6% of statements
ok github.com/edgelesssys/constellation/v2/internal/cloud/gcp (cached) coverage: 72.9% of statements
? github.com/edgelesssys/constellation/v2/internal/cloud/metadata [no test files]
ok github.com/edgelesssys/constellation/v2/internal/cloud/gcpshared (cached) coverage: 100.0% of statements
ok github.com/edgelesssys/constellation/v2/internal/cloud/openstack (cached) coverage: 92.5% of statements
? github.com/edgelesssys/constellation/v2/internal/cloud/qemu [no test files]
? github.com/edgelesssys/constellation/v2/internal/config/disktypes [no test files]
? github.com/edgelesssys/constellation/v2/internal/config/imageversion [no test files]
? github.com/edgelesssys/constellation/v2/internal/config/instancetypes [no test files]
? github.com/edgelesssys/constellation/v2/internal/config/migration [no test files]
? github.com/edgelesssys/constellation/v2/internal/constants [no test files]
? github.com/edgelesssys/constellation/v2/internal/containerimage [no test files]
ok github.com/edgelesssys/constellation/v2/internal/compatibility (cached) coverage: 83.1% of statements
ok github.com/edgelesssys/constellation/v2/internal/config (cached) coverage: 79.7% of statements
? github.com/edgelesssys/constellation/v2/internal/crypto/testvector [no test files]
? github.com/edgelesssys/constellation/v2/internal/cryptsetup [no test files]
ok github.com/edgelesssys/constellation/v2/internal/crypto (cached) coverage: 50.0% of statements
ok github.com/edgelesssys/constellation/v2/internal/file (cached) coverage: 88.2% of statements
ok github.com/edgelesssys/constellation/v2/internal/grpc/atlscredentials (cached) coverage: 76.9% of statements
ok github.com/edgelesssys/constellation/v2/internal/grpc/dialer (cached) coverage: 100.0% of statements
ok github.com/edgelesssys/constellation/v2/internal/grpc/grpclog (cached) coverage: 73.3% of statements
ok github.com/edgelesssys/constellation/v2/internal/grpc/retry (cached) coverage: 90.9% of statements
? github.com/edgelesssys/constellation/v2/internal/grpc/testdialer [no test files]
? github.com/edgelesssys/constellation/v2/internal/kms/config [no test files]
ok github.com/edgelesssys/constellation/v2/internal/imagefetcher (cached) coverage: 84.4% of statements
ok github.com/edgelesssys/constellation/v2/internal/installer (cached) coverage: 86.4% of statements
? github.com/edgelesssys/constellation/v2/internal/kms/kms [no test files]
? github.com/edgelesssys/constellation/v2/internal/kms/kms/aws [no test files]
? github.com/edgelesssys/constellation/v2/internal/kms/kms/azure [no test files]
? github.com/edgelesssys/constellation/v2/internal/kms/kms/gcp [no test files]
ok github.com/edgelesssys/constellation/v2/internal/kms/kms/cluster (cached) coverage: 75.0% of statements
ok github.com/edgelesssys/constellation/v2/internal/kms/kms/internal (cached) coverage: 86.4% of statements
ok github.com/edgelesssys/constellation/v2/internal/kms/setup (cached) coverage: 36.2% of statements
? github.com/edgelesssys/constellation/v2/internal/kms/storage [no test files]
ok github.com/edgelesssys/constellation/v2/internal/kms/storage/awss3 (cached) coverage: 61.3% of statements
ok github.com/edgelesssys/constellation/v2/internal/kms/storage/azureblob (cached) coverage: 51.9% of statements
ok github.com/edgelesssys/constellation/v2/internal/kms/storage/gcs (cached) coverage: 68.3% of statements
ok github.com/edgelesssys/constellation/v2/internal/kms/storage/memfs (cached) coverage: 100.0% of statements
ok github.com/edgelesssys/constellation/v2/internal/kms/uri (cached) coverage: 68.5% of statements
ok github.com/edgelesssys/constellation/v2/internal/kubernetes (cached) coverage: 85.5% of statements
? github.com/edgelesssys/constellation/v2/internal/logger [no test files]
ok github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl (cached) coverage: 7.8% of statements
ok github.com/edgelesssys/constellation/v2/internal/license (cached) coverage: 83.3% of statements
ok github.com/edgelesssys/constellation/v2/internal/nodestate (cached) coverage: 100.0% of statements
? github.com/edgelesssys/constellation/v2/internal/osimage [no test files]
? github.com/edgelesssys/constellation/v2/internal/osimage/archive [no test files]
? github.com/edgelesssys/constellation/v2/internal/osimage/aws [no test files]
? github.com/edgelesssys/constellation/v2/internal/osimage/azure [no test files]
? github.com/edgelesssys/constellation/v2/internal/osimage/gcp [no test files]
? github.com/edgelesssys/constellation/v2/internal/osimage/imageinfo [no test files]
? github.com/edgelesssys/constellation/v2/internal/osimage/measurementsuploader [no test files]
? github.com/edgelesssys/constellation/v2/internal/osimage/nop [no test files]
ok github.com/edgelesssys/constellation/v2/internal/osimage/secureboot (cached) coverage: 79.2% of statements
ok github.com/edgelesssys/constellation/v2/internal/retry (cached) coverage: 64.3% of statements
ok github.com/edgelesssys/constellation/v2/internal/role (cached) coverage: 70.6% of statements
? github.com/edgelesssys/constellation/v2/internal/sigstore/keyselect [no test files]
ok github.com/edgelesssys/constellation/v2/internal/semver (cached) coverage: 68.2% of statements
ok github.com/edgelesssys/constellation/v2/internal/sigstore (cached) coverage: 41.6% of statements
? github.com/edgelesssys/constellation/v2/internal/versions/components [no test files]
ok github.com/edgelesssys/constellation/v2/internal/staticupload (cached) coverage: 78.3% of statements
ok github.com/edgelesssys/constellation/v2/internal/versions (cached) coverage: 13.9% of statements
ok github.com/edgelesssys/constellation/v2/internal/versions/hash-generator (cached) coverage: 0.0% of statements [no tests to run]
? github.com/edgelesssys/constellation/v2/joinservice/cmd [no test files]
ok github.com/edgelesssys/constellation/v2/joinservice/internal/kms (cached) coverage: 85.7% of statements
ok github.com/edgelesssys/constellation/v2/joinservice/internal/kubeadm (cached) coverage: 76.1% of statements
ok github.com/edgelesssys/constellation/v2/joinservice/internal/kubernetes (cached) coverage: 8.5% of statements
ok github.com/edgelesssys/constellation/v2/joinservice/internal/kubernetesca (cached) coverage: 81.6% of statements
? github.com/edgelesssys/constellation/v2/joinservice/joinproto [no test files]
? github.com/edgelesssys/constellation/v2/keyservice/cmd [no test files]
? github.com/edgelesssys/constellation/v2/keyservice/keyserviceproto [no test files]
? github.com/edgelesssys/constellation/v2/measurement-reader/cmd [no test files]
? github.com/edgelesssys/constellation/v2/measurement-reader/internal/tdx [no test files]
? github.com/edgelesssys/constellation/v2/measurement-reader/internal/tpm [no test files]
ok github.com/edgelesssys/constellation/v2/joinservice/internal/server (cached) coverage: 76.2% of statements
ok github.com/edgelesssys/constellation/v2/joinservice/internal/watcher (cached) coverage: 80.4% of statements
ok github.com/edgelesssys/constellation/v2/keyservice/internal/server (cached) coverage: 61.9% of statements
ok github.com/edgelesssys/constellation/v2/measurement-reader/internal/sorted (cached) coverage: 94.7% of statements
? github.com/edgelesssys/constellation/v2/upgrade-agent/cmd [no test files]
? github.com/edgelesssys/constellation/v2/upgrade-agent/upgradeproto [no test files]
? github.com/edgelesssys/constellation/v2/verify/cmd [no test files]
ok github.com/edgelesssys/constellation/v2/upgrade-agent/internal/server (cached) coverage: 14.9% of statements
ok github.com/edgelesssys/constellation/v2/verify/server (cached) coverage: 95.4% of statements
? github.com/edgelesssys/constellation/v2/verify/verifyproto [no test files]
? github.com/edgelesssys/constellation/v2/3rdparty/node-maintenance-operator/api/v1beta1 [no test files]
? github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror [no test files]
ok github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/bazelfiles (cached) coverage: 75.0% of statements
ok github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/issues (cached) coverage: 88.9% of statements
ok github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/mirror (cached) coverage: 80.2% of statements
ok github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/rules (cached) coverage: 82.2% of statements
? github.com/edgelesssys/constellation/v2/hack/cli-k8s-compatibility [no test files]
? github.com/edgelesssys/constellation/v2/hack/clidocgen [no test files]
ok github.com/edgelesssys/constellation/v2/hack/configapi (cached) coverage: 19.5% of statements
? github.com/edgelesssys/constellation/v2/hack/oci-pin [no test files]
? github.com/edgelesssys/constellation/v2/hack/pseudo-version [no test files]
? github.com/edgelesssys/constellation/v2/hack/pseudo-version/internal/git [no test files]
? github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api [no test files]
? github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper [no test files]
ok github.com/edgelesssys/constellation/v2/hack/gocoverage 0.001s coverage: [no statements] [no tests to run]
ok github.com/edgelesssys/constellation/v2/hack/oci-pin/internal/extract (cached) coverage: 100.0% of statements
ok github.com/edgelesssys/constellation/v2/hack/oci-pin/internal/inject (cached) coverage: 100.0% of statements
ok github.com/edgelesssys/constellation/v2/hack/oci-pin/internal/sums (cached) coverage: 98.9% of statements
ok github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/server (cached) coverage: 60.7% of statements
? github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2 [no test files]
? github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/cloud/api [no test files]
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/controllers (cached) coverage: 30.6% of statements
? github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/cloud/fake/client [no test files]
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/cloud/aws/client (cached) coverage: 78.4% of statements
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/cloud/azure/client (cached) coverage: 89.3% of statements
? github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/constants [no test files]
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/cloud/gcp/client (cached) coverage: 80.8% of statements
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/controlplane (cached) coverage: 100.0% of statements
? github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/upgrade [no test files]
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/deploy (cached) coverage: 76.6% of statements
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/etcd (cached) coverage: 65.8% of statements
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/executor (cached) coverage: 93.2% of statements
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/node (cached) coverage: 100.0% of statements
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/patch (cached) coverage: 100.0% of statements
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/internal/poller (cached) coverage: 91.4% of statements
ok github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/sgreconciler (cached) coverage: 34.9% of statements
? github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api [no test files]
? github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api/v1alpha1 [no test files]
`
const (
exampleReportCLI = `{"Metadate":{"Created":"2023-08-24T16:09:02Z"},"Coverage":{"github.com/edgelesssys/constellation/v2/cli":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/cmd":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd":{"Coverage":65.5,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/clusterid":{"Coverage":56.2,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/cmd":{"Coverage":53.5,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/cmd/pathprefix":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/featureset":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/helm":{"Coverage":47.7,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/helm/imageversion":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/kubecmd":{"Coverage":54.1,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/libvirt":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/terraform":{"Coverage":71.3,"Notest":false,"Nostmt":false}}}`
exampleReportCLIOld = `{"Metadate":{"Created":"2023-08-24T16:48:39Z"},"Coverage":{"github.com/edgelesssys/constellation/v2/cli":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/cmd":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd":{"Coverage":73.1,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/clusterid":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/cmd":{"Coverage":61.6,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/featureset":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/helm":{"Coverage":51.7,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/helm/imageversion":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/iamid":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/kubernetes":{"Coverage":49.8,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/libvirt":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/terraform":{"Coverage":66.7,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/cli/internal/upgrade":{"Coverage":83,"Notest":false,"Nostmt":false}}}`
exampleReportDisk = `{"Metadate":{"Created":"2023-08-24T16:40:25Z"},"Coverage":{"github.com/edgelesssys/constellation/v2/disk-mapper/cmd":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/disk-mapper/internal/diskencryption":{"Coverage":0,"Notest":true,"Nostmt":false},"github.com/edgelesssys/constellation/v2/disk-mapper/internal/recoveryserver":{"Coverage":89.1,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/disk-mapper/internal/rejoinclient":{"Coverage":91.8,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/disk-mapper/internal/setup":{"Coverage":68.9,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/disk-mapper/internal/systemd":{"Coverage":25.8,"Notest":false,"Nostmt":false},"github.com/edgelesssys/constellation/v2/disk-mapper/recoverproto":{"Coverage":0,"Notest":true,"Nostmt":false}}}`
)
func TestParseStreaming(t *testing.T) {
assert := assert.New(t)
in := bytes.NewBufferString(goTestCoverOutput)
out := bytes.NewBuffer(nil)
err := parseStreaming(in, out)
assert.NoError(err)
}
func TestParseTestOutput(t *testing.T) {
assert := assert.New(t)
report, err := parseTestOutput(bytes.NewBufferString(goTestCoverOutput))
assert.NoError(err)
assert.Len(report.Coverage, 208)
}
func TestDiffCoverage(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
var oldreport, newreport report
err := json.Unmarshal([]byte(exampleReportCLI), &oldreport)
require.NoError(err)
newreport = oldreport
diff, err := diffCoverage(oldreport, newreport)
assert.NoError(err)
assert.Len(diff, 12)
err = json.Unmarshal([]byte(exampleReportDisk), &newreport)
require.NoError(err)
diff, err = diffCoverage(oldreport, newreport)
assert.NoError(err)
assert.Len(diff, 19)
}
func TestDiffsToMd(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
var oldreport, newreport report
err := json.Unmarshal([]byte(exampleReportCLI), &oldreport)
require.NoError(err)
err = json.Unmarshal([]byte(exampleReportCLIOld), &newreport)
require.NoError(err)
diff, err := diffCoverage(oldreport, newreport)
require.NoError(err)
out := new(bytes.Buffer)
err = diffsToMd(diff, out, []string{})
assert.NoError(err)
assert.NotEmpty(out)
lines := strings.Split(out.String(), "\n")
assert.Len(lines, 17)
out = new(bytes.Buffer)
err = diffsToMd(diff, out, []string{})
assert.NoError(err)
assert.NotEmpty(out)
lines = strings.Split(out.String(), "\n")
require.Len(lines, 17)
}