This adds a Hydra plugin for users to submit their open source projects to the Coverity Scan system for analysis.
First, add a <coverityscan> section to your Hydra config, including the access token, project name, and email, and a regex specifying jobs to upload:
<coverityscan>
project = testrix
jobs = foobar:.*:coverity.*
email = aseipp@pobox.com
token = ${builtins.readFile ./coverity-token}
</coverityscan>
This will upload the scan results for any job whose name matches 'coverity.*' in any jobset in the Hydra 'foobar' project, for the Coverity Scan project named 'testrix'.
Note that one upload will occur per job matched by the regular expression - so be careful with how many builds you upload.
The jobs which are matched by the jobs specification must have a file in their output path of the form:
$out/tarballs/…-cov-int.(xz|lzma|zip|bz2|tgz)
The file must have the 'cov-int' directory produced by cov-build in
the root.
(You can also output something into $out/nix-support/hydra-build-products for the Hydra UI.)
This file will be found in the store, and uploaded to the service directly using your access credentials. Note the exact extension: don't use .tar.xz, only use .xz specifically.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
THUMRES3YYSVMQUJVIF7KWGJAOWVKJ3T5TDBOZIDW63RSHZ57SKQC package Hydra::Plugin::CoverityScan;use strict;use feature 'switch';use parent 'Hydra::Plugin';use File::Basename;use LWP::UserAgent;use Hydra::Helper::CatalystUtils;sub buildFinished {my ($self, $b, $dependents) = @_;my $cfg = $self->{config}->{coverityscan};my @config = defined $cfg ? ref $cfg eq "ARRAY" ? @$cfg : ($cfg) : ();# Scan the job and see if it matches any of the Coverity Scan projectsmy $proj;my $jobName = showJobName $b;foreach my $p (@config) {next unless $jobName =~ /^$p->{jobs}$/;# If build is cancelled or aborted, do not upload buildnext if $b->buildstatus == 4 || $b->buildstatus == 3;# Otherwise, select this Coverity project$proj = $p; last;}# Bail if there's no matching projectreturn unless defined $proj;# Compile submission informationmy $project = $proj->{project};my $email = $proj->{email};my $token = $proj->{token};my $scanurl = $proj->{scanurl} || "http://scan5.coverity.com/cgi-bin/upload.py";# Sanity checksdie "coverity project name not configured" unless defined $project;die "email must be specified for Coverity project '".$project."'"unless defined $email;die "access token must be specified for Coverity project '".$project."'"unless defined $token;# Get tarball locationsmy $storePath = ($b->buildoutputs)[0]->path;my $tarballs = "$storePath/tarballs";my $covTarball;opendir TARBALLS, $tarballs or die;while (readdir TARBALLS) {next unless $_ =~ /.*-coverity-int\.(tgz|lzma|xz|bz2|zip)$/;$covTarball = "$tarballs/$_"; last;}closedir TARBALLS;unless (defined $covTarball) {print STDERR "CoverityScan.pm: Coverity tarball not found in $tarballs; skipping upload...\n";return;}# Find the file mimetypemy @exts = qw(.xz .bz2 .lzma .zip .tgz);my ($dir, $file, $ext) = fileparse($covTarball, @exts);my $mimetype;given ($ext) {when ('.xz') { $mimetype = "application/x-xz"; }when ('.lzma') { $mimetype = "application/x-xz"; }when ('.zip') { $mimetype = "application/zip"; }when ('.bz2') { $mimetype = "application/x-bzip2"; }when ('.tgz') { $mimetype = "application/x-gzip"; }default { die "couldn't parse extension of $covTarball"; }}die "couldn't detect mimetype of $covTarball" unless defined $mimetype;# Parse version number from tarballmy $pkgNameRE = "(?:(?:[A-Za-z0-9]|(?:-[^0-9]))+)";my $versionRE = "(?:[A-Za-z0-9\.\-]+)";my $shortName = basename($covTarball);my $version = $2 if $shortName =~ /^($pkgNameRE)-($versionRE)-coverity-int.*$/;die "CoverityScan.pm: Couldn't parse build version for upload! ($shortName)"unless defined $version;# Submit buildmy $jobid = $b->id;my $desc = "Hydra Coverity Build ($jobName) - $jobid:$version";print STDERR "uploading $desc ($shortName) to Coverity Scan\n";my $ua = LWP::UserAgent->new();my $resp = $ua->post($scanurl,Content_Type => 'form-data',Content => [project => $project,email => $email,token => $token,version => $version,description => $desc,file => [ $covTarball, $shortName,Content_Type => $mimetype,],],);# The Coverity HTTP endpoint doesn't handle errors very well, and always# returns a 200 :(my $results = $resp->decoded_content;if ($results =~ /ERROR!/) {print STDERR "CoverityScan.pm: upload error - ", $resp->decoded_content, "\n";return;}# Just for sanity, in case things change laterunless ($results =~ /Your request has been submitted/) {print STDERR "CoverityScan.pm: upload error, didn't find expected response - ", $resp->decoded_content, "\n";}}1;