summaryrefslogtreecommitdiff
path: root/round-robin-baseline.sh
blob: eff32441207224a566a5992957ecf73e22dc2c2a (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
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
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
#!/bin/bash

set -euf -o pipefail

scripts=$(dirname $0)
# shellcheck source=jenkins-helpers.sh
. $scripts/jenkins-helpers.sh

convert_args_to_variables "$@"

obligatory_variables rr[top_artifacts] rr[update_baseline]
declare -A           rr

push_base_artifacts="${push_base_artifacts-false}"
rewrite_base_artifacts="${rewrite_base_artifacts-false}"
rewrite_num="${rewrite_num-1}"
commit_artifacts="${commit_artifacts-true}"
verbose="${verbose-true}"
max_removed_revs="${max_removed_revs-10%}"
skip_annex_downloads="${skip_annex_downloads-false}"

if $rewrite_base_artifacts; then
   obligatory_variables build_script
   declare              build_script
fi

# To enable rewrite:
# - set rewrite_base_artifacts to true, and
# - set rewrite_num to N+1 to rewrite N oldest revisions (0 for all)

# To rewrite local base-artifacts (e.g., for testing of round-robin-notify.sh
# or bmk-scripts):
# 1. Increase rr[minor] or rr[major] in your local build script.
# 2. Do a baseline build (to clone all repos and checkout dependencies of
#    round-robin-notify.sh).
#      ~/jenkins-scripts/tcwg_bmk-build.sh '%%rr[top_artifacts]' artifacts \
#        '==rr[ci_project]' CI_PROJECT '==rr[ci_config]' CI_CONFIG
# 2a. If you know that you have all dependencies already present, then just
#     copy latest artifacts from base-artifacts's HEAD, and edit manifest
#     manually to increase rr[minor] or rr[major].
#       rsync -a --del --exclude /.git base-artifacts/ artifacts/
#       vi artifacts/manifest.sh
# 3. Run this script with "__push_base_artifacts false",
#    "__commit_artifacts false" and "__rewrite_num 0".
#      ~/jenkins-scripts/round-robin-baseline.sh \
#        '@@rr[top_artifacts]' artifacts __build_script tcwg_bmk-build.sh \
#        __push_base_artifacts false __commit_artifacts false \
#        __rewrite_base_artifacts true __rewrite_num 0
# 4. Note that the above will not change upstream base-artifacts, but notify
#    logic may push to interesting commits and/or update jira cards.

# The patch version represent the version of the generated notification files.
# upgrading it will automatically enable the rewrite process bellow.
rr[patch]=0

if $verbose; then
    set -x
fi

# Trim history of base-artifacts to keep repo size managable.
trim_base_artifacts ()
{
    (
    set -euf -o pipefail

    # - For the last 100 builds: keep everything
    # - For the next 100 builds: keep essential artifacts
    #   -- NN-<step> directories are non-essential, the rest -- jenkins/,
    #      dashboard/, etc. -- are essential.
    # - For the rest of the builds: keep only "update_baseline==force" builds
    local old_commit
    old_commit=$(git -C base-artifacts rev-parse --verify HEAD~100 \
		     2>/dev/null || true)

    if [ "$old_commit" = "" ]; then
	return 0
    fi

    local head
    head=$(git -C base-artifacts rev-parse HEAD)

    # Remove step directories (start with a number) from $old_commit
    # and older.
    git -C base-artifacts checkout --detach $old_commit
    git -C base-artifacts filter-repo --force \
	--invert-paths --path-regex '^[0-9].*' \
	--refs HEAD

    local new_old_commit
    new_old_commit=$(git -C base-artifacts rev-parse HEAD)

    # Walk through even older history (starting with new_old_commit~100)
    # and leave only commits that have update_baseline=={force,init}.
    local child orig_parent new_parent
    child=$(git -C base-artifacts rev-parse --verify HEAD~100 \
		2>/dev/null || true)

    while [ "$child" != "" ]; do
	git -C base-artifacts checkout --detach $child

	orig_parent=$(git -C base-artifacts rev-parse --verify HEAD^ \
			  2>/dev/null || true)
	# Find new_parent -- commit that has update_baseline!=onsuccess.
	new_parent=""
	while true; do
	    new_parent=$(git -C base-artifacts rev-parse --verify HEAD^ \
			     2>/dev/null || true)
	    if [ "$new_parent" = "" ]; then
		break
	    fi

	    git -C base-artifacts checkout --detach $new_parent

	    local u_b
	    u_b=$(get_baseline_manifest "{rr[update_baseline]}")
	    if [ "$u_b" != "onsuccess" ]; then
		break
	    fi
	done

	# Replace $orig_parent with $new_parent, and update new_old_commit.
	if [ "$new_parent" != "$orig_parent" ]; then
	    # Note that if $new_parent is empty, then $child will become
	    # the root commit.
	    git -C base-artifacts replace --force --graft $child $new_parent
	    git -C base-artifacts checkout --detach $new_old_commit
	    git -C base-artifacts filter-repo --force --refs HEAD
	    git -C base-artifacts replace --delete $child
	    new_old_commit=$(git -C base-artifacts rev-parse HEAD)
	fi

	# Proceed to the next commit in history.
	child="$new_parent"
    done

    git -C base-artifacts checkout --detach $head

    # Reparent history on the new version of $old_commit.
    if [ "$old_commit" != "$new_old_commit" ]; then
	git -C base-artifacts replace --force $old_commit $new_old_commit
	git -C base-artifacts filter-repo --force --refs HEAD
	git -C base-artifacts replace --delete $old_commit
    fi
    )
}

# Commit current result and artifacts to the baseline repository
update_baseline ()
{
    (
    set -euf -o pipefail

    # Rsync current artifacts.  Make sure to use -I rsync option since
    # quite often size and timestamp on artifacts/results will be the same
    # as on base-artifacts/results due to "git reset --hard HEAD^" below.
    # This caused rsync's "quick check" heuristic to skip "results" file.
    # !!! From this point on, logs and other artifacts won't be included
    # in base-artifacts.git repo (though they will be uploaded to jenkins).
    rsync -aI --del --exclude /.git ${rr[top_artifacts]}/ base-artifacts/

    local amend=""

    if [ x"${rr[update_baseline]}" = x"init" ]; then
	amend="--amend"
    fi

    local msg_title="${rr[update_baseline]}"
    if [ x"${BUILD_URL+set}" = x"set" ]; then
	# Add build number
	msg_title="$msg_title: #$(basename "$BUILD_URL")"
    fi
    msg_title="$msg_title: $(grep -v "^#" ${rr[top_artifacts]}/results | tail -n1)"
    msg_title="$msg_title: [TCWG CI] ${BUILD_URL-$(pwd)}"

    git -C base-artifacts add .
    git -C base-artifacts commit $amend -m "$msg_title

Results :
$(cat ${rr[top_artifacts]}/results | sed -e 's/^/  | /')

check_regression status : ${rr[no_regression_result]}
"
    )
}

rewrite_single_revision ()
{
    (
    set -euf -o pipefail
    local old_commit="$1"
    local log_prefix="$2"

    local orig_head
    orig_head=$(git -C base-artifacts rev-parse HEAD)

    # Return to $orig_head in case of an error.
    # shellcheck disable=SC2064
    trap "echo CLEANUP; git -C base-artifacts reset --hard $orig_head" EXIT

    local -a fixup_opts=()

    echo "Rewriting revision $old_commit :"
    echo "  $(git -C base-artifacts show --no-patch --oneline $old_commit)"
    echo ""

    # Verify that parent of $old_commit is reasonable:
    #   1. it has manifest.sh;
    #   2. TODO: maybe check that git_annex_download() succeeds for
    #            base-artifacts?  Thinking about it, that should have been
    #            verified on the previous call of rewrite_single_revision()
    #            that processed the parent revision.
    #
    # At least in one case we had history starting with an empty commit, which
    # wasn't ammended in update_baseline().  Scanning of history in
    # rewrite_base_artifacts() ignored the empty commit because it had no
    # manifest.sh file.  The loop below can be used to remove unwanted weird
    # commits from history.
    local old_parent="$old_commit"
    while true; do
	old_parent=$(git -C base-artifacts rev-parse --verify "$old_parent^" \
			 2>/dev/null || true)
	if [ "$old_parent" = "" ]; then
	    # We reached beginning of history.
	    break
	fi

	git -C base-artifacts checkout --detach "$old_parent"
	if ! [ -f base-artifacts/manifest.sh ]; then
	    # Remove commits with no manifest.sh .
	    continue
	fi

	break
    done

    if [ "$old_parent" != "" ]; then
	git_annex_download base-artifacts annex
    else
	# Initialize a new baseline when base-artifacts is empty.
	fixup_opts+=("==rr[update_baseline]" init)
	# FIXME: Move empty.git to bkp.tcwglab.
	git -C base-artifacts fetch \
	    https://git-us.linaro.org/toolchain/ci/base-artifacts/empty.git \
	    refs/heads/empty
	git -C base-artifacts checkout --detach FETCH_HEAD
    fi

    local old_artifacts="${rr[top_artifacts]}/99-rewrite/artifacts.old"

    # Fetch artifacts/ of old build
    rm -rf "$old_artifacts"
    mkdir "$old_artifacts"
    git -C base-artifacts archive "$old_commit" | tar x -C "$old_artifacts"

    # FIXME: Remove workarounds for out-dated files:
    # Remove .gitignore that ignores annex/bmk-data symlink.
    rm -f "$old_artifacts/.gitignore"
    # Remove results_id now that we use annex/bmk-data .  Note that we have
    # fetched the results pointed to by results_id in git_annex_download().
    rm -f "$old_artifacts/results_id"

    # Fetch old rr values before they are re-written
    local old_manifest="$old_artifacts/manifest.sh"
    local -A old
    old[major]=$(get_manifest "$old_manifest" "{rr[major]-0}")
    old[minor]=$(get_manifest "$old_manifest" "{rr[minor]-0}")
    old[patch]=$(get_manifest "$old_manifest" "{rr[patch]-0}")
    old[notify]=$(get_manifest "$old_manifest" "{notify-}")
    old[update_baseline]=$(get_manifest "$old_manifest" \
					"{rr[update_baseline]-}")
    old[ci_project]=$(get_manifest "$old_manifest" "{rr[ci_project]-}")
    old[ci_config]=$(get_manifest "$old_manifest" "{rr[ci_config]-}")

    # downloading the annex, unless the user explicitely asked to skip
    local res force_remove=false
    if ! $skip_annex_downloads; then
	git_annex_download "$old_artifacts" annex &
	res=0 && wait $! || res=$?
	if [ $res != 0 ]; then
	    # Something has happened to the annex'ed files.  Remove the result.
	    force_remove=true
	fi
    fi

    case "${old[major]}.${old[minor]}" in
	"0."*)
	    # FIXME: Workaround old/renamed names of ci_project/ci_config.
	    # This is, mostly, for tcwg_bmk_tx1 and tcwg_bmk_tk1 projects.
	    if [ "${old[ci_project]}" != "${rr[ci_project]}" ]; then
		fixup_opts+=("==rr[ci_project]" "${rr[ci_project]}")
	    fi
	    if [ "${old[ci_config]}" != "${rr[ci_config]}" ]; then
		fixup_opts+=("==rr[ci_config]" "${rr[ci_config]}")
	    fi

	    # FIXME: Remove old result with no git/ information.
	    # We have switched to storing git information in artifacts/git/
	    # directory long time ago, so it doesn't worth the effort to
	    # workaround such cases.  Just remove the result.
	    # Note that this will remove the result even when only minor
	    # (not major) version is increased.
	    if ! [ -d "$old_artifacts/git" ]; then
		force_remove=true
	    fi
	    ;;
    esac

    res=0
    # If major and minor are the same, it means that check_regression stage
    # is already up-to-date. Only append the manifest with patch version
    if [ "${rr[major]-0}.${rr[minor]-0}" == "${old[major]}.${old[minor]}" ]; then
        echo "rr[patch]=${rr[patch]}" | manifest_out
    else
	# otherwise run the check_regression stage
	$scripts/$build_script \
	    @@rr[top_artifacts] "$old_artifacts" __start_at check_regression \
	    "${fixup_opts[@]}" &
	res=0 && wait $! || res=$?
    fi

    if [ $res != 0 ]; then
	assert_with_msg "check_regression() failed on forced update_baseline" \
			[ "${old[update_baseline]}" = "onsuccess" ]

	if [ "${rr[major]-0}" -gt "${old[major]}" ]; then
	    # $build_script [somewhat expectedly] failed to process old results,
	    # so remove it from history.
	    # In this case $new_old_commit will be set to $old_commit's parent,
	    # so $old_commit will be removed from history.
	    force_remove=true
	fi
    fi

    if $force_remove; then
	res=1
    fi

    if [ $res = 0 ]; then
	local -a notify_opts=()

	case "${old[major]}.${old[minor]}" in
	    "0."*)
		# FIXME: Workaround possible lack of "$notify" in v0.*
		# manifests.
		# Remove once there are no configurations with v0.0 manifests.
		case "${old[notify]}":"${old[update_baseline]}" in
		    "":"force") notify_opts=(--notify onregression) ;;
		    "":*) notify_opts=(--notify ignore) ;;
		esac
		;;
	esac

	$scripts/round-robin-notify.sh \
	    @@rr[top_artifacts] "$old_artifacts" __post_mail false \
	    __post_jira_comment false "${notify_opts[@]}" \
	    __build_script "$build_script" \
	    __verbose "$verbose" &> "$log_prefix-notify.log"

	(
	    unset rr
	    manifest_pop
	    declare -A rr
	    convert_args_to_variables @@rr[top_artifacts] "$old_artifacts"
	    update_baseline

	    local repo1="${rr[baseline_branch]#linaro-local/ci/}"
	    git_annex_upload base-artifacts annex \
			     "$repo1/$(basename "${BUILD_URL-0}")-"
	)

	git -C base-artifacts diff "$old_commit" "HEAD" -- manifest.sh \
	    &> "$log_prefix-manifest.diff"
	git -C base-artifacts diff "$old_commit" "HEAD" -- notify/ \
	    &> "$log_prefix-notify.diff"
	git -C base-artifacts diff --stat -p "$old_commit" "HEAD" -- \
	    ':(exclude)manifest.sh' ':(exclude)notify/' \
	    &> "$log_prefix-other.diff"
    elif $force_remove; then
	touch "$log_prefix.removed"
	# Above "git_annex_download base-artifacts annex" may have changed
	# files in base-artifacts/annex/ directory.  Restore to prestine
	# state to avoid failure in "git -C base-artifacts checkout" below.
	git_clean base-artifacts
    else
	# $build_script [unexpectedly] failed to process old results,
	# so fail and notify developers (by sending error-mail).
	assert_with_msg "$build_script failed to process $old_commit" false
    fi

    local new_old_commit
    new_old_commit=$(git -C base-artifacts rev-parse HEAD)

    assert_with_msg "Rewritten commit did not change" \
		    [ "$old_commit" != "$new_old_commit" ]

    # Reparent history on the new version of $old_commit.
    trap "" EXIT
    git -C base-artifacts checkout --detach $orig_head
    git -C base-artifacts replace --force $old_commit $new_old_commit
    git -C base-artifacts filter-repo --force --refs HEAD
    git -C base-artifacts replace --delete $old_commit
    )
}

declare -g rewrite_base_artifacts_first=true
# Update history of base-artifacts
rewrite_base_artifacts ()
{
    (
    set -euf -o pipefail

    set +x

    local n_rev=0 total_revs=-1

    # Fetch flaky tests from base-artifacts history.
    local manifest history_root="" old_revision=""
    local -A old
    while read -r manifest; do
	total_revs=$(($total_revs + 1))
	if [ "$history_root" = "" ]; then
	    history_root="$manifest"
	    continue
	elif [ "$old_revision" != "" ]; then
	    # Continue reading from get_git_history() to have it finish
	    # gracefully.
	    continue
	fi
	n_rev=$(($n_rev + 1))

	old[major]=$(get_manifest "$manifest" "{rr[major]-0}")
	old[minor]=$(get_manifest "$manifest" "{rr[minor]-0}")
	old[patch]=$(get_manifest "$manifest" "{rr[patch]-0}")

	assert_with_msg "rr[minor] should be less than 100" [ "${rr[minor]-0}" -lt 100 ]
	assert_with_msg "rr[patch] should be less than 100" [ "${rr[patch]-0}" -lt 100 ]

	if [ "$(( rr[major]*100*100 + rr[minor]*100 + rr[patch] ))" -gt \
		"$(( old[major]*100*100 + old[minor]*100 + old[patch] ))" ]; then
	    # Found old entry to update;
	    # directory name of $manifest is the revision
	    old_revision=$(basename "$(dirname "$manifest")")
	fi
    done < <(get_git_history -0 base-artifacts manifest.sh)

    if $verbose; then
	set -x
    fi

    rm -rf "$history_root"

    if [ "$old_revision" = "" ]; then
	return 0
    fi

    local rewrite_top="${rr[top_artifacts]}/99-rewrite"

    if $rewrite_base_artifacts_first; then
	change_tag="v${old[major]}.${old[minor]}.${old[patch]}_to_v${rr[major]-0}.${rr[minor]-0}.${rr[patch]-0}"
	if [ "${BUILD_URL-}" != "" ]; then
	    change_tag="$change_tag-$(basename "$BUILD_URL")"
	fi

	local backup_branch
	backup_branch=$(echo "${rr[baseline_branch]}" \
			    | sed -e "s#linaro-local/ci/#linaro-local/$change_tag/#")
	if $push_base_artifacts; then
	    local repo="${rr[baseline_branch]#linaro-local/ci/}"
	    repo="ssh://bkp.tcwglab/home/tcwg-buildslave/base-artifacts/$repo.git"

	    git -C base-artifacts push --force \
		"$repo"	"HEAD:refs/heads/$backup_branch"
	else
	    git -C base-artifacts branch --force "$backup_branch" HEAD
	fi

	rm -rf "$rewrite_top"
    fi

    local log_prefix="$rewrite_top/$rewrite_num-$n_rev-$total_revs"
    mkdir -p "$(dirname "$log_prefix")"

    echo -e "\n""  Rewriting:  $(git -C base-artifacts show --no-patch --oneline $old_revision)""\n"

    rewrite_single_revision "$old_revision" "$log_prefix" \
	&> "$log_prefix-rewrite.log"

    # Rescan base-artifacts again for another entry to update.
    touch "$rewrite_top/more"
    )
}

# Push base-artifacts, or, maybe, skip.
# The first push, which is outside of rewrite process, always happens.
# Subsequent pushes may be skipped, if the previous push is still running.
# This is an optimization to avoid re-pushing histories during rewrite,
# which are only to be discarded moments later.
declare -g push_baseline_pid=0
declare -g push_baseline_skipped=0
push_baseline ()
{
    if [ "$push_baseline_pid" != "0" ]; then
	if ! ps -p "$push_baseline_pid" >/dev/null; then
	    wait "$push_baseline_pid"
	    push_baseline_pid=0
	fi

	if [ "$push_baseline_pid" != "0" ]; then
	    push_baseline_skipped=$(($push_baseline_skipped + 1))
	    return 0
	fi
    fi

    push_baseline_skipped=0

    local repo1="${rr[baseline_branch]#linaro-local/ci/}"
    repo="ssh://bkp.tcwglab/home/tcwg-buildslave/base-artifacts/$repo1.git"

    (
    set -euf -o pipefail

    git_annex_upload base-artifacts annex "$repo1/$(basename "${BUILD_URL-0}")-"

    if ! git ls-remote --heads "$repo" &>/dev/null; then
	ssh bkp.tcwglab git init --bare \
	    "/home/tcwg-buildslave/base-artifacts/$repo1.git"
    fi
    )

    git -C base-artifacts push --force \
	"$repo" "HEAD:refs/heads/${rr[baseline_branch]}" &
    push_baseline_pid=$!
}

if $commit_artifacts; then
    update_baseline
fi

# Compute the maximum of revisions that we accept to remove. If we remove
# more than we expected. This is suspicious, stop the rewriting process
declare nb_revs nb_removed_revs
nb_revs=$(git -C base-artifacts rev-list --count HEAD)
nb_revs=$((nb_revs<rewrite_num ? nb_revs : rewrite_num))
if [[ "$max_removed_revs" =~ .*% ]]; then
    # If max_removed_revs is expressed in percentage of the total revisions
    # convert max_removed_revs in term of number of revisions.
    max_removed_revs=${max_removed_revs/\%/ / 100}
    max_removed_revs=$((nb_revs * $max_removed_revs))
fi

while true; do
    if $push_base_artifacts; then
	if $rewrite_base_artifacts_first; then
	    # Trimming base-artifacts takes a lot of time on big histories,
	    # and it doesn't really do anything on repeat trimmings during
	    # history rewrite.  Therefore, trim only on the first iteration
	    # of this loop.
	    trim_base_artifacts
	fi
	push_baseline
	if $rewrite_base_artifacts_first; then
	    # We create a backup copy of the branch when rewriting the first
	    # revision.  If we don't have the initial push done by that time
	    # it would start to push a duplicate copy of baseline, thus slowing
	    # the initial push.  Therefore, wait for the initial push here.
	    wait "$push_baseline_pid"
	    push_baseline_pid=0
	fi
    fi

    if $rewrite_base_artifacts; then
	rewrite_num=$(($rewrite_num - 1))
	if [ "$rewrite_num" = "0" ]; then
	    break
	fi

	rm -f "${rr[top_artifacts]}/99-rewrite/more"
	rewrite_base_artifacts &
	res=0 && wait $! || res=$?
	rewrite_base_artifacts_first=false

	if [ "$res" != "0" ]; then
	    echo "WARNING: failed rewriting base-artifacts"
	    if [ -d ${rr[top_artifacts]}/jenkins ]; then
		echo "maxim.kuvyrkov@linaro.org, laurent.alfonsi@linaro.org" \
                     > artifacts/jenkins/error-mail-recipients.txt
                echo -e "${BUILD_URL-}\nWARNING: failed rewriting base-artifacts" \
                     >> artifacts/jenkins/error-mail-body.txt
	    fi
	    break
	fi

	if [ -f "${rr[top_artifacts]}/99-rewrite/more" ]; then

	    nb_removed_revs="$(find ${rr[top_artifacts]}/99-rewrite/ -maxdepth 1 \
		-name '*.removed' | wc -l)"

	    if [ "$nb_removed_revs" -gt "$max_removed_revs" ]; then
		echo "WARNING: Too many revisions removed. Aborting."
		if [ -d ${rr[top_artifacts]}/jenkins ]; then
		    echo "maxim.kuvyrkov@linaro.org, laurent.alfonsi@linaro.org" \
			 > artifacts/jenkins/error-mail-recipients.txt
                    echo -e "${BUILD_URL-}\nWARNING: Too many revisions removed while "\
			"rewriting base-artifacts" >> artifacts/jenkins/error-mail-body.txt
		fi
		break
	    fi

	    # Push current version and search for another revision to update.
	    continue
	fi
    fi

    break
done

if [ "$push_baseline_pid" != "0" ]; then
    wait "$push_baseline_pid"
    push_baseline_pid=0
    if [ "$push_baseline_skipped" != "0" ]; then
	# Do the final push, which was previously skipped.
	push_baseline
    fi
fi