Deprecate kubernetes/kubenetes release infrastructure and doc.

This commit is contained in:
David McMahon 2016-04-14 18:30:16 -07:00
parent fc3ef9320e
commit 4e07b43d70
10 changed files with 6 additions and 1580 deletions

View File

@ -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.
###############################################################################

View File

@ -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} ${@}

View File

@ -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

View File

@ -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

View File

@ -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 -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/devel/README.md?pixel)]()

View File

@ -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 -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/devel/making-release-notes.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -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 -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/devel/releasing.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -1,2 +0,0 @@
assignees:
- ihmccreery

View File

@ -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

View File

@ -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 "$@"