blob: 97b53455c2fce3f74af73c9947da2af208314f6d [file] [log] [blame]
Fathi Boudra422bf772019-12-02 11:10:16 +02001#!/bin/bash
2#
3# Copyright (c) 2019, Arm Limited. All rights reserved.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7
8# This file is sourced from the build_package.sh script to use
9# coverity_wrapper() function as a build wrapper.
10#
11# This wrapper supports two work flows:
12#
13# - Compare the branch under test with that of master, and print defects. If
14# there are defects, we arrange the build to be marked as unstable. Set
15# $cov_run_type to 'branch-report-compare' to use this.
16#
17# - Commit and create snapshot for the entire branch. Set $cov_run_type to
18# 'branch-report-full' to use this.
19#
20# Coverity analysis involves contacting the server, which have shown to be very
21# slow. Depending on the type of analysis performed, we might have to do
22# analysis more than once, and doing that in series would only increase the turn
23# around time. To mitigate this, all Coverity commands are saved as small
24# snippets, and are then called from a Makefile. Make take care of running
25# commands in parallel (all this at the expense of readability).
26
27coverity_wrapper() {
28 local cov_dir="$workspace/coverity"
29 local cov_config="$cov_dir/config"
30 local cov_compiler="${cov_compiler:-${CROSS_COMPILE}gcc}"
31
32 local golden_repo="$cov_dir/golden-repo"
33 local golden_snapshot="$cov_dir/golden-snapshot"
34
35 local branch_repo="$cov_dir/branch-repo"
36 local branch_snapshot="$cov_dir/branch-snapshot"
37
38 local auth_file="${cov_auth_file:-$ci_root/coverity/tfcibot@$coverity_host}"
39 local makefile="$workspace/makefile.cov"
40 local snippets_dir="$cov_dir/snippets"
41 local stream_name="${BUILD_CONFIG:?}"
42
43 local ref_arg
44 local description
45 local need_compare
46
47 echo_w
48 mkdir -p "$cov_dir"
49
50 if echo "${cov_run_type:?}" | grep -iq "branch-report-compare"; then
51 need_compare=1
52 local golden_url="${cov_golden_url:-$tf_src_repo_url}"
53 local golden_ref="${cov_golden_ref:-master}"
54 fi
55
56 if upon "$local_ci"; then
57 description="$USER-local ${cov_checker:?}"
58 # Reference repository can't be shallow
59 if [ ! -f "$tf_root/.git/shallow" ]; then
60 ref_arg="--reference $tf_root"
61 fi
62 else
63 description="$JOB_NAME#$BUILD_NUMBER ${cov_checker:?}"
64 ref_arg="--reference $project_filer/ref-repos/trusted-firmware"
65 fi
66
67 # Create a stream and assign to Trusted Firmware project
68 chmod 400 "$auth_file"
69
70 mkdir -p "$snippets_dir"
71 cat <<EOF >"$makefile"
72SHELL := /bin/bash
73
74define run-snippet
75echo ":\$@" >&3
76echo ">\$@: \$\$(date)"
77if ! bash -ex $snippets_dir/\$@; then \\
78 echo " :\$@ failed! See build log" >&3; \\
79 exit 1; \\
80fi
81echo "<\$@: \$\$(date)"
82endef
83
84EOF
85
86 create_snippet() {
87 # Create a script snippet
88 cat >"$snippets_dir/${name?}"
89
90 # Add a rule to the makefile
91 cat <<EOF >>"$makefile"
92$name:${deps:+ $deps}
93 @\$(run-snippet)
94
95EOF
96 }
97
98 # golden-setup. Additionally query for a snapshot ID corresponding to
99 # this version in the stream. If a snapshot ID exists, the comparison
100 # file is generated containing the snapshot ID.
101 #
102 # We need to make a shallow clone of the repository first in order to
103 # get the reference, however. And, if later we find needing a fresh
104 # snapshot, we unshallow that.
105 cat <<EOF | name="golden-setup" create_snippet
106git clone --depth 1 -q $ref_arg "$golden_url" "$golden_repo"
107cd -P "$golden_repo"
108git fetch --depth 1 -q origin "$golden_ref"
109git checkout -q FETCH_HEAD
110
111if [ -z "$cov_force_commit" ]; then
112 "$ci_root/script/get_latest_snapshot.py" \\
113 --host "$coverity_host" \\
Zelalem219df412020-05-17 19:21:20 -0500114 --https-port "$coverity_port" \\
Fathi Boudra422bf772019-12-02 11:10:16 +0200115 --file "$golden_snapshot" \\
116 --description "*$cov_checker*" \\
117 --version "\$(git show -q --format=%H)" \\
118 "$stream_name" 2>&3 || true
119fi
120
121{
122echo " golden: $golden_url $golden_ref"
123echo " golden: \$(git show -q --format=%H)"
124} >&3
125
126if [ -f "$golden_snapshot" ]; then
127 echo " golden: snapshot ID \$(cat $golden_snapshot) exists" >&3
128else
129 git fetch -q --unshallow origin
130fi
131EOF
132
133
134 # Setup branch
135 if upon "$local_ci"; then
136 if not_upon "$need_compare"; then
137 ln -s "$tf_root" "$branch_repo"
138
139 # Run scanning as-is since we don't need a comparison.
140 cat <<EOF | name="branch-setup" create_snippet
141if [ "$dont_clean" != 1 ]; then
142 cd -P "$branch_repo"
143 MAKEFLAGS= make distclean
144fi
145EOF
146 else
147 # Running comparison means that we need to make a merge
148 # commit. It's undesirable to do that on the user's
149 # working copy, so do it on a separate one.
150 cat <<EOF | name="branch-setup" create_snippet
151git clone -q $ref_arg "$tf_src_repo_url" "$branch_repo"
152cd -P "$branch_repo"
153git checkout -b cov-branch origin/master
154rsync -a --exclude=".git" --exclude "**.o" --exclude "**.d" "$tf_root/" .
155git add .
156git -c user.useconfigonly=false commit --allow-empty -q -m "Test branch"
157git checkout master
158git -c user.useconfigonly=false merge --no-ff -q cov-branch
159
160git remote add golden "$golden_url"
161git fetch -q golden "$golden_ref"
162git checkout -q -b cov-golden FETCH_HEAD
163git -c user.useconfigonly=false merge --no-edit --no-ff -q cov-branch
164EOF
165 fi
166 else
167 # Use the local checkout at $tf_root for analysing branch and
168 # golden together
169 ln -s "$tf_root" "$branch_repo"
170
171 cat <<EOF | name="branch-setup" create_snippet
172if [ "$need_compare" ]; then
173 cd -P "$branch_repo"
174 if [ -f ".git/shallow" ]; then
175 git fetch -q --unshallow origin
176 fi
177 git remote add golden "$golden_url"
178 git fetch -q golden $golden_ref
179 git branch cov-branch HEAD
180 git checkout -q -b cov-golden FETCH_HEAD
181 echo " branch: \$(git show -q --format=%H cov-branch)" >&3
182 git -c user.useconfigonly=false merge --no-edit --no-ff -q cov-branch
183fi
184EOF
185 fi
186
187
188 # Setup stream
189 cat <<EOF | name="stream-setup" create_snippet
190if cov-manage-im --mode streams --add --set "name:$stream_name" \\
191 --auth-key-file "$auth_file" \\
Zelalem219df412020-05-17 19:21:20 -0500192 --host "$coverity_host" --ssl --port "$coverity_port"; then
Fathi Boudra422bf772019-12-02 11:10:16 +0200193 cov-manage-im --mode projects --name "Arm Trusted Firmware" --update \\
194 --insert "stream:$stream_name" --auth-key-file "$auth_file" \\
Zelalem219df412020-05-17 19:21:20 -0500195 --host "$coverity_host" --ssl --port "$coverity_port"
Fathi Boudra422bf772019-12-02 11:10:16 +0200196fi
197EOF
198
199
200 # Coverity configuration
201 cat <<EOF | name="cov-config" create_snippet
202cov-configure --comptype gcc --template --compiler "$cov_compiler" \\
203 --config "$cov_config/config.xml"
204EOF
205
206
207 # cov-build on golden; only performed if a comparison file doesn't
208 # exist.
209 cat <<EOF | name="golden-cov-build" deps="cov-config golden-setup" \
210 create_snippet
211if [ ! -f "$golden_snapshot" -o -n "$cov_force_commit" ]; then
212 cd -P "$golden_repo"
213 MAKEFLAGS= cov-build --config "$cov_config/config.xml" \\
214 --dir "$cov_dir/golden" $@
215else
216 echo " golden: cov-build skipped" >&3
217fi
218EOF
219
220
221 # cov-analyze on golden; only performed if a comparison file doesn't
222 # exist.
223 cat <<EOF | name="golden-cov-analyze" deps="golden-cov-build" \
224 create_snippet
225if [ ! -f "$golden_snapshot" -o -n "$cov_force_commit" ]; then
226 cd -P "$golden_repo"
227 cov-analyze --dir "$cov_dir/golden" $cov_options --verbose 0 \\
228 --strip-path "\$(pwd -P)" \\
229 --redirect "stdout,$cov_dir/golden.txt"
230else
231 echo " golden: cov-analyze skipped" >&3
232fi
233EOF
234
235
236 # cov-commit-defects on golden. Since more than one job could have
237 # started analyzing golden after finding the snapshot misssing, we check
238 # for a snapshot again, and a commit only performed if a comparison file
239 # doesn't exist.
240 cat <<EOF | name="golden-cov-commit-defects" \
241 deps="stream-setup golden-cov-analyze" create_snippet
242if [ ! -f "$golden_snapshot" -a -z "$cov_force_commit" ]; then
243 "$ci_root/script/get_latest_snapshot.py" \\
244 --host "$coverity_host" \\
Zelalem219df412020-05-17 19:21:20 -0500245 --https-port "$coverity_port" \\
Fathi Boudra422bf772019-12-02 11:10:16 +0200246 --file "$golden_snapshot" \\
247 --description "*$cov_checker*" \\
248 --version "\$(git show -q --format=%H)" \\
249 "$stream_name" 2>&3 || true
250 retried=1
251fi
252
253if [ ! -f "$golden_snapshot" -o -n "$cov_force_commit" ]; then
254 cd -P "$golden_repo"
255 cov-commit-defects --dir "$cov_dir/golden" --host "$coverity_host" \\
Zelalem219df412020-05-17 19:21:20 -0500256 --https-port "$coverity_port" \\
Fathi Boudra422bf772019-12-02 11:10:16 +0200257 --stream "$stream_name" --auth-key-file "$auth_file" \\
258 --version "\$(git show -q --format=%H)" \\
259 --description "$description" \\
260 --snapshot-id-file "$golden_snapshot"
261 echo " golden: new snapshot ID: \$(cat $golden_snapshot)" >&3
262elif [ "\$retried" ]; then
263 {
264 echo " golden: snapshot ID \$(cat $golden_snapshot) now exists"
265 echo " golden: cov-commit-defects skipped"
266 } >&3
267else
268 echo " golden: cov-commit-defects skipped" >&3
269fi
270EOF
271
272
273 # cov-build on branch
274 cat <<EOF | name="branch-cov-build" deps="cov-config branch-setup" \
275 create_snippet
276cd -P "$branch_repo"
277MAKEFLAGS= cov-build --config "$cov_config/config.xml" --dir "$cov_dir/branch" $@
278EOF
279
280
281 # cov-analyze on branch
282 cat <<EOF | name="branch-cov-analyze" deps="branch-cov-build" \
283 create_snippet
284cd -P "$branch_repo"
285cov-analyze --dir "$cov_dir/branch" $cov_options --verbose 0 \\
286 --strip-path "\$(pwd -P)" \\
287 --redirect "stdout,$cov_dir/branch.txt"
288EOF
289
290
291 # cov-commit-defects on branch
292 cat <<EOF | name="branch-cov-commit-defects" \
293 deps="stream-setup branch-cov-analyze" create_snippet
294if [ "$cov_force_commit" ]; then
295 cd -P "$branch_repo"
296 cov-commit-defects --dir "$cov_dir/branch" --host "$coverity_host" \\
Zelalem219df412020-05-17 19:21:20 -0500297 --https-port "$coverity_port" \\
Fathi Boudra422bf772019-12-02 11:10:16 +0200298 --stream "$stream_name" --description "$description" \\
299 --version "\$(git show -q --format=%H%)" \\
300 --auth-key-file "$auth_file" \\
301 --snapshot-id-file "$branch_snapshot"
302 echo " branch: new snapshot ID: \$(cat $branch_snapshot)" >&3
303else
304 echo " branch: cov-commit-defects skipped" >&3
305fi
306EOF
307
308
309 # cov-commit-defects on branch, but compare with golden
310 cat <<EOF | name="branch-report-compare" \
311 deps="golden-cov-commit-defects branch-cov-analyze" create_snippet
312cov-commit-defects --dir "$cov_dir/branch" --host "$coverity_host" \\
Zelalem219df412020-05-17 19:21:20 -0500313 --https-port "$coverity_port" \\
Fathi Boudra422bf772019-12-02 11:10:16 +0200314 --stream "$stream_name" --auth-key-file "$auth_file" \\
315 --preview-report-v2 "$cov_dir/report.json" \\
316 --comparison-snapshot-id "\$(cat $golden_snapshot)"
317EOF
318
319
320 # cov-commit-defects on branch to report branch report
321 cat <<EOF | name="branch-report-full" \
322 deps="branch-cov-commit-defects stream-setup branch-cov-analyze" \
323 create_snippet
324cov-commit-defects --dir "$cov_dir/branch" --host "$coverity_host" \\
Zelalem219df412020-05-17 19:21:20 -0500325 --https-port "$coverity_port" \\
Fathi Boudra422bf772019-12-02 11:10:16 +0200326 --stream "$stream_name" --auth-key-file "$auth_file" \\
327 --preview-report-v2 "$cov_dir/report.json"
328EOF
329
330 local minus_j="-j"
331 if upon "$cov_serial_build"; then
332 minus_j=
333 fi
334
335 # Call Coverity targets
336 echo "Coverity run type: ${cov_run_type:?}"
337 if ! eval MAKEFLAGS= make -r $minus_j -f "$makefile" $cov_run_type; then
338 return 1
339 fi
340
341 # Generate a text report
342 local defects_file="$workspace/coverity_report.txt"
343
344 if [ -f "$cov_dir/report.json" ]; then
345 python3 "$ci_root/script/coverity_parser.py" \
346 --output "$workspace/defects.json" \
347 $cov_report_options \
348 "$cov_dir/report.json" >"$defects_file" 2>&3 || true
349 fi
350
351 # If there were defects, print them out to the console. For local CI,
352 # print them in yellow--the same color we'd use for UNSTABLE builds.
353 if [ -s "$defects_file" ]; then
354 echo_w
355 echo_w "Coverity defects found:"
356 echo_w
357 if upon "$local_ci"; then
358 echo_w "$(tput setaf 3)"
359 fi
360 cat "$defects_file" >&3
361 if upon "$local_ci"; then
362 echo_w "$(tput sgr0)"
363 fi
364 echo_w
365 echo_w "$(wc -l < "$defects_file") defects reported."
366 echo_w
367 build_unstable >&3
368 echo_w
369 else
370 echo_w
371 echo_w "No coverity defects found."
372 echo_w
373 fi
374}