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-06 19:18:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.30200 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Wed May  6 19:18:11 2026 rev:844 rq:1351023 version:5.1777995277.b985bea2

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2026-05-05 
15:16:03.780903051 +0200
+++ /work/SRC/openSUSE:Factory/.openQA.new.30200/openQA.changes 2026-05-06 
19:19:37.881371989 +0200
@@ -1,0 +2,14 @@
+Tue May 05 15:34:46 UTC 2026 - [email protected]
+
+- Update to version 5.1777995277.b985bea2:
+  * style: Enforce perlcritic policy Variables::ProtectPrivateVars
+  * fix(docs): Fix links to documentation after converting to Markdown
+  * docs: fix broken references to former .asciidoc files
+  * docs: Fix wrapping list of directories after Markdown migration
+  * docs: Improve documentation of `git_auto_clone` feature
+  * docs: Make remark about worker cache service clearer using a comma
+  * docs: Fix casing of Git in the section about setting up Git support
+  * feat: Include log in IPA results
+  * feat: enhance dynamic job limit with fast ramp-up
+
+-------------------------------------------------------------------

Old:
----
  openQA-5.1777888278.38a3a85c.obscpio

New:
----
  openQA-5.1777995277.b985bea2.obscpio

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

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.vfsijO/_old  2026-05-06 19:19:39.409434923 +0200
+++ /var/tmp/diff_new_pack.vfsijO/_new  2026-05-06 19:19:39.413435088 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1777888278.38a3a85c
+Version:        5.1777995277.b985bea2
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.vfsijO/_old  2026-05-06 19:19:39.457436901 +0200
+++ /var/tmp/diff_new_pack.vfsijO/_new  2026-05-06 19:19:39.461437065 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-devel
 Name:           %{short_name}-test
-Version:        5.1777888278.38a3a85c
+Version:        5.1777995277.b985bea2
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.vfsijO/_old  2026-05-06 19:19:39.497438548 +0200
+++ /var/tmp/diff_new_pack.vfsijO/_new  2026-05-06 19:19:39.501438713 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1777888278.38a3a85c
+Version:        5.1777995277.b985bea2
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.vfsijO/_old  2026-05-06 19:19:39.545440525 +0200
+++ /var/tmp/diff_new_pack.vfsijO/_new  2026-05-06 19:19:39.549440690 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1777888278.38a3a85c
+Version:        5.1777995277.b985bea2
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.vfsijO/_old  2026-05-06 19:19:39.585442173 +0200
+++ /var/tmp/diff_new_pack.vfsijO/_new  2026-05-06 19:19:39.589442337 +0200
@@ -99,7 +99,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1777888278.38a3a85c
+Version:        5.1777995277.b985bea2
 Release:        0
 Summary:        The openQA web-frontend, scheduler and tools
 License:        GPL-2.0-or-later

++++++ openQA-5.1777888278.38a3a85c.obscpio -> 
openQA-5.1777995277.b985bea2.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/.github/checklist.yml 
new/openQA-5.1777995277.b985bea2/.github/checklist.yml
--- old/openQA-5.1777888278.38a3a85c/.github/checklist.yml      2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/.github/checklist.yml      2026-05-05 
17:34:37.000000000 +0200
@@ -2,6 +2,6 @@
   'assets/stylesheets/**':
     - Consider providing screenshots in a PR comment to show the difference 
visually
   'docs/*.md':
-    - Consider generating documentation locally to verify it is rendered 
correctly. See https://open.qa/docs/#_making_documentation_changes
+    - Consider generating documentation locally to verify it is rendered 
correctly. See https://open.qa/docs/#making-documentation-changes
   'external/**':
     - Consider doing this change in the upstream repository directly, see 
external/os-autoinst-common/README.md
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/.perlcriticrc 
new/openQA-5.1777995277.b985bea2/.perlcriticrc
--- old/openQA-5.1777888278.38a3a85c/.perlcriticrc      2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/.perlcriticrc      2026-05-05 
17:34:37.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 
Variables::ProhibitUnusedVariables 
ValuesAndExpressions::RequireNumberSeparators 
CodeLayout::ProhibitQuotedWordLists 
RegularExpressions::ProhibitSingleCharAlternation 
BuiltinFunctions::RequireBlockGrep RegularExpressions::ProhibitUselessTopic
+include = strict ValuesAndExpressions::ProhibitInterpolationOfLiterals 
CodeLayout::ProhibitParensWithBuiltins BuiltinFunctions::RequireBlockMap 
BuiltinFunctions::ProhibitStringySplit 
ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions 
ValuesAndExpressions::RequireQuotedHeredocTerminator 
Variables::ProhibitUnusedVariables 
ValuesAndExpressions::RequireNumberSeparators 
CodeLayout::ProhibitQuotedWordLists 
RegularExpressions::ProhibitSingleCharAlternation 
BuiltinFunctions::RequireBlockGrep RegularExpressions::ProhibitUselessTopic 
Variables::ProtectPrivateVars
 
 # ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions
 # No operators like < =~ ! allowed in 'unless' or 'until', only simple
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/README.md 
new/openQA-5.1777995277.b985bea2/README.md
--- old/openQA-5.1777888278.38a3a85c/README.md  2026-05-04 11:51:18.000000000 
+0200
+++ new/openQA-5.1777995277.b985bea2/README.md  2026-05-05 17:34:37.000000000 
+0200
@@ -31,7 +31,7 @@
 [our Codespace](https://codespaces.new/os-autoinst/openQA?quickstart=1).
 See also: [GitHub Codespaces 
documentation](https://docs.github.com/en/codespaces)
 
-See [openQA in a browser](https://open.qa/docs/#_openqa_in_a_browser) for
+See [openQA in a browser](https://open.qa/docs/#openqa-in-a-browser) for
 documentation on how to use it.
 
 # Contributing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/container/helm/README.md 
new/openQA-5.1777995277.b985bea2/container/helm/README.md
--- old/openQA-5.1777888278.38a3a85c/container/helm/README.md   2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/container/helm/README.md   2026-05-05 
17:34:37.000000000 +0200
@@ -121,4 +121,4 @@
 ### Worker
 
 The worker requires some basic configuration, as described in the
-[documentation](http://open.qa/docs/#_run_openqa_workers).
+[documentation](http://open.qa/docs/#run-openqa-workers).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/docs/ContainerizedSetup.md 
new/openQA-5.1777995277.b985bea2/docs/ContainerizedSetup.md
--- old/openQA-5.1777888278.38a3a85c/docs/ContainerizedSetup.md 2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/docs/ContainerizedSetup.md 2026-05-05 
17:34:37.000000000 +0200
@@ -251,7 +251,7 @@
 
 You have to put your tests under `data/tests` directory and ISOs under
 `data/factory/iso` directory. For testing openSUSE, follow
-[this 
guide](https://github.com/os-autoinst/openQA/blob/master/docs/GettingStarted.asciidoc#testing-opensuse-or-fedora).
+[this guide](GettingStarted.md#get-testing).
 
 The test distribution might have additional dependencies which need to be
 installed into the worker container before tests can run. To install those
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/docs/Contributing.md 
new/openQA-5.1777995277.b985bea2/docs/Contributing.md
--- old/openQA-5.1777888278.38a3a85c/docs/Contributing.md       2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/docs/Contributing.md       2026-05-05 
17:34:37.000000000 +0200
@@ -263,7 +263,7 @@
 
 For openSUSE you need the packages `openQA` and `os-autoinst`.
 That should be everything necessary to run an openQA instance. For more
-details check \<\<Installing.asciidoc#\_installation,Installation\>.
+details check [Installation](Installing.md#installation).
 
 If you have to manually install packages, look into the `dependencies.yaml`
 file or the spec file, e.g. `dist/rpm/openQA.spec` (or `dist/rpm/*.spec` in 
general). You can leave out sections starting with `test_requires` for example.
@@ -300,8 +300,8 @@
 The following explains in detail what is necessary to develop openQA code.
 
 For a setup with containers you can check out the
-\<\<Contributing.asciidoc#quick-container-development-setup,Quick container
-development setup\>\> below with a complete list of instructions.
+[Quick container development setup](#quick-container-development-setup)
+below with a complete list of instructions.
 
 Otherwise follow the detailed steps below. This setup is applicable to a
 container environment as well as without.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/docs/Installing.md 
new/openQA-5.1777995277.b985bea2/docs/Installing.md
--- old/openQA-5.1777888278.38a3a85c/docs/Installing.md 2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/docs/Installing.md 2026-05-05 
17:34:37.000000000 +0200
@@ -829,18 +829,18 @@
 [Cleanup of assets, results and other data](UsersGuide.md#cleanup)
 section.
 
-## Setting up git support
+## Setting up Git support
 
-If your tests and needles are stored in git, openQA can perform various 
operations:
+If your tests and needles are stored in Git, openQA can perform various 
operations:
 
 - Automatically commit needles created in the web UI editor back to the 
repository
 
 - Automatically update the repository when scheduling tests
 
-- Update the server's tests and needles from git repos specified in a job's 
`CASEDIR` and  `NEEDLES_DIR` variables
+- Update the server's tests and needles from Git repos specified in a job's 
`CASEDIR` and  `NEEDLES_DIR` variables
 
 - Attempt to have the web UI display the correct needles each job was executed 
with via
-  temporary git checkouts, based on its variables
+  temporary Git checkouts, based on its variables
 
 By default, cloning based on `CASEDIR` and `NEEDLES_DIR` is enabled, but the 
other
 features are disabled. To control these features, you can use these config 
settings:
@@ -858,8 +858,11 @@
 
 - `git_auto_update` controls automatic test/needle updating when scheduling 
tests.
 - `git_auto_clone` controls the automatic cloning of repos referenced by 
`CASEDIR` and  `NEEDLES_DIR`, at job schedule time.
+  Check out the
+  [section about 
directories](Installing.md#terms-and-variables-for-certain-directories-used-by-openqa-and-isotovideo)
+  for where the repositories will be stored.
 - `checkout_needles_sha` controls the feature whereby, when a job viewed in 
the web UI has
-  variables indicating the needles came from a specific git repository and 
ref, openQA will
+  variables indicating the needles came from a specific Git repository and 
ref, openQA will
   attempt to clone that ref and display the needles from it.
 
 ### Configuration of automatic needle commit feature
@@ -905,7 +908,7 @@
 ```
 
 If you clone the needle repository via HTTP, you can still make `geekotest`
-able to push via SSH with a git configuration. For GitHub, it would look like
+able to push via SSH with a Git configuration. For GitHub, it would look like
 this:
 
 ``` sh
@@ -922,7 +925,7 @@
   pushInsteadOf = https://github.com/
 ```
 
-You can apply the same kind of thing for any other git hosting provider.
+You can apply the same kind of thing for any other Git hosting provider.
 
 ## Referer settings to auto-mark important jobs
 
@@ -1270,7 +1273,7 @@
 instance) it results in downloading the same assets several times. In
 such case, one can setup local cache on their own (without using
 openqa-worker-cacheservice service) and share it with workers using
-some network filesystem (see [Installing.asciidoc#Configuring remote 
workers](Installing.md#Configuring remote workers)
+some network filesystem (see [Configuring remote 
workers](Installing.md#configuring_remote_workers)
 section above).
 Such setups can use `SYNC_ASSETS_HOOK` in
 [the web UI configuration](GettingStarted.md#configuration) to ensure the
@@ -1804,59 +1807,77 @@
 ## Terms and variables for certain directories used by openQA and isotovideo
 
 - the "base directory"
-
   - by default `/var/lib`
-
   - configurable via environment variable `OPENQA_BASEDIR`
-
   - referred as `$basedir` within openQA
 
 - the "project directory"
-
   - defined as `$basedir/openqa`, by default `/var/lib/openqa`
-
   - referred as `$prjdir` within openQA
 
 - the "archive directory"
-
   - defined as `$prjdir/openqa`, by default `/var/lib/openqa/archive`
-
   - referred as `$archivedir` within openQA
 
-- the "share directory": contains directories shared between web UI and 
(remote) workers
-
+- the "share directory": contains directories shared between web UI and 
(remote)
+  workers
   - defined as `$prjdir/share`, by default `/var/lib/openqa/share`
-
   - referred as `$sharedir` within openQA
 
 - the "test case directory": contains a test distribution
-
   - by default `$sharedir/tests/$distri` or `$sharedir/tests/$distri-$version`
+  - configurable via the test variable `CASEDIR` (see backend variables
+    documentation) - this default is provided by openQA; when starting
+    isotovideo manually the `CASEDIR` variable **must** be initialized by hand
+  - relative paths are relative to `$sharedir/tests`; to avoid symlinking, use
+    e.g. `CASEDIR=opensuse` for `$sharedir/tests/opensuse` despite differing
+    `DISTRI`
+  - specifying a Git URL as `CASEDIR` is also possible; with `git_auto_clone`
+    enabled, openQA will create a checkout of the repository under the 
mentioned
+    default location if it does not already exist
+    - no de-duplication is done, e.g.
+      `CASEDIR=https://github.com/…/…-distri-opensuse.git` will lead to a
+      checkout under `$sharedir/tests/opensuse` with `DISTRI=opensuse` and a
+      separate checkout under `$sharedir/tests/microos` with `DISTRI=microos`
+      - separate checkouts can be avoided by manual symlinking, e.g. a symlink
+        for `microos` pointing to `opensuse` will prevent the duplicate
+        checkouts in this example
+  - might contain the sub directory `lib` for placing Perl modules used by the
+    tests
 
-  - configurable via the test variable `CASEDIR` (see backend variables 
documentation) - this default is provided by openQA; when starting isotovideo 
manually the `CASEDIR` variable **must** be
-    initialized by hand
-
-  - relative paths are relative to `$sharedir/tests`; to avoid symlinking, use 
e.g. `CASEDIR=opensuse` for `$sharedir/tests/opensuse` despite differing 
`DISTRI`
-
-  - might contain the sub directory `lib` for placing Perl modules used by the 
tests - the "product directory": contains the test schedule (`main.pm`) for a 
certain product within a test distribution
-
+- the "product directory": contains the test schedule (`main.pm`) for a certain
+  product within a test distribution
   - by default identical to the "test case directory"
+  - usually a directory `products/$distri` within the "test case directory"
+  - configurable via the test variable `PRODUCTDIR` (see backend variables
+    documentation)
 
-  - usually a directory `products/$distri` within the "test case directory" - 
configurable via the test variable `PRODUCTDIR` (see backend variables 
documentation)
-
-- the "needles directory": contains reference images for a certain product 
within a test distribution
-
+- the "needles directory": contains reference images for a certain product
+  within a test distribution
   - by default `$PRODUCTDIR/needles`
-
-  - configurable via the test variable `NEEDLES_DIR` (see backend variables 
documentation)
+  - configurable via the test variable `NEEDLES_DIR` (see backend variables
+    documentation)
+  - specifying a Git URL as `NEEDLES_DIR` is also possible; with
+    `git_auto_clone` enabled, openQA will create a checkout of the repository
+    under the mentioned default location if it does not already exist
 
 ### Further notes
+- The mentioned `git_auto_clone` setting is part of the general
+  [Git support](Installing.md#setting-up-git-support) and works best if used
+  consistently. If e.g. only specifying a Git URL for `CASEDIR` but not for
+  `NEEDLES_DIR`, only the former will be cloned and needles will be missing if
+  they are provided by a separate repository.
+
+  - As mentioned, there is no de-duplication of checkouts. So when cloning a 
job
+    with e.g. `CASEDIR=https://github.com/…/…-distri-opensuse.git` and
+    `DISTRI=microos` but no `NEEDLES_DIR`, needles will be missing despite 
being
+    present for `DISTRI=opensuse`.
 
 - Setting the test variables has only an influence on os-autoinst. The web UI 
on the other hand always relies
   on the directory structure described above. For the exact details how these 
paths are computed by the web UI
   have a look at `lib/OpenQA/Utils.pm`.
 
-- When enabling the worker cache parts of the usual "share directory" are 
located in the specified cache
+- When enabling the worker cache, parts of the usual "share directory" are 
located in the specified cache
   directory on the worker host.
 
 # Automatic installation of the operating systems for openQA machines
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/docs/UsersGuide.md 
new/openQA-5.1777995277.b985bea2/docs/UsersGuide.md
--- old/openQA-5.1777888278.38a3a85c/docs/UsersGuide.md 2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/docs/UsersGuide.md 2026-05-05 
17:34:37.000000000 +0200
@@ -1371,7 +1371,7 @@
 `SCENARIO_DEFINITIONS_YAML_FILE` which expects the file path of the YAML 
document
 on the openQA host. One can also specify an HTTP/HTTPs URL via that variable
 when `async=1` is used (see
-[UsersGuide.asciidoc#\_spawning_multiple_jobs_based_on_templates_isos_post](UsersGuide.md#spawning_multiple_jobs_based_on_templates_isos_post)
+[Spawning multiple jobs based on templates - isos 
post](UsersGuide.md#spawning_multiple_jobs_based_on_templates_isos_post)
 for details). Then this file is downloaded by the openQA host. The specified
 host name must be allowed via the configuration setting
 `scenario_definitions_allowed_hosts`.
@@ -1896,11 +1896,11 @@
   to handle flaky issues and even automatically retrigger according tests
 
 - In case of known sporadic issues that can not be fixed quickly consider
-  automatic retries of jobs <http://open.qa/docs/#_automatic_retries_of_jobs>
+  [automatic retries of jobs](WritingTests.md#automatic-retries-of-jobs).
 
 - In case of known non-sporadic test issues that can not be fixed quickly
-  consider overwriting the result of jobs
-  <http://open.qa/docs/#_overwrite_result_of_job>
+  consider
+  [overwriting the result of jobs](UsersGuide.md#overwrite-result-of-job).
 
 - To quickly label and - as desired - restart multiple jobs consider using the
   command line application `openqa-label-all`. Call `openqa-label-all --help`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/docs/WritingTests.md 
new/openQA-5.1777995277.b985bea2/docs/WritingTests.md
--- old/openQA-5.1777888278.38a3a85c/docs/WritingTests.md       2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/docs/WritingTests.md       2026-05-05 
17:34:37.000000000 +0200
@@ -914,8 +914,9 @@
 
 ### Handling of dependencies when cloning jobs
 
-Be sure to have read the [job dependencies](WritingTests.md#_job_dependencies) 
section to have an understanding of different dependency types
-and the distinction between parents and children.
+Be sure to have read the [job dependencies](WritingTests.md#job-dependencies)
+section to have an understanding of different dependency types and the
+distinction between parents and children.
 
 When cloning a job via `openqa-clone-job`, parent jobs are cloned as well by 
default, regardless of the type. Use `--skip-deps` to avoid cloning parent 
jobs. Use `--skip-chained-deps` to avoid cloning parents of the types `CHAINED` 
and
 `DIRECTLY_CHAINED`. When cloning a job via `openqa-clone-job`, child jobs of 
the type `PARALLEL` are cloned by default. Use `--clone-children` to clone 
child jobs of other types as
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/etc/openqa/openqa.ini 
new/openQA-5.1777995277.b985bea2/etc/openqa/openqa.ini
--- old/openQA-5.1777888278.38a3a85c/etc/openqa/openqa.ini      2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/etc/openqa/openqa.ini      2026-05-05 
17:34:37.000000000 +0200
@@ -228,7 +228,7 @@
 
 ## Sets the storage duration in days for the different audit event types
 [audit/storage_duration]
-## By default cleanup is disabled, see 
http://open.qa/docs/#_auditing_tracking_openqa_changes
+## By default cleanup is disabled, see 
https://open.qa/docs/#auditing---tracking-openqa-changes
 ## The following categories with example values can be uncommented as needed
 #startup = 10
 #jobgroup = 365
@@ -463,10 +463,14 @@
 #dynamic_job_limit_enabled = 0
 ## Minimum effective job limit when dynamic scaling is active. Defaults to 50.
 #dynamic_job_limit_min = 50
-## Load average above which the effective limit is scaled down. 0 = 
auto-detect (nproc * 0.85).
+## Load average above which the effective limit is scaled down. 0 = 
auto-detect (nproc * dynamic_job_limit_load_threshold_factor).
 #dynamic_job_limit_load_threshold = 0
-## Load average for emergency cutback (3x step decrease). 0 = auto-detect 
(nproc * 1.5).
+## Factor for auto-detecting the load threshold. Defaults to 0.85.
+#dynamic_job_limit_load_threshold_factor = 0.85
+## Load average for emergency cutback (3x step decrease). 0 = auto-detect 
(nproc * dynamic_job_limit_load_critical_factor).
 #dynamic_job_limit_load_critical = 0
+## Factor for auto-detecting the critical load threshold. Defaults to 1.5.
+#dynamic_job_limit_load_critical_factor = 1.5
 ## Number of jobs to add/remove per adjustment. Defaults to 10.
 #dynamic_job_limit_step = 10
 ## Minimum seconds between dynamic limit adjustments. Defaults to 60.
@@ -483,6 +487,10 @@
 ## stored on; scheduling is suspended if the free storage falls under the
 ## specified percentage. Defaults to 5. Set to 0 to disable.
 #assets_min_free_storage_space_percentage = 5
+## Fraction of threshold below which all load averages must fall to scale up. 
Defaults to 0.7.
+#dynamic_job_limit_scale_up_hysteresis = 0.7
+## Fraction of threshold below which "fast ramp-up" (double step) is active. 
Defaults to 0.3.
+#dynamic_job_limit_fast_ramp_up_load_factor = 0.3
 
 ## Configuration of the label/bugref carry-over
 [carry_over]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Git.pm 
new/openQA-5.1777995277.b985bea2/lib/OpenQA/Git.pm
--- old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Git.pm  2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/lib/OpenQA/Git.pm  2026-05-05 
17:34:37.000000000 +0200
@@ -141,7 +141,7 @@
                     and $e->stderr =~ m/Authentication failed for .http/)
                 {
                     $msg
-                      .= '. See https://open.qa/docs/#_setting_up_git_support 
on how to setup git support and possibly push via ssh.';
+                      .= '. See https://open.qa/docs/#setting-up-git-support 
on how to setup git support and possibly push via ssh.';
                     $e->msg($msg);
                 }
             }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Parser/Format/IPA.pm 
new/openQA-5.1777995277.b985bea2/lib/OpenQA/Parser/Format/IPA.pm
--- old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Parser/Format/IPA.pm    
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/lib/OpenQA/Parser/Format/IPA.pm    
2026-05-05 17:34:37.000000000 +0200
@@ -60,6 +60,7 @@
         my $details = {result => $result->{result}};
         my $text_fn = "IPA-$t_name.txt";
         my $content = join "\n", $t_name, $result->{result};
+        $content .= "\nlog:\t$res->{test}->{log}" if (defined 
$res->{test}->{log});
 
         $details->{text} = $text_fn;
         $details->{title} = $t_name;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Scheduler/DynamicLimit.pm 
new/openQA-5.1777995277.b985bea2/lib/OpenQA/Scheduler/DynamicLimit.pm
--- old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Scheduler/DynamicLimit.pm       
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/lib/OpenQA/Scheduler/DynamicLimit.pm       
2026-05-05 17:34:37.000000000 +0200
@@ -10,10 +10,29 @@
 use OpenQA::Utils qw(load_avg);
 use Time::HiRes 'time';
 
-# Fraction of threshold below which all load averages must fall to scale up.
-use constant SCALE_UP_HYSTERESIS => 0.7;
-# Multiplier applied to step on an emergency (critical) cutback.
-use constant EMERGENCY_STEP_MULTIPLIER => 3;
+use constant {
+    SCALE_UP_HYSTERESIS => 0.7,
+    FAST_RAMP_UP_LOAD_FACTOR => 0.3,
+    LOAD_THRESHOLD_FACTOR => 0.85,
+    LOAD_CRITICAL_FACTOR => 1.5,
+    STEP => 10,
+    MIN => 50,
+    INTERVAL => 60,
+    EMERGENCY_STEP_MULTIPLIER => 3,
+};
+
+use constant DEFAULTS => {
+    dynamic_job_limit_load_threshold => 0,
+    dynamic_job_limit_load_threshold_factor => LOAD_THRESHOLD_FACTOR,
+    dynamic_job_limit_load_critical => 0,
+    dynamic_job_limit_load_critical_factor => LOAD_CRITICAL_FACTOR,
+    dynamic_job_limit_step => STEP,
+    dynamic_job_limit_min => MIN,
+    max_running_jobs => -1,
+    dynamic_job_limit_interval => INTERVAL,
+    dynamic_job_limit_scale_up_hysteresis => SCALE_UP_HYSTERESIS,
+    dynamic_job_limit_fast_ramp_up_load_factor => FAST_RAMP_UP_LOAD_FACTOR,
+};
 
 has effective_limit => undef;
 
@@ -25,13 +44,14 @@
 
 # Returns the number of online CPUs by counting processor entries in 
/proc/cpuinfo.
 sub _nproc () {
-    scalar grep { /^processor\s*:/ } split /\n/, path('/proc/cpuinfo')->slurp;
+    state $cpus = scalar grep { /^processor\s*:/ } split /\n/, 
path('/proc/cpuinfo')->slurp;
+    return $cpus;
 }
 
 # Returns a resolved (non-zero) threshold, falling back to nproc * $factor.
 sub _resolve_threshold ($configured, $factor) {
     return $configured if $configured > 0;
-    state $nproc = _nproc();
+    my $nproc = _nproc();
     return $nproc > 0 ? $nproc * $factor : 10 * $factor;
 }
 
@@ -39,13 +59,24 @@
 # Returns a hash reference of typed values; this is the single point coupling
 # DynamicLimit to the config key names.
 sub _extract_config ($config) {
+    my $defaults = DEFAULTS();
     return {
-        threshold => 
_resolve_threshold($config->{dynamic_job_limit_load_threshold}, 0.85),
-        critical => 
_resolve_threshold($config->{dynamic_job_limit_load_critical}, 1.5),
-        step => $config->{dynamic_job_limit_step},
-        min => $config->{dynamic_job_limit_min},
-        max => $config->{max_running_jobs},
-        interval => $config->{dynamic_job_limit_interval},
+        threshold => _resolve_threshold(
+            $config->{dynamic_job_limit_load_threshold} // 
$defaults->{dynamic_job_limit_load_threshold},
+            $config->{dynamic_job_limit_load_threshold_factor} // 
$defaults->{dynamic_job_limit_load_threshold_factor}
+        ),
+        critical => _resolve_threshold(
+            $config->{dynamic_job_limit_load_critical} // 
$defaults->{dynamic_job_limit_load_critical},
+            $config->{dynamic_job_limit_load_critical_factor} // 
$defaults->{dynamic_job_limit_load_critical_factor}
+        ),
+        step => $config->{dynamic_job_limit_step} // 
$defaults->{dynamic_job_limit_step},
+        min => $config->{dynamic_job_limit_min} // 
$defaults->{dynamic_job_limit_min},
+        max => $config->{max_running_jobs} // $defaults->{max_running_jobs},
+        interval => $config->{dynamic_job_limit_interval} // 
$defaults->{dynamic_job_limit_interval},
+        scale_up_hysteresis => $config->{dynamic_job_limit_scale_up_hysteresis}
+          // $defaults->{dynamic_job_limit_scale_up_hysteresis},
+        fast_ramp_up_load_factor => 
$config->{dynamic_job_limit_fast_ramp_up_load_factor}
+          // $defaults->{dynamic_job_limit_fast_ramp_up_load_factor},
     };
 }
 
@@ -54,9 +85,10 @@
 sub _adjust ($self, $load, $p) {
     my $current = $self->effective_limit;
     my ($l1, $l5, $l15) = @$load;
+    my $load_max = max($l1, $l5, $l15);
 
     my $new;
-    if (max($l1, $l5, $l15) > $p->{critical}) {
+    if ($load_max > $p->{critical}) {
         # Emergency: cut back aggressively
         $new = max($p->{min}, $current - $p->{step} * 
EMERGENCY_STEP_MULTIPLIER);
     }
@@ -64,17 +96,19 @@
         # Load rising above threshold: decrease conservatively
         $new = max($p->{min}, $current - $p->{step});
     }
-    elsif (max($l1, $l5, $l15) < $p->{threshold} * SCALE_UP_HYSTERESIS) {
+    elsif ($load_max < $p->{threshold} * $p->{scale_up_hysteresis}) {
         # Load well below threshold on all horizons: increase conservatively
-        $new = $p->{max} >= 0 ? min($p->{max}, $current + $p->{step}) : 
$current + $p->{step};
+        # Double step for fast ramp-up if load is very low
+        my $step = $load_max < $p->{threshold} * 
$p->{fast_ramp_up_load_factor} ? $p->{step} * 2 : $p->{step};
+        $new = $p->{max} >= 0 ? min($p->{max}, $current + $step) : $current + 
$step;
     }
     else {
         $new = $current;
     }
 
     $self->effective_limit($new);
-    log_debug(sprintf 'Dynamic job limit: %d (load: %.2f/%.2f/%.2f, threshold: 
%.2f, critical: %.2f)',
-        $new, $l1, $l5, $l15, $p->{threshold}, $p->{critical});
+    log_debug(sprintf 'Dynamic job limit: %d (min: %d, max: %d, load: 
%.2f/%.2f/%.2f, threshold: %.2f, critical: %.2f)',
+        $new, $p->{min}, $p->{max}, $l1, $l5, $l15, $p->{threshold}, 
$p->{critical});
     return $new;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Schema/Result/Jobs.pm 
new/openQA-5.1777995277.b985bea2/lib/OpenQA/Schema/Result/Jobs.pm
--- old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Schema/Result/Jobs.pm   
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/lib/OpenQA/Schema/Result/Jobs.pm   
2026-05-05 17:34:37.000000000 +0200
@@ -789,7 +789,7 @@
                 die "Direct parent $parent_id needs to be cloned as well for 
the directly chained dependency "
                   . 'to work correctly. It is generally better to restart the 
parent which will restart all children '
                   . 'as well. Check out the '
-                  . '<a 
href="https://open.qa/docs/#_handling_of_related_jobs_on_failure_cancellation_restart";>'
+                  . '<a 
href="https://open.qa/docs/#handling-of-related-jobs-on-failure--cancellation--restart";>'
                   . "documentation</a> for more information.\n"
                   if $no_directly_chained_parent;
                 $p->cluster_jobs(jobs => $jobs, skip_children => 1, cancelmode 
=> $cancelmode);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Setup.pm 
new/openQA-5.1777995277.b985bea2/lib/OpenQA/Setup.pm
--- old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Setup.pm        2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/lib/OpenQA/Setup.pm        2026-05-05 
17:34:37.000000000 +0200
@@ -20,6 +20,7 @@
 use OpenQA::Constants qw(DEFAULT_WORKER_TIMEOUT MAX_TIMER);
 use OpenQA::JobGroupDefaults;
 use OpenQA::Jobs::Constants qw(OK_RESULTS);
+use OpenQA::Scheduler::DynamicLimit;
 use OpenQA::Task::Job::Limit;
 use Feature::Compat::Try;
 
@@ -153,13 +154,8 @@
         },
         scheduler => {
             max_job_scheduled_time => 7,
-            max_running_jobs => -1,
             dynamic_job_limit_enabled => 0,
-            dynamic_job_limit_min => 50,
-            dynamic_job_limit_load_threshold => 0,
-            dynamic_job_limit_load_critical => 0,
-            dynamic_job_limit_step => 10,
-            dynamic_job_limit_interval => 60,
+            %{OpenQA::Scheduler::DynamicLimit->DEFAULTS},
             results_min_free_storage_space_percentage => 5,
             archive_min_free_storage_space_percentage => 5,
             assets_min_free_storage_space_percentage => 5,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Task/Git/Clone.pm 
new/openQA-5.1777995277.b985bea2/lib/OpenQA/Task/Git/Clone.pm
--- old/openQA-5.1777888278.38a3a85c/lib/OpenQA/Task/Git/Clone.pm       
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/lib/OpenQA/Task/Git/Clone.pm       
2026-05-05 17:34:37.000000000 +0200
@@ -121,7 +121,7 @@
     die <<~"END_OF_MESSAGE" unless $git->is_workdir_clean;
         NOT updating dirty Git checkout at '$path'.
         In case this is expected (e.g. on a development openQA instance) you 
can disable auto-updating.
-        Then the Git checkout will no longer be kept up-to-date, though. Check 
out http://open.qa/docs/#_getting_tests for details.
+        Then the Git checkout will no longer be kept up-to-date, though. Check 
out https://open.qa/docs/#getting-tests for details.
         END_OF_MESSAGE
 
     unless ($requested_branch) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/lib/OpenQA/WebAPI/Plugin/Helpers.pm 
new/openQA-5.1777995277.b985bea2/lib/OpenQA/WebAPI/Plugin/Helpers.pm
--- old/openQA-5.1777888278.38a3a85c/lib/OpenQA/WebAPI/Plugin/Helpers.pm        
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/lib/OpenQA/WebAPI/Plugin/Helpers.pm        
2026-05-05 17:34:37.000000000 +0200
@@ -171,7 +171,7 @@
             $c->help_popover(
                 'Help for the <em>TODO</em>-filter',
                 '<p>Shows only jobs that need to be labeled for the black 
review badge to show up</p>',
-                'http://open.qa/docs/#_review_badges',
+                'https://open.qa/docs/#review-badges',
                 'documentation about review badges'
             );
         });
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/profiles/apparmor.d/local/usr.share.openqa.script.openqa
 
new/openQA-5.1777995277.b985bea2/profiles/apparmor.d/local/usr.share.openqa.script.openqa
--- 
old/openQA-5.1777888278.38a3a85c/profiles/apparmor.d/local/usr.share.openqa.script.openqa
   2026-05-04 11:51:18.000000000 +0200
+++ 
new/openQA-5.1777995277.b985bea2/profiles/apparmor.d/local/usr.share.openqa.script.openqa
   2026-05-05 17:34:37.000000000 +0200
@@ -1,3 +1,3 @@
 # Site-specific additions and overrides for 'usr.share.openqa.script.openqa'
 # For example to cover custom "job done" hooks, see
-# http://open.qa/docs/#_enable_custom_hook_scripts_on_job_done_based_on_result
+# https://open.qa/docs/#enable-custom-hook-scripts-on-job-done-based-on-result
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/public/openqa-cli.yaml 
new/openQA-5.1777995277.b985bea2/public/openqa-cli.yaml
--- old/openQA-5.1777888278.38a3a85c/public/openqa-cli.yaml     2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/public/openqa-cli.yaml     2026-05-05 
17:34:37.000000000 +0200
@@ -92,12 +92,12 @@
           FLAVOR=my-flavor VERSION=42 BUILD=42 TEST=my-test
 
         # Trigger a single set of jobs (see
-        # https://open.qa/docs/#_spawning_single_new_jobs_jobs_post for 
details)
+        # https://open.qa/docs/#spawning-single-new-jobs---jobs-post for 
details)
         openqa-cli api -X POST jobs \
           TEST:0=first-job TEST:1=second-job _START_AFTER:1=0
 
         # Trigger jobs on ISO "foo.iso" creating a "scheduled product" (see
-        # 
https://open.qa/docs/#_spawning_multiple_jobs_based_on_templates_isos_post
+        # 
https://open.qa/docs/#spawning-multiple-jobs-based-on-templates---isos-post
         # for details, e.g for considering to use the `async` flag)
         openqa-cli api --o3 -X POST isos ISO=foo.iso \
           DISTRI=my-distri FLAVOR=my-flavor ARCH=my-arch VERSION=42 BUILD=1234
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/systemd/openqa-webui.service 
new/openQA-5.1777995277.b985bea2/systemd/openqa-webui.service
--- old/openQA-5.1777888278.38a3a85c/systemd/openqa-webui.service       
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/systemd/openqa-webui.service       
2026-05-05 17:34:37.000000000 +0200
@@ -3,7 +3,7 @@
 Wants=openqa-setup-db.service openqa-livehandler.service 
openqa-websockets.service openqa-gru.service openqa-enqueue-asset-cleanup.timer 
openqa-enqueue-result-cleanup.timer openqa-enqueue-bug-cleanup.timer 
openqa-minion-restart.path
 After=postgresql.service openqa-setup-db.service nss-lookup.target 
remote-fs.target apache2.service nginx.service caddy.service
 Before=openqa-gru.service openqa-scheduler.service openqa-livehandler.service
-Documentation=https://open.qa/docs/#_run_the_web_ui
+Documentation=https://open.qa/docs/#run-the-web-ui
 
 [Service]
 User=geekotest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/systemd/[email protected] 
new/openQA-5.1777995277.b985bea2/systemd/[email protected]
--- old/openQA-5.1777888278.38a3a85c/systemd/[email protected]       
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/systemd/[email protected]       
2026-05-05 17:34:37.000000000 +0200
@@ -6,7 +6,7 @@
 Description=openQA Worker #%i
 After=openqa-slirpvde.service network.target nss-lookup.target 
remote-fs.target time-sync.target
 PartOf=openqa-worker.target
-Documentation=https://open.qa/docs/#_run_openqa_workers
+Documentation=https://open.qa/docs/#run-openqa-workers
 
 [Service]
 Type=simple
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/t/04-scheduler.t 
new/openQA-5.1777995277.b985bea2/t/04-scheduler.t
--- old/openQA-5.1777888278.38a3a85c/t/04-scheduler.t   2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/t/04-scheduler.t   2026-05-05 
17:34:37.000000000 +0200
@@ -487,8 +487,8 @@
         local $conf->{dynamic_job_limit_step} = 5;
         local $conf->{dynamic_job_limit_interval} = 0;
         $scheduler->dynamic_limit(OpenQA::Scheduler::DynamicLimit->new);
-        # load 0.5 < 8*0.7=5.6 => scale up from min=30 by step=5 => 35
-        is $scheduler->effective_job_limit, 35, 'dynamic limit: min+step 
returned on low load';
+        # load 0.5 < 8*0.3=2.4 => scale up from min=30 by step=5*2=10 => 40
+        is $scheduler->effective_job_limit, 40, 'dynamic limit: min+step*2 
returned on low load';
     };
 
     subtest 'dynamic limit enforced in scheduling: fewer jobs than 
max_running_jobs allocated' => sub {
@@ -513,8 +513,8 @@
         local $conf->{dynamic_job_limit_interval} = 0;
         $scheduler->dynamic_limit(OpenQA::Scheduler::DynamicLimit->new);
         my $res = $scheduler->schedule();
-        # effective_limit = min=2 + step=1 = 3; only 3 jobs allocated despite 
5 scheduled and 5 workers
-        is scalar @$res, 3, 'dynamic limit of 3 (min+step) respected in 
scheduling';
+        # effective_limit = min=2 + step=1*2 = 4; only 4 jobs allocated 
despite 5 scheduled and 5 workers
+        is scalar @$res, 4, 'dynamic limit of 4 (min+step*2) respected in 
scheduling';
 
         # Clean up only the jobs and workers created in this subtest
         $jobs->search({id => \@dyn_job_ids})->delete;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/t/14-grutasks-git.t 
new/openQA-5.1777995277.b985bea2/t/14-grutasks-git.t
--- old/openQA-5.1777888278.38a3a85c/t/14-grutasks-git.t        2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/t/14-grutasks-git.t        2026-05-05 
17:34:37.000000000 +0200
@@ -474,8 +474,8 @@
     $args{needle_ids} = [4];
     stderr_like { $res = run_gru_job(@gru_args) } qr{Git command failed: 
.*push}, 'Got error on stderr';
     is $res->{state}, 'finished', 'git job finished';
-    like $res->{result}->{errors}->[0]->{message},
-      qr{Unable to push Git commit. See .*_setting_up_git_support on how to 
setup}, 'Got error for push';
+    like $res->{result}->{errors}->[0]->{message}, qr{Unable to push Git 
commit.*See.*on how to setup},
+      'Got error for push';
 
     $openqa_git->redefine(
         run_cmd_with_log_return_error => sub ($cmd, %args) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/t/24-worker-jobs.t 
new/openQA-5.1777995277.b985bea2/t/24-worker-jobs.t
--- old/openQA-5.1777888278.38a3a85c/t/24-worker-jobs.t 2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/t/24-worker-jobs.t 2026-05-05 
17:34:37.000000000 +0200
@@ -1148,7 +1148,7 @@
 
 subtest 'Dynamic schedule' => sub {
     my $job_mock = Test::MockModule->new('OpenQA::Worker::Job');
-    my $orig = \&OpenQA::Worker::Job::_read_json_file;
+    my $orig = \&OpenQA::Worker::Job::_read_json_file;    ## no critic 
(Variables::ProtectPrivateVars)
     my $read_schedule = 0;
     $job_mock->redefine(
         _read_json_file => sub {
@@ -1228,7 +1228,7 @@
 };
 
 subtest 'image optimization' => sub {
-    my $opt = \&OpenQA::Worker::Job::_optimize_image;
+    my $opt = \&OpenQA::Worker::Job::_optimize_image;    ## no critic 
(Variables::ProtectPrivateVars)
     local $ENV{OPENQA_LOGFILE} = undef;
     combined_like {
         is $opt->('foo', {OPTIMIZE_IMAGES => 0}), 0, 'image optimization can 
be skipped';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/t/26-dynamic-job-limit.t 
new/openQA-5.1777995277.b985bea2/t/26-dynamic-job-limit.t
--- old/openQA-5.1777888278.38a3a85c/t/26-dynamic-job-limit.t   2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/t/26-dynamic-job-limit.t   2026-05-05 
17:34:37.000000000 +0200
@@ -53,15 +53,25 @@
 };
 
 sub _config (%args) {
-    return {
+    my %config = (
         max_running_jobs => $args{max} // 200,
         dynamic_job_limit_enabled => 1,
-        dynamic_job_limit_min => $args{min} // 50,
-        dynamic_job_limit_load_threshold => $args{threshold} // 8,
-        dynamic_job_limit_load_critical => $args{critical} // 16,
-        dynamic_job_limit_step => $args{step} // 10,
-        dynamic_job_limit_interval => $args{interval} // 0,
-    };
+    );
+    my %map = (
+        min => 'dynamic_job_limit_min',
+        threshold => 'dynamic_job_limit_load_threshold',
+        threshold_factor => 'dynamic_job_limit_load_threshold_factor',
+        critical => 'dynamic_job_limit_load_critical',
+        critical_factor => 'dynamic_job_limit_load_critical_factor',
+        step => 'dynamic_job_limit_step',
+        interval => 'dynamic_job_limit_interval',
+        hysteresis => 'dynamic_job_limit_scale_up_hysteresis',
+        fast_up_factor => 'dynamic_job_limit_fast_ramp_up_load_factor',
+    );
+    for my $k (keys %args) {
+        $config{$map{$k} // $k} = $args{$k} if defined $args{$k} && exists 
$map{$k};
+    }
+    return \%config;
 }
 
 sub test_dynamic_limit (%args) {
@@ -72,7 +82,7 @@
         my $dl = OpenQA::Scheduler::DynamicLimit->new;
         $dl->effective_limit($args{initial}) if defined $args{initial};
         $args{block} ? $dl->block_adjustment_for : $dl->force_next_adjustment;
-        my %conf = (min => 50, threshold => 8, step => 10, max => 200, 
%{$args{config} // {}});
+        my %conf = (threshold => 8, critical => 16, max => 200, 
%{$args{config} // {}});
         my $limit = $dl->current_limit(_config(%conf));
         is $limit, $args{expected}, $args{message} // "limit is 
$args{expected}";
     };
@@ -80,10 +90,17 @@
 
 my @cases = (
     {name => 'initial', block => 1, expected => 50, config => {interval => 
60}},
-    {name => 'scales up', initial => 100, load => '1.0 1.0 1.0', expected => 
110},
+    {name => 'scales up', initial => 100, load => '4.0 4.0 4.0', expected => 
110},
+    {name => 'fast up', initial => 100, load => '1.0 1.0 1.0', expected => 
120},
     {name => 'steady', initial => 100, load => '6.0 6.5 6.0', expected => 100},
     {name => 'scales down', initial => 100, load => '10.0 7.0 6.0', expected 
=> 90},
-    {name => 'emergency', initial => 100, load => '20.0 18.0 15.0', expected 
=> 70, config => {critical => 16}},
+    {
+        name => 'emergency',
+        initial => 100,
+        load => '20.0 18.0 15.0',
+        expected => 70,
+        config => {critical => 16}
+    },
     {name => 'floor', load => '20.0 18.0 15.0', initial => 55, expected => 50, 
config => {critical => 16}},
     {name => 'ceiling', load => '1.0 1.0 1.0', initial => 195, expected => 
200},
     {
@@ -94,22 +111,41 @@
         expected => 100,
         config => {interval => 60}
     },
-    {name => 'unlimited', initial => 100, load => '1.0 1.0 1.0', expected => 
110, config => {max => -1}},
+    {name => 'unlimited', initial => 100, load => '4.0 4.0 4.0', expected => 
110, config => {max => -1}},
 );
 
 test_dynamic_limit(%$_) for @cases;
 
 subtest 'auto-detects threshold from nproc when configured as 0' => sub {
     my $mock_dl = Test::MockModule->new('OpenQA::Scheduler::DynamicLimit');
-    $mock_dl->mock(_nproc => sub { 4 });    # 4 CPUs; threshold = 4*0.85 = 
3.4; load 1.0 < 3.4*0.7=2.38 => scale up
+    $mock_dl->mock(_nproc => sub { 4 });    # 4 CPUs; threshold = 4*0.85 = 
3.4; load 1.0 < 3.4*0.3=1.02 => fast up
     test_dynamic_limit(
         name => 'autothresh',
         initial => 100,
         load => '1.0 1.0 1.0',
-        expected => 110,
+        expected => 120,
         config => {threshold => 0});
 };
 
+subtest 'auto-detects threshold from nproc (1 CPU)' => sub {
+    my $mock_dl = Test::MockModule->new('OpenQA::Scheduler::DynamicLimit');
+    $mock_dl->mock(_nproc => sub { 1 });    # 1 CPU; threshold = 1*0.85 = 
0.85; critical = 1*1.5 = 1.5
+    test_dynamic_limit(
+        name => 'autothresh_1cpu_scale_up',
+        initial => 100,
+        load => '0.2 0.2 0.2',
+        # threshold = 0.85. 0.2 < 0.85*0.3 = 0.255. Fast up.
+        expected => 120,
+        config => {threshold => 0, critical => 0});
+    test_dynamic_limit(
+        name => 'autothresh_1cpu_emergency',
+        initial => 100,
+        load => '2.0 2.0 2.0',
+        # critical = 1.5. 2.0 > 1.5. Emergency.
+        expected => 70,
+        config => {threshold => 0, critical => 0});
+};
+
 subtest '_nproc returns positive number of CPUs' => sub {
     my $nproc = OpenQA::Scheduler::DynamicLimit::_nproc();
     cmp_ok $nproc, '>', 0, '_nproc returns a positive integer';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/t/35-script_clone_job.t 
new/openQA-5.1777995277.b985bea2/t/35-script_clone_job.t
--- old/openQA-5.1777888278.38a3a85c/t/35-script_clone_job.t    2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/t/35-script_clone_job.t    2026-05-05 
17:34:37.000000000 +0200
@@ -52,7 +52,7 @@
 );
 
 subtest 'running command' => sub {
-    my $run = \&OpenQA::Script::CloneJob::_run_cmd;
+    my $run = \&OpenQA::Script::CloneJob::_run_cmd;    ## no critic 
(Variables::ProtectPrivateVars)
     combined_like {
         like $run->('does-not-exist'), qr/Failed.*does-not-exist.*No such/i, 
'error if command does not exist'
     }
@@ -61,7 +61,7 @@
     is $run->('true'), '', 'no error if command succeeds';
 
     subtest 'get URL from command' => sub {
-        my $url_from_cmd = \&OpenQA::Script::CloneJob::_url_from_cmd;
+        my $url_from_cmd = \&OpenQA::Script::CloneJob::_url_from_cmd;    ## no 
critic (Variables::ProtectPrivateVars)
         my $res = $url_from_cmd->(echo => qw(-n http://foo/bar));
         is $res, 'http://foo/bar', 'got URL';
         is ref $res, 'Mojo::URL', 'URL returned as Mojo::URL ref';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1777888278.38a3a85c/t/api/10-jobgroups.t 
new/openQA-5.1777995277.b985bea2/t/api/10-jobgroups.t
--- old/openQA-5.1777888278.38a3a85c/t/api/10-jobgroups.t       2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/t/api/10-jobgroups.t       2026-05-05 
17:34:37.000000000 +0200
@@ -597,7 +597,7 @@
 };
 
 subtest 'helper for removing test suite defaults' => sub {
-    my $helper = 
\&OpenQA::Schema::Result::JobGroups::_remove_test_suite_defaults;
+    my $helper = 
\&OpenQA::Schema::Result::JobGroups::_remove_test_suite_defaults;    ## no 
critic (Variables::ProtectPrivateVars)
     my $group = {scenarios => {x86_64 => {product => [{foo => {machine => 
'64bit'}}]}}};
     my $test_suites = {x86_64 => {foo => 1}};
     my $scenarios = [];
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/t/lib/OpenQA/Test/Utils.pm 
new/openQA-5.1777995277.b985bea2/t/lib/OpenQA/Test/Utils.pm
--- old/openQA-5.1777888278.38a3a85c/t/lib/OpenQA/Test/Utils.pm 2026-05-04 
11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/t/lib/OpenQA/Test/Utils.pm 2026-05-05 
17:34:37.000000000 +0200
@@ -304,8 +304,8 @@
         if ($bogus) {
             monkey_patch 'OpenQA::WebSockets::Controller::Worker', ws => sub {
                 my $c = shift;
-                $c->on(json => 
\&OpenQA::WebSockets::Controller::Worker::_message);
-                $c->on(finish => 
\&OpenQA::WebSockets::Controller::Worker::_finish);
+                $c->on(json => 
\&OpenQA::WebSockets::Controller::Worker::_message);    ## no critic 
(Variables::ProtectPrivateVars)
+                $c->on(finish => 
\&OpenQA::WebSockets::Controller::Worker::_finish);    ## no critic 
(Variables::ProtectPrivateVars)
             };
         }
         local @ARGV = ('daemon');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/templates/webapi/admin/job_template/index.html.ep
 
new/openQA-5.1777995277.b985bea2/templates/webapi/admin/job_template/index.html.ep
--- 
old/openQA-5.1777888278.38a3a85c/templates/webapi/admin/job_template/index.html.ep
  2026-05-04 11:51:18.000000000 +0200
+++ 
new/openQA-5.1777995277.b985bea2/templates/webapi/admin/job_template/index.html.ep
  2026-05-05 17:34:37.000000000 +0200
@@ -71,7 +71,7 @@
         <p>
             A job template is a combination of machine, product and test suite 
settings. These combination are used
             to produce actual jobs within a certain job group. Check out
-            <a 
href="http://open.qa/docs/#_using_job_templates_to_automate_jobs_creation"; 
target="blank">the documentation</a>
+            <a 
href="https://open.qa/docs/#using-job-templates-to-automate-jobs-creation"; 
target="blank">the documentation</a>
             for more details.
         </p>
         % if (!$force_yaml_editor) {
@@ -182,7 +182,7 @@
             <div class="row">
                 <div class="col-sm-5 editor-yaml-guide" style="display: none">
                     <p class="buttons">
-                        <a 
href="http://open.qa/docs/#_job_group_editor_gh2111"; target="blank" class="btn 
btn-light">
+                        <a href="https://open.qa/docs/#job-group-editor-gh"; 
target="blank" class="btn btn-light">
                             <i class="fa-solid fa-book"></i><span>YAML editor 
documentation</span>
                         </a>
                     </p>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/templates/webapi/admin/mcp_help.html.ep 
new/openQA-5.1777995277.b985bea2/templates/webapi/admin/mcp_help.html.ep
--- old/openQA-5.1777888278.38a3a85c/templates/webapi/admin/mcp_help.html.ep    
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/templates/webapi/admin/mcp_help.html.ep    
2026-05-05 17:34:37.000000000 +0200
@@ -4,5 +4,5 @@
   %= include 'layouts/info'
   <p>
       To configure an MCP client to connect to openQA, check out the
-      <%= link_to 'documentation about MCP support' => 
url_for('https://open.qa/docs/#_mcp_support') %>.
+      <%= link_to 'documentation about MCP support' => 
url_for('https://open.qa/docs/#mcp-support') %>.
   </p>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/templates/webapi/comments/add_comment_form_groups.html.ep
 
new/openQA-5.1777995277.b985bea2/templates/webapi/comments/add_comment_form_groups.html.ep
--- 
old/openQA-5.1777888278.38a3a85c/templates/webapi/comments/add_comment_form_groups.html.ep
  2026-05-04 11:51:18.000000000 +0200
+++ 
new/openQA-5.1777995277.b985bea2/templates/webapi/comments/add_comment_form_groups.html.ep
  2026-05-05 17:34:37.000000000 +0200
@@ -58,7 +58,7 @@
           % }
           <br>
           %= include_branding 'commenting_tools';
-          %= help_popover 'Help for comments' => $help_text, 
'https://open.qa/docs/#_use_of_the_web_interface' => 'the documentation'
+          %= help_popover 'Help for comments' => $help_text, 
'https://open.qa/docs/#use-of-the-web-interface' => 'the documentation'
         </span>
     </div>
 </div>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/templates/webapi/main/index.html.ep 
new/openQA-5.1777995277.b985bea2/templates/webapi/main/index.html.ep
--- old/openQA-5.1777888278.38a3a85c/templates/webapi/main/index.html.ep        
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/templates/webapi/main/index.html.ep        
2026-05-05 17:34:37.000000000 +0200
@@ -68,14 +68,14 @@
                 <input value="1" name="show_tags" type="checkbox" 
id="filter-show-tags">
                 <label class="form-label" for="filter-show-tags">Show 
tags</label>
                 <%= help_popover('Help for <i>Show tags</i>' => '<p>Show tags 
from the corresponding group overview comments</p>',
-                    'https://open.qa/docs/#_build_tagging' => 'the 
documentation')
+                    'https://open.qa/docs/#build-tagging' => 'the 
documentation')
                 %>
                 <input value="1" name="only_tagged" type="checkbox" 
id="filter-only-tagged">
                 <label class="form-label" for="filter-only-tagged">Only 
tagged</label>
                 <%= help_popover('Help for <i>Only tagged</i>' => '
                     <p>Show only builds that have been tagged in the 
corresponding group overview comments</p>
                     <p>Implies <i>Show tags</i></p>',
-                    'https://open.qa/docs/#_build_tagging' => 'the 
documentation')
+                    'https://open.qa/docs/#build-tagging' => 'the 
documentation')
                 %>
                 <input value="1" name="fullscreen" type="checkbox" 
id="filter-fullscreen">
                 <label class="form-label" for="filter-fullscreen">Full 
screen</label>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/templates/webapi/test/create.html.ep 
new/openQA-5.1777995277.b985bea2/templates/webapi/test/create.html.ep
--- old/openQA-5.1777888278.38a3a85c/templates/webapi/test/create.html.ep       
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/templates/webapi/test/create.html.ep       
2026-05-05 17:34:37.000000000 +0200
@@ -49,7 +49,7 @@
     <div class="col-md-6">
       <label for="create-tests-casedir" class="form-label"><strong>Test 
repository (<code>CASEDIR</code>)</strong></label>
       <%= help_popover('Test repository' => '<p>Specifies the URL of the Git 
repository containing tests. May also be left blank or point to a local 
directory.</p>',
-        
'https://open.qa/docs/#_triggering_tests_based_on_an_any_remote_git_refspec_or_open_github_pull_request',
 'the documentation', 'left') %>
+        
'https://open.qa/docs/#triggering-tests-based-on-an-any-remote-git-refspec-or-open-github-pull-request',
 'the documentation', 'left') %>
       <input type="text" class="form-control" id="create-tests-casedir" 
value="<%= $preset->{casedir} // '' %>" name="CASEDIR">
     </div>
     <div class="col-md-6">
@@ -62,7 +62,7 @@
       <label for="create-tests-settings" class="form-label"><strong>Additional 
settings</strong></label>
       <%= help_popover('Test repository' => '<p>Specifies additional settings 
as newline-separated <code>KEY=value</code>-pairs that will be assigned to each 
job. ' .
         'Some settings also influence the job creation itself, e.g. 
<code>_OBSOLETE</code>.</p>',
-        
'https://open.qa/docs/#_spawning_multiple_jobs_based_on_templates_isos_post', 
'the documentation', 'left') %>
+        
'https://open.qa/docs/#spawning-multiple-jobs-based-on-templates---isos-post', 
'the documentation', 'left') %>
       <textarea class="form-control key-value-pairs" 
id="create-tests-settings" rows="15"></textarea>
     </div>
     <div class="col-md-6">
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/templates/webapi/test/infopanel.html.ep 
new/openQA-5.1777995277.b985bea2/templates/webapi/test/infopanel.html.ep
--- old/openQA-5.1777888278.38a3a85c/templates/webapi/test/infopanel.html.ep    
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/templates/webapi/test/infopanel.html.ep    
2026-05-05 17:34:37.000000000 +0200
@@ -130,7 +130,7 @@
                                 <span class="prio-value"><%= $job->priority 
%></span>
                             % }
                         % }
-                        &nbsp;<a href="https://open.qa/docs/#_job_groups_2"; 
target="_blank"><i class="fa-regular fa-circle-question" 
data-bs-toggle="tooltip" data-bs-title="Jobs with lower priority values are 
scheduled earlier (default: 50)"></i></a>
+                        &nbsp;<a href="https://open.qa/docs/#job-groups-1"; 
target="_blank"><i class="fa-regular fa-circle-question" 
data-bs-toggle="tooltip" data-bs-title="Jobs with lower priority values are 
scheduled earlier (default: 50)"></i></a>
                     </div>
                 % }
                 % if ($worker) {
@@ -187,7 +187,7 @@
                             </ul>
                             All rules are applied recursively. Advanced 
restarting options allow changing the behavior, e.g. excluding parents and 
$ok_results_explanation children. You can open the menu of advanced restarting 
options by clicking on the triangle icon
                             on the left side of the <em>$restart_text</em> 
button for jobs with dependencies.",
-                            
'https://open.qa/docs/#_handling_of_related_jobs_on_failure_cancellation_restart',
 'documentation', 'bottom', class => 'help_popover fa-solid fa-circle-question 
btn btn-secondary');
+                            
'https://open.qa/docs/#handling-of-related-jobs-on-failure--cancellation--restart',
 'documentation', 'bottom', class => 'help_popover fa-solid fa-circle-question 
btn btn-secondary');
                         %>
                       </div>
                     % }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1777888278.38a3a85c/templates/webapi/test/overview.html.ep 
new/openQA-5.1777995277.b985bea2/templates/webapi/test/overview.html.ep
--- old/openQA-5.1777888278.38a3a85c/templates/webapi/test/overview.html.ep     
2026-05-04 11:51:18.000000000 +0200
+++ new/openQA-5.1777995277.b985bea2/templates/webapi/test/overview.html.ep     
2026-05-05 17:34:37.000000000 +0200
@@ -94,7 +94,7 @@
                     <p>Additional tweaking of the query is possible by leaving
                     out query parameters completely or specifying them
                     multiple times equivalent to an logical "or" search.</p>',
-                    
'https://open.qa/docs/#_allow_group_overview_query_by_result_gh531' => 'the 
documentation')
+                    
'https://open.qa/docs/#allow-group-overview-query-by-result-gh' => 'the 
documentation')
                 %>
             <span>no filter present, click to toggle filter form</span>
         </div>

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.vfsijO/_old  2026-05-06 19:20:01.650350928 +0200
+++ /var/tmp/diff_new_pack.vfsijO/_new  2026-05-06 19:20:01.658351257 +0200
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1777888278.38a3a85c
-mtime: 1777888278
-commit: 38a3a85c92a8473b9eb1fe3472cea5faa9e06263
+version: 5.1777995277.b985bea2
+mtime: 1777995277
+commit: b985bea28944e9257ed84ebc4f95af73d2f34a52
 

Reply via email to