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-07-21 23:14:13
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.24530 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Tue Jul 21 23:14:13 2026 rev:869 rq:1367013 version:5.1784641659.4dee7d1f

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2026-07-18 
22:25:37.043350645 +0200
+++ /work/SRC/openSUSE:Factory/.openQA.new.24530/openQA.changes 2026-07-21 
23:14:19.866363589 +0200
@@ -1,0 +2,17 @@
+Tue Jul 21 13:47:48 UTC 2026 - [email protected]
+
+- Update to version 5.1784641659.4dee7d1f:
+  * fix: Escape `@` sign in strings and regexes
+  * chore(deps): Dependency cron 2026-07-21
+  * chore(deps-dev): bump brace-expansion from 5.0.5 to 5.0.7 (#7647)
+  * feat(admin): show exact timestamp on hover in product log
+  * feat(admin): query parameter search in product log
+  * feat(admin): search in settings in product log
+  * chore(deps): bump actions/setup-node in the all-actions group (#7645)
+  * fix: filter out md files when collecting python files
+  * feat(BCI): dedicated report template for BCI
+  * chore(deps): Dependency cron 2026-07-19
+  * docs: remove blank lines from variable precedence list
+  * feat: support global instance-wide test settings
+
+-------------------------------------------------------------------

Old:
----
  openQA-5.1784324412.123ebeb6.obscpio

New:
----
  openQA-5.1784641659.4dee7d1f.obscpio

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

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.HSeQ4n/_old  2026-07-21 23:14:22.090439722 +0200
+++ /var/tmp/diff_new_pack.HSeQ4n/_new  2026-07-21 23:14:22.090439722 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1784324412.123ebeb6
+Version:        5.1784641659.4dee7d1f
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.HSeQ4n/_old  2026-07-21 23:14:22.122440817 +0200
+++ /var/tmp/diff_new_pack.HSeQ4n/_new  2026-07-21 23:14:22.126440954 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-devel
 Name:           %{short_name}-test
-Version:        5.1784324412.123ebeb6
+Version:        5.1784641659.4dee7d1f
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.HSeQ4n/_old  2026-07-21 23:14:22.150441775 +0200
+++ /var/tmp/diff_new_pack.HSeQ4n/_new  2026-07-21 23:14:22.154441912 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1784324412.123ebeb6
+Version:        5.1784641659.4dee7d1f
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.HSeQ4n/_old  2026-07-21 23:14:22.182442870 +0200
+++ /var/tmp/diff_new_pack.HSeQ4n/_new  2026-07-21 23:14:22.182442870 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1784324412.123ebeb6
+Version:        5.1784641659.4dee7d1f
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.HSeQ4n/_old  2026-07-21 23:14:22.214443966 +0200
+++ /var/tmp/diff_new_pack.HSeQ4n/_new  2026-07-21 23:14:22.218444103 +0200
@@ -104,7 +104,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1784324412.123ebeb6
+Version:        5.1784641659.4dee7d1f
 Release:        0
 Summary:        Framework for automated system-level testing (web-frontend, 
scheduler and tools)
 Group:          Development/Tools/Other

++++++ node_modules.obscpio ++++++
Binary files old/brace-expansion-5.0.5.tgz and new/brace-expansion-5.0.5.tgz 
differ
Binary files old/brace-expansion-5.0.7.tgz and new/brace-expansion-5.0.7.tgz 
differ

++++++ node_modules.spec.inc ++++++
--- /var/tmp/diff_new_pack.HSeQ4n/_old  2026-07-21 23:14:23.242479157 +0200
+++ /var/tmp/diff_new_pack.HSeQ4n/_new  2026-07-21 23:14:23.246479294 +0200
@@ -47,7 +47,7 @@
 Source1046:         
https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz#/astral-regex-2.0.0.tgz
 Source1047:         
https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz#/balanced-match-4.0.4.tgz
 Source1048:         
https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz#/bootstrap-5.3.8.tgz
-Source1049:         
https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz#/brace-expansion-5.0.5.tgz
+Source1049:         
https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz#/brace-expansion-5.0.7.tgz
 Source1050:         
https://registry.npmjs.org/braces/-/braces-3.0.3.tgz#/braces-3.0.3.tgz
 Source1051:         
https://registry.npmjs.org/cacheable/-/cacheable-2.3.3.tgz#/cacheable-2.3.3.tgz
 Source1052:         
https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#/callsites-3.1.0.tgz

++++++ openQA-5.1784324412.123ebeb6.obscpio -> 
openQA-5.1784641659.4dee7d1f.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1784324412.123ebeb6/.github/workflows/javascript.yml 
new/openQA-5.1784641659.4dee7d1f/.github/workflows/javascript.yml
--- old/openQA-5.1784324412.123ebeb6/.github/workflows/javascript.yml   
2026-07-17 23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/.github/workflows/javascript.yml   
2026-07-21 15:47:39.000000000 +0200
@@ -16,7 +16,7 @@
     steps:
       - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0  # 
v7.0.0
       - name: Setup Node (version ${{ matrix.node-version }})
-        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e  # 
v6.4.0
+        uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020  # 
v7.0.0
         with:
           node-version: ${{ matrix.node-version }}
       - name: npm clean-install
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/Makefile 
new/openQA-5.1784641659.4dee7d1f/Makefile
--- old/openQA-5.1784324412.123ebeb6/Makefile   2026-07-17 23:40:12.000000000 
+0200
+++ new/openQA-5.1784641659.4dee7d1f/Makefile   2026-07-21 15:47:39.000000000 
+0200
@@ -51,7 +51,7 @@
 current_dir := $(patsubst %/,%,$(dir $(mkfile_path)))
 unstables := $(shell cat tools/unstable_tests.txt | tr '\n' :)
 shellfiles := $$(file --mime-type script/* t/* container/worker/*.sh tools/* | 
sed -n 's/^\(.*\):.*text\/x-shellscript.*$$/\1/p')
-pyfiles ?= $(shell git ls-files | xargs file --mime-type 2>/dev/null | grep -E 
'text/x-script\.python|text/x-python' | grep --invert-match -E 
'^(t/data|container/openqa_data/)' | cut -d: -f1)
+pyfiles ?= $(shell git ls-files | grep -v '\.md$$' | xargs file --mime-type 
2>/dev/null | grep -E 'text/x-script\.python|text/x-python' | grep 
--invert-match -E '^(t/data|container/openqa_data/)' | cut -d: -f1)
 
 # tests need these environment variables to be unset
 OPENQA_BASEDIR =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1784324412.123ebeb6/assets/javascripts/audit_log.js 
new/openQA-5.1784641659.4dee7d1f/assets/javascripts/audit_log.js
--- old/openQA-5.1784324412.123ebeb6/assets/javascripts/audit_log.js    
2026-07-17 23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/assets/javascripts/audit_log.js    
2026-07-21 15:47:39.000000000 +0200
@@ -315,6 +315,7 @@
 function loadProductLogTable(dataTableUrl, rescheduleUrlTemplate, showActions) 
{
   const params = new URLSearchParams(document.location.search.substring(1));
   const id = params.get('id');
+  const q = params.get('q');
   let settingsAndResultsShown = false;
   if (id) {
     dataTableUrl += '?id=' + encodeURIComponent(id);
@@ -326,6 +327,7 @@
     processing: true,
     serverSide: true,
     order: [[1, 'desc']],
+    search: {search: q || ''},
     ajax: {
       url: dataTableUrl,
       type: 'GET',
@@ -363,7 +365,7 @@
       {
         targets: 1,
         render: function (data, type, row) {
-          return type === 'display' ? timeago.format(data + 'Z') : data;
+          return type === 'display' ? '<span title="' + data + 'Z">' + 
timeago.format(data + 'Z') + '</span>' : data;
         }
       },
       {targets: 2, orderable: false},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/docs/UsersGuide.md 
new/openQA-5.1784641659.4dee7d1f/docs/UsersGuide.md
--- old/openQA-5.1784324412.123ebeb6/docs/UsersGuide.md 2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/docs/UsersGuide.md 2026-07-21 
15:47:39.000000000 +0200
@@ -262,14 +262,11 @@
 a test suite and a product that appear in the same job template. The precedence
 order for variables is as follows (from lowest to highest):
 
+- Instance-wide test settings (defined in the `[test_settings]` section of 
`openqa.ini`)
 - Product
-
 - Machine
-
 - Test suite
-
 - Job template
-
 - API POST query parameters
 
 That is, variable values set as part of the API request that triggers the jobs 
will
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/etc/openqa/openqa.ini 
new/openQA-5.1784641659.4dee7d1f/etc/openqa/openqa.ini
--- old/openQA-5.1784324412.123ebeb6/etc/openqa/openqa.ini      2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/etc/openqa/openqa.ini      2026-07-21 
15:47:39.000000000 +0200
@@ -550,3 +550,11 @@
 ## The pattern is a regex.
 ## This can be specified multiple times.
 #add_worker_class_if_missing = size-.* -> size-large
+
+## Global instance-wide test settings. These are applied to all test jobs
+## with the lowest precedence, unless overridden by more specific settings
+## (like product, machine, test suite settings or API parameters).
+## Overriding with a '+' prefix (e.g. '+TEST_SETTING1') also works here.
+[test_settings]
+#TEST_SETTING1 = value
+#TEST_SETTING2 = value
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1784324412.123ebeb6/lib/OpenQA/JobSettings.pm 
new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/JobSettings.pm
--- old/openQA-5.1784324412.123ebeb6/lib/OpenQA/JobSettings.pm  2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/JobSettings.pm  2026-07-21 
15:47:39.000000000 +0200
@@ -8,6 +8,7 @@
 use File::Basename;
 use Mojo::URL;
 use Mojo::Util 'url_unescape';
+use OpenQA::App;
 use OpenQA::Log 'log_debug';
 use OpenQA::Utils qw(asset_type_from_setting get_url_short);
 use Feature::Compat::Try;
@@ -17,6 +18,21 @@
 sub generate_settings ($params) {
     my $settings = $params->{settings};
     my @worker_class;
+
+    if (my $app = OpenQA::App->singleton) {
+        if (my $global_test_settings = $app->config->{test_settings}) {
+            for my $k (keys %$global_test_settings) {
+                my $uc_k = uc $k;
+                if ($uc_k eq 'WORKER_CLASS') {
+                    push @worker_class, $global_test_settings->{$k};
+                }
+                else {
+                    $settings->{$uc_k} = $global_test_settings->{$k};
+                }
+            }
+        }
+    }
+
     for my $entity (qw (product machine test_suite job_template)) {
         next unless $params->{$entity};
         my @entity_settings = $params->{$entity}->settings;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/lib/OpenQA/Setup.pm 
new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/Setup.pm
--- old/openQA-5.1784324412.123ebeb6/lib/OpenQA/Setup.pm        2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/Setup.pm        2026-07-21 
15:47:39.000000000 +0200
@@ -341,6 +341,7 @@
             ignored_failed_minion_jobs => '',
         },
         carry_over => {%CARRY_OVER_DEFAULTS},
+        test_settings => {},
         'test_preset example' => {
             title => 'Create example test',
             info => 'Parameters to create an example test have been pre-filled 
in the following form. '
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1784324412.123ebeb6/lib/OpenQA/WebAPI/Controller/Admin/AuditLog.pm 
new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/WebAPI/Controller/Admin/AuditLog.pm
--- 
old/openQA-5.1784324412.123ebeb6/lib/OpenQA/WebAPI/Controller/Admin/AuditLog.pm 
    2026-07-17 23:40:12.000000000 +0200
+++ 
new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/WebAPI/Controller/Admin/AuditLog.pm 
    2026-07-21 15:47:39.000000000 +0200
@@ -31,7 +31,9 @@
     }
     if (my $search_value = $self->param('search[value]')) {
         my %condition = (like => "\%$search_value%");
-        push @filter_conds, {-or => [map { $_ => \%condition } 
@searchable_columns]};
+        my @or_conds = (map { $_ => \%condition } @searchable_columns);
+        push @or_conds, 'CAST(me.settings AS text)' => \%condition;
+        push @filter_conds, {-or => \@or_conds};
     }
 
     OpenQA::WebAPI::ServerSideDataTable::render_response(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1784324412.123ebeb6/lib/OpenQA/WebAPI/Plugin/IssueReporter/OpenSuseBCIbug.pm
 
new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/WebAPI/Plugin/IssueReporter/OpenSuseBCIbug.pm
--- 
old/openQA-5.1784324412.123ebeb6/lib/OpenQA/WebAPI/Plugin/IssueReporter/OpenSuseBCIbug.pm
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/WebAPI/Plugin/IssueReporter/OpenSuseBCIbug.pm
   2026-07-21 15:47:39.000000000 +0200
@@ -0,0 +1,108 @@
+# Copyright SUSE LLC
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+package OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseBCIbug;
+use Mojo::Base -strict, -signatures;
+use Mojo::Template;
+use Mojo::Loader qw(data_section);
+use Mojo::URL;
+use OpenQA::WebAPI::Plugin::IssueReporter::Context qw(get_context 
get_regression_links);
+use OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseBugzillaUtils 
qw(get_bugzilla_url);
+
+sub actions ($c) {
+    my $ctx = get_context($c) or return [];
+    my $job = $ctx->{job};
+    my $raw_distri = $job->DISTRI // '';
+    my $bz_product = 'SUSE Linux Base Container Images';
+    my $bz_url = get_bugzilla_url($raw_distri);
+
+    my (undef, $last_good) = get_regression_links($c, $job);
+    my $latest = $c->url_for('latest')->query($job->scenario_hash)->to_abs;
+    my ($build, $image) = split /_/, $ctx->{build}, 2;
+    $image //= 'NaN';
+
+    # CONTAINER_IMAGE_TO_TEST is required only for sles
+    # opensuse container links are handled internally by BCI framework
+    my @wanted_keys = qw(
+      BCI_TEST_ENVS
+      CONTAINER_IMAGE_TO_TEST
+      HDD_1
+      CONTAINER_RUNTIMES
+      BCI_IMAGE_MARKER
+      BCI_TARGET
+    );
+
+    my %is_wanted = map { $_ => 1 } @wanted_keys;
+    my %settings;
+    for my $setting ($job->settings->all) {
+        if ($is_wanted{$setting->key}) {
+            $settings{$setting->key} = $setting->value;
+        }
+    }
+
+    # BCI exists only for sles and opensuse TW
+    # TW is a special case, it inherits the same build convention as TW host
+    # therefore it has to be extracted from the mandatory BCI marker
+    if ($raw_distri eq 'opensuse') {
+        $bz_product = 'Public ' . $bz_product;
+        $image = $settings{BCI_IMAGE_MARKER} // 'NaN';
+    }
+
+    my $bci_bug = _render(
+        'bci_bug.txt.ep',
+        {
+            image => $settings{CONTAINER_IMAGE_TO_TEST} // 'NaN',
+            host_os => $settings{HDD_1} // 'NaN',
+            bci_tests => $settings{BCI_TEST_ENVS} // 'NaN',
+            cri => $settings{CONTAINER_RUNTIMES} // 'NaN',
+            target => $settings{BCI_TARGET} // 'NaN',
+            marker => $settings{BCI_IMAGE_MARKER} // 'NaN',
+            step_url => $ctx->{step_url},
+            last_good => $last_good,
+            latest => "$latest"
+        });
+
+    my $url = Mojo::URL->new($bz_url)->query(
+        {
+            short_desc => "[QE][Build $build] image $image fails",
+            comment => $bci_bug,
+            product => $bz_product,
+            bug_file_loc => $ctx->{step_url},
+            cf_foundby => 'openQA',
+        });
+
+    return [
+        {
+            id => 'bci_bugs',
+            label => 'Report BCI image bug',
+            icon => 'fa-layer-group',
+            url => "$url",
+        }];
+}
+
+sub _render ($name, $vars) {
+    my $tmpl = data_section(__PACKAGE__, $name);
+    return Mojo::Template->new(vars => 1)->render($tmpl, $vars);
+}
+
+1;
+
+__DATA__
+@@ bci_bug.txt.ep
+## Failed test
+
+<%= $step_url %>
+
+## Test environment
+
+Container image: <%= $image %>
+HostOS: <%= $host_os %>
+BCI tests: <%= $bci_tests %>
+Container runtime: <%= $cri %>
+Marker: <%= $marker %>
+Target: <%= $target %>
+
+## Useful links
+
+Last good: <%= $last_good %> (or more recent)
+The latest result in this scenario: <%= $latest %>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1784324412.123ebeb6/lib/OpenQA/WebAPI/Plugin/IssueReporter/OpenSuseIssueReporter.pm
 
new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/WebAPI/Plugin/IssueReporter/OpenSuseIssueReporter.pm
--- 
old/openQA-5.1784324412.123ebeb6/lib/OpenQA/WebAPI/Plugin/IssueReporter/OpenSuseIssueReporter.pm
    2026-07-17 23:40:12.000000000 +0200
+++ 
new/openQA-5.1784641659.4dee7d1f/lib/OpenQA/WebAPI/Plugin/IssueReporter/OpenSuseIssueReporter.pm
    2026-07-21 15:47:39.000000000 +0200
@@ -6,6 +6,7 @@
 
 use OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseKernelBug;
 use OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseGenericBug;
+use OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseBCIbug;
 use OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseProgressIssue;
 
 sub register ($self, $app, $config) {
@@ -14,6 +15,7 @@
             return [
                 
@{OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseGenericBug::actions($c)},
                 
@{OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseKernelBug::actions($c)},
+                
@{OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseBCIbug::actions($c)},
                 
@{OpenQA::WebAPI::Plugin::IssueReporter::OpenSuseProgressIssue::actions($c)},
             ];
         });
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/package-lock.json 
new/openQA-5.1784641659.4dee7d1f/package-lock.json
--- old/openQA-5.1784324412.123ebeb6/package-lock.json  2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/package-lock.json  2026-07-21 
15:47:39.000000000 +0200
@@ -724,9 +724,9 @@
       }
     },
     "node_modules/brace-expansion": {
-      "version": "5.0.5",
-      "resolved": 
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz";,
-      "integrity": 
"sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
+      "version": "5.0.7",
+      "resolved": 
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz";,
+      "integrity": 
"sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/t/25-cache.t 
new/openQA-5.1784641659.4dee7d1f/t/25-cache.t
--- old/openQA-5.1784324412.123ebeb6/t/25-cache.t       2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/t/25-cache.t       2026-07-21 
15:47:39.000000000 +0200
@@ -149,7 +149,7 @@
 $cache_log = '';
 
 $cache->get_asset($host, {id => 922756}, 'hdd', 
'[email protected]');
-my $from = 
"http://$host/tests/922756/asset/hdd/[email protected]";;
+my $from = 
"http://$host/tests/922756/asset/hdd/sle-12-SP3-x86_64-0368-textmode\@64bit.qcow2";;
 like $cache_log, qr/Downloading "sle-12-SP3-x86_64-0368-textmode\@64bit.qcow2" 
from "$from"/, 'Asset download attempt';
 like $cache_log, qr/failed: Connection refused/, 'Asset download fails with: 
Connection refused';
 $cache_log = '';
@@ -227,7 +227,7 @@
 like $cache_log, qr/Download of ".*0368-503\@64bit.qcow2" failed: 503 Service 
Unavailable/,
   'Asset download fails with 503 - Server not available';
 like $cache_log, qr/Download error 503, waiting 0.01 seconds for next try \(4 
remaining\)/, '4 tries remaining';
-like $cache_log, qr/Purging ".*[email protected]" because of too many download 
errors/,
+like $cache_log, qr/Purging ".*-503\@64bit.qcow2" because of too many download 
errors/,
   'Bailing out after too many retries';
 ok !-e $cachedir->child($host, '[email protected]'), 
'Asset does not exist in cache';
 $cache_log = '';
@@ -245,12 +245,13 @@
 
 $cache->get_asset($host, {id => 922756}, 'hdd', 
'[email protected]');
 like $cache_log, qr/Downloading "sle-12-SP3-x86_64-0368-200\@64bit.qcow2" 
from/, 'Asset download attempt';
-like $cache_log, qr/Content of ".*[email protected]" has not changed, 
updating last use/, 'Content has not changed';
+like $cache_log, qr/Content of ".*0368-200\@64bit.qcow2" has not changed, 
updating last use/, 'Content has not changed';
 $cache_log = '';
 
 $cache->get_asset($host, {id => 922756}, 'hdd', 
'[email protected]');
 like $cache_log, qr/Downloading "sle-12-SP3-x86_64-0368-200\@64bit.qcow2" 
from/, 'Asset download attempt';
-like $cache_log, qr/Content of ".*[email protected]" has not changed, 
updating last use/, 'Content has not changed';
+like $cache_log, qr/Content of ".*-0368-200\@64bit.qcow2" has not changed, 
updating last use/,
+  'Content has not changed';
 $cache_log = '';
 
 subtest 'cache purging after successful download' => sub {
@@ -293,7 +294,7 @@
 
 $cache->get_asset("http://$host";, {id => 922756}, 'hdd', 
'[email protected]');
 like $cache_log, qr/Downloading "sle-12-SP3-x86_64-0368-200\@64bit.qcow2" 
from/, 'Asset download attempt';
-like $cache_log, qr/Content of ".*[email protected]" has not changed, 
updating last use/, 'Content has not changed';
+like $cache_log, qr/Content of ".*0368-200\@64bit.qcow2" has not changed, 
updating last use/, 'Content has not changed';
 is $cache->asset($cachedir->child(base_host("http://$host";), 
'[email protected]'))->{pending}, 0,
   'Pending flag unset if asset unchanged';
 $cache_log = '';
@@ -344,7 +345,7 @@
 
     $cache->get_asset($host, {id => 922756}, 'hdd', 
'[email protected]');
     like $cache_log, qr/Downloading "sle-12-SP3-x86_64-0368-200\@64bit.qcow2" 
from/, 'Asset download attempt';
-    like $cache_log, qr/Content of ".*[email protected]" has not changed, 
updating last use/,
+    like $cache_log, qr/Content of ".*0368-200\@64bit.qcow2" has not changed, 
updating last use/,
       'Content has not changed';
     $cache_log = '';
 
@@ -354,7 +355,7 @@
     $cache_log = '';
 
     $cache->limit(512)->refresh;
-    like $cache_log, qr/Purging ".*[email protected]" because we need space for 
new assets, reclaiming 1024 Byte/,
+    like $cache_log, qr/Purging ".*200\@64bit.qcow2" because we need space for 
new assets, reclaiming 1024 Byte/,
       'Reclaimed 1024 Byte';
     like $cache_log, qr/Cache size of "$cachedir" is 0 Byte, with limit 512 
Byte/, 'Cache limit is 512 Byte';
     $cache_log = '';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/t/25-downloader.t 
new/openQA-5.1784641659.4dee7d1f/t/25-downloader.t
--- old/openQA-5.1784324412.123ebeb6/t/25-downloader.t  2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/t/25-downloader.t  2026-07-21 
15:47:39.000000000 +0200
@@ -96,7 +96,7 @@
 };
 
 subtest 'Success' => sub {
-    my $from = 
"$host/tests/922756/asset/hdd/[email protected]";
+    my $from = 
"$host/tests/922756/asset/hdd/sle-12-SP3-x86_64-0368-200\@64bit.qcow2";
     is $downloader->download($from, $to), undef, 'Success';
 
     ok -e $to, 'File downloaded';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/t/40-job_settings.t 
new/openQA-5.1784641659.4dee7d1f/t/40-job_settings.t
--- old/openQA-5.1784324412.123ebeb6/t/40-job_settings.t        2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/t/40-job_settings.t        2026-07-21 
15:47:39.000000000 +0200
@@ -4,9 +4,12 @@
 
 use Test::Most;
 use Test::Warnings ':report_warnings';
+use Mojo::Base -signatures;
+use Test::MockObject;
 
 use FindBin;
 use lib "$FindBin::Bin/lib", 
"$FindBin::Bin/../external/os-autoinst-common/lib";
+use OpenQA::App;
 use OpenQA::JobSettings;
 use OpenQA::Test::TimeLimit '3';
 
@@ -145,4 +148,47 @@
     is_deeply $unexpanded, ['MIRROR'], 'MIRROR detected as unexpanded';
 };
 
+sub mock_setting ($key, $val) { Test::MockObject->new->set_always(key => 
$key)->set_always(value => $val) }
+
+subtest 'generate_settings with global test settings' => sub {
+    my $mock_app = Test::MockObject->new->set_always(
+        config => {
+            test_settings => {
+                pretty_serial_marker => '1',
+                worker_class => 'global_worker',
+                test_setting_var => 'global_val',
+                '+overridden_var' => 'global_plus',
+                overridden_by_plus => 'global_normal',
+            }});
+    my $orig_app = OpenQA::App->singleton;
+    OpenQA::App->set_singleton($mock_app);
+    my $mock_product = Test::MockObject->new->set_list(
+        settings => (
+            mock_setting('PRODUCT_VAR', 'prod_val'),
+            mock_setting('OVERRIDDEN_VAR', 'prod_overwrites_global'),
+            mock_setting('WORKER_CLASS', 'product_worker'),
+            mock_setting('+OVERRIDDEN_BY_PLUS', 
'prod_plus_overwrites_global_normal'),
+        ));
+    my $params = {
+        settings => {},
+        product => $mock_product,
+        input_args => {
+            input_var => 'input_val',
+        }};
+    my $error = OpenQA::JobSettings::generate_settings($params);
+    is $error, undef, 'no error during generate_settings';
+    my $expected_settings = {
+        PRETTY_SERIAL_MARKER => '1',
+        WORKER_CLASS => 'global_worker,product_worker',
+        TEST_SETTING_VAR => 'global_val',
+        OVERRIDDEN_VAR => 'global_plus',
+        OVERRIDDEN_BY_PLUS => 'prod_plus_overwrites_global_normal',
+        PRODUCT_VAR => 'prod_val',
+        INPUT_VAR => 'input_val',
+    };
+    is_deeply $params->{settings}, $expected_settings,
+'generate_settings correctly applies lowest-precedence global test settings, 
respects +, and combines WORKER_CLASS';
+    OpenQA::App->set_singleton($orig_app);
+};
+
 done_testing;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/t/api/04-jobs.t 
new/openQA-5.1784641659.4dee7d1f/t/api/04-jobs.t
--- old/openQA-5.1784324412.123ebeb6/t/api/04-jobs.t    2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/t/api/04-jobs.t    2026-07-21 
15:47:39.000000000 +0200
@@ -1297,7 +1297,7 @@
     $t->post_ok('/api/v1/jobs', form => \%jobs_post_params)->status_is(200, 
'posted job with job template name');
     like
       $jobs->find($t->tx->res->json->{id})->settings_hash->{NAME},
-      qr/\d+-opensuse-Tumbleweed-DVD-aarch64-Build1234-foo@64bit/,
+      qr/\d+-opensuse-Tumbleweed-DVD-aarch64-Build1234-foo\@64bit/,
       'job template name reflected in scenario name';
     delete $jobs_post_params{JOB_TEMPLATE_NAME};
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/t/ui/17-product-log.t 
new/openQA-5.1784641659.4dee7d1f/t/ui/17-product-log.t
--- old/openQA-5.1784324412.123ebeb6/t/ui/17-product-log.t      2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/t/ui/17-product-log.t      2026-07-21 
15:47:39.000000000 +0200
@@ -75,6 +75,9 @@
     my @cell_contents = map { $_->get_text } @cells;
     ok shift @cell_contents, 'ID present';
     ok shift @cell_contents, 'time present';
+    my $time_span = $driver->find_child_element($cells[1], 'span', 'css');
+    like $time_span->get_attribute('title'), qr/^\d{4}-\d{2}-\d{2} 
\d{2}:\d{2}:\d{2}Z$/,
+      'timestamp hover title present';
     is_deeply
       \@cell_contents,
       [qw(perci scheduled opensuse 13.1 DVD i586 0091 whatever.iso), ''],
@@ -155,5 +158,21 @@
       qr/check for dependency typos and dependency cycles/, 'results';
 };
 
+subtest 'searching by URL query parameter' => sub {
+    $driver->get($url . '/admin/productlog?q=bar');
+    like $driver->get_title(), qr/Scheduled products log/, 'on product log';
+    wait_for_ajax(msg => 'search applied from query parameter');
+    my $table = $driver->find_element_by_id('product_log_table');
+    ok $table, 'products table found';
+    my @rows = $driver->find_child_elements($table, './tbody/tr[./td[text() = 
"whatever.iso"]]', 'xpath');
+    is scalar @rows, 2, 'both rows shown because they match "bar" in settings';
+
+    $driver->get($url . '/admin/productlog?q=nonexistent_search_term');
+    wait_for_ajax(msg => 'search applied from nonexistent query parameter');
+    my $table2 = $driver->find_element_by_id('product_log_table');
+    my @rows2 = $driver->find_child_elements($table2, './tbody/tr[./td[text() 
= "whatever.iso"]]', 'xpath');
+    is scalar @rows2, 0, 'no rows shown when searching for nonexistent term';
+};
+
 kill_driver();
 done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/t/ui/18-tests-details.t 
new/openQA-5.1784641659.4dee7d1f/t/ui/18-tests-details.t
--- old/openQA-5.1784324412.123ebeb6/t/ui/18-tests-details.t    2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/t/ui/18-tests-details.t    2026-07-21 
15:47:39.000000000 +0200
@@ -237,7 +237,8 @@
     my @title = map { $_->get_attribute('title') } @report_links;
     is $title[0], 'Report product bug', 'product bug report URL available';
     is $title[1], 'Report kernel product bug', 'product bug report URL 
available';
-    is $title[2], 'Report test issue', 'test issue report URL available';
+    is $title[2], 'Report BCI image bug', 'product bug report URL available';
+    is $title[3], 'Report test issue', 'test issue report URL available';
     my @url = map { $_->get_attribute('href') } @report_links;
     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';
@@ -247,9 +248,11 @@
       
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[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],
+    like $url[2], qr{bugzilla.*enter_bug}, 'BCI bug enters bugzilla report';
+    like $url[2], qr{[?&]product=(Public\+)?SUSE\+Linux\+Base\+Container}, 
'BCI bug sets product';
+    like $url[3], qr{progress.*new}, 'progress/redmine link for reporting test 
issues';
+    like $url[3], qr{in\+scenario\+%60opensuse-13\.1-DVD-i586-kde}, 
'progress/redmine link contains scenario';
+    like $url[3],
       qr{in.*$failed_module.*$failed_module%2Fsteps%2F$failed_step},
       'progress/redmine link refers to right module/step';
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1784324412.123ebeb6/templates/webapi/admin/audit_log/productlog.html.ep
 
new/openQA-5.1784641659.4dee7d1f/templates/webapi/admin/audit_log/productlog.html.ep
--- 
old/openQA-5.1784324412.123ebeb6/templates/webapi/admin/audit_log/productlog.html.ep
        2026-07-17 23:40:12.000000000 +0200
+++ 
new/openQA-5.1784641659.4dee7d1f/templates/webapi/admin/audit_log/productlog.html.ep
        2026-07-21 15:47:39.000000000 +0200
@@ -23,9 +23,17 @@
 </div>
 
 <div class="row">
-    <div class="col-sm-12" = id="scheduled-products">
+    <div class="col-sm-12" id="scheduled-products">
         <h2><%= title %></h2>
         %= include 'layouts/info'
+        <span class="search-popover">
+            <%= help_popover('Search' => '
+                <p>Allows filtering the log.</p>
+                <p>It is possible to search via the <code>q</code> query 
parameter, e.g. <code>?q=git:</code>.</p>
+                <p>The search also covers scheduled job settings (including 
Git URLs).</p>
+                ', undef, undef, 'left');
+            %>
+        </span>
         <table id="product_log_table" class="table table-striped" 
style="width: 100%">
             <thead>
                 <tr>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1784324412.123ebeb6/tools/ci/autoinst.sha 
new/openQA-5.1784641659.4dee7d1f/tools/ci/autoinst.sha
--- old/openQA-5.1784324412.123ebeb6/tools/ci/autoinst.sha      2026-07-17 
23:40:12.000000000 +0200
+++ new/openQA-5.1784641659.4dee7d1f/tools/ci/autoinst.sha      2026-07-21 
15:47:39.000000000 +0200
@@ -1 +1 @@
-703db922d4e3ddc6ec80cddccc127c719bf6558a
\ No newline at end of file
+234e3804e44685e831e3479f8b2564fd8e30f4f4
\ No newline at end of file

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.HSeQ4n/_old  2026-07-21 23:14:33.918844620 +0200
+++ /var/tmp/diff_new_pack.HSeQ4n/_new  2026-07-21 23:14:33.922844757 +0200
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1784324412.123ebeb6
-mtime: 1784324412
-commit: 123ebeb6f53202b19240394804dd5fb49d199d88
+version: 5.1784641659.4dee7d1f
+mtime: 1784641659
+commit: 4dee7d1f5a660c78220ac18bf7facaaa4150170c
 

Reply via email to