Allow CI to embed version info at build time for CLI

- Prevent the server binary from lying about its version number
  by having it report "?.?.?" as its version number for now.
- Later we can devise a way for CI to inject the version number
  for the server into the container image at release time,
  not at build time, since the version number is not known
  at build time.
- Pre-release builds of the binary from before the release stage or
  builds on developer workstation will also report "?.?.?" as its
  version number, which is fine since they are not official releases
  and shouldn't find their way to the public.
This commit is contained in:
Ryan Richard 2020-09-28 09:58:02 -07:00
parent d23ff1f5eb
commit d43744f8e9

View File

@ -14,45 +14,18 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# -----------------------------------------------------------------------------
# Version management helpers. These functions help to set, save and load the
# following variables:
# #
# KUBE_GIT_COMMIT - The git commit id corresponding to this # This has been changed from kube's default version.sh to expect KUBE_GIT_VERSION to be set
# source code. # by the caller. If it is set, it must be a semver version number, and it will be included
# KUBE_GIT_TREE_STATE - "clean" indicates no changes since the git commit id # in the result. If it is not set, then defaults indicating that the version is unknown will
# "dirty" indicates source code changes after the git commit id # be included in the result.
# "archive" indicates the tree was produced by 'git archive' #
# KUBE_GIT_VERSION - "vX.Y" used to indicate the last release version. # These changes are to allow the CI build steps to set the version number at build time
# KUBE_GIT_MAJOR - The major part of the version # without using the original behavior of this script, which was to look at previous git
# KUBE_GIT_MINOR - The minor component of the version # tags to guess the version number.
#
# Grovels through git to set a set of env variables.
#
# If KUBE_GIT_VERSION_FILE, this function will load from that file instead of
# querying git.
kube::version::get_version_vars() { kube::version::get_version_vars() {
if [[ -n ${KUBE_GIT_VERSION_FILE-} ]]; then
kube::version::load_version_vars "${KUBE_GIT_VERSION_FILE}"
return
fi
# If the kubernetes source was exported through git archive, then
# we likely don't have a git tree, but these magic values may be filled in.
# shellcheck disable=SC2016,SC2050
# Disabled as we're not expanding these at runtime, but rather expecting
# that another tool may have expanded these and rewritten the source (!)
if [[ '$Format:%%$' == "%" ]]; then
KUBE_GIT_COMMIT='$Format:%H$'
KUBE_GIT_TREE_STATE="archive"
# When a 'git archive' is exported, the '$Format:%D$' below will look
# something like 'HEAD -> release-1.8, tag: v1.8.3' where then 'tag: '
# can be extracted from it.
if [[ '$Format:%D$' =~ tag:\ (v[^ ,]+) ]]; then
KUBE_GIT_VERSION="${BASH_REMATCH[1]}"
fi
fi
local git=(git --work-tree "${KUBE_ROOT}") local git=(git --work-tree "${KUBE_ROOT}")
if [[ -n ${KUBE_GIT_COMMIT-} ]] || KUBE_GIT_COMMIT=$("${git[@]}" rev-parse "HEAD^{commit}" 2>/dev/null); then if [[ -n ${KUBE_GIT_COMMIT-} ]] || KUBE_GIT_COMMIT=$("${git[@]}" rev-parse "HEAD^{commit}" 2>/dev/null); then
@ -65,28 +38,20 @@ kube::version::get_version_vars() {
fi fi
fi fi
# Use git describe to find the version based on tags. # If KUBE_GIT_VERSION is supplied and is not a valid Semantic Version, then refuse to build.
if [[ -n ${KUBE_GIT_VERSION-} ]] || KUBE_GIT_VERSION=$("${git[@]}" describe --tags --match='v*' --abbrev=14 "${KUBE_GIT_COMMIT}^{commit}" 2>/dev/null); then if [[ -n "${KUBE_GIT_VERSION:-""}" ]]; then
# This translates the "git describe" to an actual semver.org
# compatible semantic version that looks something like this: if ! [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
# v1.1.0-alpha.0.6+84c76d1142ea4d echo "KUBE_GIT_VERSION should be a valid Semantic Version starting with a \"v\". Current value: ${KUBE_GIT_VERSION}"
# echo "Please see more details here: https://semver.org"
# xTODO: We continue calling this "git version" because so many exit 1
# downstream consumers are expecting it there.
#
# These regexes are painful enough in sed...
# We don't want to do them in pure shell, so disable SC2001
# shellcheck disable=SC2001
DASHES_IN_VERSION=$(echo "${KUBE_GIT_VERSION}" | sed "s/[^-]//g")
if [[ "${DASHES_IN_VERSION}" == "---" ]] ; then
# shellcheck disable=SC2001
# We have distance to subversion (v1.1.0-subversion-1-gCommitHash)
KUBE_GIT_VERSION=$(echo "${KUBE_GIT_VERSION}" | sed "s/-\([0-9]\{1,\}\)-g\([0-9a-f]\{14\}\)$/.\1\+\2/")
elif [[ "${DASHES_IN_VERSION}" == "--" ]] ; then
# shellcheck disable=SC2001
# We have distance to base tag (v1.1.0-1-gCommitHash)
KUBE_GIT_VERSION=$(echo "${KUBE_GIT_VERSION}" | sed "s/-g\([0-9a-f]\{14\}\)$/+\1/")
fi fi
if [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then
KUBE_GIT_MAJOR=${BASH_REMATCH[1]}
KUBE_GIT_MINOR=${BASH_REMATCH[2]}
fi
if [[ "${KUBE_GIT_TREE_STATE}" == "dirty" ]]; then if [[ "${KUBE_GIT_TREE_STATE}" == "dirty" ]]; then
# git describe --dirty only considers changes to existing files, but # git describe --dirty only considers changes to existing files, but
# that is problematic since new untracked .go files affect the build, # that is problematic since new untracked .go files affect the build,
@ -94,56 +59,15 @@ kube::version::get_version_vars() {
KUBE_GIT_VERSION+="-dirty" KUBE_GIT_VERSION+="-dirty"
fi fi
else
# Try to match the "git describe" output to a regex to try to extract # KUBE_GIT_VERSION was not supplied
# the "major" and "minor" versions and whether this is the exact tagged KUBE_GIT_VERSION='?.?.?'
# version or whether the tree is between two tagged versions. KUBE_GIT_MAJOR='?'
if [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then KUBE_GIT_MINOR='?'
KUBE_GIT_MAJOR=${BASH_REMATCH[1]}
KUBE_GIT_MINOR=${BASH_REMATCH[2]}
if [[ -n "${BASH_REMATCH[4]}" ]]; then
KUBE_GIT_MINOR+="+"
fi
fi
# If KUBE_GIT_VERSION is not a valid Semantic Version, then refuse to build.
if ! [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
echo "KUBE_GIT_VERSION should be a valid Semantic Version. Current value: ${KUBE_GIT_VERSION}"
echo "Please see more details here: https://semver.org"
exit 1
fi
fi fi
fi fi
} }
# Saves the environment flags to $1
kube::version::save_version_vars() {
local version_file=${1-}
[[ -n ${version_file} ]] || {
echo "!!! Internal error. No file specified in kube::version::save_version_vars"
return 1
}
cat <<EOF >"${version_file}"
KUBE_GIT_COMMIT='${KUBE_GIT_COMMIT-}'
KUBE_GIT_TREE_STATE='${KUBE_GIT_TREE_STATE-}'
KUBE_GIT_VERSION='${KUBE_GIT_VERSION-}'
KUBE_GIT_MAJOR='${KUBE_GIT_MAJOR-}'
KUBE_GIT_MINOR='${KUBE_GIT_MINOR-}'
EOF
}
# Loads up the version variables from file $1
kube::version::load_version_vars() {
local version_file=${1-}
[[ -n ${version_file} ]] || {
echo "!!! Internal error. No file specified in kube::version::load_version_vars"
return 1
}
source "${version_file}"
}
# Prints the value that needs to be passed to the -ldflags parameter of go build # Prints the value that needs to be passed to the -ldflags parameter of go build
# in order to set the Kubernetes based on the git tree status. # in order to set the Kubernetes based on the git tree status.
# IMPORTANT: if you update any of these, also update the lists in # IMPORTANT: if you update any of these, also update the lists in