Merge pull request #62151 from thockin/build-cleanup-with-go-1-10
Automatic merge from submit-queue (batch tested with PRs 62495, 63003, 62829, 62151, 62002). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Build cleanup with go 1.10 Simplify our build/test scripts now that go 1.10 is in play. It has caching that seems to actually work. **Release note**: ```release-note NONE ```
This commit is contained in:
		
						commit
						fce3ad5198
					
				|  | @ -35,7 +35,7 @@ SHELL := /bin/bash | ||||||
| # This rule collects all the generated file sets into a single rule.  Other
 | # This rule collects all the generated file sets into a single rule.  Other
 | ||||||
| # rules should depend on this to ensure generated files are rebuilt.
 | # rules should depend on this to ensure generated files are rebuilt.
 | ||||||
| .PHONY: generated_files | .PHONY: generated_files | ||||||
| generated_files: gen_deepcopy gen_defaulter gen_conversion gen_openapi | generated_files: gen_deepcopy gen_defaulter gen_conversion gen_openapi gen_bindata | ||||||
| 
 | 
 | ||||||
| .PHONY: verify_generated_files | .PHONY: verify_generated_files | ||||||
| verify_generated_files: verify_gen_deepcopy    \ | verify_generated_files: verify_gen_deepcopy    \ | ||||||
|  | @ -486,110 +486,6 @@ $(DEFAULTER_GEN): | ||||||
| 	hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/defaulter-gen | 	hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/defaulter-gen | ||||||
| 	touch $@ | 	touch $@ | ||||||
| 
 | 
 | ||||||
| #
 |  | ||||||
| # Open-api generation
 |  | ||||||
| #
 |  | ||||||
| # Any package that wants open-api functions generated must include a
 |  | ||||||
| # comment-tag in column 0 of one file of the form:
 |  | ||||||
| #     // +k8s:openapi-gen=true
 |  | ||||||
| #
 |  | ||||||
| # The result file, in each pkg, of open-api generation.
 |  | ||||||
| OPENAPI_BASENAME := $(GENERATED_FILE_PREFIX)openapi |  | ||||||
| OPENAPI_FILENAME := $(OPENAPI_BASENAME).go |  | ||||||
| OPENAPI_OUTPUT_PKG := pkg/generated/openapi |  | ||||||
| 
 |  | ||||||
| # The tool used to generate open apis.
 |  | ||||||
| OPENAPI_GEN := $(BIN_DIR)/openapi-gen |  | ||||||
| 
 |  | ||||||
| # Find all the directories that request open-api generation.
 |  | ||||||
| ifeq ($(DBG_MAKEFILE),1) |  | ||||||
|     $(warning ***** finding all +k8s:openapi-gen tags) |  | ||||||
| endif |  | ||||||
| OPENAPI_DIRS := $(shell                                             \
 |  | ||||||
|     grep --color=never -l '+k8s:openapi-gen=' $(ALL_K8S_TAG_FILES)  \
 |  | ||||||
|         | xargs -n1 dirname                                         \
 |  | ||||||
|         | LC_ALL=C sort -u                                          \
 |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| OPENAPI_OUTFILE := $(OPENAPI_OUTPUT_PKG)/$(OPENAPI_FILENAME) |  | ||||||
| 
 |  | ||||||
| # This rule is the user-friendly entrypoint for openapi generation.
 |  | ||||||
| .PHONY: gen_openapi |  | ||||||
| gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN) |  | ||||||
| 
 |  | ||||||
| # For each dir in OPENAPI_DIRS, this establishes a dependency between the
 |  | ||||||
| # output file and the input files that should trigger a rebuild.
 |  | ||||||
| #
 |  | ||||||
| # Note that this is a deps-only statement, not a full rule (see below).  This
 |  | ||||||
| # has to be done in a distinct step because wildcards don't work in static
 |  | ||||||
| # pattern rules.
 |  | ||||||
| #
 |  | ||||||
| # The '$(eval)' is needed because this has a different RHS for each LHS, and
 |  | ||||||
| # would otherwise produce results that make can't parse.
 |  | ||||||
| #
 |  | ||||||
| # We depend on the $(GOFILES_META).stamp to detect when the set of input files
 |  | ||||||
| # has changed.  This allows us to detect deleted input files.
 |  | ||||||
| $(foreach dir, $(OPENAPI_DIRS), $(eval                                     \ |  | ||||||
|     $(OPENAPI_OUTFILE): $(META_DIR)/$(dir)/$(GOFILES_META).stamp           \
 |  | ||||||
|                                  $(gofiles__$(dir))                        \
 |  | ||||||
| )) |  | ||||||
| 
 |  | ||||||
| # How to regenerate open-api code.  This emits a single file for all results.
 |  | ||||||
| $(OPENAPI_OUTFILE): $(OPENAPI_GEN) $(OPENAPI_GEN) |  | ||||||
| 	function run_gen_openapi() {                                                        \
 |  | ||||||
| 	    ./hack/run-in-gopath.sh $(OPENAPI_GEN)                                          \
 |  | ||||||
| 	        --v $(KUBE_VERBOSE)                                                         \
 |  | ||||||
| 	        --logtostderr                                                               \
 |  | ||||||
| 	        -i $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(OPENAPI_DIRS)) | sed 's/ /,/g')  \
 |  | ||||||
| 	        -p $(PRJ_SRC_PATH)/$(OPENAPI_OUTPUT_PKG)                                    \
 |  | ||||||
| 	        -O $(OPENAPI_BASENAME)                                                      \
 |  | ||||||
| 	        "$$@";                                                                      \
 |  | ||||||
| 	};                                                                                  \
 |  | ||||||
| 	run_gen_openapi |  | ||||||
| 
 |  | ||||||
| # This calculates the dependencies for the generator tool, so we only rebuild
 |  | ||||||
| # it when needed.  It is PHONY so that it always runs, but it only updates the
 |  | ||||||
| # file if the contents have actually changed.  We 'sinclude' this later.
 |  | ||||||
| .PHONY: $(META_DIR)/$(OPENAPI_GEN).mk |  | ||||||
| $(META_DIR)/$(OPENAPI_GEN).mk: |  | ||||||
| 	mkdir -p $(@D);                                                       \
 |  | ||||||
| 	(echo -n "$(OPENAPI_GEN): ";                                          \
 |  | ||||||
| 	 ./hack/run-in-gopath.sh go list                                      \
 |  | ||||||
| 	     -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}'  \
 |  | ||||||
| 	     ./vendor/k8s.io/code-generator/cmd/openapi-gen                   \
 |  | ||||||
| 	     | grep --color=never "^$(PRJ_SRC_PATH)/"                         \
 |  | ||||||
| 	     | xargs ./hack/run-in-gopath.sh go list                          \
 |  | ||||||
| 	         -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}'  \
 |  | ||||||
| 	     | paste -sd' ' -                                                 \
 |  | ||||||
| 	     | sed 's/ / \\=,/g'                                              \
 |  | ||||||
| 	     | tr '=,' '\n\t'                                                 \
 |  | ||||||
| 	     | sed "s|$$(pwd -P)/||";                                         \
 |  | ||||||
| 	) > $@.tmp;                                                           \
 |  | ||||||
| 	if ! cmp -s $@.tmp $@; then                                           \
 |  | ||||||
| 	    if [[ "$(DBG_CODEGEN)" == 1 ]]; then                              \
 |  | ||||||
| 	        echo "DBG: $(OPENAPI_GEN).mk changed";                        \
 |  | ||||||
| 	    fi;                                                               \
 |  | ||||||
| 	    cat $@.tmp > $@;                                                  \
 |  | ||||||
| 	    rm -f $@.tmp;                                                     \
 |  | ||||||
| 	fi |  | ||||||
| 
 |  | ||||||
| # Include dependency info for the generator tool.  This will cause the rule of
 |  | ||||||
| # the same name to be considered and if it is updated, make will restart.
 |  | ||||||
| sinclude $(META_DIR)/$(OPENAPI_GEN).mk |  | ||||||
| 
 |  | ||||||
| # How to build the generator tool.  The deps for this are defined in
 |  | ||||||
| # the $(OPENAPI_GEN).mk, above.
 |  | ||||||
| #
 |  | ||||||
| # A word on the need to touch: This rule might trigger if, for example, a
 |  | ||||||
| # non-Go file was added or deleted from a directory on which this depends.
 |  | ||||||
| # This target needs to be reconsidered, but Go realizes it doesn't actually
 |  | ||||||
| # have to be rebuilt.  In that case, make will forever see the dependency as
 |  | ||||||
| # newer than the binary, and try to rebuild it over and over.  So we touch it,
 |  | ||||||
| # and make is happy.
 |  | ||||||
| $(OPENAPI_GEN): |  | ||||||
| 	hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/openapi-gen |  | ||||||
| 	touch $@ |  | ||||||
| 
 |  | ||||||
| #
 | #
 | ||||||
| # Conversion generation
 | # Conversion generation
 | ||||||
| #
 | #
 | ||||||
|  | @ -805,3 +701,168 @@ sinclude $(META_DIR)/$(CONVERSION_GEN).mk | ||||||
| $(CONVERSION_GEN): | $(CONVERSION_GEN): | ||||||
| 	hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/conversion-gen | 	hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/conversion-gen | ||||||
| 	touch $@ | 	touch $@ | ||||||
|  | 
 | ||||||
|  | #
 | ||||||
|  | # Open-api generation
 | ||||||
|  | #
 | ||||||
|  | # Any package that wants open-api functions generated must include a
 | ||||||
|  | # comment-tag in column 0 of one file of the form:
 | ||||||
|  | #     // +k8s:openapi-gen=true
 | ||||||
|  | #
 | ||||||
|  | # The result file, in each pkg, of open-api generation.
 | ||||||
|  | OPENAPI_BASENAME := $(GENERATED_FILE_PREFIX)openapi | ||||||
|  | OPENAPI_FILENAME := $(OPENAPI_BASENAME).go | ||||||
|  | OPENAPI_OUTPUT_PKG := pkg/generated/openapi | ||||||
|  | 
 | ||||||
|  | # The tool used to generate open apis.
 | ||||||
|  | OPENAPI_GEN := $(BIN_DIR)/openapi-gen | ||||||
|  | 
 | ||||||
|  | # Find all the directories that request open-api generation.
 | ||||||
|  | ifeq ($(DBG_MAKEFILE),1) | ||||||
|  |     $(warning ***** finding all +k8s:openapi-gen tags) | ||||||
|  | endif | ||||||
|  | OPENAPI_DIRS := $(shell                                             \
 | ||||||
|  |     grep --color=never -l '+k8s:openapi-gen=' $(ALL_K8S_TAG_FILES)  \
 | ||||||
|  |         | xargs -n1 dirname                                         \
 | ||||||
|  |         | LC_ALL=C sort -u                                          \
 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | OPENAPI_OUTFILE := $(OPENAPI_OUTPUT_PKG)/$(OPENAPI_FILENAME) | ||||||
|  | 
 | ||||||
|  | # This rule is the user-friendly entrypoint for openapi generation.
 | ||||||
|  | .PHONY: gen_openapi | ||||||
|  | gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN) | ||||||
|  | 
 | ||||||
|  | # For each dir in OPENAPI_DIRS, this establishes a dependency between the
 | ||||||
|  | # output file and the input files that should trigger a rebuild.
 | ||||||
|  | #
 | ||||||
|  | # Note that this is a deps-only statement, not a full rule (see below).  This
 | ||||||
|  | # has to be done in a distinct step because wildcards don't work in static
 | ||||||
|  | # pattern rules.
 | ||||||
|  | #
 | ||||||
|  | # The '$(eval)' is needed because this has a different RHS for each LHS, and
 | ||||||
|  | # would otherwise produce results that make can't parse.
 | ||||||
|  | #
 | ||||||
|  | # We depend on the $(GOFILES_META).stamp to detect when the set of input files
 | ||||||
|  | # has changed.  This allows us to detect deleted input files.
 | ||||||
|  | $(foreach dir, $(OPENAPI_DIRS), $(eval                                     \ | ||||||
|  |     $(OPENAPI_OUTFILE): $(META_DIR)/$(dir)/$(GOFILES_META).stamp           \
 | ||||||
|  |                                  $(gofiles__$(dir))                        \
 | ||||||
|  | )) | ||||||
|  | 
 | ||||||
|  | # How to regenerate open-api code.  This emits a single file for all results.
 | ||||||
|  | $(OPENAPI_OUTFILE): $(OPENAPI_GEN) $(OPENAPI_GEN) | ||||||
|  | 	function run_gen_openapi() {                                                        \
 | ||||||
|  | 	    ./hack/run-in-gopath.sh $(OPENAPI_GEN)                                          \
 | ||||||
|  | 	        --v $(KUBE_VERBOSE)                                                         \
 | ||||||
|  | 	        --logtostderr                                                               \
 | ||||||
|  | 	        -i $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(OPENAPI_DIRS)) | sed 's/ /,/g')  \
 | ||||||
|  | 	        -p $(PRJ_SRC_PATH)/$(OPENAPI_OUTPUT_PKG)                                    \
 | ||||||
|  | 	        -O $(OPENAPI_BASENAME)                                                      \
 | ||||||
|  | 	        "$$@";                                                                      \
 | ||||||
|  | 	};                                                                                  \
 | ||||||
|  | 	run_gen_openapi | ||||||
|  | 
 | ||||||
|  | # This calculates the dependencies for the generator tool, so we only rebuild
 | ||||||
|  | # it when needed.  It is PHONY so that it always runs, but it only updates the
 | ||||||
|  | # file if the contents have actually changed.  We 'sinclude' this later.
 | ||||||
|  | .PHONY: $(META_DIR)/$(OPENAPI_GEN).mk | ||||||
|  | $(META_DIR)/$(OPENAPI_GEN).mk: | ||||||
|  | 	mkdir -p $(@D);                                                       \
 | ||||||
|  | 	(echo -n "$(OPENAPI_GEN): ";                                          \
 | ||||||
|  | 	 ./hack/run-in-gopath.sh go list                                      \
 | ||||||
|  | 	     -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}'  \
 | ||||||
|  | 	     ./vendor/k8s.io/code-generator/cmd/openapi-gen                   \
 | ||||||
|  | 	     | grep --color=never "^$(PRJ_SRC_PATH)/"                         \
 | ||||||
|  | 	     | xargs ./hack/run-in-gopath.sh go list                          \
 | ||||||
|  | 	         -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}'  \
 | ||||||
|  | 	     | paste -sd' ' -                                                 \
 | ||||||
|  | 	     | sed 's/ / \\=,/g'                                              \
 | ||||||
|  | 	     | tr '=,' '\n\t'                                                 \
 | ||||||
|  | 	     | sed "s|$$(pwd -P)/||";                                         \
 | ||||||
|  | 	) > $@.tmp;                                                           \
 | ||||||
|  | 	if ! cmp -s $@.tmp $@; then                                           \
 | ||||||
|  | 	    if [[ "$(DBG_CODEGEN)" == 1 ]]; then                              \
 | ||||||
|  | 	        echo "DBG: $(OPENAPI_GEN).mk changed";                        \
 | ||||||
|  | 	    fi;                                                               \
 | ||||||
|  | 	    cat $@.tmp > $@;                                                  \
 | ||||||
|  | 	    rm -f $@.tmp;                                                     \
 | ||||||
|  | 	fi | ||||||
|  | 
 | ||||||
|  | # Include dependency info for the generator tool.  This will cause the rule of
 | ||||||
|  | # the same name to be considered and if it is updated, make will restart.
 | ||||||
|  | sinclude $(META_DIR)/$(OPENAPI_GEN).mk | ||||||
|  | 
 | ||||||
|  | # How to build the generator tool.  The deps for this are defined in
 | ||||||
|  | # the $(OPENAPI_GEN).mk, above.
 | ||||||
|  | #
 | ||||||
|  | # A word on the need to touch: This rule might trigger if, for example, a
 | ||||||
|  | # non-Go file was added or deleted from a directory on which this depends.
 | ||||||
|  | # This target needs to be reconsidered, but Go realizes it doesn't actually
 | ||||||
|  | # have to be rebuilt.  In that case, make will forever see the dependency as
 | ||||||
|  | # newer than the binary, and try to rebuild it over and over.  So we touch it,
 | ||||||
|  | # and make is happy.
 | ||||||
|  | $(OPENAPI_GEN): | ||||||
|  | 	hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/openapi-gen | ||||||
|  | 	touch $@ | ||||||
|  | 
 | ||||||
|  | #
 | ||||||
|  | # bindata generation
 | ||||||
|  | #
 | ||||||
|  | 
 | ||||||
|  | # The tool used to generate bindata files.
 | ||||||
|  | BINDATA_GEN := $(BIN_DIR)/go-bindata | ||||||
|  | 
 | ||||||
|  | # A wrapper script that generates all bindata files.  It is fast enough that we
 | ||||||
|  | # don't care.
 | ||||||
|  | BINDATA_SCRIPT := hack/generate-bindata.sh | ||||||
|  | 
 | ||||||
|  | # This rule is the user-friendly entrypoint for bindata generation.
 | ||||||
|  | .PHONY: gen_bindata | ||||||
|  | gen_bindata: $(BINDATA_GEN) FORCE | ||||||
|  | 	./hack/run-in-gopath.sh $(BINDATA_SCRIPT) | ||||||
|  | 
 | ||||||
|  | FORCE: | ||||||
|  | 
 | ||||||
|  | # This calculates the dependencies for the generator tool, so we only rebuild
 | ||||||
|  | # it when needed.  It is PHONY so that it always runs, but it only updates the
 | ||||||
|  | # file if the contents have actually changed.  We 'sinclude' this later.
 | ||||||
|  | .PHONY: $(META_DIR)/$(BINDATA_GEN).mk | ||||||
|  | $(META_DIR)/$(BINDATA_GEN).mk: | ||||||
|  | 	mkdir -p $(@D);                                                       \
 | ||||||
|  | 	(echo -n "$(BINDATA_GEN): ";                                          \
 | ||||||
|  | 	 ./hack/run-in-gopath.sh go list                                      \
 | ||||||
|  | 	     -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}'  \
 | ||||||
|  | 	     ./vendor/github.com/jteeuwen/go-bindata/go-bindata               \
 | ||||||
|  | 	     | grep --color=never "^$(PRJ_SRC_PATH)/"                         \
 | ||||||
|  | 	     | xargs ./hack/run-in-gopath.sh go list                          \
 | ||||||
|  | 	         -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}'  \
 | ||||||
|  | 	     | paste -sd' ' -                                                 \
 | ||||||
|  | 	     | sed 's/ / \\=,/g'                                              \
 | ||||||
|  | 	     | tr '=,' '\n\t'                                                 \
 | ||||||
|  | 	     | sed "s|$$(pwd -P)/||";                                         \
 | ||||||
|  | 	) > $@.tmp;                                                           \
 | ||||||
|  | 	if ! cmp -s $@.tmp $@; then                                           \
 | ||||||
|  | 	    if [[ "$(DBG_CODEGEN)" == 1 ]]; then                              \
 | ||||||
|  | 	        echo "DBG: $(BINDATA_GEN).mk changed";                        \
 | ||||||
|  | 	    fi;                                                               \
 | ||||||
|  | 	    cat $@.tmp > $@;                                                  \
 | ||||||
|  | 	    rm -f $@.tmp;                                                     \
 | ||||||
|  | 	fi | ||||||
|  | 
 | ||||||
|  | # Include dependency info for the generator tool.  This will cause the rule of
 | ||||||
|  | # the same name to be considered and if it is updated, make will restart.
 | ||||||
|  | sinclude $(META_DIR)/$(BINDATA_GEN).mk | ||||||
|  | 
 | ||||||
|  | # How to build the generator tool.  The deps for this are defined in
 | ||||||
|  | # the $(BINDATA_GEN).mk, above.
 | ||||||
|  | #
 | ||||||
|  | # A word on the need to touch: This rule might trigger if, for example, a
 | ||||||
|  | # non-Go file was added or deleted from a directory on which this depends.
 | ||||||
|  | # This target needs to be reconsidered, but Go realizes it doesn't actually
 | ||||||
|  | # have to be rebuilt.  In that case, make will forever see the dependency as
 | ||||||
|  | # newer than the binary, and try to rebuild it over and over.  So we touch it,
 | ||||||
|  | # and make is happy.
 | ||||||
|  | $(BINDATA_GEN): | ||||||
|  | 	hack/make-rules/build.sh ./vendor/github.com/jteeuwen/go-bindata/go-bindata | ||||||
|  | 	touch $@ | ||||||
|  |  | ||||||
|  | @ -19,7 +19,6 @@ filegroup( | ||||||
|     srcs = [ |     srcs = [ | ||||||
|         ":package-srcs", |         ":package-srcs", | ||||||
|         "//hack/boilerplate:all-srcs", |         "//hack/boilerplate:all-srcs", | ||||||
|         "//hack/cmd/teststale:all-srcs", |  | ||||||
|         "//hack/e2e-internal:all-srcs", |         "//hack/e2e-internal:all-srcs", | ||||||
|         "//hack/lib:all-srcs", |         "//hack/lib:all-srcs", | ||||||
|         "//hack/make-rules:all-srcs", |         "//hack/make-rules:all-srcs", | ||||||
|  |  | ||||||
|  | @ -1,39 +0,0 @@ | ||||||
| package(default_visibility = ["//visibility:public"]) |  | ||||||
| 
 |  | ||||||
| load( |  | ||||||
|     "@io_bazel_rules_go//go:def.bzl", |  | ||||||
|     "go_binary", |  | ||||||
|     "go_library", |  | ||||||
|     "go_test", |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| go_binary( |  | ||||||
|     name = "teststale", |  | ||||||
|     embed = [":go_default_library"], |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| go_test( |  | ||||||
|     name = "go_default_test", |  | ||||||
|     srcs = ["teststale_test.go"], |  | ||||||
|     embed = [":go_default_library"], |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| go_library( |  | ||||||
|     name = "go_default_library", |  | ||||||
|     srcs = ["teststale.go"], |  | ||||||
|     importpath = "k8s.io/kubernetes/hack/cmd/teststale", |  | ||||||
|     deps = ["//vendor/github.com/golang/glog:go_default_library"], |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| filegroup( |  | ||||||
|     name = "package-srcs", |  | ||||||
|     srcs = glob(["**"]), |  | ||||||
|     tags = ["automanaged"], |  | ||||||
|     visibility = ["//visibility:private"], |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| filegroup( |  | ||||||
|     name = "all-srcs", |  | ||||||
|     srcs = [":package-srcs"], |  | ||||||
|     tags = ["automanaged"], |  | ||||||
| ) |  | ||||||
|  | @ -1,209 +0,0 @@ | ||||||
| /* |  | ||||||
| Copyright 2016 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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| // teststale checks the staleness of a test binary. go test -c builds a test
 |  | ||||||
| // binary but it does no staleness check. In other words, every time one runs
 |  | ||||||
| // go test -c, it compiles the test packages and links the binary even when
 |  | ||||||
| // nothing has changed. This program helps to mitigate that problem by allowing
 |  | ||||||
| // to check the staleness of a given test package and its binary.
 |  | ||||||
| package main |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"encoding/json" |  | ||||||
| 	"flag" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io" |  | ||||||
| 	"os" |  | ||||||
| 	"os/exec" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"time" |  | ||||||
| 
 |  | ||||||
| 	"github.com/golang/glog" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| const usageHelp = "" + |  | ||||||
| 	`This program checks the staleness of a given test package and its test |  | ||||||
| binary so that one can make a decision about re-building the test binary. |  | ||||||
| 
 |  | ||||||
| Usage: |  | ||||||
|   teststale -binary=/path/to/test/binary -package=package |  | ||||||
| 
 |  | ||||||
| Example: |  | ||||||
|   teststale -binary="$HOME/gosrc/bin/e2e.test" -package="k8s.io/kubernetes/test/e2e" |  | ||||||
| 
 |  | ||||||
| ` |  | ||||||
| 
 |  | ||||||
| var ( |  | ||||||
| 	binary  = flag.String("binary", "", "filesystem path to the test binary file. Example: \"$HOME/gosrc/bin/e2e.test\"") |  | ||||||
| 	pkgPath = flag.String("package", "", "import path of the test package in the format used while importing packages. Example: \"k8s.io/kubernetes/test/e2e\"") |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func usage() { |  | ||||||
| 	fmt.Fprintln(os.Stderr, usageHelp) |  | ||||||
| 	fmt.Fprintln(os.Stderr, "Flags:") |  | ||||||
| 	flag.PrintDefaults() |  | ||||||
| 	os.Exit(2) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // golist is an interface emulating the `go list` command to get package information.
 |  | ||||||
| // TODO: Evaluate using `go/build` package instead. It doesn't provide staleness
 |  | ||||||
| // information, but we can probably run `go list` and `go/build.Import()` concurrently
 |  | ||||||
| // in goroutines and merge the results. Evaluate if that's faster.
 |  | ||||||
| type golist interface { |  | ||||||
| 	pkgInfo(pkgPaths []string) ([]pkg, error) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // execmd implements the `golist` interface.
 |  | ||||||
| type execcmd struct { |  | ||||||
| 	cmd  string |  | ||||||
| 	args []string |  | ||||||
| 	env  []string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (e *execcmd) pkgInfo(pkgPaths []string) ([]pkg, error) { |  | ||||||
| 	args := append(e.args, pkgPaths...) |  | ||||||
| 	cmd := exec.Command(e.cmd, args...) |  | ||||||
| 	cmd.Env = e.env |  | ||||||
| 
 |  | ||||||
| 	stdout, err := cmd.StdoutPipe() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, fmt.Errorf("failed to obtain the metadata output stream: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	dec := json.NewDecoder(stdout) |  | ||||||
| 
 |  | ||||||
| 	// Start executing the command
 |  | ||||||
| 	if err := cmd.Start(); err != nil { |  | ||||||
| 		return nil, fmt.Errorf("command did not start: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	var pkgs []pkg |  | ||||||
| 	for { |  | ||||||
| 		var p pkg |  | ||||||
| 		if err := dec.Decode(&p); err == io.EOF { |  | ||||||
| 			break |  | ||||||
| 		} else if err != nil { |  | ||||||
| 			return nil, fmt.Errorf("failed to unmarshal metadata for package %s: %v", p.ImportPath, err) |  | ||||||
| 		} |  | ||||||
| 		pkgs = append(pkgs, p) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := cmd.Wait(); err != nil { |  | ||||||
| 		return nil, fmt.Errorf("command did not complete: %v", err) |  | ||||||
| 	} |  | ||||||
| 	return pkgs, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type pkg struct { |  | ||||||
| 	Dir          string |  | ||||||
| 	ImportPath   string |  | ||||||
| 	Target       string |  | ||||||
| 	Stale        bool |  | ||||||
| 	TestGoFiles  []string |  | ||||||
| 	TestImports  []string |  | ||||||
| 	XTestGoFiles []string |  | ||||||
| 	XTestImports []string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (p *pkg) isNewerThan(cmd golist, buildTime time.Time) bool { |  | ||||||
| 	// If the package itself is stale, then we have to rebuild the whole thing anyway.
 |  | ||||||
| 	if p.Stale { |  | ||||||
| 		return true |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Test for file staleness
 |  | ||||||
| 	for _, f := range p.TestGoFiles { |  | ||||||
| 		if isNewerThan(filepath.Join(p.Dir, f), buildTime) { |  | ||||||
| 			glog.V(4).Infof("test Go file %s is stale", f) |  | ||||||
| 			return true |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	for _, f := range p.XTestGoFiles { |  | ||||||
| 		if isNewerThan(filepath.Join(p.Dir, f), buildTime) { |  | ||||||
| 			glog.V(4).Infof("external test Go file %s is stale", f) |  | ||||||
| 			return true |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	imps := []string{} |  | ||||||
| 	imps = append(imps, p.TestImports...) |  | ||||||
| 	imps = append(imps, p.XTestImports...) |  | ||||||
| 
 |  | ||||||
| 	// This calls `go list` the second time. This is required because the first
 |  | ||||||
| 	// call to `go list` checks the staleness of the package in question by
 |  | ||||||
| 	// looking the non-test dependencies, but it doesn't look at the test
 |  | ||||||
| 	// dependencies. However, it returns the list of test dependencies. This
 |  | ||||||
| 	// second call to `go list` checks the staleness of all the test
 |  | ||||||
| 	// dependencies.
 |  | ||||||
| 	pkgs, err := cmd.pkgInfo(imps) |  | ||||||
| 	if err != nil || len(pkgs) < 1 { |  | ||||||
| 		glog.V(4).Infof("failed to obtain metadata for packages %s: %v", imps, err) |  | ||||||
| 		return true |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, p := range pkgs { |  | ||||||
| 		if p.Stale { |  | ||||||
| 			glog.V(4).Infof("import %q is stale", p.ImportPath) |  | ||||||
| 			return true |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return false |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func isNewerThan(filename string, buildTime time.Time) bool { |  | ||||||
| 	stat, err := os.Stat(filename) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return true |  | ||||||
| 	} |  | ||||||
| 	return stat.ModTime().After(buildTime) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // isTestStale checks if the test binary is stale and needs to rebuilt.
 |  | ||||||
| // Some of the ideas here are inspired by how Go does staleness checks.
 |  | ||||||
| func isTestStale(cmd golist, binPath, pkgPath string) bool { |  | ||||||
| 	bStat, err := os.Stat(binPath) |  | ||||||
| 	if err != nil { |  | ||||||
| 		glog.V(4).Infof("Couldn't obtain the modified time of the binary %s: %v", binPath, err) |  | ||||||
| 		return true |  | ||||||
| 	} |  | ||||||
| 	buildTime := bStat.ModTime() |  | ||||||
| 
 |  | ||||||
| 	pkgs, err := cmd.pkgInfo([]string{pkgPath}) |  | ||||||
| 	if err != nil || len(pkgs) < 1 { |  | ||||||
| 		glog.V(4).Infof("Couldn't retrieve test package information for package %s: %v", pkgPath, err) |  | ||||||
| 		return false |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return pkgs[0].isNewerThan(cmd, buildTime) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func main() { |  | ||||||
| 	flag.Usage = usage |  | ||||||
| 	flag.Parse() |  | ||||||
| 
 |  | ||||||
| 	cmd := &execcmd{ |  | ||||||
| 		cmd: "go", |  | ||||||
| 		args: []string{ |  | ||||||
| 			"list", |  | ||||||
| 			"-json", |  | ||||||
| 		}, |  | ||||||
| 		env: os.Environ(), |  | ||||||
| 	} |  | ||||||
| 	if !isTestStale(cmd, *binary, *pkgPath) { |  | ||||||
| 		os.Exit(1) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,325 +0,0 @@ | ||||||
| /* |  | ||||||
| Copyright 2016 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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| package main |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"io/ioutil" |  | ||||||
| 	"math/rand" |  | ||||||
| 	"os" |  | ||||||
| 	"path" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"testing" |  | ||||||
| 	"time" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| const ( |  | ||||||
| 	// seed for rand.Source to generate data for files
 |  | ||||||
| 	seed int64 = 42 |  | ||||||
| 
 |  | ||||||
| 	// 1K binary file
 |  | ||||||
| 	binLen = 1024 |  | ||||||
| 
 |  | ||||||
| 	// Directory of the test package relative to $GOPATH
 |  | ||||||
| 	testImportDir = "example.com/proj/pkg" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| var ( |  | ||||||
| 	pastHour = time.Now().Add(-1 * time.Hour) |  | ||||||
| 
 |  | ||||||
| 	// The test package we are testing against
 |  | ||||||
| 	testPkg = path.Join(testImportDir, "test") |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // fakegolist implements the `golist` interface providing fake package information for testing.
 |  | ||||||
| type fakegolist struct { |  | ||||||
| 	dir       string |  | ||||||
| 	importMap map[string]pkg |  | ||||||
| 	testFiles []string |  | ||||||
| 	binfile   string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func newFakegolist() (*fakegolist, error) { |  | ||||||
| 	dir, err := ioutil.TempDir("", "teststale") |  | ||||||
| 	if err != nil { |  | ||||||
| 		// test can't proceed without a temp directory.
 |  | ||||||
| 		return nil, fmt.Errorf("failed to create a temp directory for testing: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Set the temp directory as the $GOPATH
 |  | ||||||
| 	if err := os.Setenv("GOPATH", dir); err != nil { |  | ||||||
| 		// can't proceed without pointing the $GOPATH to the temp directory.
 |  | ||||||
| 		return nil, fmt.Errorf("failed to set \"$GOPATH\" pointing to %q: %v", dir, err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Setup $GOPATH directory layout.
 |  | ||||||
| 	// Yeah! I am bored of repeatedly writing "if err != nil {}"!
 |  | ||||||
| 	if os.MkdirAll(filepath.Join(dir, "bin"), 0750) != nil || |  | ||||||
| 		os.MkdirAll(filepath.Join(dir, "pkg", "linux_amd64"), 0750) != nil || |  | ||||||
| 		os.MkdirAll(filepath.Join(dir, "src"), 0750) != nil { |  | ||||||
| 		return nil, fmt.Errorf("failed to setup the $GOPATH directory structure") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Create a temp file to represent the test binary.
 |  | ||||||
| 	binfile, err := ioutil.TempFile("", "testbin") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, fmt.Errorf("failed to create the temp file to represent the test binary: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Could have used crypto/rand instead, but it doesn't matter.
 |  | ||||||
| 	rr := rand.New(rand.NewSource(42)) |  | ||||||
| 	bin := make([]byte, binLen) |  | ||||||
| 	if _, err = rr.Read(bin); err != nil { |  | ||||||
| 		return nil, fmt.Errorf("couldn't read from the random source: %v", err) |  | ||||||
| 	} |  | ||||||
| 	if _, err := binfile.Write(bin); err != nil { |  | ||||||
| 		return nil, fmt.Errorf("couldn't write to the binary file %q: %v", binfile.Name(), err) |  | ||||||
| 	} |  | ||||||
| 	if err := binfile.Close(); err != nil { |  | ||||||
| 		// It is arguable whether this should be fatal.
 |  | ||||||
| 		return nil, fmt.Errorf("failed to close the binary file %q: %v", binfile.Name(), err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := os.Chtimes(binfile.Name(), time.Now(), time.Now()); err != nil { |  | ||||||
| 		return nil, fmt.Errorf("failed to modify the mtime of the binary file %q: %v", binfile.Name(), err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Create test source files directory.
 |  | ||||||
| 	testdir := filepath.Join(dir, "src", testPkg) |  | ||||||
| 	if err := os.MkdirAll(testdir, 0750); err != nil { |  | ||||||
| 		return nil, fmt.Errorf("failed to create test source directory %q: %v", testdir, err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	fgl := &fakegolist{ |  | ||||||
| 		dir: dir, |  | ||||||
| 		importMap: map[string]pkg{ |  | ||||||
| 			"example.com/proj/pkg/test": { |  | ||||||
| 				Dir:        path.Join(dir, "src", testPkg), |  | ||||||
| 				ImportPath: testPkg, |  | ||||||
| 				Target:     path.Join(dir, "pkg", "linux_amd64", testImportDir, "test.a"), |  | ||||||
| 				Stale:      false, |  | ||||||
| 				TestGoFiles: []string{ |  | ||||||
| 					"foo_test.go", |  | ||||||
| 					"bar_test.go", |  | ||||||
| 				}, |  | ||||||
| 				TestImports: []string{ |  | ||||||
| 					"example.com/proj/pkg/p1", |  | ||||||
| 					"example.com/proj/pkg/p1/c11", |  | ||||||
| 					"example.com/proj/pkg/p2", |  | ||||||
| 					"example.com/proj/cmd/p3/c12/c23", |  | ||||||
| 					"strings", |  | ||||||
| 					"testing", |  | ||||||
| 				}, |  | ||||||
| 				XTestGoFiles: []string{ |  | ||||||
| 					"xfoo_test.go", |  | ||||||
| 					"xbar_test.go", |  | ||||||
| 					"xbaz_test.go", |  | ||||||
| 				}, |  | ||||||
| 				XTestImports: []string{ |  | ||||||
| 					"example.com/proj/pkg/test", |  | ||||||
| 					"example.com/proj/pkg/p1", |  | ||||||
| 					"example.com/proj/cmd/p3/c12/c23", |  | ||||||
| 					"os", |  | ||||||
| 					"testing", |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 			"example.com/proj/pkg/p1":         {Stale: false}, |  | ||||||
| 			"example.com/proj/pkg/p1/c11":     {Stale: false}, |  | ||||||
| 			"example.com/proj/pkg/p2":         {Stale: false}, |  | ||||||
| 			"example.com/proj/cmd/p3/c12/c23": {Stale: false}, |  | ||||||
| 			"strings":                         {Stale: false}, |  | ||||||
| 			"testing":                         {Stale: false}, |  | ||||||
| 			"os":                              {Stale: false}, |  | ||||||
| 		}, |  | ||||||
| 		testFiles: []string{ |  | ||||||
| 			"foo_test.go", |  | ||||||
| 			"bar_test.go", |  | ||||||
| 			"xfoo_test.go", |  | ||||||
| 			"xbar_test.go", |  | ||||||
| 			"xbaz_test.go", |  | ||||||
| 		}, |  | ||||||
| 		binfile: binfile.Name(), |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Create test source files.
 |  | ||||||
| 	for _, fn := range fgl.testFiles { |  | ||||||
| 		fp := filepath.Join(testdir, fn) |  | ||||||
| 		if _, err := os.Create(fp); err != nil { |  | ||||||
| 			return nil, fmt.Errorf("failed to create the test file %q: %v", fp, err) |  | ||||||
| 		} |  | ||||||
| 		if err := os.Chtimes(fp, time.Now(), pastHour); err != nil { |  | ||||||
| 			return nil, fmt.Errorf("failed to modify the mtime of the test file %q: %v", binfile.Name(), err) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return fgl, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (fgl *fakegolist) pkgInfo(pkgPaths []string) ([]pkg, error) { |  | ||||||
| 	var pkgs []pkg |  | ||||||
| 	for _, path := range pkgPaths { |  | ||||||
| 		p, ok := fgl.importMap[path] |  | ||||||
| 		if !ok { |  | ||||||
| 			return nil, fmt.Errorf("package %q not found", path) |  | ||||||
| 		} |  | ||||||
| 		pkgs = append(pkgs, p) |  | ||||||
| 	} |  | ||||||
| 	return pkgs, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (fgl *fakegolist) chMtime(filename string, mtime time.Time) error { |  | ||||||
| 	for _, fn := range fgl.testFiles { |  | ||||||
| 		if fn == filename { |  | ||||||
| 			fp := filepath.Join(fgl.dir, "src", testPkg, fn) |  | ||||||
| 			if err := os.Chtimes(fp, time.Now(), mtime); err != nil { |  | ||||||
| 				return fmt.Errorf("failed to modify the mtime of %q: %v", filename, err) |  | ||||||
| 			} |  | ||||||
| 			return nil |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return fmt.Errorf("file %q not found", filename) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (fgl *fakegolist) chStale(pkg string, stale bool) error { |  | ||||||
| 	if p, ok := fgl.importMap[pkg]; ok { |  | ||||||
| 		p.Stale = stale |  | ||||||
| 		fgl.importMap[pkg] = p |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	return fmt.Errorf("package %q not found", pkg) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (fgl *fakegolist) cleanup() { |  | ||||||
| 	os.RemoveAll(fgl.dir) |  | ||||||
| 	os.Remove(fgl.binfile) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestIsTestStale(t *testing.T) { |  | ||||||
| 	cases := []struct { |  | ||||||
| 		fileMtime    map[string]time.Time |  | ||||||
| 		pkgStaleness map[string]bool |  | ||||||
| 		result       bool |  | ||||||
| 	}{ |  | ||||||
| 		// Basic test: binary is fresh, all modifications were before the binary was built.
 |  | ||||||
| 		{ |  | ||||||
| 			result: false, |  | ||||||
| 		}, |  | ||||||
| 		// A local test file is new, hence binary must be stale.
 |  | ||||||
| 		{ |  | ||||||
| 			fileMtime: map[string]time.Time{ |  | ||||||
| 				"foo_test.go": time.Now().Add(1 * time.Hour), |  | ||||||
| 			}, |  | ||||||
| 			result: true, |  | ||||||
| 		}, |  | ||||||
| 		// Test package is new, so binary must be stale.
 |  | ||||||
| 		{ |  | ||||||
| 			pkgStaleness: map[string]bool{ |  | ||||||
| 				"example.com/proj/pkg/test": true, |  | ||||||
| 			}, |  | ||||||
| 			result: true, |  | ||||||
| 		}, |  | ||||||
| 		// Test package dependencies are new, so binary must be stale.
 |  | ||||||
| 		{ |  | ||||||
| 			pkgStaleness: map[string]bool{ |  | ||||||
| 				"example.com/proj/cmd/p3/c12/c23": true, |  | ||||||
| 				"strings":                         true, |  | ||||||
| 			}, |  | ||||||
| 			result: true, |  | ||||||
| 		}, |  | ||||||
| 		// External test files are new, hence binary must be stale.
 |  | ||||||
| 		{ |  | ||||||
| 			fileMtime: map[string]time.Time{ |  | ||||||
| 				"xfoo_test.go": time.Now().Add(1 * time.Hour), |  | ||||||
| 				"xbar_test.go": time.Now().Add(2 * time.Hour), |  | ||||||
| 			}, |  | ||||||
| 			result: true, |  | ||||||
| 		}, |  | ||||||
| 		// External test dependency is new, so binary must be stale.
 |  | ||||||
| 		{ |  | ||||||
| 			pkgStaleness: map[string]bool{ |  | ||||||
| 				"os": true, |  | ||||||
| 			}, |  | ||||||
| 			result: true, |  | ||||||
| 		}, |  | ||||||
| 		// Multiple source files and dependencies are new, so binary must be stale.
 |  | ||||||
| 		{ |  | ||||||
| 			fileMtime: map[string]time.Time{ |  | ||||||
| 				"foo_test.go":  time.Now().Add(1 * time.Hour), |  | ||||||
| 				"xfoo_test.go": time.Now().Add(2 * time.Hour), |  | ||||||
| 				"xbar_test.go": time.Now().Add(3 * time.Hour), |  | ||||||
| 			}, |  | ||||||
| 			pkgStaleness: map[string]bool{ |  | ||||||
| 				"example.com/proj/pkg/p1":         true, |  | ||||||
| 				"example.com/proj/pkg/p1/c11":     true, |  | ||||||
| 				"example.com/proj/pkg/p2":         true, |  | ||||||
| 				"example.com/proj/cmd/p3/c12/c23": true, |  | ||||||
| 				"strings":                         true, |  | ||||||
| 				"os":                              true, |  | ||||||
| 			}, |  | ||||||
| 			result: true, |  | ||||||
| 		}, |  | ||||||
| 		// Everything is new, so binary must be stale.
 |  | ||||||
| 		{ |  | ||||||
| 			fileMtime: map[string]time.Time{ |  | ||||||
| 				"foo_test.go":  time.Now().Add(3 * time.Hour), |  | ||||||
| 				"bar_test.go":  time.Now().Add(1 * time.Hour), |  | ||||||
| 				"xfoo_test.go": time.Now().Add(2 * time.Hour), |  | ||||||
| 				"xbar_test.go": time.Now().Add(1 * time.Hour), |  | ||||||
| 				"xbaz_test.go": time.Now().Add(2 * time.Hour), |  | ||||||
| 			}, |  | ||||||
| 			pkgStaleness: map[string]bool{ |  | ||||||
| 				"example.com/proj/pkg/p1":         true, |  | ||||||
| 				"example.com/proj/pkg/p1/c11":     true, |  | ||||||
| 				"example.com/proj/pkg/p2":         true, |  | ||||||
| 				"example.com/proj/cmd/p3/c12/c23": true, |  | ||||||
| 				"example.com/proj/pkg/test":       true, |  | ||||||
| 				"strings":                         true, |  | ||||||
| 				"testing":                         true, |  | ||||||
| 				"os":                              true, |  | ||||||
| 			}, |  | ||||||
| 			result: true, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, tc := range cases { |  | ||||||
| 		fgl, err := newFakegolist() |  | ||||||
| 		if err != nil { |  | ||||||
| 			t.Fatalf("failed to setup the test: %v", err) |  | ||||||
| 		} |  | ||||||
| 		defer fgl.cleanup() |  | ||||||
| 
 |  | ||||||
| 		for fn, mtime := range tc.fileMtime { |  | ||||||
| 			if err := fgl.chMtime(fn, mtime); err != nil { |  | ||||||
| 				t.Fatalf("failed to change the mtime of %q: %v", fn, err) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		for pkg, stale := range tc.pkgStaleness { |  | ||||||
| 			if err := fgl.chStale(pkg, stale); err != nil { |  | ||||||
| 				t.Fatalf("failed to change the staleness of %q: %v", pkg, err) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if tc.result != isTestStale(fgl, fgl.binfile, testPkg) { |  | ||||||
| 			if tc.result { |  | ||||||
| 				t.Errorf("Expected test package %q to be stale", testPkg) |  | ||||||
| 			} else { |  | ||||||
| 				t.Errorf("Expected test package %q to be not stale", testPkg) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -18,10 +18,8 @@ set -o errexit | ||||||
| set -o pipefail | set -o pipefail | ||||||
| set -o nounset | set -o nounset | ||||||
| 
 | 
 | ||||||
| if [[ -z "${KUBE_ROOT:-}" ]]; then | export KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. | ||||||
| 	KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. | source "${KUBE_ROOT}/hack/lib/init.sh" | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| source "${KUBE_ROOT}/hack/lib/logging.sh" | source "${KUBE_ROOT}/hack/lib/logging.sh" | ||||||
| 
 | 
 | ||||||
| if [[ ! -d "${KUBE_ROOT}/examples" ]]; then | if [[ ! -d "${KUBE_ROOT}/examples" ]]; then | ||||||
|  | @ -31,7 +29,7 @@ fi | ||||||
| 
 | 
 | ||||||
| # kube::golang::build_kube_toolchain installs the vendored go-bindata in | # kube::golang::build_kube_toolchain installs the vendored go-bindata in | ||||||
| # $GOPATH/bin, so make sure that's explicitly part of our $PATH. | # $GOPATH/bin, so make sure that's explicitly part of our $PATH. | ||||||
| export PATH="${GOPATH}/bin:${PATH}" | export PATH="${KUBE_OUTPUT_BINPATH}:${PATH}" | ||||||
| 
 | 
 | ||||||
| if ! which go-bindata &>/dev/null ; then | if ! which go-bindata &>/dev/null ; then | ||||||
| 	echo "Cannot find go-bindata." | 	echo "Cannot find go-bindata." | ||||||
|  |  | ||||||
|  | @ -213,11 +213,6 @@ readonly KUBE_STATIC_LIBRARIES=( | ||||||
|   kubectl |   kubectl | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| # Add any files with those //generate annotations in the array below. |  | ||||||
| readonly KUBE_BINDATAS=( |  | ||||||
|   test/e2e/generated/gobindata_util.go |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| kube::golang::is_statically_linked_library() { | kube::golang::is_statically_linked_library() { | ||||||
|   local e |   local e | ||||||
|   for e in "${KUBE_STATIC_LIBRARIES[@]}"; do [[ "$1" == *"/$e" ]] && return 0; done; |   for e in "${KUBE_STATIC_LIBRARIES[@]}"; do [[ "$1" == *"/$e" ]] && return 0; done; | ||||||
|  | @ -355,6 +350,7 @@ kube::golang::setup_env() { | ||||||
|   kube::golang::create_gopath_tree |   kube::golang::create_gopath_tree | ||||||
| 
 | 
 | ||||||
|   export GOPATH="${KUBE_GOPATH}" |   export GOPATH="${KUBE_GOPATH}" | ||||||
|  |   export GOCACHE="${KUBE_GOPATH}/cache" | ||||||
| 
 | 
 | ||||||
|   # Append KUBE_EXTRA_GOPATH to the GOPATH if it is defined. |   # Append KUBE_EXTRA_GOPATH to the GOPATH if it is defined. | ||||||
|   if [[ -n ${KUBE_EXTRA_GOPATH:-} ]]; then |   if [[ -n ${KUBE_EXTRA_GOPATH:-} ]]; then | ||||||
|  | @ -416,52 +412,9 @@ kube::golang::place_bins() { | ||||||
|   done |   done | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kube::golang::fallback_if_stdlib_not_installable() { |  | ||||||
|   local go_root_dir=$(go env GOROOT); |  | ||||||
|   local go_host_os=$(go env GOHOSTOS); |  | ||||||
|   local go_host_arch=$(go env GOHOSTARCH); |  | ||||||
|   local cgo_pkg_dir=${go_root_dir}/pkg/${go_host_os}_${go_host_arch}_cgo; |  | ||||||
| 
 |  | ||||||
|   if [ -e ${cgo_pkg_dir} ]; then |  | ||||||
|     return 0; |  | ||||||
|   fi |  | ||||||
| 
 |  | ||||||
|   if [ -w ${go_root_dir}/pkg ]; then |  | ||||||
|     return 0; |  | ||||||
|   fi |  | ||||||
| 
 |  | ||||||
|   kube::log::status "+++ Warning: stdlib pkg with cgo flag not found."; |  | ||||||
|   kube::log::status "+++ Warning: stdlib pkg cannot be rebuilt since ${go_root_dir}/pkg is not writable by `whoami`"; |  | ||||||
|   kube::log::status "+++ Warning: Make ${go_root_dir}/pkg writable for `whoami` for a one-time stdlib install, Or" |  | ||||||
|   kube::log::status "+++ Warning: Rebuild stdlib using the command 'CGO_ENABLED=0 go install -a -installsuffix cgo std'"; |  | ||||||
|   kube::log::status "+++ Falling back to go build, which is slower"; |  | ||||||
| 
 |  | ||||||
|   use_go_build=true |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| # Builds the toolchain necessary for building kube. This needs to be |  | ||||||
| # built only on the host platform. |  | ||||||
| # TODO: Find this a proper home. |  | ||||||
| # Ideally, not a shell script because testing shell scripts is painful. |  | ||||||
| kube::golang::build_kube_toolchain() { |  | ||||||
|   local targets=( |  | ||||||
|     hack/cmd/teststale |  | ||||||
|     vendor/github.com/jteeuwen/go-bindata/go-bindata |  | ||||||
|   ) |  | ||||||
| 
 |  | ||||||
|   local binaries |  | ||||||
|   binaries=($(kube::golang::binaries_from_targets "${targets[@]}")) |  | ||||||
| 
 |  | ||||||
|   kube::log::status "Building the toolchain targets:" "${binaries[@]}" |  | ||||||
|   go install "${goflags[@]:+${goflags[@]}}" \ |  | ||||||
|         -gcflags "${gogcflags}" \ |  | ||||||
|         -ldflags "${goldflags}" \ |  | ||||||
|         "${binaries[@]:+${binaries[@]}}" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| # Try and replicate the native binary placement of go install without | # Try and replicate the native binary placement of go install without | ||||||
| # calling go install. | # calling go install. | ||||||
| kube::golang::output_filename_for_binary() { | kube::golang::outfile_for_binary() { | ||||||
|   local binary=$1 |   local binary=$1 | ||||||
|   local platform=$2 |   local platform=$2 | ||||||
|   local output_path="${KUBE_GOPATH}/bin" |   local output_path="${KUBE_GOPATH}/bin" | ||||||
|  | @ -477,7 +430,6 @@ kube::golang::output_filename_for_binary() { | ||||||
| 
 | 
 | ||||||
| kube::golang::build_binaries_for_platform() { | kube::golang::build_binaries_for_platform() { | ||||||
|   local platform=$1 |   local platform=$1 | ||||||
|   local use_go_build=${2-} |  | ||||||
| 
 | 
 | ||||||
|   local -a statics=() |   local -a statics=() | ||||||
|   local -a nonstatics=() |   local -a nonstatics=() | ||||||
|  | @ -496,79 +448,25 @@ kube::golang::build_binaries_for_platform() { | ||||||
|   done |   done | ||||||
| 
 | 
 | ||||||
|   if [[ "${#statics[@]}" != 0 ]]; then |   if [[ "${#statics[@]}" != 0 ]]; then | ||||||
|       kube::golang::fallback_if_stdlib_not_installable; |     CGO_ENABLED=0 go install -installsuffix static "${goflags[@]:+${goflags[@]}}" \ | ||||||
|  |       -gcflags "${gogcflags}" \ | ||||||
|  |       -ldflags "${goldflags}" \ | ||||||
|  |       "${statics[@]:+${statics[@]}}" | ||||||
|   fi |   fi | ||||||
| 
 | 
 | ||||||
|   if [[ -n ${use_go_build:-} ]]; then |   if [[ "${#nonstatics[@]}" != 0 ]]; then | ||||||
|     kube::log::progress "    " |     go install "${goflags[@]:+${goflags[@]}}" \ | ||||||
|     for binary in "${statics[@]:+${statics[@]}}"; do |       -gcflags "${gogcflags}" \ | ||||||
|       local outfile=$(kube::golang::output_filename_for_binary "${binary}" "${platform}") |       -ldflags "${goldflags}" \ | ||||||
|       CGO_ENABLED=0 go build -o "${outfile}" \ |       "${nonstatics[@]:+${nonstatics[@]}}" | ||||||
|         "${goflags[@]:+${goflags[@]}}" \ |  | ||||||
|         -gcflags "${gogcflags}" \ |  | ||||||
|         -ldflags "${goldflags}" \ |  | ||||||
|         "${binary}" |  | ||||||
|       kube::log::progress "*" |  | ||||||
|     done |  | ||||||
|     for binary in "${nonstatics[@]:+${nonstatics[@]}}"; do |  | ||||||
|       local outfile=$(kube::golang::output_filename_for_binary "${binary}" "${platform}") |  | ||||||
|       go build -o "${outfile}" \ |  | ||||||
|         "${goflags[@]:+${goflags[@]}}" \ |  | ||||||
|         -gcflags "${gogcflags}" \ |  | ||||||
|         -ldflags "${goldflags}" \ |  | ||||||
|         "${binary}" |  | ||||||
|       kube::log::progress "*" |  | ||||||
|     done |  | ||||||
|     kube::log::progress "\n" |  | ||||||
|   else |  | ||||||
|     # Use go install. |  | ||||||
|     if [[ "${#nonstatics[@]}" != 0 ]]; then |  | ||||||
|       go install "${goflags[@]:+${goflags[@]}}" \ |  | ||||||
|         -gcflags "${gogcflags}" \ |  | ||||||
|         -ldflags "${goldflags}" \ |  | ||||||
|         "${nonstatics[@]:+${nonstatics[@]}}" |  | ||||||
|     fi |  | ||||||
|     if [[ "${#statics[@]}" != 0 ]]; then |  | ||||||
|       CGO_ENABLED=0 go install -installsuffix cgo "${goflags[@]:+${goflags[@]}}" \ |  | ||||||
|         -gcflags "${gogcflags}" \ |  | ||||||
|         -ldflags "${goldflags}" \ |  | ||||||
|         "${statics[@]:+${statics[@]}}" |  | ||||||
|     fi |  | ||||||
|   fi |   fi | ||||||
| 
 | 
 | ||||||
|   for test in "${tests[@]:+${tests[@]}}"; do |   for test in "${tests[@]:+${tests[@]}}"; do | ||||||
|     local outfile=$(kube::golang::output_filename_for_binary "${test}" \ |     local outfile=$(kube::golang::outfile_for_binary "${test}" "${platform}") | ||||||
|       "${platform}") |  | ||||||
| 
 |  | ||||||
|     local testpkg="$(dirname ${test})" |     local testpkg="$(dirname ${test})" | ||||||
| 
 | 
 | ||||||
|     # Staleness check always happens on the host machine, so we don't |  | ||||||
|     # have to locate the `teststale` binaries for the other platforms. |  | ||||||
|     # Since we place the host binaries in `$KUBE_GOPATH/bin`, we can |  | ||||||
|     # assume that the binary exists there, if it exists at all. |  | ||||||
|     # Otherwise, something has gone wrong with building the `teststale` |  | ||||||
|     # binary and we should safely proceed building the test binaries |  | ||||||
|     # assuming that they are stale. There is no good reason to error |  | ||||||
|     # out. |  | ||||||
|     if test -x "${KUBE_GOPATH}/bin/teststale" && ! "${KUBE_GOPATH}/bin/teststale" -binary "${outfile}" -package "${testpkg}" |  | ||||||
|     then |  | ||||||
|       continue |  | ||||||
|     fi |  | ||||||
| 
 |  | ||||||
|     # `go test -c` below directly builds the binary. It builds the packages, |  | ||||||
|     # but it never installs them. `go test -i` only installs the dependencies |  | ||||||
|     # of the test, but not the test package itself. So neither `go test -c` |  | ||||||
|     # nor `go test -i` installs, for example, test/e2e.a. And without that, |  | ||||||
|     # doing a staleness check on k8s.io/kubernetes/test/e2e package always |  | ||||||
|     # returns true (always stale). And that's why we need to install the |  | ||||||
|     # test package. |  | ||||||
|     go install "${goflags[@]:+${goflags[@]}}" \ |  | ||||||
|         -gcflags "${gogcflags}" \ |  | ||||||
|         -ldflags "${goldflags}" \ |  | ||||||
|         "${testpkg}" |  | ||||||
| 
 |  | ||||||
|     mkdir -p "$(dirname ${outfile})" |     mkdir -p "$(dirname ${outfile})" | ||||||
|     go test -i -c \ |     go test -c \ | ||||||
|       "${goflags[@]:+${goflags[@]}}" \ |       "${goflags[@]:+${goflags[@]}}" \ | ||||||
|       -gcflags "${gogcflags}" \ |       -gcflags "${gogcflags}" \ | ||||||
|       -ldflags "${goldflags}" \ |       -ldflags "${goldflags}" \ | ||||||
|  | @ -629,14 +527,11 @@ kube::golang::build_binaries() { | ||||||
|     goldflags="${GOLDFLAGS:-} $(kube::version::ldflags)" |     goldflags="${GOLDFLAGS:-} $(kube::version::ldflags)" | ||||||
|     gogcflags="${GOGCFLAGS:-}" |     gogcflags="${GOGCFLAGS:-}" | ||||||
| 
 | 
 | ||||||
|     local use_go_build |  | ||||||
|     local -a targets=() |     local -a targets=() | ||||||
|     local arg |     local arg | ||||||
| 
 | 
 | ||||||
|     for arg; do |     for arg; do | ||||||
|       if [[ "${arg}" == "--use_go_build" ]]; then |       if [[ "${arg}" == -* ]]; then | ||||||
|         use_go_build=true |  | ||||||
|       elif [[ "${arg}" == -* ]]; then |  | ||||||
|         # Assume arguments starting with a dash are flags to pass to go. |         # Assume arguments starting with a dash are flags to pass to go. | ||||||
|         goflags+=("${arg}") |         goflags+=("${arg}") | ||||||
|       else |       else | ||||||
|  | @ -671,26 +566,14 @@ kube::golang::build_binaries() { | ||||||
|       fi |       fi | ||||||
|     fi |     fi | ||||||
| 
 | 
 | ||||||
|     # First build the toolchain before building any other targets |  | ||||||
|     kube::golang::build_kube_toolchain |  | ||||||
| 
 |  | ||||||
|     kube::log::status "Generating bindata:" "${KUBE_BINDATAS[@]}" |  | ||||||
|     for bindata in "${KUBE_BINDATAS[@]}"; do |  | ||||||
|       # Only try to generate bindata if the file exists, since in some cases |  | ||||||
|       # one-off builds of individual directories may exclude some files. |  | ||||||
|       if [[ -f "${KUBE_ROOT}/${bindata}" ]]; then |  | ||||||
|         go generate "${goflags[@]:+${goflags[@]}}" "${KUBE_ROOT}/${bindata}" |  | ||||||
|       fi |  | ||||||
|     done |  | ||||||
| 
 |  | ||||||
|     if [[ "${parallel}" == "true" ]]; then |     if [[ "${parallel}" == "true" ]]; then | ||||||
|       kube::log::status "Building go targets for {${platforms[*]}} in parallel (output will appear in a burst when complete):" "${targets[@]}" |       kube::log::status "Building go targets for {${platforms[*]}} in parallel (output will appear in a burst when complete):" "${targets[@]}" | ||||||
|       local platform |       local platform | ||||||
|       for platform in "${platforms[@]}"; do ( |       for platform in "${platforms[@]}"; do ( | ||||||
|           kube::golang::set_platform_envs "${platform}" |           kube::golang::set_platform_envs "${platform}" | ||||||
|           kube::log::status "${platform}: go build started" |           kube::log::status "${platform}: build started" | ||||||
|           kube::golang::build_binaries_for_platform ${platform} ${use_go_build:-} |           kube::golang::build_binaries_for_platform ${platform} | ||||||
|           kube::log::status "${platform}: go build finished" |           kube::log::status "${platform}: build finished" | ||||||
|         ) &> "/tmp//${platform//\//_}.build" & |         ) &> "/tmp//${platform//\//_}.build" & | ||||||
|       done |       done | ||||||
| 
 | 
 | ||||||
|  | @ -709,7 +592,7 @@ kube::golang::build_binaries() { | ||||||
|         kube::log::status "Building go targets for ${platform}:" "${targets[@]}" |         kube::log::status "Building go targets for ${platform}:" "${targets[@]}" | ||||||
|         ( |         ( | ||||||
|           kube::golang::set_platform_envs "${platform}" |           kube::golang::set_platform_envs "${platform}" | ||||||
|           kube::golang::build_binaries_for_platform ${platform} ${use_go_build:-} |           kube::golang::build_binaries_for_platform ${platform} | ||||||
|         ) |         ) | ||||||
|       done |       done | ||||||
|     fi |     fi | ||||||
|  |  | ||||||
|  | @ -278,12 +278,6 @@ runTests() { | ||||||
|   # command, which is much faster. |   # command, which is much faster. | ||||||
|   if [[ ! ${KUBE_COVER} =~ ^[yY]$ ]]; then |   if [[ ! ${KUBE_COVER} =~ ^[yY]$ ]]; then | ||||||
|     kube::log::status "Running tests without code coverage" |     kube::log::status "Running tests without code coverage" | ||||||
|     # `go test` does not install the things it builds. `go test -i` installs |  | ||||||
|     # the build artifacts but doesn't run the tests.  The two together provide |  | ||||||
|     # a large speedup for tests that do not need to be rebuilt. |  | ||||||
|     go test -i "${goflags[@]:+${goflags[@]}}" \ |  | ||||||
|       ${KUBE_RACE} ${KUBE_TIMEOUT} "${@}" \ |  | ||||||
|      "${testargs[@]:+${testargs[@]}}" |  | ||||||
|     go test "${goflags[@]:+${goflags[@]}}" \ |     go test "${goflags[@]:+${goflags[@]}}" \ | ||||||
|       ${KUBE_RACE} ${KUBE_TIMEOUT} "${@}" \ |       ${KUBE_RACE} ${KUBE_TIMEOUT} "${@}" \ | ||||||
|      "${testargs[@]:+${testargs[@]}}" \ |      "${testargs[@]:+${testargs[@]}}" \ | ||||||
|  | @ -319,21 +313,11 @@ runTests() { | ||||||
|   for path in $(echo $cover_ignore_dirs | sed 's/|/ /g'); do |   for path in $(echo $cover_ignore_dirs | sed 's/|/ /g'); do | ||||||
|       echo -e "skipped\tk8s.io/kubernetes/$path" |       echo -e "skipped\tk8s.io/kubernetes/$path" | ||||||
|   done |   done | ||||||
|   # | 
 | ||||||
|   # `go test` does not install the things it builds. `go test -i` installs |  | ||||||
|   # the build artifacts but doesn't run the tests.  The two together provide |  | ||||||
|   # a large speedup for tests that do not need to be rebuilt. |  | ||||||
|   printf "%s\n" "${@}" \ |   printf "%s\n" "${@}" \ | ||||||
|     | grep -Ev $cover_ignore_dirs \ |     | grep -Ev $cover_ignore_dirs \ | ||||||
|     | xargs -I{} -n 1 -P ${KUBE_COVERPROCS} \ |     | xargs -I{} -n 1 -P ${KUBE_COVERPROCS} \ | ||||||
|     bash -c "set -o pipefail; _pkg=\"\$0\"; _pkg_out=\${_pkg//\//_}; \ |     bash -c "set -o pipefail; _pkg=\"\$0\"; _pkg_out=\${_pkg//\//_}; \ | ||||||
|       go test -i ${goflags[@]:+${goflags[@]}} \ |  | ||||||
|         ${KUBE_RACE} \ |  | ||||||
|         ${KUBE_TIMEOUT} \ |  | ||||||
|         -cover -covermode=\"${KUBE_COVERMODE}\" \ |  | ||||||
|         -coverprofile=\"${cover_report_dir}/\${_pkg}/${cover_profile}\" \ |  | ||||||
|         \"\${_pkg}\" \ |  | ||||||
|         ${testargs[@]:+${testargs[@]}} |  | ||||||
|       go test ${goflags[@]:+${goflags[@]}} \ |       go test ${goflags[@]:+${goflags[@]}} \ | ||||||
|         ${KUBE_RACE} \ |         ${KUBE_RACE} \ | ||||||
|         ${KUBE_TIMEOUT} \ |         ${KUBE_TIMEOUT} \ | ||||||
|  |  | ||||||
|  | @ -25,9 +25,7 @@ kube::golang::verify_go_version | ||||||
| 
 | 
 | ||||||
| cd "${KUBE_ROOT}" | cd "${KUBE_ROOT}" | ||||||
| 
 | 
 | ||||||
| if [[ ! -f test/e2e/generated/bindata.go ]]; then | make --no-print-directory -C "${KUBE_ROOT}" generated_files | ||||||
|   make --no-print-directory -C "${KUBE_ROOT}" verify_generated_files |  | ||||||
| fi |  | ||||||
| 
 | 
 | ||||||
| ret=0 | ret=0 | ||||||
| go run test/typecheck/main.go "$@" || ret=$? | go run test/typecheck/main.go "$@" || ret=$? | ||||||
|  |  | ||||||
|  | @ -16,8 +16,6 @@ limitations under the License. | ||||||
| 
 | 
 | ||||||
| package generated | package generated | ||||||
| 
 | 
 | ||||||
| //go:generate ../../../hack/generate-bindata.sh
 |  | ||||||
| 
 |  | ||||||
| import "github.com/golang/glog" | import "github.com/golang/glog" | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
|  |  | ||||||
|  | @ -544,7 +544,6 @@ k8s.io/kubernetes/cmd/libs/go2idl/go-to-protobuf/protobuf,smarterclayton,0, | ||||||
| k8s.io/kubernetes/cmd/libs/go2idl/openapi-gen/generators,davidopp,1, | k8s.io/kubernetes/cmd/libs/go2idl/openapi-gen/generators,davidopp,1, | ||||||
| k8s.io/kubernetes/examples,Random-Liu,0, | k8s.io/kubernetes/examples,Random-Liu,0, | ||||||
| k8s.io/kubernetes/hack,thockin,1, | k8s.io/kubernetes/hack,thockin,1, | ||||||
| k8s.io/kubernetes/hack/cmd/teststale,thockin,1, |  | ||||||
| k8s.io/kubernetes/pkg/api,Q-Lee,1, | k8s.io/kubernetes/pkg/api,Q-Lee,1, | ||||||
| k8s.io/kubernetes/pkg/api/endpoints,cjcullen,1, | k8s.io/kubernetes/pkg/api/endpoints,cjcullen,1, | ||||||
| k8s.io/kubernetes/pkg/api/events,jlowdermilk,1, | k8s.io/kubernetes/pkg/api/events,jlowdermilk,1, | ||||||
|  |  | ||||||
| 
 | 
		Loading…
	
		Reference in New Issue