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-03-24 18:48:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Tue Mar 24 18:48:34 2026 rev:826 rq:1342076 version:5.1774278862.ea002efa

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2026-03-23 
17:14:54.985537891 +0100
+++ /work/SRC/openSUSE:Factory/.openQA.new.8177/openQA.changes  2026-03-24 
18:49:02.318876293 +0100
@@ -1,0 +2,14 @@
+Mon Mar 23 16:26:14 UTC 2026 - [email protected]
+
+- Update to version 5.1774278862.ea002efa:
+  * refactor: slightly simplify BuildResults
+  * chore(AGENTS.md): add customized file
+  * refactor: deduplicate configuration defaults and verify openqa.ini
+  * fix(ci): fix referencing commit-message-checker
+  * style: Add Test::Perl::Critic dependency
+  * docs: document "always_run" test flag
+  * feat(Makefile): add help text for missing targets
+  * fix: prevent intermittent failure in t/ui/13-admin.t
+  * fix: remove fixed container sizing in needlediff view
+
+-------------------------------------------------------------------

Old:
----
  openQA-5.1774104919.9788babf.obscpio

New:
----
  openQA-5.1774278862.ea002efa.obscpio

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

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.5K1o7y/_old  2026-03-24 18:49:04.482965585 +0100
+++ /var/tmp/diff_new_pack.5K1o7y/_new  2026-03-24 18:49:04.486965750 +0100
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1774104919.9788babf
+Version:        5.1774278862.ea002efa
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.5K1o7y/_old  2026-03-24 18:49:04.650972517 +0100
+++ /var/tmp/diff_new_pack.5K1o7y/_new  2026-03-24 18:49:04.658972847 +0100
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-devel
 Name:           %{short_name}-test
-Version:        5.1774104919.9788babf
+Version:        5.1774278862.ea002efa
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.5K1o7y/_old  2026-03-24 18:49:04.846980604 +0100
+++ /var/tmp/diff_new_pack.5K1o7y/_new  2026-03-24 18:49:04.858981100 +0100
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1774104919.9788babf
+Version:        5.1774278862.ea002efa
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.5K1o7y/_old  2026-03-24 18:49:04.958985226 +0100
+++ /var/tmp/diff_new_pack.5K1o7y/_new  2026-03-24 18:49:04.962985391 +0100
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1774104919.9788babf
+Version:        5.1774278862.ea002efa
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.5K1o7y/_old  2026-03-24 18:49:05.010987372 +0100
+++ /var/tmp/diff_new_pack.5K1o7y/_new  2026-03-24 18:49:05.014987536 +0100
@@ -90,7 +90,7 @@
 %define qemu qemu
 %endif
 # The following line is generated from dependencies.yaml
-%define style_check_requires ShellCheck perl(Code::TidyAll) perl(Perl::Critic) 
perl(Perl::Critic::Community) python3-gitlint python3-yamllint shfmt
+%define style_check_requires ShellCheck perl(Code::TidyAll) perl(Perl::Critic) 
perl(Perl::Critic::Community) perl(Test::Perl::Critic) python3-gitlint 
python3-yamllint shfmt
 # The following line is generated from dependencies.yaml
 %define cover_requires perl(Devel::Cover) 
perl(Devel::Cover::Report::Codecovbash)
 # The following line is generated from dependencies.yaml
@@ -99,7 +99,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1774104919.9788babf
+Version:        5.1774278862.ea002efa
 Release:        0
 Summary:        The openQA web-frontend, scheduler and tools
 License:        GPL-2.0-or-later

++++++ openQA-5.1774104919.9788babf.obscpio -> 
openQA-5.1774278862.ea002efa.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1774104919.9788babf/.github/workflows/commit-message-checker.yml 
new/openQA-5.1774278862.ea002efa/.github/workflows/commit-message-checker.yml
--- 
old/openQA-5.1774104919.9788babf/.github/workflows/commit-message-checker.yml   
    2026-03-24 18:49:06.695056858 +0100
+++ 
new/openQA-5.1774278862.ea002efa/.github/workflows/commit-message-checker.yml   
    2026-03-23 16:14:22.000000000 +0100
@@ -1 +1,12 @@
-symbolic link to 
../../external/os-autoinst-common/.github/workflows/commit-message-checker.yml
+---
+name: 'Commit message check'
+# yamllint disable-line rule:truthy
+on:
+  pull_request:
+  push:
+    branches:
+      - '!master'  # we must not fix commit messages when they already reached 
master
+
+jobs:
+  check-commit-message:
+    uses: 
os-autoinst/os-autoinst-common/.github/workflows/base-commit-message-checker.yml@master
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1774104919.9788babf/AGENTS.md 
new/openQA-5.1774278862.ea002efa/AGENTS.md
--- old/openQA-5.1774104919.9788babf/AGENTS.md  1970-01-01 01:00:00.000000000 
+0100
+++ new/openQA-5.1774278862.ea002efa/AGENTS.md  2026-03-23 16:14:22.000000000 
+0100
@@ -0,0 +1,35 @@
+# openQA Agent Guidelines
+
+Backend: Perl (Mojolicious), Minion job queue, PostgreSQL. Frontend:
+JavaScript (Bootstrap).
+
+## Build & Test Commands
+
+- `make tidy`: Must pass before committing (runs `perltidy` +
+  `eslint/prettier`).
+- `make test-checkstyle`: Must pass before committing.
+- `make test-unit-and-integration TESTS=t/your_test.t`: Run specific tests.
+- `make test`: Full test suite.
+
+## Conventions
+
+- Commits: [Conventional
+  Commits](https://www.conventionalcommits.org/en/v1.0.0/) format. Include
+  motivation and details for "feat" commits.
+- Documentation: AsciiDoc (`.asciidoc`).
+
+## Agent Guidelines
+
+- **Planning:** Only create `.md` plan documents in `tasks/`. Do not change
+  other files. Every plan MUST include test adaptations or new tests.
+- **Verification:** Every code change must have corresponding test adaptations
+  or new tests. `make tidy` and `make test-checkstyle` must pass before
+  creating git commits.
+
+## Constraints
+
+- `tasks/`: Read/write access for planning. NEVER run git add, git commit, or
+  git rm on this directory or delete files from there.
+- Never run git clean or any command that deletes unversioned files. Ask the
+  user for confirmation.
+- Commit message format: 50/80 rule, 80-char limit, wrap in single quotes.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1774104919.9788babf/Makefile 
new/openQA-5.1774278862.ea002efa/Makefile
--- old/openQA-5.1774104919.9788babf/Makefile   2026-03-21 15:55:19.000000000 
+0100
+++ new/openQA-5.1774278862.ea002efa/Makefile   2026-03-23 16:14:22.000000000 
+0100
@@ -210,7 +210,7 @@
 # note: Excluding dev dependencies like `eslint` via `--omit=dev` to pull in 
only dependencies needed at runtime (and for
 #       regular tests). Development tests/tooling like `js-tidy` will invoke 
`npm clean-install …` to install missing
 #       dependencies on its own anyway.
-node_modules: package-lock.json
+node_modules: package-lock.json ## Build web-related dependencies (NPM, JS, 
CSS)
        @which local-npm-registry >/dev/null 2>&1 || npm clean-install 
--no-audit --no-fund --ignore-scripts --omit=dev
        @touch node_modules
 
@@ -291,11 +291,11 @@
 endef
 
 .PHONY: run-webui-test-db
-run-webui-test-db: setup-database
+run-webui-test-db: setup-database ## Run a local web UI instance using a test 
database
        $(call RUN_SERVICE_TEST_DB,script/openqa-webui-daemon)
 
 .PHONY: run-gru-test-db
-run-gru-test-db: setup-database
+run-gru-test-db: setup-database ## Run a local GRU instance using a test 
database
        $(call RUN_SERVICE_TEST_DB,script/openqa-gru)
 
 # prepares running the tests within a container (eg. pulls os-autoinst) and 
then runs the tests considering
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1774104919.9788babf/assets/javascripts/needlediff.js 
new/openQA-5.1774278862.ea002efa/assets/javascripts/needlediff.js
--- old/openQA-5.1774104919.9788babf/assets/javascripts/needlediff.js   
2026-03-21 15:55:19.000000000 +0100
+++ new/openQA-5.1774278862.ea002efa/assets/javascripts/needlediff.js   
2026-03-23 16:14:22.000000000 +0100
@@ -38,13 +38,6 @@
   // Draw canvas into its container
   canvas.attr('width', width);
   canvas.attr('height', height);
-  container.css({
-    border: '1px solid black',
-    margin: '0px',
-    position: 'relative',
-    width: width + 'px',
-    height: height + 'px'
-  });
   container.append(canvas);
 
   Object.defineProperty(this, 'container', {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1774104919.9788babf/cpanfile 
new/openQA-5.1774278862.ea002efa/cpanfile
--- old/openQA-5.1774104919.9788babf/cpanfile   2026-03-21 15:55:19.000000000 
+0100
+++ new/openQA-5.1774278862.ea002efa/cpanfile   2026-03-23 16:14:22.000000000 
+0100
@@ -120,6 +120,7 @@
     requires 'Perl::Critic::Community';
     requires 'Perl::Tidy', '== 20260204.0.0';
     requires 'Test::CheckGitStatus';
+    requires 'Test::Perl::Critic';
 
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1774104919.9788babf/dependencies.yaml 
new/openQA-5.1774278862.ea002efa/dependencies.yaml
--- old/openQA-5.1774104919.9788babf/dependencies.yaml  2026-03-21 
15:55:19.000000000 +0100
+++ new/openQA-5.1774278862.ea002efa/dependencies.yaml  2026-03-23 
16:14:22.000000000 +0100
@@ -211,6 +211,7 @@
 
 style_check_requires:
   python3-yamllint:
+  perl(Test::Perl::Critic):
   perl(Perl::Critic):
   perl(Perl::Critic::Community):
   perl(Code::TidyAll):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1774104919.9788babf/dist/rpm/openQA.spec 
new/openQA-5.1774278862.ea002efa/dist/rpm/openQA.spec
--- old/openQA-5.1774104919.9788babf/dist/rpm/openQA.spec       2026-03-21 
15:55:19.000000000 +0100
+++ new/openQA-5.1774278862.ea002efa/dist/rpm/openQA.spec       2026-03-23 
16:14:22.000000000 +0100
@@ -90,7 +90,7 @@
 %define qemu qemu
 %endif
 # The following line is generated from dependencies.yaml
-%define style_check_requires ShellCheck perl(Code::TidyAll) perl(Perl::Critic) 
perl(Perl::Critic::Community) python3-gitlint python3-yamllint shfmt
+%define style_check_requires ShellCheck perl(Code::TidyAll) perl(Perl::Critic) 
perl(Perl::Critic::Community) perl(Test::Perl::Critic) python3-gitlint 
python3-yamllint shfmt
 # The following line is generated from dependencies.yaml
 %define cover_requires perl(Devel::Cover) 
perl(Devel::Cover::Report::Codecovbash)
 # The following line is generated from dependencies.yaml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1774104919.9788babf/docs/WritingTests.asciidoc 
new/openQA-5.1774278862.ea002efa/docs/WritingTests.asciidoc
--- old/openQA-5.1774104919.9788babf/docs/WritingTests.asciidoc 2026-03-21 
15:55:19.000000000 +0100
+++ new/openQA-5.1774278862.ea002efa/docs/WritingTests.asciidoc 2026-03-23 
16:14:22.000000000 +0100
@@ -135,6 +135,8 @@
 
 * *fatal*: When set to `1` the whole test suite is aborted if the test module
    fails. The overall state is set to `failed`.
+* *always_run*: When set to `1` the test module is executed even if a previous
+   test module failed with `fatal`.
 * *ignore_failure*: When set to `1` and the test module fails, it will not
    affect the overall result at all.
 * *milestone*: After this test succeeds, update the 'lastgood' snapshot of the
@@ -539,7 +541,8 @@
 they match the serial output which is done after the test is executed. In case
 it does not make sense to continue the test run even if the current test module
 does not have the fatal flag, use `fatal` as serial failure type, so all
-subsequent test modules will not be executed if such failure was detected.
+subsequent test modules (unless marked with `always_run`) will not be
+executed if such failure was detected.
 
 To use this functionality the test developer needs to define the patterns to
 look for in the serial output either in the main.pm or in the test itself. Any
@@ -2111,7 +2114,7 @@
 In both modes there is no need to modify tests (i.e. adding `milestone` test
 flag as the behaviour is implied). In the latter mode every test module is also
 considered `fatal`. This means the job is aborted after the first failed test
-module.
+module (unless subsequent modules are marked with `always_run`).
 
 [id="snapshots-for-each-module"]
 ==== Enable snapshots for each module
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1774104919.9788babf/lib/OpenQA/BuildResults.pm 
new/openQA-5.1774278862.ea002efa/lib/OpenQA/BuildResults.pm
--- old/openQA-5.1774104919.9788babf/lib/OpenQA/BuildResults.pm 2026-03-21 
15:55:19.000000000 +0100
+++ new/openQA-5.1774278862.ea002efa/lib/OpenQA/BuildResults.pm 2026-03-23 
16:14:22.000000000 +0100
@@ -15,10 +15,8 @@
 use Time::Seconds;
 
 sub init_job_figures ($job_result) {
-
     # relevant distributions for the build (hash is used as a set)
     $job_result->{distris} = {};
-
     # number of passed/failed/... jobs
     $job_result->{passed} = 0;
     $job_result->{failed} = 0;
@@ -31,7 +29,6 @@
 }
 
 sub count_job ($job, $jr, $labels) {
-
     $jr->{total}++;
     if ($job->state eq OpenQA::Jobs::Constants::DONE) {
         if ($job->result eq OpenQA::Jobs::Constants::PASSED) {
@@ -69,18 +66,15 @@
 }
 
 sub add_review_badge ($build_res) {
-
     $build_res->{all_passed} = $build_res->{passed} + $build_res->{softfailed} 
>= $build_res->{total} ? 1 : 0;
     $build_res->{reviewed} = $build_res->{labeled} >= $build_res->{failed} ? 1 
: 0;
     $build_res->{commented} = $build_res->{comments} >= $build_res->{failed} ? 
1 : 0;
 }
 
 sub filter_subgroups ($group, $subgroup_filter) {
-
     my @group_ids;
     my @children;
     my $group_name = $group->name;
-
     for my $child ($group->children) {
         my $full_name = $child->full_name;
         if (grep { $_ eq '' || regex_match($_, $full_name) } 
@$subgroup_filter) {
@@ -95,29 +89,24 @@
 }
 
 sub find_child_groups ($group, $subgroup_filter) {
-
     # handle regular (non-parent) groups
     return {
         group_ids => [$group->id],
         children => [],
     } unless $group->can('children');
-
     # handle simple case where no filter for subgroups present
     return {
         group_ids => $group->child_group_ids,
         children => [$group->children],
     } unless @$subgroup_filter;
-
     return filter_subgroups($group, $subgroup_filter);
 }
 
 sub compute_build_results ($group, $limit, $time_limit_days, $tags, 
$subgroup_filter, $show_tags) {
-
     # find relevant child groups taking filter into account
     my $child_groups = find_child_groups($group, $subgroup_filter);
     my $group_ids = $child_groups->{group_ids};
     my $children = $child_groups->{children};
-
     my @sorted_results;
     my %result = (
         build_results => \@sorted_results,
@@ -127,11 +116,7 @@
             id => $group->id,
             name => $group->name
         });
-
-    if (defined($limit) && int($limit) <= 0) {
-        return \%result;
-    }
-
+    return \%result if defined($limit) && int($limit) <= 0;
     # build sorting
     my $buildver_sort_mode = BUILD_SORT_BY_NAME;
     $buildver_sort_mode = $group->build_version_sort if 
$group->can('build_version_sort');
@@ -147,11 +132,8 @@
         rows => $row_limit
     );
     my %search_filter = (group_id => {in => $group_ids});
-    if ($time_limit_days) {
-        $search_filter{t_created}
-          = {'>' => time2str('%Y-%m-%d %H:%M:%S', time - ONE_DAY * 
$time_limit_days, 'UTC')};
-    }
-
+    $search_filter{t_created} = {'>' => time2str('%Y-%m-%d %H:%M:%S', time - 
ONE_DAY * $time_limit_days, 'UTC')}
+      if $time_limit_days;
     # add search filter for tags
     # caveat: a tag that references only a build, not including a version, 
might be ambiguous
     if ($tags) {
@@ -165,7 +147,6 @@
         $search_filter{BUILD} = {-in => \@builds};
         $search_filter{VERSION} = {-in => \@versions} if @versions;
     }
-
     # find relevant builds
     my $jobs_resultset = $group->result_source->schema->resultset('Jobs');
     my @builds = $jobs_resultset->search(\%search_filter, \%search_opts)->all;
@@ -175,15 +156,12 @@
         $build->{key} = join '-', $version, $buildnr;
         $versions_per_build{$buildnr}->{$version} = 1;
     }
-    if ($buildver_sort_mode == BUILD_SORT_BY_NAME) {
-        @builds = reverse sort { versioncmp($a->{key}, $b->{key}); } @builds;
-    }
-
+    @builds = reverse sort { versioncmp($a->{key}, $b->{key}); } @builds
+      if $buildver_sort_mode == BUILD_SORT_BY_NAME;
     my $max_jobs = 0;
     my $newest = ($buildver_sort_mode == BUILD_SORT_BY_OLDEST_JOB || 
$buildver_sort_mode == BUILD_SORT_BY_NAME) ? 0 : 1;
     for my $build (@builds) {
         last if defined($limit) && (--$limit < 0);
-
         my ($version, $buildnr) = ($build->VERSION, $build->BUILD);
         my $jobs = $jobs_resultset->search(
             {
@@ -200,10 +178,7 @@
             version_count => scalar keys %{$versions_per_build{$buildnr}},
         );
         init_job_figures(\%jr);
-        for my $child (@$children) {
-            init_job_figures($jr{children}->{$child->id} = {});
-        }
-
+        init_job_figures($jr{children}->{$_->id} = {}) for @$children;
         my %seen;
         my @jobs = map {
             my $key = $_->TEST . '-' . $_->ARCH . '-' . $_->FLAVOR . '-' . 
($_->MACHINE // '');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1774104919.9788babf/lib/OpenQA/Setup.pm 
new/openQA-5.1774278862.ea002efa/lib/OpenQA/Setup.pm
--- old/openQA-5.1774104919.9788babf/lib/OpenQA/Setup.pm        2026-03-21 
15:55:19.000000000 +0100
+++ new/openQA-5.1774278862.ea002efa/lib/OpenQA/Setup.pm        2026-03-23 
16:14:22.000000000 +0100
@@ -76,8 +76,8 @@
     return \%hash;
 }
 
-sub read_config ($app) {
-    my %defaults = (
+sub default_config () {
+    return {
         global => {
             appname => 'openQA',
             base_url => undef,
@@ -280,7 +280,7 @@
         influxdb => {
             ignored_failed_minion_jobs => '',
         },
-        carry_over => \%CARRY_OVER_DEFAULTS,
+        carry_over => {%CARRY_OVER_DEFAULTS},
         'test_preset example' => {
             title => 'Create example test',
             info => 'Parameters to create an example test have been pre-filled 
in the following form. '
@@ -288,13 +288,17 @@
             casedir => 
'https://github.com/os-autoinst/os-autoinst-distri-example.git',
             distri => 'example',
             build => 'openqa',
-        });
+        }};
+}
+
+sub read_config ($app) {
+    my $defaults = default_config();
 
     # in development and test mode we use fake auth and log to stderr
     my %devel_and_test_defaults = (auth => {method => 'Fake'}, logging => 
{file => undef, level => 'debug'});
     my %mode_defaults = (development => \%devel_and_test_defaults, test => 
\%devel_and_test_defaults);
 
-    my $config = _load_config($app, \%defaults, \%mode_defaults);
+    my $config = _load_config($app, $defaults, \%mode_defaults);
     my $global_config = $config->{global};
     $global_config->{recognized_referers} = [split /\s+/, 
$global_config->{recognized_referers}];
     if (my $regex = $global_config->{auto_clone_regex}) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1774104919.9788babf/t/config.t 
new/openQA-5.1774278862.ea002efa/t/config.t
--- old/openQA-5.1774104919.9788babf/t/config.t 2026-03-21 15:55:19.000000000 
+0100
+++ new/openQA-5.1774278862.ea002efa/t/config.t 2026-03-23 16:14:22.000000000 
+0100
@@ -20,8 +20,9 @@
 use OpenQA::Setup;
 use OpenQA::JobGroupDefaults;
 use OpenQA::Task::Job::Limit;
-use Mojo::File 'tempdir';
+use Mojo::File qw(path tempdir);
 use Time::Seconds;
+use Storable 'dclone';
 
 my $quiet_log = Mojo::Log->new(level => 'warn');
 
@@ -44,177 +45,29 @@
     $app->mode('test');
     my $config = read_config($app, 'reading config from default with mode 
test');
     is length($config->{_openid_secret}), 16, 'config has openid_secret';
-    my $test_config = {
-        global => {
-            appname => 'openQA',
-            branding => 'openSUSE',
-            hsts => 365,
-            audit_enabled => 1,
-            max_rss_limit => 0,
-            profiling_enabled => 0,
-            monitoring_enabled => 0,
-            mcp_enabled => 'no',
-            hide_asset_types => 'repo',
-            file_security_policy => 'download-prompt',
-            recognized_referers => [],
-            changelog_file => '/usr/share/openqa/public/Changelog',
-            job_investigate_ignore => '"(JOBTOKEN|NAME)"',
-            job_investigate_git_timeout => 20,
-            job_investigate_git_log_limit => 200,
-            search_results_limit => 50000,
-            worker_timeout => DEFAULT_WORKER_TIMEOUT,
-            force_result_regex => '',
-            parallel_children_collapsable_results_sel => ' 
.status:not(.result_passed):not(.result_softfailed)',
-            auto_clone_limit => 20,
-            api_hmac_time_tolerance => 300,
-            frontpage_builds => 3,
-            scenario_definitions_allowed_hosts => 'github.com 
raw.githubusercontent.com',
-        },
-        rate_limits => {
-            search => 5,
-        },
-        auth => {
-            method => 'Fake',
-            require_for_assets => 0,
-        },
-        'scm git' => {
-            update_remote => '',
-            update_branch => '',
-            do_push => 'no',
-            do_cleanup => 'no',
-            git_auto_clone => 'yes',
-            git_auto_commit => '',
-            git_auto_update => 'no',
-            git_auto_update_method => 'best-effort',
-            checkout_needles_sha => 'no',
-            allow_arbitrary_url_fetch => 'no',
-            temp_needle_refs_retention => 2 * ONE_MINUTE,
-        },
-        'scheduler' => {
-            max_job_scheduled_time => 7,
-            max_running_jobs => -1,
-        },
-        openid => {
-            provider => 'https://www.opensuse.org/openid/user/',
-            httpsonly => 1,
-        },
-        oauth2 => {
-            provider => '',
-            key => '',
-            secret => '',
-            authorize_url => '',
-            token_url => '',
-            user_url => '',
-            token_scope => '',
-            token_label => '',
-            id_from => 'id',
-            nickname_from => '',
-            unique_name => '',
-        },
-        hypnotoad => {
-            listen => ['http://localhost:9526/'],
-            proxy => 1,
-        },
-        audit => {
-            blacklist => '',
-            blocklist => '',
-        },
-        plugin_links => {
-            operator => {},
-            admin => {}
-        },
-        amqp => {
-            reconnect_timeout => 5,
-            publish_attempts => 10,
-            publish_retry_delay => 1,
-            publish_retry_delay_factor => 1.75,
-            url => 'amqp://guest:guest@localhost:5672/',
-            exchange => 'pubsub',
-            topic_prefix => 'suse',
-            cacertfile => '',
-            certfile => '',
-            keyfile => ''
-        },
-        obs_rsync => {
-            home => '',
-            retry_interval => 60,
-            retry_max_count => 1400,
-            queue_limit => 200,
-            concurrency => 2,
-            project_status_url => '',
-            username => '',
-            ssh_key_file => '',
-        },
-        cleanup => {
-            concurrent => 0,
-        },
-        default_group_limits => {
-            asset_size_limit => OpenQA::JobGroupDefaults::SIZE_LIMIT_GB,
-            log_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_LOGS_IN_DAYS,
-            important_log_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_IMPORTANT_LOGS_IN_DAYS,
-            result_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_RESULTS_IN_DAYS,
-            important_result_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_IMPORTANT_RESULTS_IN_DAYS,
-            job_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_JOBS_IN_DAYS,
-            important_job_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_IMPORTANT_JOBS_IN_DAYS,
-        },
-        no_group_limits => {
-            log_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_LOGS_IN_DAYS,
-            important_log_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_IMPORTANT_LOGS_IN_DAYS,
-            result_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_RESULTS_IN_DAYS,
-            important_result_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_IMPORTANT_RESULTS_IN_DAYS,
-            job_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_JOBS_IN_DAYS,
-            important_job_storage_duration => 
OpenQA::JobGroupDefaults::KEEP_IMPORTANT_JOBS_IN_DAYS,
-        },
-        minion_task_triggers => {
-            on_job_done => [],
-        },
-        misc_limits => {
-            untracked_assets_storage_duration => 14,
-            result_cleanup_max_free_percentage => 100,
-            asset_cleanup_max_free_percentage => 100,
-            screenshot_cleanup_batch_size => 
OpenQA::Task::Job::Limit::DEFAULT_SCREENSHOTS_PER_BATCH,
-            screenshot_cleanup_batches_per_minion_job => 
OpenQA::Task::Job::Limit::DEFAULT_BATCHES_PER_MINION_JOB,
-            minion_job_max_age => ONE_WEEK,
-            generic_default_limit => 10000,
-            generic_max_limit => 100000,
-            tests_overview_max_jobs => 2000,
-            all_tests_default_finished_jobs => 500,
-            all_tests_max_finished_jobs => 5000,
-            list_templates_default_limit => 5000,
-            list_templates_max_limit => 20000,
-            next_jobs_default_limit => 500,
-            next_jobs_max_limit => 10000,
-            previous_jobs_default_limit => 500,
-            previous_jobs_max_limit => 10000,
-            job_settings_max_recent_jobs => 20000,
-            assets_default_limit => 100000,
-            assets_max_limit => 200000,
-            max_online_workers => 1000,
-            wait_for_grutask_retries => 6,
-            worker_limit_retry_delay => ONE_HOUR / 4,
-            mcp_max_result_size => 500000,
-            scheduled_product_min_storage_duration => 34,
-            prio_throttling_parameters => 'MAX_JOB_TIME:0.007',
-        },
-        archiving => {
-            archive_preserved_important_jobs => 0,
-        },
-        job_settings_ui => {
-            keys_to_render_as_links => '',
-            default_data_dir => 'data',
-        },
-        influxdb => {
-            ignored_failed_minion_jobs => '',
-        },
-        carry_over => {
-            lookup_depth => 10,
-            state_changes_limit => 3,
-        },
-        webui => {
-            render_batch_size => 50,
-        },
-        secrets => {github_token => ''},
-    };
+
+    my $test_config = dclone(OpenQA::Setup::default_config());
+    # apply transformations done in read_config
+    $test_config->{global}->{recognized_referers} = [];
+    $test_config->{global}->{parallel_children_collapsable_results_sel}
+      = ' .status:not(.result_passed):not(.result_softfailed)';
+    $test_config->{auth}->{method} = 'Fake';
+    $test_config->{minion_task_triggers}->{on_job_done} = [];
+    for my $l ($test_config->{default_group_limits}, 
$test_config->{no_group_limits}) {
+        $l->{result_storage_duration} = 
OpenQA::JobGroupDefaults::KEEP_RESULTS_IN_DAYS;
+        $l->{important_result_storage_duration} = 
OpenQA::JobGroupDefaults::KEEP_IMPORTANT_RESULTS_IN_DAYS;
+        $l->{job_storage_duration} = 
OpenQA::JobGroupDefaults::KEEP_JOBS_IN_DAYS;
+        $l->{important_job_storage_duration} = 
OpenQA::JobGroupDefaults::KEEP_IMPORTANT_JOBS_IN_DAYS;
+    }
+    delete $test_config->{'test_preset example'};
+    delete $test_config->{global}->{auto_clone_regex};
+    delete $test_config->{global}->{parallel_children_collapsable_results};
+    for my $k (keys %$test_config) {
+        my $section = $test_config->{$k};
+        next unless ref $section eq 'HASH';
+        delete $section->{$_} for grep { !defined $section->{$_} } keys 
%$section;
+        delete $test_config->{$k} unless %$section;
+    }
 
     # Test configuration generation with "test" mode
     $test_config->{_openid_secret} = $config->{_openid_secret};
@@ -292,6 +145,43 @@
       'default job_storage_duration extended to result_storage_duration (no 
group)';
 };
 
+subtest 'openqa.ini documentation check' => sub {
+    my $defaults = OpenQA::Setup::default_config();
+    my $ini_path = path($FindBin::Bin)->child('..', 'etc', 'openqa', 
'openqa.ini');
+    ok -r $ini_path, "can read $ini_path";
+    my $content = $ini_path->slurp;
+
+    my %documented;
+    my $current_section;
+    for (split /\n/, $content) {
+        if (/^#?\[([^\]]+)\]/) {
+            $current_section = $1;
+        }
+        elsif ($current_section && /^#?\s*([a-z0-9_]+)\s*=/) {
+            $documented{$current_section}->{$1} = 1;
+        }
+    }
+
+    for my $section (sort keys %$defaults) {
+        # skip internal/dynamic sections
+        next if $section =~ /^(plugin_links|hooks|test_preset 
example|assets\/storage_duration|carry_over)$/;
+        for my $key (sort keys %{$defaults->{$section}}) {
+            # skip deprecated/internal/currently undocumented keys
+            next
+              if $section eq 'global'
+              && $key
+              =~ 
/^(scm|parallel_children_collapsable_results_sel|file_domain|prio_throttling_data|access_control_allow_origin_header|changelog_file|file_subdomain|search_results_limit)$/;
+            next if $section eq 'hypnotoad';
+            next if $section eq 'job_settings_ui' && $key eq 
'default_data_dir';
+            next if $section eq 'misc_limits' && $key =~ 
/^(prio_throttling_data|mcp_max_result_size)$/;
+            next if $section eq 'rate_limits' && $key eq 'search';
+            next if $section eq 'secrets';
+            next if $section eq 'audit' && $key eq 'blacklist';
+            ok $documented{$section}->{$key}, "key '$key' in section 
'[$section]' is documented in openqa.ini";
+        }
+    }
+};
+
 subtest 'trim whitespace characters from both ends of openqa.ini value' => sub 
{
     my $t_dir = tempdir;
     local $ENV{OPENQA_CONFIG} = $t_dir;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1774104919.9788babf/t/ui/13-admin.t 
new/openQA-5.1774278862.ea002efa/t/ui/13-admin.t
--- old/openQA-5.1774104919.9788babf/t/ui/13-admin.t    2026-03-21 
15:55:19.000000000 +0100
+++ new/openQA-5.1774278862.ea002efa/t/ui/13-admin.t    2026-03-23 
16:14:22.000000000 +0100
@@ -585,6 +585,12 @@
     # Make changes in a separate tab
     my $second_tab = open_new_tab($driver->get_current_url());
     $driver->switch_to_window($second_tab);
+    wait_until(
+        sub {
+            return $driver->execute_script('return typeof editor !== 
"undefined" && editor.getValue().length > 0;');
+        },
+        'editor loaded initial data'
+    );
     $form = $driver->find_element_by_id('editor-form');
     $result = $form->child('.result');
     $yaml .= ' # additional comment';

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.5K1o7y/_old  2026-03-24 18:49:18.155529727 +0100
+++ /var/tmp/diff_new_pack.5K1o7y/_new  2026-03-24 18:49:18.167530222 +0100
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1774104919.9788babf
-mtime: 1774104919
-commit: 9788babf3deee39e4b607035084754486cfcc637
+version: 5.1774278862.ea002efa
+mtime: 1774278862
+commit: ea002efad2c929be8c52a16632770814e06827ff
 

Reply via email to