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-10-28 17:50:23 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openQA (Old) and /work/SRC/openSUSE:Factory/.openQA.new.2252680 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openQA" Wed Oct 28 17:50:23 2026 rev:900 rq:1393418 version:5.1793118173.1c8a4cde Changes: -------- --- /work/SRC/openSUSE:Factory/openQA/openQA.changes 2026-10-27 16:48:36.874612698 +0100 +++ /work/SRC/openSUSE:Factory/.openQA.new.2252680/openQA.changes 2026-10-28 17:50:26.387845636 +0100 @@ -1,0 +2,25 @@ +Tue Oct 27 16:23:09 UTC 2026 - [email protected] + +- Update to version 5.1793118173.1c8a4cde: + * refactor(tests): Include `OpenQA::Task::Job::CreateZipArchive` properly + * test(archive-downloads): Remove redundant test + * refactor(archive-downloads): Use scope guard to close lock file + * refactor(archive-downloads): Remove redundant filesystem check + * refactor(archive-downloads): Remove unused default + * test(archive-downloads): Log result of Minion jobs for debugging + * refactor(tests): Use signatures in `t/60-archive-download.t` + * refactor(tests): Simplify cleanup in `t/60-archive-download.t` + * refactor(tests): Use sub tests in `t/60-archive-download.t` + * fix(archive-downloads): Fix warnings and 500 responses + * feat: Ignore bugrefs, labels, tags and flags in flag:verbatim comments + * test(worker-engine): Allow tests to pass if `OPENQA_CGROUP_SLICE` is set + * chore(deps): bump fast-uri from 3.1.7 to 3.1.9 + * ci(helm): pull test images directly inside KinD node via crictl + +------------------------------------------------------------------- +Mon Oct 26 20:27:29 UTC 2026 - [email protected] + +- Update to version 5.1793046431.4d768eeb: + * feat(investigation): Improve git log --stat filename output + +------------------------------------------------------------------- Old: ---- openQA-5.1793015014.afb80823.obscpio New: ---- openQA-5.1793118173.1c8a4cde.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openQA-client-test.spec ++++++ --- /var/tmp/diff_new_pack.t0fVum/_old 2026-10-28 17:50:28.939952451 +0100 +++ /var/tmp/diff_new_pack.t0fVum/_new 2026-10-28 17:50:28.940952493 +0100 @@ -18,7 +18,7 @@ %define short_name openQA-client Name: %{short_name}-test -Version: 5.1793015014.afb80823 +Version: 5.1793118173.1c8a4cde Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA-test.spec ++++++ --- /var/tmp/diff_new_pack.t0fVum/_old 2026-10-28 17:50:29.023955967 +0100 +++ /var/tmp/diff_new_pack.t0fVum/_new 2026-10-28 17:50:29.028956176 +0100 @@ -18,7 +18,7 @@ %define short_name openQA Name: %{short_name}-test -Version: 5.1793015014.afb80823 +Version: 5.1793118173.1c8a4cde Release: 0 Summary: Test package for openQA License: GPL-2.0-or-later ++++++ openQA-worker-test.spec ++++++ --- /var/tmp/diff_new_pack.t0fVum/_old 2026-10-28 17:50:29.128960362 +0100 +++ /var/tmp/diff_new_pack.t0fVum/_new 2026-10-28 17:50:29.129960404 +0100 @@ -18,7 +18,7 @@ %define short_name openQA-worker Name: %{short_name}-test -Version: 5.1793015014.afb80823 +Version: 5.1793118173.1c8a4cde Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA.spec ++++++ --- /var/tmp/diff_new_pack.t0fVum/_old 2026-10-28 17:50:29.220964213 +0100 +++ /var/tmp/diff_new_pack.t0fVum/_new 2026-10-28 17:50:29.222964296 +0100 @@ -104,7 +104,7 @@ %define devel_requires %devel_no_selenium_requires chromedriver Name: openQA -Version: 5.1793015014.afb80823 +Version: 5.1793118173.1c8a4cde Release: 0 Summary: Framework for automated system-level testing (web-frontend, scheduler and tools) Group: Development/Tools/Other ++++++ node_modules.obscpio ++++++ Binary files old/fast-uri-3.1.7.tgz and new/fast-uri-3.1.7.tgz differ Binary files old/fast-uri-3.1.9.tgz and new/fast-uri-3.1.9.tgz differ ++++++ node_modules.spec.inc ++++++ --- /var/tmp/diff_new_pack.t0fVum/_old 2026-10-28 17:50:31.693067679 +0100 +++ /var/tmp/diff_new_pack.t0fVum/_new 2026-10-28 17:50:31.704068140 +0100 @@ -120,7 +120,7 @@ Source1119: https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz#/fast-glob-3.3.3.tgz Source1120: https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#/fast-json-stable-stringify-2.1.0.tgz Source1121: https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#/fast-levenshtein-2.0.6.tgz -Source1122: https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz#/fast-uri-3.1.7.tgz +Source1122: https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.9.tgz#/fast-uri-3.1.9.tgz Source1123: https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#/fastest-levenshtein-1.0.16.tgz Source1124: https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz#/fastq-1.20.3.tgz Source1125: https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz#/file-entry-cache-11.1.5.tgz ++++++ openQA-5.1793015014.afb80823.obscpio -> openQA-5.1793118173.1c8a4cde.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/.github/workflows/check-helm-chart.yml new/openQA-5.1793118173.1c8a4cde/.github/workflows/check-helm-chart.yml --- old/openQA-5.1793015014.afb80823/.github/workflows/check-helm-chart.yml 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/.github/workflows/check-helm-chart.yml 2026-10-27 17:22:53.000000000 +0100 @@ -66,9 +66,8 @@ - name: Load images into the Cluster run: | - kind load docker-image --name chart-testing \ - $REGISTRY_PATH/openqa_webui:latest \ - $REGISTRY_PATH/openqa_worker:latest + docker exec chart-testing-control-plane crictl pull $REGISTRY_PATH/openqa_webui:latest + docker exec chart-testing-control-plane crictl pull $REGISTRY_PATH/openqa_worker:latest - name: Run chart-testing run: make test-helm-install diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/docs/UsersGuide.md new/openQA-5.1793118173.1c8a4cde/docs/UsersGuide.md --- old/openQA-5.1793015014.afb80823/docs/UsersGuide.md 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/docs/UsersGuide.md 2026-10-27 17:22:53.000000000 +0100 @@ -446,7 +446,7 @@ #### Flags -Currently there is only one flag for job comments supported. +The following flags are supported for job comments. ##### flag:carryover @@ -454,6 +454,15 @@ [carried over](UsersGuide.md#carry-over) to a new job failing for the same reason, without a bugref required. +##### flag:verbatim + +Adding `flag:verbatim` to a comment makes openQA ignore all bug references, +labels, tags and other flags in it: the comment does not mark the job as +reviewed, it is not carried over, it does not tag a build and `force_result` +labels in it are not applied. A `force_result` label in it still prevents +deleting the comment. Bug references are still rendered as links. This is +meant for comments posted by tools that quote text from logs. + ### Distinguish product and test issues bugref [gh#708](https://github.com/os-autoinst/openQA/pull/708) "progress.opensuse.org" is used to track test issues, bugzilla for product diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/lib/OpenQA/Archive.pm new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/Archive.pm --- old/openQA-5.1793015014.afb80823/lib/OpenQA/Archive.pm 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/Archive.pm 2026-10-27 17:22:53.000000000 +0100 @@ -6,6 +6,7 @@ use Archive::Zip qw(:ERROR_CODES :CONSTANTS); use Mojo::File 'path'; +use Mojo::Util qw(scope_guard); use OpenQA::Utils qw(resultdir assetdir check_df locate_asset human_readable_size random_hex); use OpenQA::Log qw(log_info log_error log_debug); use OpenQA::App; @@ -36,24 +37,21 @@ // 80; } -sub job_archive_filename ($job_id, $category = 'all') { +sub job_archive_filename ($job_id, $category) { return $category eq 'all' ? "job_$job_id.zip" : "job_${job_id}_$category.zip"; } sub create_job_archive ($job, $category = 'all') { my $job_id = $job->id; - my $cache_dir = path(archive_cache_dir()); - $cache_dir->make_path unless -d $cache_dir; + my $cache_dir = path(archive_cache_dir())->make_path; my $archive_name = job_archive_filename($job_id, $category); my $archive_path = $cache_dir->child($archive_name); my $lock_path = $cache_dir->child("$archive_name.lock"); open my $lock_fh, '>', $lock_path->to_string or die "Could not open lock file $lock_path: $!"; + my $lock_guard = scope_guard sub () { close $lock_fh }; flock $lock_fh, LOCK_EX or die "Could not lock $lock_path: $!"; - if (-e $archive_path) { - close $lock_fh; - return $archive_path; - } + return $archive_path if -e $archive_path; log_info "Creating archive for job $job_id (category: $category) at $archive_path"; # Archive::Zip does not keep all member data in memory. When using addFile or # addTree, it only remembers the filenames. writeToFileNamed then streams @@ -103,13 +101,11 @@ my $status = $zip->writeToFileNamed($temp_path->to_string); unless ($status == AZ_OK) { $temp_path->remove if -e $temp_path; - close $lock_fh; log_error "Failed to write archive for job $job_id to $temp_path: $status"; die "Failed to create archive: $status"; } rename $temp_path->to_string, $archive_path->to_string or die "Could not rename $temp_path to $archive_path: $!"; - close $lock_fh; return $archive_path; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/lib/OpenQA/Schema/Result/Comments.pm new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/Schema/Result/Comments.pm --- old/openQA-5.1793015014.afb80823/lib/OpenQA/Schema/Result/Comments.pm 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/Schema/Result/Comments.pm 2026-10-27 17:22:53.000000000 +0100 @@ -8,7 +8,7 @@ use OpenQA::Jobs::Constants; use OpenQA::Utils qw(find_labels find_flags find_bugref find_bugrefs); use OpenQA::Markdown qw(markdown_to_html); -use List::Util qw(first); +use List::Util qw(any); __PACKAGE__->load_components(qw(Core)); __PACKAGE__->load_components(qw(InflateColumn::DateTime Timestamps)); @@ -88,17 +88,36 @@ ); +=head2 is_verbatim + +Returns whether C<$self> contains C<flag:verbatim>. Bugrefs, labels, tags and other flags in such a comment are ignored. +=cut + +sub is_verbatim ($self) { + any { $_ eq 'verbatim' } @{$self->_parsed_flags}; +} + +# keyed on the text so an edited comment is parsed again +sub _parsed_flags ($self) { + my $text = $self->text; + my $cached = $self->{_parsed_flags}; + return $cached->[1] if $cached && $cached->[0] eq $text; + my $flags = find_flags($text); + $self->{_parsed_flags} = [$text, $flags]; + return $flags; +} + =head2 bugref Returns the first bugref if C<$self> contains a bugref, e.g. 'bug#1234'. =cut -sub bugref ($self) { find_bugref($self->text) } +sub bugref ($self) { $self->is_verbatim ? undef : find_bugref($self->text) } =head2 bugrefs Returns all bugrefs in C<$self>, e.g. 'bug#1234 poo#1234'. =cut -sub bugrefs ($self) { find_bugrefs($self->text) } +sub bugrefs ($self) { $self->is_verbatim ? [] : find_bugrefs($self->text) } =head2 label @@ -106,7 +125,7 @@ =cut sub label ($self) { - return find_labels($self->text)->[0]; + return $self->is_verbatim ? undef : find_labels($self->text)->[0]; } =head2 text_flags @@ -115,7 +134,7 @@ =cut sub text_flags ($self) { - my $flags = find_flags($self->text); + my $flags = $self->is_verbatim ? ['verbatim'] : $self->_parsed_flags; my %flag_hash; @flag_hash{@$flags} = (); return \%flag_hash; @@ -129,6 +148,7 @@ =cut sub force_result ($self) { + return (undef, undef) if $self->is_verbatim; for my $label (@{find_labels($self->text)}) { next unless $label =~ /^force_result:(\w+):?(\w*)/; return ($1, $2); @@ -147,6 +167,7 @@ =cut sub tag ($self) { + return () if $self->is_verbatim; $self->text =~ m{ \b tag : (?: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/lib/OpenQA/Schema/Result/Jobs.pm new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/Schema/Result/Jobs.pm --- old/openQA-5.1793015014.afb80823/lib/OpenQA/Schema/Result/Jobs.pm 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/Schema/Result/Jobs.pm 2026-10-27 17:22:53.000000000 +0100 @@ -1934,12 +1934,15 @@ return -e "$result_dir/autoinst-log.txt"; } -sub git_log_diff ($self, $dir, $refspec_range, $limit = undef) { +sub git_log_diff ($self, $dir, $refspec_range, %options) { return "Invalid range $refspec_range" if $refspec_range =~ m/UNKNOWN|unreadable git hash/; + my $limit = $options{limit}; + my $stat = $options{stat} // '300,200'; my $res = run_cmd_with_log_return_error( [ - 'git', '-C', $dir, 'log', ($limit ? "-$limit" : ()), - '--stat', '--pretty=oneline', '--abbrev-commit', '--no-merges', $refspec_range + 'git', '-C', $dir, 'log', + ($limit ? "-$limit" : ()), "--stat=$stat", '--pretty=oneline', '--abbrev-commit', + '--no-merges', $refspec_range ], stdout => 'trace' ); @@ -2016,7 +2019,7 @@ my $casedir = testcasedir($effective_distri, $self->VERSION); my $refspec_range = "$prev_vars->{TEST_GIT_HASH}..$self_vars->{TEST_GIT_HASH}"; my $diff_limit = $args{git_limit} ? $args{git_limit} / 2 : undef; - $inv{test_log} = $self->git_log_diff($casedir, $refspec_range, $args{git_limit}); + $inv{test_log} = $self->git_log_diff($casedir, $refspec_range, limit => $args{git_limit}); $inv{test_log} ||= 'No test changes recorded, test regression unlikely'; $inv{test_diff_stat} = $self->git_diff($casedir, $refspec_range, $diff_limit) if $inv{test_log}; # no need for duplicating needles git log if the git repo is the same @@ -2024,7 +2027,7 @@ if ($self_vars->{TEST_GIT_HASH} ne $self_vars->{NEEDLES_GIT_HASH}) { my $needles_dir = needledir($effective_distri, $self->VERSION); my $refspec_needles_range = "$prev_vars->{NEEDLES_GIT_HASH}..$self_vars->{NEEDLES_GIT_HASH}"; - $inv{needles_log} = $self->git_log_diff($needles_dir, $refspec_needles_range, $args{git_limit}); + $inv{needles_log} = $self->git_log_diff($needles_dir, $refspec_needles_range, limit => $args{git_limit}); $inv{needles_log} ||= 'No needle changes recorded, test regression due to needles unlikely'; $inv{needles_diff_stat} = $self->git_diff($needles_dir, $refspec_needles_range, $diff_limit) if $inv{needles_log}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/lib/OpenQA/Schema/ResultSet/Comments.pm new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/Schema/ResultSet/Comments.pm --- old/openQA-5.1793015014.afb80823/lib/OpenQA/Schema/ResultSet/Comments.pm 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/Schema/ResultSet/Comments.pm 2026-10-27 17:22:53.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 url_from_label); +use OpenQA::Utils qw(href_to_bugref url_from_label); use Feature::Compat::Try; =over 4 @@ -78,7 +78,7 @@ sub referenced_bugs ($self) { my $comments = $self->search({-not => {job_id => undef}}); - my %bugrefs = map { $_ => 1 } map { @{find_bugrefs($_->text)} } $comments->all; + my %bugrefs = map { $_ => 1 } map { @{$_->bugrefs} } $comments->all; return \%bugrefs; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/lib/OpenQA/WebAPI/Controller/API/V1/Comment.pm new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/WebAPI/Controller/API/V1/Comment.pm --- old/openQA-5.1793015014.afb80823/lib/OpenQA/WebAPI/Controller/API/V1/Comment.pm 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/WebAPI/Controller/API/V1/Comment.pm 2026-10-27 17:22:53.000000000 +0100 @@ -269,7 +269,7 @@ return $self->render( json => {error => "Comment $comment_id has 'force_result' label, deleting not allowed"}, status => 403 - ) if grep { defined } $comment->force_result; + ) if grep { /^force_result:/ } @{find_labels($comment->text)}; return $self->render(json => {error => 'Forbidden (must be author or admin)'}, status => 403) unless ($self->current_user->is_admin || $comment->user_id == $self->current_user->id); $self->emit_event('openqa_comment_delete', {id => $comment_id}); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/lib/OpenQA/WebAPI/Controller/File.pm new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/WebAPI/Controller/File.pm --- old/openQA-5.1793015014.afb80823/lib/OpenQA/WebAPI/Controller/File.pm 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/lib/OpenQA/WebAPI/Controller/File.pm 2026-10-27 17:22:53.000000000 +0100 @@ -168,22 +168,9 @@ my $cache_dir = path(OpenQA::Archive::archive_cache_dir()); my $archive_path = $cache_dir->child($archive_name); return $self->_redirect_to_archive($archive_path) if -e $archive_path; - try { - if (my $minion = $self->app->can('minion') ? $self->app->minion : undef) { - $self->app->log->info("Enqueuing create_zip_archive for job $job_id (category: $category)"); - $minion->enqueue( - create_zip_archive => [$job_id, $category], - {notes => {job_id => $job_id, category => $category}, priority => -10, expire => 3600}); - } - else { - # Fallback for environments without a fully-functional Minion (e.g. tests) - return $self->_redirect_to_archive(OpenQA::Archive::create_job_archive($job, $category)); - } - } - catch ($e) { - $self->app->log->error("Archive creation failed: $e"); - return $self->render(text => 'Internal Server Error', status => 500); - } + $self->app->log->info("Enqueuing create_zip_archive for job $job_id (category: $category)"); + my %options = (notes => {job_id => $job_id, category => $category}, priority => -10, expire => 3600); + $self->app->minion->enqueue(create_zip_archive => [$job_id, $category], \%options); $self->render('test/archive_wait', job => $job); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/package-lock.json new/openQA-5.1793118173.1c8a4cde/package-lock.json --- old/openQA-5.1793015014.afb80823/package-lock.json 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/package-lock.json 2026-10-27 17:22:53.000000000 +0100 @@ -1692,9 +1692,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz", - "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.9.tgz", + "integrity": "sha512-hS/0Wt3Ya043oKXs0sIxrMpKQITXhMLIrVAKKXi4gozGC9v7YRWVnXIZzjNPTO02M9BdxLCWqK1yRXgNziVyJQ==", "dev": true, "funding": [ { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/t/10-jobs.t new/openQA-5.1793118173.1c8a4cde/t/10-jobs.t --- old/openQA-5.1793015014.afb80823/t/10-jobs.t 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/t/10-jobs.t 2026-10-27 17:22:53.000000000 +0100 @@ -448,8 +448,8 @@ my $got_limit = 0; my $got_diff_limit = 0; $job_mock->redefine( - git_log_diff => sub ($self, $dir, $range, $limit) { - $got_limit = $limit; + git_log_diff => sub ($self, $dir, $range, %options) { + $got_limit = $options{limit}; return $fake_git_log; }); $job_mock->redefine( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/t/16-utils-runcmd.t new/openQA-5.1793118173.1c8a4cde/t/16-utils-runcmd.t --- old/openQA-5.1793015014.afb80823/t/16-utils-runcmd.t 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/t/16-utils-runcmd.t 2026-10-27 17:22:53.000000000 +0100 @@ -98,8 +98,10 @@ }; subtest 'error handling when checking whether working directory is clean' => sub { - my $test_file = $empty_tmp_dir->child('foo')->touch; - combined_like { $git->commit({add => ['foo'], message => 'test'}) } qr/commit.*foo.*cmd returned 0/is, + my $testfile = 'testfile.txt'; + my $msg = 'commit msg'; + my $test_file = $empty_tmp_dir->child($testfile)->touch; + combined_like { $git->commit({add => [$testfile], message => $msg}) } qr/commit.*testfile.*cmd returned 0/is, 'commit created'; stdout_like { ok $git->is_workdir_clean, 'return code 0 interpreted correctly' } qr/\[info\].*cmd returned 0\n/i, 'no error (only info) logged if check returns true'; @@ -110,16 +112,21 @@ }; subtest 'log diff computation helper of job' => sub { - like OpenQA::Schema::Result::Jobs::git_log_diff(undef, $empty_tmp_dir, 'HEAD'), qr/test.*foo/s, + my $msg = 'commit msg'; + like OpenQA::Schema::Result::Jobs::git_log_diff(undef, $empty_tmp_dir, 'HEAD'), qr/$msg.*testfile/s, + 'commit and file mentioned'; + like OpenQA::Schema::Result::Jobs::git_log_diff(undef, $empty_tmp_dir, 'HEAD', stat => '15,10'), + qr/$msg.*\.\.\.ile.txt/s, 'commit and file mentioned'; }; subtest 'cache_ref' => sub { - my $test_file = $empty_tmp_dir->child('foo')->touch; + my $testfile = 'testfile.txt'; + my $test_file = $empty_tmp_dir->child($testfile)->touch; my $test_file_2 = "$empty_tmp_dir/bar"; - is $git->cache_ref('HEAD', undef, 'foo', $test_file), + is $git->cache_ref('HEAD', undef, $testfile, $test_file), undef, 'return undef if output file already exists and could be touched'; - is $git->cache_ref('HEAD', undef, 'foo', $test_file_2), undef, 'checkout file with ref'; + is $git->cache_ref('HEAD', undef, $testfile, $test_file_2), undef, 'checkout file with ref'; ok -f $test_file_2, 'checkout succeeded'; # and now with remote other than origin @@ -131,7 +138,7 @@ my $test_file_3 = "$empty_tmp_dir/baz"; my $ref = qx{git -C "$git_remote_dir" rev-parse HEAD}; chomp $ref; - is $git->cache_ref($ref, "file://$git_remote_dir/.git", 'foo', $test_file_3), + is $git->cache_ref($ref, "file://$git_remote_dir/.git", $testfile, $test_file_3), undef, 'checkout file from remote origin with ref'; ok -f $test_file_3, 'checkout succeeded'; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/t/17-labels_carry_over.t new/openQA-5.1793118173.1c8a4cde/t/17-labels_carry_over.t --- old/openQA-5.1793015014.afb80823/t/17-labels_carry_over.t 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/t/17-labels_carry_over.t 2026-10-27 17:22:53.000000000 +0100 @@ -149,6 +149,18 @@ # Reset to a clean state $schema->txn_rollback; +$schema->txn_begin; + +subtest 'failed->failed flag:verbatim comments are not carried over' => sub { + my $comment_text = 'flag:verbatim quoting bsc#1234 flag:carryover label:force_result:softfailed:bsc#1257825'; + $t->post_ok("/api/v1/jobs/$old_job/comments", $auth => form => {text => $comment_text})->status_is(200); + $t->post_ok("/api/v1/jobs/$job/set_done", $auth => form => {result => FAILED})->status_is(200); + is scalar @{comments("/tests/$job")}, 0, 'comment with flag:verbatim not carried over'; + is $jobs->find($job)->result, FAILED, 'force_result label from a verbatim comment is not applied'; +}; + +# Reset to a clean state +$schema->txn_rollback; my ($prev_job, $curr_job) = map { $jobs->find($_) } (99962, 99963); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/t/22-dashboard.t new/openQA-5.1793118173.1c8a4cde/t/22-dashboard.t --- old/openQA-5.1793015014.afb80823/t/22-dashboard.t 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/t/22-dashboard.t 2026-10-27 17:22:53.000000000 +0100 @@ -283,6 +283,12 @@ @h4 = $t->tx->res->dom->find('div.children-collapsed .h4 a')->map('text')->each; is_deeply \@h4, [], 'also no tagged builds on parent-level shown'; +# tags in a comment with flag:verbatim are ignored +$tag_for_0092_comment->update({text => 'flag:verbatim quoting tag:0092:important:some_tag', user_id => 99901}); +$t->get_ok('/dashboard_build_results?limit_builds=20&only_tagged=1')->status_is(200); +@h4 = $t->tx->res->dom->find('div.children-collapsed .h4 a')->map('text')->each; +is_deeply \@h4, [], 'no tagged builds shown for a verbatim comment'; + # now tag build 0091 to check build tagging when there are common builds $tag_for_0092_comment->delete(); my $tag_for_0091_comment diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/t/24-worker-engine.t new/openQA-5.1793118173.1c8a4cde/t/24-worker-engine.t --- old/openQA-5.1793015014.afb80823/t/24-worker-engine.t 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/t/24-worker-engine.t 2026-10-27 17:22:53.000000000 +0100 @@ -10,8 +10,7 @@ BEGIN { $ENV{OPENQA_CACHE_SERVICE_POLL_DELAY} = 0; - delete $ENV{OPENQA_CACHE_MAX_INACTIVE_JOBS}; - delete $ENV{OPENQA_CACHE_MAX_INACTIVE_JOBS_HARD_LIMIT}; + delete @ENV{qw(OPENQA_CACHE_MAX_INACTIVE_JOBS OPENQA_CACHE_MAX_INACTIVE_JOBS_HARD_LIMIT OPENQA_CGROUP_SLICE)}; } use File::Spec::Functions qw(abs2rel catdir); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/t/60-archive-download.t new/openQA-5.1793118173.1c8a4cde/t/60-archive-download.t --- old/openQA-5.1793015014.afb80823/t/60-archive-download.t 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/t/60-archive-download.t 2026-10-27 17:22:53.000000000 +0100 @@ -17,6 +17,8 @@ use OpenQA::App; use OpenQA::WebAPI; use OpenQA::Utils qw(resultdir assetdir); +use OpenQA::Task::Job::CreateZipArchive; +use OpenQA::Test::Utils qw(perform_minion_jobs); use OpenQA::Archive; use Archive::Zip qw(:ERROR_CODES :CONSTANTS); @@ -84,7 +86,10 @@ my $url = '/tests/' . $job->id . '/archive' . ($cat eq 'all' ? '' : "?category=$cat"); my $suffix = $cat eq 'all' ? '' : "_$cat"; - $t->get_ok($url)->status_is(302)->header_like('Location' => qr|/archives/job_@{[ $job->id ]}${suffix}\.zip|); + $t->get_ok($url)->status_is(200)->text_like('p.lead', qr/Please wait while the ZIP/, "waiting for $url"); + perform_minion_jobs($app->minion); + $t->get_ok($url)->status_is(302); + $t->header_like('Location' => qr|/archives/job_@{[ $job->id ]}${suffix}\.zip|, "redirect for $url"); $t->get_ok($t->tx->res->headers->location)->status_is(200)->content_type_is('application/zip'); my $zip = Archive::Zip->new(); @@ -254,7 +259,6 @@ }; subtest 'CreateZipArchive Minion task' => sub { - require OpenQA::Task::Job::CreateZipArchive; my $mock_minion_job = Test::MockObject->new->set_always(app => $app)->set_true('finish')->set_true('fail'); my $mock_schema_obj = Test::MockObject->new; my $mock_rs = Test::MockObject->new; @@ -281,123 +285,26 @@ my $mock_minion = Test::MockModule->new('Minion'); my @guard_calls; $mock_minion->mock( - guard => sub { - my ($self, $name, $duration, $options) = @_; + guard => sub ($self, $name, $duration, $options) { push @guard_calls, {name => $name, duration => $duration, options => $options}; return 'mock_guard'; }); - my $orig_limit = $app->config->{misc_limits}->{create_zip_archive_limit}; - # default limit (2) - delete $app->config->{misc_limits}->{create_zip_archive_limit}; - $mock_archive_module->mock(create_job_archive => sub { path('/tmp/dummy.zip') }); - @guard_calls = (); - OpenQA::Task::Job::CreateZipArchive::_create_zip_archive($mock_minion_job, 4567); - is_deeply \@guard_calls, [{name => 'create_zip_archive_task', duration => 86400, options => {limit => 2}}], - 'called guard with default limit'; - - # custom configured limit (5) - $app->config->{misc_limits}->{create_zip_archive_limit} = 5; - @guard_calls = (); - OpenQA::Task::Job::CreateZipArchive::_create_zip_archive($mock_minion_job, 4567); - is_deeply \@guard_calls, [{name => 'create_zip_archive_task', duration => 86400, options => {limit => 5}}], - 'called guard with custom configured limit'; - - $app->config->{misc_limits}->{create_zip_archive_limit} = $orig_limit; - $mock_minion->unmock_all; -}; - -subtest 'Controller archive endpoint' => sub { - my $job = $schema->resultset('Jobs')->create( - { - DISTRI => 'archtest', - VERSION => '1.0', - FLAVOR => 'test', - ARCH => 'x86_64', - TEST => 'job_fail', - state => 'done', - result => 'passed', - }); - $t->get_ok('/archives/..%2fetc%2fpasswd')->status_is(404); - $t->get_ok('/archives/nonexistent.zip')->status_is(404); - - my $mock_minion = Test::MockObject->new->set_true('enqueue'); - my $mock_app_module = Test::MockModule->new('OpenQA::WebAPI'); - $mock_app_module->mock(minion => sub { $mock_minion }); - my $orig_can = $app->can('can'); - $mock_app_module->mock( - can => sub ($self, $method) { - return 1 if $method eq 'minion'; - return $orig_can ? $self->$orig_can($method) : UNIVERSAL::can($self, $method); ## no critic (ProhibitUniversalCan) - }); - $mock_minion->set_true('enqueue'); - - $case->login($t, 'admin'); - $t->get_ok('/tests/' . $job->id . '/archive')->status_is(200)->content_like(qr/Preparing Archive for Job/); - $mock_minion->called_ok('enqueue', 'Archive generation is enqueued in Minion'); - $mock_minion->clear; - $t->get_ok('/tests/' . $job->id . '/archive')->status_is(200); - $mock_minion->called_ok('enqueue', 'Repeated archive request re-enqueues generation task'); - - $mock_minion->mock(enqueue => sub { die 'Enqueue failed' }); - $t->get_ok('/tests/' . $job->id . '/archive')->status_is(500)->content_is('Internal Server Error'); -}; - -subtest 'Category specific archives' => sub { - my $job = $schema->resultset('Jobs')->create( - { - DISTRI => 'archtest', - VERSION => '1.0', - FLAVOR => 'test', - ARCH => 'x86_64', - TEST => 'category_test', - state => 'done', - result => 'passed', - }); - my $res_dir = path($job->create_result_dir); - $res_dir->child('vars.json')->spew('{}'); # COMMON_RESULT_FILES includes vars.json - $res_dir->child('ulogs')->make_path->child('ulog.txt')->spew('ulog data'); - my $asset = $schema->resultset('Assets')->create({type => 'iso', name => 'asset.iso'}); - $schema->resultset('JobsAssets')->create({job_id => $job->id, asset_id => $asset->id}); - path(assetdir(), 'iso', 'asset.iso')->dirname->make_path->child('asset.iso')->spew('asset data'); - - $case->login($t, 'admin'); - - # Test resultfiles category - $t->get_ok('/tests/' . $job->id . '/archive?category=resultfiles')->status_is(302) - ->header_like('Location' => qr|/archives/job_\d+_resultfiles.zip|); - $t->get_ok($t->tx->res->headers->location)->status_is(200); - my $zip_file = $tmp->child('resultfiles.zip'); - $zip_file->spew($t->tx->res->body); - my $zip = Archive::Zip->new(); - is $zip->read($zip_file->to_string), AZ_OK, 'Resultfiles zip is valid'; - ok $zip->memberNamed('testresults/vars.json'), 'Contains result file'; - ok !$zip->memberNamed('testresults/ulogs/ulog.txt'), 'Does not contain ulog'; - ok !$zip->memberNamed('iso/asset.iso'), 'Does not contain asset'; - - # Test ulogs category - $t->get_ok('/tests/' . $job->id . '/archive?category=ulogs')->status_is(302) - ->header_like('Location' => qr|/archives/job_\d+_ulogs.zip|); - $t->get_ok($t->tx->res->headers->location)->status_is(200); - $zip_file = $tmp->child('ulogs.zip'); - $zip_file->spew($t->tx->res->body); - $zip = Archive::Zip->new(); - is $zip->read($zip_file->to_string), AZ_OK, 'Ulogs zip is valid'; - ok !$zip->memberNamed('testresults/vars.json'), 'Does not contain result file'; - ok $zip->memberNamed('testresults/ulogs/ulog.txt'), 'Contains ulog'; - ok !$zip->memberNamed('iso/asset.iso'), 'Does not contain asset'; - - # Test assets category - $t->get_ok('/tests/' . $job->id . '/archive?category=assets')->status_is(302) - ->header_like('Location' => qr|/archives/job_\d+_assets.zip|); - $t->get_ok($t->tx->res->headers->location)->status_is(200); - $zip_file = $tmp->child('assets.zip'); - $zip_file->spew($t->tx->res->body); - $zip = Archive::Zip->new(); - is $zip->read($zip_file->to_string), AZ_OK, 'Assets zip is valid'; - ok !$zip->memberNamed('testresults/vars.json'), 'Does not contain result file'; - ok !$zip->memberNamed('testresults/ulogs/ulog.txt'), 'Does not contain ulog'; - ok $zip->memberNamed('iso/asset.iso'), 'Contains asset'; + subtest 'default limit (2)' => sub { + delete local $app->config->{misc_limits}->{create_zip_archive_limit}; + $mock_archive_module->mock(create_job_archive => sub { path('/tmp/dummy.zip') }); + @guard_calls = (); + OpenQA::Task::Job::CreateZipArchive::_create_zip_archive($mock_minion_job, 4567); + is_deeply \@guard_calls, [{name => 'create_zip_archive_task', duration => 86400, options => {limit => 2}}], + 'called guard with default limit'; + }; + subtest 'custom configured limit (5)' => sub { + local $app->config->{misc_limits}->{create_zip_archive_limit} = 5; + @guard_calls = (); + OpenQA::Task::Job::CreateZipArchive::_create_zip_archive($mock_minion_job, 4567); + is_deeply \@guard_calls, [{name => 'create_zip_archive_task', duration => 86400, options => {limit => 5}}], + 'called guard with custom configured limit'; + }; }; done_testing; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1793015014.afb80823/t/api/09-comments.t new/openQA-5.1793118173.1c8a4cde/t/api/09-comments.t --- old/openQA-5.1793015014.afb80823/t/api/09-comments.t 2026-10-26 12:43:34.000000000 +0100 +++ new/openQA-5.1793118173.1c8a4cde/t/api/09-comments.t 2026-10-27 17:22:53.000000000 +0100 @@ -295,6 +295,30 @@ is $job->result, PASSED, 'result of cancelled job has been updated'; }; +subtest 'bugrefs, labels and flags in comments with flag:verbatim are ignored' => sub { + my $job_id = 99940; + my $jobs = $t->app->schema->resultset('Jobs'); + my $bugs = $t->app->schema->resultset('Bugs'); + my $text = 'flag:verbatim quoting bsc#1234567, label:force_result:passed, label:foo and flag:carryover'; + my $id = test_create_comment('jobs', $job_id, $text); + is $jobs->find($job_id)->result, FAILED, 'force_result label is not applied'; + ok !$bugs->find({bugid => 'bsc#1234567'}), 'no bug is created'; + my $comment = $comments->find($id); + is $comment->bugref, undef, 'no bugref'; + is_deeply $comment->bugrefs, [], 'no bugrefs'; + is $comment->label, undef, 'no label'; + is_deeply $comment->text_flags, {verbatim => undef}, 'only the verbatim flag'; + ok !$comments->referenced_bugs->{'bsc#1234567'}, 'bugref is not referenced'; + my $data = $comments->comment_data_for_jobs([$jobs->find($job_id)])->{$job_id}; + is_deeply $data, {comments => 1}, 'job is not reviewed'; + $t->delete_ok("/api/v1/jobs/$job_id/comments/$id")->status_is(403, 'force_result label still prevents deletion'); + $comment->update({text => 'bsc#1234567 label:foo'}); + is $comment->bugref, 'bsc#1234567', 'bugref is found once the flag is edited away'; + $data = $comments->comment_data_for_jobs([$jobs->find($job_id)])->{$job_id}; + ok $data->{reviewed}, 'job is reviewed once the flag is gone'; + $t->delete_ok("/api/v1/jobs/$job_id/comments/$id")->status_is(200, 'comment can be deleted'); +}; + subtest 'unauthorized users can only read' => sub { my $app = $t->app; $t->ua(OpenQA::Client->new()->ioloop(Mojo::IOLoop->singleton)); ++++++ openQA.obsinfo ++++++ --- /var/tmp/diff_new_pack.t0fVum/_old 2026-10-28 17:50:46.801700031 +0100 +++ /var/tmp/diff_new_pack.t0fVum/_new 2026-10-28 17:50:46.813700533 +0100 @@ -1,5 +1,5 @@ name: openQA -version: 5.1793015014.afb80823 -mtime: 1793015014 -commit: afb808231f259ada298c3fb34b5c13571da85f7d +version: 5.1793118173.1c8a4cde +mtime: 1793118173 +commit: 1c8a4cde24dea14f4dd0dbfe5564a4d59e66df32
