2021-12-06 19:49:32 +00:00
|
|
|
#!/bin/bash
|
|
|
|
# Copyright 2021 The Chromium OS Authors. All rights reserved.
|
|
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
|
|
# found in the LICENSE file.
|
|
|
|
set -e
|
|
|
|
|
2022-01-11 22:25:27 +00:00
|
|
|
readonly GERRIT_URL=https://chromium-review.googlesource.com
|
|
|
|
readonly ORIGIN=${GERRIT_URL}/chromiumos/platform/crosvm
|
|
|
|
readonly RETRIES=3
|
2022-01-19 19:16:48 +00:00
|
|
|
readonly MIN_COMMIT_COUNT=${MIN_COMMIT_COUNT:-5}
|
2021-12-06 19:49:32 +00:00
|
|
|
|
2022-01-12 01:29:31 +00:00
|
|
|
gerrit_api_get() {
|
|
|
|
# GET request to the gerrit API. Strips XSSI protection line from output.
|
2022-01-11 22:25:27 +00:00
|
|
|
# See: https://gerrit-review.googlesource.com/Documentation/dev-rest-api.html
|
|
|
|
local url="${GERRIT_URL}/${1}"
|
|
|
|
curl --silent "$url" | tail -n +2
|
|
|
|
}
|
|
|
|
|
2022-01-12 01:29:31 +00:00
|
|
|
gerrit_api_post() {
|
|
|
|
# POST to gerrit API using http cookies from git.
|
|
|
|
local endpoint=$1
|
|
|
|
local body=$2
|
|
|
|
local cookie_file=$(git config http.cookiefile)
|
|
|
|
if [[ -z "${cookie_file}" ]]; then
|
|
|
|
echo 1>&2 "Cannot find git http cookie file."
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
local url="${GERRIT_URL}/${endpoint}"
|
|
|
|
curl --silent \
|
|
|
|
--cookie "${cookie_file}" \
|
|
|
|
-X POST \
|
|
|
|
-d "${body}" \
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
"$url" |
|
|
|
|
tail -n +2
|
|
|
|
}
|
|
|
|
|
2022-01-11 22:25:27 +00:00
|
|
|
query_change() {
|
|
|
|
# Query gerrit for a specific change.
|
|
|
|
# See: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-change
|
2022-01-12 01:29:31 +00:00
|
|
|
gerrit_api_get "changes/$1/?o=CURRENT_REVISION"
|
2022-01-11 22:25:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
query_changes() {
|
|
|
|
# Query gerrit for a list of changes.
|
|
|
|
# See: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-changes
|
|
|
|
local query=$(printf '%s+' "$@")
|
2022-01-12 01:29:31 +00:00
|
|
|
gerrit_api_get "changes/?q=${query}"
|
2022-01-11 22:25:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
query_related_changes() {
|
|
|
|
# Query related changes from gerrit.
|
|
|
|
# See: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-related-changes
|
2022-01-12 01:29:31 +00:00
|
|
|
gerrit_api_get "changes/$1/revisions/current/related"
|
2022-01-11 22:25:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get_previous_merge_id() {
|
|
|
|
# Query all open merge commits previously made by crosvm-bot. May be null if
|
|
|
|
# none are open.
|
|
|
|
query=(
|
|
|
|
project:chromiumos/platform/crosvm
|
|
|
|
branch:chromeos
|
|
|
|
status:open
|
|
|
|
owner:crosvm-bot@crosvm-packages.iam.gserviceaccount.com
|
|
|
|
)
|
|
|
|
# Pick the one that was created last.
|
|
|
|
query_changes "${query[@]}" |
|
|
|
|
jq --raw-output 'sort_by(.created)[-1].change_id'
|
|
|
|
}
|
|
|
|
|
2022-01-12 01:29:31 +00:00
|
|
|
get_change_id_from_commit() {
|
|
|
|
query_changes "project:chromiumos/platform/crosvm" "$1" |
|
|
|
|
jq --raw-output ".[0].change_id"
|
|
|
|
}
|
|
|
|
|
2022-01-11 22:25:27 +00:00
|
|
|
get_last_change_in_chain() {
|
|
|
|
# Use the related changes API to find the last change in the chain of
|
|
|
|
# commits.
|
|
|
|
local change_id=$1
|
|
|
|
|
|
|
|
# The list of commits is sorted by the git commit order, with the latest
|
|
|
|
# change first and includes the current change.
|
|
|
|
local last_change
|
|
|
|
last_change=$(query_related_changes "$change_id" | jq --raw-output \
|
|
|
|
"[.changes[] | select(.status == \"NEW\")][0].change_id")
|
|
|
|
|
|
|
|
# If there are no related changes the list will be empty.
|
|
|
|
if [ "$last_change" == "null" ]; then
|
|
|
|
echo "${change_id}"
|
|
|
|
else
|
|
|
|
echo "${last_change}"
|
|
|
|
fi
|
|
|
|
}
|
2021-12-06 19:49:32 +00:00
|
|
|
|
2022-01-12 01:29:31 +00:00
|
|
|
get_all_related_changes() {
|
|
|
|
# Queries the change ids of all related changes that are still open.
|
|
|
|
local change_id=$1
|
|
|
|
local all_changes
|
|
|
|
all_changes=$(query_related_changes "$change_id" | jq --raw-output \
|
|
|
|
".changes[] | select(.status == \"NEW\").change_id")
|
|
|
|
|
|
|
|
# If there are no related changes the list will be empty.
|
|
|
|
if [ -z "${all_changes}" ]; then
|
|
|
|
echo "${change_id}"
|
|
|
|
else
|
|
|
|
echo "${all_changes}"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2022-01-11 22:25:27 +00:00
|
|
|
fetch_change() {
|
|
|
|
# Fetch the provided change and print the commit sha.
|
|
|
|
local change_id=$1
|
|
|
|
|
|
|
|
# Find the git ref we need to fetch.
|
|
|
|
local change_ref
|
|
|
|
change_ref=$(query_change "$change_id" |
|
|
|
|
jq --raw-output -e ".revisions[.current_revision].ref")
|
|
|
|
git fetch -q origin "${change_ref}"
|
|
|
|
}
|
|
|
|
|
|
|
|
gerrit_prerequisites() {
|
2021-12-06 19:49:32 +00:00
|
|
|
# Authenticate to GoB if we don't already have a cookie.
|
|
|
|
# This should only happen when running in Kokoro, not locally.
|
|
|
|
# See: go/gob-gce
|
|
|
|
if [[ -z $(git config http.cookiefile) ]]; then
|
|
|
|
git clone https://gerrit.googlesource.com/gcompute-tools \
|
|
|
|
"${KOKORO_ARTIFACTS_DIR}/gcompute-tools"
|
|
|
|
"${KOKORO_ARTIFACTS_DIR}/gcompute-tools/git-cookie-authdaemon" --no-fork
|
|
|
|
|
2022-01-11 22:25:27 +00:00
|
|
|
# Setup correct user info for the service account.
|
|
|
|
git config user.name "Crosvm Bot"
|
|
|
|
git config user.email crosvm-bot@crosvm-packages.iam.gserviceaccount.com
|
|
|
|
fi
|
2021-12-07 22:56:22 +00:00
|
|
|
|
2021-12-06 19:49:32 +00:00
|
|
|
# We cannot use the original origin that kokoro used, as we no longer have
|
|
|
|
# access the GoB host via rpc://.
|
|
|
|
git remote remove origin
|
|
|
|
git remote add origin ${ORIGIN}
|
|
|
|
git fetch -q origin
|
|
|
|
|
|
|
|
# Set up gerrit Change-Id hook.
|
|
|
|
mkdir -p .git/hooks
|
|
|
|
curl -Lo .git/hooks/commit-msg \
|
|
|
|
https://gerrit-review.googlesource.com/tools/hooks/commit-msg
|
|
|
|
chmod +x .git/hooks/commit-msg
|
|
|
|
}
|
|
|
|
|
|
|
|
upload() {
|
2022-01-12 01:29:31 +00:00
|
|
|
git push origin \
|
|
|
|
HEAD:refs/for/chromeos%r=crosvm-uprev@google.com
|
2021-12-07 20:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
upload_with_retries() {
|
2021-12-06 19:49:32 +00:00
|
|
|
# Try uploading to gerrit. Retry due to errors on first upload.
|
|
|
|
# See: b/209031134
|
|
|
|
for i in $(seq 1 $RETRIES); do
|
|
|
|
echo "Push attempt $i"
|
2021-12-07 20:30:06 +00:00
|
|
|
if upload; then
|
2021-12-06 19:49:32 +00:00
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2022-01-12 01:29:31 +00:00
|
|
|
dry_run_change() {
|
|
|
|
# Sets the Commit-Queue+1 bit on the provided change id and all it's
|
|
|
|
# ancestors.
|
|
|
|
local change_id=$1
|
|
|
|
|
|
|
|
local all_changes=$(get_all_related_changes "$change_id")
|
|
|
|
for change in ${all_changes}; do
|
|
|
|
body='{"message": "Dry-Running the latest merge.","labels": {"Commit-Queue": +1}}'
|
|
|
|
echo "Setting CQ+1 on ${GERRIT_URL}/q/${change}"
|
|
|
|
gerrit_api_post "a/changes/${change}/revisions/current/review" "$body" >/dev/null
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2021-12-06 19:49:32 +00:00
|
|
|
main() {
|
2022-01-12 01:29:31 +00:00
|
|
|
cd "${KOKORO_ARTIFACTS_DIR}/git/crosvm"
|
|
|
|
|
2021-12-06 19:49:32 +00:00
|
|
|
gerrit_prerequisites
|
|
|
|
|
2021-12-07 20:30:06 +00:00
|
|
|
# Make a copy of the merge script, so we are using the HEAD version to
|
|
|
|
# create the merge.
|
|
|
|
cp ./tools/chromeos/create_merge "${KOKORO_ARTIFACTS_DIR}/create_merge"
|
|
|
|
|
2021-12-07 20:55:45 +00:00
|
|
|
# Clean possible stray files from previous builds.
|
|
|
|
git clean -f -d -x
|
|
|
|
git checkout -f
|
|
|
|
|
2022-01-11 22:25:27 +00:00
|
|
|
# Parent commit to use for this merge.
|
|
|
|
local parent_commit="origin/chromeos"
|
|
|
|
|
|
|
|
# Query gerrit to find the latest merge commit and fetch it to be used as
|
|
|
|
# a parent.
|
|
|
|
local previous_merge="$(get_previous_merge_id)"
|
|
|
|
if [ "$previous_merge" != "null" ]; then
|
|
|
|
# The oncall may have uploaded a custom merge or cherry-pick on top
|
|
|
|
# of the detected merge. Find the last changed in that chain.
|
|
|
|
local last_change_in_chain=$(get_last_change_in_chain "${previous_merge}")
|
|
|
|
echo "Found previous merge: ${GERRIT_URL}/q/${previous_merge}"
|
|
|
|
echo "Last change in that chain: ${GERRIT_URL}/q/${last_change_in_chain}"
|
|
|
|
fetch_change "${last_change_in_chain}"
|
|
|
|
parent_commit="FETCH_HEAD"
|
|
|
|
fi
|
|
|
|
|
2022-01-19 19:16:48 +00:00
|
|
|
local merge_count=$(git log --oneline --decorate=no --no-color \
|
|
|
|
"${parent_commit}..origin/main" | wc -l)
|
|
|
|
if [ "${merge_count}" -lt "$MIN_COMMIT_COUNT" ]; then
|
|
|
|
echo "Not enough commits to merge. Skipping."
|
2022-01-11 22:25:27 +00:00
|
|
|
return
|
|
|
|
fi
|
2021-12-14 23:13:19 +00:00
|
|
|
|
2022-01-11 22:25:27 +00:00
|
|
|
echo "Checking out parent: ${parent_commit}"
|
|
|
|
git checkout -b chromeos "${parent_commit}"
|
2021-12-06 19:49:32 +00:00
|
|
|
git branch --set-upstream-to origin/chromeos chromeos
|
2022-01-11 22:25:27 +00:00
|
|
|
|
|
|
|
"${KOKORO_ARTIFACTS_DIR}/create_merge" "origin/main"
|
2021-12-06 19:49:32 +00:00
|
|
|
|
2021-12-07 20:30:06 +00:00
|
|
|
upload_with_retries
|
2022-01-12 01:29:31 +00:00
|
|
|
|
|
|
|
# Look up the change id for the newly created merge and CQ+1
|
|
|
|
local new_commit=$(git rev-parse HEAD)
|
|
|
|
local new_change_id
|
|
|
|
new_change_id=$(get_change_id_from_commit "${new_commit}")
|
|
|
|
dry_run_change "${new_change_id}"
|
2021-12-06 19:49:32 +00:00
|
|
|
}
|
|
|
|
main
|