blob: 3d40547a20da39ecbe445e91f9e0205731024be3 [file] [log] [blame]
#!/bin/bash
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# NOTE: This tool must be able to be downloaded and run independently of the
# rest of this repo: the manual release processes that use it do not have a
# fuchsia checkout.
## usage: fetch-build-artifacts \
## [-r] [-p <parent_dir>] [-o <out_dir>] [-h] \
## <buildbucket_id>
##
## Downloads artifacts created by the specified build.
##
## <buildbucket_id> is a large number like '8938070794014050064', which you can
## find on the build results page. This tool accepts an optional leading 'b',
## letting you copy-and-paste the ID component from a URL like
## https://ci.chromium.org/p/fuchsia/builders/luci.fuchsia.ci/garnet-arm64-release-qemu_kvm/b8938011100592458048
##
## Prerequisites:
## - Install the 'gsutil' tool:
## https://cloud.google.com/storage/docs/gsutil_install
## - Run 'gcloud init'. The default project does not matter, but if you need to
## provide one you can use 'fuchsia-infra'.
## - If you don't have gcloud installed, you can run 'gsutil config' instead.
## - The user must have permission to access the target artifacts in Google
## Cloud Storage (GCS).
##
## Optional arguments:
## -r Indicates that the build ID points to a release build, whose
## artifacts are stored in a special GCS bucket.
## -p The parent directory of the destination build artifact directory:
## see -o. Defaults to "${HOME}/.cache/fuchsia/build-artifacts".
## Mutually exclusive with -o.
## -o The directory to write the artifacts to. Defaults to
## <parent_dir>/<buildbucket_id>. Mutually exclusive with -p.
## -h Prints this help message.
set -o errexit
set -o nounset
set -o pipefail
readonly DEFAULT_PARENT_DIR="${HOME}/.cache/fuchsia/build-artifacts"
function usage {
# Prints lines from this file that begin with ##.
sed -n -e 's/^## //p' -e 's/^##$//p' < "${BASH_SOURCE[0]}"
}
function main {
if [[ -z "$(which gsutil)" ]]; then
echo "ERROR: Please install gsutil and run 'gcloud init'."
echo "See https://cloud.google.com/storage/docs/gsutil_install"
return 1
fi
local parent_dir=''
local out_dir=''
local is_release=0
while getopts "rp:o:h" arg; do
case ${arg} in
r)
is_release=1
;;
p)
parent_dir="${OPTARG}"
;;
o)
out_dir="${OPTARG}"
;;
*)
usage
return 1
;;
esac
done
shift $((${OPTIND} - 1))
if [[ "${parent_dir}" ]] && [[ "${out_dir}" ]]; then
echo "ERROR: Cannot specify both -p and -o."
usage
return 1
fi
# Expect exactly one build ID.
# TODO(dbort): We could support multiple build IDs if -o isn't specified.
if [[ $# -ne 1 ]]; then
echo "ERROR: Build ID missing."
usage
return 1
fi
local build_id="$1"
# Make sure it's a number, but allow a leading 'b' since some LUCI URLs
# tack it onto the build ID component.
if [[ ! "${build_id}" =~ ^b?[0-9]+$ ]]; then
echo "ERROR: Build ID '${build_id}' is not a number."
usage
return 1
fi
build_id="${build_id#b}" # Remove leading 'b' if present.
if [[ -z "${parent_dir}" ]]; then
parent_dir="${DEFAULT_PARENT_DIR}"
fi
if [[ -z "${out_dir}" ]]; then
out_dir="${parent_dir}/${build_id}"
fi
if (( is_release )); then
local archive_bucket='fuchsia-release-archive'
else
local archive_bucket='fuchsia-archive'
fi
echo "Fetching build ${build_id} to ${out_dir} ..."
mkdir -p "${out_dir}"
local failed=0
(
set -x # Prints the gsutil command
# -m: Download files in parallel
# -c: Continue downloading later files even if an earlier one fails
# -L: Log file to use for resuming; also avoids re-downloading files
gsutil -m cp \
-c \
-L "${out_dir}/.gsutil-cp.log" \
-r \
"gs://${archive_bucket}/builds/${build_id}/*" "${out_dir}"
) || failed=1
if (( failed )); then
if (( ! is_release )); then
echo "NOTE: If you are trying to download a release build, remember"
echo " to specify the '-r' flag."
fi
return 1
fi
echo "Downloaded artifacts to ${out_dir}"
echo "DONE"
}
main "$@"