Skip to content

Commit

Permalink
Merge pull request #5971 from b10n1k/batch_restart_with_comment
Browse files Browse the repository at this point in the history
Add option to restart jobs upon comment submission
  • Loading branch information
mergify[bot] authored Nov 7, 2024
2 parents a1c8732 + 29fdf01 commit 25b7bc0
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 56 deletions.
32 changes: 26 additions & 6 deletions assets/javascripts/openqa.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,12 @@ function forceJobRestartViaRestartLink(restartLink) {
restartLink.click();
}

function restartJob(ajaxUrl, jobId) {
function restartJob(ajaxUrl, jobIds, comment) {
let singleJobId;
if (!Array.isArray(jobIds)) {
singleJobId = jobIds;
jobIds = [jobIds];
}
var showError = function (reason) {
var errorMessage = '<strong>Unable to restart job';
if (reason) {
Expand All @@ -248,30 +253,45 @@ function restartJob(ajaxUrl, jobId) {
}
addFlash('danger', errorMessage);
};

return fetchWithCSRF(ajaxUrl, {method: 'POST'})
const body = new FormData();
body.append('comment', comment);
return fetchWithCSRF(ajaxUrl, {method: 'POST', body: body})
.then(response => {
if (!response.ok) throw `Server returned ${response.status}: ${response.statusText}`;
return response.json();
})
.then(responseJSON => {
var newJobUrl;
try {
newJobUrl = responseJSON.test_url[0][jobId];
if (singleJobId) {
newJobUrl = responseJSON.test_url[0][singleJobId];
} else {
const testUrlData = responseJSON?.test_url;
if (Array.isArray(testUrlData)) {
newJobUrl = testUrlData.map(item => Object.values(item)[0]);
}
}
} catch {
// Intentionally ignore all errors
}
if (
showJobRestartResults(
responseJSON,
newJobUrl,
restartJob.bind(undefined, addParam(ajaxUrl, 'force', '1'), jobId)
restartJob.bind(undefined, addParam(ajaxUrl, 'force', '1'), jobIds, comment)
)
) {
return;
}
if (newJobUrl) {
window.location.replace(newJobUrl);
if (Array.isArray(newJobUrl)) {
addFlash(
'info',
'The jobs have been restarted. <a href="javascript: location.reload()">Reload</a> the page to show changes.'
);
} else {
window.location.replace(newJobUrl);
}
} else {
throw 'URL for new job not available';
}
Expand Down
29 changes: 27 additions & 2 deletions assets/javascripts/overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,33 @@ function showAddCommentsDialog() {
modal.show();
}

function addComments(form) {
function restartJobsWithComment(btn) {
const form = btn.form;
const text = form.elements.text.value;
const jobs = btn.dataset.jobs
.split(',')
.map(Number)
.filter(n => !isNaN(n));
const apiUrl = btn.dataset.url;
if (!text.length) {
return window.alert("The comment text mustn't be empty.");
}

const progressIndication = document.getElementById('add-comments-progress-indication');
const controls = document.getElementById('add-comments-controls');
progressIndication.style.display = 'flex';
controls.style.display = 'none';
restartJob(apiUrl, jobs, text).finally(() => {
progressIndication.style.display = 'none';
controls.style.display = 'inline';
window.addCommentsModal.hide();
});
}

function addComments(btn) {
const form = btn.form;
const text = form.elements.text.value;
const apiUrl = btn.dataset.url;
if (!text.length) {
return window.alert("The comment text mustn't be empty.");
}
Expand All @@ -301,7 +326,7 @@ function addComments(form) {
controls.style.display = 'inline';
window.addCommentsModal.hide();
};
fetchWithCSRF(form.action, {method: 'POST', body: new FormData(form)})
fetchWithCSRF(apiUrl, {method: 'POST', body: new FormData(form)})
.then(response => {
if (!response.ok) throw `Server returned ${response.status}: ${response.statusText}`;
addFlash(
Expand Down
10 changes: 9 additions & 1 deletion assets/stylesheets/overview.scss
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,12 @@
#add-comments-progress-indication {
display: none;
width: 100%;
}
}

.group-comment-icon-stack {
font-size: 0.9em;
}

.group-comment-icon-stack .fa-undo {
color: #0c4374;
}
60 changes: 38 additions & 22 deletions t/ui/10-tests_overview.t
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ like($driver->find_elements('.failedmodule', 'css')->[1]->get_attribute('href'),

my @descriptions = $driver->find_elements('td.name a', 'css');
is(scalar @descriptions, 2, 'only test suites with description content are shown as links');
disable_bootstrap_animations;
$descriptions[0]->click();
is($driver->find_element('.popover-header')->get_text, 'kde', 'description popover shows content');

Expand Down Expand Up @@ -543,18 +542,32 @@ subtest 'filter by result and state' => sub {
ok !$driver->find_element_by_id('filter-failed')->is_selected, 'other checkbox not checked';
};

subtest "job template names displayed on 'Test result overview' page" => sub {
$driver->get('/group_overview/1002');
is($driver->find_element('.progress-bar-unfinished')->get_text(),
'1 unfinished', 'expected number of unfinished jobs');

$driver->get('/tests/overview?distri=opensuse&version=13.1&build=0091&groupid=1002');
my @tds = $driver->find_elements('#results_DVD tbody tr .name');
is($tds[0]->get_text(), 'kde_variant', 'job template name kde_variant displayed correctly');

my @descriptions = $driver->find_elements('td.name a', 'css');
is(scalar @descriptions, 2, 'only test suites with description content are shown as links');
$descriptions[0]->click();
is(wait_for_element(selector => '.popover-header')->get_text, 'kde_variant', 'description popover shows content');
};

subtest 'add comments' => sub {
my @buttons = $driver->find_elements('button[title="Add comments"]');
my @buttons = $driver->find_elements('button[title="Restart or comment jobs"]');
is @buttons, 0, 'button for adding comments not present if not logged-in';

$driver->find_element_by_link_text('Login')->click;
$driver->get('/tests/overview?state=done&result=failed');
disable_bootstrap_animations;
$driver->find_element('button[title="Add comments"]')->click;
$driver->find_element('button[title="Restart or comment jobs"]')->click;
my $comment_text = 'comment via add-comments';
my $submit_button = $driver->find_element('#add-comments-controls button[type="submit"]');
my $submit_button = $driver->find_element('#add-comments-controls button[id="commentJobsBtn"]');
$driver->find_element_by_id('text')->send_keys($comment_text);
is $submit_button->get_text, 'Submit comment on all 2 jobs', 'submit button displayed with number of jobs';
is $submit_button->get_text, 'Comment on all 2 jobs', 'submit button displayed with number of jobs';
$submit_button->click;
wait_for_ajax msg => 'comments created';
like $driver->find_element_by_id('flash-messages')->get_text, qr/The comments have been created. Reload/,
Expand All @@ -565,23 +578,26 @@ subtest 'add comments' => sub {
'comments created on all relevant jobs';
is $comments->search({job_id => {-not_in => \@failed_job_ids}, text => $comment_text})->count, 0,
'comments not created on other jobs';
};

subtest "job template names displayed on 'Test result overview' page" => sub {
$driver->get('/group_overview/1002');
is($driver->find_element('.progress-bar-failed')->get_text(), '1 failed', 'The number of failed jobs is right');
is($driver->find_element('.progress-bar-unfinished')->get_text(),
'1 unfinished', 'The number of unfinished jobs is right');

$driver->get('/tests/overview?distri=opensuse&version=13.1&build=0091&groupid=1002');
my @tds = $driver->find_elements('#results_DVD tbody tr .name');
is($tds[0]->get_text(), 'kde_variant', 'job template name kde_variant displayed correctly');

my @descriptions = $driver->find_elements('td.name a', 'css');
is(scalar @descriptions, 2, 'only test suites with description content are shown as links');
disable_bootstrap_animations;
$descriptions[0]->click();
is(wait_for_element(selector => '.popover-header')->get_text, 'kde_variant', 'description popover shows content');
subtest 'restart jobs with comment' => sub {
$driver->get('/tests/overview?state=done&result=failed');
$driver->find_element('button[title="Restart or comment jobs"]')->click;
my $comment_text = 'comment current jobs and restart';
my $submit_button = $driver->find_element('#restartAndCommentJobsBtn');
$driver->find_element_by_id('text')->send_keys($comment_text);
is $submit_button->get_text, 'Restart and comment on 2 jobs', 'submit button displayed with number of jobs';
$submit_button->click;
wait_for_ajax msg => 'comments created';
like $driver->find_element_by_id('flash-messages')->get_text, qr/Reload the page to show changes/,
'info about successful restart shown';
my @failed_job_ids = map { $_->id } $jobs->search({result => FAILED})->all;
is $comments->search({job_id => {-in => \@failed_job_ids}, text => $comment_text})->count, 2,
'comments created on all relevant jobs';
is $comments->search({job_id => {-not_in => \@failed_job_ids}, text => $comment_text})->count, 0,
'comments not created on other jobs';
my $running_job_ids = map { $_->id } $jobs->search({state => RUNNING})->all;
is $running_job_ids, 2, 'all relevant jobs restarted';
};
};

subtest "job dependencies displayed on 'Test result overview' page" => sub {
Expand Down
62 changes: 37 additions & 25 deletions templates/webapi/test/overview.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@
<div class="card-body">
% my $allow_commenting = @$job_ids && current_user;
% if ($allow_commenting) {
<button type="button" class="btn btn-secondary btn-circle btn-sm trigger-edit-button" onclick="showAddCommentsDialog()" title="Add comments">
<i class="fa fa-comment" aria-hidden="true"></i>
<button type="button" class="btn btn-secondary btn-circle btn-sm trigger-edit-button" onclick="showAddCommentsDialog()" title="Restart or comment jobs">
<span class="fa-stack group-comment-icon-stack">
<i class="fa fa-comment fa-stack-2x text-danger-info" aria-hidden="true"></i>
<i class="fa fa-undo fa-stack-1x" aria-hidden="true"></i>
</span>
</button>
% }
% my @badges = qw(success secondary warning danger info primary light light);
Expand Down Expand Up @@ -215,30 +218,39 @@

% if ($allow_commenting) {
<div class="modal fade" id="add-comments-modal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form action="<%= url_for('apiv1_post_comments')->query(job_id => $job_ids) %>" method="post" onsubmit="addComments(this); return false;">
<div class="modal-header">
<h4 class="modal-title">Add comment on all currently shown jobs</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
%= include 'comments/add_comment_form_groups', group_comment => 0, nosubmit => 1
</div>
<div class="modal-footer">
<div id="add-comments-progress-indication">
<div class="flex-fill"><i class="fa fa-cog fa-spin fa-fw"></i> Saving…</div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
<div id="add-comments-controls">
<button type="submit" class="btn btn-danger">
<i class="fa fa-comment"></i> Submit comment on all <%= scalar @$job_ids %> jobs
</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Discard</button>
</div>
</div>
</form>
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form method="post">
<div class="modal-header">
<h4 class="modal-title">Add comment on all currently shown jobs</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
%= include 'comments/add_comment_form_groups', group_comment => 0, nosubmit => 1
</div>
<div class="modal-footer">
<div id="add-comments-progress-indication">
<div class="flex-fill"><i class="fa fa-cog fa-spin fa-fw"></i> Saving…</div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
<div id="add-comments-controls">
<button type="button" class="btn btn-warning" id="commentJobsBtn"
data-url="<%= url_for('apiv1_post_comments')->query(job_id=>$job_ids) %>"
onclick="addComments(this);">
<i class="fa fa-comment"></i> Comment on all <%= scalar @$job_ids %> jobs
</button>
<button type="button" class="btn btn-danger" id="restartAndCommentJobsBtn"
data-jobs="<%= join(',', @$job_ids) %>"
data-url="<%= url_for('apiv1_restart_jobs')->query(jobs=>$job_ids) %>"
onclick="restartJobsWithComment(this);">
<i class="fa fa-play-circle-o"></i> Restart and comment on <%= scalar @$job_ids %> jobs
</button>
<button type="button" class="btn btn-secondary"
data-bs-dismiss="modal">Discard</button>
</div>
</div>
</form>
</div>
</div>
</div>
% }

0 comments on commit 25b7bc0

Please sign in to comment.