1#!/bin/bash
2# Copyright 2020 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6# Due to crbug.com/1081332, we need to update AFDO metadata
7# manually. This script performs a few checks and generates a
8# new kernel_afdo.json file, which can then be committed.
9#
10# USAGE:
11# toolchain-utils$ ./afdo_tools/update_kernel_afdo
12#
13# The script modifies the JSON file and shows the git diff.
14#
15# If the changes look good, git commit them. Example commit
16# message (from crrev.com/c/2197462):
17#
18#   afdo_metadata: Publish the new kernel profiles
19#
20#   Update chromeos-kernel-3_18 to R84-13080.0-1589189810
21#   Update chromeos-kernel-4_4 to R84-13080.0-1589189726
22#   Update chromeos-kernel-4_14 to R84-13080.0-1589190025
23#   Update chromeos-kernel-4_19 to R84-13080.0-1589189550
24#
25#   BUG=None
26#   TEST=Verified in kernel-release-afdo-verify-orchestrator.
27#
28
29set -eu
30set -o pipefail
31
32CROS_REPO=https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay
33GS_BASE=gs://chromeos-prebuilt/afdo-job/vetted/kernel
34KVERS="3.18 4.4 4.14 4.19"
35errs=""
36successes=0
37
38script_dir=$(dirname "$0")
39tc_utils_dir="$script_dir/.."
40metadata_dir="$tc_utils_dir/afdo_metadata"
41outfile="$metadata_dir/kernel_afdo.json"
42
43# The most recent Monday, in Unix timestamp format.
44if [ $(date +%a) = "Mon" ]
45then
46  expected_time=$(date +%s -d 00:00:00)
47else
48  expected_time=$(date +%s -d "last Monday")
49fi
50
51# Get the current canary branch number (using beta + 1)
52beta=$(git ls-remote -h $CROS_REPO | \
53       sed -n -e "s/^.*release-R\([0-9][0-9]*\).*$/\1/p" | \
54       sort -g | tail -1)
55canary="$(($beta + 1))"
56
57json="{"
58sep=""
59for kver in $KVERS
60do
61  # Sort the gs output by timestamp (default ordering is by name, so
62  # R86-13310.3-1594633089.gcov.xz goes after R86-13310.18-1595237847.gcov.xz)
63  latest=$(gsutil.py ls -l "$GS_BASE/$kver/" | sort -k2 | \
64           grep "R${canary}" | tail -1 || true)
65  if [ -z "$latest" ]
66  then
67    # if no profiles exist for R${canary}, try the previous branch
68    latest=$(gsutil.py ls -l "$GS_BASE/$kver/" | sort -k2 | \
69             grep "R${beta}" | tail -1)
70  fi
71
72  # Verify that the file has the expected date.
73  file_time=$(echo "$latest" | awk '{print $2}')
74  file_time_unix=$(date +%s -d "$file_time")
75  if [ $file_time_unix -lt $expected_time ]
76  then
77    expected=$(env TZ=UTC date +%Y-%m-%dT%H:%M:%SZ -d @$expected_time)
78    echo "Wrong date for $kver: $file_time is before $expected" >&2
79    errs="$errs $kver"
80    continue
81  fi
82
83  # Generate JSON.
84  json_kver=$(echo "$kver" | tr . _)
85  # b/147370213 (migrating profiles from gcov format) may result in the
86  # pattern below no longer doing the right thing.
87  name=$(echo "$latest" | sed 's%.*/\(.*\)\.gcov.*%\1%')
88  json=$(cat <<EOT
89$json$sep
90    "chromeos-kernel-$json_kver": {
91        "name": "$name"
92    }
93EOT
94)
95  sep=","
96  successes=$((successes + 1))
97done
98
99# If we did not succeed for any kvers, exit now.
100if [ $successes -eq 0 ]
101then
102  echo "error: AFDO profiles out of date for all kernel versions" >&2
103  exit 2
104fi
105
106# Write new JSON file.
107printf "%s\n}\n" "$json" > "$outfile"
108
109# Show the changes.
110(cd "$tc_utils_dir" && git diff)
111
112# If no changes were made, say so.
113outdir=$(dirname "$outfile")
114shortstat=$(cd "$outdir" && git status --short $(basename "$outfile"))
115[ -n "$shortstat" ] || echo $(basename "$outfile")" is up to date."
116
117# If we had any errors, warn about them.
118[ -z "$errs" ] || echo "warning: failed to update$errs" >&2
119