blob: e31add08832699038cc34f609c6f130eed0e5db8 [file] [log] [blame]
Philipp Wollermanna5afe952016-06-21 14:58:09 +00001#!/bin/bash
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +00002
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00003# Copyright 2015 The Bazel Authors. All rights reserved.
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +00004#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
Philipp Wollermanna5afe952016-06-21 14:58:09 +000017set -eu
18
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +000019# Main deploy functions for the continous build system
20# Just source this file and use the various method:
21# bazel_build build bazel and run all its test
22# bazel_release use the artifact generated by bazel_build and push
23# them to github for a release and to GCS for a release candidate.
24# Also prepare an email for announcing the release.
25
26# Load common.sh
Philipp Wollermann5fabb432018-03-27 04:37:23 -070027SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
28source "$(dirname ${SCRIPT_DIR})/release/common.sh"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +000029
Philipp Wollermann5fabb432018-03-27 04:37:23 -070030if ! command -v gsutil &>/dev/null; then
31 echo "Required tool 'gsutil' not found. Please install it:"
32 echo "See https://cloud.google.com/sdk/downloads for instructions."
33 exit 1
34fi
35if ! command -v github-release &>/dev/null; then
36 echo "Required tool 'github-release' not found. Download it from here:"
37 echo "https://github.com/c4milo/github-release/releases"
38 echo "Just extract the archive and put the binary on your PATH."
39 exit 1
40fi
41if ! command -v debsign &>/dev/null; then
42 echo "Required tool 'debsign' not found. Please install it via apt-get:"
43 echo "apt-get install devscripts"
44 exit 1
45fi
46if ! command -v reprepro &>/dev/null; then
47 echo "Required tool 'reprepro' not found. Please install it via apt-get:"
48 echo "apt-get install reprepro"
49 exit 1
50fi
51if ! command -v gpg &>/dev/null; then
52 echo "Required tool 'gpg' not found. Please install it via apt-get:"
53 echo "apt-get install gnupg"
54 exit 1
55fi
56if ! command -v pandoc &>/dev/null; then
57 echo "Required tool 'pandoc' not found. Please install it via apt-get:"
58 echo "apt-get install pandoc"
59 exit 1
60fi
61# if ! command -v ssmtp &>/dev/null; then
62# echo "Required tool 'ssmtp' not found. Please install it via apt-get:"
63# echo "apt-get install ssmtp"
64# exit 1
65# fi
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +000066
philwoead58472019-05-10 08:23:25 -070067export APT_GPG_KEY_ID=$(gsutil cat gs://bazel-trusted-encrypted-secrets/release-key.gpg.id)
Klaus Aehlig736c46d2016-11-10 16:09:34 +000068
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +000069# Generate a string from a template and a list of substitutions.
70# The first parameter is the template name and each subsequent parameter
71# is taken as a couple: first is the string the substitute and the second
72# is the result of the substitution.
73function generate_from_template() {
74 local value="$1"
75 shift
76 while (( $# >= 2 )); do
77 value="${value//$1/$2}"
78 shift 2
79 done
80 echo "${value}"
81}
82
83# Generate the email for the release.
84# The first line of the output will be the recipient, the second line
85# the mail subjects and the subsequent lines the mail, its content.
86# If no planed release, then this function output will be empty.
87function generate_email() {
Philipp Wollermann5fabb432018-03-27 04:37:23 -070088 RELEASE_CANDIDATE_URL="https://releases.bazel.build/%release_name%/rc%rc%/index.html"
89 RELEASE_URL="https://github.com/bazelbuild/bazel/releases/tag/%release_name%"
90
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +000091 local release_name=$(get_release_name)
92 local rc=$(get_release_candidate)
93 local args=(
94 "%release_name%" "${release_name}"
95 "%rc%" "${rc}"
Damien Martin-Guillerezacbcbc22016-12-20 07:40:42 +000096 "%relnotes%" "# $(get_full_release_notes)"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +000097 )
98 if [ -n "${rc}" ]; then
99 args+=(
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700100 "%url%" "$(generate_from_template "${RELEASE_CANDIDATE_URL}" "${args[@]}")"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000101 )
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700102 generate_from_template \
103 "$(cat "${SCRIPT_DIR}/rc_email.txt")" \
104 "${args[@]}"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000105 elif [ -n "${release_name}" ]; then
106 args+=(
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700107 "%url%" "$(generate_from_template "${RELEASE_URL}" "${args[@]}")"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000108 )
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700109 generate_from_template \
110 "$(cat "${SCRIPT_DIR}/release_email.txt")" "${args[@]}"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000111 fi
112}
113
dmarting5e576632017-07-24 19:01:08 +0200114function get_release_page() {
Damien Martin-Guillerezb6e29ca2017-07-26 16:06:44 +0200115 echo "# $(get_full_release_notes)"'
Damien Martin-Guillerezbf2e4ee2016-07-06 10:04:34 +0000116
117_Notice_: Bazel installers contain binaries licensed under the GPLv2 with
118Classpath exception. Those installers should always be redistributed along with
Damien Martin-Guillerez671045b2016-10-11 14:17:28 +0000119the source code.
120
Philipp Wollermann95048272017-03-17 15:11:58 +0000121Some versions of Bazel contain a bundled version of OpenJDK. The license of the
122bundled OpenJDK and other open-source components can be displayed by running
123the command `bazel license`. The vendor and version information of the bundled
124OpenJDK can be displayed by running the command `bazel info java-runtime`.
125The binaries and source-code of the bundled OpenJDK can be
dmartinge17f8902017-07-27 13:55:10 +0200126[downloaded from our mirror server](https://mirror.bazel.build/openjdk/index.html).
Philipp Wollermann95048272017-03-17 15:11:58 +0000127
Damien Martin-Guillerez671045b2016-10-11 14:17:28 +0000128_Security_: All our binaries are signed with our
Klaus Aehligbaccf242016-10-28 17:37:35 +0000129[public key](https://bazel.build/bazel-release.pub.gpg) 48457EE0.
Damien Martin-Guillerez24795d42017-06-27 11:01:29 +0200130'
dmarting5e576632017-07-24 19:01:08 +0200131}
Damien Martin-Guillerezbf2e4ee2016-07-06 10:04:34 +0000132
dmarting5e576632017-07-24 19:01:08 +0200133# Deploy a github release using a third party tool:
134# https://github.com/c4milo/github-release
135# This methods expects the following arguments:
136# $1..$n files generated by package_build (should not contains the README file)
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700137# Please set GITHUB_TOKEN to talk to the Github API.
dmarting5e576632017-07-24 19:01:08 +0200138function release_to_github() {
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700139 local artifact_dir="$1"
140
dmarting5e576632017-07-24 19:01:08 +0200141 local release_name=$(get_release_name)
142 local rc=$(get_release_candidate)
dmarting5e576632017-07-24 19:01:08 +0200143
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000144 if [ -n "${release_name}" ] && [ -z "${rc}" ]; then
philwob8d0e1b2019-01-17 04:12:08 -0800145 local github_token="$(gsutil cat gs://bazel-trusted-encrypted-secrets/github-trusted-token.enc | \
146 gcloud kms decrypt --project bazel-public --location global --keyring buildkite --key github-trusted-token --ciphertext-file - --plaintext-file -)"
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700147
philwob8d0e1b2019-01-17 04:12:08 -0800148 GITHUB_TOKEN="${github_token}" github-release "bazelbuild/bazel" "${release_name}" "" "$(get_release_page)" "${artifact_dir}/*"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000149 fi
150}
151
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700152# Creates an index of the files contained in folder $1 in Markdown format.
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000153function create_index_md() {
dmarting5e576632017-07-24 19:01:08 +0200154 # First, add the release notes
155 get_release_page
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000156 # Then, add the list of files
157 echo
158 echo "## Index of files"
159 echo
160 for f in $1/*.sha256; do # just list the sha256 ones
161 local filename=$(basename $f .sha256);
Damien Martin-Guillerez671045b2016-10-11 14:17:28 +0000162 echo " - [${filename}](${filename}) [[SHA-256](${filename}.sha256)] [[SIG](${filename}.sig)]"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000163 done
164}
165
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700166# Creates an index of the files contained in folder $1 in HTML format.
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000167function create_index_html() {
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700168 create_index_md "${@}" | pandoc -f markdown -t html
Yun Peng70b29f42016-05-24 18:04:37 +0000169}
170
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000171# Deploy a release candidate to Google Cloud Storage.
172# It requires to have gsutil installed. You can force the path to gsutil
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700173# by setting the GSUTIL environment variable.
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000174# This methods expects the following arguments:
175# $1..$n files generated by package_build
176function release_to_gcs() {
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700177 local artifact_dir="$1"
178
Yun Peng70b29f42016-05-24 18:04:37 +0000179 local release_name="$(get_release_name)"
180 local rc="$(get_release_candidate)"
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700181
dmartingebe36f22017-03-29 12:25:01 +0000182 if [ -n "${release_name}" ]; then
dmartingc58ba092017-05-04 12:38:16 +0200183 local release_path="${release_name}/release"
dmartingebe36f22017-03-29 12:25:01 +0000184 if [ -n "${rc}" ]; then
185 release_path="${release_name}/rc${rc}"
186 fi
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700187 create_index_html "${artifact_dir}" > "${artifact_dir}/index.html"
philwo3bbf9b9d2019-04-17 07:05:01 -0700188 gsutil -m cp "${artifact_dir}/**" "gs://bazel/${release_path}"
Yun Peng70b29f42016-05-24 18:04:37 +0000189 fi
190}
191
Yun Peng3d8ae222016-10-11 13:02:42 +0000192function ensure_gpg_secret_key_imported() {
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700193 if ! gpg --list-secret-keys | grep "${APT_GPG_KEY_ID}" > /dev/null; then
194 keyfile=$(mktemp --tmpdir)
195 chmod 0600 "${keyfile}"
philwoead58472019-05-10 08:23:25 -0700196 gsutil cat "gs://bazel-trusted-encrypted-secrets/release-key.gpg.enc" | \
philwo8ab09072018-04-25 12:57:20 -0700197 gcloud kms decrypt --location "global" --keyring "buildkite" --key "bazel-release-key" --ciphertext-file "-" --plaintext-file "${keyfile}"
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700198 gpg --allow-secret-key-import --import "${keyfile}"
199 rm -f "${keyfile}"
200 fi
201
Yun Peng2d1d4922016-11-15 13:33:47 +0000202 # Make sure we use stronger digest algorithm。
203 # We use reprepro to generate the debian repository,
204 # but there's no way to pass flags to gpg using reprepro, so writting it into
205 # ~/.gnupg/gpg.conf
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700206 if ! grep "digest-algo sha256" ~/.gnupg/gpg.conf > /dev/null; then
207 echo "digest-algo sha256" >> ~/.gnupg/gpg.conf
208 fi
Yun Peng3d8ae222016-10-11 13:02:42 +0000209}
210
Yun Peng70b29f42016-05-24 18:04:37 +0000211function create_apt_repository() {
212 mkdir conf
213 cat > conf/distributions <<EOF
214Origin: Bazel Authors
215Label: Bazel
216Codename: stable
Yun Peng55e042a2016-07-26 13:36:42 +0000217Architectures: amd64 source
Damien Martin-Guillerezc616acc2017-06-27 10:49:01 +0200218Components: jdk1.8
Yun Peng70b29f42016-05-24 18:04:37 +0000219Description: Bazel APT Repository
220DebOverride: override.stable
221DscOverride: override.stable
222SignWith: ${APT_GPG_KEY_ID}
223
224Origin: Bazel Authors
225Label: Bazel
226Codename: testing
Yun Peng55e042a2016-07-26 13:36:42 +0000227Architectures: amd64 source
Damien Martin-Guillerezc616acc2017-06-27 10:49:01 +0200228Components: jdk1.8
Yun Peng70b29f42016-05-24 18:04:37 +0000229Description: Bazel APT Repository
230DebOverride: override.testing
231DscOverride: override.testing
232SignWith: ${APT_GPG_KEY_ID}
233EOF
234
235 cat > conf/options <<EOF
236verbose
237ask-passphrase
238basedir .
239EOF
240
Damien Martin-Guillerez4fb378c2016-12-20 11:04:02 +0000241 # TODO(#2264): this is a quick workaround #2256, figure out a correct fix.
242 cat > conf/override.stable <<EOF
243bazel Section contrib/devel
244bazel Priority optional
245EOF
246 cat > conf/override.testing <<EOF
247bazel Section contrib/devel
248bazel Priority optional
249EOF
Yun Peng70b29f42016-05-24 18:04:37 +0000250
Yun Peng3d8ae222016-10-11 13:02:42 +0000251 ensure_gpg_secret_key_imported
Yun Peng70b29f42016-05-24 18:04:37 +0000252
253 local distribution="$1"
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700254 local deb_pkg_name="$2"
Damien Martin-Guillerezc616acc2017-06-27 10:49:01 +0200255 local deb_dsc_name="$3"
Yun Peng55e042a2016-07-26 13:36:42 +0000256
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700257 debsign -k "${APT_GPG_KEY_ID}" "${deb_dsc_name}"
Yun Peng55e042a2016-07-26 13:36:42 +0000258
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700259 reprepro -C jdk1.8 includedeb "${distribution}" "${deb_pkg_name}"
Yun Peng55e042a2016-07-26 13:36:42 +0000260 reprepro -C jdk1.8 includedsc "${distribution}" "${deb_dsc_name}"
Yun Peng70b29f42016-05-24 18:04:37 +0000261
philwo3bbf9b9d2019-04-17 07:05:01 -0700262 gsutil -m cp -r dists pool "gs://bazel-apt"
Yun Peng70b29f42016-05-24 18:04:37 +0000263}
264
265function release_to_apt() {
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700266 local artifact_dir="$1"
267
Yun Peng70b29f42016-05-24 18:04:37 +0000268 local release_name="$(get_release_name)"
269 local rc="$(get_release_candidate)"
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700270
Yun Peng70b29f42016-05-24 18:04:37 +0000271 if [ -n "${release_name}" ]; then
Yun Peng70b29f42016-05-24 18:04:37 +0000272 local release_label="$(get_full_release_name)"
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700273 local deb_pkg_name="${release_name}/bazel_${release_label}-linux-x86_64.deb"
Damien Martin-Guillerez4fb378c2016-12-20 11:04:02 +0000274 local deb_dsc_name="${release_name}/bazel_${release_label}.dsc"
275 local deb_tar_name="${release_name}/bazel_${release_label}.tar.gz"
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700276
277 pushd "${artifact_dir}"
Yun Peng70b29f42016-05-24 18:04:37 +0000278 if [ -n "${rc}" ]; then
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700279 create_apt_repository testing "${deb_pkg_name}" "${deb_dsc_name}"
Yun Peng70b29f42016-05-24 18:04:37 +0000280 else
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700281 create_apt_repository stable "${deb_pkg_name}" "${deb_dsc_name}"
Yun Peng70b29f42016-05-24 18:04:37 +0000282 fi
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700283 popd
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000284 fi
285}
286
287# A wrapper around the release deployment methods.
288function deploy_release() {
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700289 local release_label="$(get_full_release_name)"
290 local release_name="$(get_release_name)"
291
292 if [[ ! -d $1 ]]; then
293 echo "Usage: deploy_release ARTIFACT_DIR"
294 exit 1
295 fi
296 artifact_dir="$1"
297
298 if [[ -z $release_name ]]; then
299 echo "Could not get the release name - are you in a release branch directory?"
300 exit 1
301 fi
302
303 ensure_gpg_secret_key_imported
304
305 rm -f "${artifact_dir}"/*.{sha256,sig}
306 for file in "${artifact_dir}"/*; do
307 (cd "${artifact_dir}" && sha256sum "$(basename "${file}")" > "${file}.sha256")
308 gpg --no-tty --detach-sign -u "${APT_GPG_KEY_ID}" "${file}"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000309 done
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700310
311 apt_working_dir="$(mktemp -d --tmpdir)"
312 echo "apt_working_dir = ${apt_working_dir}"
313 mkdir "${apt_working_dir}/${release_name}"
314 cp "${artifact_dir}/bazel_${release_label}-linux-x86_64.deb" "${apt_working_dir}/${release_name}"
315 cp "${artifact_dir}/bazel_${release_label}.dsc" "${apt_working_dir}/${release_name}"
316 cp "${artifact_dir}/bazel_${release_label}.tar.gz" "${apt_working_dir}/${release_name}"
317 release_to_apt "${apt_working_dir}"
318
319 gcs_working_dir="$(mktemp -d --tmpdir)"
320 echo "gcs_working_dir = ${gcs_working_dir}"
321 cp "${artifact_dir}"/* "${gcs_working_dir}"
322 release_to_gcs "${gcs_working_dir}"
323
324 github_working_dir="$(mktemp -d --tmpdir)"
325 echo "github_working_dir = ${github_working_dir}"
326 cp "${artifact_dir}"/* "${github_working_dir}"
philwo2b593702018-04-20 04:49:20 -0700327 rm -f "${github_working_dir}/bazel_${release_label}"*.{dsc,tar.gz}{,.sha256,.sig}
Philipp Wollermann5fabb432018-03-27 04:37:23 -0700328 release_to_github "${github_working_dir}"
Damien Martin-Guillerezf7a39312015-08-17 08:32:09 +0000329}