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 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
|
#!/bin/sh
set -ue
if test $# -gt 0; then
cat >> /dev/stderr <<EOF
Usage:
$0
Track KVM_RUTDIR's current branch and test each "interesting" commit.
Publish results under WEB_SUMMARYDIR.
EOF
exit 1
fi
echo args: "$@"
tester=$(realpath $0)
bindir=$(dirname ${tester})
web_makedir=$(dirname ${tester})
benchdir=$(realpath $(dirname ${tester})/../..)
# run from BENCHDIR so relative make varibles work
# and ./kvm doesn't get confused
cd ${benchdir}
make_kvm_variable() {
local v=$(make -C ${benchdir}/testing/kvm \
--no-print-directory \
print-kvm-variable \
VARIABLE=$2)
if test "${v}" == "" ; then
echo $2 not defined 1>&2
exit 1
fi
eval $1="'$v'"
}
make_web_variable() {
local v=$(make -C ${bindir} \
--no-print-directory \
print-web-variable \
VARIABLE=$2)
if test "${v}" == "" ; then
echo $2 not defined 1>&2
exit 1
fi
eval $1="'$v'"
}
NOW()
{
date --utc --iso-8601=seconds
}
RESTART()
{
# don't publish location of log file on WEB via STATUS
STATUS "restarting: $@"
echo "switching output to ${summarydir}/tester.log"
exec ${tester} >> ${summarydir}/tester.log 2>&1 < /dev/null
}
LOG()
{
if test "${logfile}" ; then
echo logfile: ${logfile} >> ${summarydir}/tester.log
echo "$*" >> ${summarydir}/tester.log
fi
}
STATUS()
{
cat <<EOF 1>&2
--------------------------------------
$*
--------------------------------------
EOF
if test "${summarydir}" ; then
${bindir}/gime-status-json.sh "${subdir}" "${start_time}" "$@" \
> ${summarydir}/status.json.tmp
mv ${summarydir}/status.json.tmp ${summarydir}/status.json
fi
LOG "$@"
}
RUN()
(
LOG "running:" "$@"
set -x
"$@"
)
SLEEP()
{
# Seemlingly nothing to do ... github gets updated up every 15
# minutes so sleep for less than that
delay=$(expr 10 \* 60)
now=$(date +%s)
future=$(expr ${now} + ${delay})
start_time=$(NOW)
STATUS "idle; will retry at $(date -u -d @${future} +%H:%M) ($(date -u -d @${now} +%H:%M) + ${delay}s)"
sleep ${delay}
}
start_time=$(NOW)
subdir= # TBD ASAP
logfile= # TBD ASAP
summarydir= # TBD ASAP
STATUS "starting at ${start_time}"
make_kvm_variable rutdir KVM_RUTDIR
make_kvm_variable prefix KVM_PREFIX
make_kvm_variable workers KVM_WORKERS
make_kvm_variable kvm_platforms KVM_PLATFORMS
make_kvm_variable kvm_os KVM_OS
make_web_variable summarydir WEB_SUMMARYDIR
make_web_variable branch_tag WEB_BRANCH_TAG
rutdir=$(realpath ${rutdir})
summarydir=$(realpath ${summarydir})
declare -A platforms
declare -A platform_status
for platform in ${kvm_platforms} ; do
platforms[${platform}]=${platform}
case " ${kvm_os} " in
*" ${platform} "* ) platform_status[${platform}]=true ;;
* ) platform_status[${platform}]=false ;;
esac
done
STATUS "config loaded: summarydir=${summarydir} rutdir=${rutdir} prefix=${prefix} workers=${workers} platforms='${platforms[*]}' platform_status='${platform_status[*]}' branch_tag=${branch_tag}"
# Update the repo.
#
# Time has passed (a run finished, woke up from sleep, or the script
# was restarted) so any new commits should be fetched.
#
# Force ${branch} to be identical to ${remote} by using --ff-only - if
# it fails the script dies.
STATUS "updating repository"
# in case scripts deleted something
git -C ${rutdir} reset --hard HEAD
git -C ${rutdir} fetch || true
git -C ${rutdir} merge --quiet --ff-only
# Update the summary web page
#
# This will add any new commits found in ${rutdir} (added by above
# fetch) and merge the results from the last test run.
STATUS "updating summary"
RUN make -C ${bindir} web-summarydir
# Select the next commit to test
#
# Search [branch_tag..HEAD] for something interesting and untested.
# If there's nothing interesting, sleep and then retry.
STATUS "looking for work"
if ! commit=$(${bindir}/gime-work.sh ${summarydir} ${rutdir} ${branch_tag}) ; then
SLEEP
RESTART "after a sleep"
fi
STATUS "selected ${commit}"
# Use ${subdir} to create the results directory.
#
# Get this done ASAP so that status can start tracking it. Once
# subdir is set, STATUS will include it.
subdir=$(make -C ${bindir} \
--no-print-directory \
print-web-variable \
TESTING_HASH=${commit} \
VARIABLE=WEB_SUBDIR)
resultsdir=${summarydir}/${subdir}
STATUS "creating results directory ${resultsdir}"
mkdir -p ${resultsdir}
rm -f ${summarydir}/current
ln -s ${subdir} ${summarydir}/current
# switch to the per-test logfile
#
# And make remaining logging very verbose
logfile=${resultsdir}/tester.log
echo writing log to ${logfile}
exec "$@" >> ${logfile} 2>&1 </dev/null
STATUS switched to ${logfile}
set -vx
# Populate the resultsdir with a summary.json asap so that the web
# page can pick it up. The fields that matter are .hash(commit) and
# .directory(subdir). The timestamps are 0 since the run hasn't
# started yet.
${bindir}/gime-summary-json.sh ${rutdir} ${commit} ${subdir} > ${resultsdir}/summary.json
RUN make -C ${bindir} web-resultsdir \
WEB_MAKEDIR=${web_makedir} \
WEB_HASH=${commit} \
WEB_SUBDIR=${subdir} \
WEB_RESULTSDIR=${resultsdir} \
WEB_SUMMARYDIR=${summarydir}
# revert back to ${commit}
#
# Discard everything back to the commit to be tested, making that
# HEAD. This could have side effects such as switching branches, take
# care. If the hash is for HEAD then this is a no-op.
STATUS "checking out ${commit}"
git -C ${rutdir} reset --hard ${commit}
# Build platforms[] and platform_status[].
#
# platforms[] contains what can be built, platform_status[] indicates
# if should be built. platform_status[] is then turned into MAKEFLAGS
# to pass down.
# emit a build.json line
#
# This is merged with build.json.in to create build.json.
build_json()
{
local run=$1
local target=$2
local platform=$3
local status=$4
jq --null-input \
--arg run "${run}" \
--arg target "${target}" \
--arg platform "${platform}" \
--arg status "${status}" \
'{ run: $run, target: $target, platform: $platform, status: $status }'
}
platform_makeflags()
{
for platform in ${platforms[@]} ; do
case ${platform_status[${platform}]} in
skip ) ;;
* ) echo KVM_${platform^^}=true ;;
esac
done
}
MAKE() {
local target=$1 ; shift
RUN make -C ${rutdir} ${target} \
$(platform_makeflags) \
WEB_MAKEDIR=${web_makedir} \
WEB_RESULTSDIR= \
WEB_SUMMARYDIR=
}
KVM() {
local kvm_target=$1 ; shift
RUN ${benchdir}/kvm ${kvm_target} \
$(platform_makeflags) \
WEB_MAKEDIR=${web_makedir} \
WEB_HASH=${commit} \
WEB_RESULTSDIR=${resultsdir} \
WEB_SUMMARYDIR=${summarydir} \
PUBLISH_SOURCE_URL=https://github.com/libreswan/libreswan/blob/${commit}
}
run_target()
{
local run=$1 ; shift
local target=$1 ; shift
local platform=
local status=true
local kvm_target=${target}
if test $# -gt 0 ; then
platform=$1 ; shift
status=${platform_status[${platform}]}
kvm_target=${target}-${platform}
fi
# should the target be skipped?
if test "${status}" = skip ; then
result=skipped
build_json "${run}" "${target}" "${platform}" "skipped" >> ${resultsdir}/build.json.in
jq -s . < ${resultsdir}/build.json.in > ${resultsdir}/build.json
return
fi
# Update build.json
#
# Merge build.json.in and the current build command into
# build.json.
{
cat ${resultsdir}/build.json.in
build_json "${run}" "${target}" "${platform}" "running"
} | jq -s . > ${resultsdir}/build.json
# Update the status.
href="<a href=\"$(basename ${resultsdir})/${kvm_target}.log\">${kvm_target}</a>"
STATUS "running '${run} ${href}'"
# Run the target
#
# This duplicates the output writing it both to STDOUT and to the
# target log file.
#
# Notice how the first stage of the pipeline saves it's status by
# touching ${kvm_target}.ok.
if ${run} ${kvm_target} 2>&1 ; then
touch ${resultsdir}/${kvm_target}.ok ;
fi | tee ${resultsdir}/${kvm_target}.log
# Figure out and save the the result.
if test -r ${resultsdir}/${kvm_target}.ok ; then
result=ok
elif test ${status} != true ; then
# for instance, OpenBSD build fail is ignored.
result=ignored
else
result=failed
fi
# handle any magic extra processing
case ${result}:${kvm_target} in
ok:html )
mkdir -p ${resultsdir}/documentation
rm -f ${resultsdir}/documentation/*.html
cp -v ${rutdir}/OBJ.*/html/*.html ${resultsdir}/documentation/
# Use libreswan.7 as the index page since that
# should be the starting point for someone reading
# about libreswan.
cp -v ${rutdir}/OBJ.*/html/libreswan.7.html ${resultsdir}/documentation/index.html
;;
ok:check )
# should also only update latest when most recent
# commit; how?
rm -f ${summarydir}/latest
ln -s $(basename ${resultsdir}) ${summarydir}/latest
;;
esac
# Maintain a list of KVM_$(OS)={true,false} flags. These are
# passed to to ./kvm which passes them onto MAKE controlling which
# OS platforms are and are not enabled.
if test -n "${platform}" ; then
if test "${result}" != ok ; then
platform_status[${platform}]=skip
fi
fi
gzip -v -9 ${resultsdir}/${kvm_target}.log
# Update the status: done.
STATUS "'${run} ${href}' ok"
# Update build.json.
#
# This time add the result to build.json.in and built build.json
# from that.
build_json "${run}" "${target}" "${platform}" "${result}" >> ${resultsdir}/build.json.in
jq -s . < ${resultsdir}/build.json.in > ${resultsdir}/build.json
if test "${result}" = failed ; then
RESTART "${kvm_target} barfed"
fi
}
# List of raw results; will be converted to an array
cp /dev/null ${resultsdir}/build.json.in
# Native targets
run_target MAKE distclean
run_target MAKE html
for platform in ${platforms[@]} ; do
run_target KVM upgrade ${platform}
run_target KVM transmogrify ${platform}
done
run_target KVM keys
for platform in ${platforms[@]} ; do
run_target KVM install ${platform}
done
run_target KVM check
# Eliminate any files in the repo and the latest results directory
# that are identical.
#
# Trying to do much more than this exceeds either hardlink's internal
# cache of checksums (causing hardlink opportunities to be missed); or
# the kernel's file cache (causing catatonic performance).
#
# It is assumed that git, when switching checkouts, creates new files,
# and not modifies in-place.
STATUS "hardlink $(basename ${rutdir}) $(${resultsdir})"
hardlink -v ${rutdir} ${resultsdir}
# Clean out old logs
#
# The script can run for a long time before idleing so do this every
# time. Never delete log files for -0- commits (i.e., releases).
STATUS "deleting *.log.gz files older than 14 days"
find ${summarydir} \
-type d -name '*-0-*' -prune \
-o \
-type f -name '*.log.gz' -mtime +14 -print0 | \
xargs -0 --no-run-if-empty rm -v
# Updating tests/
STATUS "updating bisect/ directory (slow, ignoring result)"
RUN ${bindir}/gime-bisectdir.sh ${summarydir} || true
RESTART "run complete"
|