From 94cf731978323309d670bbea9382802bd2841031 Mon Sep 17 00:00:00 2001 From: Benjamin Elder Date: Tue, 19 Nov 2019 08:44:00 -0800 Subject: [PATCH 1/2] typecheck support setting tags, skipping test code, and ignoring directories --- test/typecheck/main.go | 72 +++++++++++++++++++++++++------------ test/typecheck/main_test.go | 4 ++- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/test/typecheck/main.go b/test/typecheck/main.go index 851b54926ac..b6bd558b4da 100644 --- a/test/typecheck/main.go +++ b/test/typecheck/main.go @@ -41,12 +41,15 @@ import ( ) var ( - verbose = flag.Bool("verbose", false, "print more information") - cross = flag.Bool("cross", true, "build for all platforms") - platforms = flag.String("platform", "", "comma-separated list of platforms to typecheck") - timings = flag.Bool("time", false, "output times taken for each phase") - defuses = flag.Bool("defuse", false, "output defs/uses") - serial = flag.Bool("serial", false, "don't type check platforms in parallel") + verbose = flag.Bool("verbose", false, "print more information") + cross = flag.Bool("cross", true, "build for all platforms") + platforms = flag.String("platform", "", "comma-separated list of platforms to typecheck") + timings = flag.Bool("time", false, "output times taken for each phase") + defuses = flag.Bool("defuse", false, "output defs/uses") + serial = flag.Bool("serial", false, "don't type check platforms in parallel") + skipTest = flag.Bool("skip-test", false, "don't type check test code") + tags = flag.String("tags", "", "comma-separated list of build tags to apply in addition to go's defaults") + ignoreDirs = flag.String("ignore-dirs", "", "comma-separated list of directories to ignore in addition to the default hardcoded list including staging, vendor, and hidden dirs") isTerminal = terminal.IsTerminal(int(os.Stdout.Fd())) logPrefix = "" @@ -62,6 +65,24 @@ var ( } darwinPlatString = "darwin/386,darwin/amd64" windowsPlatString = "windows/386,windows/amd64" + + // directories we always ignore + standardIgnoreDirs = []string{ + // Staging code is symlinked from vendor/k8s.io, and uses import + // paths as if it were inside of vendor/. It fails typechecking + // inside of staging/, but works when typechecked as part of vendor/. + "staging", + // OS-specific vendor code tends to be imported by OS-specific + // packages. We recursively typecheck imported vendored packages for + // each OS, but don't typecheck everything for every OS. + "vendor", + "_output", + // This is a weird one. /testdata/ is *mostly* ignored by Go, + // and this translates to kubernetes/vendor not working. + // edit/record.go doesn't compile without gopkg.in/yaml.v2 + // in $GOSRC/$GOROOT (both typecheck and the shell script). + "pkg/kubectl/cmd/testdata/edit", + } ) type analyzer struct { @@ -79,6 +100,10 @@ func newAnalyzer(platform string) *analyzer { platSplit := strings.Split(platform, "/") ctx.GOOS, ctx.GOARCH = platSplit[0], platSplit[1] ctx.CgoEnabled = true + if *tags != "" { + tagsSplit := strings.Split(*tags, ",") + ctx.BuildTags = append(ctx.BuildTags, tagsSplit...) + } a := &analyzer{ platform: platform, @@ -158,6 +183,9 @@ func (a *analyzer) filterFiles(fs map[string]*ast.File) []*ast.File { files := []*ast.File{} for _, f := range fs { fpath := a.fset.File(f.Pos()).Name() + if *skipTest && strings.HasSuffix(fpath, "_test.go") { + continue + } dir, name := filepath.Split(fpath) matches, err := a.ctx.MatchFile(dir, name) if err != nil { @@ -219,7 +247,8 @@ func (a *analyzer) typeCheck(dir string, files []*ast.File) error { } type collector struct { - dirs []string + dirs []string + ignoreDirs []string } // handlePath walks the filesystem recursively, collecting directories, @@ -231,23 +260,14 @@ func (c *collector) handlePath(path string, info os.FileInfo, err error) error { } if info.IsDir() { // Ignore hidden directories (.git, .cache, etc) - if len(path) > 1 && path[0] == '.' || - // Staging code is symlinked from vendor/k8s.io, and uses import - // paths as if it were inside of vendor/. It fails typechecking - // inside of staging/, but works when typechecked as part of vendor/. - path == "staging" || - // OS-specific vendor code tends to be imported by OS-specific - // packages. We recursively typecheck imported vendored packages for - // each OS, but don't typecheck everything for every OS. - path == "vendor" || - path == "_output" || - // This is a weird one. /testdata/ is *mostly* ignored by Go, - // and this translates to kubernetes/vendor not working. - // edit/record.go doesn't compile without gopkg.in/yaml.v2 - // in $GOSRC/$GOROOT (both typecheck and the shell script). - path == "pkg/kubectl/cmd/testdata/edit" { + if len(path) > 1 && path[0] == '.' { return filepath.SkipDir } + for _, dir := range c.ignoreDirs { + if path == dir { + return filepath.SkipDir + } + } c.dirs = append(c.dirs, path) } return nil @@ -310,7 +330,13 @@ func main() { args = append(args, ".") } - c := collector{} + c := collector{ + ignoreDirs: append([]string(nil), standardIgnoreDirs...), + } + if *ignoreDirs != "" { + c.ignoreDirs = append(c.ignoreDirs, strings.Split(*ignoreDirs, ",")...) + } + for _, arg := range args { err := filepath.Walk(arg, c.handlePath) if err != nil { diff --git a/test/typecheck/main_test.go b/test/typecheck/main_test.go index b03212c0050..b643d0cde2a 100644 --- a/test/typecheck/main_test.go +++ b/test/typecheck/main_test.go @@ -146,7 +146,9 @@ func TestHandlePackage(t *testing.T) { } func TestHandlePath(t *testing.T) { - c := collector{} + c := collector{ + ignoreDirs: standardIgnoreDirs, + } e := errors.New("ex") i, _ := os.Stat(".") // i.IsDir() == true if c.handlePath("foo", nil, e) != e { From b24dbac09a9472ca9e9331016c0e8f4340d72a58 Mon Sep 17 00:00:00 2001 From: Benjamin Elder Date: Tue, 19 Nov 2019 09:43:18 -0800 Subject: [PATCH 2/2] add hack/verify-typecheck-providerless.sh --- hack/make-rules/verify.sh | 3 ++- hack/verify-typecheck-providerless.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100755 hack/verify-typecheck-providerless.sh diff --git a/hack/make-rules/verify.sh b/hack/make-rules/verify.sh index d71e61b097d..1ceb531a065 100755 --- a/hack/make-rules/verify.sh +++ b/hack/make-rules/verify.sh @@ -39,7 +39,8 @@ EXCLUDED_PATTERNS=( # Exclude typecheck in certain cases, if they're running in a separate job. if [[ ${EXCLUDE_TYPECHECK:-} =~ ^[yY]$ ]]; then EXCLUDED_PATTERNS+=( - "verify-typecheck.sh" # runs in separate typecheck job + "verify-typecheck.sh" # runs in separate typecheck job + "verify-typecheck-providerless.sh" # runs in separate typecheck job ) fi diff --git a/hack/verify-typecheck-providerless.sh b/hack/verify-typecheck-providerless.sh new file mode 100755 index 00000000000..f5b6f53474a --- /dev/null +++ b/hack/verify-typecheck-providerless.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# Copyright 2018 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. + +cd "${KUBE_ROOT}" +# verify the providerless build +# https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/20190729-building-without-in-tree-providers.md +hack/verify-typecheck.sh --skip-test --tags=providerless --ignore-dirs=test