From d63860411af861d1d7ab07ee4bfd36c67cfde272 Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Thu, 2 Jul 2015 12:44:11 -0700 Subject: [PATCH] Add `build-official-release.sh` This commit does 4 things: * Adds a script which will: (a) clone from a git tag, make release, and give you very detailed instructions as to what to do from that point. * Changes `push-official-release.sh` so we can't push "dirty" releases anymore (which `build-official-release.sh` also double checks at the end.) * Fixes #9576 by ensuring a correct umask. * Changes common.sh to gtar all the way through, to ensure that bloody OS X tar never touches the release process, because I don't want to have to understand two tar programs and how release artifacts are created from both (c.f. #10615.) --- build/build-official-release.sh | 116 ++++++++++++++++++++++++++++++++ build/common.sh | 53 +++++++++------ build/push-official-release.sh | 5 ++ 3 files changed, 152 insertions(+), 22 deletions(-) create mode 100755 build/build-official-release.sh diff --git a/build/build-official-release.sh b/build/build-official-release.sh new file mode 100755 index 00000000000..2519611ea96 --- /dev/null +++ b/build/build-official-release.sh @@ -0,0 +1,116 @@ +#!/bin/bash + +# Copyright 2015 The Kubernetes Authors All rights reserved. +# +# 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/GoogleCloudPlatform/kubernetes.git" +declare -r KUBE_RELEASE_VERSION=${1-} +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]*)$" +[[ ${KUBE_RELEASE_VERSION} =~ ${VERSION_REGEX} ]] || { + echo "!!! You must specify the version you are releasing in the form of '${VERSION_REGEX}'" >&2 + exit 1 +} + +declare -r KUBE_BUILD_DIR="/tmp/kubernetes-release-${KUBE_RELEASE_VERSION}-$(date +%s)" + +# 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 +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") + +echo "" +echo "Success! You must now do the following: (you may want to cut" +echo " and paste these instructions elsewhere, step 1 can be spammy)" +echo "" +echo " 1) (cd ${KUBE_BUILD_DIR}; build/push-official-release.sh ${KUBE_RELEASE_VERSION})" +echo " 2) Go to https://github.com/GoogleCloudPlatform/kubernetes/releases" +echo " and create a new 'Release ${KUBE_RELEASE_VERSION} Candidate' release" +echo " with the ${KUBE_RELEASE_VERSION} tag. Mark it as a pre-release." +echo " 3) Upload the ${KUBE_BUILD_DIR}/kubernetes.tar.gz to GitHub" +echo " 4) Use this template for the release:" +echo "" +echo "## [Documentation](http://releases.k8s.io/${KUBE_RELEASE_VERSION}/docs)" +echo "## [Examples](http://releases.k8s.io/${KUBE_RELEASE_VERSION}/examples)" +echo "## Changes since (last PR )" +echo "" +echo "" +echo "" +echo "binary | hash alg | hash" +echo "------ | -------- | ----" +echo "\`kubernetes.tar.gz\` | md5 | \`${MD5}\`" +echo "\`kubernetes.tar.gz\` | sha1 | \`${SHA1}\`" +echo "" +echo " We'll fill in the release notes in the next stage." +echo " 5) Ensure all the binaries are in place on GitHub and GCS before cleaning." +echo " 6) (cd ${KUBE_BUILD_DIR}; make clean; cd -; rm -rf ${KUBE_BUILD_DIR})" +echo "" diff --git a/build/common.sh b/build/common.sh index 764006c0bec..3cb907817d4 100644 --- a/build/common.sh +++ b/build/common.sh @@ -118,6 +118,7 @@ readonly KUBE_DOCKER_WRAPPED_BINARIES=( # DOCKER_MOUNT_ARGS function kube::build::verify_prereqs() { kube::log::status "Verifying Prerequisites...." + kube::build::ensure_tar if [[ "${1-}" != "clean" ]]; then if [[ -z "$(which docker)" ]]; then @@ -194,6 +195,27 @@ function kube::build::is_osx() { [[ "$(uname)" == "Darwin" ]] } +function kube::build::ensure_tar() { + if [[ -n "${TAR:-}" ]]; then + return + fi + + # Find gnu tar if it is available, bomb out if not. + TAR=tar + if which gtar &>/dev/null; then + TAR=gtar + else + if which gnutar &>/dev/null; then + TAR=gnutar + fi + fi + if ! "${TAR}" --version | grep -q GNU; then + echo " !!! Cannot find GNU tar. Build on Linux or install GNU tar" + echo " on Mac OS X (brew install gnu-tar)." + return 1 + fi +} + function kube::build::clean_output() { # Clean out the output directory if it exists. if kube::build::has_docker ; then @@ -332,12 +354,14 @@ function kube::build::source_targets() { # Set up the context directory for the kube-build image and build it. function kube::build::build_image() { + kube::build::ensure_tar + local -r build_context_dir="${LOCAL_OUTPUT_IMAGE_STAGING}/${KUBE_BUILD_IMAGE}" kube::build::build_image_cross mkdir -p "${build_context_dir}" - tar czf "${build_context_dir}/kube-source.tar.gz" $(kube::build::source_targets) + "${TAR}" czf "${build_context_dir}/kube-source.tar.gz" $(kube::build::source_targets) kube::version::get_version_vars kube::version::save_version_vars "${build_context_dir}/kube-version-defs" @@ -760,29 +784,12 @@ function kube::release::package_full_tarball() { # of the files to be packaged. This assumes that ${2}/kubernetes is what is # being packaged. function kube::release::create_tarball() { + kube::build::ensure_tar + local tarfile=$1 local stagingdir=$2 - # Find gnu tar if it is available - local tar=tar - if which gtar &>/dev/null; then - tar=gtar - else - if which gnutar &>/dev/null; then - tar=gnutar - fi - fi - - local tar_cmd=("$tar" "czf" "${tarfile}" "-C" "${stagingdir}" "kubernetes") - if "$tar" --version | grep -q GNU; then - tar_cmd=("${tar_cmd[@]}" "--owner=0" "--group=0") - else - echo " !!! GNU tar not available. User names will be embedded in output and" - echo " release tars are not official. Build on Linux or install GNU tar" - echo " on Mac OS X (brew install gnu-tar)" - fi - - "${tar_cmd[@]}" + "${TAR}" czf "${tarfile}" -C "${stagingdir}" kubernetes --owner=0 --group=0 } # --------------------------------------------------------------------------- @@ -840,6 +847,8 @@ function kube::release::gcs::ensure_release_bucket() { } function kube::release::gcs::stage_and_hash() { + kube::build::ensure_tar + # Split the args into srcs... and dst local -r args=( "$@" ) local -r split=$((${#args[@]}-1)) # Split point for src/dst args @@ -850,7 +859,7 @@ function kube::release::gcs::stage_and_hash() { srcdir=$(dirname ${src}) srcthing=$(basename ${src}) mkdir -p ${GCS_STAGE}/${dst} - tar c -C ${srcdir} ${srcthing} | tar x -C ${GCS_STAGE}/${dst} + "${TAR}" c -C ${srcdir} ${srcthing} | "${TAR}" x -C ${GCS_STAGE}/${dst} done } diff --git a/build/push-official-release.sh b/build/push-official-release.sh index 03617d30e05..0aefbd33be0 100755 --- a/build/push-official-release.sh +++ b/build/push-official-release.sh @@ -39,5 +39,10 @@ KUBE_GCS_LATEST_CONTENTS=${KUBE_RELEASE_VERSION} 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 + kube::release::gcs::release kube::release::gcs::publish_latest_official