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
