blob: eed10c4ea2782258f0e80f962e843d80a56d9749 [file] [log] [blame]
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +02001#!/bin/bash
2
3# Copyright 2019 Samsung Electronics Co., Ltd.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17set -Eeuxo pipefail
18PS4='+['$(readlink -f "$0")' ${FUNCNAME[0]%main}#$LINENO] '
19
20echo '---> maven-coverity.sh'
21
Artem Naluzhnyyec81f732019-08-01 14:38:18 +020022SUBMISSION_ATTEMPTS=5
23SUBMISSION_INITIAL_REST_INTERVAL=30 # seconds, will be doubled after each attempt
24
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +020025#-----------------------------------------------------------------------------
Artem Naluzhnyydcc213d2019-09-02 14:27:36 +020026# Check for git repo changes within the last $MAX_GIT_REPO_AGE_HOURS hours
27#
28# It makes sense to set the value twice the 'cron' interval for the job (e.g.
29# if 'cron: @daily', then MAX_GIT_REPO_AGE_HOURS=48)
30
31if ! [[ "${MAX_GIT_REPO_AGE_HOURS:=0}" =~ ^[0-9]+$ ]]; then
32 echo '[ERROR] MAX_GIT_REPO_AGE_HOURS must be non-negative integer.' \
33 >&2
34 exit 1
35fi
36
37if [ ${MAX_GIT_REPO_AGE_HOURS:=0} -ne 0 ]; then
38 LAST_COMMIT_AGE=$(( $(date +%s) - $(git log -1 --pretty=format:%ct) ))
39
Artem Naluzhnyy2aaed582019-09-30 10:00:50 +020040 if [ $LAST_COMMIT_AGE -gt $(( MAX_GIT_REPO_AGE_HOURS *60*60 )) ]; then
Artem Naluzhnyydcc213d2019-09-02 14:27:36 +020041 echo '[NOTICE] Git repository did not have any commits last' \
42 "${MAX_GIT_REPO_AGE_HOURS} hours - no need to re-analyse it." \
43 >&2
44 exit 0
45 fi
46fi
47
48#-----------------------------------------------------------------------------
Artem Naluzhnyy59016a42019-08-11 20:48:23 +020049# Process parameters for JS/TS/Python/Ruby/PHP files analysis
Artem Naluzhnyy59bc0372019-07-01 10:52:48 +020050
Artem Naluzhnyy59bc0372019-07-01 10:52:48 +020051if [ -n "${SEARCH_PATHS:=}" ]; then
52 for SEARCH_PATH in ${SEARCH_PATHS}; do
53 if [ -d "${SEARCH_PATH}" ]; then
Artem Naluzhnyy59016a42019-08-11 20:48:23 +020054 FS_CAPTURE_SEARCH_PARAMS="${FS_CAPTURE_SEARCH_PARAMS:=} --fs-capture-search '${SEARCH_PATH}'"
Artem Naluzhnyy59bc0372019-07-01 10:52:48 +020055 else
Artem Naluzhnyydcc213d2019-09-02 14:27:36 +020056 echo "[ERROR] '${SEARCH_PATH}' from \$SEARCH_PATHS is not an" \
57 "existing directory." \
58 >&2
Artem Naluzhnyy59bc0372019-07-01 10:52:48 +020059 exit 1
60 fi
61 done
Artem Naluzhnyy59bc0372019-07-01 10:52:48 +020062
Artem Naluzhnyy59016a42019-08-11 20:48:23 +020063 for EXCLUDE_REGEX in ${SEARCH_EXCLUDE_REGEXS:=}; do
64 EXCLUDE_REGEX=${EXCLUDE_REGEX//\'/\'\\\'\'} # escape single quote "'"
65 FS_CAPTURE_SEARCH_PARAMS="${FS_CAPTURE_SEARCH_PARAMS} --fs-capture-search-exclude-regex '${EXCLUDE_REGEX}'"
66
67 # FIXME: a hack to deal with temporary(?) non-functional filter to ignore
68 # specific source code parts by Coverity Scan ("--fs-capture-search-exclude-regex"
69 # CLI parameter for "cov-build" tool). The hack can be removed when this CLI
70 # parameter is fixed on Coverity side.
71 FS_CAPTURE_SEARCH_EXCLUDE_HACK_PARAMS="${FS_CAPTURE_SEARCH_EXCLUDE_HACK_PARAMS:=} --tu-pattern 'file('\\''${EXCLUDE_REGEX}'\\'')'"
72 done
73fi
Artem Naluzhnyy59bc0372019-07-01 10:52:48 +020074
75#-----------------------------------------------------------------------------
Artem Naluzhnyy373fc1c2019-06-11 17:14:07 +020076# Check if we are allowed to submit results to Coverity Scan service
77# and have not exceeded our upload quota limits
78# See also: https://scan.coverity.com/faq#frequency
79
Artem Naluzhnyy5ec3b772019-08-17 16:21:27 +020080if [ "${DRY_RUN}" != 'true' ]; then
81 CURL_OUTPUT=$(
82 curl \
83 --verbose \
84 --silent \
85 --show-error \
86 --fail \
87 --form "project=${COVERITY_PROJECT_NAME}" \
88 --form "token=${COVERITY_TOKEN}" \
89 'https://scan.coverity.com/api/upload_permitted'
90 )
Artem Naluzhnyy373fc1c2019-06-11 17:14:07 +020091
Artem Naluzhnyy5ec3b772019-08-17 16:21:27 +020092 IS_COVERITY_UPLOAD_PERMITTED=$(
93 echo "${CURL_OUTPUT}" \
94 | jq '.upload_permitted'
95 )
96 if [ x"${IS_COVERITY_UPLOAD_PERMITTED}" != x'true' ]; then
Artem Naluzhnyydcc213d2019-09-02 14:27:36 +020097 echo "[WARNING] Upload quota reached. Next upload permitted at" \
98 $(echo "${CURL_OUTPUT}" | jq '.next_upload_permitted_at') \
99 >&2
Artem Naluzhnyy5ec3b772019-08-17 16:21:27 +0200100 exit 1
101 fi
Artem Naluzhnyy373fc1c2019-06-11 17:14:07 +0200102fi
103
104#-----------------------------------------------------------------------------
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200105# Get Coverity Scan build tool
106
107curl \
108 --verbose \
109 --silent \
110 --show-error \
111 --fail \
112 --form "project=${COVERITY_PROJECT_NAME}" \
113 --form "token=${COVERITY_TOKEN}" \
Artem Naluzhnyy01319e12019-09-02 15:51:12 +0200114 --output '/tmp/coverity_tool.tgz' \
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200115 'https://scan.coverity.com/download/linux64'
116
Artem Naluzhnyy450f6c62019-06-11 17:19:40 +0200117curl \
118 --verbose \
119 --silent \
120 --show-error \
121 --fail \
122 --form "project=${COVERITY_PROJECT_NAME}" \
123 --form "token=${COVERITY_TOKEN}" \
124 --form 'md5=1' \
Artem Naluzhnyy01319e12019-09-02 15:51:12 +0200125 --output '/tmp/coverity_tool.md5' \
Artem Naluzhnyy450f6c62019-06-11 17:19:40 +0200126 'https://scan.coverity.com/download/linux64'
127
Artem Naluzhnyy01319e12019-09-02 15:51:12 +0200128echo -n ' /tmp/coverity_tool.tgz' >> '/tmp/coverity_tool.md5'
129md5sum --check '/tmp/coverity_tool.md5'
Artem Naluzhnyy450f6c62019-06-11 17:19:40 +0200130
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200131tar \
132 --extract \
133 --gunzip \
Artem Naluzhnyy01319e12019-09-02 15:51:12 +0200134 --file='/tmp/coverity_tool.tgz' \
135 --directory='/tmp'
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200136
Artem Naluzhnyy01319e12019-09-02 15:51:12 +0200137COVERITY_BUILD_TOOL_DIRECTORY='/tmp/'$(
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200138 head -1 <( \
139 tar \
140 --list \
141 --gunzip \
Artem Naluzhnyy01319e12019-09-02 15:51:12 +0200142 --file='/tmp/coverity_tool.tgz'
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200143 )
144)
145COVERITY_BINARY_DIRECTORY="${COVERITY_BUILD_TOOL_DIRECTORY}bin"
146test -d "${COVERITY_BINARY_DIRECTORY}" \
147 || exit 1
148export PATH="${PATH}:${COVERITY_BINARY_DIRECTORY}"
149
Artem Naluzhnyy01319e12019-09-02 15:51:12 +0200150rm '/tmp/coverity_tool.tgz'
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200151
152#-----------------------------------------------------------------------------
153# Build
154
155export MAVEN_OPTS
156
Artem Naluzhnyy59bc0372019-07-01 10:52:48 +0200157eval cov-build \
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200158 --dir 'cov-int' \
Artem Naluzhnyy59016a42019-08-11 20:48:23 +0200159 --append-log \
160 ${FS_CAPTURE_SEARCH_PARAMS:=} \
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200161 "${MVN}" clean install \
162 --errors \
163 --global-settings "${GLOBAL_SETTINGS_FILE}" \
164 --settings "${SETTINGS_FILE}" \
165 ${MAVEN_OPTIONS:=} \
166 ${MAVEN_PARAMS:=}
167
Artem Naluzhnyy59016a42019-08-11 20:48:23 +0200168# FIXME: a hack to deal with temporary(?) non-functional filter to ignore
169# specific source code parts by Coverity Scan ("--fs-capture-search-exclude-regex"
170# CLI parameter for "cov-build" tool). The hack can be removed when this CLI
171# parameter is fixed on Coverity side.
172if [ -n "${FS_CAPTURE_SEARCH_EXCLUDE_HACK_PARAMS:=}" ]; then
173 eval cov-manage-emit \
174 --dir 'cov-int' \
175 ${FS_CAPTURE_SEARCH_EXCLUDE_HACK_PARAMS} \
176 delete
177fi
178
179# Extract git data for analysed files
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200180cov-import-scm \
181 --dir 'cov-int' \
182 --scm 'git'
183
Artem Naluzhnyy59016a42019-08-11 20:48:23 +0200184# List all analysed files from the project
Artem Naluzhnyy097f7342019-06-27 14:14:14 +0200185cov-manage-emit \
186 --dir cov-int \
187 list \
188| grep \
189 --invert-match \
190 '^Translation unit:$' \
191| sed \
Artem Naluzhnyy64ff9982019-08-16 14:12:51 +0200192 --regexp-extended \
193 's!^[[:digit:]]+ -> !!' \
Artem Naluzhnyy59016a42019-08-11 20:48:23 +0200194| sort \
Artem Naluzhnyy64ff9982019-08-16 14:12:51 +0200195> 'cov-int/coverity-scan-analysed-files.txt'
196
197# List all analyzed files that are not tracked by SCM repository
198cov-manage-emit \
199 --dir cov-int \
200 list-scm-unknown \
201| sed \
202 --regexp-extended \
203 's!^[^ ]+ !!' \
204| sort \
205> 'cov-int/scm-untracked-files.txt'
Artem Naluzhnyy097f7342019-06-27 14:14:14 +0200206
Artem Naluzhnyyf8fd3e42019-08-17 17:18:28 +0200207if [ -s 'cov-int/scm-untracked-files.txt' ]; then
208 echo '[WARNING] There are some files analysed but not tracked by SCM repository.' \
209 'There might be 3rd-party or auto-generated sources. See details in' \
210 '"cov-int/scm-untracked-files.txt" file.' \
211 >&2
212fi
213
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200214#-----------------------------------------------------------------------------
215# Submit results to Coverity service
216
Artem Naluzhnyy5ec3b772019-08-17 16:21:27 +0200217if [ "${DRY_RUN}" != 'true' ]; then
218 tar \
219 --create \
220 --gzip \
221 --file='results.tgz' \
222 'cov-int'
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200223
Artem Naluzhnyy5ec3b772019-08-17 16:21:27 +0200224 for (( ATTEMPT=1; ATTEMPT<=SUBMISSION_ATTEMPTS; ATTEMPT++ )); do
225 CURL_OUTPUT=$(
226 curl \
227 --verbose \
228 --silent \
229 --show-error \
230 --fail \
231 --write-out '\n%{http_code}' \
232 --form "project=${COVERITY_PROJECT_NAME}" \
233 --form "email=${COVERITY_USER_EMAIL}" \
234 --form "token=${COVERITY_TOKEN}" \
235 --form 'file=@results.tgz' \
236 --form "version=${GIT_COMMIT:0:7}" \
237 --form "description=${GIT_BRANCH}" \
238 'https://scan.coverity.com/builds'
239 )
240 HTTP_RESPONSE_CODE=$(echo -n "${CURL_OUTPUT}" | tail -1)
241 test x"${HTTP_RESPONSE_CODE}" = x"200" \
242 && break
Artem Naluzhnyyec81f732019-08-01 14:38:18 +0200243
Artem Naluzhnyy5ec3b772019-08-17 16:21:27 +0200244 sleep "${SUBMISSION_REST_INTERVAL:-$SUBMISSION_INITIAL_REST_INTERVAL}"
Artem Naluzhnyyec81f732019-08-01 14:38:18 +0200245
Artem Naluzhnyy5ec3b772019-08-17 16:21:27 +0200246 SUBMISSION_REST_INTERVAL=$(( ${SUBMISSION_REST_INTERVAL:-$SUBMISSION_INITIAL_REST_INTERVAL} * 2 ))
247 done
Artem Naluzhnyyec81f732019-08-01 14:38:18 +0200248
Artem Naluzhnyy5ec3b772019-08-17 16:21:27 +0200249 HTTP_RESPONSE=$(echo -n "${CURL_OUTPUT}" | head -n -1 | tr -d '\n')
250 if [ x"${HTTP_RESPONSE}" != x"Build successfully submitted." ]; then
Artem Naluzhnyydcc213d2019-09-02 14:27:36 +0200251 echo "[ERROR] Coverity Scan service responded with '${HTTP_RESPONSE}'" \
252 "while 'Build successfully submitted.' expected." \
253 >&2
Artem Naluzhnyy5ec3b772019-08-17 16:21:27 +0200254 exit 1
255 fi
Artem Naluzhnyydcc213d2019-09-02 14:27:36 +0200256
257 echo "[INFO] Build successfully submitted to Coverity Scan server." >&2
Artem Naluzhnyyec81f732019-08-01 14:38:18 +0200258fi
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200259
260#-----------------------------------------------------------------------------
Artem Naluzhnyy6ba95782019-06-10 16:39:54 +0200261exit 0