mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #85457 from BenTheElder/typecheck-fun
Typecheck support for verifying providerless build
This commit is contained in:
		@@ -40,6 +40,7 @@ EXCLUDED_PATTERNS=(
 | 
				
			|||||||
if [[ ${EXCLUDE_TYPECHECK:-} =~ ^[yY]$ ]]; then
 | 
					if [[ ${EXCLUDE_TYPECHECK:-} =~ ^[yY]$ ]]; then
 | 
				
			||||||
  EXCLUDED_PATTERNS+=(
 | 
					  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
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										26
									
								
								hack/verify-typecheck-providerless.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										26
									
								
								hack/verify-typecheck-providerless.sh
									
									
									
									
									
										Executable file
									
								
							@@ -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
 | 
				
			||||||
@@ -47,6 +47,9 @@ var (
 | 
				
			|||||||
	timings    = flag.Bool("time", false, "output times taken for each phase")
 | 
						timings    = flag.Bool("time", false, "output times taken for each phase")
 | 
				
			||||||
	defuses    = flag.Bool("defuse", false, "output defs/uses")
 | 
						defuses    = flag.Bool("defuse", false, "output defs/uses")
 | 
				
			||||||
	serial     = flag.Bool("serial", false, "don't type check platforms in parallel")
 | 
						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()))
 | 
						isTerminal = terminal.IsTerminal(int(os.Stdout.Fd()))
 | 
				
			||||||
	logPrefix  = ""
 | 
						logPrefix  = ""
 | 
				
			||||||
@@ -62,6 +65,24 @@ var (
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	darwinPlatString  = "darwin/386,darwin/amd64"
 | 
						darwinPlatString  = "darwin/386,darwin/amd64"
 | 
				
			||||||
	windowsPlatString = "windows/386,windows/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 {
 | 
					type analyzer struct {
 | 
				
			||||||
@@ -79,6 +100,10 @@ func newAnalyzer(platform string) *analyzer {
 | 
				
			|||||||
	platSplit := strings.Split(platform, "/")
 | 
						platSplit := strings.Split(platform, "/")
 | 
				
			||||||
	ctx.GOOS, ctx.GOARCH = platSplit[0], platSplit[1]
 | 
						ctx.GOOS, ctx.GOARCH = platSplit[0], platSplit[1]
 | 
				
			||||||
	ctx.CgoEnabled = true
 | 
						ctx.CgoEnabled = true
 | 
				
			||||||
 | 
						if *tags != "" {
 | 
				
			||||||
 | 
							tagsSplit := strings.Split(*tags, ",")
 | 
				
			||||||
 | 
							ctx.BuildTags = append(ctx.BuildTags, tagsSplit...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	a := &analyzer{
 | 
						a := &analyzer{
 | 
				
			||||||
		platform:  platform,
 | 
							platform:  platform,
 | 
				
			||||||
@@ -158,6 +183,9 @@ func (a *analyzer) filterFiles(fs map[string]*ast.File) []*ast.File {
 | 
				
			|||||||
	files := []*ast.File{}
 | 
						files := []*ast.File{}
 | 
				
			||||||
	for _, f := range fs {
 | 
						for _, f := range fs {
 | 
				
			||||||
		fpath := a.fset.File(f.Pos()).Name()
 | 
							fpath := a.fset.File(f.Pos()).Name()
 | 
				
			||||||
 | 
							if *skipTest && strings.HasSuffix(fpath, "_test.go") {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		dir, name := filepath.Split(fpath)
 | 
							dir, name := filepath.Split(fpath)
 | 
				
			||||||
		matches, err := a.ctx.MatchFile(dir, name)
 | 
							matches, err := a.ctx.MatchFile(dir, name)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -220,6 +248,7 @@ func (a *analyzer) typeCheck(dir string, files []*ast.File) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type collector struct {
 | 
					type collector struct {
 | 
				
			||||||
	dirs       []string
 | 
						dirs       []string
 | 
				
			||||||
 | 
						ignoreDirs []string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// handlePath walks the filesystem recursively, collecting directories,
 | 
					// 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() {
 | 
						if info.IsDir() {
 | 
				
			||||||
		// Ignore hidden directories (.git, .cache, etc)
 | 
							// Ignore hidden directories (.git, .cache, etc)
 | 
				
			||||||
		if len(path) > 1 && path[0] == '.' ||
 | 
							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" {
 | 
					 | 
				
			||||||
			return filepath.SkipDir
 | 
								return filepath.SkipDir
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							for _, dir := range c.ignoreDirs {
 | 
				
			||||||
 | 
								if path == dir {
 | 
				
			||||||
 | 
									return filepath.SkipDir
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		c.dirs = append(c.dirs, path)
 | 
							c.dirs = append(c.dirs, path)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -310,7 +330,13 @@ func main() {
 | 
				
			|||||||
		args = append(args, ".")
 | 
							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 {
 | 
						for _, arg := range args {
 | 
				
			||||||
		err := filepath.Walk(arg, c.handlePath)
 | 
							err := filepath.Walk(arg, c.handlePath)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,7 +146,9 @@ func TestHandlePackage(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestHandlePath(t *testing.T) {
 | 
					func TestHandlePath(t *testing.T) {
 | 
				
			||||||
	c := collector{}
 | 
						c := collector{
 | 
				
			||||||
 | 
							ignoreDirs: standardIgnoreDirs,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	e := errors.New("ex")
 | 
						e := errors.New("ex")
 | 
				
			||||||
	i, _ := os.Stat(".") // i.IsDir() == true
 | 
						i, _ := os.Stat(".") // i.IsDir() == true
 | 
				
			||||||
	if c.handlePath("foo", nil, e) != e {
 | 
						if c.handlePath("foo", nil, e) != e {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user