go.etcd.io/etcd@v3.3.27+incompatible/scripts/release (about) 1 #!/usr/bin/env bash 2 3 set -o errexit 4 set -o nounset 5 set -o pipefail 6 7 help() { 8 echo "$(basename $0) [version]" 9 echo "Release etcd using the same approach as the etcd-release-runbook (https://goo.gl/Gxwysq)" 10 echo "" 11 echo "WARNING: This does not perform the 'Add API capabilities', 'Performance testing' " 12 echo " or 'Documentation' steps. These steps must be performed manually BEFORE running this tool." 13 echo "" 14 echo "WARNING: This script does not sign releases, publish releases to github or sent announcement" 15 echo " emails. These steps must be performed manually AFTER running this tool." 16 echo "" 17 echo " args:" 18 echo " version: version of etcd to release, e.g. '3.2.18'" 19 echo " flags:" 20 echo " --no-upload: skip gs://etcd binary artifact uploads." 21 echo " --no-docker-push: skip docker image pushes." 22 echo "" 23 } 24 25 main() { 26 VERSION=$1 27 if [[ ! "${VERSION}" =~ [0-9]+.[0-9]+.[0-9]+ ]]; then 28 echo "Expected 'version' param of the form '<major-version>.<minor-version>.<patch-version>' but got '${VERSION}'" 29 exit 1 30 fi 31 RELEASE_VERSION="v${VERSION}" 32 MINOR_VERSION=$(echo "${VERSION}" | cut -d. -f 1-2) 33 BRANCH="release-${MINOR_VERSION}" 34 35 if ! command -v docker >/dev/null; then 36 echo "cannot find docker" 37 exit 1 38 fi 39 40 # Expected umask for etcd release artifacts 41 umask 022 42 43 # Set up release directory. 44 local reldir="/tmp/etcd-release-${VERSION}" 45 if [ ! -d "${reldir}/etcd" ]; then 46 mkdir -p "${reldir}" 47 cd "${reldir}" 48 git clone https://github.com/etcd-io/etcd.git --branch "${BRANCH}" 49 fi 50 cd "${reldir}/etcd" 51 52 # If a release version tag already exists, use it. 53 local remote_tag_exists=$(git ls-remote origin "refs/tags/${RELEASE_VERSION}" | grep -c "${RELEASE_VERSION}") 54 if [ ${remote_tag_exists} -gt 0 ]; then 55 echo "Release version tag exists on remote. Checking out refs/tags/${RELEASE_VERSION}" 56 git checkout -q "tags/${RELEASE_VERSION}" 57 fi 58 59 # Check go version. 60 # download "yq" from https://github.com/mikefarah/yq 61 local go_version="go$(yq read .travis.yml "go[0]")" 62 local current_go_version=$(go version | awk '{ print $3 }') 63 if [[ "${current_go_version}" != "${go_version}" ]]; then 64 echo "Current go version is ${current_go_version}, but etcd ${RELEASE_VERSION} requires ${go_version} (see .travis.yml)." 65 exit 1 66 fi 67 68 # If the release tag does not already exist remotely, create it. 69 if [ ${remote_tag_exists} -eq 0 ]; then 70 # Bump version/version.go to release version. 71 local source_version=$(egrep "\s+Version\s*=" version/version.go | sed -e "s/.*\"\(.*\)\".*/\1/g") 72 if [[ "${source_version}" != "${VERSION}" ]]; then 73 source_minor_version=$(echo "${source_version}" | cut -d. -f 1-2) 74 if [[ "${source_minor_version}" != "${MINOR_VERSION}" ]]; then 75 echo "Wrong etcd minor version in version/version.go. Expected ${MINOR_VERSION} but got ${source_minor_version}. Aborting." 76 exit 1 77 fi 78 echo "Updating version from ${source_version} to ${VERSION} in version/version.go" 79 sed -i "s/${source_version}/${VERSION}/g" version/version.go 80 fi 81 82 echo "Building etcd and checking --version output" 83 ./build 84 local etcd_version=$(bin/etcd --version | grep "etcd Version" | awk '{ print $3 }') 85 if [[ "${etcd_version}" != "${VERSION}" ]]; then 86 echo "Wrong etcd version in version/version.go. Expected ${etcd_version} but got ${VERSION}. Aborting." 87 exit 1 88 fi 89 echo "bin/etcd --version:" 90 bin/etcd --version 91 sleep 3 92 93 if [[ ! -z $(git status -s) ]]; then 94 echo "Committing version/version.go update." 95 git add version/version.go 96 git commit -m "version: bump up to ${VERSION}" 97 git diff --staged 98 fi 99 100 # Push the version change if it's not already been pushed. 101 if [ $(git rev-list --count "origin/${BRANCH}..${BRANCH}") -gt 0 ]; then 102 read -p "Push version bump up to ${VERSION} to github.com/etcd-io/etcd [y/N]? " confirm 103 [[ "${confirm,,}" == "y" ]] || exit 1 104 git push 105 fi 106 107 # Tag release. 108 if [ $(git tag --list | grep -c "${RELEASE_VERSION}") -gt 0 ]; then 109 echo "Skipping tag step. git tag ${RELEASE_VERSION} already exists." 110 else 111 echo "Tagging release..." 112 KEYID=$(gpg --list-keys --with-colons| awk -F: '/^pub:/ { print $5 }') 113 if [[ -z "${KEYID}" ]]; then 114 echo "Failed to load gpg key. Is gpg set up correctly for etcd releases?" 115 exit 1 116 fi 117 git tag --local-user "${KEYID}" --sign "${RELEASE_VERSION}" --message "${RELEASE_VERSION}" 118 fi 119 120 # Verify the latest commit has the version tag 121 local tag="$(git describe --exact-match HEAD)" 122 if [ "${tag}" != "${RELEASE_VERSION}" ]; then 123 echo "Error: Expected HEAD to be tagged with ${RELEASE_VERSION}, but 'git describe --exact-match HEAD' reported: ${tag}" 124 exit 1 125 fi 126 127 # Verify the version tag is on the right branch 128 local branch=$(git branch --contains "${RELEASE_VERSION}") 129 if [ "${branch}" != "release-${MINOR_VERSION}" ]; then 130 echo "Error: Git tag ${RELEASE_VERSION} should be on branch release-${MINOR_VERSION} but is on ${branch}" 131 exit 1 132 fi 133 134 # Push the tag change if it's not already been pushed. 135 read -p "Push etcd ${RELEASE_VERSION} tag [y/N]? " confirm 136 [[ "${confirm,,}" == "y" ]] || exit 1 137 git push origin "tags/${RELEASE_VERSION}" 138 fi 139 140 # Build release. 141 # TODO: check the release directory for all required build artifacts. 142 if [ -d release ]; then 143 echo "Skpping release build step. /release directory already exists." 144 else 145 echo "Building release..." 146 # Check for old and new names of the release build script. 147 # TODO: Move the release script into this on as a function? 148 if [ -f ./scripts/release.sh ]; then 149 ./scripts/release.sh "${RELEASE_VERSION}" 150 else 151 ./scripts/build-release.sh "${RELEASE_VERSION}" 152 fi 153 fi 154 155 # Sanity checks. 156 ./release/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcd --version | grep -q "etcd Version: ${VERSION}" || true 157 ./release/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcdctl version | grep -q "etcdctl version: ${VERSION}" || true 158 echo "./release/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcd --version:" 159 ./release/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcd --version 160 sleep 3 161 162 # Upload artifacts. 163 if [ "${NO_UPLOAD}" == 1 ]; then 164 echo "Skipping artifact upload to gs://etcd. --no-upload flat is set." 165 else 166 read -p "Upload etcd ${RELEASE_VERSION} release artifacts to gs://etcd [y/N]? " confirm 167 [[ "${confirm,,}" == "y" ]] || exit 1 168 gsutil -m cp ./release/*.zip gs://etcd/${RELEASE_VERSION}/ 169 gsutil -m cp ./release/*.tar.gz gs://etcd/${RELEASE_VERSION}/ 170 gsutil -m acl ch -u allUsers:R -r gs://etcd/${RELEASE_VERSION}/ 171 fi 172 173 # Push images. 174 if [ "${NO_DOCKER_PUSH}" == 1 ]; then 175 echo "Skipping docker push. --no-docker-push flat is set." 176 else 177 read -p "Publish etcd ${RELEASE_VERSION} docker images to quay.io [y/N]? " confirm 178 [[ "${confirm,,}" == "y" ]] || exit 1 179 for i in {1..5}; do 180 docker login quay.io && break 181 echo "login failed, retrying" 182 done 183 gcloud docker -- login -u _json_key -p "$(cat /etc/gcp-key-etcd-development.json)" https://gcr.io 184 185 echo "Pushing container images to quay.io" ${RELEASE_VERSION} 186 docker push quay.io/coreos/etcd:${RELEASE_VERSION} 187 188 echo "Pushing container images to gcr.io" ${RELEASE_VERSION} 189 gcloud docker -- push gcr.io/etcd-development/etcd:${RELEASE_VERSION} 190 191 for TARGET_ARCH in "-arm64" "-ppc64le"; do 192 echo "Pushing container images to quay.io" ${RELEASE_VERSION}${TARGET_ARCH} 193 docker push quay.io/coreos/etcd:${RELEASE_VERSION}${TARGET_ARCH} 194 195 echo "Pushing container images to gcr.io" ${RELEASE_VERSION}${TARGET_ARCH} 196 gcloud docker -- push gcr.io/etcd-development/etcd:${RELEASE_VERSION}${TARGET_ARCH} 197 done 198 199 echo "Setting permissions using gsutil..." 200 gsutil -m acl ch -u allUsers:R -r gs://artifacts.etcd-development.appspot.com 201 fi 202 203 ### Release validation 204 mkdir -p downloads 205 206 # Check image versions 207 for IMAGE in "quay.io/coreos/etcd:${RELEASE_VERSION}" "gcr.io/etcd-development/etcd:${RELEASE_VERSION}"; do 208 local image_version=$(docker run --rm "${IMAGE}" etcd --version | grep "etcd Version" | awk -F: '{print $2}' | tr -d '[:space:]') 209 if [ "${image_version}" != "${VERSION}" ]; then 210 echo "Check failed: etcd --version output for ${IMAGE} is incorrect: ${image_version}" 211 exit 1 212 fi 213 done 214 215 # Check gsutil binary versions 216 local BINARY_TGZ="etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64.tar.gz" 217 gsutil cp "gs://etcd/${RELEASE_VERSION}/${BINARY_TGZ}" downloads 218 tar -zx -C downloads -f "downloads/${BINARY_TGZ}" 219 local binary_version=$("./downloads/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcd" --version | grep "etcd Version" | awk -F: '{print $2}' | tr -d '[:space:]') 220 if [ "${binary_version}" != "${VERSION}" ]; then 221 echo "Check failed: etcd --version output for ${BINARY_TGZ} from gs://etcd/${RELEASE_VERSION} is incorrect: ${binary_version}" 222 exit 1 223 fi 224 225 # TODO: signing process 226 echo "" 227 echo "WARNING: The release has not been signed and published to github. This must be done manually." 228 echo "" 229 echo "Success." 230 exit 0 231 } 232 233 POSITIONAL=() 234 NO_UPLOAD=0 235 NO_DOCKER_PUSH=0 236 237 while test $# -gt 0; do 238 case "$1" in 239 -h|--help) 240 shift 241 help 242 exit 0 243 ;; 244 --no-upload) 245 NO_UPLOAD=1 246 shift 247 ;; 248 --no-docker-push) 249 NO_DOCKER_PUSH=1 250 shift 251 ;; 252 *) 253 POSITIONAL+=("$1") # save it in an array for later 254 shift # past argument 255 ;; 256 esac 257 done 258 set -- "${POSITIONAL[@]}" # restore positional parameters 259 260 if [[ ! $# -eq 1 ]]; then 261 help 262 exit 1 263 fi 264 265 main $1