diff --git a/.circleci/config.yml b/.circleci/config.yml index cbec5a196..11a10b5a0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,6 +25,9 @@ jobs: - run: name: Dependencies command: scripts/validate/gomod.sh + - run: + name: Kubernetes dependency pinning + command: ./scripts/validate/check_version.sh - save_cache: key: validate-{{ checksum "go.mod" }}-{{ checksum "go.sum" }} paths: diff --git a/Makefile b/Makefile index 0bc52a490..2ada10b51 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ release: build goreleaser ##### =====> Utility targets <===== ##### -.PHONY: clean test list cover format docker +.PHONY: clean test list cover format docker check_version mod: @echo "Prune Dependencies..." $Q go mod tidy @@ -119,7 +119,9 @@ format: goimports $Q find . -iname \*.go | grep -v \ -e "^$$" $(addprefix -e ,$(IGNORED_PACKAGES)) | xargs $(gobin_tool) -run $(goimports) -w - +check_version: mod + @echo "Checking kubernetes dependency version pinning" + ./scripts/validate/check_version.sh ##### =====> Internals <===== ##### diff --git a/deps.md b/deps.md new file mode 100644 index 000000000..dc363cee0 --- /dev/null +++ b/deps.md @@ -0,0 +1,27 @@ +# How to Upgrade Deps +Kubernetes takes a pseudo-mono-repo approach to its dependencies. +Because of this, we need to have our go.mod do a bunch of rewrites, +in order to read the actual version + +## Steps +Set the versions of the top level dep `k8s.io/kubernetes` to the release. +A la: + +`k8s.io/kubernetes d32e40e20d167e103faf894261614c5b45c44198` + +Replace all of the "replace" the entries in go.mod with: + +`replace k8s.io/component-base => github.com/kubernetes/kubernetes/staging/src/k8s.io/component-base d32e40e20d167e103faf894261614c5b45c44198` + +You may need to add additional replace entries, based repository list in +the [kubernetes repository](https://github.com/kubernetes/kubernetes/tree/release-1.17/staging). + +You *must* use the sha, not a tag. The reason behind this is that git tags are handled +differently by go modules and they are prefixed with the module name. +More details about this can be found in the (go documentation)[https://github.com/golang/go/wiki/Modules#publishing-a-release] + +Once this is done, run go build ./... + + +### Notes +All of the k8s.io/* references in go.mod should reference v0.0.0 other than k8s.io/kubernetes diff --git a/scripts/validate/check_version.sh b/scripts/validate/check_version.sh new file mode 100755 index 000000000..e76647c58 --- /dev/null +++ b/scripts/validate/check_version.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -euo pipefail + +echo "Checking kubernetes version replacement / pinning" + +readonly kubeversion=$(go list -m -f '{{.Version}}' k8s.io/kubernetes) + +if [[ "${kubeversion}" =~ '^v.*' ]]; then + echo "Kube Version: ${kubeversion} in unexpected format, must start with v" + exit 1 +fi + +echo "Found kubernetes version: ${kubeversion}" + +readonly sha=$(curl http://api.github.com/repos/kubernetes/kubernetes/tags -L -s |jq -r --arg kubeversion "${kubeversion}" '.[] |select (.name==$kubeversion) | .commit.sha') + +if [[ ! "${sha}" =~ ^[0-9a-f]{40}$ ]]; then + echo "Kube Sha: ${sha} in unexpected format" + exit 1 +fi + +echo "Found sha for kubernetes version ${kubeversion}: ${sha}" +# TODO: Check direct deps +# Humans should check the versions reference directly (i.e. bits under require) those should either read +# kubeversion, or v0.0.0 + + +readonly short_sha=$(echo $sha|cut -b1-12) +readonly non_matching_versions=$(go list -m -json k8s.io/...|jq --arg short_sha "${short_sha}" 'select(.Replace != null) | select(.Replace.Version[-12:] != $short_sha)') + + +if [[ ! -z "${non_matching_versions}" ]]; then + echo "Found non-matching versions: ${non_matching_versions}" + exit 1 +fi + +