Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package openQA for openSUSE:Factory checked 
in at 2025-09-14 18:50:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.1977 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Sun Sep 14 18:50:21 2025 rev:746 rq:1304465 version:5.1757696527.61d51d58

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2025-09-12 
21:10:58.018862572 +0200
+++ /work/SRC/openSUSE:Factory/.openQA.new.1977/openQA.changes  2025-09-14 
18:50:57.880080797 +0200
@@ -1,0 +2,10 @@
+Fri Sep 12 19:18:15 UTC 2025 - [email protected]
+
+- Update to version 5.1757696527.61d51d58:
+  * Avoid partitioning in raid0 device
+  * Avoid "Server returned …" error if there is an actual error message
+  * Highlight invalid/problematic group config fields in UI when applying
+  * Improve validation of cleanup configuration
+  * AMQP: include list of failed modules in job.done messages
+
+-------------------------------------------------------------------

Old:
----
  openQA-5.1757597587.61c22a78.obscpio

New:
----
  openQA-5.1757696527.61d51d58.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.187OqO/_old  2025-09-14 18:50:58.840121028 +0200
+++ /var/tmp/diff_new_pack.187OqO/_new  2025-09-14 18:50:58.844121195 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1757597587.61c22a78
+Version:        5.1757696527.61d51d58
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.187OqO/_old  2025-09-14 18:50:58.872122368 +0200
+++ /var/tmp/diff_new_pack.187OqO/_new  2025-09-14 18:50:58.872122368 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-devel
 Name:           %{short_name}-test
-Version:        5.1757597587.61c22a78
+Version:        5.1757696527.61d51d58
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.187OqO/_old  2025-09-14 18:50:58.896123374 +0200
+++ /var/tmp/diff_new_pack.187OqO/_new  2025-09-14 18:50:58.900123542 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1757597587.61c22a78
+Version:        5.1757696527.61d51d58
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.187OqO/_old  2025-09-14 18:50:58.924124548 +0200
+++ /var/tmp/diff_new_pack.187OqO/_new  2025-09-14 18:50:58.928124715 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1757597587.61c22a78
+Version:        5.1757696527.61d51d58
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.187OqO/_old  2025-09-14 18:50:58.964126223 +0200
+++ /var/tmp/diff_new_pack.187OqO/_new  2025-09-14 18:50:58.964126223 +0200
@@ -99,7 +99,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1757597587.61c22a78
+Version:        5.1757696527.61d51d58
 Release:        0
 Summary:        The openQA web-frontend, scheduler and tools
 License:        GPL-2.0-or-later

++++++ openQA-5.1757597587.61c22a78.obscpio -> 
openQA-5.1757696527.61d51d58.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1757597587.61c22a78/assets/assetpack.def 
new/openQA-5.1757696527.61d51d58/assets/assetpack.def
--- old/openQA-5.1757597587.61c22a78/assets/assetpack.def       2025-09-11 
15:33:07.000000000 +0200
+++ new/openQA-5.1757696527.61d51d58/assets/assetpack.def       2025-09-12 
19:02:07.000000000 +0200
@@ -127,6 +127,7 @@
 < ../node_modules/datatables.net-bs5/js/dataTables.bootstrap5.min.js
 < ../node_modules/timeago/jquery.timeago.js
 < javascripts/index.js
+< javascripts/render.js
 < javascripts/admintable.js
 < javascripts/admin_user.js
 < javascripts/admin_api_keys.js
@@ -157,7 +158,6 @@
 < ../node_modules/anser/lib/index.js
 
 ! test_result.js
-< javascripts/render.js
 < javascripts/test_result.js
 < javascripts/needlediff.js
 < javascripts/running.js
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1757597587.61c22a78/assets/javascripts/job_templates.js 
new/openQA-5.1757696527.61d51d58/assets/javascripts/job_templates.js
--- old/openQA-5.1757597587.61c22a78/assets/javascripts/job_templates.js        
2025-09-11 15:33:07.000000000 +0200
+++ new/openQA-5.1757696527.61d51d58/assets/javascripts/job_templates.js        
2025-09-12 19:02:07.000000000 +0200
@@ -505,6 +505,46 @@
   form.find('.properties-status').html(result);
 }
 
+// adds/removes "is-invalid"/"invalid-feedback" classes/elements within the 
specified form for the specified response
+// returns the overall error with mentionings of internal field names replaced 
with labels from the form
+function updateValidation(form, response) {
+  const E = createElement;
+  const errorsByField = response?.errors_by_field ?? {};
+  const warningsByField = response?.warnings_by_field ?? {};
+  const elements = Array.from(form.elements);
+  const labels = elements.filter(e => e.labels?.length > 0).map(e => 
[`'${e.name}'`, `"${e.labels[0].innerText}"`]);
+  const applyLabels = msg => labels.reduce((msg, label) => 
msg.replace(...label), msg);
+  const overallError = typeof response.error === 'string' ? 
applyLabels(response.error) : undefined;
+  elements.forEach(element => {
+    const fieldName = element.name;
+    if (fieldName.length === 0) {
+      return;
+    }
+    const errors = errorsByField[fieldName];
+    const warnings = warningsByField[fieldName];
+    const hasErrors = Array.isArray(errors) && errors.length > 0;
+    const hasWarnings = Array.isArray(warnings) && warnings.length > 0;
+    const parentElement = element.parentElement;
+    let feedbackElement = parentElement.querySelector('.invalid-feedback');
+    element.classList[hasErrors || hasWarnings ? 'add' : 
'remove']('is-invalid');
+    element.classList[hasWarnings ? 'add' : 
'remove']('is-invalid-non-critical');
+    if (hasErrors || hasWarnings) {
+      if (feedbackElement === null) {
+        feedbackElement = E('div', [], {class: 'invalid-feedback'});
+        parentElement.appendChild(feedbackElement);
+      } else {
+        feedbackElement.innerHTML = '';
+      }
+      const addBadge = (className, msg) => 
feedbackElement.appendChild(E('span', [msg], {class: className}));
+      hasErrors && errors.map(applyLabels).forEach(addBadge.bind(undefined, 
'badge text-bg-danger'));
+      hasWarnings && 
warnings.map(applyLabels).forEach(addBadge.bind(undefined, 'badge 
text-bg-warning'));
+    } else if (feedbackElement !== null) {
+      parentElement.removeChild(feedbackElement);
+    }
+  });
+  return overallError;
+}
+
 function submitProperties(form) {
   var editorForm = $(form);
   editorForm.find('.buttons').hide();
@@ -523,9 +563,19 @@
         });
     })
     .then(({response, json}) => {
-      if (!response.ok || json.error)
-        throw `Server returned ${response.status}: 
${response.statusText}\n${json.error || ''}`;
-      showSubmitResults(editorForm, '<i class="fa fa-save"></i> Changes 
applied');
+      const collapse = 
document.getElementById('show-advanced-cleanup-settings-button');
+      if (json?.error?.includes('_jobs') && 
collapse.getAttribute('aria-expanded') !== 'true') {
+        collapse.click();
+      }
+      const overallError = updateValidation(form, json);
+      if (overallError) throw overallError;
+      if (!response.ok) throw `Server returned ${response.status}: 
${response.statusText}`;
+      const warnings = json?.warnings_by_field;
+      const remark =
+        typeof warnings === 'object' && Object.keys(warnings).length > 0
+          ? ', but <strong>there are warnings</strong> (see highlighted 
fields)'
+          : '';
+      showSubmitResults(editorForm, `<i class="fa fa-save"></i> Changes 
applied${remark}`);
 
       // show new name
       var newJobName = $('#editor-name').val();
@@ -538,10 +588,6 @@
       $('td.prio input').attr('placeholder', defaultPrio);
     })
     .catch(error => {
-      const collapse = 
document.getElementById('show-advanced-cleanup-settings-button');
-      if (error.includes('_jobs') && collapse.getAttribute('aria-expanded') 
!== 'true') {
-        collapse.click();
-      }
       showSubmitResults(
         editorForm,
         `<i class="fa fa-exclamation-circle"></i> Unable to apply changes: 
<strong>${error}</strong>`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1757597587.61c22a78/assets/stylesheets/forms.scss 
new/openQA-5.1757696527.61d51d58/assets/stylesheets/forms.scss
--- old/openQA-5.1757597587.61c22a78/assets/stylesheets/forms.scss      
2025-09-11 15:33:07.000000000 +0200
+++ new/openQA-5.1757696527.61d51d58/assets/stylesheets/forms.scss      
2025-09-12 19:02:07.000000000 +0200
@@ -129,3 +129,10 @@
         background-color: $default-bg-color-dark;
     }
 }
+
+// formatting for validation warnings
+.is-invalid-non-critical {
+    border-color: var(--bs-warning) !important;
+    background-image: none !important;
+    padding-right: 0.5rem !important;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1757597587.61c22a78/contrib/ay-openqa-worker.xml.erb 
new/openQA-5.1757696527.61d51d58/contrib/ay-openqa-worker.xml.erb
--- old/openQA-5.1757597587.61c22a78/contrib/ay-openqa-worker.xml.erb   
2025-09-11 15:33:07.000000000 +0200
+++ new/openQA-5.1757696527.61d51d58/contrib/ay-openqa-worker.xml.erb   
2025-09-12 19:02:07.000000000 +0200
@@ -3,19 +3,19 @@
 <profile xmlns="http://www.suse.com/1.0/yast2ns"; 
xmlns:config="http://www.suse.com/1.0/configns";>
   <general>
     <mode>
-      <confirm config:type="boolean">false</confirm>
+      <confirm t="boolean">false</confirm>
     </mode>
   </general>
   <networking>
     <!-- okurz: 2023-06-13: For multiple network interfaces by default the 
last is configured, prefer the first -->
-    <interfaces config:type="list">
+    <interfaces t="list">
       <interface>
         <bootproto>dhcp</bootproto>
         <name>eth0</name>
         <startmode>auto</startmode>
       </interface>
     </interfaces>
-    <keep_install_network config:type="boolean">true</keep_install_network>
+    <keep_install_network t="boolean">true</keep_install_network>
     <routing t="map">
       <ipv4_forward t="boolean">true</ipv4_forward>
       <ipv6_forward t="boolean">true</ipv6_forward>
@@ -23,7 +23,7 @@
   </networking>
   <% if os_release[:id] == 'opensuse-leap' %>
   <add-on>
-    <add_on_others config:type="list">
+    <add_on_others t="list">
       <listentry>
         <media_url>https://download.opensuse.org/distribution/leap/<%= 
os_release[:version] %>/repo/oss</media_url>
         <alias>repo-oss</alias>
@@ -49,14 +49,14 @@
   <% end %>
   <software>
     <% if os_release[:id] == 'opensuse-leap' %>
-    <products config:type="list">
+    <products t="list">
       <product>Leap</product>
     </products>
     <% end %>
-    <patterns config:type="list">
+    <patterns t="list">
       <pattern>kvm_server</pattern>
     </patterns>
-    <packages config:type="list">
+    <packages t="list">
       <package>openssh</package>
       <package>sudo</package>
       <package>salt-minion</package>
@@ -67,16 +67,16 @@
     <hwclock>UTC</hwclock>
     <timezone>Etc/UTC</timezone>
   </timezone>
-  <partitioning config:type="list">
+  <partitioning t="list">
     <drive>
+      <initialize t="boolean">true</initialize> <%# wipe out partition table 
before AutoYaST starts partition calculation %>
       <% disk = disks.sort_by { |d| d[:size] }.first %> <%# find the 
[smallest] disk for main OS installation %>
       <device><%= disk[:udev_names][0] %></device> <%# print the disk device 
name %>
-      <initialize config:type="boolean">true</initialize>
-      <partitions config:type="list">
+      <partitions t="list">
         <partition>
           <mount>/</mount>
           <size>max</size>
-          <filesystem config:type="symbol">btrfs</filesystem>
+          <filesystem t="symbol">btrfs</filesystem>
         </partition>
         <partition>
           <mount>swap</mount>
@@ -89,12 +89,12 @@
     <% if raidarray.length > 1 %> <%# if there is more than one disk remaining 
on the system, combine them into a raid array %>
       <% for d in 0..raidarray.length - 1 %>
       <drive>
+      <initialize t="boolean">true</initialize> <%# wipe out partition table 
before AutoYaST starts partition calculation %>
       <type t="symbol">CT_DISK</type>
       <device><%= raidarray[d][:udev_names][0] %></device> <%# print full 
device name such as /dev/nvme0n1 %>
-      <disklabel>none</disklabel>
-      <partitions config:type="list">
+      <partitions t="list">
         <partition>
-          <raid_name>/dev/md/openqa</raid_name>
+          <raid_name>/dev/md/openqa</raid_name> <%# device node used within 
automount systemd service var-lib-automount %>
           <size>max</size>
         </partition>
       </partitions>
@@ -104,12 +104,6 @@
     <drive>
       <type t="symbol">CT_MD</type>
       <device>/dev/md/openqa</device>
-      <partitions config:type="list">
-        <partition>
-          <mount>/var/lib/openqa</mount>
-          <size>max</size>
-        </partition>
-      </partitions>
       <raid_options>
         <raid_type>raid0</raid_type>
         <device_order t="list">
@@ -123,27 +117,37 @@
     <% else %> <%# maybe we have only one disk left on the system %>
     <% if raidarray.length != 0 %>
     <drive>
-      <type t="symbol">CT_DISK</type>
+      <initialize t="boolean">true</initialize> <%# wipe out partition table %>
       <device><%= raidarray[0][:udev_names][0] %></device> <%# print full 
device name such as /dev/nvme0n1 %>
-      <disklabel>gpt</disklabel>
-      <use>all</use>
       <partitions t="list">
         <partition>
+          <%# create raid device even with a single disk to comply with 
systemd automount service %>
+          <raid_name>/dev/md/openqa</raid_name>
           <size>max</size>
-          <filesystem t="symbol">ext4</filesystem>
-          <mount>/var/lib/openqa</mount>
         </partition>
       </partitions>
+      <use>all</use>
+    </drive>
+    <drive>
+    <type t="symbol">CT_MD</type>
+    <device>/dev/md/openqa</device>
+    <raid_options>
+      <raid_type>raid0</raid_type>
+      <device_order t="list">
+        <device><%= raidarray[0][:udev_names][0] %></device>
+      </device_order>
+    </raid_options>
+    <use>all</use>
     </drive>
     <% end %> <%# end inner if %>
     <% end %> <%# end outer if-else %>
   </partitioning>
   <scripts>
-    <post-scripts config:type="list">
+    <post-scripts t="list">
       <script>
         <filename>setup.sh</filename>
         <interpreter>shell</interpreter>
-        <debug config:type="boolean">true</debug>
+        <debug t="boolean">true</debug>
         <source><![CDATA[
             echo 'roles: worker' > /etc/salt/grains
         ]]></source>
@@ -151,13 +155,13 @@
     </post-scripts>
   </scripts>
   <firewall>
-    <enable_firewall config:type="boolean">true</enable_firewall>
-    <start_firewall config:type="boolean">true</start_firewall>
+    <enable_firewall t="boolean">true</enable_firewall>
+    <start_firewall t="boolean">true</start_firewall>
     <default_zone>public</default_zone>
-    <zones config:type="list">
+    <zones t="list">
       <zone>
        <name>public</name>
-       <services config:type="list">
+       <services t="list">
           <service>ssh</service>
        </services>
       </zone>
@@ -165,7 +169,7 @@
   </firewall>
   <services-manager t="map">
     <services>
-      <enable config:type="list">
+      <enable t="list">
         <service>sshd</service>
         <service>chronyd</service>
       </enable>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1757597587.61c22a78/lib/OpenQA/WebAPI/Controller/API/V1/JobGroup.pm
 
new/openQA-5.1757696527.61d51d58/lib/OpenQA/WebAPI/Controller/API/V1/JobGroup.pm
--- 
old/openQA-5.1757597587.61c22a78/lib/OpenQA/WebAPI/Controller/API/V1/JobGroup.pm
    2025-09-11 15:33:07.000000000 +0200
+++ 
new/openQA-5.1757696527.61d51d58/lib/OpenQA/WebAPI/Controller/API/V1/JobGroup.pm
    2025-09-12 19:02:07.000000000 +0200
@@ -189,6 +189,8 @@
 
 sub _check_keep_logs_and_results ($self, $properties, $group = undef) {
     my @errors;
+    my %errors_by_field;
+    my %warnings_by_field;
     my $prefix = $self->is_parent ? 'default_' : '';
     for my $important ('', '_important') {
         my $log_key = "${prefix}keep${important}_logs_in_days";
@@ -197,13 +199,42 @@
         my $log_value = $properties->{$log_key} // ($group ? $group->$log_key 
: 0);
         my $result_value = $properties->{$result_key} // ($group ? 
$group->$result_key : 0);
         my $job_value = $properties->{$job_key} // ($group ? $group->$job_key 
: 0);
-        push @errors, "'$log_key' must be <= '$result_key'" if $result_value 
!= 0 && $log_value > $result_value;
-        push @errors, "'$result_key' must be <= '$job_key'" if $job_value != 0 
&& $result_value > $job_value;
+        if ($result_value != 0 && $log_value > $result_value) {
+            push @{$errors_by_field{$log_key}}, "must be <= '$result_key'";
+            push @errors, "'$log_key' must be <= '$result_key'";
+        }
+        if ($job_value != 0 && $result_value > $job_value) {
+            push @{$errors_by_field{$result_key}}, "must be <= '$job_key'";
+            push @errors, "'$result_key' must be <= '$job_key'";
+        }
     }
-    $self->render(json => {error => join(', ', @errors)}, status => 400) if 
@errors;
+    for my $field (qw(logs results jobs)) {
+        my $important_key = "${prefix}keep_important_${field}_in_days";
+        my $regular_key = "${prefix}keep_${field}_in_days";
+        my $important_value = $properties->{$important_key} // ($group ? 
$group->$important_key : 0);
+        my $regular_value = $properties->{$regular_key} // ($group ? 
$group->$regular_key : 0);
+        if ($important_value != 0 && $important_value < $regular_value) {
+            push @{$warnings_by_field{$important_key}}, "should be >= 
'$regular_key'";
+        }
+    }
+    $self->{_errors} = \@errors;
+    $self->{_errors_by_field} = \%errors_by_field;
+    $self->{_warnings_by_field} = \%warnings_by_field;
     return @errors == 0;
 }
 
+sub _render_json ($self, $id = undef) {
+    my $errors = $self->{_errors};
+    my $status = @$errors ? 400 : 200;
+    my %res = (
+        errors_by_field => $self->{_errors_by_field} // {},
+        warnings_by_field => $self->{_warnings_by_field} // {},
+    );
+    $res{id} = $id if defined $id;
+    $res{error} = join(', ', @$errors) if @$errors;
+    $self->render(json => \%res, status => $status);
+}
+
 =over 4
 
 =item create()
@@ -242,13 +273,13 @@
     }
 
     my $properties = $self->load_properties;
-    return undef unless $self->_check_keep_logs_and_results($properties);
+    return $self->_render_json unless 
$self->_check_keep_logs_and_results($properties);
     my $id;
     try { $id = $self->resultset->create($properties)->id }
     catch ($e) { return $self->render(json => {error => $e}, status => 400) }
 
     $self->emit_event(openqa_jobgroup_create => {id => $id});
-    $self->render(json => {id => $id});
+    $self->_render_json($id);
 }
 
 =over 4
@@ -281,13 +312,13 @@
     }
 
     my $properties = $self->load_properties;
-    return undef unless $self->_check_keep_logs_and_results($properties, 
$group);
+    return $self->_render_json unless 
$self->_check_keep_logs_and_results($properties, $group);
     my $id;
     try { $id = $group->update($properties)->id }
     catch ($e) { return $self->render(json => {error => $e}, status => 400) }
 
     $self->emit_event(openqa_jobgroup_update => {id => $id});
-    $self->render(json => {id => $id});
+    $self->_render_json($id);
 }
 
 =over 4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1757597587.61c22a78/lib/OpenQA/WebAPI/Plugin/AMQP.pm 
new/openQA-5.1757696527.61d51d58/lib/OpenQA/WebAPI/Plugin/AMQP.pm
--- old/openQA-5.1757597587.61c22a78/lib/OpenQA/WebAPI/Plugin/AMQP.pm   
2025-09-11 15:33:07.000000000 +0200
+++ new/openQA-5.1757696527.61d51d58/lib/OpenQA/WebAPI/Plugin/AMQP.pm   
2025-09-12 19:02:07.000000000 +0200
@@ -104,6 +104,7 @@
         if ($event_data->{bugref} = $bugref) {
             $event_data->{bugurl} = OpenQA::Utils::bugurl($bugref);
         }
+        $event_data->{failedmodules} = $job->failed_modules;
     }
     my $job_settings = $job->settings_hash;
     for my $detail (qw(ISO HDD_1)) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1757597587.61c22a78/t/23-amqp.t 
new/openQA-5.1757696527.61d51d58/t/23-amqp.t
--- old/openQA-5.1757597587.61c22a78/t/23-amqp.t        2025-09-11 
15:33:07.000000000 +0200
+++ new/openQA-5.1757696527.61d51d58/t/23-amqp.t        2025-09-12 
19:02:07.000000000 +0200
@@ -98,6 +98,7 @@
             MACHINE => 'RainbowPC',
             TEST => 'rainbow',
             bugref => undef,
+            failedmodules => [],
             group_id => undef,
             id => $job,
             newbuild => undef,
@@ -139,6 +140,7 @@
             TEST => 'kde',
             bugref => 'bsc#123',
             bugurl => 'https://bugzilla.suse.com/show_bug.cgi?id=123',
+            failedmodules => ['aplay'],
             group_id => 1001,
             id => 99963,
             newbuild => undef,
@@ -182,6 +184,7 @@
             MACHINE => 'RainbowPC',
             TEST => 'rainbow',
             bugref => undef,
+            failedmodules => [],
             group_id => undef,
             remaining => 1,
         },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1757597587.61c22a78/t/api/10-jobgroups.t 
new/openQA-5.1757696527.61d51d58/t/api/10-jobgroups.t
--- old/openQA-5.1757597587.61c22a78/t/api/10-jobgroups.t       2025-09-11 
15:33:07.000000000 +0200
+++ new/openQA-5.1757696527.61d51d58/t/api/10-jobgroups.t       2025-09-12 
19:02:07.000000000 +0200
@@ -529,10 +529,12 @@
                 $params->{keep_results_name} => 1,
                 $params->{keep_jobs_name} => 1
             );
-            my @expected_errors = (
-                "'$params->{keep_logs_name}' must be <= 
'$params->{keep_results_name}'",
-                "'$params->{keep_important_logs_name}' must be <= 
'$params->{keep_important_results_name}'",
+            my %expected_errors_by_field = (
+                $params->{keep_logs_name} => ["must be <= 
'$params->{keep_results_name}'"],
+                $params->{keep_important_logs_name} => ["must be <= 
'$params->{keep_important_results_name}'"],
             );
+            my @fields = qw(keep_logs_name keep_important_logs_name);
+            my @expected_errors = map { "'$params->{$_}' 
$expected_errors_by_field{$params->{$_}}->[0]" } @fields;
             my %form_invalid_1 = (
                 %form_invalid,
                 $params->{keep_important_logs_name} => 5,
@@ -541,13 +543,32 @@
             $t->post_ok($params->{endpoint}, form => \%form_invalid_1);
             $t->status_is(400, "creation fails if $params->{keep_results_name} 
lower than $params->{keep_logs_name}");
             $t->json_is('/error' => join(', ', @expected_errors), "error 
message on invalid $test creation (1)");
-            my %form_invalid_2 = (%form_invalid, $params->{keep_logs_name} => 
1, $params->{keep_results_name} => 2);
+            $t->json_is(
+                '/errors_by_field' => \%expected_errors_by_field,
+                "errors by field on invalid $test creation (1)"
+            );
+            $t->json_is('/warnings_by_field' => {}, "no warnings by field on 
invalid $test creation (1)");
+            my %form_invalid_2 = (
+                %form_invalid, $params->{keep_logs_name} => 1,
+                $params->{keep_important_logs_name} => 0,
+                $params->{keep_results_name} => 2,
+                $params->{keep_important_results_name} => 1
+            );
             $t->post_ok($params->{endpoint}, form => \%form_invalid_2);
             $t->status_is(400, "creation fails if $params->{keep_jobs_name} 
lower than $params->{keep_results_name}");
             $t->json_is(
                 '/error' => "'$params->{keep_results_name}' must be <= 
'$params->{keep_jobs_name}'",
                 "error message on invalid $test creation (2)"
             );
+            $t->json_is(
+                '/errors_by_field' => {$params->{keep_results_name} => ["must 
be <= '$params->{keep_jobs_name}'"]},
+                "no warnings by field on invalid $test creation (2)"
+            );
+            $t->json_is(
+                '/warnings_by_field' =>
+                  {$params->{keep_important_results_name} => ["should be >= 
'$params->{keep_results_name}'"]},
+                "no warnings by field on invalid $test creation (2)"
+            );
             $t->post_ok($params->{endpoint}, form => {name => 
$params->{name}});
             $t->status_is(200, "can create $test without retention 
parameters");
             return unless my $group_id = $t->tx->res->json->{id};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1757597587.61c22a78/t/ui/13-admin.t 
new/openQA-5.1757696527.61d51d58/t/ui/13-admin.t
--- old/openQA-5.1757597587.61c22a78/t/ui/13-admin.t    2025-09-11 
15:33:07.000000000 +0200
+++ new/openQA-5.1757696527.61d51d58/t/ui/13-admin.t    2025-09-12 
19:02:07.000000000 +0200
@@ -428,17 +428,28 @@
         $ele = 
$driver->find_element_by_id('editor-keep-important-results-in-days');
         $ele->send_keys(Selenium::Remote::WDKeys->KEYS->{control}, 'a');
         $ele->send_keys('500');
+        $ele = $driver->find_element_by_id('editor-keep-results-in-days');
+        $ele->send_keys(Selenium::Remote::WDKeys->KEYS->{control}, 'a');
+        $ele->send_keys('501');
         is($driver->find_element('#properties p.buttons 
button.btn-primary')->get_attribute('disabled'),
             undef, 'group properties save button is enabled');
         $driver->find_element_by_id('editor-carry-over-bugrefs')->click();
         $driver->find_element('#properties p.buttons 
button.btn-primary')->click();
         wait_for_ajax(msg => 'ensure there is no race condition, even though 
the page is reloaded');
+        my $status = $driver->find_element('.properties-status')->get_text;
+        my $input = 
$driver->find_element('#editor-keep-important-results-in-days.is-invalid.is-invalid-non-critical');
+        my $badge_sel = '#editor-keep-important-results-in-days ~ 
.invalid-feedback .badge.text-bg-warning';
+        my $badge = $driver->find_element($badge_sel)->get_text;
+        ok $input, 'input is highlighted to show a non-critical validation 
issue';
+        like $status, qr/Changes applied.*warnings/i, 'remark about warnings';
+        like $badge, qr/should be >= "Keep results for"/i, 'badge with warning 
shown';
         $driver->refresh();
         $driver->title_is('openQA: Job templates for Cool Group has been 
edited!', 'new name on title');
         $driver->find_element_by_id('toggle-group-properties')->click();
         is element_prop('editor-name'), 'Cool Group has been edited!', 'name 
edited';
         is element_prop('editor-size-limit'), '1000', 'size edited';
         is element_prop('editor-keep-important-results-in-days'), '500', 'keep 
important results in days edited';
+        is element_prop('editor-keep-results-in-days'), '501', 'keep results 
in days edited';
         is element_prop('editor-default-priority'), '50', 'default priority 
should be the same';
         ok !element_prop('editor-carry-over-bugrefs', 'checked'), 'bug carry 
over disabled';
 

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.187OqO/_old  2025-09-14 18:51:18.672952112 +0200
+++ /var/tmp/diff_new_pack.187OqO/_new  2025-09-14 18:51:18.676952279 +0200
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1757597587.61c22a78
-mtime: 1757597587
-commit: 61c22a780705673e7e7f3851258b010055803546
+version: 5.1757696527.61d51d58
+mtime: 1757696527
+commit: 61d51d581dd3fd1923856261bbed6dbfd384114a
 

Reply via email to