blob: a04df103da7bb3c07044bc7543dffef00841d9c1 [file] [log] [blame]
#!/bin/bash
set -e
declare -A REPOS=(
["getting-started"]="https://fuchsia.googlesource.com/sdk-samples/getting-started"
["drivers"]="https://fuchsia.googlesource.com/sdk-samples/drivers"
["fortune-teller"]="https://fuchsia.googlesource.com/sdk-samples/fortune-teller"
)
usage() {
echo "Verify and update dependencies on Fuchsia SDK repositories."
echo
echo "Usage: $0 [--dry-run|-n] [--no-tests|-nt] [--debug] [REPO [REPO ...]]"
echo " --dry-run | -n Do not push roller CLs to Gerrit"
echo " --debug Turns Bash tracing on (set -x)"
echo " --no-tests | -nt Skip locally running tests on CLs before sending to Gerrit"
echo " REPO full git URL of a repo or shortname for known repos."
echo
echo "example:"
echo
echo " $0 -n -nt"
echo " Generates roller CLs for all known repos, but do not test and do not submit them"
echo
echo " $0 drivers"
echo " Generates roller CL for the driver repo if necessary."
echo
echo "If there is an open roller CL (hashtag:roller) for the given repository,"
echo "this tool reuses it and submits a new patchset. Otherwise it will"
echo "create a new CL. The CL still needs to be reviewed and merged on Gerrit."
}
main() {
if ! command -v 'cipd' >/dev/null; then
echo >&2 "Cannot find the cipd tool, please add it to PATH"
exit 1
fi
if ! command -v 'bazel' >/dev/null; then
echo >&2 "Cannot find the bazel tool, please add it to PATH"
exit 1
fi
if ! command -v 'gob-curl' >/dev/null; then
echo >&2 "Cannot find the gob-curl tool, please add it to PATH"
exit 1
fi
dry_run=0 # false
run_tests=1 # true
debug=0
repos=()
while [[ $# -gt 0 ]]; do
if [[ $1 == -* ]]; then
case "$1" in
--dry-run|-n)
dry_run=1
;;
--no-tests|-nt)
run_tests=0
;;
--debug)
set -x
;;
-h|--help)
usage
exit 0
;;
*)
echo >&2 "Invalid syntax."
usage
exit 1
esac
shift
continue
fi
if [[ $1 =~ https:\/\/|git:\/\/ ]]; then
repos+=( "$1" )
else
if [[ -n "${REPOS[$1]}" ]]; then
repos+=( "${REPOS[$1]}" )
else
echo >&2 "Invalid repo: $1"
exit 1
fi
fi
shift
done
if [[ ${#repos[@]} -eq 0 ]]; then
repos+=( "${REPOS[@]}" )
fi
for repo in "${repos[@]}"; do
update_repo "$repo"
done
}
get_latest() {
os="$1"
arch="$2"
sdk_t="$3"
cipd describe fuchsia/sdk/${sdk_t}/${os}-${arch} -version latest |
sed -n 's/ *version:\(.*\)/\1/p'
}
get_latest_sdk_integration_version() {
branch="$1"
git ls-remote \
https://fuchsia.googlesource.com/sdk-integration "$branch" \
| cut -f 1
}
get_smaller_version() {
local smaller=$1
shift
local all_same=1
while [[ $# -gt 0 ]]; do
if [[ $smaller > $1 ]]; then
smaller=$1
all_same=0
fi
shift
done
if [[ $all_same -eq 0 ]]; then
echo " Warning: latest versions differ for different os/arch, using the older: $smaller" >&2
fi
echo $smaller
}
update_sdk_integration() {
repo="$1"
w="$2"
current="$(sed -n \
-e '/^ *name *= *"rules_fuchsia" *, *$/,/^ *) *$/!b' \
-e 's/^ *commit *= *"\(.*\)".*/\1/p' "$w")"
if [[ -z "$current" ]]; then
# repo does not use versioned sdk-integration references in WORKSPACE
return 1
fi
branch="$(sed -n \
-e '/^ *name *= *"rules_fuchsia" *, *$/,/^ *) *$/!b' \
-e 's/.* branch *= *"\(.*\)".*/\1/p' "$w")"
if [[ -z "$branch" ]]; then
branch="main"
fi
new_version="$(get_latest_sdk_integration_version "$branch")"
if [[ "$new_version" != "$current" ]]; then
echo " SDK integration version (${current}) is old. Latest is ${new_version}."
update_sdk_integration_version $w $new_version
return 0
fi
return 1
}
update_fuchsia_sdk() {
repo="$1"
w="$2"
current="$(sed -n \
-e '/^ *fuchsia_sdk_repository *($/,/^ *) *$/!b' \
-e 's/^ *cipd_tag *= *"version:\(.*\)".*/\1/p' "$w")"
has_experimental=0
if [[ -n "$(get_current_sha256 $w linux_experimental)" ]]; then
has_experimental=1
fi
versions=( "$(get_latest linux amd64 core)" "$(get_latest mac amd64 core)" )
if [[ $has_experimental -eq 1 ]]; then
versions+=( "$(get_latest linux amd64 experimental)" "$(get_latest mac amd64 experimental)" )
fi
new_version="$(get_smaller_version "${versions[@]}")"
if [[ "$new_version" != "$current" ]]; then
echo " core SDK version (${current}) is old. Latest is ${new_version}."
update_current_version $w $new_version
update_current_sha256 $w linux $(get_sha256 linux amd64 core $new_version)
update_current_sha256 $w mac $(get_sha256 mac amd64 core $new_version)
# if repo uses experimental
if [[ $has_experimental -eq 1 ]]; then
update_current_sha256 $w linux_experimental $(get_sha256 linux amd64 experimental $new_version)
update_current_sha256 $w mac_experimental $(get_sha256 mac amd64 experimental $new_version)
fi
return 0
fi
return 1
}
update_submodules() {
if [[ -n "$(git submodule update --remote)" ]]; then
return 1
fi
return 0
}
get_current_sha256() {
w="$1"
key="$2"
sed -n -e '/^ *fuchsia_sdk_repository *( *$/,/^ *) *$/!b' \
-e '/^ *sha256 *= *{ *$/,/^ *} *, *$/!b' \
-e 's/^ *"'${key}'" *: *"\(.*\)".*/\1/p' \
"$w"
}
update_sdk_integration_version() {
w="$1"
newversion="$2"
sed -i'' -e '/^ *name *= *"rules_fuchsia" *, *$/,/^ *) *$/!b' \
-e 's/^\( *commit *= *"\)\(.*\)\(".*\)/\1'${newversion}'\3/' \
"$w"
}
update_current_version() {
w="$1"
newversion="$2"
sed -i'' -e '/^ *fuchsia_sdk_repository *( *$/,/^ *) *$/!b' \
-e 's/^\( *cipd_tag *= *"version:\)\(.*\)\(".*\)/\1'${newversion}'\3/' \
"$w"
}
update_current_sha256() {
w="$1"
key="$2"
newsha="$3"
sed -i'' -e '/^ *fuchsia_sdk_repository *( *$/,/^ *) *$/!b' \
-e '/^ *sha256 *= *{ *$/,/^ *} *, *$/!b' \
-e 's/^\( *"'${key}'" *: *"\)\(.*\)\(".*\)/\1'${newsha}'\3/' \
"$w"
}
get_sha256() {
os="$1"
arch="$2"
sdk_t="$3"
version="$4"
# this is a hack, but I couldn't figure out another way to get the SHA256 from
# cipd
local url="https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/${sdk_t}/${os}-${arch}/+/version:${version}"
curl -s "$url" | sed -n 's|.*https://storage.googleapis.com/chrome-infra-packages/store/SHA256/\([0-9a-f]*\).*|\1|p'
}
get_existing_roller_cl() {
repo=$1
if [[ "$repo" =~ https://fuchsia.googlesource.com/ ]]; then
project="${repo##https://fuchsia.googlesource.com/}"
gob-curl -q \
"https://fuchsia-review.git.corp.google.com/a/changes/?q=project:${project}+status:open+hashtag:roller&n=1" \
2>/dev/null | \
sed -n 's/.*"change_id":"\([^"]*\)".*/\1/p'
fi
}
update_repo() {
local repo="$1"
local d="$(mktemp -d)"
cd "$d"
echo "Checking $repo..."
git clone -q --recursive "$repo"
trap "echo \"Temporary directory preserved in $d\"" EXIT
cd "$(basename $repo)"
local updated=0
if [[ ! -f "WORKSPACE.bazel" ]]; then
echo >&2 "Error, repo does not contain WORKSPACE.bazel: $repo"
return 1
fi
if grep -q "fuchsia_sdk_repository" "WORKSPACE.bazel"; then
update_fuchsia_sdk "$repo" "WORKSPACE.bazel" && updated=1
update_sdk_integration "$repo" "WORKSPACE.bazel" && updated=1
fi
update_submodules && updated=1
if [[ $updated -eq 1 ]]; then
if [[ $run_tests -eq 1 ]]; then
echo " Testing before updating..."
# test the change
if [[ -x scripts/run_tests.sh ]]; then
scripts/run_tests.sh
elif [[ -x scripts/smoke_test.sh ]]; then
scripts/smoke_test.sh
elif [[ -x scripts/build.sh ]]; then
scripts/build.sh
elif [[ -f src/BUILD.bazel ]] && grep "samples_repository" src/BUILD.bazel; then
bazel build --config=fuchsia_x64 src:samples_repository
else
echo "Don't know how to test repo $repo. Ignoring it."
fi
else
echo " Skipping tests because flag -nt/--no-tests is used"
fi
existing_cl="$(get_existing_roller_cl $repo)"
if [[ -n "$existing_cl" ]]; then
echo " Warning: reusing existing Change-ID $existing_cl" >&2
existing_cl="Change-Id: $existing_cl"
fi
# install commit hook that creates the change-id:
f=`git rev-parse --git-dir`/hooks/commit-msg
mkdir -p $(dirname $f)
curl -s -Lo $f https://gerrit-review.googlesource.com/tools/hooks/commit-msg
chmod +x $f
git commit -m "[version roller] Update dependencies" \
-m "SDK version updated from $current to $new_version" \
-m "$existing_cl" \
$w
if [[ $dry_run -eq 1 ]]; then
echo
echo " DRY-RUN: this is what we would have pushed:" >&2
echo
git show
else
git push origin HEAD:refs/for/main -o t=roller
cd ..
rm -rf $d
fi
trap EXIT
fi
}
main "$@"