250 lines
7.4 KiB
Bash
Executable File
250 lines
7.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# Copyright 2020 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.
|
|
|
|
# Due to crbug.com/1081332, we need to update AFDO metadata
|
|
# manually. This script performs a few checks and generates a
|
|
# new kernel_afdo.json file, which can then be submitted.
|
|
#
|
|
|
|
USAGE="
|
|
Usage: $(basename $0) [main|beta|stable|all] [--help]
|
|
|
|
Description:
|
|
The script takes one optional argument which is the channel where we want
|
|
to update the kernel afdo and creates a commit (or commits with \"all\"
|
|
channels) in the corresponding branch.
|
|
No arguments defaults to \"all\".
|
|
Follow the prompt to submit the changes.
|
|
NO CLEAN-UP NEEDED. The script ignores any local changes and keeps
|
|
the current branch unchanged.
|
|
"
|
|
|
|
set -eu
|
|
set -o pipefail
|
|
|
|
GS_BASE=gs://chromeos-prebuilt/afdo-job/vetted/kernel
|
|
KVERS="4.4 4.14 4.19 5.4"
|
|
failed_channels=""
|
|
# Add skipped chrome branches in ascending order here.
|
|
SKIPPED_BRANCHES="95"
|
|
|
|
script_dir=$(dirname "$0")
|
|
tc_utils_dir="${script_dir}/.."
|
|
metadata_dir="${tc_utils_dir}/afdo_metadata"
|
|
outfile="$(realpath --relative-to="${tc_utils_dir}" \
|
|
"${metadata_dir}"/kernel_afdo.json)"
|
|
# Convert toolchain_utils into the absolute path.
|
|
abs_tc_utils_dir="$(realpath ${tc_utils_dir})"
|
|
|
|
# Check profiles uploaded within the last week.
|
|
expected_time=$(date +%s -d "week ago")
|
|
|
|
declare -A branch branch_number commit
|
|
remote_repo=$(git -C "${tc_utils_dir}" remote)
|
|
canary_ref="refs/heads/main"
|
|
# Read the last two release-Rxx from remote branches
|
|
# and assign them to stable_ref and beta_ref.
|
|
# sort -V is the version sort which puts R100 after R99.
|
|
last_branches=$(git -C "${tc_utils_dir}" ls-remote -h "${remote_repo}" \
|
|
release-R\* | cut -f2 | sort -V | tail -n 2)
|
|
# We need `echo` to convert newlines into spaces for read.
|
|
read stable_ref beta_ref <<< $(echo ${last_branches})
|
|
# Branch names which start from release-R.
|
|
branch["beta"]=${beta_ref##*/}
|
|
branch["stable"]=${stable_ref##*/}
|
|
branch["canary"]=${canary_ref##*/}
|
|
|
|
# Get current branch numbers (number which goes after R).
|
|
branch_number["stable"]=$(echo "${branch["stable"]}" | \
|
|
sed -n -e "s/^release-R\([0-9][0-9]*\).*$/\1/p")
|
|
branch_number["beta"]=$(echo "${branch["beta"]}" | \
|
|
sed -n -e "s/^release-R\([0-9][0-9]*\).*$/\1/p")
|
|
branch_number["canary"]="$((branch_number[beta] + 1))"
|
|
for skipped_branch in $SKIPPED_BRANCHES ; do
|
|
if [[ ${branch_number["canary"]} == $skipped_branch ]] ; then
|
|
((branch_number[canary]++))
|
|
fi
|
|
done
|
|
|
|
# Without arguments the script updates all branches.
|
|
channels=${1:-"all"}
|
|
case "${channels}" in
|
|
stable | canary | beta )
|
|
;;
|
|
main )
|
|
channels="canary"
|
|
;;
|
|
all )
|
|
channels="canary beta stable"
|
|
;;
|
|
--help | help | -h )
|
|
echo "$USAGE"
|
|
exit 0
|
|
;;
|
|
* )
|
|
echo "Channel \"${channels}\" is not supported.
|
|
Must be main (or canary), beta, stable or all." >&2
|
|
echo "$USAGE"
|
|
exit 1
|
|
esac
|
|
|
|
# Fetch latest branches.
|
|
git -C "${tc_utils_dir}" fetch "${remote_repo}"
|
|
|
|
worktree_dir=$(mktemp -d)
|
|
echo "-> Working in ${worktree_dir}"
|
|
# Create a worktree and make changes there.
|
|
# This way we don't need to clean-up and sync toolchain_utils before the
|
|
# change. Neither we should care about clean-up after the submit.
|
|
git -C "${tc_utils_dir}" worktree add --detach "${worktree_dir}"
|
|
trap "git -C ${abs_tc_utils_dir} worktree remove ${worktree_dir}" EXIT
|
|
cd "${worktree_dir}"
|
|
|
|
for channel in ${channels}
|
|
do
|
|
errs=""
|
|
successes=0
|
|
curr_branch_number=${branch_number[${channel}]}
|
|
curr_branch=${branch[${channel}]}
|
|
echo
|
|
echo "Checking \"${channel}\" channel..."
|
|
echo "branch_number=${curr_branch_number} branch=${curr_branch}"
|
|
json="{"
|
|
sep=""
|
|
for kver in $KVERS
|
|
do
|
|
# Sort the gs output by timestamp (default ordering is by name, so
|
|
# R86-13310.3-1594633089.gcov.xz goes after R86-13310.18-1595237847.gcov.xz)
|
|
latest=$(gsutil.py ls -l "$GS_BASE/$kver/" | sort -k2 | \
|
|
grep "R${curr_branch_number}" | tail -1 || true)
|
|
if [[ -z "$latest" && "${channel}" != "stable" ]]
|
|
then
|
|
# if no profiles exist for the current branch, try the previous branch
|
|
latest=$(gsutil.py ls -l "$GS_BASE/$kver/" | sort -k2 | \
|
|
grep "R$((curr_branch_number - 1))" | tail -1)
|
|
fi
|
|
|
|
# Verify that the file has the expected date.
|
|
file_time=$(echo "$latest" | awk '{print $2}')
|
|
file_time_unix=$(date +%s -d "$file_time")
|
|
if [ $file_time_unix -lt $expected_time ]
|
|
then
|
|
expected=$(env TZ=UTC date +%Y-%m-%dT%H:%M:%SZ -d @$expected_time)
|
|
echo "Wrong date for $kver: $file_time is before $expected" >&2
|
|
errs="$errs $kver"
|
|
continue
|
|
fi
|
|
|
|
# Generate JSON.
|
|
json_kver=$(echo "$kver" | tr . _)
|
|
# b/147370213 (migrating profiles from gcov format) may result in the
|
|
# pattern below no longer doing the right thing.
|
|
name=$(echo "$latest" | sed 's%.*/\(.*\)\.gcov.*%\1%')
|
|
json=$(cat <<EOT
|
|
$json$sep
|
|
"chromeos-kernel-$json_kver": {
|
|
"name": "$name"
|
|
}
|
|
EOT
|
|
)
|
|
sep=","
|
|
successes=$((successes + 1))
|
|
done
|
|
|
|
# If we did not succeed for any kvers, exit now.
|
|
if [[ $successes -eq 0 ]]
|
|
then
|
|
echo "error: AFDO profiles out of date for all kernel versions" >&2
|
|
failed_channels="${failed_channels} ${channel}"
|
|
continue
|
|
fi
|
|
|
|
git reset --hard HEAD
|
|
echo git checkout "${remote_repo}/${curr_branch}"
|
|
git checkout "${remote_repo}/${curr_branch}"
|
|
|
|
# Write new JSON file.
|
|
# Don't use `echo` since `json` might have esc characters in it.
|
|
printf "%s\n}\n" "$json" > "$outfile"
|
|
|
|
# If no changes were made, say so.
|
|
outdir=$(dirname "$outfile")
|
|
shortstat=$(cd "$outdir" && git status --short $(basename "$outfile"))
|
|
[ -z "$shortstat" ] && echo $(basename "$outfile")" is up to date." \
|
|
&& continue
|
|
|
|
# If we had any errors, warn about them.
|
|
if [[ -n "$errs" ]]
|
|
then
|
|
echo "warning: failed to update $errs in ${channel}" >&2
|
|
failed_channels="${failed_channels} ${channel}"
|
|
continue
|
|
fi
|
|
|
|
git add afdo_metadata/kernel_afdo.json
|
|
case "${channel}" in
|
|
canary )
|
|
commit_contents="afdo_metadata: Publish the new kernel profiles
|
|
|
|
Update chromeos-kernel-4_4
|
|
Update chromeos-kernel-4_14
|
|
Update chromeos-kernel-4_19
|
|
Update chromeos-kernel-5_4
|
|
|
|
BUG=None
|
|
TEST=Verified in kernel-release-afdo-verify-orchestrator"
|
|
;;
|
|
beta | stable )
|
|
commit_contents="afdo_metadata: Publish the new kernel profiles\
|
|
in ${curr_branch}
|
|
|
|
Have PM pre-approval because this shouldn't break the release branch.
|
|
|
|
BUG=None
|
|
TEST=Verified in kernel-release-afdo-verify-orchestrator"
|
|
;;
|
|
* )
|
|
echo "internal error: unhandled channel \"${channel}\"" >&2
|
|
exit 2
|
|
esac
|
|
|
|
git commit -v -e -m "${commit_contents}"
|
|
|
|
commit[${channel}]=$(git -C "${worktree_dir}" rev-parse HEAD)
|
|
done
|
|
|
|
echo
|
|
# Array size check doesn't play well with the unbound variable option.
|
|
set +u
|
|
if [[ ${#commit[@]} -gt 0 ]]
|
|
then
|
|
set -u
|
|
echo "The change is applied in ${!commit[@]}."
|
|
echo "Run these commands to submit the change:"
|
|
echo
|
|
for channel in ${!commit[@]}
|
|
do
|
|
echo -e "\tgit -C ${tc_utils_dir} push ${remote_repo} \
|
|
${commit[${channel}]}:refs/for/${branch[${channel}]}"
|
|
done
|
|
|
|
# Report failed channels.
|
|
if [[ -n "${failed_channels}" ]]
|
|
then
|
|
echo
|
|
echo "error: failed to update kernel afdo in ${failed_channels}" >&2
|
|
exit 3
|
|
fi
|
|
else
|
|
# No commits. Check if it is due to failures.
|
|
if [[ -z "${failed_channels}" ]]
|
|
then
|
|
echo "No changes are applied. It looks like AFDO versions are up to date."
|
|
else
|
|
echo "error: update in ${failed_channels} failed" >&2
|
|
exit 3
|
|
fi
|
|
fi
|