diff --git a/README-gcb.md b/README-gcb.md
new file mode 100644
index 00000000000..3b3aaea59ac
--- /dev/null
+++ b/README-gcb.md
@@ -0,0 +1,53 @@
+Table of Contents
+=================
+* [Intro](#intro)
+* [Typical Workflows](#typical-workflows)
+
+# Container Builder Staging and Release
+
+## Intro
+
+The Kubernetes release process can now be staged and released on both the GCP
+Container Builder (GCB) or on the desktop with the necessary permissions.
+
+## Typical Workflows
+
+The typical workflow is very simple and works similar to `anago` in both mock
+and `--nomock` variants with a clear division between the two. Stage and
+release using either `--nomock` or in the default (mock) mode.
+
+The hybrid model is also supported
+* Stage on GCB
+* Release on desktop
+
+```
+# On GCB, stage a (mock) master branch build from head
+$ gcbmgr stage master --build-at-head
+
+# On GCB, stage a (mock) release-1.9 branch build using test signal
+$ gcbmgr stage release-1.9
+
+# On GCB, view last 5 jobs
+$ gcbmgr
+-OR-
+$ gcbmgr list
+
+# View completed staged builds
+$ gcbmgr staged
+
+# Release (from GCB)
+$ gcbmgr release master --buildversion=
+
+# Release (from GCB)
+$ gcbmgr release release-1.9 --buildversion=
+
+# And of course the man page has all the most detailed and up to date info:
+$ gcbmgr -man
+```
+
+Guidance from `gcbmgr staged` instructs you how to release a staged build on
+GCB or the desktop.
+
+NOTE: Releases from GCB are currently unable to send email, so the update
+ occurs in the form of a new release tracking issue on the
+ kubernetes/sig-release repo (k8s-release-robot/sig-release for mock runs).
diff --git a/README.md b/README.md
index 1d908dbf65a..3329f53af62 100644
--- a/README.md
+++ b/README.md
@@ -70,9 +70,17 @@ on a branch. Without the [--official] flag, a beta would be created.
There are two workflows you can choose from:
1. Run through a complete release end to end
-2. Create any number of staged (--stage) releases and release from there
+2. Create staged (--stage) releases and release from there
-First try a staged alpha release:
+*NOTE:* Again, the tooling works by default in *mock mode* and runs in *"full
+production"* mode using `--nomock`.
+
+*IMPORTANT:* Staging and release workflows operate exclusively in either mock
+or `--nomock` modes. If you stage something in mock mode, it is not available
+in `--nomock` mode. Be sure to both stage and release with or without
+`--nomock`.
+
+First try a (mock) staged alpha release:
```
$ anago master --stage
```
@@ -111,14 +119,14 @@ $ anago release-9.9.9
## Typical Workflows
-Stage an official (patch) release on your local disk:
+Stage a (mock) official patch release on your local disk:
```
# add --build-at-head to force a build, otherwise rely on find_green_build
# in-line to find a build candidate
$ anago release-1.8 --stage
```
-Release previously staged official (patch) release from your local disk:
+Release previously (mock) staged official patch release from your local disk:
```
# $buildversion will come from the output at the end of the above --stage run
# as will this command-line in its entirety
diff --git a/anago b/anago
index 8af231d1159..7421fc60263 100755
--- a/anago
+++ b/anago
@@ -30,7 +30,6 @@ PROG=${0##*/}
#+ [--security_layer=/path/to/pointer/to/script]
#+ [--exclude-suites=" ..."]
#+ [--build-at-head]
-#+ [--user-at-domain=]
#+ [--prebuild] [--buildonly]
#+ [--mailto=,] [--gcb]
#+ [--tmpdir=]
@@ -102,10 +101,6 @@ PROG=${0##*/}
#+ A simple $USER check controls who can run in --nomock mode as ACLs
#+ restrict who can actually push bits anyway.
#+
-#+ --user-at-domain will let you specify an alternate full user@domain.tld.
-#+ This should be the address associated with the release GCP project and
-#+ the account from which you will be sending mail.
-#+
#+ OPTIONS
#+ [--stage] - Write all artifacts to
#+ gs://$RELEASE_BUCKET/stage for later use
@@ -137,9 +132,6 @@ PROG=${0##*/}
#+ Users are prompted to remove draft releases,
#+ but the action to create them in the first
#+ place should be explicit.
-#+ [--user-at-domain=] - Specify an (alternate) user@domain.tld
-#+ (registered at GCP project and for mailing
-#+ release announcements)
#+ [--gcb] - Running from GCB
#+ [--tmpdir=] - Set an alternate temp dir
#+ [--prebuild] - Used during GCB to halt before building
@@ -179,7 +171,10 @@ PROG=${0##*/}
# If NO ARGUMENTS should return usage, uncomment the following line:
usage=${1:-yes}
-source $(dirname $(readlink -ne $BASH_SOURCE))/lib/common.sh
+# Deal with OSX limitations out the gate for anyone that tries this there
+BASE_ROOT=$(dirname $(readlink -e "$BASH_SOURCE" 2>&1)) \
+ || BASE_ROOT="$BASH_SOURCE"
+source $BASE_ROOT/lib/common.sh
source $TOOL_LIB_PATH/gitlib.sh
source $TOOL_LIB_PATH/releaselib.sh
@@ -199,12 +194,6 @@ RELEASE_BRANCH=${POSITIONAL_ARGV[0]}
[[ $RELEASE_BRANCH =~ $BRANCH_REGEX ]] \
|| common::exit 1 "Invalid branch name!"
-# Backport https://github.com/kubernetes/kubernetes/pull/47939 and remove this
-if ((FLAGS_stage)) && \
- ([[ $RELEASE_BRANCH != "master" ]] && ((${BASH_REMATCH[2]}<8))); then
- common::exit 1 "--stage only works for 1.8+ releases."
-fi
-
# Check arg conflicts
if ((FLAGS_rc)) || ((FLAGS_official)); then
if [[ "$RELEASE_BRANCH" == "master" ]]; then
@@ -292,7 +281,7 @@ ensure_registry_acls () {
fi
# Always reset back to $USER
- ((FLAGS_gcb)) || logrun $GCLOUD config set account $USER_AT_DOMAIN
+ ((FLAGS_gcb)) || logrun $GCLOUD config set account $GCP_USER
done
logrun rm -f $emptyfile
@@ -304,16 +293,15 @@ ensure_registry_acls () {
# Checks GCP users to ensure they are logged in and accessible
# return 1 on failure
ensure_gcp_users () {
- local userat="$USER_AT_DOMAIN"
local user
local -a users_to_check
- users_to_check+=($G_AUTH_USER $userat)
+ users_to_check+=($G_AUTH_USER $GCP_USER)
for user in ${users_to_check[*]}; do
logecho -n "Checking cloud account/auth $user: "
- if (logrun gcloud config set account $user && \
- logrun gcloud docker -- version >/dev/null 2>&1); then
+ if (logrun $GCLOUD config set account $user && \
+ logrun $GCLOUD docker -- version >/dev/null 2>&1); then
logecho -r "$OK"
else
logecho -r "$FAILED"
@@ -321,22 +309,10 @@ ensure_gcp_users () {
logecho "$user is not in the credentialed accounts list!"
logecho "Sign in with:"
logecho
- logecho "$ gcloud auth login $user"
+ logecho "$ $GCLOUD auth login $user"
return 1
fi
done
-
- # Ensure $USER is active to start
- # The loop above finishes on $userat
- gcloud_auth_list=$($GCLOUD auth list --filter=status:ACTIVE \
- --format="value(account)" 2>/dev/null)
- if ! [[ "$gcloud_auth_list" =~ $userat ]]; then
- logecho "$userat is not the active gcloud user!"
- logecho "Set with:"
- logecho
- logecho "$ gcloud config set account $userat"
- return 1
- fi
}
###############################################################################
@@ -352,8 +328,9 @@ check_prerequisites () {
# We check for docker here as a word which passes for docker-ce and
# docker-engine as docker packages are in transiation of deprecating
# docker-engine
- common::check_packages jq pandoc docker ${PREREQUISITE_PACKAGES[*]}
- common::check_pip_packages yq || common::exit 1 "Exiting..."
+ common::check_packages jq pandoc docker ${PREREQUISITE_PACKAGES[*]} \
+ || return 1
+ common::check_pip_packages yq || return 1
security_layer::auth_check 2 || return 1
@@ -365,11 +342,6 @@ check_prerequisites () {
# to ensure both mock and --nomock runs will work.
ensure_registry_acls "${ALL_CONTAINER_REGISTRIES[*]}" || return 1
- # Verify write access to $WRITE_RELEASE_BUCKETS
- for rb in ${WRITE_RELEASE_BUCKETS[*]}; do
- release::gcs::ensure_release_bucket $rb || return 1
- done
-
logecho -n "Checking cloud project state: "
GCLOUD_PROJECT=$($GCLOUD config get-value project 2>/dev/null)
if [[ -z "$GCLOUD_PROJECT" ]]; then
@@ -380,6 +352,11 @@ check_prerequisites () {
return 1
fi
logecho -r "$OK"
+
+ # Verify write access to $WRITE_RELEASE_BUCKETS
+ for rb in ${WRITE_RELEASE_BUCKETS[*]}; do
+ release::gcs::ensure_release_bucket $rb || return 1
+ done
}
###############################################################################
@@ -573,6 +550,26 @@ git_tag () {
logrun -s git tag -a -m "$commit_string" "${RELEASE_VERSION[$label]}"
}
+##############################################################################
+# Tag/Build a local kube_cross image based on the version in scope
+PROGSTEP[local_kube_cross]="TAG/BUILD LOCAL KUBE CROSS"
+local_kube_cross () {
+ local docker_image="gcr.io/google_containers/kube-cross"
+ local version="$(cat $TREE_ROOT/build/build-image/cross/VERSION)"
+ local image="$docker_image:$version"
+ local local_image="$docker_image:local"
+
+ logecho -n "Checking if $image exists locally: "
+ if logrun -s docker pull $image; then
+ logecho -n "Tagging docker image $image as $local_image: "
+ logrun -s docker tag $image $local_image
+ else
+ logecho -n "Building docker image $image: "
+ logrun -s docker build --cache-from $docker_image -t $image \
+ -t $local_image $TREE_ROOT/build/build-image/cross/
+ fi
+}
+
##############################################################################
# Prepare sources for building for a given label
# @param label - The label to process
@@ -679,7 +676,10 @@ build_tree () {
if ((FLAGS_gcb)); then
# make_cross done separately
# OUT_DIR works in this context. Woohoo!
- logrun -s -v make package-tarballs OUT_DIR=$OUT_DIR-$version || return 1
+ # KUBE_DOCKER_IMAGE_TAG needed here due to references deep in
+ # build/lib/release.sh
+ logrun -s -v make package-tarballs KUBE_DOCKER_IMAGE_TAG="$version" \
+ OUT_DIR=$OUT_DIR-$version || return 1
else
# TODO: Ideally we update LOCAL_OUTPUT_ROOT in build/common.sh to be
# modifiable. In the meantime just mv the dir after it's done
@@ -922,7 +922,7 @@ announce () {
local subject
local announcement_text=$TMPDIR/$PROG-announce.$$
- ((FLAGS_nomock)) || mailto=$USER_AT_DOMAIN
+ ((FLAGS_nomock)) || mailto=$GCP_USER
mailto=${FLAGS_mailto:-$mailto}
if [[ "$arg" == "--branch" ]]; then
@@ -952,9 +952,9 @@ announce () {
# Due to announcements landing on public mailing lists requiring membership,
# post from the invoking user (for now until this is productionized further)
# and use reply-to to ensure replies go to the right place.
- common::sendmail -h "$mailto" "K8s-Anago<$USER_AT_DOMAIN>" \
+ common::sendmail -h "$mailto" "K8s-Anago<$GCP_USER>" \
"K8s-Anago" \
- "$subject" "$USER_AT_DOMAIN" \
+ "$subject" "$GCP_USER" \
"$announcement_text" || return 1
fi
@@ -1039,9 +1039,13 @@ update_github_release () {
# publish binary
logecho -n "Uploading binary to github: "
- logrun -s $GHCURL -H "Content-Type:application/x-compressed" \
+ if $GHCURL -H "Content-Type:application/x-compressed" \
--data-binary @$tarball \
- "${K8S_GITHUB_API/api\./uploads\.}/releases/$release_id/assets?name=${tarball##*/}"
+ "${K8S_GITHUB_API/api\./uploads\.}/releases/$release_id/assets?name=${tarball##*/}"; then
+ logecho $OK
+ else
+ logecho $FAILED
+ fi
if $draft; then
logecho
@@ -1053,7 +1057,7 @@ update_github_release () {
if ((FLAGS_yes)) || \
common::askyorn -y "Delete draft release (id #$release_id) now"; then
logecho -n "Deleting the draft release (id #$release_id): "
- logrun $GHCURL -X DELETE $K8S_GITHUB_API/releases/$release_id
+ $GHCURL -X DELETE $K8S_GITHUB_API/releases/$release_id
fi
# verify it was deleted
@@ -1156,8 +1160,9 @@ get_build_candidate () {
fi
if [[ -z $BRANCH_POINT ]]; then
- if [[ -n $JENKINS_BUILD_VERSION ]]; then
- logecho -r "$ATTENTION: Using --buildversion=$JENKINS_BUILD_VERSION"
+ if [[ -n "$FLAGS_buildversion" ]]; then
+ logecho -r "$ATTENTION: Using --buildversion=$FLAGS_buildversion"
+ JENKINS_BUILD_VERSION="$FLAGS_buildversion"
else
logecho "Asking Jenkins for a good build (this may take some time)..."
FLAGS_verbose=1 release::set_build_version \
@@ -1359,6 +1364,100 @@ push_all_artifacts () {
fi
}
+##############################################################################
+# Sets major global variables
+# RELEASE_GB - space requirements per build
+# GCP_USER - The user that drives the entire release
+# RELEASE_BUCKET - mock or standard release bucket location
+# BUCKET_TYPE - stage or release
+# WRITE_RELEASE_BUCKETS - array of writable buckets
+# READ_RELEASE_BUCKETS - array of readable buckets for multiple sourcing of
+# mock staged builds
+# GCRIO_REPO - GCR repo based on mock or --nomock
+# ALL_CONTAINER_REGISTRIES - when running mock this array also contains
+# google_containers so we can check access in mock
+# mode before an actual release occurs
+set_globals () {
+ # Define the placeholder/"role" user for GCB
+ local gcb_user="gcb@google.com"
+
+ logecho -n "Setting global variables: "
+
+ # Default disk requirements per version - Modified in found_staged_location()
+ RELEASE_GB="75"
+
+ if ((FLAGS_gcb)); then
+ # a placeholder that satisfies @google.com conditional below
+ GCP_USER="$gcb_user"
+ else
+ # Nothing should work without this. The entire release workflow depends
+ # on it whether running from the desktop or GCB
+ GCP_USER=$($GCLOUD auth list --filter=status:ACTIVE \
+ --format="value(account)" 2>/dev/null)
+ if [[ -z "$GCP_USER" ]]; then
+ logecho $FAILED
+ logecho "Unable to set a valid GCP credential!"
+ return 1
+ fi
+ fi
+
+ RELEASE_BUCKET="kubernetes-release"
+ if [[ $GCP_USER =~ "@google.com" ]]; then
+ WRITE_RELEASE_BUCKETS=("$RELEASE_BUCKET")
+ READ_RELEASE_BUCKETS=("$RELEASE_BUCKET")
+ fi
+
+ if ((FLAGS_stage)); then
+ BUCKET_TYPE="stage"
+ else
+ BUCKET_TYPE="release"
+ fi
+
+ if ((FLAGS_nomock)); then
+ GCRIO_REPO="${FLAGS_gcrio_repo:-google_containers}"
+ ALL_CONTAINER_REGISTRIES=("$GCRIO_REPO")
+ else
+ # GCS buckets cannot contain @ or "google", so for those users, just use
+ # the "$USER" portion of $GCP_USER/$gcb_user
+ RELEASE_BUCKET_USER="$RELEASE_BUCKET-${GCP_USER%%@google.com}"
+ RELEASE_BUCKET_GCB="$RELEASE_BUCKET-${gcb_user%%@google.com}"
+ RELEASE_BUCKET_USER="${RELEASE_BUCKET_USER/@/-at-}"
+ RELEASE_BUCKET_GCB="${RELEASE_BUCKET_GCB/@/-at-}"
+ # GCP also doesn't like anything even remotely looking like a domain name
+ # in the bucket name so convert . to -
+ RELEASE_BUCKET_USER="${RELEASE_BUCKET_USER/\./-}"
+ RELEASE_BUCKET_GCB="${RELEASE_BUCKET_GCB/\./-}"
+ RELEASE_BUCKET="$RELEASE_BUCKET_USER"
+
+ # All the RELEASE_BUCKETS we could possibly write to
+ WRITE_RELEASE_BUCKETS+=("$RELEASE_BUCKET_USER")
+ # All the RELEASE_BUCKETS we could possibly read from (for staging)
+ READ_RELEASE_BUCKETS+=("$RELEASE_BUCKET_USER")
+ # If a regular user is running mocks, also look in the GCB mock bucket for
+ # releases
+ ((FLAGS_gcb)) || READ_RELEASE_BUCKETS+=("$RELEASE_BUCKET_GCB")
+
+ # Set GCR values
+ GCRIO_REPO="${FLAGS_gcrio_repo:-kubernetes-release-test}"
+ [[ $GCP_USER =~ "@google.com" ]] \
+ && ALL_CONTAINER_REGISTRIES=("$GCRIO_REPO" "google_containers")
+
+ # This is passed to logrun() where appropriate when we want to mock
+ # specific activities like pushes
+ LOGRUN_MOCK="-m"
+ fi
+
+ # TODO:
+ # These KUBE_ globals extend beyond the scope of the new release refactored
+ # tooling so to pass these through as flags will require fixes across
+ # kubernetes/kubernetes and kubernetes/release which we can do at a later time
+ export KUBE_DOCKER_REGISTRY="gcr.io/$GCRIO_REPO"
+ export KUBE_RELEASE_RUN_TESTS=n
+ export KUBE_SKIP_CONFIRMATIONS=y
+
+ logecho $OK
+}
+
###############################################################################
# MAIN
###############################################################################
@@ -1367,61 +1466,6 @@ push_all_artifacts () {
: ${FLAGS_rc:=0}
: ${FLAGS_official:=0}
-# Default disk requirements per version - Modified in found_staged_location()
-RELEASE_GB="75"
-
-# Domain check
-if [[ "$FLAGS_user_at_domain" ]]; then
- USER_AT_DOMAIN="$FLAGS_user_at_domain"
-elif [[ "$HOSTNAME" =~ \.([^\.]+\.[a-z]{2,})$ ]]; then
- USER_AT_DOMAIN="$USER@${BASH_REMATCH[1]}"
-elif ((FLAGS_gcb)); then
- # Just a placeholder that satisfies @google.com conditionals but isn't used
- USER_AT_DOMAIN="gcb@google.com"
-fi
-
-if [[ -z $USER_AT_DOMAIN ]]; then
- common::exit 1 "$FATAL: Unable to determine your domain." \
- "Use --user-at-domain=user@domain.tld"
-fi
-
-# Set with --buildversion or set it later in release::set_build_version()
-JENKINS_BUILD_VERSION=$FLAGS_buildversion
-
-RELEASE_BUCKET="kubernetes-release"
-if [[ $USER_AT_DOMAIN =~ "google.com" ]]; then
- WRITE_RELEASE_BUCKETS=("$RELEASE_BUCKET")
- READ_RELEASE_BUCKETS=("$RELEASE_BUCKET")
-fi
-
-if ((FLAGS_stage)); then
- BUCKET_TYPE="stage"
-else
- BUCKET_TYPE="release"
-fi
-if ((FLAGS_nomock)); then
- GCRIO_REPO="${FLAGS_gcrio_repo:-google_containers}"
- ALL_CONTAINER_REGISTRIES=("$GCRIO_REPO")
-else
- RELEASE_BUCKET_USER="$RELEASE_BUCKET-$USER"
- RELEASE_BUCKET_MOCK="$RELEASE_BUCKET-mock"
- # This is passed to logrun() where appropriate when we want to mock
- # specific activities like pushes
- LOGRUN_MOCK="-m"
- # Point to a mock-specific bucket. $USER for desktop runs
- if ((FLAGS_gcb)); then
- RELEASE_BUCKET=$RELEASE_BUCKET_MOCK
- else
- RELEASE_BUCKET=$RELEASE_BUCKET_USER
- fi
- # All the RELEASE_BUCKETS we could possibly write to
- WRITE_RELEASE_BUCKETS+=("$RELEASE_BUCKET")
- # All the RELEASE_BUCKETS we could possibly read from (for staging)
- READ_RELEASE_BUCKETS+=("$RELEASE_BUCKET_USER" "$RELEASE_BUCKET_MOCK")
- GCRIO_REPO="${FLAGS_gcrio_repo:-kubernetes-release-test}"
- [[ $USER_AT_DOMAIN =~ "google.com" ]] \
- && ALL_CONTAINER_REGISTRIES=("$GCRIO_REPO" "google_containers")
-fi
BASEDIR=${FLAGS_basedir}
if [[ -z "${BASEDIR}" ]]; then
# Goobuntu machines have a standard path for "local" disk as the home
@@ -1433,14 +1477,6 @@ if [[ -z "${BASEDIR}" ]]; then
fi
fi
-# TODO:
-# These KUBE_ globals extend beyond the scope of the new release refactored
-# tooling so to pass these through as flags will require fixes across
-# kubernetes/kubernetes and kubernetes/release which we can do at a later time
-export KUBE_DOCKER_REGISTRY="gcr.io/$GCRIO_REPO"
-export KUBE_RELEASE_RUN_TESTS=n
-export KUBE_SKIP_CONFIRMATIONS=y
-
##############################################################################
# Initialize logs
##############################################################################
@@ -1454,11 +1490,34 @@ common::logfileinit $LOGFILE 10
# BEGIN script
common::timestamp begin
+# Point release managers to GCB as the preferred method
+if ! ((FLAGS_gcb)); then
+ logecho $HR
+ logecho "${TPUT[BOLD]}**** Welcome to the Kubernetes Release Tool, Release" \
+ "Manager ****"
+ logecho
+ logecho "***************** $PROG has moved to the cloud! *******************${TPUT[OFF]}"
+ logecho
+ logecho "* Kubernetes releases have been moved off the desktop"
+ logecho
+ logecho "* Desktop $PROG has not been disabled, but running via GCB is the" \
+ "preferred method. Usage is similar to $PROG."
+ logecho
+ logecho "* https://github.com/kubernetes/release/blob/master/README-gcb.md" \
+ "for details on how to get started."
+ logecho $HR
+ logecho
+ logecho -n "Press any key to continue..."
+ logrun read -n1
+ logecho
+fi
+
# Order workflow based on conditions
((FLAGS_stage)) || common::stepindex "gitlib::github_acls"
common::stepindex "check_prerequisites" "get_build_candidate" \
"prepare_workspace" "common::disk_space_check"
common::stepindex "prepare_tree"
+((FLAGS_gcb)) && common::stepindex "local_kube_cross"
if ((FLAGS_buildonly)); then
((FLAGS_gcb)) && common::stepindex "make_cross"
((FLAGS_gcb)) || common::stepindex "build_tree"
@@ -1474,7 +1533,7 @@ elif ! ((FLAGS_prebuild)); then
if ! ((FLAGS_stage)); then
common::stepindex "announce"
if ((FLAGS_gcb)); then
- common::stepindex "gitlib::create_release_issue"
+ common::stepindex "gitlib::update_release_issue"
else
common::stepindex "update_github_release"
fi
@@ -1504,6 +1563,10 @@ if ! ((FLAGS_buildonly)) && ! common::set_cloud_binaries; then
common::exit 1 "Exiting..."
fi
+# Set the majorify of global values
+# Moved here b/c now depends on gcloud
+set_globals
+
((FLAGS_stage)) || common::run_stateful gitlib::github_acls
# Simple check to validate who can do actual releases
@@ -1635,6 +1698,11 @@ if [[ -z $STAGED_LOCATION ]]; then
# Iterate over session release versions for setup, tagging and building
for label in ${!RELEASE_VERSION[@]}; do
common::run_stateful "prepare_tree $label" RELEASE_VERSION[$label]
+ # This doesn't have to be done per label, but does need to be inserted
+ # after an initial prepare_tree(), so just let the statefulness of it
+ # ignore a second iteration/call.
+ ((FLAGS_gcb)) \
+ && common::run_stateful local_kube_cross
# --prebuild for GCB, skip actual builds. Do everything else
if ! ((FLAGS_prebuild)); then
if ((FLAGS_gcb)); then
@@ -1674,7 +1742,7 @@ else
# Force complete for these three stages
for label in ${!RELEASE_VERSION[@]}; do
SKIP_STEPS+=(prepare_tree+$label build_tree+$label)
- ((FLAGS_gcb)) && SKIP_STEPS+=(make_cross+$label)
+ ((FLAGS_gcb)) && SKIP_STEPS+=(local_kube_cross make_cross+$label)
done
SKIP_STEPS+=(generate_release_notes)
for entry in ${SKIP_STEPS[*]}; do
@@ -1721,28 +1789,28 @@ if ((FLAGS_stage)); then
# clean up here on success
# Debatable if this should only happen on GCB
if ((FLAGS_gcb)) && ((FLAGS_stage)); then
- # Get a list of things to delete
- # Everything but the one staged by this run
- logecho "Cleaning up old staged builds..."
+ # Delete everything that's not this build in the vX.Y. namespace
# || true to catch non-zero exit when list is empty
- $GSUTIL ls -d gs://$RELEASE_BUCKET/$BUCKET_TYPE/${JENKINS_BUILD_VERSION%%-*}* |grep -v $JENKINS_BUILD_VERSION |xargs $GSUTIL -mq rm -r || true
+ if [[ $JENKINS_BUILD_VERSION =~ (v[0-9]+\.[0-9]+\.) ]]; then
+ logecho "Cleaning up old staged builds from" \
+ "gs://$RELEASE_BUCKET/$BUCKET_TYPE/${BASH_REMATCH[1]}..."
+ $GSUTIL ls -d gs://$RELEASE_BUCKET/$BUCKET_TYPE/${BASH_REMATCH[1]}* |\
+ grep -v $JENKINS_BUILD_VERSION |xargs $GSUTIL -mq rm -r || true
+ fi
fi
common::exit 0
fi
if [[ -n "$PARENT_BRANCH" ]]; then
+ # TODO: This needs the gcb create/update release issue treatment
common::run_stateful "announce --branch"
else
common::run_stateful announce
# For GCB create/update a release tracking issue
if ((FLAGS_gcb)); then
- #if search_release_issue $RELEASE_VERSION_PRIME; then
- # comment_release_issue
- #else
- common::run_stateful "gitlib::create_release_issue $RELEASE_VERSION_PRIME"
- #fi
+ common::run_stateful "gitlib::update_release_issue $RELEASE_VERSION_PRIME"
else
common::run_stateful update_github_release
fi
diff --git a/build/Dockerfile.k8s-cloud-builder b/build/Dockerfile.k8s-cloud-builder
new file mode 100644
index 00000000000..cb674a10eb5
--- /dev/null
+++ b/build/Dockerfile.k8s-cloud-builder
@@ -0,0 +1,50 @@
+# To rebuild and publish this container run:
+# gcloud container builds submit --config update_build_container.yaml .
+
+FROM ubuntu
+
+# Install packages
+RUN apt-get -q update && apt-get install -qqy apt-transport-https \
+ ca-certificates curl git gnupg2 lsb-release python \
+ software-properties-common wget python-setuptools python-dev \
+ build-essential jq pandoc gettext-base
+
+# Install Pip packages
+RUN easy_install pip
+RUN pip install yq
+
+# Packages required by the make in k8s
+# localtime
+RUN apt-get -q update && apt-get install -qqy tzdata
+
+# install net tools
+# required by common.sh
+RUN apt-get -q update && apt-get install -qqy grep net-tools rsync
+
+# Install gcloud
+RUN echo "deb https://packages.cloud.google.com/apt cloud-sdk-$(lsb_release -cs) main" > /etc/apt/sources.list.d/google-cloud-sdk.list && \
+ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
+ apt-get -q update && \
+ apt-get install -qqy google-cloud-sdk
+
+# Install docker stuff
+#---------------------
+# Based on instructions from:
+# https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/#uninstall-old-versions
+RUN \
+ apt-get -y update && \
+ apt-get install -y \
+ linux-image-extra-virtual \
+ apt-transport-https \
+ ca-certificates \
+ curl \
+ software-properties-common && \
+ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
+ add-apt-repository \
+ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
+ $(lsb_release -cs) \
+ stable edge" && \
+ apt-get -y update
+
+ARG DOCKER_VERSION=17.09.0~ce-0~ubuntu
+RUN apt-get install -y docker-ce=${DOCKER_VERSION} unzip
diff --git a/build/build-k8s-cloud-builder-container b/build/build-k8s-cloud-builder-container
new file mode 100755
index 00000000000..e37ca0e948d
--- /dev/null
+++ b/build/build-k8s-cloud-builder-container
@@ -0,0 +1 @@
+gcloud container builds submit --config k8s-container.yaml .
diff --git a/build/k8s-container.yaml b/build/k8s-container.yaml
new file mode 100644
index 00000000000..2614248f70f
--- /dev/null
+++ b/build/k8s-container.yaml
@@ -0,0 +1,8 @@
+# To build and upload a new version of the build container run:
+# gcloud container builds submit --config k8s-container.yaml .
+
+steps:
+ - name: 'gcr.io/cloud-builders/docker'
+ args: ['build', '-f', 'Dockerfile.k8s-cloud-builder', '-t', 'gcr.io/$PROJECT_ID/k8s-cloud-builder', '.']
+
+images: ['gcr.io/$PROJECT_ID/k8s-cloud-builder' ]
diff --git a/gcb/release.yaml b/gcb/release.yaml
new file mode 100644
index 00000000000..2edb178d944
--- /dev/null
+++ b/gcb/release.yaml
@@ -0,0 +1,38 @@
+timeout: 14400s
+
+secrets:
+- kmsKeyName: projects/kubernetes-release-test/locations/global/keyRings/anago/cryptoKeys/anago-crypto
+ secretEnv:
+ GITHUB_TOKEN: CiQAgPFXnRMc5ZcjM+vEL/4GqevMkjKgWNzwzv9vCQTqLoqzjeoSUQCWqHUkjJaDHICJxKpaJWFzktaSMH9V23XtbqbARYGQumKZYylQQ8kQ5DJPDSjisGoI5c7F+Mgic6iqHY/qmEWRGJo+wwMPqb8BMx9wrotP/A==
+
+steps:
+- name: gcr.io/cloud-builders/git
+ args:
+ - "clone"
+ - "https://github.com/kubernetes/release"
+
+- name: gcr.io/$PROJECT_ID/k8s-cloud-builder
+ dir: release
+ secretEnv:
+ - GITHUB_TOKEN
+ args:
+ - "./anago"
+ - "${_RELEASE_BRANCH}"
+ - "${_NOMOCK}"
+ - "${_OFFICIAL}"
+ - "${_BUILDVERSION}"
+ - "--yes"
+ - "--gcb"
+ - "--basedir=/workspace"
+ - "--tmpdir=/workspace/tmp"
+
+tags:
+- ${_GCP_USER_TAG}
+- ${_RELEASE_BRANCH}
+- ${_BUILD_POINT}
+- ${_NOMOCK_TAG}
+- ${_OFFICIAL_TAG}
+- RELEASE
+
+options:
+ machineType: N1_HIGHCPU_32
diff --git a/gcb/stage.yaml b/gcb/stage.yaml
new file mode 100644
index 00000000000..ca379db8b95
--- /dev/null
+++ b/gcb/stage.yaml
@@ -0,0 +1,74 @@
+timeout: 14400s
+
+secrets:
+- kmsKeyName: projects/kubernetes-release-test/locations/global/keyRings/anago/cryptoKeys/anago-crypto
+ secretEnv:
+ GITHUB_TOKEN: CiQAgPFXnRMc5ZcjM+vEL/4GqevMkjKgWNzwzv9vCQTqLoqzjeoSUQCWqHUkjJaDHICJxKpaJWFzktaSMH9V23XtbqbARYGQumKZYylQQ8kQ5DJPDSjisGoI5c7F+Mgic6iqHY/qmEWRGJo+wwMPqb8BMx9wrotP/A==
+
+steps:
+- name: gcr.io/cloud-builders/git
+ args:
+ - "clone"
+ - "https://github.com/kubernetes/release"
+
+- name: gcr.io/$PROJECT_ID/k8s-cloud-builder
+ dir: release
+ secretEnv:
+ - GITHUB_TOKEN
+ args:
+ - "./anago"
+ - "${_RELEASE_BRANCH}"
+ - "--stage"
+ - "--prebuild"
+ - "${_BUILD_AT_HEAD}"
+ - "${_NOMOCK}"
+ - "${_OFFICIAL}"
+ - "${_BUILDVERSION}"
+ - "--yes"
+ - "--gcb"
+ - "--basedir=/workspace"
+ - "--tmpdir=/workspace/tmp"
+
+- name: gcr.io/google_containers/kube-cross:local
+ dir: release
+ args:
+ - "./anago"
+ - "${_RELEASE_BRANCH}"
+ - "--stage"
+ - "--buildonly"
+ - "${_BUILD_AT_HEAD}"
+ - "${_NOMOCK}"
+ - "${_OFFICIAL}"
+ - "${_BUILDVERSION}"
+ - "--yes"
+ - "--gcb"
+ - "--basedir=/workspace"
+ - "--tmpdir=/workspace/tmp"
+
+- name: gcr.io/$PROJECT_ID/k8s-cloud-builder
+ dir: release
+ secretEnv:
+ - GITHUB_TOKEN
+ args:
+ - "./anago"
+ - "${_RELEASE_BRANCH}"
+ - "--stage"
+ - "${_BUILD_AT_HEAD}"
+ - "${_NOMOCK}"
+ - "${_OFFICIAL}"
+ - "${_BUILDVERSION}"
+ - "--yes"
+ - "--gcb"
+ - "--basedir=/workspace"
+ - "--tmpdir=/workspace/tmp"
+
+tags:
+- ${_GCP_USER_TAG}
+- ${_RELEASE_BRANCH}
+- ${_BUILD_POINT}
+- ${_NOMOCK_TAG}
+- ${_OFFICIAL_TAG}
+- STAGE
+
+options:
+ machineType: N1_HIGHCPU_32
diff --git a/gcbmgr b/gcbmgr
new file mode 100755
index 00000000000..20cf8537cc5
--- /dev/null
+++ b/gcbmgr
@@ -0,0 +1,460 @@
+#!/bin/bash
+#
+# Copyright 2017 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.
+#
+# Set PROGram name
+PROG=${0##*/}
+########################################################################
+#+
+#+ NAME
+#+ $PROG - Manage Kubernetes Container Release Builds
+#+
+#+ SYNOPSIS
+#+ Reporting:
+#+ $PROG list [STATUS]
+#+ $PROG staged
+#+ $PROG tail|stream [BUILD_ID]
+#+ Staging:
+#+ $PROG stage [--buildversion=]
+#+ [--build-at-head] [--nomock] [--official]
+#+ Releasing:
+#+ $PROG release --buildversion=
+#+ [--nomock] [--official]
+#+ $PROG [--helpshort|--usage|-?]
+#+ $PROG [--help|-man]
+#+
+#+ DESCRIPTION
+#+ Manage Kubernetes/Kubernetes release builds created on Container Builder
+#+ on the Google Cloud Platform.
+#+
+#+ Releases can only occur from staged builds. The --buildversion arg
+#+ works for both staging and releasing. The format of a build version is
+#+ vX.Y.Z{-alpha.n|-beta.n}.NN+commit-hash
+#+ (Ex. v1.8.8-beta.0.72+cce11c6a185279)
+#+
+#+ 'list' shows a columnized output of job associated tags, the job id and
+#+ the start time of the job. The tags provide lots of useful info:
+#+
+#+ * Who - $USER or GCP USER
+#+ * Source commit - HEAD, (result of) find_green_build or --buildversion
+#+ * Branch
+#+ * Type - STAGE or RELEASE
+#+ * Flags - --official and --nomock
+#+
+#+ Typical usage:
+#+
+#+ # List running jobs
+#+ $ $PROG
+#+
+#+ # List up to last 5 succeeding jobs
+#+ $ $PROG list success
+#+
+#+ # "tail"/stream most recent running build
+#+ $ $PROG tail
+#+
+#+ # Check Staged builds
+#+ $ $PROG staged
+#+
+#+ # Stage a new master branch release (on passing blocking tests)
+#+ $ $PROG master
+#+
+#+ # Stage a new master branch release (at head)
+#+ $ $PROG master --build-at-head
+#+
+#+ # Stage a new release-1.9 branch release (on passing blocking tests)
+#+ $ $PROG release-1.9
+#+
+#+ # Stage a new release-1.9 branch release (at head)
+#+ $ $PROG release-1.9
+#+
+#+ # Release a previously staged build
+#+ $ $PROG release-1.8 --buildversion=v1.8.8-beta.0.72+cce11c6a185279
+#+
+#+ OPTIONS
+#+ tail|stream - tail/stream the latest running job to your
+#+ console window. You can also specify a
+#+ BUILD_ID to stream.
+#+ list - List last (up to) 5 jobs.
+#+ Default is to list jobs of any status
+#+ Or specified by one of WORKING, FAILURE
+#+ SUCCESS or CANCELLED (case not important)
+#+ staged - Show all staged builds. With --nomock
+#+ non-mock staged builds are shown. Without
+#+ --nomock, both stage/*-$GCP_USER
+#+ & stage/*-gcb builds are shown and
+#+ available for release.
+#+ --build-at-head - Build directly from head. Do not analyze
+#+ test data to pick a candidate.
+#+ --nomock - Stage a non-mocked release build to prepare
+#+ for an actual release.
+#+ --official - For release-* branches, stage an official
+#+ X.Y.Z release. Without --official, only the
+#+ -beta on the branch is incremented and built.
+#+ --buildversion - Release from a previously staged build or
+#+ stage a known version.
+#+ [--help | -man] - display man page for this script
+#+ [--usage | -?] - display in-line usage
+#+
+#+ EXAMPLES
+#+ $PROG - Default 'list' behavior
+#+ $PROG stream - Show the most recent active log
+#+ $PROG master --build-at-head
+#+ - Build at head on the master branch
+#+ $PROG release-1.8 --official
+#+ - Analyze test data to find a candidate and
+#+ stage an official build for release in mock
+#+ mode.
+#+ $PROG release-1.8 --official --nomock
+#+ - Same as above but stage in non-mock bucket.
+#+
+#+ FILES
+#+ anago - Main release tool
+#+ find_green_build - Test analysis tool
+#+
+#+ SEE ALSO
+#+ lib/common.sh - base function definitions
+#+ lib/github.sh - github specific functions
+#+ lib/releaselib.sh - release specific functions
+#+
+#+ BUGS/TODO
+#+
+########################################################################
+# Deal with OSX limitations out the gate for anyone that tries this there
+BASE_ROOT=$(dirname $(readlink -e "$BASH_SOURCE" 2>&1)) \
+ || BASE_ROOT="$BASH_SOURCE"
+source $BASE_ROOT/lib/common.sh
+source $TOOL_LIB_PATH/gitlib.sh
+source $TOOL_LIB_PATH/releaselib.sh
+
+###############################################################################
+# FUNCTIONS
+###############################################################################
+###############################################################################
+# common::cleanexit prog-specific override function
+# @param exit code
+#
+common::cleanexit () {
+ [[ -t 1 ]] && tput cnorm
+
+ common::timestamp end
+ exit ${1:-0}
+}
+
+
+list_staged_builds () {
+ local bucket
+ local i
+ local n
+ local minor
+ local staging_buckets
+
+ # Gather last releases
+ gitlib::last_releases
+
+ logecho
+ logecho "${TPUT[BOLD]}Last published releases by branch:${TPUT[OFF]}"
+ for i in $(for n in ${!LAST_RELEASE[*]}; do echo $n; done |sort -h); do
+ logecho $i: ${LAST_RELEASE[$i]}
+ done
+
+ for bucket in $BUCKET $USER_BUCKET; do
+ # Store existing buckets in an array for later use
+ staging_buckets+=(gs://$bucket/stage)
+ logecho
+ logecho "${TPUT[BOLD]}Staged builds on $bucket:${TPUT[OFF]}"
+ gsutil ls -h gs://$bucket/stage 2>&-
+ done
+
+ # TODO: Experiment to look at all current versions and then compare
+ # the related builds in staging to them to only show valid/usable
+ # staged builds. The below experiment works except that it excludes
+ # master branch Z+1s until the first Z+1 is published. Still looking
+ # for a clever, uncomplicated way of displaying this without sending
+ # people through the gauntlet of trying to figure this out themselves.
+ # On the plus side, anago does a pretty good job of cleaning up older
+ # staged builds so the effect here is minimal
+ #for i in $(for n in ${!LAST_RELEASE[*]}; do echo $n; done |sort -h); do
+ # [[ ${LAST_RELEASE[$i]} =~ (v[0-9]+\.[0-9]+\.) ]]
+ # minor=${BASH_REMATCH[1]}
+ # n=$(echo ${LAST_RELEASE[$i]} | tr -d '[a-z-.]')
+ # for build in $(gsutil ls -h ${staging_buckets[*]} |fgrep $minor); do
+ # [[ $build =~ ${VER_REGEX[release]} ]]
+ # n2=$(echo ${BASH_REMATCH[0]} | tr -d '[a-z-.]')
+ # ((n2&-)
+
+ # Convert time to local time
+ time=$(date -d $time +%Y-%b-%d+%R:%S)
+ echo "$tags" "${status:0:1}" "$id" "$time"
+ echo
+ ((counter>=count)) && break
+ done
+ } |column -te -c80
+}
+
+submit_it () {
+ local substitutions
+
+ # Additional TAG substitutions
+ substitutions="_OFFICIAL_TAG=$OFFICIAL_TAG,_NOMOCK_TAG=$NOMOCK_TAG"
+ substitutions+=",_BUILD_POINT=$BUILD_POINT,_GCP_USER_TAG=$GCP_USER_TAG"
+
+ [[ $COMMAND == stage ]] && substitutions+=",_BUILD_AT_HEAD=$BUILD_AT_HEAD"
+
+ # The usual suspects
+ substitutions+=",_RELEASE_BRANCH=$RELEASE_BRANCH,_OFFICIAL=$OFFICIAL"
+ substitutions+=",_NOMOCK=$NOMOCK,_BUILDVERSION=$BUILDVERSION"
+
+ if ! JOB_DATA=$($GCLOUD container builds submit --no-source \
+ --config=$YAML_FILE --async --disk-size=$DISK_SIZE \
+ --substitutions $substitutions 2>&1); then
+ logecho "$FAILED: Job was not submitted. Details:"
+ logecho "$JOB_DATA"
+ exit 1
+ fi
+
+ BUILD_ID=$(echo "$JOB_DATA" |awk 'END{print $1}')
+ [[ "$JOB_DATA" =~ Logs\ are\ available\ at\ \[(https.*)\]\. ]] \
+ && BUILD_URL=${BASH_REMATCH[1]}
+ logecho $HR
+ logecho "${COMMAND^^} $BUILD_ID submitted sucessfully."
+ logecho $HR
+
+ logecho
+ logecho "To view last build:"
+ logecho "$ $PROG tail"
+ logecho
+ logecho "To view this specific build:"
+ logecho "$ $PROG tail $BUILD_ID"
+ logecho "-OR-"
+ logecho "$ $GCLOUD container builds log --stream $BUILD_ID"
+ logecho "-OR-"
+ logecho "$BUILD_URL"
+}
+
+release_it () {
+ if [[ -z $RELEASE_BRANCH ]]; then
+ logecho "Branch not set. Can't continue"
+ return 1
+ fi
+
+ # Check for mandatory buildversion
+ if [[ -z $FLAGS_buildversion ]]; then
+ logecho "--buildversion= required for 'release' jobs."
+ return 1
+ fi
+
+ submit_it
+}
+
+stage_it () {
+ if [[ -z $RELEASE_BRANCH ]]; then
+ logecho "Branch not set. Can't continue"
+ return 1
+ fi
+
+ # Get kube_cross version
+ KUBE_CROSS_VERSION=$(curl -s https://raw.githubusercontent.com/kubernetes/kubernetes/$RELEASE_BRANCH/build/build-image/cross/VERSION)
+
+ [[ -z $KUBE_CROSS_VERSION ]] \
+ && common::exit 1 "Unable to set KUBE_CROSS_VERSION. Exiting..."
+
+ # Submit it
+ submit_it
+}
+
+
+###############################################################################
+# MAIN
+###############################################################################
+##############################################################################
+# Initialize logs
+##############################################################################
+# Initialize and save up to 10 (rotated logs)
+MYLOG=$TMPDIR/$PROG.log
+common::logfileinit $MYLOG 10
+# BEGIN script
+common::timestamp begin
+
+gitlib::repo_state || common::exit 1 "Exiting..."
+
+# Ensure some prerequisites
+if ! common::set_cloud_binaries; then
+ logecho "Releasing Kubernetes requires gsutil and gcloud. Please download,"
+ logecho "install and authorize through the Google Cloud SDK:"
+ logecho
+ logecho "https://developers.google.com/cloud/sdk/"
+ common::exit 1 "Exiting..."
+fi
+common::check_packages jq || common::exit 1 "Exiting..."
+
+logecho
+
+# Defaults to "list" operation
+COMMAND=${POSITIONAL_ARGV[0]:-"list"}
+ARG2=${POSITIONAL_ARGV[1]}
+PROJECT="kubernetes-release-test"
+# Append $PROJECT to GCLOUD
+GCLOUD+=" --project $PROJECT"
+BUCKET="kubernetes-release"
+# disk size must take base image into consideration.
+# The amount specified is not what is "free"
+DISK_SIZE="150"
+GCP_USER=$($GCLOUD auth list --filter=status:ACTIVE --format="value(account)")
+# This is used as a tag so convert @ to -at- (for yaml tag field
+# where @ is invalid)
+# First, for @google.com users strip off the @domain.tld
+# If non-google.com, convert @ to -at-
+GCP_USER_TAG=${GCP_USER%%@google.com}
+GCP_USER_TAG=${GCP_USER_TAG/@/-at-}
+# GCP also doesn't like anything even remotely looking like a domain name
+# in the bucket name so convert . to -
+GCP_USER_TAG=${GCP_USER_TAG/\./-}
+
+if ((FLAGS_official)); then
+ OFFICIAL_TAG="official"
+ OFFICIAL="--$OFFICIAL_TAG"
+ DISK_SIZE="250"
+fi
+
+if ((FLAGS_build_at_head)); then
+ BUILD_POINT="HEAD"
+ BUILD_AT_HEAD="--build-at-head"
+fi
+
+if ((FLAGS_nomock)); then
+ NOMOCK_TAG="nomock"
+ NOMOCK="--$NOMOCK_TAG"
+else
+ USER_BUCKET=$BUCKET-$GCP_USER_TAG
+ BUCKET+="-gcb"
+fi
+
+# BUILD_POINT used in yaml tags field and is one of:
+# * HEAD (from --build-at-head)
+# * Value of FLAGS_buildversion
+# * Defaulting to searching for a build using find_green_build
+#
+if [[ -n $FLAGS_buildversion ]]; then
+ BUILD_POINT=$FLAGS_buildversion
+ BUILDVERSION="--buildversion=${FLAGS_buildversion/+/-}"
+else
+ BUILD_POINT=${BUILD_POINT:-"find_green_build"}
+fi
+
+# TODO: Add a check here that user is allowed to submit jobs to $PROJECT
+# Respond with guidance on how to get on board
+
+case $COMMAND in
+ list) list_jobs $ARG2
+ common::exit 0
+ ;;
+ staged) list_staged_builds
+ common::exit 0
+ ;;
+ stream|tail) stream_job_log $ARG2
+ common::exit 0
+ ;;
+ stage) YAML_FILE="$TOOL_ROOT/gcb/stage.yaml"
+ RELEASE_BRANCH="$ARG2"
+ stage_it
+ ;;
+ release) if ((FLAGS_nomock)); then
+ logecho
+ logecho "$ATTENTION!!"
+ if ! Askyorn "Are you sure you want to submit an actual release job against the $RELEASE_BRANCH branch"; then
+ common::exit 1 "Exiting..."
+ fi
+ fi
+
+ DISK_SIZE="100"
+ YAML_FILE="$TOOL_ROOT/gcb/release.yaml"
+ RELEASE_BRANCH="$ARG2"
+ release_it
+ ;;
+ *) common::exit 1 "Unknown option $COMMAND. Exiting..."
+ ;;
+esac || common::exit 1 "Exiting..."
+
+# END script
+common::timestamp end
diff --git a/lib/common.sh b/lib/common.sh
index 53c05a7ab41..3a7222d4519 100755
--- a/lib/common.sh
+++ b/lib/common.sh
@@ -24,9 +24,11 @@ export PROG
set -o errtrace
-# TODO:
-# - Figure out a way to share common bits with other Kubernetes sub repos
-# - cleanup / function headers
+# OSX not supported. Tell them right away
+if [[ $(uname) == "Darwin" ]]; then
+ echo "OSX is not a supported OS for running these tools. Exiting..."
+ exit 1
+fi
##############################################################################
# COMMON CONSTANTS
diff --git a/lib/gitlib.sh b/lib/gitlib.sh
index d780b13a1bf..56d2a9b5e0e 100644
--- a/lib/gitlib.sh
+++ b/lib/gitlib.sh
@@ -20,22 +20,16 @@
###############################################################################
# CONSTANTS
###############################################################################
-# TODO: This needs to be pulled into .netrc or some other more secure location
-# Any contributor could by accident or on purpose change the yaml or this script
-# directly to "set -x" in which case, the TOKEN would be readable in the
-# GCB logs
-# netrc with git doesn't seem to work, but a combination approach with
-# netrc for curl and git remotes with embedded tokens might be an answer
-# the files themselves in the container don't need to be encrypted necessarily
-# as noone has access to those, but we can't expose this via the env
: ${GITHUB_TOKEN:=$FLAGS_github_token}
-GHCURL="curl -s --fail --retry 10 -u $GITHUB_TOKEN:x-oauth-basic"
+[[ -n $GITHUB_TOKEN ]] && GITHUB_TOKEN_FLAG=("-u" "$GITHUB_TOKEN:x-oauth-basic")
+GHCURL="curl -s --fail --retry 10 ${GITHUB_TOKEN_FLAG[*]}"
JCURL="curl -g -s --fail --retry 10"
K8S_GITHUB_API_ROOT='https://api.github.com/repos'
K8S_GITHUB_API="$K8S_GITHUB_API_ROOT/kubernetes/kubernetes"
K8S_GITHUB_RAW_ORG='https://raw.githubusercontent.com/kubernetes'
-K8S_GITHUB_SEARCHAPI='https://api.github.com/search/issues?per_page=100&q=is:pr%20repo:kubernetes/kubernetes%20'
+K8S_GITHUB_SEARCHAPI_ROOT='https://api.github.com/search/issues?per_page=100'
+K8S_GITHUB_SEARCHAPI="$K8S_GITHUB_SEARCHAPI_ROOT&q=is:pr%20repo:kubernetes/kubernetes%20"
K8S_GITHUB_URL='https://github.com/kubernetes/kubernetes'
if ((FLAGS_gcb)); then
K8S_GITHUB_AUTH_ROOT="https://git@github.com/"
@@ -315,14 +309,16 @@ fi
###############################################################################
# Search for a matching release tracking issue
-# @param version RELEASE_VERSION_PRIME
+# @param version - RELEASE_VERSION_PRIME
+# @param repo - org/repo
# returns 1 if none found
-# prints most recent issue maching
+# prints most recent open issue maching
gitlib::search_release_issue () {
local version=$1
+ local repo=$2
local issue
- issue=$($GHCURL $K8S_GITHUB_SEARCHAPI_ROOT&q=Release+$version+Tracking+in:title+type:issue+state:open+repo:$RELEASE_TRACKING_REPO | jq -r '.items[] | (.number | tostring)' |sort -n |tail -1)
+ issue=$($GHCURL "$K8S_GITHUB_SEARCHAPI_ROOT&q=Release+$version+Tracking+in:title+type:issue+state:open+repo:$repo" | jq -r '.items[] | (.number | tostring)' |sort -n |tail -1)
[[ -z $issue ]] && return 1
@@ -330,14 +326,14 @@ gitlib::search_release_issue () {
}
###############################################################################
-# Create a release tracking issue for posting notifications.
+# Create/update a release tracking issue for posting notifications.
# Mostly for use by --gcb since there's no other email mechanism from which
# to send detailed html notifictions.
# @param version RELEASE_VERSION_PRIME
-PROGSTEP[create_release_issue]="CREATE/UPDATE RELEASE TRACKING ISSUE"
-gitlib::create_release_issue () {
+PROGSTEP[gitlib::update_release_issue]="CREATE/UPDATE RELEASE TRACKING ISSUE"
+gitlib::update_release_issue () {
local version=$1
- local assignee="david-mcmahon"
+ local assignee
local milestone
local stage
local text
@@ -353,58 +349,52 @@ gitlib::create_release_issue () {
if ((FLAGS_nomock)); then
repo="kubernetes/sig-release"
- # Let the cc below build the guide
- assignee="null"
# Would be nice to have a broad distribution list here on par with email
# distributions
- cc="@kubernetes/sig-release-members"
+ cc="cc @kubernetes/sig-release-members"
else
- logecho "No PR created for mock runs..."
- return 0
- # Need a real mock repo to update issues in
- # Also this might have to be a global if we end up using
- # comment_release_issue() and search_release_issue()
- repo="david-mcmahon/release"
+ repo="k8s-release-robot/sig-release"
# Force milestone to null on this repo or the curl hangs
milestone="null"
fi
- text="Kubernetes $version has been built and pushed.\n\nThe release notes have been updated in $CHANGELOG_FILE with a pointer to it on github"
-
- # If the milestone doesn't exist, this will fail.
- # May want to check that and only add if there's a valid value to add, Ugh.
- issue_number=$($GHCURL $K8S_GITHUB_API_ROOT/$repo/issues --data \
- "{
- \"title\": \"Release $version Tracking\",
- \"body\": \"$text\ncc $cc\n\",
- \"assignee\": \"$assignee\",
- \"milestone\": $milestone,
- \"labels\": [
- \"sig-release\",
- \"stage/${stage:-stable}\"
- ]
- }" |jq -r '.number')
-
- if [[ -n $issue_number ]]; then
- logecho "Created issue #$issue_number on github:"
- logecho "http://github.com/$repo/issues/$issue_number"
+ text="Kubernetes $version has been built and pushed.\n\nThe release notes have been updated in $CHANGELOG_FILE with a pointer to it on github."
+
+ # Search for an existing OPEN issue
+ logecho -n "Searching for an existing release tracking issue: "
+ if issue_number=$(gitlib::search_release_issue $version $repo); then
+ logecho "$issue_number"
+ logecho -n "Updating issue $issue_number: "
+ # Add a comment
+ if $GHCURL $K8S_GITHUB_API_ROOT/$repo/issues/$issue_number/comments \
+ --data "{ \"body\": \"$text\n$cc\n\" }"; then
+ logecho $OK
+ else
+ logecho $FAILED
+ return 1
+ fi
else
- logecho "There was a problem creating the release tracking issue"
- logecho "This should be done manually."
+ logecho "NONE"
+ # Create a new issue
+ # If the milestone doesn't exist, this will fail.
+ # May want to check that and only add if there's a valid value to add, Ugh.
+ issue_number=$($GHCURL $K8S_GITHUB_API_ROOT/$repo/issues --data \
+ "{
+ \"title\": \"Release $version Tracking\",
+ \"body\": \"$text\n$cc\n\",
+ \"milestone\": $milestone,
+ \"labels\": [
+ \"sig/release\",
+ \"stage/${stage:-stable}\"
+ ]
+ }" |jq -r '.number')
+
+ if [[ -n $issue_number ]]; then
+ logecho "Created issue #$issue_number on github:"
+ logecho "http://github.com/$repo/issues/$issue_number"
+ else
+ logecho "There was a problem creating the release tracking issue"
+ logecho "This should be done manually."
+ fi
fi
}
-
-###############################################################################
-# Create a release tracking issue for posting notifications.
-# Mostly for use by --gcb since there's no other email mechanism from which
-# to send detailed html notifictions.
-gitlib::comment_release_issue () {
- local issue=$1
-
- $GHCURL $K8S_GITHUB_API_ROOT/$RELEASE_TRACKING_REPO/issues/$issue/comments \
- --data \
- "{
- \"body\": \"$(awk '{printf "%s\\n", $0}' $HOME/look/release-notes.md)\"
- }"
-}
-
diff --git a/lib/releaselib.sh b/lib/releaselib.sh
index 78a02894627..e454dd988b0 100644
--- a/lib/releaselib.sh
+++ b/lib/releaselib.sh
@@ -686,7 +686,7 @@ release::gcs::publish_version () {
[[ "$version" =~ alpha|beta|rc ]] || type="stable"
fi
- if ! $GSUTIL ls $release_dir >/dev/null 2>&1 ; then
+ if ! logrun $GSUTIL ls $release_dir; then
logecho "Release files don't exist at $release_dir"
return 1
fi
@@ -948,8 +948,9 @@ release::docker::release () {
done
fi
- # Always reset back to ${USER_AT_DOMAIN:-$USER@$DOMAIN_NAME}
- logrun $GCLOUD config set account "${USER_AT_DOMAIN:-$USER@$DOMAIN_NAME}"
+ # Always reset back to $GCP_USER
+ # This is set in push-build.sh and anago
+ ((FLAGS_gcb)) || logrun $GCLOUD config set account $GCP_USER
return $ret
}
@@ -1007,7 +1008,7 @@ release::docker::release_from_tarfiles () {
docker tag $orig_tag $new_tag
logecho -n "Pushing $new_tag: "
# 'gcloud docker' gives lots of internal_failure's so add retries
- logrun -r 5 -s ${docker_push_cmd[@]} push "$new_tag"
+ logrun -r 5 -s ${docker_push_cmd[@]} push "$new_tag" || return 1
done
docker rmi $orig_tag ${new_tags[@]} &>/dev/null || true
diff --git a/push-build.sh b/push-build.sh
index 65e491788de..cfdbb574aa9 100755
--- a/push-build.sh
+++ b/push-build.sh
@@ -23,7 +23,7 @@ PROG=${0##*/}
#+
#+ SYNOPSIS
#+ $PROG [--nomock] [--federation] [--noupdatelatest] [--ci]
-#+ [--bucket=] [--domain-name=domain.tld]
+#+ [--bucket=]
#+ [--private-bucket]
#+ $PROG [--helpshort|--usage|-?]
#+ $PROG [--help|-man]
@@ -54,7 +54,6 @@ PROG=${0##*/}
#+ values are kubernetes(default) or federation.
#+ [--gcs-suffix=] - Specify a suffix to append to the upload
#+ destination on GCS.
-#+ [--domain-name=] - Specify an alternate domain.tld
#+ [--docker-registry=] - If set, push docker images to specified
#+ registry/project
#+ [--version-suffix=] - Append suffix to version name if set.
@@ -106,7 +105,6 @@ common::timestamp begin
# MAIN
###############################################################################
RELEASE_BUCKET=${FLAGS_bucket:-"kubernetes-release-dev"}
-DOMAIN_NAME=${FLAGS_domain_name:-"google.com"}
# Compatibility with incoming global args
[[ $KUBE_GCS_UPDATE_LATEST == "n" ]] && FLAGS_noupdatelatest=1
@@ -172,6 +170,12 @@ if ! common::set_cloud_binaries; then
common::exit 1
fi
+# Nothing should work without this. The entire release workflow depends
+# on it whether running from the desktop or GCB
+GCP_USER=$($GCLOUD auth list --filter=status:ACTIVE \
+ --format="value(account)" 2>/dev/null)
+[[ -n "$GCP_USER" ]] || common::exit 1 "Unable to set a valid GCP credential!"
+
logecho -n "Check/make release bucket $RELEASE_BUCKET: "
logrun -s release::gcs::ensure_release_bucket $RELEASE_BUCKET || common::exit 1