Merge pull request #1137 from DeterminateSystems/runcommand-logs
Store and display the output of RunCommands
This commit is contained in:
@ -126,23 +126,35 @@ sub view_nixlog : Chained('buildChain') PathPart('nixlog') {
|
||||
|
||||
$c->stash->{step} = $step;
|
||||
|
||||
showLog($c, $mode, $step->busy == 0, $step->drvpath);
|
||||
my $drvPath = $step->drvpath;
|
||||
my $log_uri = $c->uri_for($c->controller('Root')->action_for("log"), [basename($drvPath)]);
|
||||
showLog($c, $mode, $log_uri);
|
||||
}
|
||||
|
||||
|
||||
sub view_log : Chained('buildChain') PathPart('log') {
|
||||
my ($self, $c, $mode) = @_;
|
||||
showLog($c, $mode, $c->stash->{build}->finished,
|
||||
$c->stash->{build}->drvpath);
|
||||
|
||||
my $drvPath = $c->stash->{build}->drvpath;
|
||||
my $log_uri = $c->uri_for($c->controller('Root')->action_for("log"), [basename($drvPath)]);
|
||||
showLog($c, $mode, $log_uri);
|
||||
}
|
||||
|
||||
|
||||
sub view_runcommandlog : Chained('buildChain') PathPart('runcommandlog') {
|
||||
my ($self, $c, $uuid, $mode) = @_;
|
||||
|
||||
my $log_uri = $c->uri_for($c->controller('Root')->action_for("runcommandlog"), $uuid);
|
||||
showLog($c, $mode, $log_uri);
|
||||
$c->stash->{template} = 'runcommand-log.tt';
|
||||
$c->stash->{runcommandlog} = $c->stash->{build}->runcommandlogs->find({ uuid => $uuid });
|
||||
}
|
||||
|
||||
|
||||
sub showLog {
|
||||
my ($c, $mode, $finished, $drvPath) = @_;
|
||||
my ($c, $mode, $log_uri) = @_;
|
||||
$mode //= "pretty";
|
||||
|
||||
my $log_uri = $c->uri_for($c->controller('Root')->action_for("log"), [basename($drvPath)]);
|
||||
|
||||
if ($mode eq "pretty") {
|
||||
$c->stash->{log_uri} = $log_uri;
|
||||
$c->stash->{template} = 'log.tt';
|
||||
|
@ -530,4 +530,23 @@ sub log :Local :Args(1) {
|
||||
}
|
||||
}
|
||||
|
||||
sub runcommandlog :Local :Args(1) {
|
||||
my ($self, $c, $uuid) = @_;
|
||||
|
||||
my $tail = $c->request->params->{"tail"};
|
||||
|
||||
die if defined $tail && $tail !~ /^[0-9]+$/;
|
||||
|
||||
my $runlog = $c->model('DB')->resultset('RunCommandLogs')->find({ uuid => $uuid })
|
||||
or notFound($c, "The RunCommand log is not available.");
|
||||
|
||||
my $logFile = constructRunCommandLogPath($runlog);
|
||||
if (-f $logFile) {
|
||||
serveLogFile($c, $logFile, $tail);
|
||||
return;
|
||||
} else {
|
||||
notFound($c, "The RunCommand log is not available.");
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -13,12 +13,14 @@ use Nix::Store;
|
||||
use Encode;
|
||||
use Sys::Hostname::Long;
|
||||
use IPC::Run;
|
||||
use UUID4::Tiny qw(is_uuid4_string);
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(
|
||||
cancelBuilds
|
||||
captureStdoutStderr
|
||||
captureStdoutStderrWithStdin
|
||||
constructRunCommandLogPath
|
||||
findLog
|
||||
gcRootFor
|
||||
getBaseUrl
|
||||
@ -589,4 +591,18 @@ sub isLocalStore {
|
||||
}
|
||||
|
||||
|
||||
sub constructRunCommandLogPath {
|
||||
my ($runlog) = @_;
|
||||
my $uuid = $runlog->uuid;
|
||||
|
||||
if (!is_uuid4_string($uuid)) {
|
||||
die "UUID was invalid."
|
||||
}
|
||||
|
||||
my $hydra_path = Hydra::Model::DB::getHydraPath;
|
||||
my $bucket = substr($uuid, 0, 2);
|
||||
|
||||
return "$hydra_path/runcommand-logs/$bucket/$uuid";
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -5,6 +5,10 @@ use warnings;
|
||||
use parent 'Hydra::Plugin';
|
||||
use experimental 'smartmatch';
|
||||
use JSON::MaybeXS;
|
||||
use File::Basename qw(dirname);
|
||||
use File::Path qw(make_path);
|
||||
use IPC::Run3;
|
||||
use Try::Tiny;
|
||||
|
||||
sub isEnabled {
|
||||
my ($self) = @_;
|
||||
@ -160,10 +164,31 @@ sub buildFinished {
|
||||
|
||||
$runlog->started();
|
||||
|
||||
system("$command") == 0
|
||||
or warn "notification command '$command' failed with exit status $? ($!)\n";
|
||||
my $logPath = Hydra::Helper::Nix::constructRunCommandLogPath($runlog) or die "RunCommandLog not found.";
|
||||
my $dir = dirname($logPath);
|
||||
my $oldUmask = umask();
|
||||
my $f;
|
||||
|
||||
$runlog->completed_with_child_error($?, $!);
|
||||
try {
|
||||
# file: 640, dir: 750
|
||||
umask(0027);
|
||||
make_path($dir);
|
||||
|
||||
open($f, '>', $logPath);
|
||||
umask($oldUmask);
|
||||
|
||||
run3($command, \undef, $f, $f, { return_if_system_error => 1 }) == 1
|
||||
or warn "notification command '$command' failed with exit status $? ($!)\n";
|
||||
|
||||
close($f);
|
||||
|
||||
$runlog->completed_with_child_error($?, $!);
|
||||
1;
|
||||
} catch {
|
||||
die "Died while trying to process RunCommand (${\$runlog->uuid}): $_";
|
||||
} finally {
|
||||
umask($oldUmask);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,12 @@ __PACKAGE__->table("runcommandlogs");
|
||||
is_nullable: 0
|
||||
sequence: 'runcommandlogs_id_seq'
|
||||
|
||||
=head2 uuid
|
||||
|
||||
data_type: 'uuid'
|
||||
is_nullable: 0
|
||||
size: 16
|
||||
|
||||
=head2 job_matcher
|
||||
|
||||
data_type: 'text'
|
||||
@ -98,6 +104,8 @@ __PACKAGE__->add_columns(
|
||||
is_nullable => 0,
|
||||
sequence => "runcommandlogs_id_seq",
|
||||
},
|
||||
"uuid",
|
||||
{ data_type => "uuid", is_nullable => 0, size => 16 },
|
||||
"job_matcher",
|
||||
{ data_type => "text", is_nullable => 0 },
|
||||
"build_id",
|
||||
@ -130,6 +138,20 @@ __PACKAGE__->add_columns(
|
||||
|
||||
__PACKAGE__->set_primary_key("id");
|
||||
|
||||
=head1 UNIQUE CONSTRAINTS
|
||||
|
||||
=head2 C<runcommandlogs_uuid_unique>
|
||||
|
||||
=over 4
|
||||
|
||||
=item * L</uuid>
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->add_unique_constraint("runcommandlogs_uuid_unique", ["uuid"]);
|
||||
|
||||
=head1 RELATIONS
|
||||
|
||||
=head2 build
|
||||
@ -148,10 +170,31 @@ __PACKAGE__->belongs_to(
|
||||
);
|
||||
|
||||
|
||||
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2021-11-19 15:15:36
|
||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:9AIzlQl1RjRXrs9gQCZKVw
|
||||
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-01-24 10:24:52
|
||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZVpYU6k3d/k/nitjpdgf/A
|
||||
|
||||
use POSIX qw(WEXITSTATUS WIFEXITED WIFSIGNALED WTERMSIG);
|
||||
use UUID4::Tiny qw(create_uuid_string);
|
||||
|
||||
|
||||
=head2 new
|
||||
|
||||
Initialize a new row object.
|
||||
|
||||
Sets the UUID automatically unless a UUID is specified in the attributes.
|
||||
|
||||
=cut
|
||||
sub new {
|
||||
my ($class, $attrs) = @_;
|
||||
|
||||
if (!defined $attrs->{uuid}) {
|
||||
$attrs->{uuid} = create_uuid_string();
|
||||
}
|
||||
|
||||
my $new = $class->next::method($attrs);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
=head2 started
|
||||
|
||||
|
Reference in New Issue
Block a user