1*9c263d07SPeter Maydell#!/bin/sh -e 2*9c263d07SPeter Maydell 3*9c263d07SPeter Maydell# Upload a created tarball to Coverity Scan, as per 4*9c263d07SPeter Maydell# https://scan.coverity.com/projects/qemu/builds/new 5*9c263d07SPeter Maydell 6*9c263d07SPeter Maydell# This work is licensed under the terms of the GNU GPL version 2, 7*9c263d07SPeter Maydell# or (at your option) any later version. 8*9c263d07SPeter Maydell# See the COPYING file in the top-level directory. 9*9c263d07SPeter Maydell# 10*9c263d07SPeter Maydell# Copyright (c) 2017-2020 Linaro Limited 11*9c263d07SPeter Maydell# Written by Peter Maydell 12*9c263d07SPeter Maydell 13*9c263d07SPeter Maydell# Note that this script will automatically download and 14*9c263d07SPeter Maydell# run the (closed-source) coverity build tools, so don't 15*9c263d07SPeter Maydell# use it if you don't trust them! 16*9c263d07SPeter Maydell 17*9c263d07SPeter Maydell# This script assumes that you're running it from a QEMU source 18*9c263d07SPeter Maydell# tree, and that tree is a fresh clean one, because we do an in-tree 19*9c263d07SPeter Maydell# build. (This is necessary so that the filenames that the Coverity 20*9c263d07SPeter Maydell# Scan server sees are relative paths that match up with the component 21*9c263d07SPeter Maydell# regular expressions it uses; an out-of-tree build won't work for this.) 22*9c263d07SPeter Maydell# The host machine should have as many of QEMU's dependencies 23*9c263d07SPeter Maydell# installed as possible, for maximum coverity coverage. 24*9c263d07SPeter Maydell 25*9c263d07SPeter Maydell# To do an upload you need to be a maintainer in the Coverity online 26*9c263d07SPeter Maydell# service, and you will need to know the "Coverity token", which is a 27*9c263d07SPeter Maydell# secret 8 digit hex string. You can find that from the web UI in the 28*9c263d07SPeter Maydell# project settings, if you have maintainer access there. 29*9c263d07SPeter Maydell 30*9c263d07SPeter Maydell# Command line options: 31*9c263d07SPeter Maydell# --dry-run : run the tools, but don't actually do the upload 32*9c263d07SPeter Maydell# --update-tools-only : update the cached copy of the tools, but don't run them 33*9c263d07SPeter Maydell# --tokenfile : file to read Coverity token from 34*9c263d07SPeter Maydell# --version ver : specify version being analyzed (default: ask git) 35*9c263d07SPeter Maydell# --description desc : specify description of this version (default: ask git) 36*9c263d07SPeter Maydell# --srcdir : QEMU source tree to analyze (default: current working dir) 37*9c263d07SPeter Maydell# --results-tarball : path to copy the results tarball to (default: don't 38*9c263d07SPeter Maydell# copy it anywhere, just upload it) 39*9c263d07SPeter Maydell# 40*9c263d07SPeter Maydell# User-specifiable environment variables: 41*9c263d07SPeter Maydell# COVERITY_TOKEN -- Coverity token 42*9c263d07SPeter Maydell# COVERITY_EMAIL -- the email address to use for uploads (default: 43*9c263d07SPeter Maydell# looks at your git user.email config) 44*9c263d07SPeter Maydell# COVERITY_BUILD_CMD -- make command (default: 'make -jN' where N is 45*9c263d07SPeter Maydell# number of CPUs as determined by 'nproc') 46*9c263d07SPeter Maydell# COVERITY_TOOL_BASE -- set to directory to put coverity tools 47*9c263d07SPeter Maydell# (default: /tmp/coverity-tools) 48*9c263d07SPeter Maydell# 49*9c263d07SPeter Maydell# You must specify the token, either by environment variable or by 50*9c263d07SPeter Maydell# putting it in a file and using --tokenfile. Everything else has 51*9c263d07SPeter Maydell# a reasonable default if this is run from a git tree. 52*9c263d07SPeter Maydell 53*9c263d07SPeter Maydellcheck_upload_permissions() { 54*9c263d07SPeter Maydell # Check whether we can do an upload to the server; will exit the script 55*9c263d07SPeter Maydell # with status 1 if the check failed (usually a bad token); 56*9c263d07SPeter Maydell # will exit the script with status 0 if the check indicated that we 57*9c263d07SPeter Maydell # can't upload yet (ie we are at quota) 58*9c263d07SPeter Maydell # Assumes that PROJTOKEN, PROJNAME and DRYRUN have been initialized. 59*9c263d07SPeter Maydell 60*9c263d07SPeter Maydell echo "Checking upload permissions..." 61*9c263d07SPeter Maydell 62*9c263d07SPeter Maydell if ! up_perm="$(wget https://scan.coverity.com/api/upload_permitted --post-data "token=$PROJTOKEN&project=$PROJNAME" -q -O -)"; then 63*9c263d07SPeter Maydell echo "Coverity Scan API access denied: bad token?" 64*9c263d07SPeter Maydell exit 1 65*9c263d07SPeter Maydell fi 66*9c263d07SPeter Maydell 67*9c263d07SPeter Maydell # Really up_perm is a JSON response with either 68*9c263d07SPeter Maydell # {upload_permitted:true} or {next_upload_permitted_at:<date>} 69*9c263d07SPeter Maydell # We do some hacky string parsing instead of properly parsing it. 70*9c263d07SPeter Maydell case "$up_perm" in 71*9c263d07SPeter Maydell *upload_permitted*true*) 72*9c263d07SPeter Maydell echo "Coverity Scan: upload permitted" 73*9c263d07SPeter Maydell ;; 74*9c263d07SPeter Maydell *next_upload_permitted_at*) 75*9c263d07SPeter Maydell if [ "$DRYRUN" = yes ]; then 76*9c263d07SPeter Maydell echo "Coverity Scan: upload quota reached, continuing dry run" 77*9c263d07SPeter Maydell else 78*9c263d07SPeter Maydell echo "Coverity Scan: upload quota reached; stopping here" 79*9c263d07SPeter Maydell # Exit success as this isn't a build error. 80*9c263d07SPeter Maydell exit 0 81*9c263d07SPeter Maydell fi 82*9c263d07SPeter Maydell ;; 83*9c263d07SPeter Maydell *) 84*9c263d07SPeter Maydell echo "Coverity Scan upload check: unexpected result $up_perm" 85*9c263d07SPeter Maydell exit 1 86*9c263d07SPeter Maydell ;; 87*9c263d07SPeter Maydell esac 88*9c263d07SPeter Maydell} 89*9c263d07SPeter Maydell 90*9c263d07SPeter Maydell 91*9c263d07SPeter Maydellupdate_coverity_tools () { 92*9c263d07SPeter Maydell # Check for whether we need to download the Coverity tools 93*9c263d07SPeter Maydell # (either because we don't have a copy, or because it's out of date) 94*9c263d07SPeter Maydell # Assumes that COVERITY_TOOL_BASE, PROJTOKEN and PROJNAME are set. 95*9c263d07SPeter Maydell 96*9c263d07SPeter Maydell mkdir -p "$COVERITY_TOOL_BASE" 97*9c263d07SPeter Maydell cd "$COVERITY_TOOL_BASE" 98*9c263d07SPeter Maydell 99*9c263d07SPeter Maydell echo "Checking for new version of coverity build tools..." 100*9c263d07SPeter Maydell wget https://scan.coverity.com/download/linux64 --post-data "token=$PROJTOKEN&project=$PROJNAME&md5=1" -O coverity_tool.md5.new 101*9c263d07SPeter Maydell 102*9c263d07SPeter Maydell if ! cmp -s coverity_tool.md5 coverity_tool.md5.new; then 103*9c263d07SPeter Maydell # out of date md5 or no md5: download new build tool 104*9c263d07SPeter Maydell # blow away the old build tool 105*9c263d07SPeter Maydell echo "Downloading coverity build tools..." 106*9c263d07SPeter Maydell rm -rf coverity_tool coverity_tool.tgz 107*9c263d07SPeter Maydell wget https://scan.coverity.com/download/linux64 --post-data "token=$PROJTOKEN&project=$PROJNAME" -O coverity_tool.tgz 108*9c263d07SPeter Maydell if ! (cat coverity_tool.md5.new; echo " coverity_tool.tgz") | md5sum -c --status; then 109*9c263d07SPeter Maydell echo "Downloaded tarball didn't match md5sum!" 110*9c263d07SPeter Maydell exit 1 111*9c263d07SPeter Maydell fi 112*9c263d07SPeter Maydell # extract the new one, keeping it corralled in a 'coverity_tool' directory 113*9c263d07SPeter Maydell echo "Unpacking coverity build tools..." 114*9c263d07SPeter Maydell mkdir -p coverity_tool 115*9c263d07SPeter Maydell cd coverity_tool 116*9c263d07SPeter Maydell tar xf ../coverity_tool.tgz 117*9c263d07SPeter Maydell cd .. 118*9c263d07SPeter Maydell mv coverity_tool.md5.new coverity_tool.md5 119*9c263d07SPeter Maydell fi 120*9c263d07SPeter Maydell 121*9c263d07SPeter Maydell rm -f coverity_tool.md5.new 122*9c263d07SPeter Maydell} 123*9c263d07SPeter Maydell 124*9c263d07SPeter Maydell 125*9c263d07SPeter Maydell# Check user-provided environment variables and arguments 126*9c263d07SPeter MaydellDRYRUN=no 127*9c263d07SPeter MaydellUPDATE_ONLY=no 128*9c263d07SPeter Maydell 129*9c263d07SPeter Maydellwhile [ "$#" -ge 1 ]; do 130*9c263d07SPeter Maydell case "$1" in 131*9c263d07SPeter Maydell --dry-run) 132*9c263d07SPeter Maydell shift 133*9c263d07SPeter Maydell DRYRUN=yes 134*9c263d07SPeter Maydell ;; 135*9c263d07SPeter Maydell --update-tools-only) 136*9c263d07SPeter Maydell shift 137*9c263d07SPeter Maydell UPDATE_ONLY=yes 138*9c263d07SPeter Maydell ;; 139*9c263d07SPeter Maydell --version) 140*9c263d07SPeter Maydell shift 141*9c263d07SPeter Maydell if [ $# -eq 0 ]; then 142*9c263d07SPeter Maydell echo "--version needs an argument" 143*9c263d07SPeter Maydell exit 1 144*9c263d07SPeter Maydell fi 145*9c263d07SPeter Maydell VERSION="$1" 146*9c263d07SPeter Maydell shift 147*9c263d07SPeter Maydell ;; 148*9c263d07SPeter Maydell --description) 149*9c263d07SPeter Maydell shift 150*9c263d07SPeter Maydell if [ $# -eq 0 ]; then 151*9c263d07SPeter Maydell echo "--description needs an argument" 152*9c263d07SPeter Maydell exit 1 153*9c263d07SPeter Maydell fi 154*9c263d07SPeter Maydell DESCRIPTION="$1" 155*9c263d07SPeter Maydell shift 156*9c263d07SPeter Maydell ;; 157*9c263d07SPeter Maydell --tokenfile) 158*9c263d07SPeter Maydell shift 159*9c263d07SPeter Maydell if [ $# -eq 0 ]; then 160*9c263d07SPeter Maydell echo "--tokenfile needs an argument" 161*9c263d07SPeter Maydell exit 1 162*9c263d07SPeter Maydell fi 163*9c263d07SPeter Maydell COVERITY_TOKEN="$(cat "$1")" 164*9c263d07SPeter Maydell shift 165*9c263d07SPeter Maydell ;; 166*9c263d07SPeter Maydell --srcdir) 167*9c263d07SPeter Maydell shift 168*9c263d07SPeter Maydell if [ $# -eq 0 ]; then 169*9c263d07SPeter Maydell echo "--srcdir needs an argument" 170*9c263d07SPeter Maydell exit 1 171*9c263d07SPeter Maydell fi 172*9c263d07SPeter Maydell SRCDIR="$1" 173*9c263d07SPeter Maydell shift 174*9c263d07SPeter Maydell ;; 175*9c263d07SPeter Maydell --results-tarball) 176*9c263d07SPeter Maydell shift 177*9c263d07SPeter Maydell if [ $# -eq 0 ]; then 178*9c263d07SPeter Maydell echo "--results-tarball needs an argument" 179*9c263d07SPeter Maydell exit 1 180*9c263d07SPeter Maydell fi 181*9c263d07SPeter Maydell RESULTSTARBALL="$1" 182*9c263d07SPeter Maydell shift 183*9c263d07SPeter Maydell ;; 184*9c263d07SPeter Maydell *) 185*9c263d07SPeter Maydell echo "Unexpected argument '$1'" 186*9c263d07SPeter Maydell exit 1 187*9c263d07SPeter Maydell ;; 188*9c263d07SPeter Maydell esac 189*9c263d07SPeter Maydelldone 190*9c263d07SPeter Maydell 191*9c263d07SPeter Maydellif [ -z "$COVERITY_TOKEN" ]; then 192*9c263d07SPeter Maydell echo "COVERITY_TOKEN environment variable not set" 193*9c263d07SPeter Maydell exit 1 194*9c263d07SPeter Maydellfi 195*9c263d07SPeter Maydell 196*9c263d07SPeter Maydellif [ -z "$COVERITY_BUILD_CMD" ]; then 197*9c263d07SPeter Maydell NPROC=$(nproc) 198*9c263d07SPeter Maydell COVERITY_BUILD_CMD="make -j$NPROC" 199*9c263d07SPeter Maydell echo "COVERITY_BUILD_CMD: using default '$COVERITY_BUILD_CMD'" 200*9c263d07SPeter Maydellfi 201*9c263d07SPeter Maydell 202*9c263d07SPeter Maydellif [ -z "$COVERITY_TOOL_BASE" ]; then 203*9c263d07SPeter Maydell echo "COVERITY_TOOL_BASE: using default /tmp/coverity-tools" 204*9c263d07SPeter Maydell COVERITY_TOOL_BASE=/tmp/coverity-tools 205*9c263d07SPeter Maydellfi 206*9c263d07SPeter Maydell 207*9c263d07SPeter Maydellif [ -z "$SRCDIR" ]; then 208*9c263d07SPeter Maydell SRCDIR="$PWD" 209*9c263d07SPeter Maydellfi 210*9c263d07SPeter Maydell 211*9c263d07SPeter MaydellPROJTOKEN="$COVERITY_TOKEN" 212*9c263d07SPeter MaydellPROJNAME=QEMU 213*9c263d07SPeter MaydellTARBALL=cov-int.tar.xz 214*9c263d07SPeter Maydell 215*9c263d07SPeter Maydell 216*9c263d07SPeter Maydellif [ "$UPDATE_ONLY" = yes ]; then 217*9c263d07SPeter Maydell # Just do the tools update; we don't need to check whether 218*9c263d07SPeter Maydell # we are in a source tree or have upload rights for this, 219*9c263d07SPeter Maydell # so do it before some of the command line and source tree checks. 220*9c263d07SPeter Maydell update_coverity_tools 221*9c263d07SPeter Maydell exit 0 222*9c263d07SPeter Maydellfi 223*9c263d07SPeter Maydell 224*9c263d07SPeter Maydellcd "$SRCDIR" 225*9c263d07SPeter Maydell 226*9c263d07SPeter Maydellecho "Checking this is a QEMU source tree..." 227*9c263d07SPeter Maydellif ! [ -e "$SRCDIR/VERSION" ]; then 228*9c263d07SPeter Maydell echo "Not in a QEMU source tree?" 229*9c263d07SPeter Maydell exit 1 230*9c263d07SPeter Maydellfi 231*9c263d07SPeter Maydell 232*9c263d07SPeter Maydell# Fill in defaults used by the non-update-only process 233*9c263d07SPeter Maydellif [ -z "$VERSION" ]; then 234*9c263d07SPeter Maydell VERSION="$(git describe --always HEAD)" 235*9c263d07SPeter Maydellfi 236*9c263d07SPeter Maydell 237*9c263d07SPeter Maydellif [ -z "$DESCRIPTION" ]; then 238*9c263d07SPeter Maydell DESCRIPTION="$(git rev-parse HEAD)" 239*9c263d07SPeter Maydellfi 240*9c263d07SPeter Maydell 241*9c263d07SPeter Maydellif [ -z "$COVERITY_EMAIL" ]; then 242*9c263d07SPeter Maydell COVERITY_EMAIL="$(git config user.email)" 243*9c263d07SPeter Maydellfi 244*9c263d07SPeter Maydell 245*9c263d07SPeter Maydellcheck_upload_permissions 246*9c263d07SPeter Maydell 247*9c263d07SPeter Maydellupdate_coverity_tools 248*9c263d07SPeter Maydell 249*9c263d07SPeter MaydellTOOLBIN="$(cd "$COVERITY_TOOL_BASE" && echo $PWD/coverity_tool/cov-analysis-*/bin)" 250*9c263d07SPeter Maydell 251*9c263d07SPeter Maydellif ! test -x "$TOOLBIN/cov-build"; then 252*9c263d07SPeter Maydell echo "Couldn't find cov-build in the coverity build-tool directory??" 253*9c263d07SPeter Maydell exit 1 254*9c263d07SPeter Maydellfi 255*9c263d07SPeter Maydell 256*9c263d07SPeter Maydellexport PATH="$TOOLBIN:$PATH" 257*9c263d07SPeter Maydell 258*9c263d07SPeter Maydellcd "$SRCDIR" 259*9c263d07SPeter Maydell 260*9c263d07SPeter Maydellecho "Doing make distclean..." 261*9c263d07SPeter Maydellmake distclean 262*9c263d07SPeter Maydell 263*9c263d07SPeter Maydellecho "Configuring..." 264*9c263d07SPeter Maydell# We configure with a fixed set of enables here to ensure that we don't 265*9c263d07SPeter Maydell# accidentally reduce the scope of the analysis by doing the build on 266*9c263d07SPeter Maydell# the system that's missing a dependency that we need to build part of 267*9c263d07SPeter Maydell# the codebase. 268*9c263d07SPeter Maydell./configure --disable-modules --enable-sdl --enable-gtk \ 269*9c263d07SPeter Maydell --enable-opengl --enable-vte --enable-gnutls \ 270*9c263d07SPeter Maydell --enable-nettle --enable-curses --enable-curl \ 271*9c263d07SPeter Maydell --audio-drv-list=oss,alsa,sdl,pa --enable-virtfs \ 272*9c263d07SPeter Maydell --enable-vnc --enable-vnc-sasl --enable-vnc-jpeg --enable-vnc-png \ 273*9c263d07SPeter Maydell --enable-xen --enable-brlapi \ 274*9c263d07SPeter Maydell --enable-linux-aio --enable-attr \ 275*9c263d07SPeter Maydell --enable-cap-ng --enable-trace-backends=log --enable-spice --enable-rbd \ 276*9c263d07SPeter Maydell --enable-xfsctl --enable-libusb --enable-usb-redir \ 277*9c263d07SPeter Maydell --enable-libiscsi --enable-libnfs --enable-seccomp \ 278*9c263d07SPeter Maydell --enable-tpm --enable-libssh --enable-lzo --enable-snappy --enable-bzip2 \ 279*9c263d07SPeter Maydell --enable-numa --enable-rdma --enable-smartcard --enable-virglrenderer \ 280*9c263d07SPeter Maydell --enable-mpath --enable-libxml2 --enable-glusterfs \ 281*9c263d07SPeter Maydell --enable-virtfs --enable-zstd 282*9c263d07SPeter Maydell 283*9c263d07SPeter Maydellecho "Making libqemustub.a..." 284*9c263d07SPeter Maydellmake libqemustub.a 285*9c263d07SPeter Maydell 286*9c263d07SPeter Maydellecho "Running cov-build..." 287*9c263d07SPeter Maydellrm -rf cov-int 288*9c263d07SPeter Maydellmkdir cov-int 289*9c263d07SPeter Maydellcov-build --dir cov-int $COVERITY_BUILD_CMD 290*9c263d07SPeter Maydell 291*9c263d07SPeter Maydellecho "Creating results tarball..." 292*9c263d07SPeter Maydelltar cvf - cov-int | xz > "$TARBALL" 293*9c263d07SPeter Maydell 294*9c263d07SPeter Maydellif [ ! -z "$RESULTSTARBALL" ]; then 295*9c263d07SPeter Maydell echo "Copying results tarball to $RESULTSTARBALL..." 296*9c263d07SPeter Maydell cp "$TARBALL" "$RESULTSTARBALL" 297*9c263d07SPeter Maydellfi 298*9c263d07SPeter Maydell 299*9c263d07SPeter Maydellecho "Uploading results tarball..." 300*9c263d07SPeter Maydell 301*9c263d07SPeter Maydellif [ "$DRYRUN" = yes ]; then 302*9c263d07SPeter Maydell echo "Dry run only, not uploading $TARBALL" 303*9c263d07SPeter Maydell exit 0 304*9c263d07SPeter Maydellfi 305*9c263d07SPeter Maydell 306*9c263d07SPeter Maydellcurl --form token="$PROJTOKEN" --form email="$COVERITY_EMAIL" \ 307*9c263d07SPeter Maydell --form file=@"$TARBALL" --form version="$VERSION" \ 308*9c263d07SPeter Maydell --form description="$DESCRIPTION" \ 309*9c263d07SPeter Maydell https://scan.coverity.com/builds?project="$PROJNAME" 310*9c263d07SPeter Maydell 311*9c263d07SPeter Maydellecho "Done." 312