From 5bb3e2be784275d3d9651ac5dac8ab82654de00a Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Thu, 18 Nov 2021 13:46:56 -0500 Subject: [PATCH] Record the errno if exec fails --- src/lib/Hydra/Plugin/RunCommand.pm | 4 +- src/lib/Hydra/Schema/Result/RunCommandLogs.pm | 5 +- t/plugins/RunCommand/errno.t | 50 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 t/plugins/RunCommand/errno.t diff --git a/src/lib/Hydra/Plugin/RunCommand.pm b/src/lib/Hydra/Plugin/RunCommand.pm index 6a997d17..1a122411 100644 --- a/src/lib/Hydra/Plugin/RunCommand.pm +++ b/src/lib/Hydra/Plugin/RunCommand.pm @@ -161,9 +161,9 @@ sub buildFinished { $runlog->started(); system("$command") == 0 - or warn "notification command '$command' failed with exit status $?\n"; + or warn "notification command '$command' failed with exit status $? ($!)\n"; - $runlog->completed_with_child_error($?); + $runlog->completed_with_child_error($?, $!); } } diff --git a/src/lib/Hydra/Schema/Result/RunCommandLogs.pm b/src/lib/Hydra/Schema/Result/RunCommandLogs.pm index bce53a9c..3a6ca9ae 100644 --- a/src/lib/Hydra/Schema/Result/RunCommandLogs.pm +++ b/src/lib/Hydra/Schema/Result/RunCommandLogs.pm @@ -197,7 +197,10 @@ sub completed_with_child_error { if ($child_error == -1) { # -1 indicates `exec` failed, and this is the only # case where the reported errno is valid. - $errno = $reported_errno; + # + # The `+ 0` is because $! is a dual var and likes to be a string + # if it can. +0 forces it to not be. Sigh. + $errno = $reported_errno + 0; } if (WIFEXITED($child_error)) { diff --git a/t/plugins/RunCommand/errno.t b/t/plugins/RunCommand/errno.t new file mode 100644 index 00000000..35fea599 --- /dev/null +++ b/t/plugins/RunCommand/errno.t @@ -0,0 +1,50 @@ +use feature 'unicode_strings'; +use strict; +use warnings; +use JSON::MaybeXS; +use Setup; + +my %ctx = test_init( + hydra_config => q| + + command = invalid-command-this-does-not-exist + +|); + +require Hydra::Schema; +require Hydra::Model::DB; + +use Test2::V0; + +my $db = Hydra::Model::DB->new; +hydra_setup($db); + +my $project = $db->resultset('Projects')->create({name => "tests", displayname => "", owner => "root"}); + +# Most basic test case, no parameters +my $jobset = createBaseJobset("basic", "runcommand.nix", $ctx{jobsdir}); + +ok(evalSucceeds($jobset), "Evaluating jobs/runcommand.nix should exit with return code 0"); +is(nrQueuedBuildsForJobset($jobset), 1, "Evaluating jobs/runcommand.nix should result in 1 build1"); + +(my $build) = queuedBuildsForJobset($jobset); + +is($build->job, "metrics", "The only job should be metrics"); +ok(runBuild($build), "Build should exit with return code 0"); +my $newbuild = $db->resultset('Builds')->find($build->id); +is($newbuild->finished, 1, "Build should be finished."); +is($newbuild->buildstatus, 0, "Build should have buildstatus 0."); + +ok(sendNotifications(), "Notifications execute successfully."); + +subtest "Validate a run log was created" => sub { + my $runlog = $build->runcommandlogs->find({}); + is($runlog->job_matcher, "*:*:*", "An unspecified job matcher is defaulted to *:*:*"); + is($runlog->command, 'invalid-command-this-does-not-exist', "The executed command is saved."); + is($runlog->start_time, within(time() - 1, 2), "The start time is recent."); + is($runlog->end_time, within(time() - 1, 2), "The end time is also recent."); + is($runlog->exit_code, undef, "This command should not have executed."); + is($runlog->error_number, 2, "This command failed to exec."); +}; + +done_testing;