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-05-04 12:51:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.30200 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Mon May  4 12:51:19 2026 rev:842 rq:1350373 version:5.1777617029.fd9e1e69

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2026-04-30 
20:32:04.918931431 +0200
+++ /work/SRC/openSUSE:Factory/.openQA.new.30200/openQA.changes 2026-05-04 
12:53:59.818664554 +0200
@@ -1,0 +2,16 @@
+Fri May 01 06:30:37 UTC 2026 - [email protected]
+
+- Update to version 5.1777617029.fd9e1e69:
+  * style: Enforce perlcritic policy ProhibitSingleCharAlternation
+  * fix(apparmor): Add jsonnet to worker profile
+  * style: Enforce perlcritic policy CodeLayout::ProhibitQuotedWordLists
+  * style: Enforce perlcritic policy RequireNumberSeparators
+  * build(deps-dev): bump eslint from 10.1.0 to 10.2.1
+  * style: Enforce perlcritic policy Variables::ProhibitUnusedVariables
+  * feat: Ensure temporary directory exists when caching assets
+  * fix(docs): fix mobile view rendering by ensuring CSS override
+  * chore(lint): extend stylelint to cover documentation CSS
+  * refactor: break down create_from_settings into smaller functions
+  * feat: automatically add configurable worker classes to jobs
+
+-------------------------------------------------------------------

Old:
----
  openQA-5.1777474261.55e5cd5e.obscpio

New:
----
  openQA-5.1777617029.fd9e1e69.obscpio

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

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.tZPAXP/_old  2026-05-04 12:54:04.174843843 +0200
+++ /var/tmp/diff_new_pack.tZPAXP/_new  2026-05-04 12:54:04.182844172 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1777474261.55e5cd5e
+Version:        5.1777617029.fd9e1e69
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.tZPAXP/_old  2026-05-04 12:54:04.482856519 +0200
+++ /var/tmp/diff_new_pack.tZPAXP/_new  2026-05-04 12:54:04.498857178 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-devel
 Name:           %{short_name}-test
-Version:        5.1777474261.55e5cd5e
+Version:        5.1777617029.fd9e1e69
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.tZPAXP/_old  2026-05-04 12:54:04.774868538 +0200
+++ /var/tmp/diff_new_pack.tZPAXP/_new  2026-05-04 12:54:04.798869526 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1777474261.55e5cd5e
+Version:        5.1777617029.fd9e1e69
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.tZPAXP/_old  2026-05-04 12:54:05.078881051 +0200
+++ /var/tmp/diff_new_pack.tZPAXP/_new  2026-05-04 12:54:05.090881545 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1777474261.55e5cd5e
+Version:        5.1777617029.fd9e1e69
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.tZPAXP/_old  2026-05-04 12:54:05.482897679 +0200
+++ /var/tmp/diff_new_pack.tZPAXP/_new  2026-05-04 12:54:05.506898667 +0200
@@ -99,7 +99,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1777474261.55e5cd5e
+Version:        5.1777617029.fd9e1e69
 Release:        0
 Summary:        The openQA web-frontend, scheduler and tools
 License:        GPL-2.0-or-later

++++++ node_modules.obscpio ++++++
Binary files old/@eslint-config-array-0.23.3.tgz and 
new/@eslint-config-array-0.23.3.tgz differ
Binary files old/@eslint-config-array-0.23.5.tgz and 
new/@eslint-config-array-0.23.5.tgz differ
Binary files old/@eslint-config-helpers-0.5.3.tgz and 
new/@eslint-config-helpers-0.5.3.tgz differ
Binary files old/@eslint-config-helpers-0.5.5.tgz and 
new/@eslint-config-helpers-0.5.5.tgz differ
Binary files old/@eslint-core-1.1.1.tgz and new/@eslint-core-1.1.1.tgz differ
Binary files old/@eslint-core-1.2.1.tgz and new/@eslint-core-1.2.1.tgz differ
Binary files old/@eslint-object-schema-3.0.3.tgz and 
new/@eslint-object-schema-3.0.3.tgz differ
Binary files old/@eslint-object-schema-3.0.5.tgz and 
new/@eslint-object-schema-3.0.5.tgz differ
Binary files old/@eslint-plugin-kit-0.6.1.tgz and 
new/@eslint-plugin-kit-0.6.1.tgz differ
Binary files old/@eslint-plugin-kit-0.7.1.tgz and 
new/@eslint-plugin-kit-0.7.1.tgz differ
Binary files old/eslint-10.1.0.tgz and new/eslint-10.1.0.tgz differ
Binary files old/eslint-10.2.1.tgz and new/eslint-10.2.1.tgz differ

++++++ node_modules.spec.inc ++++++
--- /var/tmp/diff_new_pack.tZPAXP/_old  2026-05-04 12:54:08.251011607 +0200
+++ /var/tmp/diff_new_pack.tZPAXP/_new  2026-05-04 12:54:08.275012594 +0200
@@ -11,12 +11,12 @@
 Source1010:         
https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-6.0.0.tgz#/@csstools-selector-specificity-6.0.0.tgz
 Source1011:         
https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#/@eslint-community-eslint-utils-4.9.1.tgz
 Source1012:         
https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#/@eslint-community-regexpp-4.12.2.tgz
-Source1013:         
https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz#/@eslint-config-array-0.23.3.tgz
-Source1014:         
https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz#/@eslint-config-helpers-0.5.3.tgz
-Source1015:         
https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz#/@eslint-core-1.1.1.tgz
+Source1013:         
https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz#/@eslint-config-array-0.23.5.tgz
+Source1014:         
https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz#/@eslint-config-helpers-0.5.5.tgz
+Source1015:         
https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz#/@eslint-core-1.2.1.tgz
 Source1016:         
https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz#/@eslint-js-10.0.1.tgz
-Source1017:         
https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz#/@eslint-object-schema-3.0.3.tgz
-Source1018:         
https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz#/@eslint-plugin-kit-0.6.1.tgz
+Source1017:         
https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz#/@eslint-object-schema-3.0.5.tgz
+Source1018:         
https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz#/@eslint-plugin-kit-0.7.1.tgz
 Source1019:         
https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz#/@fortawesome-fontawesome-free-6.7.2.tgz
 Source1020:         
https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz#/@humanfs-core-0.19.1.tgz
 Source1021:         
https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz#/@humanfs-node-0.16.7.tgz
@@ -103,7 +103,7 @@
 Source1102:         
https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz#/env-paths-2.2.1.tgz
 Source1103:         
https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz#/error-ex-1.3.4.tgz
 Source1104:         
https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#/escape-string-regexp-4.0.0.tgz
-Source1105:         
https://registry.npmjs.org/eslint/-/eslint-10.1.0.tgz#/eslint-10.1.0.tgz
+Source1105:         
https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz#/eslint-10.2.1.tgz
 Source1106:         
https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz#/eslint-config-prettier-10.1.8.tgz
 Source1107:         
https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz#/eslint-plugin-prettier-5.5.5.tgz
 Source1108:         
https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz#/eslint-scope-9.1.2.tgz

++++++ openQA-5.1777474261.55e5cd5e.obscpio -> 
openQA-5.1777617029.fd9e1e69.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/.perlcriticrc 
new/openQA-5.1777617029.fd9e1e69/.perlcriticrc
--- old/openQA-5.1777474261.55e5cd5e/.perlcriticrc      2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/.perlcriticrc      2026-05-01 
08:30:29.000000000 +0200
@@ -1,6 +1,6 @@
 theme = community + openqa
 severity = 4
-include = strict ValuesAndExpressions::ProhibitInterpolationOfLiterals 
CodeLayout::ProhibitParensWithBuiltins BuiltinFunctions::RequireBlockMap 
BuiltinFunctions::ProhibitStringySplit 
ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions 
ValuesAndExpressions::RequireQuotedHeredocTerminator
+include = strict ValuesAndExpressions::ProhibitInterpolationOfLiterals 
CodeLayout::ProhibitParensWithBuiltins BuiltinFunctions::RequireBlockMap 
BuiltinFunctions::ProhibitStringySplit 
ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions 
ValuesAndExpressions::RequireQuotedHeredocTerminator 
Variables::ProhibitUnusedVariables 
ValuesAndExpressions::RequireNumberSeparators 
CodeLayout::ProhibitQuotedWordLists 
RegularExpressions::ProhibitSingleCharAlternation
 
 # ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions
 # No operators like < =~ ! allowed in 'unless' or 'until', only simple
@@ -46,3 +46,7 @@
 # -- Superfluous use strict/warning.
 [OpenQA::RedundantStrictWarning]
 equivalent_modules = Test::Most
+
+[ValuesAndExpressions::RequireNumberSeparators]
+min_value = 1000000
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/docs/style.css 
new/openQA-5.1777617029.fd9e1e69/docs/style.css
--- old/openQA-5.1777474261.55e5cd5e/docs/style.css     2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/docs/style.css     2026-05-01 
08:30:29.000000000 +0200
@@ -1,5 +1,4 @@
 /* openQA Documentation Style (Mimicking Asciidoctor) */
-
 body {
   font-family: 'Open Sans', 'DejaVu Sans', sans-serif;
   color: #333;
@@ -7,9 +6,7 @@
   margin: 0;
   display: flex;
   overflow-wrap: break-word;
-  word-wrap: break-word;
 }
-
 /* Sidebar TOC */
 #TOC {
   position: fixed;
@@ -23,49 +20,24 @@
   font-size: 0.9em;
   z-index: 1000;
 }
-
 /* Add dots after section numbers */
-.toc-section-number::after,
-.header-section-number::after {
+.toc-section-number::after, .header-section-number::after {
   content: '. ';
 }
-
-/* Responsive design */
-@media (max-width: 800px) {
-  body {
-    flex-direction: column;
-  }
-  #TOC {
-    position: static;
-    width: 100%;
-    height: auto;
-    border-right: none;
-    border-bottom: 1px solid #ddd;
-  }
-  main {
-    margin-left: 0;
-    padding: 20px;
-  }
-}
-
 #TOC ul {
   list-style: none;
   padding-left: 20px;
 }
-
 #TOC > ul {
   padding-left: 0;
 }
-
 #TOC a {
   text-decoration: none;
   color: #0056b3;
 }
-
 #TOC a:hover {
   text-decoration: underline;
 }
-
 /* Main Content */
 main {
   margin-left: 300px;
@@ -74,19 +46,12 @@
   flex-grow: 1;
   min-width: 0;
 }
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
+h1, h2, h3, h4, h5, h6 {
   color: #ba3925;
   font-weight: 300;
   margin-top: 1.5em;
   margin-bottom: 0.5em;
 }
-
 h1 {
   font-size: 2.2em;
   border-bottom: 1px solid #eee;
@@ -100,7 +65,6 @@
 h3 {
   font-size: 1.4em;
 }
-
 /* Section Anchors */
 .anchor {
   margin-left: 10px;
@@ -109,16 +73,9 @@
   font-size: 0.8em;
   text-decoration: none;
 }
-
-h1:hover .anchor,
-h2:hover .anchor,
-h3:hover .anchor,
-h4:hover .anchor,
-h5:hover .anchor,
-h6:hover .anchor {
+h1:hover .anchor, h2:hover .anchor, h3:hover .anchor, h4:hover .anchor, 
h5:hover .anchor, h6:hover .anchor {
   visibility: visible;
 }
-
 /* Code blocks */
 pre {
   background: #f4f4f4;
@@ -127,7 +84,6 @@
   border-radius: 4px;
   overflow-x: auto;
 }
-
 code {
   font-family: 'Droid Sans Mono', 'Courier New', monospace;
   background: #fdf6f2;
@@ -135,13 +91,11 @@
   border-radius: 3px;
   color: #ba3925;
 }
-
 pre code {
   background: transparent;
   padding: 0;
   color: inherit;
 }
-
 /* Admonitions */
 blockquote {
   margin: 1.5em 0;
@@ -149,18 +103,12 @@
   border-left: 5px solid #ccc;
   background: #f9f9f9;
 }
-
 /* Specific styling for Note/Warning/Tip */
-p > strong:first-child:contains('Note:'),
-p > strong:first-child:contains('Warning:'),
-p > strong:first-child:contains('Tip:'),
-p > strong:first-child:contains('Important:'),
-p > strong:first-child:contains('Caution:') {
+p > strong:first-child:contains('Note:'), p > 
strong:first-child:contains('Warning:'), p > 
strong:first-child:contains('Tip:'), p > 
strong:first-child:contains('Important:'), p > 
strong:first-child:contains('Caution:') {
   display: block;
   margin-bottom: 5px;
   text-transform: uppercase;
 }
-
 /* We use a different approach since :contains is not standard CSS */
 .admonition-note {
   border-left-color: #1f70c2;
@@ -174,7 +122,6 @@
   border-left-color: #28a745;
   background: #f6fff6;
 }
-
 /* Images */
 img {
   max-width: 100%;
@@ -182,7 +129,6 @@
   display: block;
   margin: 1em 0;
 }
-
 footer {
   margin-top: 50px;
   font-size: 0.8em;
@@ -190,3 +136,20 @@
   border-top: 1px solid #eee;
   padding-top: 20px;
 }
+/* Responsive design */
+@media (width <= 800px) {
+  body {
+    display: block;
+  }
+  #TOC {
+    position: static;
+    width: 100%;
+    height: auto;
+    border-right: none;
+    border-bottom: 1px solid #ddd;
+  }
+  main {
+    margin-left: 0;
+    padding: 20px;
+  }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/etc/openqa/openqa.ini 
new/openQA-5.1777617029.fd9e1e69/etc/openqa/openqa.ini
--- old/openQA-5.1777474261.55e5cd5e/etc/openqa/openqa.ini      2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/etc/openqa/openqa.ini      2026-05-01 
08:30:29.000000000 +0200
@@ -510,3 +510,11 @@
 #casedir = https://github.com/os-autoinst/os-autoinst-distri-example.git
 #distri = example
 #build = openqa
+
+## Configuration for automatically adding worker classes to jobs based on 
patterns
+[worker_class_auto_assignment]
+## Automatically add a worker class to a job if no existing worker class 
matches the pattern.
+## Format: pattern -> class
+## The pattern is a regex.
+## This can be specified multiple times.
+#add_worker_class_if_missing = size-.* -> size-large
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/CLI.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/CLI.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/CLI.pm  2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/CLI.pm  2026-05-01 
08:30:29.000000000 +0200
@@ -62,7 +62,6 @@
 }
 
 sub _print_options ($label, $options) {
-    my @rows;
     my @getopts;
     for my $option (@$options) {
         my ($spec, $desc);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/CacheService/Model/Cache.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/CacheService/Model/Cache.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/CacheService/Model/Cache.pm     
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/CacheService/Model/Cache.pm     
2026-05-01 08:30:29.000000000 +0200
@@ -16,7 +16,7 @@
 use Time::HiRes qw(gettimeofday);
 
 # Only consider files larger than 250 MB for metrics (rates for smaller files 
are unrealistic)
-use constant METRICS_DOWNLOAD_SIZE => $ENV{OPENQA_METRICS_DOWNLOAD_SIZE} // 
262144000;
+use constant METRICS_DOWNLOAD_SIZE => $ENV{OPENQA_METRICS_DOWNLOAD_SIZE} // 
262_144_000;
 
 has downloader => sub { OpenQA::Downloader->new };
 has [qw(location log sqlite min_free_percentage)];
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Config.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Config.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Config.pm       2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Config.pm       2026-05-01 
08:30:29.000000000 +0200
@@ -6,10 +6,12 @@
 
 use Config::IniFiles;
 use Exporter qw(import);
-use OpenQA::Log qw(log_info);
+use OpenQA::Log qw(log_info log_warning);
 use Mojo::File qw(path);
+use Feature::Compat::Try;
 
-our @EXPORT = qw(config_dir_within_app_home lookup_config_files 
parse_config_files parse_config_files_as_hash);
+our @EXPORT
+  = qw(config_dir_within_app_home lookup_config_files parse_config_files 
parse_config_files_as_hash parse_worker_class_auto_assignment);
 
 sub _config_dirs ($config_dir_within_home) {
     return [[$ENV{OPENQA_CONFIG} // ()], [$config_dir_within_home // ()], 
['/etc/openqa', '/usr/etc/openqa']];
@@ -17,6 +19,33 @@
 
 sub config_dir_within_app_home ($app) { $app->child('etc', 'openqa') }
 
+sub _parse_auto_assignment_entry ($entry) {
+    my ($pattern_str, $class) = split /\s*->\s*/, $entry, 2;
+    if (!defined $class) {
+        log_warning("Missing delimiter ' -> ' in worker_class_auto_assignment: 
$entry");
+        return ();
+    }
+    my $pattern_regex;
+    try { $pattern_regex = qr/$pattern_str/ }
+    catch ($e) {
+        log_warning("Invalid regex pattern in worker_class_auto_assignment: 
$pattern_str");
+        return ();
+    }
+    return {pattern => $pattern_regex, class => $class};
+}
+
+sub parse_worker_class_auto_assignment ($config) {
+    return $config->{_worker_class_auto_assignment_rules} if 
$config->{_worker_class_auto_assignment_rules};
+
+    my $section = $config->{worker_class_auto_assignment} or return [];
+    my $entries = $section->{add_worker_class_if_missing} or return [];
+    $entries = [$entries] unless ref $entries eq 'ARRAY';
+
+    my $rules = [map { _parse_auto_assignment_entry($_) } grep { $_ } 
@$entries];
+    $config->{_worker_class_auto_assignment_rules} = $rules;
+    return $rules;
+}
+
 sub lookup_config_files ($config_dir_within_home, $name, $silent = 0) {
     my $config_name;
     my @config_file_paths;
@@ -32,7 +61,7 @@
             last if $has_main_config;
         }
         if (@config_file_paths) {
-            log_info "Reading $config_name config from: @config_file_paths" 
unless $silent;
+            log_info("Reading $config_name config from: @config_file_paths") 
unless $silent;
             last;
         }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Downloader.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Downloader.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Downloader.pm   2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Downloader.pm   2026-05-01 
08:30:29.000000000 +0200
@@ -20,11 +20,13 @@
 has res => undef;
 
 sub download ($self, $url, $target, $options = {}) {
-    my $log = $self->log;
-
-    local $ENV{MOJO_TMPDIR} = $self->tmpdir;
+    my $tmpdir = path($self->tmpdir);
+    try { $tmpdir->make_path }
+    catch ($e) { return "Unable to create temporary directory: $e" }
+    local $ENV{MOJO_TMPDIR} = $tmpdir;
 
     my $remaining_attempts = $self->attempts;
+    my $log = $self->log;
     my ($code, $err);
     while (1) {
         $options->{on_attempt}->() if $options->{on_attempt};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Parser/Format/JUnit.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Parser/Format/JUnit.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Parser/Format/JUnit.pm  
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Parser/Format/JUnit.pm  
2026-05-01 08:30:29.000000000 +0200
@@ -38,7 +38,6 @@
     my $dom = Mojo::DOM->new($xml);
     confess 'Failed parsing XML' if @{$dom->tree} <= 2;
 
-    my @tests;
     for my $ts ($dom->find('testsuite')->each) {
         my $ts_category = $ts->{package};
         my $script = $ts->{script} ? $ts->{script} : undef;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Parser/Format/XUnit.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Parser/Format/XUnit.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Parser/Format/XUnit.pm  
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Parser/Format/XUnit.pm  
2026-05-01 08:30:29.000000000 +0200
@@ -17,7 +17,6 @@
     confess 'No XML given/loaded' unless $xml;
     my $dom = Mojo::DOM->new->xml(1)->parse($xml);
 
-    my @tests;
     my %t_names;
     my $i = 1;
     for my $ts ($dom->find('testsuite')->each) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Schema/Result/Jobs.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Schema/Result/Jobs.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Schema/Result/Jobs.pm   
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Schema/Result/Jobs.pm   
2026-05-01 08:30:29.000000000 +0200
@@ -1423,7 +1423,7 @@
             # Perform weak check on the number of bytes if the file size is > 
250 MB
             my $temp_final_str = $temp_final_file->to_string;
             my ($sum, $real_sum)
-              = $chunk->end > 250000000
+              = $chunk->end > 250_000_000
               ? ($chunk->end, -s $temp_final_str)
               : ($chunk->total_cksum, $chunk->file_digest($temp_final_str));
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Schema/ResultSet/AuditEvents.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Schema/ResultSet/AuditEvents.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Schema/ResultSet/AuditEvents.pm 
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Schema/ResultSet/AuditEvents.pm 
2026-05-01 08:30:29.000000000 +0200
@@ -25,7 +25,6 @@
 );
 
 sub delete_expired_entries ($self, %options) {
-    my @event_type_globs;
     my @queries;
     my $other_time_constraint;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Schema/ResultSet/Jobs.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Schema/ResultSet/Jobs.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Schema/ResultSet/Jobs.pm        
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Schema/ResultSet/Jobs.pm        
2026-05-01 08:30:29.000000000 +0200
@@ -9,6 +9,7 @@
 use Encode qw(decode_utf8);
 use File::Basename 'basename';
 use IPC::Run;
+use OpenQA::Config;
 use OpenQA::App;
 use OpenQA::Jobs::Constants;
 use OpenQA::Constants qw(DEFAULT_MAX_JOB_TIME);
@@ -24,7 +25,7 @@
 use Mojolicious::Validator::Validation;
 use Time::HiRes 'time';
 use DateTime;
-use List::Util qw(any);
+use List::Util qw(any uniq);
 use Scalar::Util qw(looks_like_number);
 
 =head2 latest_build
@@ -102,6 +103,35 @@
     return @latest;
 }
 
+sub _apply_auto_worker_class_assignment ($settings_ref) {
+    my $app = OpenQA::App->singleton or return undef;
+    my $rules = 
OpenQA::Config::parse_worker_class_auto_assignment($app->config // {});
+    return unless @$rules;
+
+    my @existing = grep { $_ } split qr/,/, $settings_ref->{WORKER_CLASS} // 
'';
+    my @to_add = grep {
+        my $pattern = $_->{pattern};
+        !any { $_ =~ $pattern } @existing;
+    } @$rules;
+    return unless @to_add;
+
+    for my $rule (@to_add) {
+        log_info("Auto-assigning worker class '$rule->{class}' to job (no 
match for pattern '$rule->{pattern}')");
+    }
+    $settings_ref->{WORKER_CLASS} = join ',', sort(uniq(@existing, map { 
$_->{class} } @to_add));
+}
+
+sub _build_job_settings ($settings_ref) {
+    my $now = now;
+    my @job_settings;
+    for my $key (keys %$settings_ref) {
+        my $val = $settings_ref->{$key};
+        push @job_settings, map { {t_created => $now, t_updated => $now, key 
=> $key, value => $_} }
+          grep { defined $_ } $key =~ qr/(^WORKER_CLASS|\[\])$/ ? split(m/,/, 
$val // '') : ($val);
+    }
+    return \@job_settings;
+}
+
 sub create_from_settings ($self, $settings, $scheduled_product_id = undef) {
     my %settings = %$settings;
     my %new_job_args;
@@ -112,8 +142,8 @@
 
     # validate special settings
     my %special_settings = (TEST => delete $settings{TEST}, _PRIORITY => 
delete $settings{_PRIORITY});
-    my $validator = Mojolicious::Validator->new;
-    my $v = Mojolicious::Validator::Validation->new(validator => $validator, 
input => \%special_settings);
+    my $v
+      = Mojolicious::Validator::Validation->new(validator => 
Mojolicious::Validator->new, input => \%special_settings);
     my $test = $v->required('TEST')->like(TEST_NAME_REGEX)->param;
     my $prio = $v->optional('_PRIORITY')->num->param;
     die 'The following settings are invalid: ' . join(', ', @{$v->failed}) . 
"\n" if $v->has_error;
@@ -141,10 +171,9 @@
         if (my $value = delete $settings{$key}) { $new_job_args{$key} = $value 
}
     }
 
-    # assign default for WORKER_CLASS
     $settings{WORKER_CLASS} ||= 'qemu_' . ($new_job_args{ARCH} // 'x86_64');
+    _apply_auto_worker_class_assignment(\%settings);
 
-    # assign scheduled product
     $new_job_args{scheduled_product_id} = $scheduled_product_id;
 
     my $debug_msg = $self->_apply_prio_throttling(\%settings, \%new_job_args, 
$group);
@@ -153,16 +182,7 @@
     my $job = $self->create(\%new_job_args);
     log_debug(sprintf "(Job %d) $debug_msg", $job->id) if $debug_msg;
 
-    # add job settings
-    my @job_settings;
-    my $now = now;
-    for my $key (keys %settings) {
-        my @values = $key =~ qr/(^WORKER_CLASS|\[\])$/ ? split(m/,/, 
$settings{$key}) : ($settings{$key});
-        push @job_settings, {t_created => $now, t_updated => $now, key => 
$key, value => $_} for @values;
-    }
-    $job->settings->populate(\@job_settings);
-
-    # associate currently available assets with job
+    $job->settings->populate(_build_job_settings(\%settings));
     $job->register_assets_from_settings;
 
     log_info('Ignoring invalid group ' . encode_json($group_args) . ' when 
creating new job ' . $job->id)
@@ -171,6 +191,7 @@
     return $job;
 }
 
+
 sub _update_priority ($value, $throt_config, $job_args) {
     my $scale = $throt_config->{scale} // 0;
     my $reference = $throt_config->{reference} // 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm 
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm 
2026-05-01 08:30:29.000000000 +0200
@@ -970,7 +970,6 @@
     my $schema = $self->schema;
 
     my %settings;    # Machines, product and test suite settings for the job
-    my @classes;    # Populated with WORKER_CLASS settings from machines and 
products
     my %params = (input_args => $args, settings => \%settings);
 
     # Populated with Product settings if there are DISTRI, VERSION, FLAVOR, 
ARCH in arguments.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Worker/Job.pm 
new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Worker/Job.pm
--- old/openQA-5.1777474261.55e5cd5e/lib/OpenQA/Worker/Job.pm   2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/lib/OpenQA/Worker/Job.pm   2026-05-01 
08:30:29.000000000 +0200
@@ -976,7 +976,7 @@
     my $local_upload = $global_settings->{LOCAL_UPLOAD} // 1;
     my $ua = $self->client->ua;
     my @channels_worker_only = ('worker');
-    my @channels_both = ('autoinst', 'worker');
+    my @channels_both = qw(autoinst worker);
     my $error;
 
     log_info("Uploading $filename using multiple chunks", channels => 
\@channels_worker_only, default => 1);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/package-lock.json 
new/openQA-5.1777617029.fd9e1e69/package-lock.json
--- old/openQA-5.1777474261.55e5cd5e/package-lock.json  2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/package-lock.json  2026-05-01 
08:30:29.000000000 +0200
@@ -24,7 +24,7 @@
       "devDependencies": {
         "@eslint/js": "^10.0.1",
         "@stylistic/stylelint-plugin": "^5.0.1",
-        "eslint": "^10.1.0",
+        "eslint": "^10.2.1",
         "eslint-config-prettier": "^10.1.8",
         "eslint-plugin-prettier": "^5.5.5",
         "globals": "^17.4.0",
@@ -325,13 +325,13 @@
       }
     },
     "node_modules/@eslint/config-array": {
-      "version": "0.23.3",
-      "resolved": 
"https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz";,
-      "integrity": 
"sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==",
+      "version": "0.23.5",
+      "resolved": 
"https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz";,
+      "integrity": 
"sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
-        "@eslint/object-schema": "^3.0.3",
+        "@eslint/object-schema": "^3.0.5",
         "debug": "^4.3.1",
         "minimatch": "^10.2.4"
       },
@@ -340,22 +340,22 @@
       }
     },
     "node_modules/@eslint/config-helpers": {
-      "version": "0.5.3",
-      "resolved": 
"https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz";,
-      "integrity": 
"sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==",
+      "version": "0.5.5",
+      "resolved": 
"https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz";,
+      "integrity": 
"sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
-        "@eslint/core": "^1.1.1"
+        "@eslint/core": "^1.2.1"
       },
       "engines": {
         "node": "^20.19.0 || ^22.13.0 || >=24"
       }
     },
     "node_modules/@eslint/core": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz";,
-      "integrity": 
"sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz";,
+      "integrity": 
"sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
@@ -387,9 +387,9 @@
       }
     },
     "node_modules/@eslint/object-schema": {
-      "version": "3.0.3",
-      "resolved": 
"https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz";,
-      "integrity": 
"sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==",
+      "version": "3.0.5",
+      "resolved": 
"https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz";,
+      "integrity": 
"sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==",
       "dev": true,
       "license": "Apache-2.0",
       "engines": {
@@ -397,13 +397,13 @@
       }
     },
     "node_modules/@eslint/plugin-kit": {
-      "version": "0.6.1",
-      "resolved": 
"https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz";,
-      "integrity": 
"sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==",
+      "version": "0.7.1",
+      "resolved": 
"https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz";,
+      "integrity": 
"sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
-        "@eslint/core": "^1.1.1",
+        "@eslint/core": "^1.2.1",
         "levn": "^0.4.1"
       },
       "engines": {
@@ -1421,18 +1421,18 @@
       }
     },
     "node_modules/eslint": {
-      "version": "10.1.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.1.0.tgz";,
-      "integrity": 
"sha512-S9jlY/ELKEUwwQnqWDO+f+m6sercqOPSqXM5Go94l7DOmxHVDgmSFGWEzeE/gwgTAr0W103BWt0QLe/7mabIvA==",
+      "version": "10.2.1",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz";,
+      "integrity": 
"sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.8.0",
         "@eslint-community/regexpp": "^4.12.2",
-        "@eslint/config-array": "^0.23.3",
-        "@eslint/config-helpers": "^0.5.3",
-        "@eslint/core": "^1.1.1",
-        "@eslint/plugin-kit": "^0.6.1",
+        "@eslint/config-array": "^0.23.5",
+        "@eslint/config-helpers": "^0.5.5",
+        "@eslint/core": "^1.2.1",
+        "@eslint/plugin-kit": "^0.7.1",
         "@humanfs/node": "^0.16.6",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@humanwhocodes/retry": "^0.4.2",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/package.json 
new/openQA-5.1777617029.fd9e1e69/package.json
--- old/openQA-5.1777474261.55e5cd5e/package.json       2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/package.json       2026-05-01 
08:30:29.000000000 +0200
@@ -3,8 +3,8 @@
   "version": "1.0.0",
   "description": "Testing Framework",
   "scripts": {
-    "lint": "eslint \"assets/javascripts/**/*.js\" && stylelint 
\"assets/stylesheets/**/*.{scss,css}\"",
-    "fix": "eslint --fix \"assets/javascripts/**/*.js\" && stylelint --fix 
\"assets/stylesheets/**/*.{scss,css}\""
+    "lint": "eslint \"assets/javascripts/**/*.js\" && stylelint 
\"assets/stylesheets/**/*.{scss,css}\" \"docs/*.css\"",
+    "fix": "eslint --fix \"assets/javascripts/**/*.js\" && stylelint --fix 
\"assets/stylesheets/**/*.{scss,css}\" \"docs/*.css\""
   },
   "license": "GPL-2.0",
   "bugs": {
@@ -14,7 +14,7 @@
   "devDependencies": {
     "@eslint/js": "^10.0.1",
     "@stylistic/stylelint-plugin": "^5.0.1",
-    "eslint": "^10.1.0",
+    "eslint": "^10.2.1",
     "eslint-config-prettier": "^10.1.8",
     "eslint-plugin-prettier": "^5.5.5",
     "globals": "^17.4.0",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/profiles/apparmor.d/usr.share.openqa.script.worker
 
new/openQA-5.1777617029.fd9e1e69/profiles/apparmor.d/usr.share.openqa.script.worker
--- 
old/openQA-5.1777474261.55e5cd5e/profiles/apparmor.d/usr.share.openqa.script.worker
 2026-04-29 16:51:01.000000000 +0200
+++ 
new/openQA-5.1777617029.fd9e1e69/profiles/apparmor.d/usr.share.openqa.script.worker
 2026-05-01 08:30:29.000000000 +0200
@@ -117,6 +117,7 @@
   /usr/bin/isotovideo rix,
   /usr/bin/isoinfo rix,
   /usr/bin/jq rix,
+  /usr/bin/jsonnet rix,
   /usr/bin/podman rix,
   /usr/bin/lscpu rCx,
   /{usr/,}bin/mkdir rix,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/t/05-scheduler-capabilities.t 
new/openQA-5.1777617029.fd9e1e69/t/05-scheduler-capabilities.t
--- old/openQA-5.1777474261.55e5cd5e/t/05-scheduler-capabilities.t      
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/05-scheduler-capabilities.t      
2026-05-01 08:30:29.000000000 +0200
@@ -13,6 +13,8 @@
 use OpenQA::WebAPI::Controller::API::V1::Worker;
 use Test::Mojo;
 use Test::Warnings ':report_warnings';
+use Test::MockModule;
+use Test::MockObject;
 use Mojo::Util 'monkey_patch';
 use OpenQA::Test::TimeLimit '10';
 
@@ -203,4 +205,33 @@
 
 # job G is not grabbed because there is no worker with class 'special'
 
+subtest 'auto_worker_class' => sub {
+    my $mock_app = Test::MockModule->new('OpenQA::App', no_auto => 1);
+    my $mock_app_obj = Test::MockObject->new;
+    $mock_app_obj->set_always(
+        config => {
+            global => {worker_timeout => 60},
+            misc_limits => {
+                throttle_failing_job_threshold => 0,
+                throttle_failing_job_prio_step => 0,
+                throttle_failing_job_history_length => 0,
+            },
+            worker_class_auto_assignment => {
+                add_worker_class_if_missing => 'size-.* -> size-large'
+            }});
+    my $mock_log = Test::MockObject->new;
+    $mock_log->set_always(info => 1);
+    $mock_log->set_always(level => 'info');
+    $mock_app_obj->set_always(log => $mock_log);
+    $mock_app->redefine(singleton => $mock_app_obj);
+
+    my $job = job_create({TEST => 'auto_class_test', ARCH => 'x86_64'});
+    my @classes = sort map { $_->value } $job->settings->search({key => 
'WORKER_CLASS'})->all;
+    is_deeply \@classes, ['qemu_x86_64', 'size-large'], 'auto-assigned 
size-large';
+
+    $job = job_create({TEST => 'auto_class_test_existing', ARCH => 'x86_64', 
WORKER_CLASS => 'size-small,qemu_x86_64'});
+    @classes = sort map { $_->value } $job->settings->search({key => 
'WORKER_CLASS'})->all;
+    is_deeply \@classes, ['qemu_x86_64', 'size-small'], 'kept existing 
size-small';
+};
+
 done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/t/05-scheduler-dependencies.t 
new/openQA-5.1777617029.fd9e1e69/t/05-scheduler-dependencies.t
--- old/openQA-5.1777474261.55e5cd5e/t/05-scheduler-dependencies.t      
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/05-scheduler-dependencies.t      
2026-05-01 08:30:29.000000000 +0200
@@ -157,7 +157,7 @@
     is $scheduled_jobs->{99928}->{priority}, 46, 'regular prio for job 99928 
assumed';
     is $scheduled_jobs->{$_}->{priority_offset}, 0, "job $_ not deprioritized 
yet" for (99927, 99928);
     combined_like { $scheduler->schedule }
-    qr/Unable to serialize directly chained job sequence of 9992(7|8): 
detected cycle at 9992(7|8)/,
+    qr/Unable to serialize directly chained job sequence of 9992[78]: detected 
cycle at 9992[78]/,
       'info about cycle logged';
     $scheduler->_update_scheduled_jobs;    # apply deprioritization
     is $scheduled_jobs->{99927}->{priority}, 46, 'reduced prio for job 99927 
assumed';
@@ -1290,7 +1290,7 @@
     my $free_workers = 
OpenQA::Scheduler::Model::Jobs::determine_free_workers();
     my $allocated_workers;
     combined_like { $allocated_workers = 
OpenQA::Scheduler::Model::Jobs->singleton->_allocate_jobs($free_workers) }
-    qr/Need to schedule 3 parallel jobs for job 1.*Discarding job 
(1|2|3).*Discarding job (1|2|3)/s,
+    qr/Need to schedule 3 parallel jobs for job 1.*Discarding job 
[123].*Discarding job [123]/s,
       'discarding jobs due to incomplete parallel cluster';
     is $mocked_jobs{1}->{priority_offset}, 10, 'priority of parallel parent 
increased (once per child)';
     is_deeply $allocated_workers, {}, 'no workers "held" so far while still 
increased prio'
@@ -1299,7 +1299,7 @@
     # run the scheduler again assuming highest prio for parallel parent; 
worker supposed to be "held"
     $mocked_jobs{1}->{priority} = 0;
     combined_like { ($allocated_workers) = 
OpenQA::Scheduler::Model::Jobs->singleton->_allocate_jobs($free_workers) }
-    qr/Holding worker .* for job (1|2|3) to avoid starvation.*Holding worker 
.* for job (1|2|3) to avoid starvation/s,
+    qr/Holding worker .* for job [123] to avoid starvation.*Holding worker .* 
for job [123] to avoid starvation/s,
       'holding 2 workers (for 2 of our parallel jobs while 3rd worker is 
unavailable)';
     is_deeply [sort keys %$allocated_workers], [map { $_->id } 
@mocked_free_workers], 'both free workers "held"';
     ok $_ >= 1 && $_ <= 3, "worker held for expected job ($_)" for values 
%$allocated_workers;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/16-utils.t 
new/openQA-5.1777617029.fd9e1e69/t/16-utils.t
--- old/openQA-5.1777474261.55e5cd5e/t/16-utils.t       2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/16-utils.t       2026-05-01 
08:30:29.000000000 +0200
@@ -81,20 +81,21 @@
 };
 
 subtest 'download speed' => sub {
-    is download_rate([1638459407, 528237], [1638459408, 628237], 1024), 
'930.91';
-    is download_rate([1638459407, 528237], [1638459408, 628237], 1024 * 1024 * 
1024), '976128930.91';
-    is download_rate([1638459407, 528237], [1638459407, 528237], 1024), undef;
-
-    is download_speed([1638459407, 528237], [1638459408, 628237], 1024), 
'930.91 Byte/s';
-    is download_speed([1638459407, 528237], [1638459408, 628237], 1024 * 
1024), '931 KiB/s';
-    is download_speed([1638459407, 528237], [1638459408, 628237], 1024 * 1024 
* 1024), '931 MiB/s';
-    is download_speed([1638459407, 528237], [1638459408, 628237], 1024 * 1024 
* 1024 * 1024), '931 GiB/s';
-    is download_speed([1638459407, 528237], [1638459408, 628237], 1024 * 1024 
* 1024 * 1024 * 1024), '953251 GiB/s';
+    is download_rate([1_638_459_407, 528237], [1_638_459_408, 628237], 1024), 
'930.91';
+    is download_rate([1_638_459_407, 528237], [1_638_459_408, 628237], 1024 * 
1024 * 1024), '976128930.91';
+    is download_rate([1_638_459_407, 528237], [1_638_459_407, 528237], 1024), 
undef;
+
+    is download_speed([1_638_459_407, 528237], [1_638_459_408, 628237], 1024), 
'930.91 Byte/s';
+    is download_speed([1_638_459_407, 528237], [1_638_459_408, 628237], 1024 * 
1024), '931 KiB/s';
+    is download_speed([1_638_459_407, 528237], [1_638_459_408, 628237], 1024 * 
1024 * 1024), '931 MiB/s';
+    is download_speed([1_638_459_407, 528237], [1_638_459_408, 628237], 1024 * 
1024 * 1024 * 1024), '931 GiB/s';
+    is download_speed([1_638_459_407, 528237], [1_638_459_408, 628237], 1024 * 
1024 * 1024 * 1024 * 1024),
+      '953251 GiB/s';
 
-    is download_speed([1638459407, 528237], [1638459508, 628237], 1024 * 1024 
* 512), '5.1 MiB/s';
-    is download_speed([1638459407, 528237], [1638459407, 588237], 123456789), 
'1.9 GiB/s';
+    is download_speed([1_638_459_407, 528237], [1_638_459_508, 628237], 1024 * 
1024 * 512), '5.1 MiB/s';
+    is download_speed([1_638_459_407, 528237], [1_638_459_407, 588237], 
123_456_789), '1.9 GiB/s';
 
-    is download_speed([1638459407, 528237], [1638459407, 528237], 1024), 
'??/s';
+    is download_speed([1_638_459_407, 528237], [1_638_459_407, 528237], 1024), 
'??/s';
 };
 
 subtest 'labels' => sub {
@@ -152,7 +153,7 @@
     $t3 => sub {
         my ($k, $v, $ks, $what) = @_;
         next if reftype $what eq 'HASH' && exists $what->{_data};
-        like $_[0], qr/bar|baz|foo|0|1|fish$|fish2|boring/, 'Walked';
+        like $_[0], qr/bar|baz|foo|[01]|fish$|fish2|boring/, 'Walked';
 
         $what->[$k] = {_type => ref $v, _data => $v} if reftype $what eq 
'ARRAY';
         $what->{$k} = {_type => ref $v, _data => $v} if reftype $what eq 
'HASH';
@@ -534,10 +535,10 @@
 subtest 'human readable size' => sub {
     is human_readable_size(0), '0 Byte', 'zero';
     is human_readable_size(1), '1 Byte', 'one';
-    is human_readable_size(13443399680), '13 GiB', 'two digits GB';
-    is human_readable_size(8007188480), '7.5 GiB', 'smaller GB';
-    is human_readable_size(-8007188480), '-7.5 GiB', 'negative smaller GB';
-    is human_readable_size(717946880), '685 MiB', 'large MB';
+    is human_readable_size(13_443_399_680), '13 GiB', 'two digits GB';
+    is human_readable_size(8_007_188_480), '7.5 GiB', 'smaller GB';
+    is human_readable_size(-8_007_188_480), '-7.5 GiB', 'negative smaller GB';
+    is human_readable_size(717_946_880), '685 MiB', 'large MB';
     is human_readable_size(245760), '240 KiB', 'less than a MB';
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/17-build_tagging.t 
new/openQA-5.1777617029.fd9e1e69/t/17-build_tagging.t
--- old/openQA-5.1777474261.55e5cd5e/t/17-build_tagging.t       2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/17-build_tagging.t       2026-05-01 
08:30:29.000000000 +0200
@@ -59,7 +59,6 @@
 };
 
 sub create_job_version_build ($version, $build) {
-    my %job_hash;
     $job_hash->{VERSION} = $version;
     $job_hash->{BUILD} = $build;
     $jobs->create($job_hash);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/25-cache-service.t 
new/openQA-5.1777617029.fd9e1e69/t/25-cache-service.t
--- old/openQA-5.1777474261.55e5cd5e/t/25-cache-service.t       2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/25-cache-service.t       2026-05-01 
08:30:29.000000000 +0200
@@ -101,8 +101,8 @@
     my $dir2 = tempdir;
     my $rsync_request = $cache_client->rsync_request(from => $dir, to => 
$dir2);
 
-    my $t_dir = int rand 13432432;
-    my $data = int rand 348394280934820842093;
+    my $t_dir = int rand 13_432_432;
+    my $data = int rand 348_394_280_934_820_842_093;
     $dir->child($t_dir)->spew($data);
     my $expected = $dir2->child('tests')->child($t_dir);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/25-downloader.t 
new/openQA-5.1777617029.fd9e1e69/t/25-downloader.t
--- old/openQA-5.1777474261.55e5cd5e/t/25-downloader.t  2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/25-downloader.t  2026-05-01 
08:30:29.000000000 +0200
@@ -5,6 +5,7 @@
 
 use Test::Most;
 use Test::Warnings ':report_warnings';
+use Mojo::Base -signatures;
 use utf8;
 use FindBin;
 use lib "$FindBin::Bin/lib", 
"$FindBin::Bin/../external/os-autoinst-common/lib";
@@ -20,6 +21,7 @@
 use OpenQA::Test::Utils qw(fake_asset_server wait_for_or_bail_out);
 use OpenQA::Test::TimeLimit '10';
 use Mojo::File qw(tempdir);
+use Test::MockModule;
 
 my $port = Mojo::IOLoop::Server->generate_port;
 my $host = "127.0.0.1:$port";
@@ -67,6 +69,12 @@
 
 $ua->connect_timeout(0.25)->inactivity_timeout(0.25);
 
+subtest 'Unable to create temporary directory' => sub {
+    my $file_mock = Test::MockModule->new('Mojo::File');
+    $file_mock->redefine(make_path => sub ($self) { die 'fake error' });
+    like $downloader->download('from', 'to'), qr/temp.*dir.*fake error/, 
'error returned';
+};
+
 subtest 'Connection refused' => sub {
     my $from = 
"http://$host/tests/922756/asset/hdd/[email protected]";;
     like $downloader->download($from, $to), qr/Download of "$to" failed: 
Connection refused/, 'Failed';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/32-openqa_client.t 
new/openQA-5.1777617029.fd9e1e69/t/32-openqa_client.t
--- old/openQA-5.1777474261.55e5cd5e/t/32-openqa_client.t       2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/32-openqa_client.t       2026-05-01 
08:30:29.000000000 +0200
@@ -18,10 +18,10 @@
 plan skip_all => 'set HEAVY=1 to execute (takes longer)' unless $ENV{HEAVY};
 
 OpenQA::Test::Case->new->init_data(fixtures_glob => '01-jobs.pl 02-workers.pl 
03-users.pl');
-my $chunk_size = 10000000;
+my $chunk_size = 10_000_000;
 
 # allow up to 200MB - videos mostly
-$ENV{MOJO_MAX_MESSAGE_SIZE} = 207741824;
+$ENV{MOJO_MAX_MESSAGE_SIZE} = 207_741_824;
 
 my $tempdir = tempdir("$FindBin::Script-XXXX", TMPDIR => 1);
 chdir $tempdir;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/t/34-developer_mode-unit.t 
new/openQA-5.1777617029.fd9e1e69/t/34-developer_mode-unit.t
--- old/openQA-5.1777474261.55e5cd5e/t/34-developer_mode-unit.t 2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/34-developer_mode-unit.t 2026-05-01 
08:30:29.000000000 +0200
@@ -35,7 +35,7 @@
 my @ipc_messages_for_websocket_server;
 my $fake_send_msg_failure;
 my $mock_client = Test::MockModule->new('OpenQA::WebSockets::Client');
-my ($client_called, $last_command);
+my $client_called;
 $mock_client->redefine(
     send_msg => sub {
         my $self = shift;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/api/02-iso.t 
new/openQA-5.1777617029.fd9e1e69/t/api/02-iso.t
--- old/openQA-5.1777474261.55e5cd5e/t/api/02-iso.t     2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/api/02-iso.t     2026-05-01 
08:30:29.000000000 +0200
@@ -512,7 +512,7 @@
     is $res->json->{count}, 0, 'no jobs scheduled if cycle detected';
     like
       $res->json->{failed}->[0]->{error_messages}->[0],
-      qr/There is a cycle in the dependencies of chained-(a|b|c|d)/,
+      qr/There is a cycle in the dependencies of chained-[abcd]/,
       'cycle reported';
     $schema->txn_rollback;
 };
@@ -583,7 +583,7 @@
 
         my $res = schedule_iso($t, {%iso, _GROUP => 'opensuse test'});
         is $res->json->{count}, 0, 'none of the jobs has been scheduled';
-        like $_->{error_messages}->[0], qr/chained-(c|d|e) \(bar,baz\) does 
not match .* \(foo\)/, 'error reported'
+        like $_->{error_messages}->[0], qr/chained-[cde] \(bar,baz\) does not 
match .* \(foo\)/, 'error reported'
           for @{$res->json->{failed}};
         $schema->txn_rollback;
     };
@@ -816,7 +816,7 @@
 
     my $res = schedule_iso($t, {scheduled_product_clone_id => 'foobar'}, 400);
     like $res->body, qr/scheduled_product_id.*invalid/, 'error returned if 
scheduled product to clone from is invalid';
-    $res = schedule_iso($t, {scheduled_product_clone_id => 1234567}, 404);
+    $res = schedule_iso($t, {scheduled_product_clone_id => 1_234_567}, 404);
     like $res->body, qr/to clone.*not found/, 'error returned if scheduled 
product to clone from does not exist';
 
     $res = schedule_iso($t, {scheduled_product_clone_id => 
$scheduled_product_id}, 200, {async => 1});
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/api/04-jobs.t 
new/openQA-5.1777617029.fd9e1e69/t/api/04-jobs.t
--- old/openQA-5.1777474261.55e5cd5e/t/api/04-jobs.t    2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/api/04-jobs.t    2026-05-01 
08:30:29.000000000 +0200
@@ -48,7 +48,7 @@
 my @data = ("[audit]\n", "blocklist = job_grab\n");
 $tempdir->child('openqa.ini')->spew(join '', @data);
 
-my $chunk_size = 10000000;
+my $chunk_size = 10_000_000;
 
 my $io_loop_mock = mock_io_loop(subprocess => 1);
 
@@ -60,7 +60,7 @@
 }
 
 # allow up to 200MB - videos mostly
-$ENV{MOJO_MAX_MESSAGE_SIZE} = 207741824;
+$ENV{MOJO_MAX_MESSAGE_SIZE} = 207_741_824;
 
 my $t = client(Test::Mojo->new('OpenQA::WebAPI'));
 my $cfg = $t->app->config;
@@ -333,7 +333,7 @@
     $t->get_ok('/api/v1/job_settings/jobs' => form => {key => '*_TEST_ISSUES', 
list_value => 26103})->status_is(200)
       ->json_is({jobs => []});
 
-    local $t->app->config->{misc_limits}{job_settings_max_recent_jobs} = 
1000000000;
+    local $t->app->config->{misc_limits}{job_settings_max_recent_jobs} = 
1_000_000_000;
     $t->get_ok('/api/v1/job_settings/jobs' => form => {key => '*_TEST_ISSUES', 
list_value => 26110})->status_is(200)
       ->json_is({jobs => [99981]});
     $t->get_ok('/api/v1/job_settings/jobs' => form => {key => '*_TEST_ISSUES', 
list_value => 26103})->status_is(200)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/api/08-jobtemplates.t 
new/openQA-5.1777617029.fd9e1e69/t/api/08-jobtemplates.t
--- old/openQA-5.1777474261.55e5cd5e/t/api/08-jobtemplates.t    2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/api/08-jobtemplates.t    2026-05-01 
08:30:29.000000000 +0200
@@ -257,7 +257,6 @@
     my $yaml2 = path("$FindBin::Bin/../data/08-opensuse-test.yaml")->slurp;
     my %yaml = (1001 => $yaml1, 1002 => $yaml2);
 
-    my @templates;
     for my $group ($job_groups->search) {
         my $id = $group->id;
         my $yaml = $group->to_yaml;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/api/17-mcp.t 
new/openQA-5.1777617029.fd9e1e69/t/api/17-mcp.t
--- old/openQA-5.1777474261.55e5cd5e/t/api/17-mcp.t     2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/api/17-mcp.t     2026-05-01 
08:30:29.000000000 +0200
@@ -136,7 +136,8 @@
 
     subtest 'Job does not exist' => sub {
         local $t->app->config->{misc_limits}{mcp_max_result_size} = 100;
-        my $result = $client->call_tool('openqa_get_log_file', {job_id => 
999999999, file_name => 'autoinst-log.txt'});
+        my $result
+          = $client->call_tool('openqa_get_log_file', {job_id => 999_999_999, 
file_name => 'autoinst-log.txt'});
         ok $result->{isError}, 'is an error';
         my $text = $result->{content}[0]{text};
         like $text, qr/Job does not exist/, 'error message';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/config.t 
new/openQA-5.1777617029.fd9e1e69/t/config.t
--- old/openQA-5.1777474261.55e5cd5e/t/config.t 2026-04-29 16:51:01.000000000 
+0200
+++ new/openQA-5.1777617029.fd9e1e69/t/config.t 2026-05-01 08:30:29.000000000 
+0200
@@ -358,6 +358,42 @@
             qr/Wrong format/, 'warning logged';
         };
     };
+
+    subtest 'parse_worker_class_auto_assignment' => sub {
+        my $config = {
+            worker_class_auto_assignment => {
+                add_worker_class_if_missing =>
+                  ['size-.* -> size-large', 'gpu-.* -> gpu-none', 'invalid 
line', 'bad regex ( -> size-error',]}};
+
+        my $mock_config = Test::MockModule->new('OpenQA::Config');
+        my @warnings;
+        $mock_config->redefine(log_warning => sub { push @warnings, $_[0] });
+
+        my $rules = 
OpenQA::Config::parse_worker_class_auto_assignment($config);
+
+        is scalar @$rules, 2, 'parsed 2 valid rules';
+        is $rules->[0]{class}, 'size-large', 'first rule class';
+        ok 'size-small' =~ $rules->[0]{pattern}, 'first rule pattern matches';
+
+        is $rules->[1]{class}, 'gpu-none', 'second rule class';
+        ok 'gpu-anything' =~ $rules->[1]{pattern}, 'second rule pattern 
matches';
+
+        is scalar @warnings, 2, 'got 2 warnings for invalid lines';
+        like $warnings[0], qr/Missing delimiter/, 'warning for missing 
delimiter';
+        like $warnings[1], qr/Invalid regex pattern/, 'warning for invalid 
regex';
+
+        subtest 'single value' => sub {
+            my $config = {worker_class_auto_assignment => 
{add_worker_class_if_missing => 'size-.* -> size-large'}};
+            my $rules = 
OpenQA::Config::parse_worker_class_auto_assignment($config);
+            is scalar @$rules, 1, 'parsed 1 rule from single value';
+        };
+
+        subtest 'empty' => sub {
+            is_deeply OpenQA::Config::parse_worker_class_auto_assignment({}), 
[], 'empty config returns empty array';
+            is_deeply 
OpenQA::Config::parse_worker_class_auto_assignment({worker_class_auto_assignment
 => {}}), [],
+              'empty section returns empty array';
+        };
+    };
 };
 
 done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/fixtures/01-jobs.pl 
new/openQA-5.1777617029.fd9e1e69/t/fixtures/01-jobs.pl
--- old/openQA-5.1777474261.55e5cd5e/t/fixtures/01-jobs.pl      2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/fixtures/01-jobs.pl      2026-05-01 
08:30:29.000000000 +0200
@@ -61,7 +61,7 @@
         settings => [
             {key => 'DESKTOP', value => 'minimalx'},
             {key => 'ISO', value => 
'openSUSE-Factory-staging_e-x86_64-Build87.5011-Media.iso'},
-            {key => 'ISO_MAXSIZE', value => 737280000},
+            {key => 'ISO_MAXSIZE', value => 737_280_000},
             {key => 'ISO_1', value => 
'openSUSE-Factory-staging_e-x86_64-Build87.5011-Media.iso'},
             {key => 'BASE_TEST_ISSUES', value => '26103'}
         ],
@@ -429,7 +429,7 @@
         priority => 50,
         result => 'skipped',
         state => 'cancelled',
-        t_created => time2str('%Y-%m-%d %H:%M:%S', time - 3000100, 'UTC'),
+        t_created => time2str('%Y-%m-%d %H:%M:%S', time - 3_000_100, 'UTC'),
         t_started => undef,
         t_finished => undef,
         TEST => 'RAID0',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/ui/18-tests-details.t 
new/openQA-5.1777617029.fd9e1e69/t/ui/18-tests-details.t
--- old/openQA-5.1777474261.55e5cd5e/t/ui/18-tests-details.t    2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/ui/18-tests-details.t    2026-05-01 
08:30:29.000000000 +0200
@@ -238,11 +238,11 @@
     like $url[0], qr{bugzilla.*enter_bug.*tests%2F99937}, 'bugzilla link 
referencing current test';
     like $url[0], qr{in\+scenario\+%60opensuse-13\.1-DVD-i586-kde}, 'bugzilla 
link contains scenario marked verbatim';
     like $url[1], qr{bugzilla.*enter_bug}, 'kernel product bug uses bugzilla 
enter_bug';
-    like $url[1], qr{(?:\?|&)product=openSUSE\+Distribution(?:&|$)}, 'kernel 
product bug sets product';
+    like $url[1], qr{[?&]product=openSUSE\+Distribution(?:&|$)}, 'kernel 
product bug sets product';
     like $url[1],
-      
qr{(?:\?|&)short_desc=%5BQE%5D%5BBuild\+0091%5D\+Kernel\+test\+fails\+in\+bootloader},
+      
qr{[?&]short_desc=%5BQE%5D%5BBuild\+0091%5D\+Kernel\+test\+fails\+in\+bootloader},
       'kernel short_desc correct';
-    like $url[1], qr{(?:\?|&)comment=}, 'kernel product bug has comment 
template';
+    like $url[1], qr{[?&]comment=}, 'kernel product bug has comment template';
     like $url[2], qr{progress.*new}, 'progress/redmine link for reporting test 
issues';
     like $url[2], qr{in\+scenario\+%60opensuse-13\.1-DVD-i586-kde}, 
'progress/redmine link contains scenario';
     like $url[2],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777474261.55e5cd5e/t/ui/26-jobs_restart.t 
new/openQA-5.1777617029.fd9e1e69/t/ui/26-jobs_restart.t
--- old/openQA-5.1777474261.55e5cd5e/t/ui/26-jobs_restart.t     2026-04-29 
16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/ui/26-jobs_restart.t     2026-05-01 
08:30:29.000000000 +0200
@@ -24,7 +24,7 @@
 
 sub prepare_database () {
     # Populate more cluster jobs
-    my @test_names = ('create_hdd', 'support_server', 'master_node', 
'slave_node');
+    my @test_names = qw(create_hdd support_server master_node slave_node);
     for my $n (0 .. 3) {
         my $new = {
             id => 99900 + $n,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777474261.55e5cd5e/t/ui/27-plugin_obs_rsync_obs_status.t 
new/openQA-5.1777617029.fd9e1e69/t/ui/27-plugin_obs_rsync_obs_status.t
--- old/openQA-5.1777474261.55e5cd5e/t/ui/27-plugin_obs_rsync_obs_status.t      
2026-04-29 16:51:01.000000000 +0200
+++ new/openQA-5.1777617029.fd9e1e69/t/ui/27-plugin_obs_rsync_obs_status.t      
2026-05-01 08:30:29.000000000 +0200
@@ -224,7 +224,7 @@
 };
 
 subtest 'build service authentication: signature generation' => sub {
-    $mocked_time = 1664187470;
+    $mocked_time = 1_664_187_470;
     note 'time right now: ' . time;
     is time(), $mocked_time, 'Time is not frozen!';
     is $helper->is_status_dirty('ProjTestingSignature'), 1, 'signature matches 
fixture';

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.tZPAXP/_old  2026-05-04 12:54:22.223586681 +0200
+++ /var/tmp/diff_new_pack.tZPAXP/_new  2026-05-04 12:54:22.231587010 +0200
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1777474261.55e5cd5e
-mtime: 1777474261
-commit: 55e5cd5e9f3a12facb9f43e315f30b401a9279a9
+version: 5.1777617029.fd9e1e69
+mtime: 1777617029
+commit: fd9e1e6944c531b90a4edef6a15954e3390a1a3d
 

Reply via email to