diff --git a/assets/javascripts/overview.js b/assets/javascripts/overview.js index 0e64463ab41..eddcb936e13 100644 --- a/assets/javascripts/overview.js +++ b/assets/javascripts/overview.js @@ -289,6 +289,7 @@ function showAddCommentsDialog() { function addComments(form) { const text = form.elements.text.value; + let restartRequested = document.getElementById('restartRequestedCheck').checked ? 1 : 0; if (!text.length) { return window.alert("The comment text mustn't be empty."); } @@ -301,10 +302,15 @@ function addComments(form) { controls.style.display = 'inline'; window.addCommentsModal.hide(); }; + const formData = new FormData(form); + formData.append('restartRequested', restartRequested); + $.ajax({ url: form.action, method: 'POST', - data: $(form).serialize(), + data: formData, + processData: false, // Important to prevent jQuery from processing the data + contentType: false, success: response => { addFlash( 'info', diff --git a/lib/OpenQA/WebAPI/Controller/API/V1/Comment.pm b/lib/OpenQA/WebAPI/Controller/API/V1/Comment.pm index 7d647774c21..b37107271f3 100644 --- a/lib/OpenQA/WebAPI/Controller/API/V1/Comment.pm +++ b/lib/OpenQA/WebAPI/Controller/API/V1/Comment.pm @@ -168,13 +168,15 @@ sub create_many ($self) { my $validation = $self->validation; $validation->required('text')->like(qr/^(?!\s*$).+/); $validation->required('job_id')->num(0, undef); + $validation->optional('restartRequested')->in(0, 1); return $self->reply->validation_error({format => 'json'}) if $validation->has_error; my $text = $validation->param('text'); my $job_ids = $validation->every_param('job_id'); + my $wanna_restart = $validation->param('restartRequested'); my $schema = $self->schema; my $comments = $schema->resultset('Comments'); - my (@created, @failed); + my (@created, @failed, @failed_restart); for my $job_id (@$job_ids) { my $txn_guard = $schema->txn_scope_guard; eval { @@ -191,12 +193,22 @@ sub create_many ($self) { push @failed, {job_id => $job_id} if $@; } + if ($wanna_restart && $wanna_restart == 1) { + for my $job_id (@$job_ids) { + my ($res, $jobs, $auto, $single_job_id, $dup_route); + my %args = (jobs => $job_id); + $self->param('jobid', $job_id); + eval { ($res, $jobs, $auto, $single_job_id, $dup_route) = $self->restart_job(\%args); }; + push @failed_restart, {job_id => $job_id, error => "Failed to restart job: $@"} if ($@); + $self->emit_event(openqa_job_restart => {id => $single_job_id, result => $res, auto => $auto}); + } + } + # create a single event containing all relevant IDs for this action - my %res = (created => \@created, failed => \@failed); + my %res = (created => \@created, failed => \@failed, failed_restart => \@failed_restart); $self->emit_event('openqa_comments_create', \%res); - $res{error} = 'Not all comments could be created.' if @failed; - $self->render(json => \%res, status => (@failed ? 400 : 200)); + $self->render(json => \%res, status => (@failed || @failed_restart ? 400 : 200)); } =over 4 diff --git a/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm b/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm index c7fcf00e493..c60fc141586 100644 --- a/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm +++ b/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm @@ -808,42 +808,8 @@ sub done ($self) { } sub _restart ($self, %args) { - my $dup_route = $args{duplicate_route_compatibility}; - my @flags = qw(force skip_aborting_jobs skip_parents skip_children skip_ok_result_children); - my $validation = $self->validation; - $validation->optional('clone')->num(0); - $validation->optional('prio')->num; - $validation->optional('dup_type_auto')->num(0); # recorded within the event; for informal purposes only - $validation->optional('jobid')->num(0); - $validation->optional('jobs'); - $validation->optional('set')->like(qr/.+=.*/); - $validation->optional($_)->num(0) for @flags; - return $self->reply->validation_error({format => 'json'}) if $validation->has_error; - - my $jobs = $self->param('jobid'); - my $single_job_id; - if ($jobs) { - $self->app->log->debug("Restarting job $jobs"); - $jobs = [$jobs]; - $single_job_id = $jobs->[0]; - } - else { - $jobs = $self->every_param('jobs'); - $self->app->log->debug("Restarting jobs @$jobs"); - } - - my $auto = defined $validation->param('dup_type_auto') ? int($validation->param('dup_type_auto')) : 0; - my %settings = map { split('=', $_, 2) } @{$validation->every_param('set')}; - my @params = map { $validation->param($_) ? ($_ => 1) : () } @flags; - push @params, clone => !defined $validation->param('clone') || $validation->param('clone'); - push @params, prio => int($validation->param('prio')) if defined $validation->param('prio'); - push @params, skip_aborting_jobs => 1 if $dup_route && !defined $validation->param('skip_aborting_jobs'); - push @params, force => 1 if $dup_route && !defined $validation->param('force'); - push @params, settings => \%settings; - - my $res = OpenQA::Resource::Jobs::job_restart($jobs, @params); - OpenQA::Scheduler::Client->singleton->wakeup; - + my ($res, $jobs, $auto, $single_job_id, $dup_route) = $self->restart_job(\%args); + return $self->reply->validation_error({format => 'json'}) unless defined $res; my $duplicates = $res->{duplicates}; my @urls; for (my $i = 0; $i < @$duplicates; $i++) { diff --git a/lib/OpenQA/WebAPI/Plugin/Helpers.pm b/lib/OpenQA/WebAPI/Plugin/Helpers.pm index 6a7a1e40649..0620219cc2e 100644 --- a/lib/OpenQA/WebAPI/Plugin/Helpers.pm +++ b/lib/OpenQA/WebAPI/Plugin/Helpers.pm @@ -10,6 +10,8 @@ use OpenQA::Schema; use OpenQA::Utils qw(bugurl human_readable_size render_escaped_refs href_to_bugref); use OpenQA::Events; use OpenQA::Jobs::Constants qw(EXECUTION_STATES PRE_EXECUTION_STATES ABORTED_RESULTS FAILED NOT_COMPLETE_RESULTS); +use OpenQA::Resource::Jobs; +use OpenQA::Scheduler::Client; use Text::Glob qw(glob_to_regex_string); use List::Util qw(any); @@ -224,6 +226,45 @@ sub register ($self, $app, $config) { return $c->tag('span', title => $text, $text); }); + $app->helper( + restart_job => sub ($c, $args) { + my $dup_route = $args->{duplicate_route_compatibility}; + my @flags = qw(force skip_aborting_jobs skip_parents skip_children skip_ok_result_children); + my $validation = $c->validation; + $validation->optional('clone')->num(0); + $validation->optional('prio')->num; + $validation->optional('dup_type_auto')->num(0); # recorded within the event; for informal purposes only + $validation->optional('jobid')->num(0); + $validation->optional('jobs'); + $validation->optional('set')->like(qr/.+=.*/); + $validation->optional($_)->num(0) for @flags; + return undef if $validation->has_error; + + my $jobs = $c->param('jobid'); + my $single_job_id; + if ($jobs) { + $c->app->log->debug("Restarting job $jobs"); + $jobs = [$jobs]; + $single_job_id = $jobs->[0]; + } + else { + $jobs = $c->every_param('jobs'); + $c->app->log->debug("Restarting jobs @$jobs"); + } + + my $auto = defined $validation->param('dup_type_auto') ? int($validation->param('dup_type_auto')) : 0; + my %settings = map { split('=', $_, 2) } @{$validation->every_param('set')}; + my @params = map { $validation->param($_) ? ($_ => 1) : () } @flags; + push @params, clone => !defined $validation->param('clone') || $validation->param('clone'); + push @params, prio => int($validation->param('prio')) if defined $validation->param('prio'); + push @params, skip_aborting_jobs => 1 if $dup_route && !defined $validation->param('skip_aborting_jobs'); + push @params, force => 1 if $dup_route && !defined $validation->param('force'); + push @params, settings => \%settings; + my $res = OpenQA::Resource::Jobs::job_restart($jobs, @params); + OpenQA::Scheduler::Client->singleton->wakeup; + return ($res, $jobs, $auto, $single_job_id, $dup_route); + }); + my %progress_bar_query_by_key = ( unfinished => [state => [EXECUTION_STATES, PRE_EXECUTION_STATES]], skipped => [result => [ABORTED_RESULTS]], diff --git a/templates/webapi/test/overview.html.ep b/templates/webapi/test/overview.html.ep index 28b00a37b3e..b1e14fa0727 100644 --- a/templates/webapi/test/overview.html.ep +++ b/templates/webapi/test/overview.html.ep @@ -231,10 +231,17 @@