From fc00fa20d295e4b608c1e8985b723be50dbe5256 Mon Sep 17 00:00:00 2001 From: Alex Tereschenko Date: Sat, 10 Jun 2017 20:23:50 +0200 Subject: [PATCH] static code analysis: introduce automated scans via SonarCloud This adds Travis and Docker configurations for automated scans, both for master branch and internal PRs. External PRs won't be checked due to security concerns (and Travis limitation related to that) - GH and SonarCloud tokens are not propagated to those. An organization and project must be created in SonarCloud for reporting, as well as a technical GH user with mraa repo commit permission, to set PR statuses in the "checks" section. Signed-off-by: Alex Tereschenko --- .dockerignore | 2 ++ .travis.yml | 3 ++ Dockerfile | 20 +++++++++++-- docker-compose.yaml | 22 +++++++++++++++ sonar-scan.sh | 68 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+), 3 deletions(-) create mode 100755 sonar-scan.sh diff --git a/.dockerignore b/.dockerignore index 0274e0a..d7d615e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,4 @@ Dockerfile docker-compose.yaml +.scannerwork/ +.vscode/ diff --git a/.travis.yml b/.travis.yml index af6140d..9f5ecb9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ env: - TARGET=java BUILDARCH=MOCK - TARGET=node4 BUILDARCH=MOCK - TARGET=node5 BUILDARCH=MOCK + - TARGET=sonar-scan matrix: exclude: @@ -32,6 +33,8 @@ matrix: env: TARGET=java JSONPLAT=ON - compiler: clang env: TARGET=java BUILDARCH=MOCK + - compiler: clang + env: TARGET=sonar-scan allow_failures: - compiler: gcc env: TARGET=node4 JSONPLAT=ON diff --git a/Dockerfile b/Dockerfile index 299b421..ce7dfa7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN apt-get -y update && \ # Install apt-utils apt-get -y --no-install-recommends install apt-utils && \ # Main Build Dependencies - apt-get -y --no-install-recommends install git build-essential cmake clang-3.8 g++-4.8 wget libpcre3 libpcre3-dev \ + apt-get -y --no-install-recommends install git build-essential cmake clang-3.8 g++-4.8 wget unzip libpcre3 libpcre3-dev \ # Docs Build Dependencies python-sphinx doxygen graphviz \ # Python Build Dependencies @@ -25,8 +25,22 @@ RUN wget http://iotdk.intel.com/misc/tr/swig-3.0.10.tar.gz && \ # Node.js Build Dependencies RUN wget -q -O - https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash +# Static code analysis scanner +ENV SONAR_DIR /usr/sonar +ENV SONAR_VER "3.0.3.778" +WORKDIR $SONAR_DIR + +RUN wget https://sonarsource.bintray.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_VER}-linux.zip && \ + wget https://sonarqube.com/static/cpp/build-wrapper-linux-x86.zip && \ + unzip sonar-scanner-cli-${SONAR_VER}-linux.zip && \ + unzip build-wrapper-linux-x86.zip && \ + rm sonar-scanner-cli-${SONAR_VER}-linux.zip build-wrapper-linux-x86.zip + +ENV PATH $SONAR_DIR/sonar-scanner-${SONAR_VER}-linux/bin:$SONAR_DIR/build-wrapper-linux-x86:$PATH + # Set Workdir -WORKDIR /usr/src/app +ARG MRAA_SRC_DIR +WORKDIR $MRAA_SRC_DIR # Configure Build Arguments ARG BUILDARCH @@ -72,7 +86,7 @@ RUN tr -d "\r" < src/doxy2swig.py > src/_doxy2swig.py && \ chmod u+x src/doxy2swig.py # Change Workdir to build directory -WORKDIR /usr/src/app/build +WORKDIR $MRAA_SRC_DIR/build # Run cmake RUN . $NVM_DIR/nvm.sh && cmake \ diff --git a/docker-compose.yaml b/docker-compose.yaml index 98f83c9..3122a88 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -31,10 +31,20 @@ services: - CXX=${CXX:-clang++-3.8} - NODE_VERSION=${NODE_VERSION:-v4.4.7} - BUILDARCH=${BUILDARCH} + - MRAA_SRC_DIR=${MRAA_SRC_DIR:-/usr/src/app} environment: - http_proxy - https_proxy - no_proxy + - MRAA_SRC_DIR=/usr/src/app + - SONAR_TOKEN + - SONAR_ORG + - SONAR_PROJ_KEY + - TRAVIS_BRANCH + - TRAVIS_PULL_REQUEST + - TRAVIS_REPO_SLUG + - TRAVIS_PULL_REQUEST_SLUG + - GITHUB_TOKEN doc: extends: main @@ -82,3 +92,15 @@ services: build: args: - NODE_VERSION=v5.12.0 + + sonar-scan: + extends: main + build: + args: + - BUILDSWIG=ON + - BUILDSWIGPYTHON=ON + - BUILDSWIGNODE=ON + - BUILDSWIGJAVA=ON + - ONEWIRE=ON + - JSONPLAT=ON + command: bash -c "$${MRAA_SRC_DIR}/sonar-scan.sh" diff --git a/sonar-scan.sh b/sonar-scan.sh new file mode 100755 index 0000000..e8f2c18 --- /dev/null +++ b/sonar-scan.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# +# The script is used for determining options and running a static code +# analysis scan via SonarCloud. +# +# Author: Alex Tereschenko +# +# All environment variables used are passed from either Travis or docker-compose. +# See details at https://docs.sonarqube.org/display/SONAR/Analysis+Parameters. +# +# Travis ones are: +# Created by us: +# - SONAR_ORG - SonarCloud "organization", under which the project is located. +# - SONAR_PROJ_KEY - SonarCloud project key (name) to report to. +# - SONAR_TOKEN - access token for that project (must be protected in Travis). +# - GITHUB_TOKEN - GH OAuth token used by SonarCloud's GH plugin to report status in PRs. +# See details at https://docs.sonarqube.org/display/PLUG/GitHub+Plugin. Must be protected. +# Default: +# - All TRAVIS_* variables. They are described in Travis docs +# at https://docs.travis-ci.com/user/environment-variables +# +# docker-compose ones are: +# - MRAA_SRC_DIR - path to mraa's git clone in the Docker container. + +bw_output_path="${MRAA_SRC_DIR}/build/bw-output" + +sonar_cmd_base="build-wrapper-linux-x86-64 --out-dir ${bw_output_path} make clean all && \ + sonar-scanner \ + --debug \ + -Dsonar.projectKey=${SONAR_PROJ_KEY} \ + -Dsonar.projectBaseDir=${MRAA_SRC_DIR} \ + -Dsonar.sources=${MRAA_SRC_DIR} \ + -Dsonar.inclusions='api/**/*,CMakeLists.txt,examples/**/*,imraa/**/*,include/**/*,src/**/*,tests/**/*' \ + -Dsonar.coverage.exclusions='**/*' \ + -Dsonar.cfamily.build-wrapper-output=${bw_output_path} \ + -Dsonar.host.url=https://sonarqube.com \ + -Dsonar.organization=${SONAR_ORG} \ + -Dsonar.login=${SONAR_TOKEN} \ +" + +# Some useful data for logs +echo "TRAVIS_BRANCH: ${TRAVIS_BRANCH}" +echo "TRAVIS_PULL_REQUEST: ${TRAVIS_PULL_REQUEST}" +echo "TRAVIS_PULL_REQUEST_SLUG: ${TRAVIS_PULL_REQUEST_SLUG}" +echo "TRAVIS_REPO_SLUG: ${TRAVIS_REPO_SLUG}" + +if [ "${TRAVIS_BRANCH}" == "master" -a "${TRAVIS_PULL_REQUEST}" == "false" ]; then + # Master branch push - do a full-blown scan + echo "Performing master branch push scan" + sonar_cmd="${sonar_cmd_base}" +elif [ "${TRAVIS_PULL_REQUEST}" != "false" -a "${TRAVIS_PULL_REQUEST_SLUG}" == "${TRAVIS_REPO_SLUG}" ]; then + # Internal PR - do a preview scan with report to the PR + echo "Performing internal pull request scan" + sonar_cmd="${sonar_cmd_base} \ + -Dsonar.analysis.mode=preview \ + -Dsonar.github.pullRequest=${TRAVIS_PULL_REQUEST} \ + -Dsonar.github.repository=${TRAVIS_REPO_SLUG} \ + -Dsonar.github.oauth=${GITHUB_TOKEN} \ + " +else + echo "Skipping the scan - external pull request or non-master branch push" + exit 0 +fi + +echo "About to run the scan, the command is:" +echo "${sonar_cmd}" + +eval "${sonar_cmd}"