blob: 9a21d429a46b72f3305e3a21b04c70c5acee8e31 [file] [log] [blame]
Leonardo Sandoval9dfdd1b2020-08-06 17:08:11 -05001#!/usr/bin/env bash
Fathi Boudra422bf772019-12-02 11:10:16 +02002#
Leonardo Sandoval579c7372020-10-23 15:23:32 -05003# Copyright (c) 2019-2020 Arm Limited. All rights reserved.
Fathi Boudra422bf772019-12-02 11:10:16 +02004#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7#
8# Clone and sync all Trusted Firmware repositories.
9#
10# The main repository is checked out at the required refspec (GERRIT_REFSPEC).
11# The rest of repositories are attempted to sync to the topic of that refspec
12# (as pointed to by GERRIT_TOPIC). 'repo_under_test' must be set to a
13# GERRIT_PROJECT for sync to work.
14#
15# For every cloned repository, set its location to a variable so that the
16# checked out location can be passed down to sub-jobs.
17#
18# Generate an environment file that can then be sourced by the caller.
19
20set -e
21
22ci_root="$(readlink -f "$(dirname "$0")/..")"
23source "$ci_root/utils.sh"
24
25clone_log="$workspace/clone_repos.log"
26clone_data="$workspace/clone.data"
27override_data="$workspace/override.data"
28gerrit_data="$workspace/gerrit.data"
29inject_data="$workspace/inject.data"
30
31# File containing parameters for sub jobs
32param_file="$workspace/env.param"
33
34# Emit a parameter to sub jobs
35emit_param() {
36 echo "$1=$2" >> "$param_file"
37}
38
Zelalem219df412020-05-17 19:21:20 -050039# Emit a parameter for code coverage metadata
40code_cov_emit_param() {
41 emit_param "CC_$(echo ${1^^} | tr '-' _)_$2" "$3"
42}
43
Fathi Boudra422bf772019-12-02 11:10:16 +020044meta_data() {
45 echo "$1" >> "$clone_data"
46}
47
48# Path into the project filer where various pieces of scripts that override
49# some CI environment variables are stored.
50ci_overrides="$project_filer/ci-overrides"
51
52display_override() {
53 echo
54 echo -n "Override: "
55 # Print the relative path of the override file.
56 echo "$1" | sed "s#$ci_overrides/\?##"
57}
58
59strip_var() {
60 local var="$1"
61 local val="$(echo "${!var}" | sed 's#^\s*\|\s*$##g')"
62 eval "$var=\"$val\""
63}
64
65prefix_tab() {
66 sed 's/^/\t/g' < "${1:?}"
67}
68
69prefix_arrow() {
70 sed 's/^/ > /g' < "${1:?}"
71}
72
73test_source() {
74 local file="${1:?}"
75 if ! bash -c "source $file" &>/dev/null; then
76 return 1
77 fi
78
79 source "$file"
80 return 0
81}
82
83post_gerrit_comment() {
84 local gerrit_url="${gerrit_url:-$GERRIT_HOST}"
85 gerrit_url="${gerrit_url:?}"
86
87 # Posting comments to gerrit.oss.arm.com does not require any special
88 # credentials, review.trustedfirmware.org does. Provide the ci-bot-user
89 # account credentials for the latter.
90 if [ "$gerrit_url" == "review.trustedfirmware.org" ]; then
91 ssh -p 29418 -i "$tforg_key" "$tforg_user@$gerrit_url" gerrit \
Zelalem219df412020-05-17 19:21:20 -050092 review "$GERRIT_CHANGE_NUMBER,$GERRIT_PATCHSET_NUMBER" \
93 --message "'$(cat ${msg_file:?})'"
Fathi Boudra422bf772019-12-02 11:10:16 +020094 else
95 ssh -p 29418 "$gerrit_url" gerrit review \
Zelalem219df412020-05-17 19:21:20 -050096 "$GERRIT_CHANGE_NUMBER,$GERRIT_PATCHSET_NUMBER" \
97 --message "'$(cat ${msg_file:?})'"
Fathi Boudra422bf772019-12-02 11:10:16 +020098 fi
99}
100
101# Whether we've synchronized branches or not
102has_synched=0
103
104# Whether we've overridden some CI environment variables.
105has_overrides=0
106
107# Whether we've injected environment via. Jenkins
108has_env_inject=0
109
110# Default Gerrit failure message file
111gerrit_fail_msg_file="$workspace/gerrit-fail"
112
113clone_and_sync() {
114 local stat
115 local topic
116 local refspec="${!ref}"
117 local s_before s_after s_diff
118 local reference_dir="$project_filer/ref-repos/${name?}"
119 local ref_repo
120 local ret
121 local gerrit_server
122 local gerrit_user
123 local gerrit_keyfile
124
125 strip_var refspec
126 strip_var url
127
128 case "$url" in
129 *${arm_gerrit_url}*)
130 gerrit_server="arm"
131 ;;
132
133 *${tforg_gerrit_url}*)
134 # SSH authentication is required on trustedfirmware.org.
135 gerrit_server="tforg"
136 gerrit_user="$tforg_user"
137 gerrit_keyfile="$tforg_key"
138 ;;
139
140 *)
141 # The project to clone might not be hosted on a Gerrit
142 # server at all (e.g. Github).
143 ;;
144 esac
145
146 # Refspec translation is supported for Gerrit patches only.
147 if [ "$gerrit_server" ]; then
148 refspec="$($ci_root/script/translate_refspec.py \
149 -p "$name" -s "$gerrit_server" -u "$gerrit_user" \
150 -k "$gerrit_keyfile" "$refspec")"
151 fi
152
153 # Clone in the filter workspace
154 mkdir -p "$ci_scratch"
155 pushd "$ci_scratch"
156
157 # Seconds before
158 s_before="$(date +%s)"
159
160 # Clone repository to the directory same as its name; HEAD stays at
161 # master.
162 if [ -d "$reference_dir" ]; then
163 ref_repo="--reference $reference_dir"
164 fi
Zelalem219df412020-05-17 19:21:20 -0500165 echo "$ref_repo $url $name $branch"
Fathi Boudra422bf772019-12-02 11:10:16 +0200166 git clone -q $ref_repo "$url" "$name" &>"$clone_log"
Zelalem219df412020-05-17 19:21:20 -0500167 code_cov_emit_param "${name}" "URL" "${url}"
Fathi Boudra422bf772019-12-02 11:10:16 +0200168 stat="on branch master"
169
170 pushd "$name"
171
172 if [ "$refspec" ] && [ "$refspec" != "master" ]; then
173 # If a specific revision is specified, always use that.
174 git fetch -q origin "$refspec" &>"$clone_log"
175 git checkout -q FETCH_HEAD &>"$clone_log"
176 stat="refspec $refspec"
177
178 # If it's not a commit hash, have the refspec replicated on the
179 # clone so that downstream jobs can clone from this one using
180 # the same refspec.
181 if echo "$refspec" | grep -qv '^[a-f0-9]\+$'; then
182 git branch "$refspec" FETCH_HEAD
183 fi
184 elif [ "$name" = "$repo_under_test" ]; then
185 # Main repository under test
186 if [ "$GERRIT_REFSPEC" ]; then
187 # Fetch and checkout GERRIT_REFSPEC
188 git fetch -q origin "$GERRIT_REFSPEC" \
189 &>"$clone_log"
190 git checkout -q FETCH_HEAD &>"$clone_log"
191 refspec="$GERRIT_REFSPEC"
192 stat="refspec $refspec"
193 git branch "$refspec" FETCH_HEAD
194 fi
195 elif [ "$GERRIT_TOPIC" ]; then
196 # Auxiliary repository: it's already on master when cloned above.
197 topic="$GERRIT_TOPIC"
198
199 # Check first if there's a Gerrit topic matching the topic of
200 # the main repository under test
201 ret=0
202 refspec="$("$ci_root/script/translate_refspec.py" -p "$name" \
203 -u "$gerrit_user" -k "$gerrit_keyfile" \
204 -s "$gerrit_server" "topic:$topic" 2>/dev/null)" \
Zelalem219df412020-05-17 19:21:20 -0500205 || ret="$?"
Fathi Boudra422bf772019-12-02 11:10:16 +0200206 if [ "$ret" = 0 ]; then
207 {
208 git fetch -q origin "$refspec"
209 git checkout -q FETCH_HEAD
210 } &>"$clone_log"
211 stat="gerrit topic $topic"
212 git branch "$refspec" FETCH_HEAD
213
214 has_synched=1
215 elif git fetch -q origin "topics/$topic" &>"$clone_log"; then
216 # If there's a remote branch matching the Gerrit topic
217 # name, checkout to that; otherwise, stay on master.
218 git checkout -q FETCH_HEAD &>"$clone_log"
219 refspec="topics/$topic"
220 stat="on branch $refspec"
221 git branch "$refspec" FETCH_HEAD
222
223 has_synched=1
224 fi
225 fi
226
Zelalem219df412020-05-17 19:21:20 -0500227 code_cov_emit_param "${name}" "REFSPEC" "${refspec}"
Fathi Boudra422bf772019-12-02 11:10:16 +0200228 # Generate meta data. Eliminate any quoting in commit subject as it
229 # might cause problems when reporting back to Gerrit.
230 meta_data "$name: $stat"
231 meta_data " $(git show --quiet --format=%H): $(git show --quiet --format=%s | sed "s/[\"']/ /g")"
232 meta_data " Commit date: $(git show --quiet --format=%cd)"
233 meta_data
Zelalem219df412020-05-17 19:21:20 -0500234 code_cov_emit_param "${name}" "COMMIT" "$(git show --quiet --format=%H)"
Fathi Boudra422bf772019-12-02 11:10:16 +0200235
236 # Calculate elapsed seconds
237 s_after="$(date +%s)"
238 let "s_diff = $s_after - $s_before" || true
239
240 echo
241 echo "Repository: $url ($stat)"
242 prefix_arrow <(git show --quiet)
243 echo "Cloned in $s_diff seconds"
244 echo
245
246 popd
247 popd
248
249 emit_env "$loc" "$ci_scratch/$name"
250 emit_env "$ref" "$refspec"
251
252 # If this repository is being tested under a Gerrit trigger, set the
253 # Gerrit test groups.
254 if [ "$name" = "$repo_under_test" ]; then
255 # For a Gerrit trigger, it's possible that users publish patch
256 # sets in quick succession. If the CI is already busy, this
257 # leads to more and more triggers queuing up. Also, it's likey
258 # that older patch sets are tested before new ones. But because
259 # there are newer patch sets already in queue, we should avoid
260 # running tests on older ones as their results will be discarded
261 # anyway.
262 pushd "$ci_scratch/$name"
263
264 change_id="$(git show -q --format=%b | awk '/Change-Id/{print $2}')"
265 commit_id="$(git show -q --format=%H)"
266 latest_commit_id="$($ci_root/script/translate_refspec.py \
267 -p "$name" -u "$gerrit_user" -k "$gerrit_keyfile" \
268 -s "$gerrit_server" "change:$change_id")"
269
270 if [ "$commit_id" != "$latest_commit_id" ]; then
271 # Overwrite Gerrit failure message
272 cat <<EOF >"$gerrit_fail_msg_file"
273Patch set $GERRIT_PATCHSET_NUMBER is not the latest; not tested.
274Please await results for the latest patch set.
275EOF
276
277 cat "$gerrit_fail_msg_file"
278 echo
279 die
280 fi
281
282 # Run nominations on this repository
283 rules_file="$ci_root/script/$name.nomination.py"
284 if [ -f "$rules_file" ]; then
285 "$ci_root/script/gen_nomination.py" "$rules_file" > "$nom_file"
286 if [ -s "$nom_file" ]; then
287 emit_env "NOMINATION_FILE" "$nom_file"
288 echo "$name has $(wc -l < $nom_file) test nominations."
289 fi
290 fi
291
292 popd
293
294 # Allow for groups to be overridden
295 GERRIT_BUILD_GROUPS="${GERRIT_BUILD_GROUPS-$gerrit_build_groups}"
296 if [ "$GERRIT_BUILD_GROUPS" ]; then
297 emit_env "GERRIT_BUILD_GROUPS" "$GERRIT_BUILD_GROUPS"
298 fi
299
300 GERRIT_TEST_GROUPS="${GERRIT_TEST_GROUPS-$gerrit_test_groups}"
301 if [ "$GERRIT_TEST_GROUPS" ]; then
302 emit_env "GERRIT_TEST_GROUPS" "$GERRIT_TEST_GROUPS"
303 fi
304 fi
305}
306
307# When triggered from Gerrit, the main repository that is under test. Can be
308# either TF, TFTF, SCP or CI.
309if [ "$GERRIT_REFSPEC" ]; then
310 repo_under_test="${repo_under_test:-$REPO_UNDER_TEST}"
311 repo_under_test="${repo_under_test:?}"
312fi
313
314# Environment file in Java property file format, that's soured in Jenkins job
315env_file="$workspace/env"
316rm -f "$env_file"
317
318# Workspace on external filer where all repositories gets cloned so that they're
319# accessible to all Jenkins slaves.
320if upon "$local_ci"; then
321 ci_scratch="$workspace/filer"
322else
323 scratch_owner="${JOB_NAME:?}-${BUILD_NUMBER:?}"
324 ci_scratch="$project_scratch/$scratch_owner"
325 tforg_key="$CI_BOT_KEY"
326 tforg_user="$CI_BOT_USERNAME"
327fi
328
329if [ -d "$ci_scratch" ]; then
330 # This could be because of jobs of same name running from
331 # production/staging/temporary VMs
332 echo "Scratch space $ci_scratch already exists; removing."
333 rm -rf "$ci_scratch"
334fi
335mkdir -p "$ci_scratch"
336
337# Nomination file
338nom_file="$ci_scratch/nominations"
339
340# Set CI_SCRATCH so that it'll be injected when sub-jobs are triggered.
341emit_param "CI_SCRATCH" "$ci_scratch"
342
343# However, on Jenkins v2, injected environment variables won't override current
344# job's parameters. This means that the current job (the scratch owner, the job
345# that's executing this script) would always observe CI_SCRATCH as empty, and
346# therefore won't be able to remove it. Therefore, use a different variable
347# other than CI_SCRATCH parameter for the current job to refer to the scratch
348# space (although they both will have the same value!)
349emit_env "SCRATCH_OWNER" "$scratch_owner"
350emit_env "SCRATCH_OWNER_SPACE" "$ci_scratch"
351
352strip_var CI_ENVIRONMENT
353if [ "$CI_ENVIRONMENT" ]; then
354 {
355 echo
356 echo "Injected environment:"
357 prefix_tab <(echo "$CI_ENVIRONMENT")
358 echo
359 } >> "$inject_data"
360
361 cat "$inject_data"
362
363 tmp_env=$(mktempfile)
364 echo "$CI_ENVIRONMENT" > "$tmp_env"
365 source "$tmp_env"
366 cat "$tmp_env" >> "$env_file"
367
368 has_env_inject=1
369fi
370
371if [ "$GERRIT_BRANCH" ]; then
372 # Overrides targeting a specific Gerrit branch.
373 target_branch_override="$ci_overrides/branch/$GERRIT_BRANCH/env"
374 if [ -f "$target_branch_override" ]; then
375 display_override "$target_branch_override"
376
377 {
378 echo
379 echo "Target branch overrides:"
380 prefix_tab "$target_branch_override"
381 echo
382 } >> "$override_data"
383
384 cat "$override_data"
385
386 source "$target_branch_override"
387 cat "$target_branch_override" >> "$env_file"
388
389 has_overrides=1
390 fi
391fi
392
393TF_REFSPEC="${tf_refspec:-$TF_REFSPEC}"
394if not_upon "$no_tf"; then
395 # Clone Trusted Firmware repository
396 url="$tf_src_repo_url" name="trusted-firmware" ref="TF_REFSPEC" \
397 loc="TF_CHECKOUT_LOC" \
398 gerrit_build_groups="tf-gerrit-build" \
399 gerrit_test_groups="tf-gerrit-tests tf-gerrit-tftf" \
400 clone_and_sync
401fi
402
403TFTF_REFSPEC="${tftf_refspec:-$TFTF_REFSPEC}"
404if not_upon "$no_tftf"; then
405 # Clone Trusted Firmware TF repository
406 url="$tftf_src_repo_url" name="trusted-firmware-tf" ref="TFTF_REFSPEC" \
407 loc="TFTF_CHECKOUT_LOC" \
Zelalem219df412020-05-17 19:21:20 -0500408 gerrit_test_groups="tftf-l1-build tftf-l1-fvp tftf-l1-spm" \
Fathi Boudra422bf772019-12-02 11:10:16 +0200409 clone_and_sync
410fi
411
Zelalem219df412020-05-17 19:21:20 -0500412# Clone code coverage repository if code coverage is enabled
413if not_upon "$no_cc"; then
414 pushd "$ci_scratch"
415 git clone -q $cc_src_repo_url cc_plugin -b $cc_src_repo_tag 2> /dev/null
416 popd
417fi
418
Fathi Boudra422bf772019-12-02 11:10:16 +0200419SCP_REFSPEC="${scp_refspec:-$SCP_REFSPEC}"
420if upon "$clone_scp"; then
421 # Clone SCP Firmware repository
422 # NOTE: currently scp/firmware:master is not tracking the upstream.
423 # Therefore, if the url is gerrit.oss.arm.com/scp/firmware and there is
424 # no ref_spec, then set the ref_spec to master-upstream.
Fathi Boudra422bf772019-12-02 11:10:16 +0200425 if [ "$scp_src_repo_url" = "$scp_src_repo_default" ]; then
426 SCP_REFSPEC="${SCP_REFSPEC:-master-upstream}"
427 fi
428
429 url="$scp_src_repo_url" name="scp" ref="SCP_REFSPEC" \
430 loc="SCP_CHECKOUT_LOC" clone_and_sync
431
432 pushd "$ci_scratch/scp"
433
434 # Edit the submodule URL to point to the reference repository so that
435 # all submodule update pick from the reference repository instead of
436 # Github.
437 cmsis_ref_repo="${cmsis_root:-$project_filer/ref-repos/cmsis}"
438 if [ -d "$cmsis_ref_repo" ]; then
439 cmsis_reference="--reference $cmsis_ref_repo"
440 fi
Fathi Boudra422bf772019-12-02 11:10:16 +0200441 git submodule -q update $cmsis_reference --init
Zelalem1af7a7b2020-08-04 17:34:32 -0500442 # Workaround while fixing permissions on /arm/projectscratch/ssg/trusted-fw/ref-repos/cmsis
443 cd cmsis
444 code_cov_emit_param "CMSIS" "URL" "$(git remote -v | grep fetch | awk '{print $2}')"
445 code_cov_emit_param "CMSIS" "COMMIT" "$(git rev-parse HEAD)"
446 code_cov_emit_param "CMSIS" "REFSPEC" "master"
447 cd ..
448 ########################################
Fathi Boudra422bf772019-12-02 11:10:16 +0200449 popd
450fi
451
452CI_REFSPEC="${ci_refspec:-$CI_REFSPEC}"
453if not_upon "$no_ci"; then
454 # Clone Trusted Firmware CI repository
455 url="$tf_ci_repo_url" name="trusted-firmware-ci" ref="CI_REFSPEC" \
456 loc="CI_ROOT" gerrit_test_groups="ci-l1" \
457 clone_and_sync
458fi
459
460if [ "$GERRIT_BRANCH" ]; then
461 # If this CI run was in response to a Gerrit commit, post a comment back
462 # to the patch set calling out everything that we've done so far. This
463 # reassures both the developer and the reviewer about CI refspecs used
464 # for CI testing.
465 #
466 # Note the extra quoting for the message, which Gerrit requires.
467 if upon "$has_synched"; then
468 echo "Branches synchronized:" >> "$gerrit_data"
469 echo >> "$gerrit_data"
470 cat "$clone_data" >> "$gerrit_data"
471 fi
472
473 if upon "$has_overrides"; then
474 cat "$override_data" >> "$gerrit_data"
475 fi
476
477 if upon "$has_env_inject"; then
478 cat "$inject_data" >> "$gerrit_data"
479 fi
480
481 if [ -s "$gerrit_data" ]; then
482 msg_file="$gerrit_data" post_gerrit_comment
483 fi
484fi
485
Zelalem219df412020-05-17 19:21:20 -0500486echo "SCP_TOOLS_COMMIT=$SCP_TOOLS_COMMIT" >> "$param_file"
487
Fathi Boudra422bf772019-12-02 11:10:16 +0200488# Copy environment file to ci_scratch for sub-jobs' access
489cp "$env_file" "$ci_scratch"
490cp "$param_file" "$ci_scratch"
491
492# Copy clone data so that it's available for sub-jobs' HTML reporting
493if [ -f "$clone_data" ]; then
494 cp "$clone_data" "$ci_scratch"
495fi
496
497# vim: set tw=80 sw=8 noet: