Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package openQA for openSUSE:Factory checked 
in at 2026-09-28 10:40:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.383539 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Mon Sep 28 10:40:39 2026 rev:883 rq:1380339 version:5.1790312789.f59cf41c

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2026-09-24 
23:06:17.827442940 +0200
+++ /work/SRC/openSUSE:Factory/.openQA.new.383539/openQA.changes        
2026-09-28 10:41:25.083298740 +0200
@@ -1,0 +2,26 @@
+Fri Sep 25 05:06:40 UTC 2026 - [email protected]
+
+- Update to version 5.1790312789.f59cf41c:
+  * chore(deps): Dependency cron 2026-09-25
+  * refactor: Reduce parameters of `update_note`
+  * refactor: Reduce parameters of `job_statistics`
+  * feat(job-stats): Allow specifying the setting to add additional jobs by
+  * docs: Update documentation of `/isos/job_stats` after recent changes
+  * feat: Return only "latest" jobs in `/isos/job_stats`
+  * feat: Include additional jobs for submission in `/isos/job_stats`
+  * test(devel-fullstack): Fix waiting for `outstanding_images`
+
+-------------------------------------------------------------------
+Thu Sep 24 19:06:47 UTC 2026 - [email protected]
+
+- Update to version 5.1790273241.6c254f29:
+  * refactor: Reduce parameters of `update_note`
+  * refactor: Reduce parameters of `job_statistics`
+  * feat(job-stats): Allow specifying the setting to add additional jobs by
+  * docs: Update documentation of `/isos/job_stats` after recent changes
+  * feat: Return only "latest" jobs in `/isos/job_stats`
+  * feat: Include additional jobs for submission in `/isos/job_stats`
+  * test(devel-fullstack): Fix waiting for `outstanding_images`
+  * feat(cli): Add worker reservation subcommand
+
+-------------------------------------------------------------------

Old:
----
  openQA-5.1790264833.381b79cd.obscpio

New:
----
  openQA-5.1790312789.f59cf41c.obscpio

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

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.1GbCbZ/_old  2026-09-28 10:41:27.849414731 +0200
+++ /var/tmp/diff_new_pack.1GbCbZ/_new  2026-09-28 10:41:27.850414773 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1790264833.381b79cd
+Version:        5.1790312789.f59cf41c
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.1GbCbZ/_old  2026-09-28 10:41:27.921417751 +0200
+++ /var/tmp/diff_new_pack.1GbCbZ/_new  2026-09-28 10:41:27.923417835 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-devel
 Name:           %{short_name}-test
-Version:        5.1790264833.381b79cd
+Version:        5.1790312789.f59cf41c
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.1GbCbZ/_old  2026-09-28 10:41:27.987420518 +0200
+++ /var/tmp/diff_new_pack.1GbCbZ/_new  2026-09-28 10:41:27.991420686 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1790264833.381b79cd
+Version:        5.1790312789.f59cf41c
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.1GbCbZ/_old  2026-09-28 10:41:28.054423328 +0200
+++ /var/tmp/diff_new_pack.1GbCbZ/_new  2026-09-28 10:41:28.059423538 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1790264833.381b79cd
+Version:        5.1790312789.f59cf41c
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.1GbCbZ/_old  2026-09-28 10:41:28.117425970 +0200
+++ /var/tmp/diff_new_pack.1GbCbZ/_new  2026-09-28 10:41:28.124426263 +0200
@@ -104,7 +104,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1790264833.381b79cd
+Version:        5.1790312789.f59cf41c
 Release:        0
 Summary:        Framework for automated system-level testing (web-frontend, 
scheduler and tools)
 Group:          Development/Tools/Other

++++++ openQA-5.1790264833.381b79cd.obscpio -> 
openQA-5.1790312789.f59cf41c.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1790264833.381b79cd/lib/OpenQA/Schema/ResultSet/ScheduledProducts.pm
 
new/openQA-5.1790312789.f59cf41c/lib/OpenQA/Schema/ResultSet/ScheduledProducts.pm
--- 
old/openQA-5.1790264833.381b79cd/lib/OpenQA/Schema/ResultSet/ScheduledProducts.pm
   2026-09-24 17:47:13.000000000 +0200
+++ 
new/openQA-5.1790312789.f59cf41c/lib/OpenQA/Schema/ResultSet/ScheduledProducts.pm
   2026-09-25 07:06:29.000000000 +0200
@@ -5,6 +5,7 @@
 
 use Mojo::Base 'DBIx::Class::ResultSet', -signatures;
 use Mojo::JSON qw(encode_json);
+use OpenQA::Schema::Result::Jobs;
 use OpenQA::Schema::Result::ScheduledProducts qw(CANCELLED);
 use OpenQA::App;
 
@@ -31,7 +32,7 @@
     return {jobs_cancelled => $count};
 }
 
-sub update_note ($self, $distri, $version, $flavor, $arch, $build, $note) {
+sub update_note ($self, $params, $note) {
     my $sth = $self->result_source->schema->storage->dbh->prepare(
         <<~'END_SQL'
         UPDATE scheduled_products SET results['note'] = ? where id = (
@@ -43,17 +44,13 @@
         ) RETURNING id;
         END_SQL
     );
-    $sth->bind_param(1, encode_json($note));
-    $sth->bind_param(2, $distri);
-    $sth->bind_param(3, $version);
-    $sth->bind_param(4, $flavor);
-    $sth->bind_param(5, $arch);
-    $sth->bind_param(6, $build);
-    $sth->execute;
+    $sth->execute(encode_json($note), @$params);
     return {updated_product_id => $sth->fetchrow_arrayref->[0]};
 }
 
-sub job_statistics ($self, $distri, $version, $flavor, $arch, $build, 
$group_ids = undef, $include_null_groups = 0) {
+my $MAIN_SETTINGS_GROUP_BY = join ',', 
OpenQA::Schema::Result::Jobs::MAIN_SETTINGS;
+
+sub job_statistics ($self, $params, $group_ids, $include_null_groups) {
     my $group_filter = '';
     my @binds;
     if ($group_ids && @$group_ids) {
@@ -64,6 +61,22 @@
     my $sth = $self->result_source->schema->storage->dbh->prepare(
         <<~"END_SQL"
         WITH RECURSIVE
+        -- get the scheduled product
+        most_recent_scheduled_product AS (
+            SELECT
+                max(id) as id,
+                max(t_created) as t_created,
+                any_value(settings ->> ?) as submission_id
+            FROM
+                scheduled_products
+            WHERE
+                status in ('new', 'scheduling', 'scheduled') and distri = ? 
and version = ? and flavor = ? and arch = ? and build = ?
+            GROUP BY
+                arch
+            ORDER BY
+                id DESC
+            LIMIT 1
+        ),
         -- get the initial set of jobs in the scheduled product
         initial_job_ids AS (
             SELECT
@@ -72,16 +85,19 @@
             FROM
                 jobs
             WHERE
-                jobs.scheduled_product_id in (
-                    SELECT
-                        max(id)
-                    FROM
-                        scheduled_products
-                    WHERE
-                        status in ('new', 'scheduling', 'scheduled') and 
distri = ? and version = ? and flavor = ? and arch = ? and build = ?
-                    GROUP BY
-                        arch
-                )
+                jobs.scheduled_product_id in (SELECT id FROM 
most_recent_scheduled_product)
+            UNION ALL
+            SELECT
+                job_settings.job_id AS job_id,
+                null AS scheduled_product_id
+            FROM
+                job_settings
+            JOIN
+                jobs ON jobs.id = job_settings.job_id
+            WHERE
+                key = ? and value = (SELECT submission_id FROM 
most_recent_scheduled_product)
+                and jobs.t_created >= (SELECT t_created FROM 
most_recent_scheduled_product)
+                and distri = ? and version = ? and flavor = ? and arch = ? and 
build = ?
         ),
         -- find more recent jobs for each initial job recursively
         latest_id_resolver AS (
@@ -112,6 +128,7 @@
             SELECT DISTINCT ON (job_id)
                 job_id as initial_job_id,
                 latest_job_id,
+                $MAIN_SETTINGS_GROUP_BY,
                 mrj.state as latest_job_state,
                 mrj.result as latest_job_result,
                 mrj.scheduled_product_id as scheduled_product_id,
@@ -123,16 +140,28 @@
                 latest_job_id IS NOT NULL
                 $group_filter
             ORDER BY
-                job_id,
+                job_id DESC, $MAIN_SETTINGS_GROUP_BY,
                 level DESC
+        ),
+        -- deduplicated jobs by $MAIN_SETTINGS_GROUP_BY returning only the 
"latest"
+        deduplicated_jobs AS (
+            SELECT DISTINCT ON ($MAIN_SETTINGS_GROUP_BY)
+                latest_job_id,
+                latest_job_state,
+                latest_job_result,
+                scheduled_product_id,
+                $MAIN_SETTINGS_GROUP_BY
+            FROM most_recent_jobs
+            ORDER BY $MAIN_SETTINGS_GROUP_BY, latest_job_id DESC
         )
         SELECT
             latest_job_state,
             latest_job_result,
             array_agg(latest_job_id) as job_ids,
-            array_agg(DISTINCT scheduled_product_id) as scheduled_product_ids
+            array_agg(DISTINCT scheduled_product_id) as scheduled_product_ids,
+            (SELECT submission_id from most_recent_scheduled_product)
         FROM
-            most_recent_jobs
+            deduplicated_jobs
         WHERE
             latest_job_id IS NOT NULL
         GROUP BY
@@ -140,7 +169,7 @@
             latest_job_result
         END_SQL
     );
-    $sth->execute($distri, $version, $flavor, $arch, $build, @binds);
+    $sth->execute((@$params) x 2, @binds);
     return $sth->fetchall_hashref([qw(latest_job_state latest_job_result)]);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1790264833.381b79cd/lib/OpenQA/WebAPI/Controller/API/V1/Iso.pm 
new/openQA-5.1790312789.f59cf41c/lib/OpenQA/WebAPI/Controller/API/V1/Iso.pm
--- old/openQA-5.1790264833.381b79cd/lib/OpenQA/WebAPI/Controller/API/V1/Iso.pm 
2026-09-24 17:47:13.000000000 +0200
+++ new/openQA-5.1790312789.f59cf41c/lib/OpenQA/WebAPI/Controller/API/V1/Iso.pm 
2026-09-25 07:06:29.000000000 +0200
@@ -66,8 +66,8 @@
 specified DISTRI, VERSION, FLAVOR, ARCH and BUILD parameters. Scheduled 
products
 that are cancelling/cancelled are not considered.
 
-This allows to determine whether all jobs that have been scheduled for a
-certain purpose are done and whether the jobs have passed. If jobs have been
+This allows determining whether all jobs that have been scheduled for a certain
+purpose are done and whether the jobs have passed. If jobs have been
 cloned/restarted then only the state/result of the latest job is taken into
 account.
 
@@ -86,6 +86,13 @@
 product IDs for each combination are mainly returned for easier retracing but
 could also be used to generate a more detailed report.
 
+If a scheduled product has a SUBMISSION_ID setting (or the setting specified 
via
+`additional_jobs_by`), additional jobs that have been created with that setting
+are returned as well.
+
+Jobs are deduplicated by their main settings like with `/jobs?latest` (see
+documentation of that route for details).
+
 =back
 
 =cut
@@ -98,7 +105,8 @@
     my $include_null_groups
       = ($self->validation->param('not_group_glob') && 
!$self->validation->param('group_glob')) ? 1 : 0;
     my $scheduled_products = 
$self->app->schema->resultset('ScheduledProducts');
-    $self->render(json => $scheduled_products->job_statistics(@$params, 
$group_ids, $include_null_groups));
+    unshift @$params, $self->param('additional_jobs_by') // 'SUBMISSION_ID';
+    $self->render(json => $scheduled_products->job_statistics($params, 
$group_ids, $include_null_groups));
 }
 
 =over 4
@@ -119,7 +127,7 @@
     $validation->required('note');
     return undef unless my $params = $self->_get_iso_params_and_validate;
     my $scheduled_products = 
$self->app->schema->resultset('ScheduledProducts');
-    $self->render(json => $scheduled_products->update_note(@$params, 
$validation->param('note')));
+    $self->render(json => $scheduled_products->update_note($params, 
$validation->param('note')));
 }
 
 sub validate_create_parameters ($self) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1790264833.381b79cd/t/api/02-iso.t 
new/openQA-5.1790312789.f59cf41c/t/api/02-iso.t
--- old/openQA-5.1790264833.381b79cd/t/api/02-iso.t     2026-09-24 
17:47:13.000000000 +0200
+++ new/openQA-5.1790312789.f59cf41c/t/api/02-iso.t     2026-09-25 
07:06:29.000000000 +0200
@@ -10,6 +10,7 @@
 use lib "$FindBin::Bin/../lib", 
"$FindBin::Bin/../../external/os-autoinst-common/lib";
 use Test::Mojo;
 use Test::Warnings ':report_warnings';
+use DateTime::Duration;
 use OpenQA::Jobs::Constants;
 use OpenQA::JobDependencies::Constants;
 use OpenQA::Test::TimeLimit '300';
@@ -27,6 +28,7 @@
 my $products = $schema->resultset('Products');
 my $test_suites = $schema->resultset('TestSuites');
 my $jobs = $schema->resultset('Jobs');
+my $job_settings = $schema->resultset('JobSettings');
 my $scheduled_products = $schema->resultset('ScheduledProducts');
 my $gru_tasks = $schema->resultset('GruTasks');
 my $limits = $cfg->{misc_limits};
@@ -319,20 +321,61 @@
 subtest 'job statistics can be queried about the scheduled product' => sub {
     $schema->txn_begin;
     # assume some of the scheduled jobs are already done
+    my $scheduled_product = $scheduled_products->find(4);
+    my $second = DateTime::Duration->new(seconds => 1);
+    my @params = (DISTRI => 'opensuse', VERSION => '13.1', FLAVOR => 'DVD', 
ARCH => 'i586', BUILD => '0091');
     $jobs->find(99985)->update({state => DONE, result => INCOMPLETE});
     $jobs->find(99988)->update({state => DONE, result => FAILED});
-    $jobs->find(99993)->update({state => DONE, result => PASSED});
-    $jobs->find(99994)->update({state => DONE, result => PASSED});
+    $jobs->find(99993)->update({state => DONE, result => PASSED, TEST => 
'foo'});
+    $jobs->find(99994)->update({state => DONE, result => PASSED, TEST => 
'foo'});
+    $jobs->find(80000)->update({@params, t_created => 
$scheduled_product->t_created - $second});    # older than sp
+    $jobs->find(99764)->update({@params, t_created => 
$scheduled_product->t_created + $second});    # newer than sp
+    $job_settings->create({job_id => 80000, key => 'SUBMISSION_ID', value => 
'increment:1234'});
+    $job_settings->create({job_id => 99764, key => 'SUBMISSION_ID', value => 
'increment:1234'});
+
     $t->get_ok("/api/v1/isos/job_stats?$params")->status_is(200);
-    $schema->txn_rollback;
     my $json = $t->tx->res->json;
     is_deeply [sort keys %$json], [DONE, SCHEDULED], 'expected states present';
     is_deeply [sort keys %{$json->{done}}], [FAILED, INCOMPLETE, PASSED], 
'expected results present';
     is_deeply [sort @{$json->{done}->{failed}->{job_ids}}], [99988], 'failed 
jobs';
     is_deeply [sort @{$json->{done}->{incomplete}->{job_ids}}], [99985], 
'incomplete jobs';
-    is_deeply [sort @{$json->{done}->{passed}->{job_ids}}], [99993, 99994], 
'passed jobs';
+    is_deeply [sort @{$json->{done}->{passed}->{job_ids}}], [99994], 'passed 
jobs';
     is_deeply [sort @{$json->{scheduled}->{none}->{job_ids}}], [99986, 99987, 
99989, 99990, 99991, 99992],
       'scheduled jobs';
+
+    subtest 'additional jobs for submission are pulled-in via SUBMISSION_ID' 
=> sub {
+        $scheduled_product->update_setting(SUBMISSION_ID => 'increment:1234');
+        $t->get_ok("/api/v1/isos/job_stats?$params")->status_is(200);
+        my $json = $t->tx->res->json;
+        is_deeply [sort keys %$json], [DONE, SCHEDULED], 'expected states 
present';
+        is_deeply [sort keys %{$json->{done}}], [FAILED, INCOMPLETE, PASSED], 
'expected results present';
+        is_deeply [sort @{$json->{done}->{passed}->{job_ids}}], [99764, 99994],
+          'passed jobs: job newer than sp with matching SUBMISSION_ID 
included';
+        is_deeply [sort @{$json->{done}->{failed}->{job_ids}}], [99988], 
'failed jobs';
+        is_deeply [sort @{$json->{done}->{incomplete}->{job_ids}}], [99985], 
'incomplete jobs';
+        is_deeply [sort @{$json->{scheduled}->{none}->{job_ids}}], [99986, 
99987, 99989, 99990, 99991, 99992],
+          'scheduled jobs';
+    };
+
+    subtest 'additional jobs can be pulled-in via custom setting using 
additional_jobs_by' => sub {
+        $scheduled_product->update_setting(SUBMISSION_ID => 'different_val');
+        $scheduled_product->update_setting(REQUEST_ID => 'req:42');
+        $job_settings->create({job_id => 99764, key => 'REQUEST_ID', value => 
'req:42'});
+
+        # without additional_jobs_by, default SUBMISSION_ID is used and 
doesn't match
+        $t->get_ok("/api/v1/isos/job_stats?$params")->status_is(200);
+        my $json = $t->tx->res->json;
+        is_deeply [sort @{$json->{done}->{passed}->{job_ids}}], [99994],
+          'job 99764 not included because SUBMISSION_ID does not match';
+
+        # with additional_jobs_by=REQUEST_ID, REQUEST_ID matches
+        
$t->get_ok("/api/v1/isos/job_stats?$params&additional_jobs_by=REQUEST_ID")->status_is(200);
+        $json = $t->tx->res->json;
+        is_deeply [sort @{$json->{done}->{passed}->{job_ids}}], [99764, 99994],
+          'passed jobs: job newer than sp with matching REQUEST_ID included 
via additional_jobs_by';
+    };
+
+    $schema->txn_rollback;
 };
 
 subtest 'job statistics can be filtered by job groups' => sub {
@@ -362,7 +405,6 @@
     $schema->txn_rollback;
 };
 
-
 subtest 'note can be updated by distri, version, flavor, arch and build 
parameters' => sub {
     $t->put_ok("/api/v1/experimental/isos/note?$params");
     $t->status_is(400, 'error returned if parameter missing');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1790264833.381b79cd/tools/ci/autoinst.sha 
new/openQA-5.1790312789.f59cf41c/tools/ci/autoinst.sha
--- old/openQA-5.1790264833.381b79cd/tools/ci/autoinst.sha      2026-09-24 
17:47:13.000000000 +0200
+++ new/openQA-5.1790312789.f59cf41c/tools/ci/autoinst.sha      2026-09-25 
07:06:29.000000000 +0200
@@ -1 +1 @@
-5.044000-282ca44441fdf0dfd37891bdf1d73c35bfc152de
\ No newline at end of file
+5.044000-67006216e29f8e8655bad025ea594b14fd2eaf79
\ No newline at end of file

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.1GbCbZ/_old  2026-09-28 10:41:35.645741653 +0200
+++ /var/tmp/diff_new_pack.1GbCbZ/_new  2026-09-28 10:41:35.649741820 +0200
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1790264833.381b79cd
-mtime: 1790264833
-commit: 381b79cd3be82c79d4499f5b7b66242a550ef46d
+version: 5.1790312789.f59cf41c
+mtime: 1790312789
+commit: f59cf41c9b1df25ef268f9beb77753a2fd8b132f
 

Reply via email to