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-04-08 17:17:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Wed Apr  8 17:17:48 2026 rev:833 rq:1345177 version:5.1775643384.e9cf2643

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2026-04-04 
19:07:29.369302362 +0200
+++ /work/SRC/openSUSE:Factory/.openQA.new.21863/openQA.changes 2026-04-08 
17:18:00.785553336 +0200
@@ -2 +2 @@
-Thu Apr 02 07:37:36 UTC 2026 - [email protected]
+Wed Apr 08 10:16:33 UTC 2026 - [email protected]
@@ -4 +4,12 @@
-- Update to version 5.1775115436.d37d45f6:
+- Update to version 5.1775643384.e9cf2643:
+  * fix: Move Workers constants to Constants.pm
+  * refactor: Remove $VERSION variables from modules
+  * fix(apparmor): let ipmitool read enterprise-numbers
+  * fix(apparmor): add rules for xterm-console
+  * fix(apparmor): allow to start icewm
+  * fix(apparmor): remove unnecessary rules from x3270 profile
+  * test: Cover initdb
+  * fix(apparmor): allow x3270 to write trace files
+  * fix: Let worker init fail for missing working dir
+  * ci(mergify): prevent any unused merge queue checks
+  * test(43-scheduling-and-worker-scalability): automate job count scenarios
@@ -37,0 +49,7 @@
+  * chore(deps): bump picomatch from 2.3.1 to 2.3.2
+  * build(deps-dev): bump flatted from 3.4.1 to 3.4.2
+
+-------------------------------------------------------------------
+Mon Mar 30 20:17:41 UTC 2026 - [email protected]
+
+- Update to version 5.1774895777.6c2911d1:
@@ -46,0 +65,8 @@
+  * feat: support parallel Perl tests with PROVE_JOBS in Makefile
+  * fix(ui): Prevent build tag labels from rendering in all caps
+  * feat: replace Test::Strict with Test::Compile in compilation check
+
+-------------------------------------------------------------------
+Mon Mar 30 08:07:50 UTC 2026 - [email protected]
+
+- Update to version 5.1774854217.24dbd811:
@@ -56 +81,0 @@
-  * feat: support parallel Perl tests with PROVE_JOBS in Makefile
@@ -58 +82,0 @@
-  * fix(ui): Prevent build tag labels from rendering in all caps
@@ -60 +83,0 @@
-  * feat: replace Test::Strict with Test::Compile in compilation check
@@ -71 +93,0 @@
-  * chore(deps): bump picomatch from 2.3.1 to 2.3.2
@@ -72,0 +95,8 @@
+  * feat: replace deprecated fork-awesome with Font Awesome 6 Free
+  * fix(influxdb): prevent empty tags populated to telegraf
+  * feat(MCP): Add MCP tool annotations
+
+-------------------------------------------------------------------
+Thu Mar 26 08:07:45 UTC 2026 - [email protected]
+
+- Update to version 5.1774510397.efec10a7:
@@ -78 +107,0 @@
-  * feat: replace deprecated fork-awesome with Font Awesome 6 Free
@@ -82 +111,5 @@
-  * fix(influxdb): prevent empty tags populated to telegraf
+
+-------------------------------------------------------------------
+Wed Mar 25 01:08:28 UTC 2026 - [email protected]
+
+- Update to version 5.1774384552.1377209d:
@@ -84 +116,0 @@
-  * feat(MCP): Add MCP tool annotations
@@ -101,0 +134,5 @@
+
+-------------------------------------------------------------------
+Mon Mar 23 16:26:14 UTC 2026 - [email protected]
+
+- Update to version 5.1774278862.ea002efa:
@@ -108 +144,0 @@
-  * build(deps-dev): bump flatted from 3.4.1 to 3.4.2
@@ -110,0 +147,6 @@
+  * fix: remove fixed container sizing in needlediff view
+
+-------------------------------------------------------------------
+Mon Mar 23 02:08:22 UTC 2026 - [email protected]
+
+- Update to version 5.1774104919.9788babf:
@@ -115 +156,0 @@
-  * fix: remove fixed container sizing in needlediff view
@@ -158,0 +200,6 @@
+  * fix(investigation): select casedir/needledir correctly when no symlink
+
+-------------------------------------------------------------------
+Fri Mar 13 22:08:20 UTC 2026 - [email protected]
+
+- Update to version 5.1773427330.0b172206:
@@ -163 +209,0 @@
-  * test: Fix unstable test for stacking of parallel tests on overview page
@@ -182 +228,11 @@
-  * fix(investigation): select casedir/needledir correctly when no symlink
+
+-------------------------------------------------------------------
+Fri Mar 13 01:00:04 UTC 2026 - [email protected]
+
+- Update to version 5.1773333964.ffc5eff5:
+  * test: Fix unstable test for stacking of parallel tests on overview page
+
+-------------------------------------------------------------------
+Thu Mar 12 05:26:52 UTC 2026 - [email protected]
+
+- Update to version 5.1773291834.69acf4b4:
@@ -185,0 +242,6 @@
+  * feat: adapt to os-autoinst switching to markdown
+
+-------------------------------------------------------------------
+Tue Mar 10 17:07:52 UTC 2026 - [email protected]
+
+- Update to version 5.1773151075.654d76ed:
@@ -199 +260,0 @@
-  * docs: Link to latest passed job to ensure the download tab exists
@@ -201 +261,0 @@
-  * feat: allow filtering by job result and state in /tests/latest
@@ -206,0 +267,8 @@
+  * feat: add privacy policy
+
+-------------------------------------------------------------------
+Mon Mar 09 15:07:31 UTC 2026 - [email protected]
+
+- Update to version 5.1773068319.a9347c1b:
+  * docs: Link to latest passed job to ensure the download tab exists
+  * feat: allow filtering by job result and state in /tests/latest
@@ -210 +277,0 @@
-  * feat: add privacy policy
@@ -213 +279,0 @@
-  * feat: adapt to os-autoinst switching to markdown
@@ -216 +281,0 @@
-  * style: Use builtin functions without parentheses consistently
@@ -217,0 +283,7 @@
+  * feat: allow users to delete/anonymize their own account
+
+-------------------------------------------------------------------
+Thu Mar 05 16:46:27 UTC 2026 - [email protected]
+
+- Update to version 5.1772722702.3877b2ca:
+  * style: Use builtin functions without parentheses consistently
@@ -218,0 +291,5 @@
+
+-------------------------------------------------------------------
+Thu Mar 05 10:10:51 UTC 2026 - [email protected]
+
+- Update to version 5.1772705410.5c7fe0aa:
@@ -221,0 +299,6 @@
+  * feat: support show_build=1 for overview badges
+
+-------------------------------------------------------------------
+Tue Mar 03 15:10:02 UTC 2026 - [email protected]
+
+- Update to version 5.1772550094.48b5cce5:
@@ -230 +312,0 @@
-  * feat: allow users to delete/anonymize their own account
@@ -238,0 +321,5 @@
+
+-------------------------------------------------------------------
+Mon Mar 02 19:07:33 UTC 2026 - [email protected]
+
+- Update to version 5.1772475695.6c6c7eda:
@@ -240 +327,6 @@
-  * feat: support show_build=1 for overview badges
+  * fix(npm): bump to non-vulerable versions (boo#1259005, boo#1258632)
+
+-------------------------------------------------------------------
+Mon Mar 02 14:07:44 UTC 2026 - [email protected]
+
+- Update to version 5.1772460208.7a4e1e06:
@@ -246 +337,0 @@
-  * fix(npm): bump to non-vulerable versions (boo#1259005, boo#1258632)
@@ -260,0 +352,5 @@
+
+-------------------------------------------------------------------
+Thu Feb 26 18:08:33 UTC 2026 - [email protected]
+
+- Update to version 5.1772092969.74a39650:
@@ -267 +362,0 @@
-  * docs(image): describe the TW image with openQA available in o3
@@ -272,0 +368,11 @@
+  * feat(openqa-upstreams.inc): set `max_conns` to max connection handled
+  * refactor: optimize and harden aggregate overview badges implementation
+  * refactor: improve aggregate overview badges implementation
+  * test: consolidate SVG badge unit tests
+  * feat: implement test result badges for aggregate overview queries
+
+-------------------------------------------------------------------
+Wed Feb 25 20:08:14 UTC 2026 - [email protected]
+
+- Update to version 5.1772031289.93bc2a13:
+  * docs(image): describe the TW image with openQA available in o3
@@ -278 +383,0 @@
-  * feat(openqa-upstreams.inc): set `max_conns` to max connection handled
@@ -280,0 +386,5 @@
+
+-------------------------------------------------------------------
+Tue Feb 24 21:52:18 UTC 2026 - [email protected]
+
+- Update to version 5.1771942065.808b073f:
@@ -285,4 +394,0 @@
-  * refactor: optimize and harden aggregate overview badges implementation
-  * refactor: improve aggregate overview badges implementation
-  * test: consolidate SVG badge unit tests
-  * feat: implement test result badges for aggregate overview queries
@@ -298,0 +405,10 @@
+  * Fix tools/test_helm_chart after Helm chart reorganization
+  * Update Helm chart documentation
+  * Move worker subchart under openqa/ and fix connectivity
+  * Add single openqa parent chart with ingress and nginx
+  * Remove old helm chart structure
+
+-------------------------------------------------------------------
+Mon Feb 23 16:01:06 UTC 2026 - [email protected]
+
+- Update to version 5.1771846996.b67911c1:
@@ -301,0 +418,5 @@
+
+-------------------------------------------------------------------
+Sat Feb 21 20:10:39 UTC 2026 - [email protected]
+
+- Update to version 5.1771626210.b82f14f2:
@@ -303,0 +425,5 @@
+
+-------------------------------------------------------------------
+Fri Feb 20 17:09:47 UTC 2026 - [email protected]
+
+- Update to version 5.1771589939.8f8502b4:
@@ -305,5 +430,0 @@
-  * Fix tools/test_helm_chart after Helm chart reorganization
-  * Update Helm chart documentation
-  * Move worker subchart under openqa/ and fix connectivity
-  * Add single openqa parent chart with ingress and nginx
-  * Remove old helm chart structure
@@ -317,0 +439,8 @@
+  * fix(43-scheduling-and-worker-scalability): prevent sporadic issues
+  * refactor: use join for properties in determine_free_workers
+  * fix: do not cache websocket_api_version if not set
+
+-------------------------------------------------------------------
+Thu Feb 19 13:10:12 UTC 2026 - [email protected]
+
+- Update to version 5.1771473096.98530511:
@@ -323,3 +451,0 @@
-  * fix(43-scheduling-and-worker-scalability): prevent sporadic issues
-  * refactor: use join for properties in determine_free_workers
-  * fix: do not cache websocket_api_version if not set
@@ -353,0 +480,5 @@
+
+-------------------------------------------------------------------
+Tue Feb 10 13:08:35 UTC 2026 - [email protected]
+
+- Update to version 5.1770718745.ce2072d3:
@@ -371,0 +503,7 @@
+  * Bump js-yaml from 4.1.0 to 4.1.1
+  * build(deps): bump ace-builds from 1.43.3 to 1.43.4
+
+-------------------------------------------------------------------
+Thu Feb 05 17:16:04 UTC 2026 - [email protected]
+
+- Update to version 5.1770308102.12dfd0e4:
@@ -415,0 +554,5 @@
+
+-------------------------------------------------------------------
+Thu Jan 29 06:10:03 UTC 2026 - [email protected]
+
+- Update to version 5.1769644379.ef069e9d:
@@ -436,2 +578,0 @@
-  * refactor(investigation): Use TEST_GIT_URL and NEEDLES_GIT_URL
-  * refactor(investigation): Rename gitrepodir function
@@ -440,0 +582,7 @@
+
+-------------------------------------------------------------------
+Tue Jan 27 23:08:10 UTC 2026 - [email protected]
+
+- Update to version 5.1769550212.662a4f95:
+  * refactor(investigation): Use TEST_GIT_URL and NEEDLES_GIT_URL
+  * refactor(investigation): Rename gitrepodir function
@@ -466 +613,0 @@
-  * Dependency cron 2026-01-22
@@ -470,2 +616,0 @@
-  * feat: Show limits on "Next & Previous" tab within table
-  * fix: Avoid Perl warning if product spec contains undef values
@@ -474 +618,0 @@
-  * GenericBug: Add [QE] to the subject
@@ -487,0 +632,14 @@
+
+-------------------------------------------------------------------
+Thu Jan 22 17:43:32 UTC 2026 - [email protected]
+
+- Update to version 5.1769068942.639067ee:
+  * Dependency cron 2026-01-22
+  * feat: Show limits on "Next & Previous" tab within table
+
+-------------------------------------------------------------------
+Wed Jan 21 13:01:48 UTC 2026 - [email protected]
+
+- Update to version 5.1768996386.e3f58202:
+  * fix: Avoid Perl warning if product spec contains undef values
+  * GenericBug: Add [QE] to the subject
@@ -495,0 +654,5 @@
+
+-------------------------------------------------------------------
+Tue Jan 20 13:17:03 UTC 2026 - [email protected]
++++ 446 more lines (skipped)
++++ between /work/SRC/openSUSE:Factory/openQA/openQA.changes
++++ and /work/SRC/openSUSE:Factory/.openQA.new.21863/openQA.changes

Old:
----
  openQA-5.1775115436.d37d45f6.obscpio

New:
----
  openQA-5.1775643384.e9cf2643.obscpio

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

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.eC16ob/_old  2026-04-08 17:18:02.441621526 +0200
+++ /var/tmp/diff_new_pack.eC16ob/_new  2026-04-08 17:18:02.445621690 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1775115436.d37d45f6
+Version:        5.1775643384.e9cf2643
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.eC16ob/_old  2026-04-08 17:18:02.473622843 +0200
+++ /var/tmp/diff_new_pack.eC16ob/_new  2026-04-08 17:18:02.473622843 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-devel
 Name:           %{short_name}-test
-Version:        5.1775115436.d37d45f6
+Version:        5.1775643384.e9cf2643
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.eC16ob/_old  2026-04-08 17:18:02.513624491 +0200
+++ /var/tmp/diff_new_pack.eC16ob/_new  2026-04-08 17:18:02.513624491 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1775115436.d37d45f6
+Version:        5.1775643384.e9cf2643
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.eC16ob/_old  2026-04-08 17:18:02.557626302 +0200
+++ /var/tmp/diff_new_pack.eC16ob/_new  2026-04-08 17:18:02.561626468 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1775115436.d37d45f6
+Version:        5.1775643384.e9cf2643
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.eC16ob/_old  2026-04-08 17:18:02.601628115 +0200
+++ /var/tmp/diff_new_pack.eC16ob/_new  2026-04-08 17:18:02.605628279 +0200
@@ -99,7 +99,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1775115436.d37d45f6
+Version:        5.1775643384.e9cf2643
 Release:        0
 Summary:        The openQA web-frontend, scheduler and tools
 License:        GPL-2.0-or-later

++++++ openQA-5.1775115436.d37d45f6.obscpio -> 
openQA-5.1775643384.e9cf2643.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/.mergify.yml 
new/openQA-5.1775643384.e9cf2643/.mergify.yml
--- old/openQA-5.1775115436.d37d45f6/.mergify.yml       2026-04-02 
09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/.mergify.yml       2026-04-08 
12:16:24.000000000 +0200
@@ -64,3 +64,6 @@
       - and:
           - updated-at<4 days ago
           - author=dependabot[bot]
+queue_rules: []
+merge_queue:
+  status_comments: none
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/codecov.yml 
new/openQA-5.1775643384.e9cf2643/codecov.yml
--- old/openQA-5.1775115436.d37d45f6/codecov.yml        2026-04-02 
09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/codecov.yml        2026-04-08 
12:16:24.000000000 +0200
@@ -21,6 +21,7 @@
         paths:
           - lib/OpenQA/
           - script/create_admin
+          - script/initdb
       tests:
         target: 100.0
         threshold: 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Constants.pm 
new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Constants.pm
--- old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Constants.pm    2026-04-02 
09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Constants.pm    2026-04-08 
12:16:24.000000000 +0200
@@ -108,6 +108,9 @@
     BUILD_SORT_BY_OLDEST_JOB => 2
 };
 
+use constant VNCPORT_OFFSET => $ENV{VNCPORT_OFFSET} // 90;
+use constant VNC_PORT => 5900 + VNCPORT_OFFSET;
+
 our @EXPORT_OK = qw(
   WEBSOCKET_API_VERSION DEFAULT_WORKER_TIMEOUT
   WORKER_COMMAND_ABORT WORKER_COMMAND_QUIT WORKER_COMMAND_CANCEL 
WORKER_COMMAND_OBSOLETE WORKER_COMMAND_LIVELOG_STOP
@@ -124,6 +127,7 @@
   FRAGMENT_REGEX
   JOBS_OVERVIEW_SEARCH_CRITERIA
   BUILD_SORT_BY_NAME BUILD_SORT_BY_NEWEST_JOB BUILD_SORT_BY_OLDEST_JOB
+  VNCPORT_OFFSET VNC_PORT
 );
 
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Log.pm 
new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Log.pm
--- old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Log.pm  2026-04-02 
09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Log.pm  2026-04-08 
12:16:24.000000000 +0200
@@ -17,7 +17,6 @@
 use Sys::Hostname;
 use Feature::Compat::Try;
 
-our $VERSION = '0.0.1';
 our @EXPORT_OK = qw(
   log_debug
   log_trace
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Schema/Result/Workers.pm 
new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Schema/Result/Workers.pm
--- old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Schema/Result/Workers.pm        
2026-04-02 09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Schema/Result/Workers.pm        
2026-04-08 12:16:24.000000000 +0200
@@ -10,7 +10,7 @@
 use OpenQA::App;
 use OpenQA::Log qw(log_error log_warning log_info);
 use OpenQA::WebSockets::Client;
-use OpenQA::Constants qw(WORKER_API_COMMANDS DB_TIMESTAMP_ACCURACY);
+use OpenQA::Constants qw(WORKER_API_COMMANDS DB_TIMESTAMP_ACCURACY VNC_PORT);
 use OpenQA::Jobs::Constants;
 use Mojo::JSON qw(encode_json decode_json);
 use List::Util qw(any);
@@ -19,8 +19,6 @@
 
 use constant WS_SERVER_GRACE_PERIOD => $ENV{OPENQA_WEB_SOCKETS_GRACE_PERIOD} 
// (ONE_MINUTE * 5);
 
-use constant VNC_PORT_OFFSET => 5990;
-
 __PACKAGE__->table('workers');
 __PACKAGE__->load_components(qw(InflateColumn::DateTime Timestamps));
 __PACKAGE__->add_columns(
@@ -254,7 +252,7 @@
 
 sub vnc_argument ($self) {
     my $hostname = $self->get_property('WORKER_HOSTNAME') || $self->host;
-    my $instance = $self->instance + VNC_PORT_OFFSET;
+    my $instance = $self->instance + VNC_PORT;
     return "$hostname:$instance";
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Utils.pm 
new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Utils.pm
--- old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Utils.pm        2026-04-02 
09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Utils.pm        2026-04-08 
12:16:24.000000000 +0200
@@ -89,7 +89,6 @@
 use constant RANDOM_STRING_DEFAULT_LENGTH => 16;
 use constant DEFAULT_OPENQA_BASE_PORT => 9526;
 
-our $VERSION = sprintf '%d.%03d', q$Revision: 1.12 $ =~ /(\d+)/g;
 our @EXPORT = qw(
   UNCONSTRAINED_BUGREF_REGEX
   BUGREF_REGEX
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1775115436.d37d45f6/lib/OpenQA/WebAPI/Description.pm 
new/openQA-5.1775643384.e9cf2643/lib/OpenQA/WebAPI/Description.pm
--- old/openQA-5.1775115436.d37d45f6/lib/OpenQA/WebAPI/Description.pm   
2026-04-02 09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/lib/OpenQA/WebAPI/Description.pm   
2026-04-08 12:16:24.000000000 +0200
@@ -10,7 +10,6 @@
 use Pod::POM;
 use Exporter 'import';
 
-our $VERSION = sprintf '%d.%03d', q$Revision: 0.01 $ =~ /(\d+)/g;
 our @EXPORT = qw(
   get_pod_from_controllers
   set_api_desc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Worker/Settings.pm 
new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Worker/Settings.pm
--- old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Worker/Settings.pm      
2026-04-02 09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Worker/Settings.pm      
2026-04-08 12:16:24.000000000 +0200
@@ -10,6 +10,7 @@
 use Config::IniFiles;
 use Time::Seconds;
 use OpenQA::Config;
+use OpenQA::Constants qw(VNCPORT_OFFSET);
 use OpenQA::Log qw(setup_log log_info);
 use OpenQA::Utils 'is_host_local';
 use Net::Domain 'hostfqdn';
@@ -18,7 +19,6 @@
 has 'webui_hosts';
 has 'webui_host_specific_settings';
 
-use constant VNCPORT_OFFSET => $ENV{VNCPORT_OFFSET} // 90;
 use constant QEMU_PORT_OFFSET => 20_002;
 use constant DEFAULT_CRITICAL_LOAD_AVG_THRESHOLD => 40;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Worker.pm 
new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Worker.pm
--- old/openQA-5.1775115436.d37d45f6/lib/OpenQA/Worker.pm       2026-04-02 
09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/lib/OpenQA/Worker.pm       2026-04-08 
12:16:24.000000000 +0200
@@ -317,6 +317,7 @@
     return 1 if $self->_store_package_list($global_settings->{PACKAGES_CMD});
 
     # initialize clients to connect to the web UIs
+    my $found_working_dir;
     for my $host (@$webui_hosts) {
         die "settings for $host not correctly initialized\n"
           unless my $host_settings = $webui_host_specific_settings->{$host};
@@ -336,6 +337,7 @@
             log_error("Ignoring host '$host': Working directory does not 
exist. (Checked: @working_dirs)");
             next;
         }
+        $found_working_dir = 1;
         $client->working_directory($working_dir);
         log_info("Project dir for host $host is $working_dir");
 
@@ -349,6 +351,7 @@
                 $client->register();
             });
     }
+    $return_code = 1 unless $found_working_dir;
 
     my $interval = $global_settings->{IPMI_AUTOSHUTDOWN_INTERVAL} // 
DEFAULT_IPMI_AUTOSHUTDOWN_INTERVAL;
     if (   $global_settings->{IPMI_HOSTNAME}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/lib/OpenQA/YAML.pm 
new/openQA-5.1775643384.e9cf2643/lib/OpenQA/YAML.pm
--- old/openQA-5.1775115436.d37d45f6/lib/OpenQA/YAML.pm 2026-04-02 
09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/lib/OpenQA/YAML.pm 2026-04-08 
12:16:24.000000000 +0200
@@ -12,7 +12,6 @@
 use YAML::XS;    # Required by JSON::Validator as a runtime dependency
 use YAML::PP 0.027;
 
-our $VERSION = '0.0.1';
 our @EXPORT_OK = qw(
   &validate_data &load_yaml &dump_yaml
 );
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1775115436.d37d45f6/profiles/apparmor.d/usr.share.openqa.script.worker
 
new/openQA-5.1775643384.e9cf2643/profiles/apparmor.d/usr.share.openqa.script.worker
--- 
old/openQA-5.1775115436.d37d45f6/profiles/apparmor.d/usr.share.openqa.script.worker
 2026-04-02 09:37:16.000000000 +0200
+++ 
new/openQA-5.1775643384.e9cf2643/profiles/apparmor.d/usr.share.openqa.script.worker
 2026-04-08 12:16:24.000000000 +0200
@@ -41,7 +41,10 @@
   /etc/qemu/* r,
   /etc/udev/udev.conf r,
   /etc/vde2/vdecmd r,
+  /{usr/,}etc/ssh/ssh_config r,
+  /{usr/,}etc/ssh/ssh_config.d/** r,
   /etc/containers/storage.conf r,
+  /etc/shells r,
   /usr/etc/openqa/client.conf r,
   /usr/etc/openqa/client.conf.d/ r,
   /usr/etc/openqa/client.conf.d/** r,
@@ -85,6 +88,7 @@
   /sys/fs/cgroup/systemd/openqa.slice/** rw,
   /sys/kernel/mm/transparent_hugepage/enabled r,
   /sys/kernel/mm/transparent_hugepage/hpage_pmd_size r,
+  /sys/module/vt/parameters/default_{red,grn,blu} r,
   /tmp/** rwk,
   /usr/bin/Xvnc rCx,
   /{usr/,}bin/cat rix,
@@ -106,7 +110,7 @@
   /usr/bin/gunzip rix,
   /usr/bin/head rix,
   /usr/bin/hostname rix,
-  /usr/bin/icewm-default rix,
+  /usr/bin/icewm{,-default,-lite} cx -> icewm,
   /usr/bin/ionice rix,
   /usr/bin/ipmitool rix,
   /usr/bin/isotovideo rix,
@@ -131,6 +135,8 @@
   /usr/bin/sha1sum rix,
   /usr/bin/slirpvde rix,
   /usr/bin/snd2png rix,
+  /usr/bin/ssh rix,
+  /usr/bin/ssh.hmac r,
   /usr/bin/ssh-keygen rix,
   /usr/bin/tail rix,
   /usr/bin/tee rix,
@@ -140,6 +146,7 @@
   /usr/bin/unxz rix,
   /usr/bin/unzip-plain rix,
   /usr/bin/x3270 cx,
+  /usr/bin/xterm rix,
   /usr/bin/xterm-console rix,
   /usr/bin/xz rix,
   /usr/lib*/qemu/block-curl.so rix,
@@ -156,6 +163,7 @@
   /usr/lib/utempter/utempter rix,
   /usr/sbin/smbd rix,
   /usr/sbin/ipmiconsole rix,
+  /usr/share/misc/enterprise-numbers r,
   /usr/share/openqa/lib/** r,
   /usr/share/openqa/lib/DBIx/Class/Timestamps.pm r,
   /usr/share/openqa/lib/OpenQA/** r,
@@ -185,6 +193,17 @@
   /var/lib/openqa/share/tests/** r,
   owner /sys/**/ rw,
 
+  profile icewm {
+    #include <abstractions/X>
+    #include <abstractions/base>
+    #include <abstractions/fonts>
+
+    /usr/bin/icewm{,-default,-lite} mr,
+    /etc/icewm/** r,
+    /usr/share/icewm/** r,
+    /var/lib/openqa/pool/*/autoinst-log.txt w,
+
+  }
 
   profile /usr/bin/Xvnc {
     #include <abstractions/X>
@@ -230,19 +249,13 @@
 
     /{usr/,}bin/bash rix,
     /dev/ptmx rw,
-    /etc/ssh/ssh_config r,
     /etc/x3270/ibm_hosts r,
     /proc/*/fd/ r,
     /proc/filesystems r,
     /proc/meminfo r,
-    /usr/bin/head rix,
-    /usr/bin/icewm rix,
-    /usr/bin/ssh rix,
     /usr/bin/x3270 mr,
-    /usr/bin/xterm-console rix,
-    /var/lib/openqa/pool/*/known_hosts w,
-    /var/lib/openqa/pool/1/x3scr.*.txt w,
-    /var/lib/openqa/pool/1/x3trc.* w,
+    /var/lib/openqa/pool/*/x3scr.*.txt w,
+    /var/lib/openqa/pool/*/x3trc.* w,
 
   }
   # Site-specific additions and overrides. See local/README for details.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/script/initdb 
new/openQA-5.1775643384.e9cf2643/script/initdb
--- old/openQA-5.1775115436.d37d45f6/script/initdb      2026-04-02 
09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/script/initdb      2026-04-08 
12:16:24.000000000 +0200
@@ -55,9 +55,7 @@
 if ($user) {
     my $uid = getpwnam $user or die "No such login $user";
     my $gid = getgrnam $user;
-    if ($gid) {
-        setgid($gid) || die "can't sgid to $user group";
-    }
+    setgid($gid) || die "can't sgid to $user group" if $gid;
     setuid($uid) || die "can't suid to $user";
 }
 
@@ -106,8 +104,8 @@
         exit 0;
     }
     else {
-        print "Unexpected result from deployment!\n";
-        exit 1;
+        print "Unexpected result from deployment!\n";    # uncoverable 
statement
+        exit 1;    # uncoverable statement
     }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/t/24-worker-overall.t 
new/openQA-5.1775643384.e9cf2643/t/24-worker-overall.t
--- old/openQA-5.1775115436.d37d45f6/t/24-worker-overall.t      2026-04-02 
09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/t/24-worker-overall.t      2026-04-08 
12:16:24.000000000 +0200
@@ -109,8 +109,9 @@
 ok my $settings = $worker->settings, 'settings instantiated';
 my $global_settings = $settings->global_settings;
 delete $global_settings->{LOG_DIR};
-combined_like { $worker->init }
-qr{Ignoring host.*Working directory does not exist.*Checked: 
t/data/openqa/share},
+
+combined_like { is ${$worker->init}, 1, 'no working directory found returns 1' 
}
+qr{Ignoring host.*Working directory does not exist.*Checked: 
t/data/openqa/share.*Ignoring host .*remotehost.*Checked:}s,
   'hosts with non-existent working directory ignored and error logged';
 is $worker->app->level, 'debug', 'log level set to debug with verbose switch';
 my @webui_hosts = sort keys %{$worker->clients_by_webui_host};
@@ -990,5 +991,19 @@
       'ipmitool called correctly';
 };
 
+subtest 'working_directory exists for one of two hosts' => sub {
+    my $worker
+      = OpenQA::Worker->new({instance => 1, apikey => 'foo', apisecret => 
'bar', verbose => 1, 'no-cleanup' => 1});
+    my $tempdir = tempdir("$FindBin::Script-working_dir-XXXX", TMPDIR => 1);
+    my $mock_ws = Test::MockModule->new('OpenQA::Worker::Settings');
+    my $webui_host_specific_settings = {
+        'https://remotehost' => {SHARE_DIRECTORY => "$tempdir"},
+        'http://localhost:9527' => {}};
+    $mock_ws->redefine(webui_host_specific_settings => sub ($self) { 
$webui_host_specific_settings });
+
+    combined_like { is ${$worker->init}, 0, 'at least one working directory 
found returns 0' }
+qr{Ignoring host.*Working directory does not exist.*Checked: 
t/data/openqa/share.*Project dir for host https://remotehost is /tmp}s,
+      'hosts with non-existent working directory ignored and error logged';
+};
 
 done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1775115436.d37d45f6/t/43-scheduling-and-worker-scalability.t 
new/openQA-5.1775643384.e9cf2643/t/43-scheduling-and-worker-scalability.t
--- old/openQA-5.1775115436.d37d45f6/t/43-scheduling-and-worker-scalability.t   
2026-04-02 09:37:16.000000000 +0200
+++ new/openQA-5.1775643384.e9cf2643/t/43-scheduling-and-worker-scalability.t   
2026-04-08 12:16:24.000000000 +0200
@@ -15,7 +15,7 @@
 use Mojo::Util qw(dumper scope_guard);
 use IPC::Run qw(start);
 use FindBin;
-use lib "$FindBin::Bin/lib", 
"$FindBin::Bin/../external/os-autoinst-common/lib";
+use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib", 
"$FindBin::Bin/../external/os-autoinst-common/lib";
 use OpenQA::Constants qw(WEBSOCKET_API_VERSION);
 use OpenQA::Scheduler::Model::Jobs;
 use OpenQA::Utils qw(service_port);
@@ -31,13 +31,8 @@
 
 BEGIN {
     # set defaults
-    $ENV{SCALABILITY_TEST_JOB_COUNT} //= 5;
-    $ENV{SCALABILITY_TEST_WORKER_COUNT} //= 2;
+    $ENV{SCALABILITY_TEST_WORKER_COUNT} //= 5;
     $ENV{SCALABILITY_TEST_WITH_OFFLINE_WEBUI_HOST} //= 1;
-
-    # allow the scheduler to assigns all jobs within one tick (needs to be in 
BEGIN block because the env variable
-    # is assigned to constant)
-    $ENV{OPENQA_SCHEDULER_MAX_JOB_ALLOCATION} = 
$ENV{SCALABILITY_TEST_JOB_COUNT};
 }
 
 setup_mojo_app_with_default_worker_timeout;
@@ -45,22 +40,38 @@
 
 my $load_avg_file = simulate_load('0.93 0.95 3.25 2/2207 1212', 
'43-scheduling-and-worker-scalability');
 
-# read number of workers to spawn from environment variable; skip test 
entirely if variable not present
-# similar to other fullstack tests
+# read number of workers to create
 my $worker_count = $ENV{SCALABILITY_TEST_WORKER_COUNT};
-my $job_count = $ENV{SCALABILITY_TEST_JOB_COUNT} // $worker_count;
-BAIL_OUT 'invalid SCALABILITY_TEST_WORKER_COUNT/SCALABILITY_TEST_JOB_COUNT'
-  if !(looks_like_number($worker_count) && looks_like_number($job_count) && 
$worker_count > 0 && $job_count > 0);
-note "Running scalability test with $worker_count worker(s) and $job_count 
job(s).";
-note 'Set SCALABILITY_TEST_WORKER_COUNT/SCALABILITY_TEST_JOB_COUNT to adjust 
this.';
+BAIL_OUT 'invalid SCALABILITY_TEST_WORKER_COUNT' if 
!looks_like_number($worker_count) || $worker_count <= 0;
+
+# determine job counts for three scenarios: worker count > job count, worker 
count = job count, worker count < job count
+my @job_counts
+  = $ENV{SCALABILITY_TEST_JOB_COUNT}
+  ? ($ENV{SCALABILITY_TEST_JOB_COUNT})
+  : sort { $a <=> $b } grep { $_ > 0 } ($worker_count - 2, $worker_count, 
$worker_count + 2);
+my %seen;
+@job_counts = grep { !$seen{$_}++ } @job_counts;
 
-# setup basedir, config dir and database
+note "Running scalability tests with $worker_count worker(s) and job counts: 
@job_counts.";
+
+# setup basedir, config dir
 my $tempdir = setup_fullstack_temp_dir('scalability');
 chdir $tempdir;
 my $guard = scope_guard sub { chdir $FindBin::Bin };
-my $schema = OpenQA::Test::Database->new->create;
-my $workers = $schema->resultset('Workers');
-my $jobs = $schema->resultset('Jobs');
+
+my $worker_path = path($FindBin::Bin)->child('../script/worker');
+my $isotovideo_path = path($FindBin::Bin)->child('dummy-isotovideo.sh');
+
+sub spawn_worker ($instance, $api_key, $api_secret, $webui_host) {
+    local $ENV{PERL5OPT} = '';    # uncoverable statement
+    note "Starting worker '$instance'";    # uncoverable statement
+    $0 = 'openqa-worker';    # uncoverable statement
+    my @worker_args = (
+        "--apikey=$api_key", "--apisecret=$api_secret", "--host=$webui_host", 
"--isotovideo=$isotovideo_path",
+        '--verbose', '--no-cleanup',
+    );
+    start ['perl', $worker_path, "--instance=$instance", @worker_args];    # 
uncoverable statement
+}
 
 # configure websocket server to apply SCALABILITY_TEST_WORKER_LIMIT
 my $worker_limit = $ENV{SCALABILITY_TEST_WORKER_LIMIT} // 100;
@@ -74,163 +85,165 @@
 $web_socket_server_mock->redefine(_setup => $configure_web_socket_server);
 $configure_web_socket_server->($app);    # invoke this function here for the 
sake of tracking coverage
 
-# create web UI and websocket server
-my $web_socket_server = create_websocket_server(undef, 0, 1, 1);
-my $webui = create_webapi(undef, 1);
-
-# prepare spawning workers
-my $testsdir = path($ENV{OPENQA_BASEDIR}, 'openqa', 'share', 
'tests')->make_path;
-my $resultdir = path($ENV{OPENQA_BASEDIR}, 'openqa', 'testresults')->make_path;
-my $api_credentials = create_user_for_workers;
-my $api_key = $api_credentials->key;
-my $api_secret = $api_credentials->secret;
-my $webui_port = service_port 'webui';
-my $webui_host = "http://localhost:$webui_port";;
-my $worker_path = path($FindBin::Bin)->child('../script/worker');
-my $isotovideo_path = path($FindBin::Bin)->child('dummy-isotovideo.sh');
-$webui_host .= ' http://localhost:12345' if 
$ENV{SCALABILITY_TEST_WITH_OFFLINE_WEBUI_HOST};
-my @worker_args = (
-    "--apikey=$api_key", "--apisecret=$api_secret", "--host=$webui_host", 
"--isotovideo=$isotovideo_path",
-    '--verbose', '--no-cleanup',
-);
-note "Tests dir: $testsdir";
-note "Result dir: $resultdir";
-
-# spawn workers
-note "Spawning $worker_count workers";
-
-sub spawn_worker {
-    my ($instance) = @_;
-
-    local $ENV{PERL5OPT} = '';    # uncoverable statement
-    note "Starting worker '$instance'";    # uncoverable statement
-    $0 = 'openqa-worker';    # uncoverable statement
-    start ['perl', $worker_path, "--instance=$instance", @worker_args];    # 
uncoverable statement
-}
-my %worker_ids;
-my @workers = map { spawn_worker($_) } (1 .. $worker_count);
-
-# create jobs
-note "Creating $job_count jobs";
-
-sub log_jobs {
-    # uncoverable sub only used in case of failures
-    my @job_info
-      # uncoverable statement
-      = map {
-        # uncoverable statement
-        sprintf 'id: %s, state: %s, result: %s, reason: %s', $_->id, 
$_->state, $_->result, $_->reason // 'none'
-      } $jobs->search({}, {order_by => 'id'});
-    # uncoverable statement
-    diag "All jobs:\n - " . join "\n - ", @job_info;
+my @workers;
+my ($web_socket_server, $webui);
+for my $job_count (@job_counts) {
+    subtest "Scalability test with $worker_count worker(s) and $job_count 
job(s)" => sub {
+        # ensure fresh database for each scenario
+        my $schema = OpenQA::Test::Database->new->create;
+        local $ENV{OPENQA_DATABASE_SEARCH_PATH} = 
$schema->search_path_for_tests;
+        my $workers_rs = $schema->resultset('Workers');
+        my $jobs_rs = $schema->resultset('Jobs');
+
+        # ensure the scheduler can assign all jobs within one tick
+        local $ENV{OPENQA_SCHEDULER_MAX_JOB_ALLOCATION} = $job_count;
+
+        # create web UI and websocket server for this scenario
+        $web_socket_server = create_websocket_server(undef, 0, 1, 1);
+        $webui = create_webapi(undef, 1);
+
+        # prepare spawning workers
+        my $api_credentials = create_user_for_workers;
+        my $api_key = $api_credentials->key;
+        my $api_secret = $api_credentials->secret;
+        my $webui_port = service_port 'webui';
+        my $webui_host = "http://localhost:$webui_port";;
+        $webui_host .= ' http://localhost:12345' if 
$ENV{SCALABILITY_TEST_WITH_OFFLINE_WEBUI_HOST};
+
+        my $log_jobs = sub {
+            # uncoverable sub only used in case of failures
+            my @job_info
+              # uncoverable statement
+              = map {
+                # uncoverable statement
+                sprintf 'id: %s, state: %s, result: %s, reason: %s', $_->id, 
$_->state, $_->result, $_->reason // 'none'
+              } $jobs_rs->search({}, {order_by => 'id'})->all;
+            # uncoverable statement
+            diag "All jobs:\n - " . join "\n - ", @job_info;
+        };
+
+        # spawn workers
+        note "Spawning $worker_count workers";
+        @workers = map { spawn_worker($_, $api_key, $api_secret, $webui_host) 
} (1 .. $worker_count);
+
+        # create jobs
+        note "Creating $job_count jobs";
+        my $distri = 'opensuse';
+        my $version = 'Factory';
+        my @job_settings = (
+            BUILD => '0048@0815',
+            DISTRI => $distri,
+            VERSION => $version,
+            FLAVOR => 'tape',
+            ARCH => 'x86_64',
+            MACHINE => 'xxx',
+        );
+        $jobs_rs->create({@job_settings, TEST => "dummy-$_"}) for 1 .. 
$job_count;
+
+        # the casedir must exist before making symlink from casedir to the 
current working directory
+        my $casedir = testcasedir($distri, $version, undef);
+        path($casedir)->make_path unless -d $casedir;
+
+        my $seconds_to_wait_per_worker = 5.0;
+        my $seconds_to_wait_per_job = 2.5;
+        my $polling_interval = 0.1;
+        my $polling_tries_workers = $seconds_to_wait_per_worker / 
$polling_interval * $worker_count;
+        my $polling_tries_jobs = $seconds_to_wait_per_job / $polling_interval 
* $job_count;
+
+        subtest 'wait for workers to be idle' => sub {
+            # wait for all workers to register, have correct API version and 
be idle
+            # this ensures they are fully visible to the scheduler
+            my $actual_count = 0;
+            for my $try (1 .. $polling_tries_workers) {
+                my @idle
+                  = grep { $_->status eq 'idle' && ($_->websocket_api_version 
|| 0) == WEBSOCKET_API_VERSION }
+                  $workers_rs->all;
+                $actual_count = scalar @idle;
+                last if $actual_count == $worker_count;
+                note "Waiting until all workers are registered and idle, try 
$try";    # uncoverable statement
+                sleep $polling_interval;    # uncoverable statement
+            }
+            is $actual_count, $worker_count, 'all workers registered and idle';
+
+            # check that no workers are in unexpected offline/error states
+            my @non_idle_workers;
+            for my $worker ($workers_rs->all) {
+                my $is_idle = $worker->status eq 'idle';
+                push @non_idle_workers, $worker->info    # uncoverable 
statement
+                  if !$is_idle || ($worker->websocket_api_version || 0) != 
WEBSOCKET_API_VERSION;
+            }
+            is scalar @non_idle_workers, 0, 'all workers idling' or 
always_explain \@non_idle_workers;
+        };
+
+        subtest 'assign and run jobs' => sub {
+            my $scheduler = OpenQA::Scheduler::Model::Jobs->singleton;
+
+            # ensure the scheduler also sees them as free
+            for my $try (1 .. $polling_tries_workers) {
+                last if scalar 
@{OpenQA::Scheduler::Model::Jobs::determine_free_workers()} == $worker_count;
+                sleep $polling_interval;    # uncoverable statement
+            }
+
+            # retry scheduling until all workers have a job assigned (or all 
jobs are assigned)
+            my $expected_allocated = min($worker_count, $job_count);
+            for my $try (1 .. $polling_tries_workers) {
+                $scheduler->schedule;
+                last
+                  if $jobs_rs->search({state => {-in => [ASSIGNED, SETUP, 
RUNNING, DONE]}})->count
+                  >= $expected_allocated;
+                sleep $polling_interval;    # uncoverable statement
+            }
+
+            my $allocated_count = $jobs_rs->search({state => {-in => 
[ASSIGNED, SETUP, RUNNING, DONE]}})->count;
+            ok $allocated_count >= $expected_allocated, 'all workers have a 
job or all jobs assigned'
+              or diag "Allocated count: $allocated_count, expected at least: 
$expected_allocated";
+
+            my $remaining_jobs = $job_count - $worker_count;
+            note 'Remaining ' . ($remaining_jobs > 0 ? ('jobs: ' . 
$remaining_jobs) : ('workers: ' . -$remaining_jobs));
+
+            for my $try (1 .. $polling_tries_jobs) {
+                my $done_count = $jobs_rs->search({state => DONE})->count;
+                last if $done_count == $job_count;
+                my $scheduled_count = $jobs_rs->search({state => 
SCHEDULED})->count;
+                if ($scheduled_count > 0) {
+                    note "Trying to assign $scheduled_count scheduled jobs";   
 # uncoverable statement
+                    OpenQA::Scheduler::Model::Jobs->singleton->schedule;    # 
uncoverable statement
+                }
+                note "Waiting until all jobs are done 
($done_count/$job_count), try $try";
+                sleep $polling_interval;    # uncoverable statement
+            }
+            my $done = is $jobs_rs->search({state => DONE})->count, 
$job_count, 'all jobs done';
+            my $passed = is $jobs_rs->search({result => PASSED})->count, 
$job_count, 'all jobs passed';
+            $log_jobs->() unless $done && $passed;
+        };
+
+        subtest 'stop all workers' => sub {
+            stop_service $_ for @workers;
+            @workers = ();
+            my @non_offline_workers;
+            for my $try (1 .. $polling_tries_workers) {
+                @non_offline_workers = ();
+                for my $worker ($workers_rs->all) {
+                    push @non_offline_workers, $worker->id unless 
$worker->dead;
+                }
+                last unless @non_offline_workers;
+                note "Waiting until all workers are offline, try $try";    # 
uncoverable statement
+                sleep $polling_interval;    # uncoverable statement
+            }
+            ok !@non_offline_workers, 'all workers offline' or always_explain 
\@non_offline_workers;
+        };
+
+        stop_service $web_socket_server;
+        stop_service $webui;
+        undef $web_socket_server;
+        undef $webui;
+    };
 }
-my %job_ids;
-my $distri = 'opensuse';
-my $version = 'Factory';
-my @job_settings = (
-    BUILD => '0048@0815',
-    DISTRI => $distri,
-    VERSION => $version,
-    FLAVOR => 'tape',
-    ARCH => 'x86_64',
-    MACHINE => 'xxx',
-);
-$job_ids{$jobs->create({@job_settings, TEST => "dummy-$_"})->id} = 1 for 1 .. 
$job_count;
-
-# the casedir must exist before making symlink from casedir to the current 
working directory
-my $casedir = testcasedir($distri, $version, undef);
-path($casedir)->make_path unless -d $casedir;
-
-my $seconds_to_wait_per_worker = 5.0;
-my $seconds_to_wait_per_job = 2.5;
-my $polling_interval = 0.1;
-my $polling_tries_workers = $seconds_to_wait_per_worker / $polling_interval * 
$worker_count;
-my $polling_tries_jobs = $seconds_to_wait_per_job / $polling_interval * 
$job_count;
-
-subtest 'wait for workers to be idle' => sub {
-    # wait for all workers to register, have correct API version and be idle
-    # this ensures they are fully visible to the scheduler
-    my $actual_count = 0;
-    for my $try (1 .. $polling_tries_workers) {
-        my @idle
-          = grep { $_->status eq 'idle' && ($_->websocket_api_version || 0) == 
WEBSOCKET_API_VERSION } $workers->all;
-        $actual_count = scalar @idle;
-        last if $actual_count == $worker_count;
-        note "Waiting until all workers are registered and idle, try $try";    
# uncoverable statement
-        sleep $polling_interval;    # uncoverable statement
-    }
-    is $actual_count, $worker_count, 'all workers registered and idle';
-
-    # check that no workers are in unexpected offline/error states
-    my @non_idle_workers;
-    for my $worker ($workers->all) {
-        my $is_idle = $worker->status eq 'idle';
-        $worker_ids{$worker->id} = 1 if $is_idle;
-        push @non_idle_workers, $worker->info    # uncoverable statement
-          if !$is_idle || ($worker->websocket_api_version || 0) != 
WEBSOCKET_API_VERSION;
-    }
-    is scalar @non_idle_workers, 0, 'all workers idling' or always_explain 
\@non_idle_workers;
-};
-
-subtest 'assign and run jobs' => sub {
-    my $scheduler = OpenQA::Scheduler::Model::Jobs->singleton;
-
-    # ensure the scheduler also sees them as free
-    for my $try (1 .. $polling_tries_workers) {
-        last if scalar 
@{OpenQA::Scheduler::Model::Jobs::determine_free_workers()} == $worker_count;
-        sleep $polling_interval;    # uncoverable statement
-    }
-
-    # retry scheduling until all workers have a job assigned (or all jobs are 
assigned)
-    my $expected_allocated = min($worker_count, $job_count);
-    for my $try (1 .. $polling_tries_workers) {
-        $scheduler->schedule;
-        last if $jobs->search({state => {-in => [ASSIGNED, SETUP, RUNNING, 
DONE]}})->count >= $expected_allocated;
-        sleep $polling_interval;    # uncoverable statement
-    }
-
-    my $allocated_count = $jobs->search({state => {-in => [ASSIGNED, SETUP, 
RUNNING, DONE]}})->count;
-    ok $allocated_count >= $expected_allocated, 'all workers have a job or all 
jobs assigned'
-      or diag "Allocated count: $allocated_count, expected at least: 
$expected_allocated";
-
-    my $remaining_jobs = $job_count - $worker_count;
-    note 'Remaining ' . ($remaining_jobs > 0 ? ('jobs: ' . $remaining_jobs) : 
('workers: ' . -$remaining_jobs));
-
-    for my $try (1 .. $polling_tries_jobs) {
-        my $done_count = $jobs->search({state => DONE})->count;
-        last if $done_count == $job_count;
-        my $scheduled_count = $jobs->search({state => SCHEDULED})->count;
-        if ($scheduled_count > 0) {
-            note "Trying to assign $scheduled_count scheduled jobs";
-            OpenQA::Scheduler::Model::Jobs->singleton->schedule;
-        }
-        note "Waiting until all jobs are done ($done_count/$job_count), try 
$try";
-        sleep $polling_interval;
-    }
-    my $done = is $jobs->search({state => DONE})->count, $job_count, 'all jobs 
done';
-    my $passed = is $jobs->search({result => PASSED})->count, $job_count, 'all 
jobs passed';
-    log_jobs unless $done && $passed;
-};
-
-subtest 'stop all workers' => sub {
-    stop_service $_ for @workers;
-    my @non_offline_workers;
-    for my $try (1 .. $polling_tries_workers) {
-        @non_offline_workers = ();
-        for my $worker ($workers->all) {
-            push @non_offline_workers, $worker->id unless $worker->dead;
-        }
-        last unless @non_offline_workers;
-        note "Waiting until all workers are offline, try $try";    # 
uncoverable statement
-        sleep $polling_interval;    # uncoverable statement
-    }
-    ok !@non_offline_workers, 'all workers offline' or always_explain 
\@non_offline_workers;
-};
 
 done_testing;
 
 END {
     stop_service $_ for @workers;
-    stop_service $web_socket_server;
-    stop_service $webui;
+    stop_service $web_socket_server if $web_socket_server;
+    stop_service $webui if $webui;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1775115436.d37d45f6/t/44-scripts-initdb.t 
new/openQA-5.1775643384.e9cf2643/t/44-scripts-initdb.t
--- old/openQA-5.1775115436.d37d45f6/t/44-scripts-initdb.t      1970-01-01 
01:00:00.000000000 +0100
+++ new/openQA-5.1775643384.e9cf2643/t/44-scripts-initdb.t      2026-04-08 
12:16:24.000000000 +0200
@@ -0,0 +1,64 @@
+#!/usr/bin/env perl
+# Copyright SUSE LLC
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+use Test::Most;
+use Mojo::Base -signatures;
+use Test::Warnings ':report_warnings';
+
+use FindBin '$Bin';
+use lib "$FindBin::Bin/lib", 
"$FindBin::Bin/../external/os-autoinst-common/lib";
+use OpenQA::Test::TimeLimit '10';
+use OpenQA::Test::Database;
+use File::Copy::Recursive qw(dircopy);
+use Mojo::File qw(path tempdir);
+
+my $now = time;
+my $schema_name = OpenQA::Test::Database::generate_schema_name;
+my $schema_version = $OpenQA::Schema::VERSION - 1;
+$ENV{OPENQA_DATABASE} = 'test';
+$ENV{OPENQA_DATABASE_SEARCH_PATH} = $schema_name;
+$ENV{OPENQA_SCHEMA_VERSION_OVERRIDE} = $schema_version;
+
+my $schema = OpenQA::Schema::connect_db(deploy => 0, silent => 1, from_script 
=> 1);
+$schema->storage->dbh->do("create schema \"$schema_name\"");
+
+my $tempdir = tempdir;
+my $dbicdh_dir = path($FindBin::RealBin, '../dbicdh');
+dircopy $dbicdh_dir, $tempdir or BAIL_OUT "Unable to make temporary dbicdh 
dir: $!";
+
+my $cmd = "$Bin/../script/initdb";
+my $output = qx{"$cmd" --prepare_init --init_database --dir="$tempdir" --force 
--user "$ENV{USER}" 2>&1};
+is $?, 0, 'command exited with zero return code';
+like $output, qr/overwriting.*$tempdir/i, 'files in temp dbicdh dir specified 
via --dir overwritten via --force flag';
+like $output, qr/Database initialized/i, 'database initialized';
+ok $schema->resultset('Users')->find({username => 'system'}), 'system user has 
been created';
+
+my $sql_mtime = 
$tempdir->child("PostgreSQL/deploy/$schema_version/001-auto.sql")->stat->mtime;
+cmp_ok $sql_mtime, '>=', $now, 'SQL code for deployment of current schema 
version has been updated';
+
+subtest 'database exists and is up to data' => sub {
+    my $output = qx{"$cmd" --init_database --dir="$tempdir" 2>&1};
+    is $? >> 8, 4, 'command exited with return code 4';
+    like $output, qr/Database already exists and schema is up to date/i, 
'nothing to do';
+};
+
+$ENV{OPENQA_SCHEMA_VERSION_OVERRIDE} = ++$schema_version;
+
+subtest 'deploy directory already contains the schema' => sub {
+    my $output = qx{"$cmd" --prepare_init --init_database --dir="$tempdir" 
2>&1};
+    is $? >> 8, 1, 'command exited with return code 1';
+    unlike $output, qr/overwriting.*$tempdir/i, 'files in temp dbicdh dir 
specified via --dir overwritten via --force';
+    like $output, qr/use.*--force/i, 'use of --force suggested';
+};
+
+subtest 'database exists but needs updating' => sub {
+    my $output = qx{"$cmd" --prepare_init --init_database --dir="$tempdir" 
--force 2>&1};
+    is $?, 0, 'command exited with zero return code';
+    like $output, qr/overwriting.*$tempdir/i, 'files in temp dbicdh dir 
specified via --dir overwritten via --force';
+    like $output, qr/Database already exists, but schema was upgraded/i, 
'schema was upgraded';
+    my $sql_mtime = 
$tempdir->child("PostgreSQL/deploy/$schema_version/001-auto.sql")->stat->mtime;
+    cmp_ok $sql_mtime, '>=', $now, 'SQL code for deployment of current schema 
version has been updated';
+};
+
+done_testing;

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.eC16ob/_old  2026-04-08 17:18:23.226477362 +0200
+++ /var/tmp/diff_new_pack.eC16ob/_new  2026-04-08 17:18:23.230477528 +0200
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1775115436.d37d45f6
-mtime: 1775115436
-commit: d37d45f6bc93713ff653b54288eb576fa5ac8c8c
+version: 5.1775643384.e9cf2643
+mtime: 1775643384
+commit: e9cf2643a809d4429843d924729fa374c5a09e88
 

Reply via email to