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-10-03 15:44:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.11973 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Fri Oct  3 15:44:03 2025 rev:762 rq:1308695 version:5.1759402042.49e912c3

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2025-10-02 
19:21:11.464945907 +0200
+++ /work/SRC/openSUSE:Factory/.openQA.new.11973/openQA.changes 2025-10-03 
15:45:06.416708572 +0200
@@ -1,0 +2,7 @@
+Thu Oct 02 18:13:03 UTC 2025 - [email protected]
+
+- Update to version 5.1759402042.49e912c3:
+  * Introduce array job settings
+  * Retry `obs_rsync_update_*` tasks if Gru service terminates
+
+-------------------------------------------------------------------

Old:
----
  openQA-5.1759329378.3b8e8685.obscpio

New:
----
  openQA-5.1759402042.49e912c3.obscpio

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

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.Epzppj/_old  2025-10-03 15:45:07.808766047 +0200
+++ /var/tmp/diff_new_pack.Epzppj/_new  2025-10-03 15:45:07.812766212 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1759329378.3b8e8685
+Version:        5.1759402042.49e912c3
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.Epzppj/_old  2025-10-03 15:45:07.844767533 +0200
+++ /var/tmp/diff_new_pack.Epzppj/_new  2025-10-03 15:45:07.844767533 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-devel
 Name:           %{short_name}-test
-Version:        5.1759329378.3b8e8685
+Version:        5.1759402042.49e912c3
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.Epzppj/_old  2025-10-03 15:45:07.872768690 +0200
+++ /var/tmp/diff_new_pack.Epzppj/_new  2025-10-03 15:45:07.876768854 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1759329378.3b8e8685
+Version:        5.1759402042.49e912c3
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.Epzppj/_old  2025-10-03 15:45:07.904770011 +0200
+++ /var/tmp/diff_new_pack.Epzppj/_new  2025-10-03 15:45:07.908770176 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1759329378.3b8e8685
+Version:        5.1759402042.49e912c3
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.Epzppj/_old  2025-10-03 15:45:07.940771497 +0200
+++ /var/tmp/diff_new_pack.Epzppj/_new  2025-10-03 15:45:07.944771662 +0200
@@ -99,7 +99,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1759329378.3b8e8685
+Version:        5.1759402042.49e912c3
 Release:        0
 Summary:        The openQA web-frontend, scheduler and tools
 License:        GPL-2.0-or-later

++++++ openQA-5.1759329378.3b8e8685.obscpio -> 
openQA-5.1759402042.49e912c3.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1759329378.3b8e8685/lib/OpenQA/Schema/Result/Jobs.pm 
new/openQA-5.1759402042.49e912c3/lib/OpenQA/Schema/Result/Jobs.pm
--- old/openQA-5.1759329378.3b8e8685/lib/OpenQA/Schema/Result/Jobs.pm   
2025-10-01 16:36:18.000000000 +0200
+++ new/openQA-5.1759402042.49e912c3/lib/OpenQA/Schema/Result/Jobs.pm   
2025-10-02 12:47:22.000000000 +0200
@@ -410,7 +410,7 @@
     my $settings = $self->{_settings} = {};
     my $all = $prefetched || [$self->settings->all];
     for (@$all) {
-        # handle multi-value WORKER_CLASS
+        # handle multi-value WORKER_CLASS and array settings (like ISSUES[])
         if (defined $settings->{$_->key}) {
             $settings->{$_->key} .= ',' . $_->value;
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1759329378.3b8e8685/lib/OpenQA/Schema/ResultSet/JobSettings.pm 
new/openQA-5.1759402042.49e912c3/lib/OpenQA/Schema/ResultSet/JobSettings.pm
--- old/openQA-5.1759329378.3b8e8685/lib/OpenQA/Schema/ResultSet/JobSettings.pm 
2025-10-01 16:36:18.000000000 +0200
+++ new/openQA-5.1759402042.49e912c3/lib/OpenQA/Schema/ResultSet/JobSettings.pm 
2025-10-02 12:47:22.000000000 +0200
@@ -5,15 +5,29 @@
 use Mojo::Base 'DBIx::Class::ResultSet', -signatures;
 
 use OpenQA::App;
+use List::Util qw(min);
 
 sub all_values_sorted ($self, $job_id, $key) {
     state $options = {distinct => 1, columns => 'value', order_by => 'value'};
     [map { $_->value } $self->search({job_id => $job_id, key => $key}, 
$options)];
 }
 
+sub jobs_for_setting_by_exact_key_and_value ($self, $key, $value, $limit) {
+    my $limits = OpenQA::App->singleton->config->{misc_limits};
+    $limit = min($limits->{generic_max_limit}, $limit // 
$limits->{generic_default_limit});
+    my $options = {columns => ['job_id'], rows => $limit, order_by => {-desc 
=> 'id'}};
+    return [map { $_->job_id } $self->search({key => $key, value => $value}, 
$options)];
+}
+
 sub jobs_for_setting ($self, $options) {
-    my $limit = 
OpenQA::App->singleton->config->{misc_limits}{job_settings_max_recent_jobs};
+    # Return jobs for settings specified by a concrete key/value pair
+    my $value = $options->{value};
+    my $limit = $options->{limit};
+    return $self->jobs_for_setting_by_exact_key_and_value($options->{key}, 
$value, $limit) if defined $value;
 
+    # Return jobs for settings specified by a key with globbing and a value 
that can be part of a comma-separated list
+    my $server_side_limit = 
OpenQA::App->singleton->config->{misc_limits}{job_settings_max_recent_jobs};
+    $limit = min($server_side_limit, defined($limit) ? ($limit) : ());
     my $key_like = $options->{key};
     $key_like =~ s/\*/\%/g;
     my $list_value = $options->{list_value};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1759329378.3b8e8685/lib/OpenQA/Schema/ResultSet/Jobs.pm 
new/openQA-5.1759402042.49e912c3/lib/OpenQA/Schema/ResultSet/Jobs.pm
--- old/openQA-5.1759329378.3b8e8685/lib/OpenQA/Schema/ResultSet/Jobs.pm        
2025-10-01 16:36:18.000000000 +0200
+++ new/openQA-5.1759402042.49e912c3/lib/OpenQA/Schema/ResultSet/Jobs.pm        
2025-10-02 12:47:22.000000000 +0200
@@ -196,8 +196,8 @@
     my @job_settings;
     my $now = now;
     for my $key (keys %settings) {
-        my @values = $key eq 'WORKER_CLASS' ? split(m/,/, $settings{$key}) : 
($settings{$key});
-        push(@job_settings, {t_created => $now, t_updated => $now, key => 
$key, value => $_}) for (@values);
+        my @values = $key =~ qr/(^WORKER_CLASS|\[\])$/ ? split(m/,/, 
$settings{$key}) : ($settings{$key});
+        push(@job_settings, {t_created => $now, t_updated => $now, key => 
$key, value => $_}) for @values;
     }
     $job->settings->populate(\@job_settings);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1759329378.3b8e8685/lib/OpenQA/Script/CloneJob.pm 
new/openQA-5.1759402042.49e912c3/lib/OpenQA/Script/CloneJob.pm
--- old/openQA-5.1759329378.3b8e8685/lib/OpenQA/Script/CloneJob.pm      
2025-10-01 16:36:18.000000000 +0200
+++ new/openQA-5.1759402042.49e912c3/lib/OpenQA/Script/CloneJob.pm      
2025-10-02 12:47:22.000000000 +0200
@@ -15,6 +15,7 @@
 use Mojo::URL;
 use Mojo::JSON;    # booleans
 use OpenQA::Script::CloneJobSUSE;
+use List::Util 'any';
 
 our @EXPORT = qw(
   clone_jobs
@@ -35,9 +36,11 @@
 
 my $TEST_NAME = TEST_NAME_ALLOWED_CHARS;
 my $TEST_NAME_PLUS_MINUS = TEST_NAME_ALLOWED_CHARS_PLUS_MINUS;
-my $SETTINGS_REGEX = 
qr|([A-Z0-9_]+)(:([$TEST_NAME]+(?:[$TEST_NAME_PLUS_MINUS]+[$TEST_NAME])?))?(\+)?=(.*)|;
+my $SETTINGS_REGEX = 
qr|([A-Z0-9_]+(\[\])?)(:([$TEST_NAME]+(?:[$TEST_NAME_PLUS_MINUS]+[$TEST_NAME])?))?(\+)?=(.*)|;
 
-sub is_global_setting ($key) { grep /^$key$/, GLOBAL_SETTINGS }
+sub is_global_setting ($key) {
+    any { $key eq $_ } GLOBAL_SETTINGS;
+}
 
 sub clone_job_apply_settings ($argv, $depth, $settings, $options) {
     delete $settings->{NAME};    # usually autocreated
@@ -48,7 +51,7 @@
             warn "command-line argument '$arg' is no valid setting and will be 
ignored\n";
             next;
         }
-        my ($key, $scope, $plus, $value) = ($1, $3, $4, $5);
+        my ($key, $scope, $plus, $value) = ($1, $4, $5, $6);
         next if defined $scope && ($settings->{TEST} // '') ne $scope;
         next if !defined $scope && !is_global_setting($key) && $depth > 1 && 
!$options->{'parental-inheritance'};
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1759329378.3b8e8685/lib/OpenQA/WebAPI/Controller/API/V1/JobSettings.pm
 
new/openQA-5.1759402042.49e912c3/lib/OpenQA/WebAPI/Controller/API/V1/JobSettings.pm
--- 
old/openQA-5.1759329378.3b8e8685/lib/OpenQA/WebAPI/Controller/API/V1/JobSettings.pm
 2025-10-01 16:36:18.000000000 +0200
+++ 
new/openQA-5.1759402042.49e912c3/lib/OpenQA/WebAPI/Controller/API/V1/JobSettings.pm
 2025-10-02 12:47:22.000000000 +0200
@@ -10,22 +10,36 @@
 
 Filters jobs based on a single setting key/value pair.
 
+  openqa-cli api job_settings/jobs key="ISSUES[]" value=39911
   openqa-cli api job_settings/jobs key="*_TEST_ISSUES" list_value=39911
   openqa-cli api job_settings/jobs key="*" list_value=39911
 
 =item C<key>
 
-The setting key to filter by. It accepts a string or a glob of a job variable.
-Some variables are not stored and they can not be used.
+The setting key to filter by. Some variables are not stored and they can not be
+used.
+
+=item C<value>
+
+Returns all jobs where the value of the setting specified by C<key> is 
C<value>.
+
+As this query might find many jobs the results are limited by the server-side
+setting C<{misc_limits}{generic_default_limit}>. This limit can be increased
+using the C<limit> paremter (up to C<{misc_limits}{generic_max_limit}>).
 
 =item C<list_value>
 
-The value to match for the given key. This can be a string without special 
characters.
+Returns all jobs where the value of the setting specified by C<key> contains a
+comma-separated list that in turn contains C<list_value>. This can be a string
+without special characters. When C<list_value> is used, C<key> might contain an
+asterisks for globbing.
+
+Use of C<list_value> is expensive so the search is limited via the server-side
+setting C<{misc_limits}{job_settings_max_recent_jobs}>.
 
 =item Returns
 
-On success, returns an array of the matched job ids. The results rely on
-C<{misc_limits}{job_settings_max_recent_jobs}>.
+On success, returns an array of the matched job IDs.
 
 =back
 
@@ -33,14 +47,22 @@
 
 sub jobs ($self) {
     my $validation = $self->validation;
-    $validation->required('key')->like(qr/^[\w\*]+$/);
-    $validation->required('list_value')->like(qr/^\w+$/);
+    $validation->required('key')->like(qr/^[\w\*\[\]]+$/);
+    $validation->optional('value');
+    $validation->optional('list_value')->like(qr/^\w+$/);
+    $validation->optional('limit')->num(0);
     return $self->reply->validation_error({format => 'json'}) if 
$validation->has_error;
 
     my $key = $validation->param('key');
+    my $value = $validation->param('value');
     my $list_value = $validation->param('list_value');
-    my $jobs = $self->schema->resultset('JobSettings')->jobs_for_setting({key 
=> $key, list_value => $list_value});
-    $self->render(json => {jobs => $jobs});
+    my $limit = $validation->param('limit');
+    return $self->render(json => {error => 'either "value" or "list_value" 
needs to be specified'}, status => 400)
+      unless defined($value)
+      xor defined($list_value);
+    my $job_settings = $self->schema->resultset('JobSettings');
+    my $options = {key => $key, value => $value, list_value => $list_value, 
limit => $limit};
+    $self->render(json => {jobs => $job_settings->jobs_for_setting($options)});
 }
 
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1759329378.3b8e8685/lib/OpenQA/WebAPI/Plugin/ObsRsync/Task.pm 
new/openQA-5.1759402042.49e912c3/lib/OpenQA/WebAPI/Plugin/ObsRsync/Task.pm
--- old/openQA-5.1759329378.3b8e8685/lib/OpenQA/WebAPI/Plugin/ObsRsync/Task.pm  
2025-10-01 16:36:18.000000000 +0200
+++ new/openQA-5.1759402042.49e912c3/lib/OpenQA/WebAPI/Plugin/ObsRsync/Task.pm  
2025-10-02 12:47:22.000000000 +0200
@@ -5,6 +5,7 @@
 use Mojo::Base 'Mojolicious::Plugin', -signatures;
 use Mojo::File;
 use IPC::Run;
+use OpenQA::Task::SignalGuard;
 use Feature::Compat::Try;
 
 sub register ($self, $app, $conf) {
@@ -76,6 +77,7 @@
 }
 
 sub update_dirty_status ($job, $args) {
+    my $ensure_task_retry_on_termination_signal_guard = 
OpenQA::Task::SignalGuard->new($job);
     my $app = $job->app;
     my $project = $args->{project};
     my $helper = $app->obs_rsync;
@@ -84,6 +86,7 @@
 }
 
 sub update_obs_builds_text ($job, $args) {
+    my $ensure_task_retry_on_termination_signal_guard = 
OpenQA::Task::SignalGuard->new($job);
     my $app = $job->app;
     my $alias = $args->{alias};
     my $helper = $app->obs_rsync;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1759329378.3b8e8685/t/api/04-jobs.t 
new/openQA-5.1759402042.49e912c3/t/api/04-jobs.t
--- old/openQA-5.1759329378.3b8e8685/t/api/04-jobs.t    2025-10-01 
16:36:18.000000000 +0200
+++ new/openQA-5.1759402042.49e912c3/t/api/04-jobs.t    2025-10-02 
12:47:22.000000000 +0200
@@ -292,6 +292,11 @@
       ->json_is({jobs => []});
     $t->get_ok('/api/v1/job_settings/jobs' => form => {key => '%test%', 
list_value => '%test%'})->status_is(400)
       ->json_is({error_status => 400, error => 'Erroneous parameters (key 
invalid, list_value invalid)'});
+    my $value_error = 'either "value" or "list_value" needs to be specified';
+    $t->get_ok('/api/v1/job_settings/jobs' => form => {key => 'KEY'});
+    $t->status_is(400)->json_is('/error', $value_error, 'error if no value or 
list_value specified');
+    $t->get_ok('/api/v1/job_settings/jobs' => form => {key => 'KEY', value => 
'foo', list_value => 'bar'});
+    $t->status_is(400)->json_is('/error', $value_error, 'error if value and 
list_value are both specified');
 
     $t->get_ok('/api/v1/job_settings/jobs' => form => {key => '*_TEST_ISSUES', 
list_value => 26103})->status_is(200)
       ->json_is({jobs => [99926]});
@@ -970,6 +975,26 @@
     is $jobs->find($id)->settings_hash->{WORKER_CLASS}, 'svirt', 'specified 
WORKER_CLASS assigned';
 };
 
+subtest 'array settings correctly assigned when posting job' => sub {
+    my @test_values = qw(foo bar baz);
+    my $test_values_joined = join ',', @test_values;
+    my %array_params = (%jobs_post_params, 'ISSUES[]' => $test_values_joined);
+    my @expected_issues = map { {key => 'ISSUES[]', value => $_} } 
@test_values;
+    $t->post_ok('/api/v1/jobs', form => \%array_params)->status_is(200);
+    ok my $id = $t->tx->res->json->{id}, 'id returned (0)' or always_explain 
$t->tx->res->json;
+    my $job = $jobs->find($id);
+    my $issue_rows = $job->settings->search({key => 'ISSUES[]'}, {order_by => 
{-asc => 'id'}});
+    my @issues = map { {key => $_->key, value => $_->value} } $issue_rows->all;
+    is_deeply \@issues, \@expected_issues, 'issues stored as distinct rows';
+    is $job->settings_hash->{'ISSUES[]'}, $test_values_joined, 'ISSUES joined 
again when accessing hash';
+    $t->get_ok('/api/v1/jobs/' . $id)->status_is(200);
+    $t->json_is('/job/settings/ISSUES[]' => $test_values_joined, 'ISSUES 
joined again when queried via API');
+    for my $value (@test_values) {
+        $t->get_ok('/api/v1/job_settings/jobs' => form => {key => 'ISSUES[]', 
value => $value})->status_is(200);
+        $t->json_is('/jobs', [$id], "job can be retrieved using single value 
$value");
+    }
+};
+
 subtest 'priority correctly assigned when posting job' => sub {
     # post new job and check default priority
     $t->post_ok('/api/v1/jobs', form => \%jobs_post_params)->status_is(200);

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.Epzppj/_old  2025-10-03 15:45:25.597500508 +0200
+++ /var/tmp/diff_new_pack.Epzppj/_new  2025-10-03 15:45:25.609501003 +0200
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1759329378.3b8e8685
-mtime: 1759329378
-commit: 3b8e86855acd7c896b2bf14e212b157c3035f02a
+version: 5.1759402042.49e912c3
+mtime: 1759402042
+commit: 49e912c3ae9327420f34bb58f5edf168bc52dbcb
 

Reply via email to