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