mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
We can use the gerrit api to detect previous merge commits the bot has made, then use those as the base for the next merge. This will create smaller merges and is easier to manage as we do not have to abandon so many changes. One complication is detecting possible cherry picks the oncall may have added to the previous merge commit. Only open merge commits are taken into account. BUG=b:213932296 TEST=./ci/kokoro/simulate build-merge-into-chromeos.sh Change-Id: I795109be4c45bec49068c3e292a3947505755442 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3381832 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: Dennis Kempin <denniskempin@google.com>
171 lines
5.5 KiB
Bash
Executable file
171 lines
5.5 KiB
Bash
Executable file
#!/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
|
|
cd "${KOKORO_ARTIFACTS_DIR}/git/crosvm"
|
|
|
|
readonly GERRIT_URL=https://chromium-review.googlesource.com
|
|
readonly ORIGIN=${GERRIT_URL}/chromiumos/platform/crosvm
|
|
readonly RETRIES=3
|
|
|
|
gerrit_api() {
|
|
# Call gerrit API. Strips XSSI protection line from output.
|
|
# See: https://gerrit-review.googlesource.com/Documentation/dev-rest-api.html
|
|
local url="${GERRIT_URL}/${1}"
|
|
curl --silent "$url" | tail -n +2
|
|
}
|
|
|
|
query_change() {
|
|
# Query gerrit for a specific change.
|
|
# See: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-change
|
|
gerrit_api "changes/$1/?o=CURRENT_REVISION"
|
|
}
|
|
|
|
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+' "$@")
|
|
gerrit_api "changes/?q=${query}"
|
|
}
|
|
|
|
query_related_changes() {
|
|
# Query related changes from gerrit.
|
|
# See: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-related-changes
|
|
gerrit_api "changes/$1/revisions/current/related"
|
|
}
|
|
|
|
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'
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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() {
|
|
# 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
|
|
|
|
# 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
|
|
|
|
# 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() {
|
|
git push origin HEAD:refs/for/chromeos%r=crosvm-uprev@google.com
|
|
}
|
|
|
|
upload_with_retries() {
|
|
# 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"
|
|
if upload; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
main() {
|
|
gerrit_prerequisites
|
|
|
|
# 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"
|
|
|
|
# Clean possible stray files from previous builds.
|
|
git clean -f -d -x
|
|
git checkout -f
|
|
|
|
# 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
|
|
|
|
local merge_list=$(git log --oneline --decorate=no --no-color \
|
|
"${parent_commit}..origin/main")
|
|
if [ -z "$merge_list" ]; then
|
|
echo "Already up to date, nothing to merge."
|
|
return
|
|
else
|
|
echo "Merge list:"
|
|
echo "${merge_list}"
|
|
echo ""
|
|
fi
|
|
|
|
echo "Checking out parent: ${parent_commit}"
|
|
git checkout -b chromeos "${parent_commit}"
|
|
git branch --set-upstream-to origin/chromeos chromeos
|
|
|
|
"${KOKORO_ARTIFACTS_DIR}/create_merge" "origin/main"
|
|
|
|
upload_with_retries
|
|
}
|
|
main
|