Add a plugin to execute arbitrary commands when a build finishes

[?]
Aug 1, 2018, 5:40 PM
6ZXL5UOPGRFVDX42LMO72HWDMH6YLR3FOH5NC75TSMTUC5HQI46QC

Dependencies

Change contents

  • file addition: RunCommand.pm (----------)
    [2.1]
    package Hydra::Plugin::RunCommand;
    use strict;
    use parent 'Hydra::Plugin';
    use experimental 'smartmatch';
    use JSON;
    sub configSectionMatches {
    my ($name, $project, $jobset, $job) = @_;
    my @elems = split ':', $name;
    die "invalid section name '$name'\n" if scalar(@elems) > 3;
    my $project2 = $elems[0] // "*";
    return 0 if $project2 ne "*" && $project ne $project2;
    my $jobset2 = $elems[1] // "*";
    return 0 if $jobset2 ne "*" && $jobset ne $jobset2;
    my $job2 = $elems[2] // "*";
    return 0 if $job2 ne "*" && $job ne $job2;
    return 1;
    }
    sub eventMatches {
    my ($cfg, $event) = @_;
    for my $x (split " ", ($cfg->{events} // "buildFinished")) {
    return 1 if $x eq $event;
    }
    return 0;
    }
    sub buildFinished {
    my ($self, $build, $dependents) = @_;
    my $event = "buildFinished";
    my $config = $self->{config}->{runcommand} // [];
    my $tmp;
    foreach my $cfg (@$config) {
    next unless eventMatches($cfg, $event);
    next unless configSectionMatches(
    $cfg->{job} // "*:*:*",
    $build->get_column('project'),
    $build->get_column('jobset'),
    $build->get_column('job'));
    my $command = $cfg->{command} // die "<runcommand> section lacks a 'command' option";
    unless (defined $tmp) {
    $tmp = File::Temp->new(SUFFIX => '.json');
    my $json = {
    event => $event,
    build => $build->id,
    finished => $build->get_column('finished'),
    timestamp => $build->get_column('timestamp'),
    project => $build->get_column('project'),
    jobset => $build->get_column('jobset'),
    job => $build->get_column('job'),
    drvPath => $build->get_column('drvpath'),
    startTime => $build->get_column('starttime'),
    stopTime => $build->get_column('stoptime'),
    buildStatus => $build->get_column('buildstatus'),
    outputs => [],
    products => [],
    metrics => [],
    };
    for my $output ($build->buildoutputs) {
    my $j = {
    name => $output->name,
    path => $output->path,
    };
    push @{$json->{outputs}}, $j;
    }
    for my $product ($build->buildproducts) {
    my $j = {
    productNr => $product->productnr,
    type => $product->type,
    subtype => $product->subtype,
    fileSize => $product->filesize,
    sha1hash => $product->sha1hash,
    sha256hash => $product->sha256hash,
    path => $product->path,
    name => $product->name,
    defaultPath => $product->defaultpath,
    };
    push @{$json->{products}}, $j;
    }
    for my $metric ($build->buildmetrics) {
    my $j = {
    name => $metric->name,
    unit => $metric->unit,
    value => $metric->value,
    };
    push @{$json->{metrics}}, $j;
    }
    print $tmp encode_json($json) or die;
    }
    $ENV{"HYDRA_JSON"} = $tmp->filename;
    system("$command") == 0
    or warn "notification command '$command' failed with exit status $?\n";
    }
    }
    1;