AppVeyor is an awesome SaaS1 CI2 server similar to Travis CI but for Windows developers. It enables you to build, test and deploy all sorts of projects: C/C++, .NET, IIS, SQL Server, WiX, among others (see Installed Software). Moreover, it is completely free for open source projects.
Coverity Scan is a free SaaS version of Coverity, static code analysis solution for C/C++, C# and Java. Coverity Scan is used by some major Open Source projects such as Linux, Python, PostgreSQL, Apache Software Foundation projects.
Unlike Travis CI, AppVeyor currently lacks out of the box integration with Coverity Scan. In this article I’ll show you how to enable Coverity Scan code analysis for your project by injecting custom PowerShell scripts into AppVeyor build process.
The rest of the article assumes that you have a GitHub repository registered with both AppVeyor and Coverity Scan, and you are familiar with Coverity Scan workflow (i.e. manually building your project with Coverity Build Tool and submitting results to Coverity Scan server).
The Necessary Steps
Analysing project source code with Coverity Scan involves the following steps:
- Download Coverity Build Tool.
- Build project with Coverity Build Tool.
- Compress scan data.
- Upload scan data to Coverity Scan server.
A Note on Scan Data Submissions Frequency
One important thing to note when working with Coverity Scan is build submissions frequency. Coverity Scan limits maximum number of submitted builds on daily and weekly basis. But even with limits left out of scope it is probably impractical to run each and every build with Coverity Scan since it takes noticeably longer time to complete. Let’s see how we can deal with it.
Using Dedicated Branch
Coverity Scan documentation suggests us to create a separate branch dedicated for code analysis (let’s call it analyse). In that case, we can conditionally enable Coverity Scan when building our project using
APPVEYOR_REPO_BRANCH built‐in environment variable. Personally, I find this approach somewhat inconvenient: we need to keep our analyse branch in sync with develop branch (although this can be automated if necessary).
Using Scheduled Builds
Alternatively, we can use AppVeyor Scheduled Builds feature to run Coverity Scan. For example, I use the following crontab expression to launch Coverity build at 5:00 p.m. UTC+03 on Friday:
0 14 * * 5. Also there is a handy built‐in variable named
APPVEYOR_SCHEDULED_BUILD which is set to
True when the build is a scheduled one. I find this approach more convenient, so I’ll stick to it for the rest of the article.
Downloading Coverity Build Tool
The first step may sound simple, but one does not simply download Coverity Build Tool. First, for security and legal reasons you need to pass your Coverity Scan project name and token as part of download request. Second, the download link is specific to you project language. See more on Coverity Community discussion page.
We will use PowerShell, and the right place to put our script is
install hook in
Let’s deal with input data.
The Project name is your Coverity Scan project name as seen in web UI. Usually it’s the same as GitHub project name (
owner-name/repo-name), in which case you can use convinient
APPVEYOR_REPO_NAME built‐in variable for it.
The Project token is used by Coverity Scan for automated build submissions. You can examine and regenerate it in your Coverity Scan web GUI Project Settings page. The token is meant to be kept in secret, so it is a good practice to use AppVeyor Secure Variables feature to encrypt it:
The Download link can be obtained from your Coverity Scan web GUI Submit Build page. Choose link for
Win64 platform (AppVeyor build worker is 64‐bit Windows Server). In my case (the project language is
C++), the download link is
Now we can craft the HTTP request with the help of Invoke-WebRequest cmdlet:
Building Project with Coverity Build Tool
The next step is to build the project with Coverity Build Tool. This means passing your build command to
cov-int is a name of directory to place collected scan data into.
For example, if your build command is
Then, corresponding Coverity Build command becomes
For this to work we need to drop AppVeyor built‐in MSBuild support in favour of custom build script:
The actual PowerShell code snippet:
Things to note here:
- I’m using predefined
PLATFORMvariables to simulate behaviour of AppVeyour buit-in MSBuild provider.
- The directory
cov-analysis-win64-7.6.0is created by extracting Coverity Build Tool ZIP archive on the previous step.
- After building the project with Coverity Build Tool there will be directory named
Compressing Scan Data
Coverity Scan requires the scan data collected during build to be compressed. We can easily do this with 7‐Zip which comes pre‐installed on AppVeyor build worker. However, I’ll demonstrate you pure PowerShell/.NET way of doing this which involves some nasty .NET bug and one cool PowerShell trick to workaround it.
Currently, the only way to create ZIP archive in PowerShell which is available out of the box (that I’m aware of) is to use .NET System.IO.Compression.ZipFile API:
Unfortunately, if you try to upload ZIP file created with
IO.Compression.ZipFile the analysis will fail. The reason is a bug in
IO.Compression.ZipFile implementation due to which file names inside ZIP archive are encoded with backslashes as path separators (according to ZIP format specification
all slashes MUST be forward slashes “/” as opposed to backwards slashes “\”). As a result, such an archive cannot be unpacked on *nix systems (Coverity Scan is using Ubuntu currently).
To workaround the bug, we need to create custom encoder for ZIP file name entries, which means defining .NET class. Can we do this from PowerShell script? Yep, we can!
Things to note:
Add-Type -TypeDefinition $zipEncoderDefdefines new C# class, a custom encoder which replaces back slashes with forward slashes. The object of this class is passed as last parameter to
- The fourth parameter of
trueto indicate that
$env:APPVEYOR_BUILD_FOLDER\cov-intdirectory must be included into archive as a root directory (otherwise, only content of
cov-intis included). That is required by Coverity Scan.
- After compressing the scan data there will be file named
Uploading Scan Data to Coverity Scan Server
That last step is the most complex one. In order to upload scan data to Coverity Scan server we need to send multipart/form‐data3 HTML form containing archived scan data along with some build metadata (the process is documented in Upload a Project Build page of your Coverity Scan project web GUI). This can be accomplished in many ways, I’ll use [System.Net.Http.MultipartFormDataContent][url-dotnet-multipart-form‐data].
First, we need to initialize
$client.Timeout value must be large enough for the form to upload, otherwise exception will be thrown while sending data.
Next, we’ll fill form fields one by one. Those fields are token, email, file, version and description.
The Token Field
The token is our Coverity Scan project token we used before to download Coverity Build Tool.
The Email Field
The email is an email address to which Coverity Scan should send a notification about analysis results.
I recommend you to secure your email:
The File Field
The file is our zipped scan data produced earlier:
The Version Field
Your need to set this field to the version of your build:
The Description Field
An arbitrary text describing your build:
Finally, we can submit the form:
Things to note:
- We need to pass the project name in
owner-name/repo-nameformat in the query string.
- On timeout
Examining the Results
After uploading the scan data you can examine intermediate results in your Coverity Scan project web GUI, and the final results will be delivered to you by email. Then use View Defects button in Coverity Scan web GUI to start triaging discovered issues.
Here is full appveyor.yml utilising the approach described in the article.