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-11 20:52:29 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openQA (Old) and /work/SRC/openSUSE:Factory/.openQA.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openQA" Wed Mar 11 20:52:29 2026 rev:821 rq:1338061 version:5.1773151075.654d76ed Changes: -------- --- /work/SRC/openSUSE:Factory/openQA/openQA.changes 2026-03-10 17:54:16.557933823 +0100 +++ /work/SRC/openSUSE:Factory/.openQA.new.8177/openQA.changes 2026-03-11 20:53:08.940577686 +0100 @@ -1,0 +2,25 @@ +Tue Mar 10 17:07:52 UTC 2026 - [email protected] + +- Update to version 5.1773151075.654d76ed: + * refactor: Write `renderComments()` in a more compact way + * fix: Restore spacing between bug and other icons after 9346b7165 + * ci(helm): replace internal retry with okurz/retry/ + * refactor: Use signature in callback to clarify input parameters + * style: Add three perlcritic rules + * style: Make .perlcriticrc a real file instead of a symlink + * chore(deps): Adjust bot commit message to conventional commits + * test: Add test for rendering `label:linked` with bug reference + * feat: Improve handling non-bugref URLs in `mark_job_linked` after 7f6790 + * test: Verify that only one label is added via `mark_job_linked` + * feat: Render labels with bug references as clickable links + * refactor: Improve coding style in `renderComments()` + * feat: Use bugref within label when creating 'Job mentioned in …' comment + * docs: document the priority throttling for scheduled jobs + * Dependency cron 2026-03-09 + * feat: Streamline "relates to default checkout" condition + * feat: Enable `git_auto_update` if `CASEDIR` and `NEEDLES_DIR` are set + * feat: Support `CASEDIR` lookup introduced in ef229dc also in Git tasks + * fix: Handle error when determining Git server host correctly + * feat: add privacy policy + +------------------------------------------------------------------- Old: ---- openQA-5.1773068319.a9347c1b.obscpio New: ---- openQA-5.1773151075.654d76ed.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openQA-client-test.spec ++++++ --- /var/tmp/diff_new_pack.EC3tyC/_old 2026-03-11 20:53:11.580686604 +0100 +++ /var/tmp/diff_new_pack.EC3tyC/_new 2026-03-11 20:53:11.584686769 +0100 @@ -18,7 +18,7 @@ %define short_name openQA-client Name: %{short_name}-test -Version: 5.1773068319.a9347c1b +Version: 5.1773151075.654d76ed Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA-devel-test.spec ++++++ --- /var/tmp/diff_new_pack.EC3tyC/_old 2026-03-11 20:53:11.612687924 +0100 +++ /var/tmp/diff_new_pack.EC3tyC/_new 2026-03-11 20:53:11.612687924 +0100 @@ -18,7 +18,7 @@ %define short_name openQA-devel Name: %{short_name}-test -Version: 5.1773068319.a9347c1b +Version: 5.1773151075.654d76ed Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA-test.spec ++++++ --- /var/tmp/diff_new_pack.EC3tyC/_old 2026-03-11 20:53:11.644689244 +0100 +++ /var/tmp/diff_new_pack.EC3tyC/_new 2026-03-11 20:53:11.644689244 +0100 @@ -18,7 +18,7 @@ %define short_name openQA Name: %{short_name}-test -Version: 5.1773068319.a9347c1b +Version: 5.1773151075.654d76ed Release: 0 Summary: Test package for openQA License: GPL-2.0-or-later ++++++ openQA-worker-test.spec ++++++ --- /var/tmp/diff_new_pack.EC3tyC/_old 2026-03-11 20:53:11.676690564 +0100 +++ /var/tmp/diff_new_pack.EC3tyC/_new 2026-03-11 20:53:11.684690894 +0100 @@ -18,7 +18,7 @@ %define short_name openQA-worker Name: %{short_name}-test -Version: 5.1773068319.a9347c1b +Version: 5.1773151075.654d76ed Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA.spec ++++++ --- /var/tmp/diff_new_pack.EC3tyC/_old 2026-03-11 20:53:11.752693700 +0100 +++ /var/tmp/diff_new_pack.EC3tyC/_new 2026-03-11 20:53:11.752693700 +0100 @@ -99,7 +99,7 @@ %define devel_requires %devel_no_selenium_requires chromedriver Name: openQA -Version: 5.1773068319.a9347c1b +Version: 5.1773151075.654d76ed Release: 0 Summary: The openQA web-frontend, scheduler and tools License: GPL-2.0-or-later ++++++ openQA-5.1773068319.a9347c1b.obscpio -> openQA-5.1773151075.654d76ed.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/.github/workflows/check-helm-chart.yml new/openQA-5.1773151075.654d76ed/.github/workflows/check-helm-chart.yml --- old/openQA-5.1773068319.a9347c1b/.github/workflows/check-helm-chart.yml 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/.github/workflows/check-helm-chart.yml 2026-03-10 14:57:55.000000000 +0100 @@ -43,6 +43,11 @@ with: python-version: 3.13 + - name: Install retry + run: | + curl -sSfL https://raw.githubusercontent.com/okurz/retry/main/retry -o /usr/local/bin/retry + chmod +x /usr/local/bin/retry + - name: Set up chart-testing uses: helm/chart-testing-action@v2 @@ -51,8 +56,8 @@ - name: Download images run: | - RETRY=3 SLEEP=15 tools/retry docker pull $REGISTRY_PATH/openqa_webui:latest - RETRY=3 SLEEP=15 tools/retry docker pull $REGISTRY_PATH/openqa_worker:latest + retry -r 3 -s 15 -e docker pull $REGISTRY_PATH/openqa_webui:latest + retry -r 3 -s 15 -e docker pull $REGISTRY_PATH/openqa_worker:latest - name: Load images into the Cluster run: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/.perlcriticrc new/openQA-5.1773151075.654d76ed/.perlcriticrc --- old/openQA-5.1773068319.a9347c1b/.perlcriticrc 2026-03-11 20:53:12.868739742 +0100 +++ new/openQA-5.1773151075.654d76ed/.perlcriticrc 2026-03-10 14:57:55.000000000 +0100 @@ -1 +1,49 @@ -symbolic link to external/os-autoinst-common/.perlcriticrc +theme = community + openqa +severity = 4 +include = strict ValuesAndExpressions::ProhibitInterpolationOfLiterals CodeLayout::ProhibitParensWithBuiltins BuiltinFunctions::RequireBlockMap BuiltinFunctions::ProhibitStringySplit + +verbose = ::warning file=%f,line=%l,col=%c,title=%m - severity %s::[%p] %e\n + +# == Perlcritic Policies +# -- Test::Most brings in strict & warnings +[TestingAndDebugging::RequireUseStrict] +equivalent_modules = Test::Most + +[TestingAndDebugging::RequireUseWarnings] +equivalent_modules = Test::Most + +# -- Avoid double quotes unless there's interpolation or a single quote. +[ValuesAndExpressions::ProhibitInterpolationOfLiterals] +allow_if_string_contains_single_quote = 1 +severity = 3 + +# -- Prohibit deep nesting +[ControlStructures::ProhibitDeepNests] +severity = 4 +add_themes = community +max_nests = 4 + +# == Community Policies +# -- Test::Most brings in strict & warnings +[Freenode::StrictWarnings] +extra_importers = Test::Most + +# -- Test::Most brings in strict & warnings +[Community::StrictWarnings] +extra_importers = Test::Most + +[Community::DiscouragedModules] +severity = 3 + +# Test modules have no package declaration +[Community::PackageMatchesFilename] +severity = 1 + +# == Custom Policies +# -- Useless quotes on hashes +[OpenQA::HashKeyQuotes] +severity = 5 + +# -- Superfluous use strict/warning. +[OpenQA::RedundantStrictWarning] +equivalent_modules = Test::Most diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/assets/javascripts/openqa.js new/openQA-5.1773151075.654d76ed/assets/javascripts/openqa.js --- old/openQA-5.1773068319.a9347c1b/assets/javascripts/openqa.js 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/assets/javascripts/openqa.js 2026-03-10 14:57:55.000000000 +0100 @@ -579,31 +579,22 @@ } function renderComments(row) { - const bugs = row.comment_data.bugs; - var html = ''; - bugs.forEach(function (bug) { - const css_class = bug.css_class; - const title = bug.title; - const url = bug.url; - html += '<span id="bug-' + row.id + '"> ' + '<a href="' + htmlEscape(url) + '">'; - html += '<i class="test-label ' + htmlEscape(css_class) + '" title="' + htmlEscape(title) + '"></i>'; + const commentData = row.comment_data; + let html = ''; + commentData.bugs.forEach(function (bug) { + html += ` <span id="bug-${row.id}"><a href="${htmlEscape(bug.url)}">`; + html += `<i class="test-label ${htmlEscape(bug.css_class)}" title="${htmlEscape(bug.title)}"></i>`; html += '</a></span>'; }); - - if (row.comment_data.label) { - const label = row.comment_data.label; - html += '<span id="test-label-' + row.id + '">'; - html += - ' <i class="test-label label_' + - htmlEscape(label) + - ' fa fa-bookmark" title="Label: ' + - htmlEscape(label) + - '"></i>'; - html += '</span>'; - } else if (row.comment_data.comments) { - html += '<span id="comment-' + row.id + '"> '; - html += row.comment_data.comment_icon; - html += '</span>'; + const label = commentData.label; + if (label) { + const labelUrl = commentData.label_url; + html += labelUrl ? ` <a href="${htmlEscape(labelUrl)}">` : ' '; + html += `<span id="test-label-${row.id}">`; + html += `<i class="test-label label_${htmlEscape(label)} fa fa-bookmark" title="Label: ${htmlEscape(label)}"></i>`; + html += labelUrl ? '</span></a>' : '</span>'; + } else if (commentData.comments) { + html += ` <span id="comment-${row.id}">${commentData.comment_icon}</span>`; } return html; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/cpanfile new/openQA-5.1773151075.654d76ed/cpanfile --- old/openQA-5.1773068319.a9347c1b/cpanfile 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/cpanfile 2026-03-10 14:57:55.000000000 +0100 @@ -117,7 +117,7 @@ requires 'Code::TidyAll'; requires 'Perl::Critic'; requires 'Perl::Critic::Community'; - requires 'Perl::Tidy', '== 20260109.0.0'; + requires 'Perl::Tidy', '== 20260204.0.0'; requires 'Test::CheckGitStatus'; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/dependencies.yaml new/openQA-5.1773151075.654d76ed/dependencies.yaml --- old/openQA-5.1773068319.a9347c1b/dependencies.yaml 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/dependencies.yaml 2026-03-10 14:57:55.000000000 +0100 @@ -84,7 +84,7 @@ sudo: tar: xorg-x11-fonts: - perl(Perl::Tidy): '== 20260109.0.0' + perl(Perl::Tidy): '== 20260204.0.0' perl(Test::CheckGitStatus): devel_requires: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/docs/Installing.asciidoc new/openQA-5.1773151075.654d76ed/docs/Installing.asciidoc --- old/openQA-5.1773068319.a9347c1b/docs/Installing.asciidoc 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/docs/Installing.asciidoc 2026-03-10 14:57:55.000000000 +0100 @@ -675,6 +675,50 @@ If you switch authentication method from Fake to any other, review your API keys! You may be vulnerable for up to a day until Fake API key expires. + +[[priority-throttling]] +=== Job Priority Throttling + +Priority throttling of openQA test jobs can be configured based on specific +parameter values found in the job settings. This mechanism is primarily designed +to encourage the use of efficient resources. + +The throttling system allows for the dynamic adjustment of job priorities based +on parameter values in settings, such as hardware resources or runtime limits. + +Throttling parameters are defined in `openqa.ini`, with the following syntax: +[source] +prio_throttling_parameters = parameter_n:scale_n[:reference_n][,…] + +where: + +* `parameter_n`: the name of a parameter +* `reference_n`: an optional threshold or reference, that can be zero, making +the scale negative or positive for values lower or higher than it. +* `scale_n`: the priority scale factor applied to the difference between the +parameter and its reference. This number is based on experience and custom needs. +When it is missing or zero, the throttling isn't applied for the parameter n. + +`MAX_JOB_TIME`, the max duration of the job in seconds, can also have a +throttling scale configured to encourage shorter test runtimes. When this +parameter is missing in the settings, a `DEFAULT_MAX_JOB_TIME` value is assumed +(refer to openQA code). A positive `TIMEOUT_SCALE`, 1 by default, may also be +defined to multiply the job time and the scale applies to the resulting product. +Its scale only applies to jobs having that value exceeding `DEFAULT_MAX_JOB_TIME`. + +When defining a custom `prio_throttling_parameters` configuration, +administrators must explicitly include the `MAX_JOB_TIME` rule, to retain +runtime-based throttling. + +The final priority of a job is the sum of a base priority, defined in the job +templates or scenario definitions, plus all adjustments calculated for the +configured parameters that match the job settings. + +**Example:** +[source] +prio_throttling_parameters = MAX_JOB_TIME:0.007,QEMURAM:0.005:2048 + + == Run the web UI To start openQA and enable it to run on each boot call diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/docs/PrivacyPolicy.asciidoc new/openQA-5.1773151075.654d76ed/docs/PrivacyPolicy.asciidoc --- old/openQA-5.1773068319.a9347c1b/docs/PrivacyPolicy.asciidoc 1970-01-01 01:00:00.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/docs/PrivacyPolicy.asciidoc 2026-03-10 14:57:55.000000000 +0100 @@ -0,0 +1,124 @@ += Privacy Policy +:toc: + +== Introduction + +openQA is an automated testing framework. This privacy policy describes how we +collect, use, and protect your personal information when you use an openQA +instance. + +This policy applies to users of openQA. Individual openQA instance operators +may have their own privacy practices. + +== Data We Collect + +=== Account Information + +When you sign in to an openQA instance for the first time via an external +authentication provider, an account is automatically created. We collect the +following information provided by that provider: + +* Username +* Email address (optional) +* Full name (optional) +* Nickname (optional) +* Role (operator, admin) + +=== Authentication Data + +* API keys and secrets (stored in hashed form) +* Session data (login time, user ID) + +=== Activity Data + +* Comments you post on jobs or test results +* Job settings and configurations you create +* Audit events recording your actions +* Developer session data when using the interactive debugging feature + +== How We Use Your Data + +Your data is used for: + +* Providing the openQA testing service +* Authenticating your session +* Managing your permissions and API access +* Recording test activities and results +* Maintaining security through audit logging +* No marketing or advertising purposes + +== Data Protection + +We implement appropriate technical and organizational measures: + +* API secrets are stored using secure hashing +* Access controls limit who can view your data +* Audit logs track changes to accounts and data +* When you delete your account, your personal data is anonymized while + preserving historical records (see User Rights) + +== Data Sharing + +We do not share your personal data with third parties except: + +* When required by law or legal process +* When necessary to protect our rights or safety +* Aggregated, anonymized data that cannot identify you + +We do not sell your personal data. + +== User Rights + +You have the following rights regarding your personal data: + +=== Access + +You can view your account information through the web interface or API. + +=== Correction + +Account details (username, email, fullname, nickname) are retrieved from your +external authentication provider. To update this information, please do so +through that provider. + +=== Deletion + +You can delete your account, which will: +* Remove your personal information (email, fullname, nickname) +* Anonymize your username (replaced with "deleted-user-[id]") +* Delete your API keys +* Clear your user reference from comments and audit events +* Preserve historical test data without identifying you + +To exercise these rights, use the account deletion feature in your user +settings or contact the instance administrator. + +=== Data Portability + +You can export your data through the openQA API. + +=== Contact + +For privacy inquiries, contact the administrator of your openQA instance. + +== Cookies and Tracking + +openQA uses session cookies for authentication. These cookies are necessary +for the service to function and are not used for tracking or advertising. + +No third-party analytics or tracking services are used. + +== Policy Changes + +This policy may be updated from time to time. The effective date is noted +below. Significant changes will be communicated through the openQA instance's +announcement channels. + +== Effective Date + +This policy was last updated: March 2026 + +== Contact Information + +For questions about this privacy policy or to exercise your data rights, +contact the openQA instance administrator. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/docs/index.asciidoc new/openQA-5.1773151075.654d76ed/docs/index.asciidoc --- old/openQA-5.1773068319.a9347c1b/docs/index.asciidoc 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/docs/index.asciidoc 2026-03-10 14:57:55.000000000 +0100 @@ -21,3 +21,4 @@ include::Contributing.asciidoc[] include::Branding.asciidoc[] include::ContainerizedSetup.asciidoc[] +include::PrivacyPolicy.asciidoc[] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Scheduler/Model/Jobs.pm new/openQA-5.1773151075.654d76ed/lib/OpenQA/Scheduler/Model/Jobs.pm --- old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Scheduler/Model/Jobs.pm 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/lib/OpenQA/Scheduler/Model/Jobs.pm 2026-03-10 14:57:55.000000000 +0100 @@ -204,8 +204,8 @@ } ($job_id => ($sort_criteria || $job_id)); } keys %$cluster_info; - my $sort_function = sub { - [sort { $sort_criteria{$a} cmp $sort_criteria{$b} } @{shift()}] + my $sort_function = sub ($job_ids) { + [sort { $sort_criteria{$a} cmp $sort_criteria{$b} } @$job_ids] }; my ($directly_chained_job_sequence, $job_ids); try { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Schema/ResultSet/Comments.pm new/openQA-5.1773151075.654d76ed/lib/OpenQA/Schema/ResultSet/Comments.pm --- old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Schema/ResultSet/Comments.pm 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/lib/OpenQA/Schema/ResultSet/Comments.pm 2026-03-10 14:57:55.000000000 +0100 @@ -6,7 +6,7 @@ use Mojo::Base 'DBIx::Class::ResultSet', -signatures; use DBIx::Class::Timestamps; use OpenQA::App; -use OpenQA::Utils qw(find_bugrefs href_to_bugref); +use OpenQA::Utils qw(find_bugrefs href_to_bugref url_from_label); use Feature::Compat::Try; =over 4 @@ -118,6 +118,7 @@ } elsif (my $label = $comment->label) { $res->{label} = $label; + $res->{label_url} = url_from_label($label); $res->{reviewed} = 1; } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Schema/ResultSet/Jobs.pm new/openQA-5.1773151075.654d76ed/lib/OpenQA/Schema/ResultSet/Jobs.pm --- old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Schema/ResultSet/Jobs.pm 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/lib/OpenQA/Schema/ResultSet/Jobs.pm 2026-03-10 14:57:55.000000000 +0100 @@ -16,7 +16,7 @@ use OpenQA::Log qw(log_trace log_debug log_info); use OpenQA::Schema::Result::Jobs; use OpenQA::Schema::Result::JobDependencies; -use OpenQA::Utils 'testcasedir'; +use OpenQA::Utils qw(testcasedir href_to_bugref); use Mojo::File 'path'; use Mojo::JSON 'encode_json'; use Mojo::URL; @@ -540,7 +540,9 @@ my $comments = $job->comments; return undef if $comments->search({text => {like => 'label:linked%'}}, {rows => 1})->first; my $user = $self->result_source->schema->resultset('Users')->system({select => ['id']}); - $comments->create_with_event({text => "label:linked Job mentioned in $referer_url", user_id => $user->id}); + my $bugref = href_to_bugref($referer_url); + my $label = $referer_url eq $bugref ? "label:linked $referer" : "label:linked:$bugref"; + $comments->create_with_event({text => "$label mentions this job", user_id => $user->id}); } 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Task/Git/Clone.pm new/openQA-5.1773151075.654d76ed/lib/OpenQA/Task/Git/Clone.pm --- old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Task/Git/Clone.pm 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/lib/OpenQA/Task/Git/Clone.pm 2026-03-10 14:57:55.000000000 +0100 @@ -54,8 +54,8 @@ my $git = OpenQA::Git->new(app => $app, dir => $path); my $origin_url = -d $path ? $git->get_origin_url : undef; - my $url = $origin_url // $clones->{$path}; - my $server_host = _extract_server_host($url); + my $server_host = _extract_server_host($origin_url // $clones->{$path}); + return $job->fail("Unable to determine Git server host of repo '$path'.") unless defined $server_host; my $error; try { _git_clone($git, $ctx, $path, $clones->{$path}, $origin_url); @@ -137,6 +137,7 @@ } sub _extract_server_host ($url) { + return undef unless $url; if ($url =~ m{^[^@]+@([^:]+):}) { # e.g. "[email protected]:qa/foo", "user@host:repo" return $1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Utils.pm new/openQA-5.1773151075.654d76ed/lib/OpenQA/Utils.pm --- old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Utils.pm 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/lib/OpenQA/Utils.pm 2026-03-10 14:57:55.000000000 +0100 @@ -97,6 +97,7 @@ needledir productdir testcasedir + effective_distri git_commit_url is_in_tests save_base64_png @@ -108,6 +109,7 @@ find_bugref find_bugrefs bugurl + url_from_label bugref_to_href href_to_bugref url_to_href @@ -214,6 +216,15 @@ return $dir; } +sub _relates_to_default_checkout ($dir_job_variable) { + return !looks_like_url_with_scheme($dir_job_variable) && !path($dir_job_variable)->is_abs; +} + +sub effective_distri ($job_settings) { + my $casedir = $job_settings->{CASEDIR}; + return defined $casedir && _relates_to_default_checkout($casedir) ? $casedir : $job_settings->{DISTRI}; +} + =head2 git_commit_url git_commit_url(distri => DISTRI, version => VERSION) @@ -425,11 +436,17 @@ # same page as https://github.com/os-autoinst/openQA/pull/966 and vice # versa for both an issue as well as pull request # for pagure.io it has to be "issue", not "issues" - $bugref =~ BUGREF_REGEX; + $bugref =~ BUGREF_REGEX or return $bugref; my $issuetext = $+{marker} eq 'pio' ? 'issue' : 'issues'; return $BUGREFS{$+{marker}} . ($+{repo} ? "$+{repo}/$issuetext/" : '') . $+{id}; } +sub url_from_label ($label) { + return undef unless $label =~ m/^linked:(?<ref>.*)/; + my $url = bugurl($+{ref}); + return $url =~ m/^https?:.*/ ? $url : undef; +} + sub bugref_to_href ($text) { my $regex = BUGREF_REGEX; $text =~ s{$regex}{<a href="@{[bugurl($+{match})]}">$+{match}</a>}gi; @@ -543,13 +560,20 @@ return \%downloads; } +sub _empty_or_relates_to_default_checkout ($dir_job_var) { + return !(defined $dir_job_var) || (length $dir_job_var == 0) || _relates_to_default_checkout($dir_job_var); +} + sub create_git_clone_list ($job_settings, $clones = {}) { return $clones unless my $distri = $job_settings->{DISTRI}; + return $clones unless my $effective_distri = effective_distri($job_settings); + my $testcasedir = testcasedir($effective_distri); + my $needledir = needledir($effective_distri, undef, undef, $distri); my $config = OpenQA::App->singleton->config->{'scm git'}; if ($config->{git_auto_update} eq 'yes') { - # Potential existing git clones to update without having CASEDIR or NEEDLES_DIR - not $job_settings->{CASEDIR} and $clones->{testcasedir($distri)} = undef; - not $job_settings->{NEEDLES_DIR} and $clones->{needledir($distri)} = undef; + # Update potentially existing default Git checkouts unless CASEDIR/NEEDLES_DIR point to a custom location + _empty_or_relates_to_default_checkout($job_settings->{CASEDIR}) and $clones->{$testcasedir} = undef; + _empty_or_relates_to_default_checkout($job_settings->{NEEDLES_DIR}) and $clones->{$needledir} = undef; } if ($config->{git_auto_clone} eq 'yes') { # Check CASEDIR and NEEDLES_DIR @@ -557,11 +581,11 @@ my $needles_url = Mojo::URL->new($job_settings->{NEEDLES_DIR} // ''); if ($case_url->scheme) { $case_url->fragment($job_settings->{TEST_GIT_REFSPEC}) if ($job_settings->{TEST_GIT_REFSPEC}); - $clones->{testcasedir($distri)} = $case_url; + $clones->{$testcasedir} = $case_url; } if ($needles_url->scheme) { $needles_url->fragment($job_settings->{NEEDLES_GIT_REFSPEC}) if ($job_settings->{NEEDLES_GIT_REFSPEC}); - $clones->{needledir($distri)} = $needles_url; + $clones->{$needledir} = $needles_url; } } return $clones; @@ -835,7 +859,7 @@ # workaround https://github.com/mojolicious/mojo/issues/1629 sub fix_top_level_help { @ARGV = () if ($ARGV[0] // '') =~ qr/^(-h|(--)?help)$/ } -sub looks_like_url_with_scheme { return !!Mojo::URL->new(shift)->scheme } +sub looks_like_url_with_scheme ($value) { !!Mojo::URL->new($value)->scheme } sub check_df ($dir) { my $df = Filesys::Df::df($dir, 1) // {}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/lib/OpenQA/WebAPI/Controller/Test.pm new/openQA-5.1773151075.654d76ed/lib/OpenQA/WebAPI/Controller/Test.pm --- old/openQA-5.1773068319.a9347c1b/lib/OpenQA/WebAPI/Controller/Test.pm 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/lib/OpenQA/WebAPI/Controller/Test.pm 2026-03-10 14:57:55.000000000 +0100 @@ -272,6 +272,7 @@ $data{comments} = $comment_data->{comments}; $data{reviewed} = $comment_data->{reviewed}; $data{label} = $comment_data->{label}; + $data{label_url} = $comment_data->{label_url}; $data{comment_icon} = $self->comment_icon($job_id, $data{comments}); my $bugs = $comment_data->{bugs}; $data{bugs} = [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Worker/Engines/isotovideo.pm new/openQA-5.1773151075.654d76ed/lib/OpenQA/Worker/Engines/isotovideo.pm --- old/openQA-5.1773068319.a9347c1b/lib/OpenQA/Worker/Engines/isotovideo.pm 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/lib/OpenQA/Worker/Engines/isotovideo.pm 2026-03-10 14:57:55.000000000 +0100 @@ -7,7 +7,7 @@ use OpenQA::JobSettings; use OpenQA::Log qw(log_error log_info log_debug log_warning get_channel_handle format_settings); use OpenQA::Utils - qw(asset_type_from_setting base_host locate_asset looks_like_url_with_scheme testcasedir productdir needledir); + qw(asset_type_from_setting base_host locate_asset looks_like_url_with_scheme effective_distri testcasedir productdir needledir); use POSIX qw(:sys_wait_h strftime uname _exit); use Mojo::JSON 'encode_json'; # booleans use Cpanel::JSON::XS (); @@ -391,8 +391,7 @@ # ensure a CASEDIR and a PRODUCTDIR is assigned and create a symlink if required my $absolute_paths = $vars->{ABSOLUTE_TEST_CONFIG_PATHS}; my $casedir = $vars->{CASEDIR}; - my $effective_distri = defined $casedir && !looks_like_url_with_scheme($casedir) ? $casedir : $vars->{DISTRI}; - my @vars_for_default_dirs = ($effective_distri, $vars->{VERSION}, $shared_cache); + my @vars_for_default_dirs = (effective_distri($vars), $vars->{VERSION}, $shared_cache); my $default_casedir = testcasedir(@vars_for_default_dirs); my $default_productdir = productdir(@vars_for_default_dirs, $vars->{DISTRI}); my $target_name = path($default_casedir)->basename; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/t/10-jobs.t new/openQA-5.1773151075.654d76ed/t/10-jobs.t --- old/openQA-5.1773068319.a9347c1b/t/10-jobs.t 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/t/10-jobs.t 2026-03-10 14:57:55.000000000 +0100 @@ -34,8 +34,7 @@ schema_name => $schema_name ); my $t = Test::Mojo->new('OpenQA::WebAPI'); -my $jobs = $t->app->schema->resultset('Jobs'); -my $users = $t->app->schema->resultset('Users'); +my ($jobs, $users, $comments) = map { $t->app->schema->resultset($_) } qw(Jobs Users Comments); # for "investigation" tests my $fake_git_log = 'deadbeef Break test foo'; @@ -1155,4 +1154,29 @@ is scalar @{$results->{details}}, 0, 'empty details returned if JSON file malformed' or always_explain $results; }; +subtest 'marking job as linked' => sub { + OpenQA::App->singleton->config->{global}->{recognized_referers} = ['progress.opensuse.org', 'foo.bar']; + my $job_id = 99937; + my $job = $jobs->find($job_id); + $jobs->mark_job_linked($job_id, 'https://progress.opensuse.org/issues/194990'); + my $expected = ['label:linked:poo#194990 mentions this job']; + is_deeply [map { $_->text } $job->comments], $expected, + 'bugref resolved (to be rendered as such in comment) and used in label (to be not treated like an actual bugref)'; + + my $comment_data = $comments->comment_data_for_jobs([$job]); + subtest 'label recognized' => sub { + my $data = $comment_data->{$job_id}; + is $data->{label}, 'linked:poo#194990', 'added label is recognized'; + is $data->{label_url}, 'https://progress.opensuse.org/issues/194990', 'URL is extracted again from label'; + } or always_explain $comment_data; + + $jobs->mark_job_linked($job_id, 'https://foo.bar/some/path'); + is_deeply [map { $_->text } $job->comments], $expected, 'no 2nd label added'; + + $job->comments->delete; + $jobs->mark_job_linked($job_id, 'https://foo.bar/some/path'); + $expected = ['label:linked https://foo.bar/some/path mentions this job']; + is_deeply [map { $_->text } $job->comments], $expected, 'linked label for non-bugref URL'; +}; + done_testing(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/t/14-grutasks-git.t new/openQA-5.1773151075.654d76ed/t/14-grutasks-git.t --- old/openQA-5.1773068319.a9347c1b/t/14-grutasks-git.t 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/t/14-grutasks-git.t 2026-03-10 14:57:55.000000000 +0100 @@ -163,6 +163,14 @@ is $mocked_git_calls[$i], $test->[1], "$i: " . $test->[0]; } + subtest 'git server host cannot be determined' => sub { + %$clone_dirs = ("$git_clones/nodefault" => undef); + stderr_like { $res = run_gru_job(@gru_args) } + qr(Unable to determine Git server host), 'error on stderr'; + is $res->{state}, 'failed', 'minion job failed'; + like $res->{result}, qr/Unable to determine Git server host/, 'error message'; + }; + subtest 'no default remote branch' => sub { $ENV{OPENQA_GIT_CLONE_RETRIES} = 0; %$clone_dirs = ("$git_clones/nodefault" => 'http://localhost/nodefault.git'); @@ -347,6 +355,14 @@ create_git_clone_list(\%job_settings, \%clones); my %expected_clones = map { ("t/data/openqa/share/tests/some-distri$_" => undef) } '', '/needles'; is_deeply \%clones, \%expected_clones, 'clones added for distri' or always_explain \%clones; + + subtest 'CASEDIR deviates from DISTRI' => sub { + %clones = (); + %job_settings = (CASEDIR => 'some-casedir', DISTRI => 'some-distri'); + create_git_clone_list(\%job_settings, \%clones); + my %expected_clones = map { ("t/data/openqa/share/tests/some-casedir$_" => undef) } '', '/needles'; + is_deeply \%clones, \%expected_clones, 'clones added for distri' or always_explain \%clones; + }; }; subtest 'enqueue_git_clones' => sub { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/t/ui/01-list.t new/openQA-5.1773151075.654d76ed/t/ui/01-list.t --- old/openQA-5.1773068319.a9347c1b/t/ui/01-list.t 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/t/ui/01-list.t 2026-03-10 14:57:55.000000000 +0100 @@ -109,6 +109,9 @@ # ensure chained jobs 99937 is still displayed on page one together with its chained dependency 99938 $jobs->search({id => 99937})->update({t_finished => time2str('%Y-%m-%d %H:%M:%S', time - 149 * ONE_HOUR, 'UTC')}); + # create linked label with bugref; supposed to be rendered as clickable label (and *not* as bugref) + $jobs->find({id => 80000})->comments->create({text => 'label:linked:poo#123', user_id => 1}); + assume_all_assets_exist; } @@ -133,6 +136,15 @@ $time->attribute_like('title', qr/.*Z/, 'finish time title of 99946'); $time->text_like(qr/about 3 hours ago/, 'finish time of 99946'); +subtest 'label:linked with bugref' => sub { + my $link = $driver->find_element('#job_80000 a[href="https://progress.opensuse.org/issues/123"]'); + my $label = $driver->find_element('#job_80000 .test-label'); + ok $link, 'rendered as link'; + ok $label, 'label present' or return; + is $label->get_attribute('title'), 'Label: linked:poo#123', 'title contains bugref'; + element_not_present '#job_80000 .fa-bolt', 'no bugref icon displayed (only the label)'; +}; + subtest 'running jobs, progress bars' => sub { is $driver->find_element('#job_99961 .progress-bar-striped')->get_text(), 'running', 'striped progress bar if not modules present yet'; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/templates/webapi/api_key/index.html.ep new/openQA-5.1773151075.654d76ed/templates/webapi/api_key/index.html.ep --- old/openQA-5.1773068319.a9347c1b/templates/webapi/api_key/index.html.ep 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/templates/webapi/api_key/index.html.ep 2026-03-10 14:57:55.000000000 +0100 @@ -53,6 +53,7 @@ <li>Anonymize audit log entries (your username will be replaced)</li> <li>Replace your username, email, and profile information with placeholder values</li> </ul> + <p>See our <a href="https://github.com/os-autoinst/openQA/blob/master/docs/PrivacyPolicy.asciidoc" target="_blank">Privacy Policy</a> for more information about how we handle your data.</p> <div class="alert alert-warning"> <strong>This action cannot be undone.</strong> </div> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/templates/webapi/layouts/bootstrap.html.ep new/openQA-5.1773151075.654d76ed/templates/webapi/layouts/bootstrap.html.ep --- old/openQA-5.1773068319.a9347c1b/templates/webapi/layouts/bootstrap.html.ep 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/templates/webapi/layouts/bootstrap.html.ep 2026-03-10 14:57:55.000000000 +0100 @@ -66,6 +66,7 @@ </span> </div> <div id='footer-legal' class="text-center"> + <a href='https://github.com/os-autoinst/openQA/blob/master/docs/PrivacyPolicy.asciidoc'>Privacy Policy</a> - openQA is licensed under %= link_to 'GPL-2.0' => 'https://github.com/os-autoinst/openQA' % if ($current_version) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/tools/ci/autoinst.sha new/openQA-5.1773151075.654d76ed/tools/ci/autoinst.sha --- old/openQA-5.1773068319.a9347c1b/tools/ci/autoinst.sha 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/tools/ci/autoinst.sha 2026-03-10 14:57:55.000000000 +0100 @@ -1 +1 @@ -01b8328736a8a278079a5893dcc2569b25af0c25 +f10b3febe79d5b706696b8e71c0ab0a2366a0015 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/tools/ci/ci-packages.txt new/openQA-5.1773151075.654d76ed/tools/ci/ci-packages.txt --- old/openQA-5.1773068319.a9347c1b/tools/ci/ci-packages.txt 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/tools/ci/ci-packages.txt 2026-03-10 14:57:55.000000000 +0100 @@ -188,7 +188,7 @@ perl-Perl-Critic-Policy-Plicease-ProhibitArrayAssignAref-100.0.0 perl-Perl-Critic-Policy-Variables-ProhibitLoopOnHash-0.008 perl-PerlIO-utf8_strict-0.010 -perl-Perl-Tidy-20260109.0.0 +perl-Perl-Tidy-20260204.0.0 perl-Pod-Parser-1.66 perl-Pod-POM-2.01 perl-Pod-Spell-1.26 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1773068319.a9347c1b/tools/ci/prepare_dependency_pr.sh new/openQA-5.1773151075.654d76ed/tools/ci/prepare_dependency_pr.sh --- old/openQA-5.1773068319.a9347c1b/tools/ci/prepare_dependency_pr.sh 2026-03-09 15:58:39.000000000 +0100 +++ new/openQA-5.1773151075.654d76ed/tools/ci/prepare_dependency_pr.sh 2026-03-10 14:57:55.000000000 +0100 @@ -7,6 +7,7 @@ git checkout -b dependency_"$depid" bash tools/ci/build_dependencies.sh +msg="chore(deps): Dependency cron $depid" git status git --no-pager diff tools/ci/ci-packages.txt git diff --quiet tools/ci/ci-packages.txt || ( @@ -17,7 +18,7 @@ git add tools/ci/ci-packages.txt tools/ci/autoinst.sha # these might have changed by tidy in tools/ci/build_dependencies.sh git add cpanfile dbicdh dependencies.yaml tools/* script/* lib/* t/* - git commit -m "Dependency cron $depid" + git commit -m "$msg" git push -q -f https://[email protected]/os-autoinst-bot/openQA.git dependency_"$depid" - hub pull-request -m "Dependency cron $depid" --base "$CIRCLE_PROJECT_USERNAME":"$CIRCLE_BRANCH" --head "os-autoinst-bot:dependency_$depid" + hub pull-request -m "$msg" --base "$CIRCLE_PROJECT_USERNAME":"$CIRCLE_BRANCH" --head "os-autoinst-bot:dependency_$depid" ) ++++++ openQA.obsinfo ++++++ --- /var/tmp/diff_new_pack.EC3tyC/_old 2026-03-11 20:53:24.765230531 +0100 +++ /var/tmp/diff_new_pack.EC3tyC/_new 2026-03-11 20:53:24.781231192 +0100 @@ -1,5 +1,5 @@ name: openQA -version: 5.1773068319.a9347c1b -mtime: 1773068319 -commit: a9347c1b5ff7779798e2286164f43c4ac7363945 +version: 5.1773151075.654d76ed +mtime: 1773151075 +commit: 654d76edc6b0fc7ca984379670c280d1943e7029
