mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
Merge pull request #12579 from hashicorp/ci-missing-packages-oss
ci: ensure package coverage of test-core
This commit is contained in:
62
.github/workflows/test-core.yaml
vendored
62
.github/workflows/test-core.yaml
vendored
@@ -42,6 +42,7 @@ jobs:
|
||||
cache-key-suffix: -checks
|
||||
- name: Run make check
|
||||
run: |
|
||||
make missing
|
||||
make bootstrap
|
||||
make check
|
||||
compile:
|
||||
@@ -87,42 +88,51 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pkg:
|
||||
- acl
|
||||
- acl/...
|
||||
- client
|
||||
- client/allocdir
|
||||
- client/allochealth
|
||||
- client/allocrunner
|
||||
- client/allocwatcher
|
||||
- client/config
|
||||
- client/consul
|
||||
- client/devicemanager
|
||||
- client/dynamicplugins
|
||||
- client/fingerprint
|
||||
- client/allocdir/...
|
||||
- client/allochealth/...
|
||||
- client/allocrunner/...
|
||||
- client/allocwatcher/...
|
||||
- client/config/...
|
||||
- client/consul/...
|
||||
- client/devicemanager/...
|
||||
- client/dynamicplugins/...
|
||||
- client/fingerprint/...
|
||||
- client/interfaces/...
|
||||
- client/lib/...
|
||||
- client/logmon
|
||||
- client/pluginmanager
|
||||
- client/state
|
||||
- client/stats
|
||||
- client/structs
|
||||
- client/taskenv
|
||||
- client/logmon/...
|
||||
- client/pluginmanager/...
|
||||
- client/servers/...
|
||||
- client/serviceregistration/...
|
||||
- client/state/...
|
||||
- client/stats/...
|
||||
- client/structs/...
|
||||
- client/taskenv/...
|
||||
- command
|
||||
- command/agent
|
||||
- drivers/docker
|
||||
- drivers/exec
|
||||
- drivers/java
|
||||
- drivers/rawexec
|
||||
- command/agent/...
|
||||
- command/raft_tools/...
|
||||
- drivers/docker/...
|
||||
- drivers/exec/...
|
||||
- drivers/java/...
|
||||
- drivers/mock/...
|
||||
- drivers/rawexec/...
|
||||
- drivers/shared/...
|
||||
- drivers/qemu/...
|
||||
- helper/...
|
||||
- internal/...
|
||||
- jobspec/...
|
||||
- lib/...
|
||||
- nomad
|
||||
- nomad/deploymentwatcher
|
||||
- nomad/stream
|
||||
- nomad/structs
|
||||
- nomad/volumewatcher
|
||||
- nomad/deploymentwatcher/...
|
||||
- nomad/drainer/...
|
||||
- nomad/state/...
|
||||
- nomad/stream/...
|
||||
- nomad/structs/...
|
||||
- nomad/volumewatcher/...
|
||||
- plugins/...
|
||||
- scheduler/...
|
||||
- testutil
|
||||
- testutil/...
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: magnetikonline/action-golang-cache@v1
|
||||
|
||||
@@ -410,6 +410,7 @@ ui-screenshots-local:
|
||||
@echo "==> Collecting UI screenshots (local)..."
|
||||
@cd scripts/screenshots/src && SCREENSHOTS_DIR="../screenshots" node index.js
|
||||
|
||||
.PHONY: version
|
||||
version:
|
||||
ifneq (,$(wildcard version/version_ent.go))
|
||||
@$(CURDIR)/scripts/version.sh version/version.go version/version_ent.go
|
||||
@@ -417,4 +418,8 @@ else
|
||||
@$(CURDIR)/scripts/version.sh version/version.go version/version.go
|
||||
endif
|
||||
|
||||
.PHONY: version
|
||||
.PHONY: missing
|
||||
missing:
|
||||
@echo "==> Checking for packages not being tested ..."
|
||||
@go run -modfile tools/go.mod tools/missing/main.go \
|
||||
.github/workflows/test-core.yaml
|
||||
|
||||
14
tools/go.mod
14
tools/go.mod
@@ -2,6 +2,16 @@ module github.com/hashicorp/nomad/tools
|
||||
|
||||
go 1.17
|
||||
|
||||
require github.com/aws/aws-sdk-go v1.37.26
|
||||
require (
|
||||
github.com/aws/aws-sdk-go v1.37.26
|
||||
github.com/stretchr/testify v1.7.1
|
||||
gophers.dev/pkgs/ignore v0.3.1
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
)
|
||||
|
||||
require github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
)
|
||||
|
||||
@@ -10,6 +10,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -20,6 +22,11 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gophers.dev/pkgs/ignore v0.3.1 h1:MmNywpk5VAxWQ7/Yz9E1NmEEHLTh0hRWLiHENdVy4Ls=
|
||||
gophers.dev/pkgs/ignore v0.3.1/go.mod h1:HwTn4Fc9oicp2TxFV/8P0CswwfsVQczZvG6ZTy2TRXA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
178
tools/missing/main.go
Normal file
178
tools/missing/main.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"gophers.dev/pkgs/ignore"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := run(os.Args[1:]); err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "FAIL: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
type YamlFile struct {
|
||||
Jobs struct {
|
||||
TestPackages struct {
|
||||
Strategy struct {
|
||||
Matrix struct {
|
||||
Packages []string `yaml:"pkg"`
|
||||
} `yaml:"matrix"`
|
||||
} `yaml:"strategy"`
|
||||
} `yaml:"tests-pkgs"`
|
||||
} `yaml:"jobs"`
|
||||
}
|
||||
|
||||
func run(args []string) error {
|
||||
if len(args) != 1 {
|
||||
return errors.New("requires filename")
|
||||
}
|
||||
|
||||
f, err := os.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ignore.Close(f)
|
||||
|
||||
coverage, err := inMatrix(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
packages, err := inCode(".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var isMissing []string
|
||||
for _, pkg := range packages {
|
||||
if !isCovered(coverage, pkg) {
|
||||
isMissing = append(isMissing, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(isMissing)
|
||||
for _, pkg := range isMissing {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "missing: %s\n", pkg)
|
||||
}
|
||||
|
||||
if len(isMissing) > 0 {
|
||||
return fmt.Errorf("detected %d packages not tested", len(isMissing))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isCovered returns true if pkg is covered by a package in coverage.
|
||||
func isCovered(coverage []string, pkg string) bool {
|
||||
for _, p := range coverage {
|
||||
if isCoveredOne(p, pkg) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isCoveredOne returns true if p covers pkg.
|
||||
//
|
||||
// p may be a complete path, or a prefix ending with recursive '...'
|
||||
func isCoveredOne(p string, pkg string) bool {
|
||||
if p == pkg {
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.HasSuffix(p, "/...") {
|
||||
prefix := strings.TrimSuffix(p, "/...")
|
||||
if strings.HasPrefix(pkg, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func inMatrix(r io.Reader) ([]string, error) {
|
||||
var yFile YamlFile
|
||||
if err := yaml.NewDecoder(r).Decode(&yFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := yFile.Jobs.TestPackages.Strategy.Matrix.Packages
|
||||
return p, nil
|
||||
}
|
||||
|
||||
type nothing struct{}
|
||||
|
||||
var null = nothing{}
|
||||
|
||||
// uninteresting lists remaining packages that contain Go code but still
|
||||
// do not need to be covered by test cases.
|
||||
var uninteresting = []string{
|
||||
// module
|
||||
"api",
|
||||
|
||||
// main
|
||||
".",
|
||||
|
||||
// testing helpers
|
||||
"ci",
|
||||
"client/testutil",
|
||||
"client/vaultclient",
|
||||
"e2e",
|
||||
"nomad/mock",
|
||||
"plugins/csi/fake",
|
||||
|
||||
// not core code
|
||||
"demo",
|
||||
"tools",
|
||||
"version",
|
||||
}
|
||||
|
||||
func skip(p string) bool {
|
||||
for _, prefix := range uninteresting {
|
||||
if strings.HasPrefix(p, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func inCode(root string) ([]string, error) {
|
||||
m := map[string]nothing{}
|
||||
|
||||
err := filepath.Walk(root, func(path string, info fs.FileInfo, err error) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if skip(path) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if ext := filepath.Ext(path); ext == ".go" {
|
||||
m[filepath.Dir(path)] = null
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
delete(m, ".") // package main
|
||||
|
||||
var packages []string
|
||||
for p := range m {
|
||||
packages = append(packages, p)
|
||||
}
|
||||
sort.Strings(packages)
|
||||
return packages, nil
|
||||
}
|
||||
21
tools/missing/main_test.go
Normal file
21
tools/missing/main_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_isCoveredOne(t *testing.T) {
|
||||
try := func(p string, exp bool) {
|
||||
result := isCoveredOne(p, "foo/bar")
|
||||
require.Equal(t, exp, result)
|
||||
}
|
||||
try("baz", false)
|
||||
try("foo", false)
|
||||
try("foo/bar/baz", false)
|
||||
try("foo/bar", true)
|
||||
try("foo/bar/...", true)
|
||||
try("foo/...", true)
|
||||
try("abc/...", false)
|
||||
}
|
||||
Reference in New Issue
Block a user