blob: d1b2dbb2dd2a5d20fef94d06b638d9468e6cbb7c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
#!/bin/bash
set -euf -o pipefail
scripts=$(dirname $0)
# shellcheck source=jenkins-helpers.sh
. $scripts/jenkins-helpers.sh
convert_args_to_variables "$@"
shift "$SHIFT_CONVERTED_ARGS"
obligatory_variables \
artifacts BUILD_URL ci_project ci_config current_project \
first_bad last_good summary
declare \
artifacts BUILD_URL ci_project ci_config current_project \
first_bad last_good summary
dryrun="${dryrun-false}"
icommits="interesting-commits"
verbose="${verbose-true}"
if $verbose; then
set -x
fi
if $dryrun; then
dryrun="echo DRYRUN: "
else
dryrun=""
fi
prepare_interesting_commits ()
{
(
set -euf -o pipefail
# Clone interesting-commits.git repo, which contains a regression
# summaries for SHA1s. These are the "first_bad" commits.
clone_or_update_repo $icommits master \
https://git-us.linaro.org/toolchain/ci/interesting-commits.git \
auto master
git_init_linaro_local_remote $icommits baseline false
)
}
# Update interesting-commit's entry for a given commit
# $1: component
# $2: sha1 of first_bad commit
# $3: sha1 of last_good commit
#
# Interesting-commits store regression history in the following hierarchy:
# 1. At the top level we have COMPONENT directories.
# 2. At the 2nd level we have SHA1 directories.
# 2a. We also have "git describe" symlinks to SHA1 directories for convenience.
# 3. At the 3rd level we have CI_PROJECT directories.
# 4. At the 4th level we have CI_CONFIG directories, and ...
# 4a. ... status.txt, which contains status of changes from SHA1 across all
# CI_CONFIGs in CI_PROJECT.
# 5. At the 5th level we have per-build files last_good, summary.txt, etc.
update_interesting_entry ()
{
(
set -euf -o pipefail
local component="$1"
local first_bad="$2"
local last_good="$3"
local subdir
subdir=$(interesting_subdir "$component" "$first_bad")
local describe
describe=$(describe_sha1 "$component" "$first_bad" false)
if ! [ -d $icommits/$subdir ] && [ x"$describe" != x"" ]; then
local d
d=$(dirname "$describe")
mkdir -p $icommits/$component/$d
local symlink=""
while [ x"$d" != x"." ]; do
symlink="../$symlink"
d=$(dirname "$d")
done
symlink="${symlink}sha1/$first_bad"
ln -s $symlink $icommits/$component/$describe
git -C $icommits add $component/$describe
fi
# shellcheck disable=SC2154
subdir=$(interesting_subdir "$component" "$first_bad" \
"$ci_project" "$ci_config")
mkdir -p "$icommits/$subdir"
echo "$BUILD_URL" > "$icommits/$subdir/build_url"
echo "$last_good" > "$icommits/$subdir/last_good"
git -C "$icommits" add "$subdir/build_url" "$subdir/last_good"
cp $summary "$icommits/$subdir/summary.txt"
git -C "$icommits" add "$subdir/summary.txt"
local status="$subdir/../status.txt"
if [ x"$describe" = x"" ]; then
describe=$(describe_sha1 "$component" "$first_bad" true)
fi
cat > $icommits/$status <<EOF
Status of $describe commit for $ci_project:
$(git -C "$component" log -n1 "$first_bad")
EOF
local ci_config
while read ci_config; do
if ! [ -f "$icommits/$subdir/../$ci_config/summary.txt" ]; then
continue
fi
echo "* $ci_config"
(
cat $icommits/$subdir/../$ci_config/summary.txt
cat $icommits/$subdir/../$ci_config/build_url
) | sed "s/^/** /"
done < <(cd $icommits/$subdir/..; ls) >> $icommits/$status
git -C "$icommits" add "$status"
)
}
update_interesting_commits ()
{
(
set -euf -o pipefail
# Reset to master branch
git -C $icommits remote update -p
git -C $icommits reset -q --hard refs/remotes/baseline/master
local isubdir
isubdir=$(interesting_subdir "$current_project" "$first_bad" \
"$ci_project")
local reported_before=false
if [ -d "$icommits/$isubdir/$ci_config" ]; then
reported_before=true
fi
# We have successfully identified a bad commit with a good parent!
# Add $first_bad to interesting commits.
update_interesting_entry "$current_project" "$first_bad" "$last_good"
# Commit and push
git -C $icommits commit -m "Add entry $first_bad from ${BUILD_URL-$(pwd)}"
$dryrun git -C $icommits push baseline HEAD:refs/heads/master
if $reported_before; then
# This is a re-occurring problem (usually, in linux-next).
# Don't spam developers.
rm -f $artifacts/jira-status.txt $artifacts/mail-recipients.txt
else
touch $artifacts/jira-status.txt $artifacts/mail-recipients.txt
fi
)
}
# Update mail files with status of $first_bad regression
update_mail_files ()
{
(
set -euf -o pipefail
if ! [ -f $artifacts/mail-recipients.txt ]; then
return
fi
local isubdir
isubdir=$(interesting_subdir "$current_project" "$first_bad" \
"$ci_project")
sed -e "/#INTERESTING_COMMIT_STATUS#/r $icommits/$isubdir/status.txt" \
-e "/#INTERESTING_COMMIT_STATUS#/d" \
< $artifacts/mail-body.draft > $artifacts/mail-body.txt
cp $artifacts/mail-subject.draft $artifacts/mail-subject.txt
if [ "$(ls "$icommits/$isubdir" | wc -l)" = 2 ]; then
cp $artifacts/mail-recipients.draft $artifacts/mail-recipients.txt
else
# This is not the first entry for $first_bad in $ci_project --
# don't notify the patch author.
# One line for ci_config, and one for status.txt.
echo "bcc:tcwg-validation@linaro.org" \
> $artifacts/mail-recipients.txt
fi
)
}
# Post update to Jira
post_to_jira ()
{
(
set -euf -o pipefail
if ! [ -f $artifacts/jira-status.txt ]; then
return
fi
local isubdir
isubdir=$(interesting_subdir "$current_project" "$first_bad" \
"$ci_project")
sed -e "/#INTERESTING_COMMIT_STATUS#/r $icommits/$isubdir/status.txt" \
-e "/#INTERESTING_COMMIT_STATUS#/d" \
< $artifacts/jira-status.draft > $artifacts/jira-status.txt
if [ -f $HOME/.jipdate.yml ]; then
echo y | $dryrun jipdate.py -f $artifacts/jira-status.txt
fi
)
}
prepare_interesting_commits
while true; do
update_interesting_commits &
if wait $!; then
update_mail_files
post_to_jira
break
fi
done
|