mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Deprecate kubernetes/kubenetes release infrastructure and doc.
This commit is contained in:
parent
fc3ef9320e
commit
4e07b43d70
569
build/common.sh
569
build/common.sh
@ -409,36 +409,6 @@ function kube::build::destroy_container() {
|
||||
"${DOCKER[@]}" rm -f -v "$1" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
# Validate a release version
|
||||
#
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# version
|
||||
# Returns:
|
||||
# If version is a valid release version
|
||||
# Sets: (e.g. for '1.2.3-alpha.4')
|
||||
# VERSION_MAJOR (e.g. '1')
|
||||
# VERSION_MINOR (e.g. '2')
|
||||
# VERSION_PATCH (e.g. '3')
|
||||
# VERSION_EXTRA (e.g. '-alpha.4')
|
||||
# VERSION_PRERELEASE (e.g. 'alpha')
|
||||
# VERSION_PRERELEASE_REV (e.g. '4')
|
||||
function kube::release::parse_and_validate_release_version() {
|
||||
local -r version_regex="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-(beta|alpha)\\.(0|[1-9][0-9]*))?$"
|
||||
local -r version="${1-}"
|
||||
[[ "${version}" =~ ${version_regex} ]] || {
|
||||
kube::log::error "Invalid release version: '${version}', must match regex ${version_regex}"
|
||||
return 1
|
||||
}
|
||||
VERSION_MAJOR="${BASH_REMATCH[1]}"
|
||||
VERSION_MINOR="${BASH_REMATCH[2]}"
|
||||
VERSION_PATCH="${BASH_REMATCH[3]}"
|
||||
VERSION_EXTRA="${BASH_REMATCH[4]}"
|
||||
VERSION_PRERELEASE="${BASH_REMATCH[5]}"
|
||||
VERSION_PRERELEASE_REV="${BASH_REMATCH[6]}"
|
||||
}
|
||||
|
||||
# Validate a ci version
|
||||
#
|
||||
# Globals:
|
||||
@ -1061,537 +1031,8 @@ function kube::release::create_tarball() {
|
||||
"${TAR}" czf "${tarfile}" -C "${stagingdir}" kubernetes --owner=0 --group=0
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# GCS Release
|
||||
|
||||
function kube::release::gcs::release() {
|
||||
[[ ${KUBE_GCS_UPLOAD_RELEASE} =~ ^[yY]$ ]] || return 0
|
||||
|
||||
kube::release::gcs::verify_prereqs || return 1
|
||||
kube::release::gcs::ensure_release_bucket || return 1
|
||||
kube::release::gcs::copy_release_artifacts || return 1
|
||||
}
|
||||
|
||||
# Verify things are set up for uploading to GCS
|
||||
function kube::release::gcs::verify_prereqs() {
|
||||
if [[ -z "$(which gsutil)" || -z "$(which gcloud)" ]]; then
|
||||
echo "Releasing Kubernetes requires gsutil and gcloud. Please download,"
|
||||
echo "install and authorize through the Google Cloud SDK: "
|
||||
echo
|
||||
echo " https://developers.google.com/cloud/sdk/"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -z "${GCLOUD_ACCOUNT-}" ]]; then
|
||||
GCLOUD_ACCOUNT=$(gcloud config list --format='value(core.account)' 2>/dev/null)
|
||||
fi
|
||||
if [[ -z "${GCLOUD_ACCOUNT-}" ]]; then
|
||||
echo "No account authorized through gcloud. Please fix with:"
|
||||
echo
|
||||
echo " gcloud auth login"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -z "${GCLOUD_PROJECT-}" ]]; then
|
||||
GCLOUD_PROJECT=$(gcloud config list --format='value(core.project)' 2>/dev/null)
|
||||
fi
|
||||
if [[ -z "${GCLOUD_PROJECT-}" ]]; then
|
||||
echo "No account authorized through gcloud. Please fix with:"
|
||||
echo
|
||||
echo " gcloud config set project <project id>"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Create a unique bucket name for releasing Kube and make sure it exists.
|
||||
function kube::release::gcs::ensure_release_bucket() {
|
||||
local project_hash
|
||||
project_hash=$(kube::build::short_hash "$GCLOUD_PROJECT")
|
||||
KUBE_GCS_RELEASE_BUCKET=${KUBE_GCS_RELEASE_BUCKET-kubernetes-releases-${project_hash}}
|
||||
|
||||
if ! gsutil ls "gs://${KUBE_GCS_RELEASE_BUCKET}" >/dev/null 2>&1 ; then
|
||||
echo "Creating Google Cloud Storage bucket: $KUBE_GCS_RELEASE_BUCKET"
|
||||
gsutil mb -p "${GCLOUD_PROJECT}" "gs://${KUBE_GCS_RELEASE_BUCKET}" || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function kube::release::gcs::stage_and_hash() {
|
||||
kube::build::ensure_tar || return 1
|
||||
|
||||
# Split the args into srcs... and dst
|
||||
local -r args=( "$@" )
|
||||
local -r split=$((${#args[@]}-1)) # Split point for src/dst args
|
||||
local -r srcs=( "${args[@]::${split}}" )
|
||||
local -r dst="${args[${split}]}"
|
||||
|
||||
for src in ${srcs[@]}; do
|
||||
srcdir=$(dirname ${src})
|
||||
srcthing=$(basename ${src})
|
||||
mkdir -p ${GCS_STAGE}/${dst} || return 1
|
||||
"${TAR}" c -C ${srcdir} ${srcthing} | "${TAR}" x -C ${GCS_STAGE}/${dst} || return 1
|
||||
done
|
||||
}
|
||||
|
||||
function kube::release::gcs::copy_release_artifacts() {
|
||||
# TODO: This isn't atomic. There will be points in time where there will be
|
||||
# no active release. Also, if something fails, the release could be half-
|
||||
# copied. The real way to do this would perhaps to have some sort of release
|
||||
# version so that we are never overwriting a destination.
|
||||
local -r gcs_destination="gs://${KUBE_GCS_RELEASE_BUCKET}/${KUBE_GCS_RELEASE_PREFIX}"
|
||||
|
||||
kube::log::status "Staging release artifacts to ${GCS_STAGE}"
|
||||
|
||||
rm -rf ${GCS_STAGE} || return 1
|
||||
mkdir -p ${GCS_STAGE} || return 1
|
||||
|
||||
# Stage everything in release directory
|
||||
kube::release::gcs::stage_and_hash "${RELEASE_DIR}"/* . || return 1
|
||||
|
||||
# Having the configure-vm.sh script and GCI code from the GCE cluster
|
||||
# deploy hosted with the release is useful for GKE.
|
||||
kube::release::gcs::stage_and_hash "${RELEASE_STAGE}/full/kubernetes/cluster/gce/configure-vm.sh" extra/gce || return 1
|
||||
kube::release::gcs::stage_and_hash "${RELEASE_STAGE}/full/kubernetes/cluster/gce/gci/node.yaml" extra/gce || return 1
|
||||
kube::release::gcs::stage_and_hash "${RELEASE_STAGE}/full/kubernetes/cluster/gce/gci/master.yaml" extra/gce || return 1
|
||||
kube::release::gcs::stage_and_hash "${RELEASE_STAGE}/full/kubernetes/cluster/gce/gci/configure.sh" extra/gce || return 1
|
||||
|
||||
# Upload the "naked" binaries to GCS. This is useful for install scripts that
|
||||
# download the binaries directly and don't need tars.
|
||||
local platform platforms
|
||||
platforms=($(cd "${RELEASE_STAGE}/client" ; echo *))
|
||||
for platform in "${platforms[@]}"; do
|
||||
local src="${RELEASE_STAGE}/client/${platform}/kubernetes/client/bin/*"
|
||||
local dst="bin/${platform/-//}/"
|
||||
# We assume here the "server package" is a superset of the "client package"
|
||||
if [[ -d "${RELEASE_STAGE}/server/${platform}" ]]; then
|
||||
src="${RELEASE_STAGE}/server/${platform}/kubernetes/server/bin/*"
|
||||
fi
|
||||
kube::release::gcs::stage_and_hash "$src" "$dst" || return 1
|
||||
done
|
||||
|
||||
kube::log::status "Hashing files in ${GCS_STAGE}"
|
||||
find ${GCS_STAGE} -type f | while read path; do
|
||||
kube::release::md5 ${path} > "${path}.md5" || return 1
|
||||
kube::release::sha1 ${path} > "${path}.sha1" || return 1
|
||||
done
|
||||
|
||||
kube::log::status "Copying release artifacts to ${gcs_destination}"
|
||||
|
||||
# First delete all objects at the destination
|
||||
if gsutil ls "${gcs_destination}" >/dev/null 2>&1; then
|
||||
kube::log::error "${gcs_destination} not empty."
|
||||
[[ ${KUBE_GCS_DELETE_EXISTING} =~ ^[yY]$ ]] || {
|
||||
read -p "Delete everything under ${gcs_destination}? [y/n] " -r || {
|
||||
kube::log::status "EOF on prompt. Skipping upload"
|
||||
return
|
||||
}
|
||||
[[ $REPLY =~ ^[yY]$ ]] || {
|
||||
kube::log::status "Skipping upload"
|
||||
return
|
||||
}
|
||||
}
|
||||
kube::log::status "Deleting everything under ${gcs_destination}"
|
||||
gsutil -q -m rm -f -R "${gcs_destination}" || return 1
|
||||
fi
|
||||
|
||||
local gcs_options=()
|
||||
if [[ ${KUBE_GCS_NO_CACHING} =~ ^[yY]$ ]]; then
|
||||
gcs_options=("-h" "Cache-Control:private, max-age=0")
|
||||
fi
|
||||
|
||||
gsutil -q -m "${gcs_options[@]+${gcs_options[@]}}" cp -r "${GCS_STAGE}"/* ${gcs_destination} || return 1
|
||||
|
||||
# TODO(jbeda): Generate an HTML page with links for this release so it is easy
|
||||
# to see it. For extra credit, generate a dynamic page that builds up the
|
||||
# release list using the GCS JSON API. Use Angular and Bootstrap for extra
|
||||
# extra credit.
|
||||
|
||||
if [[ ${KUBE_GCS_MAKE_PUBLIC} =~ ^[yY]$ ]]; then
|
||||
kube::log::status "Marking all uploaded objects public"
|
||||
gsutil -q -m acl ch -R -g all:R "${gcs_destination}" >/dev/null 2>&1 || return 1
|
||||
fi
|
||||
|
||||
gsutil ls -lhr "${gcs_destination}" || return 1
|
||||
|
||||
if [[ -n "${KUBE_GCS_RELEASE_BUCKET_MIRROR:-}" ]] &&
|
||||
[[ "${KUBE_GCS_RELEASE_BUCKET_MIRROR}" != "${KUBE_GCS_RELEASE_BUCKET}" ]]; then
|
||||
local -r gcs_mirror="gs://${KUBE_GCS_RELEASE_BUCKET_MIRROR}/${KUBE_GCS_RELEASE_PREFIX}"
|
||||
kube::log::status "Mirroring build to ${gcs_mirror}"
|
||||
gsutil -q -m "${gcs_options[@]+${gcs_options[@]}}" rsync -d -r "${gcs_destination}" "${gcs_mirror}" || return 1
|
||||
if [[ ${KUBE_GCS_MAKE_PUBLIC} =~ ^[yY]$ ]]; then
|
||||
kube::log::status "Marking all uploaded mirror objects public"
|
||||
gsutil -q -m acl ch -R -g all:R "${gcs_mirror}" >/dev/null 2>&1 || return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Publish a new ci version, (latest,) but only if the release files actually
|
||||
# exist on GCS.
|
||||
#
|
||||
# Globals:
|
||||
# See callees
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# Success
|
||||
function kube::release::gcs::publish_ci() {
|
||||
kube::release::gcs::verify_release_files || return 1
|
||||
|
||||
kube::release::parse_and_validate_ci_version "${KUBE_GCS_PUBLISH_VERSION}" || return 1
|
||||
local -r version_major="${VERSION_MAJOR}"
|
||||
local -r version_minor="${VERSION_MINOR}"
|
||||
|
||||
local -r publish_files=(ci/latest.txt ci/latest-${version_major}.txt ci/latest-${version_major}.${version_minor}.txt)
|
||||
|
||||
for publish_file in ${publish_files[*]}; do
|
||||
# If there's a version that's above the one we're trying to release, don't
|
||||
# do anything, and just try the next one.
|
||||
kube::release::gcs::verify_ci_ge "${publish_file}" || continue
|
||||
kube::release::gcs::publish "${publish_file}" || return 1
|
||||
done
|
||||
}
|
||||
|
||||
# Publish a new official version, (latest or stable,) but only if the release
|
||||
# files actually exist on GCS and the release we're dealing with is newer than
|
||||
# the contents in GCS.
|
||||
#
|
||||
# Globals:
|
||||
# KUBE_GCS_PUBLISH_VERSION
|
||||
# See callees
|
||||
# Arguments:
|
||||
# release_kind: either 'latest' or 'stable'
|
||||
# Returns:
|
||||
# Success
|
||||
function kube::release::gcs::publish_official() {
|
||||
local -r release_kind="${1-}"
|
||||
|
||||
kube::release::gcs::verify_release_files || return 1
|
||||
|
||||
kube::release::parse_and_validate_release_version "${KUBE_GCS_PUBLISH_VERSION}" || return 1
|
||||
local -r version_major="${VERSION_MAJOR}"
|
||||
local -r version_minor="${VERSION_MINOR}"
|
||||
|
||||
local publish_files
|
||||
if [[ "${release_kind}" == 'latest' ]]; then
|
||||
publish_files=(release/latest.txt release/latest-${version_major}.txt release/latest-${version_major}.${version_minor}.txt)
|
||||
elif [[ "${release_kind}" == 'stable' ]]; then
|
||||
publish_files=(release/stable.txt release/stable-${version_major}.txt release/stable-${version_major}.${version_minor}.txt)
|
||||
else
|
||||
kube::log::error "Wrong release_kind: must be 'latest' or 'stable'."
|
||||
return 1
|
||||
fi
|
||||
|
||||
for publish_file in ${publish_files[*]}; do
|
||||
# If there's a version that's above the one we're trying to release, don't
|
||||
# do anything, and just try the next one.
|
||||
kube::release::gcs::verify_release_gt "${publish_file}" || continue
|
||||
kube::release::gcs::publish "${publish_file}" || return 1
|
||||
done
|
||||
}
|
||||
|
||||
# Verify that the release files we expect actually exist.
|
||||
#
|
||||
# Globals:
|
||||
# KUBE_GCS_RELEASE_BUCKET
|
||||
# KUBE_GCS_RELEASE_PREFIX
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# If release files exist
|
||||
function kube::release::gcs::verify_release_files() {
|
||||
local -r release_dir="gs://${KUBE_GCS_RELEASE_BUCKET}/${KUBE_GCS_RELEASE_PREFIX}"
|
||||
if ! gsutil ls "${release_dir}" >/dev/null 2>&1 ; then
|
||||
kube::log::error "Release files don't exist at '${release_dir}'"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if the new version is greater than the version currently published on
|
||||
# GCS.
|
||||
#
|
||||
# Globals:
|
||||
# KUBE_GCS_PUBLISH_VERSION
|
||||
# KUBE_GCS_RELEASE_BUCKET
|
||||
# Arguments:
|
||||
# publish_file: the GCS location to look in
|
||||
# Returns:
|
||||
# If new version is greater than the GCS version
|
||||
#
|
||||
# TODO(16529): This should all be outside of build an in release, and should be
|
||||
# refactored to reduce code duplication. Also consider using strictly nested
|
||||
# if and explicit handling of equals case.
|
||||
function kube::release::gcs::verify_release_gt() {
|
||||
local -r publish_file="${1-}"
|
||||
local -r new_version=${KUBE_GCS_PUBLISH_VERSION}
|
||||
local -r publish_file_dst="gs://${KUBE_GCS_RELEASE_BUCKET}/${publish_file}"
|
||||
|
||||
kube::release::parse_and_validate_release_version "${new_version}" || return 1
|
||||
|
||||
local -r version_major="${VERSION_MAJOR}"
|
||||
local -r version_minor="${VERSION_MINOR}"
|
||||
local -r version_patch="${VERSION_PATCH}"
|
||||
local -r version_prerelease="${VERSION_PRERELEASE}"
|
||||
local -r version_prerelease_rev="${VERSION_PRERELEASE_REV}"
|
||||
|
||||
local gcs_version
|
||||
if gcs_version="$(gsutil cat "${publish_file_dst}")"; then
|
||||
kube::release::parse_and_validate_release_version "${gcs_version}" || {
|
||||
kube::log::error "${publish_file_dst} contains invalid release version, can't compare: '${gcs_version}'"
|
||||
return 1
|
||||
}
|
||||
|
||||
local -r gcs_version_major="${VERSION_MAJOR}"
|
||||
local -r gcs_version_minor="${VERSION_MINOR}"
|
||||
local -r gcs_version_patch="${VERSION_PATCH}"
|
||||
local -r gcs_version_prerelease="${VERSION_PRERELEASE}"
|
||||
local -r gcs_version_prerelease_rev="${VERSION_PRERELEASE_REV}"
|
||||
|
||||
local greater=true
|
||||
if [[ "${version_major}" -lt "${gcs_version_major}" ]]; then
|
||||
greater=false
|
||||
elif [[ "${version_major}" -gt "${gcs_version_major}" ]]; then
|
||||
: # fall out
|
||||
elif [[ "${version_minor}" -lt "${gcs_version_minor}" ]]; then
|
||||
greater=false
|
||||
elif [[ "${version_minor}" -gt "${gcs_version_minor}" ]]; then
|
||||
: # fall out
|
||||
elif [[ "${version_patch}" -lt "${gcs_version_patch}" ]]; then
|
||||
greater=false
|
||||
elif [[ "${version_patch}" -gt "${gcs_version_patch}" ]]; then
|
||||
: # fall out
|
||||
# Use lexicographic (instead of integer) comparison because
|
||||
# version_prerelease is a string, ("alpha" or "beta",) but first check if
|
||||
# either is an official release (i.e. empty prerelease string).
|
||||
#
|
||||
# We have to do this because lexicographically "beta" > "alpha" > "", but
|
||||
# we want official > beta > alpha.
|
||||
elif [[ -n "${version_prerelease}" && -z "${gcs_version_prerelease}" ]]; then
|
||||
greater=false
|
||||
elif [[ -z "${version_prerelease}" && -n "${gcs_version_prerelease}" ]]; then
|
||||
: # fall out
|
||||
elif [[ "${version_prerelease}" < "${gcs_version_prerelease}" ]]; then
|
||||
greater=false
|
||||
elif [[ "${version_prerelease}" > "${gcs_version_prerelease}" ]]; then
|
||||
: # fall out
|
||||
# Finally resort to -le here, since we want strictly-greater-than.
|
||||
elif [[ "${version_prerelease_rev}" -le "${gcs_version_prerelease_rev}" ]]; then
|
||||
greater=false
|
||||
fi
|
||||
|
||||
if [[ "${greater}" != "true" ]]; then
|
||||
kube::log::status "${new_version} (just uploaded) <= ${gcs_version} (latest on GCS), not updating ${publish_file_dst}"
|
||||
return 1
|
||||
else
|
||||
kube::log::status "${new_version} (just uploaded) > ${gcs_version} (latest on GCS), updating ${publish_file_dst}"
|
||||
fi
|
||||
else # gsutil cat failed; file does not exist
|
||||
kube::log::error "Release file '${publish_file_dst}' does not exist. Continuing."
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if the new version is greater than or equal to the version currently
|
||||
# published on GCS. (Ignore the build; if it's different, overwrite anyway.)
|
||||
#
|
||||
# Globals:
|
||||
# KUBE_GCS_PUBLISH_VERSION
|
||||
# KUBE_GCS_RELEASE_BUCKET
|
||||
# Arguments:
|
||||
# publish_file: the GCS location to look in
|
||||
# Returns:
|
||||
# If new version is greater than the GCS version
|
||||
#
|
||||
# TODO(16529): This should all be outside of build an in release, and should be
|
||||
# refactored to reduce code duplication. Also consider using strictly nested
|
||||
# if and explicit handling of equals case.
|
||||
function kube::release::gcs::verify_ci_ge() {
|
||||
local -r publish_file="${1-}"
|
||||
local -r new_version=${KUBE_GCS_PUBLISH_VERSION}
|
||||
local -r publish_file_dst="gs://${KUBE_GCS_RELEASE_BUCKET}/${publish_file}"
|
||||
|
||||
kube::release::parse_and_validate_ci_version "${new_version}" || return 1
|
||||
|
||||
local -r version_major="${VERSION_MAJOR}"
|
||||
local -r version_minor="${VERSION_MINOR}"
|
||||
local -r version_patch="${VERSION_PATCH}"
|
||||
local -r version_prerelease="${VERSION_PRERELEASE}"
|
||||
local -r version_prerelease_rev="${VERSION_PRERELEASE_REV}"
|
||||
local -r version_commits="${VERSION_COMMITS}"
|
||||
|
||||
local gcs_version
|
||||
if gcs_version="$(gsutil cat "${publish_file_dst}")"; then
|
||||
kube::release::parse_and_validate_ci_version "${gcs_version}" || {
|
||||
kube::log::error "${publish_file_dst} contains invalid ci version, can't compare: '${gcs_version}'"
|
||||
return 1
|
||||
}
|
||||
|
||||
local -r gcs_version_major="${VERSION_MAJOR}"
|
||||
local -r gcs_version_minor="${VERSION_MINOR}"
|
||||
local -r gcs_version_patch="${VERSION_PATCH}"
|
||||
local -r gcs_version_prerelease="${VERSION_PRERELEASE}"
|
||||
local -r gcs_version_prerelease_rev="${VERSION_PRERELEASE_REV}"
|
||||
local -r gcs_version_commits="${VERSION_COMMITS}"
|
||||
|
||||
local greater=true
|
||||
if [[ "${version_major}" -lt "${gcs_version_major}" ]]; then
|
||||
greater=false
|
||||
elif [[ "${version_major}" -gt "${gcs_version_major}" ]]; then
|
||||
: # fall out
|
||||
elif [[ "${version_minor}" -lt "${gcs_version_minor}" ]]; then
|
||||
greater=false
|
||||
elif [[ "${version_minor}" -gt "${gcs_version_minor}" ]]; then
|
||||
: # fall out
|
||||
elif [[ "${version_patch}" -lt "${gcs_version_patch}" ]]; then
|
||||
greater=false
|
||||
elif [[ "${version_patch}" -gt "${gcs_version_patch}" ]]; then
|
||||
: # fall out
|
||||
# Use lexicographic (instead of integer) comparison because
|
||||
# version_prerelease is a string, ("alpha" or "beta")
|
||||
elif [[ "${version_prerelease}" < "${gcs_version_prerelease}" ]]; then
|
||||
greater=false
|
||||
elif [[ "${version_prerelease}" > "${gcs_version_prerelease}" ]]; then
|
||||
: # fall out
|
||||
elif [[ "${version_prerelease_rev}" -lt "${gcs_version_prerelease_rev}" ]]; then
|
||||
greater=false
|
||||
elif [[ "${version_prerelease_rev}" -gt "${gcs_version_prerelease_rev}" ]]; then
|
||||
: # fall out
|
||||
# If either version_commits is empty, it will be considered less-than, as
|
||||
# expected, (e.g. 1.2.3-beta < 1.2.3-beta.1).
|
||||
elif [[ "${version_commits}" -lt "${gcs_version_commits}" ]]; then
|
||||
greater=false
|
||||
fi
|
||||
|
||||
if [[ "${greater}" != "true" ]]; then
|
||||
kube::log::status "${new_version} (just uploaded) < ${gcs_version} (latest on GCS), not updating ${publish_file_dst}"
|
||||
return 1
|
||||
else
|
||||
kube::log::status "${new_version} (just uploaded) >= ${gcs_version} (latest on GCS), updating ${publish_file_dst}"
|
||||
fi
|
||||
else # gsutil cat failed; file does not exist
|
||||
kube::log::error "File '${publish_file_dst}' does not exist. Continuing."
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Publish a release to GCS: upload a version file, if KUBE_GCS_MAKE_PUBLIC,
|
||||
# make it public, and verify the result.
|
||||
#
|
||||
# Globals:
|
||||
# KUBE_GCS_RELEASE_BUCKET
|
||||
# RELEASE_STAGE
|
||||
# KUBE_GCS_PUBLISH_VERSION
|
||||
# KUBE_GCS_MAKE_PUBLIC
|
||||
# Arguments:
|
||||
# publish_file: the GCS location to look in
|
||||
# Returns:
|
||||
# If new version is greater than the GCS version
|
||||
function kube::release::gcs::publish() {
|
||||
local -r publish_file="${1-}"
|
||||
|
||||
kube::release::gcs::publish_to_bucket "${KUBE_GCS_RELEASE_BUCKET}" "${publish_file}" || return 1
|
||||
|
||||
if [[ -n "${KUBE_GCS_RELEASE_BUCKET_MIRROR:-}" ]] &&
|
||||
[[ "${KUBE_GCS_RELEASE_BUCKET_MIRROR}" != "${KUBE_GCS_RELEASE_BUCKET}" ]]; then
|
||||
kube::release::gcs::publish_to_bucket "${KUBE_GCS_RELEASE_BUCKET_MIRROR}" "${publish_file}" || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function kube::release::gcs::publish_to_bucket() {
|
||||
local -r publish_bucket="${1}"
|
||||
local -r publish_file="${2}"
|
||||
local -r publish_file_dst="gs://${publish_bucket}/${publish_file}"
|
||||
|
||||
mkdir -p "${RELEASE_STAGE}/upload" || return 1
|
||||
echo "${KUBE_GCS_PUBLISH_VERSION}" > "${RELEASE_STAGE}/upload/latest" || return 1
|
||||
|
||||
gsutil -m cp "${RELEASE_STAGE}/upload/latest" "${publish_file_dst}" || return 1
|
||||
|
||||
local contents
|
||||
if [[ ${KUBE_GCS_MAKE_PUBLIC} =~ ^[yY]$ ]]; then
|
||||
kube::log::status "Making uploaded version file public and non-cacheable."
|
||||
gsutil acl ch -R -g all:R "${publish_file_dst}" >/dev/null 2>&1 || return 1
|
||||
gsutil setmeta -h "Cache-Control:private, max-age=0" "${publish_file_dst}" >/dev/null 2>&1 || return 1
|
||||
# If public, validate public link
|
||||
local -r public_link="https://storage.googleapis.com/${publish_bucket}/${publish_file}"
|
||||
kube::log::status "Validating uploaded version file at ${public_link}"
|
||||
contents="$(curl -s "${public_link}")"
|
||||
else
|
||||
# If not public, validate using gsutil
|
||||
kube::log::status "Validating uploaded version file at ${publish_file_dst}"
|
||||
contents="$(gsutil cat "${publish_file_dst}")"
|
||||
fi
|
||||
if [[ "${contents}" == "${KUBE_GCS_PUBLISH_VERSION}" ]]; then
|
||||
kube::log::status "Contents as expected: ${contents}"
|
||||
else
|
||||
kube::log::error "Expected contents of file to be ${KUBE_GCS_PUBLISH_VERSION}, but got ${contents}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Docker Release
|
||||
|
||||
# Releases all docker images to a docker registry specified by KUBE_DOCKER_REGISTRY
|
||||
# using tag KUBE_DOCKER_IMAGE_TAG.
|
||||
#
|
||||
# Globals:
|
||||
# KUBE_DOCKER_REGISTRY
|
||||
# KUBE_DOCKER_IMAGE_TAG
|
||||
# KUBE_SERVER_PLATFORMS
|
||||
# Returns:
|
||||
# If new pushing docker images was successful.
|
||||
function kube::release::docker::release() {
|
||||
local binaries=(
|
||||
"kube-apiserver"
|
||||
"kube-controller-manager"
|
||||
"kube-scheduler"
|
||||
"kube-proxy"
|
||||
"hyperkube"
|
||||
)
|
||||
|
||||
local docker_push_cmd=("${DOCKER[@]}")
|
||||
if [[ "${KUBE_DOCKER_REGISTRY}" == "gcr.io/"* ]]; then
|
||||
docker_push_cmd=("gcloud" "docker")
|
||||
fi
|
||||
|
||||
if [[ "${KUBE_DOCKER_REGISTRY}" == "gcr.io/google_containers" ]]; then
|
||||
# Activate credentials for the k8s.production.user@gmail.com
|
||||
gcloud config set account k8s.production.user@gmail.com
|
||||
fi
|
||||
|
||||
for arch in "${KUBE_SERVER_PLATFORMS[@]##*/}"; do
|
||||
for binary in "${binaries[@]}"; do
|
||||
|
||||
# TODO(IBM): Enable hyperkube builds for ppc64le again
|
||||
if [[ ${binary} != "hyperkube" || ${arch} != "ppc64le" ]]; then
|
||||
|
||||
local docker_target="${KUBE_DOCKER_REGISTRY}/${binary}-${arch}:${KUBE_DOCKER_IMAGE_TAG}"
|
||||
kube::log::status "Pushing ${binary} to ${docker_target}"
|
||||
"${docker_push_cmd[@]}" push "${docker_target}"
|
||||
|
||||
# If we have a amd64 docker image. Tag it without -amd64 also and push it for compatibility with earlier versions
|
||||
if [[ ${arch} == "amd64" ]]; then
|
||||
local legacy_docker_target="${KUBE_DOCKER_REGISTRY}/${binary}:${KUBE_DOCKER_IMAGE_TAG}"
|
||||
|
||||
"${DOCKER[@]}" tag -f "${docker_target}" "${legacy_docker_target}" 2>/dev/null
|
||||
|
||||
kube::log::status "Pushing ${binary} to ${legacy_docker_target}"
|
||||
"${docker_push_cmd[@]}" push "${legacy_docker_target}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
if [[ "${KUBE_DOCKER_REGISTRY}" == "gcr.io/google_containers" ]]; then
|
||||
# Activate default account
|
||||
gcloud config set account ${USER}@google.com
|
||||
fi
|
||||
}
|
||||
|
||||
function kube::release::gcloud_account_is_active() {
|
||||
local -r account="${1-}"
|
||||
if [[ "$(gcloud config list --format='value(core.account)')" == "${account}" ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
###############################################################################
|
||||
# Most of the ::release:: namespace functions have been moved to
|
||||
# github.com/kubernetes/release. Have a look in that repo and specifically in
|
||||
# lib/releaselib.sh for ::release::-related functionality.
|
||||
###############################################################################
|
||||
|
@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2014 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.
|
||||
|
||||
# Clean out the output directory on the docker host.
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
function pop_dir {
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||
source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||
|
||||
if [[ -z "${1:-}" ]]; then
|
||||
echo "Usage: ${0} <last-release-pr-number> <current-release-pr-number> --api-token=$TOKEN [opts]"
|
||||
echo "To create a GitHub API token, see https://github.com/settings/tokens"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pushd . > /dev/null
|
||||
trap 'pop_dir' INT TERM EXIT
|
||||
|
||||
kube::golang::build_binaries contrib/release-notes
|
||||
kube::golang::place_bins
|
||||
echo "Fetching release notes"
|
||||
releasenotes=$(kube::util::find-binary "release-notes")
|
||||
"${releasenotes}" --last-release-pr=${1} --current-release-pr=${2} ${@}
|
||||
|
@ -1,34 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2015 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.
|
||||
|
||||
# Pushes a development build to a directory in your current project,
|
||||
# pushing to something like:
|
||||
# gs://kubernetes-releases-3fda2/devel/v0.8.0-437-g7f147ed/
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
LATEST=$(git describe)
|
||||
KUBE_GCS_NO_CACHING=n
|
||||
KUBE_GCS_MAKE_PUBLIC=y
|
||||
KUBE_GCS_UPLOAD_RELEASE=y
|
||||
KUBE_GCS_RELEASE_PREFIX="devel/${LATEST}"
|
||||
|
||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||
source "${KUBE_ROOT}/build/common.sh"
|
||||
|
||||
kube::release::gcs::release
|
@ -1,59 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2014 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.
|
||||
|
||||
# Pushes an official release to our official release location
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
if [[ "$#" -lt 1 ]]; then
|
||||
echo "Usage: ${0} <version> [<type>]"
|
||||
echo "(<type> defaults to 'latest')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
KUBE_RELEASE_VERSION="${1-}"
|
||||
KUBE_RELEASE_TYPE="${2:-"latest"}"
|
||||
|
||||
KUBE_GCS_NO_CACHING='n'
|
||||
KUBE_GCS_MAKE_PUBLIC='y'
|
||||
KUBE_GCS_UPLOAD_RELEASE='y'
|
||||
KUBE_GCS_RELEASE_BUCKET='kubernetes-release'
|
||||
KUBE_GCS_RELEASE_PREFIX="release/${KUBE_RELEASE_VERSION}"
|
||||
KUBE_GCS_PUBLISH_VERSION="${KUBE_RELEASE_VERSION}"
|
||||
|
||||
KUBE_DOCKER_REGISTRY="gcr.io/google_containers"
|
||||
KUBE_DOCKER_IMAGE_TAG="${KUBE_RELEASE_VERSION}"
|
||||
KUBE_GCLOUD_PRODUCTION_ACCOUNT="k8s.production.user@gmail.com"
|
||||
|
||||
KUBE_ROOT="$(dirname "${BASH_SOURCE}")/.."
|
||||
source "${KUBE_ROOT}/build/common.sh"
|
||||
|
||||
if "${KUBE_ROOT}/cluster/kubectl.sh" 'version' | grep 'Client' | grep 'dirty'; then
|
||||
echo "!!! Tag at invalid point, or something else is bad. Build is dirty. Don't push this build." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! kube::release::gcloud_account_is_active "${KUBE_GCLOUD_PRODUCTION_ACCOUNT}"; then
|
||||
kube::log::error "Pushing images to gcr.io/google_containers requires being logged in as ${KUBE_GCLOUD_PRODUCTION_ACCOUNT}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
kube::release::parse_and_validate_release_version "${KUBE_RELEASE_VERSION}"
|
||||
kube::release::gcs::release
|
||||
kube::release::docker::release
|
||||
kube::release::gcs::publish_official $KUBE_RELEASE_TYPE
|
@ -110,11 +110,7 @@ Guide](../admin/README.md).
|
||||
|
||||
## Building releases
|
||||
|
||||
* **Making release notes** ([making-release-notes.md](making-release-notes.md)): Generating release notes for a new release.
|
||||
|
||||
* **Releasing Kubernetes** ([releasing.md](releasing.md)): How to create a Kubernetes release (as in version)
|
||||
and how the version information gets embedded into the built binaries.
|
||||
|
||||
See the [kubernetes/release](https://github.com/kubernetes/release) repository for details on creating releases and related tools and helper scripts.
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
[]()
|
||||
|
@ -1,86 +0,0 @@
|
||||
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
|
||||
|
||||
<!-- BEGIN STRIP_FOR_RELEASE -->
|
||||
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
|
||||
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
|
||||
|
||||
If you are using a released version of Kubernetes, you should
|
||||
refer to the docs that go with that version.
|
||||
|
||||
<!-- TAG RELEASE_LINK, added by the munger automatically -->
|
||||
<strong>
|
||||
The latest release of this document can be found
|
||||
[here](http://releases.k8s.io/release-1.4/docs/devel/making-release-notes.md).
|
||||
|
||||
Documentation for other releases can be found at
|
||||
[releases.k8s.io](http://releases.k8s.io).
|
||||
</strong>
|
||||
--
|
||||
|
||||
<!-- END STRIP_FOR_RELEASE -->
|
||||
|
||||
<!-- END MUNGE: UNVERSIONED_WARNING -->
|
||||
|
||||
## Making release notes
|
||||
|
||||
This documents the process for making release notes for a release.
|
||||
|
||||
### 1) Note the PR number of the previous release
|
||||
|
||||
Find the most-recent PR that was merged with the previous .0 release. Remember
|
||||
this as $LASTPR.
|
||||
|
||||
- _TODO_: Figure out a way to record this somewhere to save the next
|
||||
release engineer time.
|
||||
|
||||
Find the most-recent PR that was merged with the current .0 release. Remember
|
||||
this as $CURRENTPR.
|
||||
|
||||
### 2) Run the release-notes tool
|
||||
|
||||
```bash
|
||||
${KUBERNETES_ROOT}/build/make-release-notes.sh $LASTPR $CURRENTPR
|
||||
```
|
||||
|
||||
### 3) Trim the release notes
|
||||
|
||||
This generates a list of the entire set of PRs merged since the last minor
|
||||
release. It is likely long and many PRs aren't worth mentioning. If any of the
|
||||
PRs were cherrypicked into patches on the last minor release, you should exclude
|
||||
them from the current release's notes.
|
||||
|
||||
Open up `candidate-notes.md` in your favorite editor.
|
||||
|
||||
Remove, regroup, organize to your hearts content.
|
||||
|
||||
|
||||
### 4) Update CHANGELOG.md
|
||||
|
||||
With the final markdown all set, cut and paste it to the top of `CHANGELOG.md`
|
||||
|
||||
### 5) Update the Release page
|
||||
|
||||
* Switch to the [releases](https://github.com/kubernetes/kubernetes/releases)
|
||||
page.
|
||||
|
||||
* Open up the release you are working on.
|
||||
|
||||
* Cut and paste the final markdown from above into the release notes
|
||||
|
||||
* Press Save.
|
||||
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
[]()
|
||||
<!-- END MUNGE: GENERATED_ANALYTICS -->
|
@ -1,309 +0,0 @@
|
||||
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
|
||||
|
||||
<!-- BEGIN STRIP_FOR_RELEASE -->
|
||||
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
|
||||
width="25" height="25">
|
||||
|
||||
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
|
||||
|
||||
If you are using a released version of Kubernetes, you should
|
||||
refer to the docs that go with that version.
|
||||
|
||||
<!-- TAG RELEASE_LINK, added by the munger automatically -->
|
||||
<strong>
|
||||
The latest release of this document can be found
|
||||
[here](http://releases.k8s.io/release-1.4/docs/devel/releasing.md).
|
||||
|
||||
Documentation for other releases can be found at
|
||||
[releases.k8s.io](http://releases.k8s.io).
|
||||
</strong>
|
||||
--
|
||||
|
||||
<!-- END STRIP_FOR_RELEASE -->
|
||||
|
||||
<!-- END MUNGE: UNVERSIONED_WARNING -->
|
||||
|
||||
# Releasing Kubernetes
|
||||
|
||||
This document explains how to cut a release, and the theory behind it. If you
|
||||
just want to cut a release and move on with your life, you can stop reading
|
||||
after the first section.
|
||||
|
||||
## How to cut a Kubernetes release
|
||||
|
||||
Regardless of whether you are cutting a major or minor version, cutting a
|
||||
release breaks down into four pieces:
|
||||
|
||||
1. selecting release components;
|
||||
1. cutting/branching the release;
|
||||
1. building and pushing the binaries; and
|
||||
1. publishing binaries and release notes.
|
||||
1. updating the master branch.
|
||||
|
||||
You should progress in this strict order.
|
||||
|
||||
### Selecting release components
|
||||
|
||||
First, figure out what kind of release you're doing, what branch you're cutting
|
||||
from, and other prerequisites.
|
||||
|
||||
* Alpha releases (`vX.Y.0-alpha.W`) are cut directly from `master`.
|
||||
* Alpha releases don't require anything besides green tests, (see below).
|
||||
* Beta releases (`vX.Y.Z-beta.W`) are cut from their respective release branch,
|
||||
`release-X.Y`.
|
||||
* Make sure all necessary cherry picks have been resolved. You should ensure
|
||||
that all outstanding cherry picks have been reviewed and merged and the
|
||||
branch validated on Jenkins. See [Cherry Picks](cherry-picks.md) for more
|
||||
information on how to manage cherry picks prior to cutting the release.
|
||||
* Beta releases also require green tests, (see below).
|
||||
* Official releases (`vX.Y.Z`) are cut from their respective release branch,
|
||||
`release-X.Y`.
|
||||
* Official releases should be similar or identical to their respective beta
|
||||
releases, so have a look at the cherry picks that have been merged since
|
||||
the beta release and question everything you find.
|
||||
* Official releases also require green tests, (see below).
|
||||
* New release series are also cut directly from `master`.
|
||||
* **This is a big deal!** If you're reading this doc for the first time, you
|
||||
probably shouldn't be doing this release, and should talk to someone on the
|
||||
release team.
|
||||
* New release series cut a new release branch, `release-X.Y`, off of
|
||||
`master`, and also release the first beta in the series, `vX.Y.0-beta.0`.
|
||||
* Every change in the `vX.Y` series from this point on will have to be
|
||||
cherry picked, so be sure you want to do this before proceeding.
|
||||
* You should still look for green tests, (see below).
|
||||
|
||||
No matter what you're cutting, you're going to want to look at
|
||||
[Jenkins](http://kubekins.dls.corp.google.com/) (Google internal only). Figure
|
||||
out what branch you're cutting from, (see above,) and look at the critical jobs
|
||||
building from that branch. First glance through builds and look for nice solid
|
||||
rows of green builds, and then check temporally with the other critical builds
|
||||
to make sure they're solid around then as well.
|
||||
|
||||
If you're doing an alpha release or cutting a new release series, you can
|
||||
choose an arbitrary build. If you are doing an official release, you have to
|
||||
release from HEAD of the branch, (because you have to do some version-rev
|
||||
commits,) so choose the latest build on the release branch. (Remember, that
|
||||
branch should be frozen.)
|
||||
|
||||
Once you find some greens, you can find the build hash for a build by looking at
|
||||
the Full Console Output and searching for `build_version=`. You should see a line:
|
||||
|
||||
```console
|
||||
build_version=v1.2.0-alpha.2.164+b44c7d79d6c9bb
|
||||
```
|
||||
|
||||
Or, if you're cutting from a release branch (i.e. doing an official release),
|
||||
|
||||
```console
|
||||
build_version=v1.1.0-beta.567+d79d6c9bbb44c7
|
||||
```
|
||||
|
||||
Please note that `build_version` was called `githash` versions prior to v1.2.
|
||||
|
||||
Because Jenkins builds frequently, if you're looking between jobs
|
||||
(e.g. `kubernetes-e2e-gke-ci` and `kubernetes-e2e-gce`), there may be no single
|
||||
`build_version` that's been run on both jobs. In that case, take the a green
|
||||
`kubernetes-e2e-gce` build (but please check that it corresponds to a temporally
|
||||
similar build that's green on `kubernetes-e2e-gke-ci`). Lastly, if you're having
|
||||
trouble understanding why the GKE continuous integration clusters are failing
|
||||
and you're trying to cut a release, don't hesitate to contact the GKE
|
||||
oncall.
|
||||
|
||||
Before proceeding to the next step:
|
||||
|
||||
```sh
|
||||
export BUILD_VERSION=v1.2.0-alpha.2.164+b44c7d79d6c9bb
|
||||
```
|
||||
|
||||
Where `v1.2.0-alpha.2.164+b44c7d79d6c9bb` is the build hash you decided on. This
|
||||
will become your release point.
|
||||
|
||||
### Cutting/branching the release
|
||||
|
||||
You'll need the latest version of the releasing tools:
|
||||
|
||||
```console
|
||||
git clone git@github.com:kubernetes/kubernetes.git
|
||||
cd kubernetes
|
||||
```
|
||||
|
||||
or `git fetch upstream && git checkout upstream/master` from an existing repo.
|
||||
|
||||
Decide what version you're cutting and export it:
|
||||
|
||||
- alpha release: `export RELEASE_VERSION="vX.Y.0-alpha.W"`;
|
||||
- beta release: `export RELEASE_VERSION="vX.Y.Z-beta.W"`;
|
||||
- official release: `export RELEASE_VERSION="vX.Y.Z"`;
|
||||
- new release series: `export RELEASE_VERSION="vX.Y"`.
|
||||
|
||||
Then, run
|
||||
|
||||
```console
|
||||
./release/cut-official-release.sh "${RELEASE_VERSION}" "${BUILD_VERSION}"
|
||||
```
|
||||
|
||||
This will do a dry run of the release. It will give you instructions at the
|
||||
end for `pushd`ing into the dry-run directory and having a look around.
|
||||
`pushd` into the directory and make sure everything looks as you expect:
|
||||
|
||||
```console
|
||||
git log "${RELEASE_VERSION}" # do you see the commit you expect?
|
||||
make release
|
||||
./cluster/kubectl.sh version -c
|
||||
```
|
||||
|
||||
If you're satisfied with the result of the script, go back to `upstream/master`
|
||||
run
|
||||
|
||||
```console
|
||||
./release/cut-official-release.sh "${RELEASE_VERSION}" "${BUILD_VERSION}" --no-dry-run
|
||||
```
|
||||
|
||||
and follow the instructions.
|
||||
|
||||
### Publishing binaries and release notes
|
||||
|
||||
Only publish a beta release if it's a standalone pre-release (*not*
|
||||
vX.Y.Z-beta.0). We create beta tags after we do official releases to
|
||||
maintain proper semantic versioning, but we don't publish these beta releases.
|
||||
|
||||
The script you ran above will prompt you to take any remaining steps to push
|
||||
tars, and will also give you a template for the release notes. Compose an
|
||||
email to the team with the template. Figure out what the PR numbers for this
|
||||
release and last release are, and get an api-token from GitHub
|
||||
(https://github.com/settings/tokens). From a clone of
|
||||
[kubernetes/contrib](https://github.com/kubernetes/contrib),
|
||||
|
||||
```
|
||||
go run release-notes/release-notes.go --last-release-pr=<number> --current-release-pr=<number> --api-token=<token> --base=<release-branch>
|
||||
```
|
||||
|
||||
where `<release-branch>` is `master` for alpha releases and `release-X.Y` for beta and official releases.
|
||||
|
||||
**If this is a first official release (vX.Y.0)**, look through the release
|
||||
notes for all of the alpha releases since the last cycle, and include anything
|
||||
important in release notes.
|
||||
|
||||
Feel free to edit the notes, (e.g. cherry picks should generally just have the
|
||||
same title as the original PR).
|
||||
|
||||
Send the email out, letting people know these are the draft release notes. If
|
||||
they want to change anything, they should update the appropriate PRs with the
|
||||
`release-note` label.
|
||||
|
||||
When you're ready to announce the release, [create a GitHub
|
||||
release](https://github.com/kubernetes/kubernetes/releases/new):
|
||||
|
||||
1. pick the appropriate tag;
|
||||
1. check "This is a pre-release" if it's an alpha or beta release;
|
||||
1. fill in the release title from the draft;
|
||||
1. re-run the appropriate release notes tool(s) to pick up any changes people
|
||||
have made;
|
||||
1. find the appropriate `kubernetes.tar.gz` in [GCS bucket](https://console.developers.google.com/storage/browser/kubernetes-release/release/),
|
||||
download it, double check the hash (compare to what you had in the release
|
||||
notes draft), and attach it to the release; and
|
||||
1. publish!
|
||||
|
||||
### Manual tasks for new release series
|
||||
|
||||
*TODO(#20946) Burn this list down.*
|
||||
|
||||
If you are cutting a new release series, there are a few tasks that haven't yet
|
||||
been automated that need to happen after the branch has been cut:
|
||||
|
||||
1. Update the master branch constant for doc generation: change the
|
||||
`latestReleaseBranch` in `cmd/mungedocs/mungedocs.go` to the new release
|
||||
branch (`release-X.Y`), run `hack/update-generated-docs.sh`. This will let
|
||||
the unversioned warning in docs point to the latest release series. Please
|
||||
send the changes as a PR titled "Update the latestReleaseBranch to
|
||||
release-X.Y in the munger".
|
||||
1. Send a note to the test team (@kubernetes/goog-testing) that a new branch
|
||||
has been created.
|
||||
1. There is currently much work being done on our Jenkins infrastructure
|
||||
and configs. Eventually we could have a relatively simple interface
|
||||
to make this change or a way to automatically use the new branch.
|
||||
See [recent Issue #22672](https://github.com/kubernetes/kubernetes/issues/22672).
|
||||
1. You can provide this guidance in the email to aid in the setup:
|
||||
1. See [End-2-End Testing in Kubernetes](e2e-tests.md) for the test jobs
|
||||
that should be running in CI, which are under version control in
|
||||
`hack/jenkins/e2e.sh` (on the release branch) and
|
||||
`hack/jenkins/job-configs/kubernetes-jenkins/kubernetes-e2e.yaml`
|
||||
(in `master`). You'll want to munge these for the release
|
||||
branch so that, as we cherry-pick fixes onto the branch, we know that
|
||||
it builds, etc. (Talk with @ihmccreery for more details.)
|
||||
1. Make sure all features that are supposed to be GA are covered by tests,
|
||||
but remove feature tests on the release branch for features that aren't
|
||||
GA. You can use `hack/list-feature-tests.sh` to see a list of tests
|
||||
labeled as `[Feature:.+]`; make sure that these are all either
|
||||
covered in CI jobs on the release branch or are experimental
|
||||
features. (The answer should already be 'yes', but this is a
|
||||
good time to reconcile.)
|
||||
1. Make a dashboard in Jenkins that contains all of the jobs for this
|
||||
release cycle, and also add them to Critical Builds. (Don't add
|
||||
them to the merge-bot blockers; see kubernetes/contrib#156.)
|
||||
|
||||
|
||||
## Injecting Version into Binaries
|
||||
|
||||
*Please note that this information may be out of date. The scripts are the
|
||||
authoritative source on how version injection works.*
|
||||
|
||||
Kubernetes may be built from either a git tree or from a tarball. We use
|
||||
`make` to encapsulate a number of build steps into a single command. This
|
||||
includes generating code, which means that tools like `go build` might work
|
||||
(once files are generated) but might be using stale generated code. `make` is
|
||||
the supported way to build.
|
||||
|
||||
When building from git, we want to be able to insert specific information about
|
||||
the build tree at build time. In particular, we want to use the output of `git
|
||||
describe` to generate the version of Kubernetes and the status of the build
|
||||
tree (add a `-dirty` prefix if the tree was modified.)
|
||||
|
||||
When building from a tarball or using the Go build system, we will not have
|
||||
access to the information about the git tree, but we still want to be able to
|
||||
tell whether this build corresponds to an exact release (e.g. v0.3) or is
|
||||
between releases (e.g. at some point in development between v0.3 and v0.4).
|
||||
|
||||
In order to cover the different build cases, we start by providing information
|
||||
that can be used when using only Go build tools or when we do not have the git
|
||||
version information available.
|
||||
|
||||
To be able to provide a meaningful version in those cases, we set the contents
|
||||
of variables in a Go source file that will be used when no overrides are
|
||||
present.
|
||||
|
||||
We are using `pkg/version/base.go` as the source of versioning in absence of
|
||||
information from git. Here is a sample of that file's contents:
|
||||
|
||||
```go
|
||||
var (
|
||||
gitVersion string = "v0.4-dev" // version from git, output of $(git describe)
|
||||
gitCommit string = "" // sha1 from git, output of $(git rev-parse HEAD)
|
||||
)
|
||||
```
|
||||
|
||||
This means a build with `go install` or `go get` or a build from a tarball will
|
||||
yield binaries that will identify themselves as `v0.4-dev` and will not be able
|
||||
to provide you with a SHA1.
|
||||
|
||||
To add the extra versioning information when building from git, the
|
||||
`make` build will gather that information (using `git describe` and
|
||||
`git rev-parse`) and then create a `-ldflags` string to pass to `go install` and
|
||||
tell the Go linker to override the contents of those variables at build time. It
|
||||
can, for instance, tell it to override `gitVersion` and set it to
|
||||
`v0.4-13-g4567bcdef6789-dirty` and set `gitCommit` to `4567bcdef6789...` which
|
||||
is the complete SHA1 of the (dirty) tree used at build time.
|
||||
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
[]()
|
||||
<!-- END MUNGE: GENERATED_ANALYTICS -->
|
@ -1,2 +0,0 @@
|
||||
assignees:
|
||||
- ihmccreery
|
@ -1,143 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2015 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.
|
||||
|
||||
# Builds an official release based on a git tag, with instructions for
|
||||
# how to proceed after the bits are built.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
# Get the md5 (duplicated from common.sh, but don't want to pull in
|
||||
# all of common.sh here)
|
||||
function md5() {
|
||||
if which md5 >/dev/null 2>&1; then
|
||||
md5 -q "$1"
|
||||
else
|
||||
md5sum "$1" | awk '{ print $1 }'
|
||||
fi
|
||||
}
|
||||
|
||||
# Get the sha1 (duplicated from common.sh, but don't want to pull in
|
||||
# all of common.sh here)
|
||||
function sha1() {
|
||||
if which shasum >/dev/null 2>&1; then
|
||||
shasum -a1 "$1" | awk '{ print $1 }'
|
||||
else
|
||||
sha1sum "$1" | awk '{ print $1 }'
|
||||
fi
|
||||
}
|
||||
|
||||
declare -r KUBE_GITHUB="https://github.com/kubernetes/kubernetes.git"
|
||||
declare -r KUBE_RELEASE_VERSION=${1-}
|
||||
declare -r TMPDIR=${TMPDIR:-"/tmp"}
|
||||
declare -r KUBE_RELEASE_UMASK=${KUBE_RELEASE_UMASK:-022}
|
||||
|
||||
VERSION_REGEX="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-(beta|alpha)\\.(0|[1-9][0-9]*))?$"
|
||||
[[ ${KUBE_RELEASE_VERSION} =~ ${VERSION_REGEX} ]] || {
|
||||
echo "!!! You must specify the version you are releasing in the form of '${VERSION_REGEX}'" >&2
|
||||
exit 1
|
||||
}
|
||||
VERSION_MAJOR="${BASH_REMATCH[1]}"
|
||||
VERSION_MINOR="${BASH_REMATCH[2]}"
|
||||
if [[ "$KUBE_RELEASE_VERSION" =~ "alpha" ]]; then
|
||||
# We don't want to version docs for alpha releases, so we are just pointing to head.
|
||||
RELEASE_BRANCH="master"
|
||||
else
|
||||
RELEASE_BRANCH="release-${VERSION_MAJOR}.${VERSION_MINOR}"
|
||||
fi
|
||||
|
||||
if [[ "$KUBE_RELEASE_VERSION" =~ alpha|beta ]]; then
|
||||
KUBE_RELEASE_TYPE="latest"
|
||||
else
|
||||
KUBE_RELEASE_TYPE="stable"
|
||||
fi
|
||||
|
||||
declare -r KUBE_BUILD_DIR=$(mktemp -d "${TMPDIR}/kubernetes-build-release-${KUBE_RELEASE_VERSION}-XXXXXXX")
|
||||
|
||||
# Set the default umask for the release. This ensures consistency
|
||||
# across our release builds.
|
||||
umask "${KUBE_RELEASE_UMASK}"
|
||||
|
||||
echo "Cloning ${KUBE_GITHUB} at ${KUBE_RELEASE_VERSION}."
|
||||
echo
|
||||
echo "NOTE: Ignore the deatched HEAD warning you're about to get. We want that."
|
||||
echo
|
||||
git clone ${KUBE_GITHUB} -b "${KUBE_RELEASE_VERSION}" "${KUBE_BUILD_DIR}"
|
||||
|
||||
# !!! REMINDER !!!
|
||||
#
|
||||
# Past this point, you are dealing with a different release. Don't
|
||||
# assume you're executing code from the same repo as this script is
|
||||
# running in. This needs to be a version agnostic build.
|
||||
|
||||
echo
|
||||
echo "Cloned, building release."
|
||||
echo
|
||||
|
||||
cd "${KUBE_BUILD_DIR}"
|
||||
|
||||
export KUBE_RELEASE_RUN_TESTS=n
|
||||
export KUBE_SKIP_CONFIRMATIONS=y
|
||||
# In order to build docker images for a release and tag them appropriately we need
|
||||
# to set these two variables.
|
||||
export KUBE_DOCKER_REGISTRY="gcr.io/google_containers"
|
||||
export KUBE_DOCKER_IMAGE_TAG="${KUBE_RELEASE_VERSION}"
|
||||
|
||||
make release
|
||||
|
||||
if ${KUBE_BUILD_DIR}/cluster/kubectl.sh version | grep Client | grep dirty; then
|
||||
echo "!!! Tag at invalid point, or something else is bad. Build is dirty. Don't push this build." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ln -s ${KUBE_BUILD_DIR}/_output/release-tars/kubernetes.tar.gz ${KUBE_BUILD_DIR}
|
||||
|
||||
MD5=$(md5 "${KUBE_BUILD_DIR}/kubernetes.tar.gz")
|
||||
SHA1=$(sha1 "${KUBE_BUILD_DIR}/kubernetes.tar.gz")
|
||||
|
||||
cat <<- EOM
|
||||
|
||||
Success! You must now do the following (you may want to cut and paste these
|
||||
instructions elsewhere):
|
||||
|
||||
1) pushd ${KUBE_BUILD_DIR}; build/push-official-release.sh ${KUBE_RELEASE_VERSION} ${KUBE_RELEASE_TYPE}
|
||||
|
||||
2) Release notes draft, to be published when the release is announced:
|
||||
|
||||
a) Title:
|
||||
|
||||
Release ${KUBE_RELEASE_VERSION}
|
||||
|
||||
b) Template for the description:
|
||||
|
||||
## [Documentation](http://releases.k8s.io/${RELEASE_BRANCH}/docs/README.md)
|
||||
## [Examples](http://releases.k8s.io/${RELEASE_BRANCH}/examples)
|
||||
## Changes since <last release> (last PR <last PR>)
|
||||
|
||||
<release notes>
|
||||
|
||||
binary | hash alg | hash
|
||||
------ | -------- | ----
|
||||
\`kubernetes.tar.gz\` | md5 | \`${MD5}\`
|
||||
\`kubernetes.tar.gz\` | sha1 | \`${SHA1}\`
|
||||
|
||||
3) Ensure all the binaries are in place on GCS before cleaning, (you might
|
||||
want to wait until the release is announced and published on GitHub, too).
|
||||
|
||||
4) make clean; popd; rm -rf ${KUBE_BUILD_DIR}
|
||||
|
||||
EOM
|
@ -1,335 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2015 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.
|
||||
|
||||
# This script automates the release processes for all pre-releases and official
|
||||
# releases for Kubernetes. See docs/devel/releasing.md for more info.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
# Sets DIR, INSTRUCTIONS
|
||||
function main() {
|
||||
# Parse arguments
|
||||
if [[ "$#" -ne 2 && "$#" -ne 3 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
local -r new_version=${1-}
|
||||
local -r build_version=${2-}
|
||||
DRY_RUN=true
|
||||
if [[ "${3-}" == "--no-dry-run" ]]; then
|
||||
echo "!!! This NOT is a dry run."
|
||||
DRY_RUN=false
|
||||
else
|
||||
echo "This is a dry run."
|
||||
fi
|
||||
|
||||
check-prereqs
|
||||
|
||||
# Get and verify version info
|
||||
local -r alpha_version_regex="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.0-alpha\\.([1-9][0-9]*)$"
|
||||
local -r beta_version_regex="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)-beta\\.([1-9][0-9]*)$"
|
||||
local -r official_version_regex="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
|
||||
local -r series_version_regex="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
|
||||
if [[ "${new_version}" =~ $alpha_version_regex ]]; then
|
||||
local -r release_type='alpha'
|
||||
local -r version_major="${BASH_REMATCH[1]}"
|
||||
local -r version_minor="${BASH_REMATCH[2]}"
|
||||
local -r version_alpha_rev="${BASH_REMATCH[3]}"
|
||||
elif [[ "${new_version}" =~ $beta_version_regex ]]; then
|
||||
local -r release_type='beta'
|
||||
local -r version_major="${BASH_REMATCH[1]}"
|
||||
local -r version_minor="${BASH_REMATCH[2]}"
|
||||
local -r version_patch="${BASH_REMATCH[3]}"
|
||||
local -r version_beta_rev="${BASH_REMATCH[4]}"
|
||||
elif [[ "${new_version}" =~ $official_version_regex ]]; then
|
||||
local -r release_type='official'
|
||||
local -r version_major="${BASH_REMATCH[1]}"
|
||||
local -r version_minor="${BASH_REMATCH[2]}"
|
||||
local -r version_patch="${BASH_REMATCH[3]}"
|
||||
elif [[ "${new_version}" =~ $series_version_regex ]]; then
|
||||
local -r release_type='series'
|
||||
local -r version_major="${BASH_REMATCH[1]}"
|
||||
local -r version_minor="${BASH_REMATCH[2]}"
|
||||
else
|
||||
usage
|
||||
echo
|
||||
echo "!!! You specified an invalid version '${new_version}'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the git commit from the build_version and verify it
|
||||
local -r git_commit_regex="^[0-9a-f]{7}$"
|
||||
local -r git_commit=$(echo "${build_version}" | awk -F'+' '{print $2}' | head -c7)
|
||||
if ! [[ "${git_commit}" =~ $git_commit_regex ]]; then
|
||||
usage
|
||||
echo
|
||||
echo "!!! You specified an invalid build_version '${build_version}'."
|
||||
echo "!!! Tried to extract commit, got ${git_commit}."
|
||||
exit 1
|
||||
fi
|
||||
echo "Doing ${release_type} release '${new_version}'."
|
||||
|
||||
# Set the default umask for the release. This ensures consistency
|
||||
# across our release builds.
|
||||
#
|
||||
# TODO(ihmccreery): This should be in our build process, not our release
|
||||
# process.
|
||||
local -r release_umask=${release_umask:-022}
|
||||
umask "${release_umask}"
|
||||
|
||||
declare -r TMPDIR=${TMPDIR:-"/tmp"}
|
||||
local -r github="https://github.com/kubernetes/kubernetes.git"
|
||||
declare -r DIR=$(mktemp -d "${TMPDIR}/kubernetes-${release_type}-release-${new_version}-XXXXXXX")
|
||||
|
||||
# Start a tmp file that will hold instructions for the user.
|
||||
declare -r INSTRUCTIONS=$(mktemp "${TMPDIR}/kubernetes-${release_type}-release-${new_version}-instructions-XXXXXXX")
|
||||
if $DRY_RUN; then
|
||||
cat > "${INSTRUCTIONS}" <<- EOM
|
||||
Success on dry run! Do
|
||||
|
||||
pushd ${DIR}
|
||||
|
||||
to see what happened.
|
||||
|
||||
You would now do the following, if not a dry run:
|
||||
|
||||
EOM
|
||||
else
|
||||
cat > "${INSTRUCTIONS}" <<- EOM
|
||||
Success! You must now do the following (you may want to cut and paste these
|
||||
instructions elsewhere):
|
||||
|
||||
EOM
|
||||
fi
|
||||
|
||||
echo "Cloning from '${github}'..."
|
||||
git clone "${github}" "${DIR}"
|
||||
|
||||
# !!! REMINDER !!!
|
||||
#
|
||||
# Past this point, you are dealing with a different clone of the repo at some
|
||||
# version. Don't assume you're executing code from the same repo as this script
|
||||
# is running in. This is a version agnostic process.
|
||||
pushd "${DIR}"
|
||||
|
||||
if [[ "${release_type}" == 'alpha' ]]; then
|
||||
local -r ancestor="v${version_major}.${version_minor}.0-alpha.$((${version_alpha_rev}-1))"
|
||||
|
||||
git checkout "${git_commit}"
|
||||
verify-at-git-commit "${git_commit}"
|
||||
verify-ancestor "${ancestor}"
|
||||
|
||||
alpha-release "${new_version}"
|
||||
elif [[ "${release_type}" == 'beta' ]]; then
|
||||
local -r release_branch="release-${version_major}.${version_minor}"
|
||||
local -r ancestor="v${version_major}.${version_minor}.${version_patch}-beta.$((${version_beta_rev}-1))"
|
||||
|
||||
git checkout "${release_branch}"
|
||||
verify-at-git-commit "${git_commit}"
|
||||
verify-ancestor "${ancestor}"
|
||||
|
||||
beta-release "${new_version}"
|
||||
|
||||
git-push ${release_branch}
|
||||
elif [[ "${release_type}" == 'official' ]]; then
|
||||
local -r release_branch="release-${version_major}.${version_minor}"
|
||||
local -r beta_version="v${version_major}.${version_minor}.$((${version_patch}+1))-beta.0"
|
||||
local -r ancestor="${new_version}-beta.0"
|
||||
|
||||
git checkout "${release_branch}"
|
||||
verify-at-git-commit "${git_commit}"
|
||||
verify-ancestor "${ancestor}"
|
||||
|
||||
official-release "${new_version}"
|
||||
beta-release "${beta_version}"
|
||||
|
||||
git-push ${release_branch}
|
||||
else # [[ "${release_type}" == 'series' ]]
|
||||
local -r release_branch="release-${version_major}.${version_minor}"
|
||||
local -r alpha_version="v${version_major}.$((${version_minor}+1)).0-alpha.0"
|
||||
local -r beta_version="v${version_major}.${version_minor}.0-beta.0"
|
||||
# NOTE: We check the second alpha version, ...-alpha.1, because ...-alpha.0
|
||||
# is the branch point for the previous release cycle, so could provide a
|
||||
# false positive if we accidentally try to release off of the old release
|
||||
# branch.
|
||||
local -r ancestor="v${version_major}.${version_minor}.0-alpha.1"
|
||||
|
||||
git checkout "${git_commit}"
|
||||
verify-at-git-commit "${git_commit}"
|
||||
verify-ancestor "${ancestor}"
|
||||
|
||||
alpha-release "${alpha_version}"
|
||||
|
||||
echo "Branching ${release_branch}."
|
||||
git checkout -b "${release_branch}"
|
||||
versionize-docs-and-commit "${release_branch}"
|
||||
|
||||
beta-release "${beta_version}"
|
||||
|
||||
git-push ${release_branch}
|
||||
fi
|
||||
|
||||
echo
|
||||
cat "${INSTRUCTIONS}"
|
||||
}
|
||||
|
||||
function usage() {
|
||||
echo "Usage: ${0} <release_version> <build_version> [--no-dry-run]"
|
||||
echo
|
||||
echo "<release_version> is the version you want to release,"
|
||||
echo "<build_version> is the version of the build you want to mark as <release-version>."
|
||||
echo "Please see docs/devel/releasing.md for more info."
|
||||
}
|
||||
|
||||
function check-prereqs() {
|
||||
SED=sed
|
||||
if which gsed &>/dev/null; then
|
||||
SED=gsed
|
||||
fi
|
||||
if ! ($SED --version 2>&1 | grep -q GNU); then
|
||||
echo "!!! GNU sed is required. If on OS X, use 'brew install gnu-sed'."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function alpha-release() {
|
||||
local -r alpha_version="${1}"
|
||||
|
||||
echo "Doing an alpha release of ${alpha_version}."
|
||||
|
||||
echo "Tagging ${alpha_version} at $(current-git-commit)."
|
||||
git tag -a -m "Kubernetes pre-release ${alpha_version}" "${alpha_version}"
|
||||
git-push "${alpha_version}"
|
||||
|
||||
cat >> "${INSTRUCTIONS}" <<- EOM
|
||||
- Finish the ${alpha_version} release build: from this directory (clone of
|
||||
upstream/master),
|
||||
./release/build-official-release.sh ${alpha_version}
|
||||
EOM
|
||||
}
|
||||
|
||||
function beta-release() {
|
||||
local -r beta_version="${1}"
|
||||
|
||||
echo "Doing a beta release of ${beta_version}."
|
||||
|
||||
rev-version-and-commit "${beta_version}"
|
||||
|
||||
echo "Tagging ${beta_version} at $(current-git-commit)."
|
||||
git tag -a -m "Kubernetes pre-release ${beta_version}" "${beta_version}"
|
||||
git-push "${beta_version}"
|
||||
|
||||
cat >> "${INSTRUCTIONS}" <<- EOM
|
||||
- Finish the ${beta_version} release build: from this directory (clone of
|
||||
upstream/master),
|
||||
./release/build-official-release.sh ${beta_version}
|
||||
EOM
|
||||
}
|
||||
|
||||
function official-release() {
|
||||
local -r official_version="${1}"
|
||||
|
||||
echo "Doing an official release of ${official_version}."
|
||||
|
||||
rev-version-and-commit "${official_version}"
|
||||
|
||||
echo "Tagging ${official_version} at $(current-git-commit)."
|
||||
git tag -a -m "Kubernetes release ${official_version}" "${official_version}"
|
||||
git-push "${official_version}"
|
||||
|
||||
cat >> "${INSTRUCTIONS}" <<- EOM
|
||||
- Finish the ${official_version} release build: from this directory (clone of
|
||||
upstream/master),
|
||||
./release/build-official-release.sh ${official_version}
|
||||
EOM
|
||||
}
|
||||
|
||||
function verify-at-git-commit() {
|
||||
local -r git_commit="${1}"
|
||||
echo "Verifying we are at ${git_commit}."
|
||||
if [[ $(current-git-commit) != ${git_commit} ]]; then
|
||||
cat <<- EOM
|
||||
!!! We are not at commit ${git_commit}! (If you're cutting a beta or official
|
||||
release, that probably means your release branch isn't frozen, so the commit
|
||||
you want to release isn't at HEAD of the release branch.)"
|
||||
EOM
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function current-git-commit() {
|
||||
git rev-parse --short HEAD
|
||||
}
|
||||
|
||||
function verify-ancestor() {
|
||||
local -r ancestor="${1}"
|
||||
# Check to make sure the previous version is an ancestor.
|
||||
echo "Checking that previous version '${ancestor}' is an ancestor."
|
||||
if ! git merge-base --is-ancestor "${ancestor}" HEAD; then
|
||||
echo "!!! Previous version '${ancestor}' is not an ancestor!"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function versionize-docs-and-commit() {
|
||||
local -r release_branch="${1}"
|
||||
echo "Versionizing docs for ${release_branch} and committing."
|
||||
# NOTE: This is using versionize-docs.sh at the release point.
|
||||
./build/versionize-docs.sh ${release_branch}
|
||||
git commit -am "Versioning docs and examples for ${release_branch}."
|
||||
}
|
||||
|
||||
function rev-version-and-commit() {
|
||||
local -r version="${1}"
|
||||
local -r version_file="pkg/version/base.go"
|
||||
|
||||
local -r version_regex="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-beta\\.(0|[1-9][0-9]*))?$"
|
||||
if [[ "${version}" =~ $version_regex ]]; then
|
||||
local -r version_major="${BASH_REMATCH[1]}"
|
||||
# We append a '+' to the minor version on a beta build per hack/lib/version.sh's logic.
|
||||
if [[ -z "${BASH_REMATCH[4]}" ]]; then
|
||||
local -r version_minor="${BASH_REMATCH[2]}"
|
||||
else
|
||||
local -r version_minor="${BASH_REMATCH[2]}+"
|
||||
fi
|
||||
else
|
||||
echo "!!! Something went wrong. Tried to rev version to invalid version; should not have gotten to this point."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating ${version_file} to ${version}"
|
||||
$SED -ri -e "s/gitMajor\s+string = \"[^\"]*\"/gitMajor string = \"${version_major}\"/" "${version_file}"
|
||||
$SED -ri -e "s/gitMinor\s+string = \"[^\"]*\"/gitMinor string = \"${version_minor}\"/" "${version_file}"
|
||||
$SED -ri -e "s/gitVersion\s+string = \"[^\"]*\"/gitVersion string = \"${version}+\$Format:%h\$\"/" "${version_file}"
|
||||
gofmt -s -w "${version_file}"
|
||||
|
||||
echo "Committing version change ${version}"
|
||||
git add "${version_file}"
|
||||
git commit -m "Kubernetes version ${version}"
|
||||
}
|
||||
|
||||
function git-push() {
|
||||
local -r object="${1}"
|
||||
if $DRY_RUN; then
|
||||
echo "Dry run: would have done git push origin ${object}"
|
||||
else
|
||||
git push origin "${object}"
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
Loading…
Reference in New Issue
Block a user