Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package openQA for openSUSE:Factory checked in at 2025-05-02 15:01:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openQA (Old) and /work/SRC/openSUSE:Factory/.openQA.new.30101 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openQA" Fri May 2 15:01:15 2025 rev:689 rq:1273980 version:5.1746018652.10b1e438 Changes: -------- --- /work/SRC/openSUSE:Factory/openQA/openQA.changes 2025-04-25 22:19:37.232321200 +0200 +++ /work/SRC/openSUSE:Factory/.openQA.new.30101/openQA.changes 2025-05-02 15:02:35.301991041 +0200 @@ -1,0 +2,14 @@ +Fri May 02 09:26:33 UTC 2025 - ok...@suse.com + +- Update to version 5.1746018652.10b1e438: + * Bump datatables.net-bs5 from 2.2.2 to 2.3.0 + * Follow symlinks but only delete files with dump-db script + * Avoid unbound variable error in dump-db script + * Fix result in case of giving up gru jobs without GruTasks + * Add nice and ionice to dump-db script + * Documented the PROVE_COMMAND and prove_wrapper feature + * Add explicit test for `obsolete_minion_jobs` + * Avoid leftover Minion jobs after failing txn when scheduling jobs + * Wrap prove to prevent unhandled output + +------------------------------------------------------------------- Old: ---- openQA-5.1745500773.055f94fe.obscpio New: ---- openQA-5.1746018652.10b1e438.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openQA-client-test.spec ++++++ --- /var/tmp/diff_new_pack.8GdElH/_old 2025-05-02 15:02:36.370035929 +0200 +++ /var/tmp/diff_new_pack.8GdElH/_new 2025-05-02 15:02:36.370035929 +0200 @@ -18,7 +18,7 @@ %define short_name openQA-client Name: %{short_name}-test -Version: 5.1745500773.055f94fe +Version: 5.1746018652.10b1e438 Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA-devel-test.spec ++++++ --- /var/tmp/diff_new_pack.8GdElH/_old 2025-05-02 15:02:36.406037442 +0200 +++ /var/tmp/diff_new_pack.8GdElH/_new 2025-05-02 15:02:36.406037442 +0200 @@ -18,7 +18,7 @@ %define short_name openQA-devel Name: %{short_name}-test -Version: 5.1745500773.055f94fe +Version: 5.1746018652.10b1e438 Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA-test.spec ++++++ --- /var/tmp/diff_new_pack.8GdElH/_old 2025-05-02 15:02:36.434038619 +0200 +++ /var/tmp/diff_new_pack.8GdElH/_new 2025-05-02 15:02:36.438038786 +0200 @@ -18,7 +18,7 @@ %define short_name openQA Name: %{short_name}-test -Version: 5.1745500773.055f94fe +Version: 5.1746018652.10b1e438 Release: 0 Summary: Test package for openQA License: GPL-2.0-or-later ++++++ openQA-worker-test.spec ++++++ --- /var/tmp/diff_new_pack.8GdElH/_old 2025-05-02 15:02:36.474040299 +0200 +++ /var/tmp/diff_new_pack.8GdElH/_new 2025-05-02 15:02:36.474040299 +0200 @@ -18,7 +18,7 @@ %define short_name openQA-worker Name: %{short_name}-test -Version: 5.1745500773.055f94fe +Version: 5.1746018652.10b1e438 Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA.spec ++++++ --- /var/tmp/diff_new_pack.8GdElH/_old 2025-05-02 15:02:36.502041476 +0200 +++ /var/tmp/diff_new_pack.8GdElH/_new 2025-05-02 15:02:36.502041476 +0200 @@ -94,7 +94,7 @@ %define devel_requires %devel_no_selenium_requires chromedriver Name: openQA -Version: 5.1745500773.055f94fe +Version: 5.1746018652.10b1e438 Release: 0 Summary: The openQA web-frontend, scheduler and tools License: GPL-2.0-or-later ++++++ node_modules.obscpio ++++++ Binary files old/datatables.net-2.2.2.tgz and new/datatables.net-2.2.2.tgz differ Binary files old/datatables.net-2.3.0.tgz and new/datatables.net-2.3.0.tgz differ Binary files old/datatables.net-bs5-2.2.2.tgz and new/datatables.net-bs5-2.2.2.tgz differ Binary files old/datatables.net-bs5-2.3.0.tgz and new/datatables.net-bs5-2.3.0.tgz differ ++++++ node_modules.spec.inc ++++++ --- /var/tmp/diff_new_pack.8GdElH/_old 2025-05-02 15:02:37.122067535 +0200 +++ /var/tmp/diff_new_pack.8GdElH/_new 2025-05-02 15:02:37.126067703 +0200 @@ -67,8 +67,8 @@ Source1066: https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz#/d3-zoom-3.0.0.tgz Source1067: https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz#/dagre-0.8.5.tgz Source1068: https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz#/dagre-d3-0.6.4.tgz -Source1069: https://registry.npmjs.org/datatables.net/-/datatables.net-2.2.2.tgz#/datatables.net-2.2.2.tgz -Source1070: https://registry.npmjs.org/datatables.net-bs5/-/datatables.net-bs5-2.2.2.tgz#/datatables.net-bs5-2.2.2.tgz +Source1069: https://registry.npmjs.org/datatables.net/-/datatables.net-2.3.0.tgz#/datatables.net-2.3.0.tgz +Source1070: https://registry.npmjs.org/datatables.net-bs5/-/datatables.net-bs5-2.3.0.tgz#/datatables.net-bs5-2.3.0.tgz Source1071: https://registry.npmjs.org/debug/-/debug-4.4.0.tgz#/debug-4.4.0.tgz Source1072: https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#/deep-is-0.1.4.tgz Source1073: https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz#/delaunator-5.0.1.tgz ++++++ openQA-5.1745500773.055f94fe.obscpio -> openQA-5.1746018652.10b1e438.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/Makefile new/openQA-5.1746018652.10b1e438/Makefile --- old/openQA-5.1745500773.055f94fe/Makefile 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/Makefile 2025-04-30 15:10:52.000000000 +0200 @@ -16,6 +16,8 @@ TESTS ?= # EXTRA_PROVE_ARGS: Additional prove arguments to pass EXTRA_PROVE_ARGS ?= +# PROVE: Test application for Perl tests +PROVE ?= prove ifeq ($(TESTS),) PROVE_ARGS ?= --trap -r ${EXTRA_PROVE_ARGS} t else @@ -240,7 +242,7 @@ export GLOBIGNORE="$(GLOBIGNORE)";\ export DEVEL_COVER_DB_FORMAT=JSON;\ export PERL5OPT="$(COVEROPT)$(PERL5OPT) -It/lib -I$(PWD)/t/lib -I$(PWD)/external/os-autoinst-common/lib -MOpenQA::Test::PatchDeparse";\ - RETRY=${RETRY} HOOK=./tools/delete-coverdb-folder timeout -s SIGINT -k 5 -v ${TIMEOUT_RETRIES} tools/retry prove ${PROVE_LIB_ARGS} ${PROVE_ARGS} + RETRY=${RETRY} HOOK=./tools/delete-coverdb-folder timeout -s SIGINT -k 5 -v ${TIMEOUT_RETRIES} tools/retry "${PROVE}" ${PROVE_LIB_ARGS} ${PROVE_ARGS} .PHONY: setup-database setup-database: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/docs/Contributing.asciidoc new/openQA-5.1746018652.10b1e438/docs/Contributing.asciidoc --- old/openQA-5.1745500773.055f94fe/docs/Contributing.asciidoc 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/docs/Contributing.asciidoc 2025-04-30 15:10:52.000000000 +0200 @@ -267,6 +267,18 @@ See the docs for details https://metacpan.org/pod/Devel::Cover +To run the tests with a different command than `prove` you can set the +`PROVE` variable in the Makefile. For example, in our CircleCI tests we +use `tools/prove_wrapper` to run the tests. This wrapper is a simple script that +will run `prove` and fail the test if there is unhandled output. This is useful +to avoid having unhandled output in tests. To run the tests with +`tools/prove_wrapper` you can do: + +[source,sh] +---- +PROVE=tools/prove_wrapper make test TESTS=t/foo.t +---- + There are some ways to save some time when executing local tests: * One option is selecting individual tests to run as explained above diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/lib/OpenQA/Schema/Result/ScheduledProducts.pm new/openQA-5.1746018652.10b1e438/lib/OpenQA/Schema/Result/ScheduledProducts.pm --- old/openQA-5.1745500773.055f94fe/lib/OpenQA/Schema/Result/ScheduledProducts.pm 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/lib/OpenQA/Schema/Result/ScheduledProducts.pm 2025-04-30 15:10:52.000000000 +0200 @@ -248,7 +248,7 @@ } sub _create_jobs_in_database ($self, $jobs, $failed_job_info, $skip_chained_deps, $include_children, - $successful_job_ids) + $successful_job_ids, $minion_ids = undef) { my $schema = $self->result_source->schema; my $jobs_resultset = $schema->resultset('Jobs'); @@ -307,8 +307,8 @@ $tmp_downloads{$_}->{blocked_job_id}] } keys %tmp_downloads; my $gru = OpenQA::App->singleton->gru; - $gru->enqueue_download_jobs(\%downloads); - $gru->enqueue_git_clones(\%clones, $successful_job_ids) if keys %clones; + $gru->enqueue_download_jobs(\%downloads, $minion_ids); + $gru->enqueue_git_clones(\%clones, $successful_job_ids, $minion_ids) if keys %clones; } =over 4 @@ -399,16 +399,22 @@ # define function to create jobs in the database; executed as transaction my @successful_job_ids; my @failed_job_info; + my @minion_ids; + my $gru = OpenQA::App->singleton->gru; try { $schema->txn_do_retry_on_deadlock( sub { $self->_create_jobs_in_database($jobs, \@failed_job_info, $skip_chained_deps, $include_children, - \@successful_job_ids); + \@successful_job_ids, \@minion_ids); }, - sub { (@successful_job_ids, @failed_job_info) = () }); + sub { # this handler is generally covered but tests are unable to reproduce the deadlock 100 % of the time + $gru->obsolete_minion_jobs(\@minion_ids); # uncoverable statement + (@successful_job_ids, @failed_job_info, @minion_ids) = (); # uncoverable statement + }); } catch ($e) { + $gru->obsolete_minion_jobs(\@minion_ids); push(@notes, "Transaction failed: $e"); push(@failed_job_info, map { {job_id => $_, error_messages => [$e]} } @successful_job_ids); @successful_job_ids = (); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/lib/OpenQA/Shared/GruJob.pm new/openQA-5.1746018652.10b1e438/lib/OpenQA/Shared/GruJob.pm --- old/openQA-5.1745500773.055f94fe/lib/OpenQA/Shared/GruJob.pm 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/lib/OpenQA/Shared/GruJob.pm 2025-04-30 15:10:52.000000000 +0200 @@ -10,7 +10,9 @@ sub _grutasks ($self) { $self->minion->app->schema->resultset('GruTasks'); } sub execute ($self) { - my $gru_id = $self->info->{notes}{gru_id}; + my $notes = $self->info->{notes}; + return $self->finish if $notes->{obsolete}; + my $gru_id = $notes->{gru_id}; if ($gru_id and not $self->info->{finished}) { # We have a gru_id and this is the first run of the job my $gru = $self->_grutasks->find($gru_id); @@ -21,7 +23,8 @@ my $delay = 2**(1 + $retried); my $msg = "Could not find GruTask '$gru_id' after $retried retries"; if ($retried > $max_retries) { - return $self->note(stop_reason => "$msg, giving up"); + $self->note(stop_reason => "$msg, giving up"); + return undef; } log_debug("$msg, delaying ${delay}s"); return $self->retry({delay => $delay}); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/lib/OpenQA/Shared/Plugin/Gru.pm new/openQA-5.1746018652.10b1e438/lib/OpenQA/Shared/Plugin/Gru.pm --- old/openQA-5.1745500773.055f94fe/lib/OpenQA/Shared/Plugin/Gru.pm 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/lib/OpenQA/Shared/Plugin/Gru.pm 2025-04-30 15:10:52.000000000 +0200 @@ -174,6 +174,13 @@ }); } +sub obsolete_minion_jobs ($self, $job_ids) { + my $minion = $self->app->minion; + for my $job_id (@$job_ids) { + if (my $job = $minion->job($job_id)) { $job->note(obsolete => 1) } + } +} + sub enqueue ($self, $task, $args = [], $options = {}, $jobs = []) { my $ttl = $options->{ttl}; my $limit = $options->{limit} ? $options->{limit} : undef; @@ -216,13 +223,14 @@ # enqueues the limit_assets task with the default parameters sub enqueue_limit_assets ($self) { $self->enqueue('limit_assets', [], {priority => 0, ttl => 172800, limit => 1}) } -sub enqueue_download_jobs ($self, $downloads) { +sub enqueue_download_jobs ($self, $downloads, $minion_ids = undef) { return unless %$downloads; # array of hashrefs job_id => id; this is what create needs # to create entries in a related table (gru_dependencies) for my $url (keys %$downloads) { my ($path, $do_extract, $block_job_ids) = @{$downloads->{$url}}; - $self->enqueue('download_asset', [$url, $path, $do_extract], {priority => 10}, $block_job_ids); + my $job = $self->enqueue('download_asset', [$url, $path, $do_extract], {priority => 10}, $block_job_ids); + push @$minion_ids, $job->{minion_id} if $minion_ids; } } @@ -253,7 +261,7 @@ $self->enqueue('git_clone', \%clones, {priority => 10}); } -sub enqueue_git_clones ($self, $clones, $job_ids) { +sub enqueue_git_clones ($self, $clones, $job_ids, $minion_ids = undef) { return unless keys %$clones; return unless OpenQA::App->singleton->config->{'scm git'}->{git_auto_clone} eq 'yes'; # $clones is a hashref with paths as keys and git urls as values @@ -267,7 +275,10 @@ } my $found = $self->_find_existing_minion_job('git_clone', $clones_sr, $job_ids); - $self->enqueue('git_clone', $clones_sr, {priority => 10}, $job_ids) unless $found; + return $found if $found; + my $job = $self->enqueue('git_clone', $clones_sr, {priority => 10}, $job_ids); + push @$minion_ids, $job->{minion_id} if $minion_ids; + return $job; } sub enqueue_and_keep_track { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm new/openQA-5.1746018652.10b1e438/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm --- old/openQA-5.1745500773.055f94fe/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/lib/OpenQA/WebAPI/Controller/API/V1/Job.pm 2025-04-30 15:10:52.000000000 +0200 @@ -316,7 +316,7 @@ =cut -sub _create_job ($self, $global_params, $job_suffix = undef, $job_specific_params = {}) { +sub _create_job ($self, $global_params, $job_suffix, $job_specific_params, $minion_ids) { # job_create expects upper case keys my %up_params = map { uc $_ => $global_params->{$_} } keys %$global_params; $up_params{uc $_} = $job_specific_params->{$_} for keys %$job_specific_params; @@ -344,9 +344,9 @@ # enqueue gru jobs and calculate blocked by push @{$downloads->{$_}}, [$job_id] for keys %$downloads; - $self->gru->enqueue_download_jobs($downloads); + $self->gru->enqueue_download_jobs($downloads, $minion_ids); my $clones = create_git_clone_list($job_settings); - $self->gru->enqueue_git_clones($clones, [$job_id]) if keys %$clones; + $self->gru->enqueue_git_clones($clones, [$job_id], $minion_ids) if keys %$clones; return $job_id; } @@ -391,14 +391,14 @@ =cut -sub _create_jobs ($self, $global_params, $grouped_params) { +sub _create_jobs ($self, $global_params, $grouped_params, $minion_ids) { if (keys %$grouped_params) { # create as many jobs as unique ":"-suffixes exist - $self->_create_job($global_params, $_, $grouped_params->{$_}) for keys %$grouped_params; + $self->_create_job($global_params, $_, $grouped_params->{$_}, $minion_ids) for keys %$grouped_params; } else { # create a single job if there are no job-specific parameters - $self->_create_job($global_params); + $self->_create_job($global_params, undef, {}, $minion_ids); } $self->_create_dependencies; } @@ -421,8 +421,12 @@ my $json = $self->{_json} = {}; my $event_data = $self->{_event_data} = []; my $dependencies = $self->{_dependencies} = []; + my @minion_ids; + my $gru = OpenQA::App->singleton->gru; try { - $self->schema->txn_do_retry_on_deadlock(sub { $self->_create_jobs($global_params, $grouped_params) }); + $self->schema->txn_do_retry_on_deadlock( + sub { $self->_create_jobs($global_params, $grouped_params, \@minion_ids) }, + sub { $gru->obsolete_minion_jobs(\@minion_ids) }); OpenQA::Scheduler::Client->singleton->wakeup; } catch ($e) { @@ -430,6 +434,7 @@ $json->{error} = $e; delete $json->{id}; delete $json->{ids}; + $gru->obsolete_minion_jobs(\@minion_ids); } $self->emit_event(openqa_job_create => $_) for @$event_data; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/package-lock.json new/openQA-5.1746018652.10b1e438/package-lock.json --- old/openQA-5.1745500773.055f94fe/package-lock.json 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/package-lock.json 2025-04-30 15:10:52.000000000 +0200 @@ -15,7 +15,7 @@ "chosen-js": "^1.8.7", "d3": "^7.9.0", "dagre-d3": "^0.6.4", - "datatables.net-bs5": "^2.2.2", + "datatables.net-bs5": "^2.3.0", "fork-awesome": "^1.2.0", "jquery": "^3.7.1", "jquery-ujs": "^1.2.3", @@ -835,21 +835,21 @@ } }, "node_modules/datatables.net": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-2.2.2.tgz", - "integrity": "sha512-gfODIKE3gpgbVeZy2QGj2Dq9roO6hy00S+k1knklrqlMyAMrh1wt0Q6ryBUM7gU96U77ysbq8dYhxFdmcC/oPQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-2.3.0.tgz", + "integrity": "sha512-IX5Dsc7bTNqI3RyT4B7imtFicLMCg7ZLwwx/gvR6cbwYgfG+mLX2KAVm7BNmnwOhUdMMcGSGSE19RpTn31TTGQ==", "license": "MIT", "dependencies": { "jquery": ">=1.7" } }, "node_modules/datatables.net-bs5": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/datatables.net-bs5/-/datatables.net-bs5-2.2.2.tgz", - "integrity": "sha512-0mAbpUf0EpnIEc0RlN6vSrSk9y/+NuReiwDpjHYY3RfzdvH6Lt0+7Q9OU5RIbYxaFxES/z60thxdrw7IUFnBhw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/datatables.net-bs5/-/datatables.net-bs5-2.3.0.tgz", + "integrity": "sha512-JvcYrf2kEVzHY7NKsJxV132kehhc5+iRIpZAYmYqSW52yCcMiQYWtw1Z4+Wb/FMbJDQwP9exCtTwroLYPKwkeQ==", "license": "MIT", "dependencies": { - "datatables.net": "2.2.2", + "datatables.net": "2.3.0", "jquery": ">=1.7" } }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/package.json new/openQA-5.1746018652.10b1e438/package.json --- old/openQA-5.1745500773.055f94fe/package.json 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/package.json 2025-04-30 15:10:52.000000000 +0200 @@ -24,7 +24,7 @@ "chosen-js": "^1.8.7", "d3": "^7.9.0", "dagre-d3": "^0.6.4", - "datatables.net-bs5": "^2.2.2", + "datatables.net-bs5": "^2.3.0", "fork-awesome": "^1.2.0", "jquery": "^3.7.1", "jquery-ujs": "^1.2.3", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/script/dump-db new/openQA-5.1746018652.10b1e438/script/dump-db --- old/openQA-5.1745500773.055f94fe/script/dump-db 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/script/dump-db 2025-04-30 15:10:52.000000000 +0200 @@ -2,7 +2,7 @@ set -euo pipefail DUMP_FOLDER=${DUMP_FOLDER:-"/var/lib/openqa/SQL-DUMPS"} DAYS_TO_KEEP=${DAYS_TO_KEEP:-"7"} -[[ $1 = '-h' ]] || [[ $1 = '--help' ]] && echo "Dump the openQA postgresql database to ${DUMP_FOLDER} and clean-up backups older than ${DAYS_TO_KEEP} days." && exit +[[ ${1-} = '-h' ]] || [[ ${1-} = '--help' ]] && echo "Dump the openQA postgresql database to ${DUMP_FOLDER} and clean-up backups older than ${DAYS_TO_KEEP} days." && exit -pg_dump -Fc -c openqa -f "${DUMP_FOLDER}/$(date -Idate).dump" -find "${DUMP_FOLDER}" -mtime "+${DAYS_TO_KEEP}" -print0 -delete +ionice -c3 nice -n19 pg_dump -Fc -c openqa -f "${DUMP_FOLDER}/$(date -Idate).dump" +find -L "${DUMP_FOLDER}" -type f -mtime "+${DAYS_TO_KEEP}" -print0 -delete diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/t/14-grutasks.t new/openQA-5.1746018652.10b1e438/t/14-grutasks.t --- old/openQA-5.1745500773.055f94fe/t/14-grutasks.t 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/t/14-grutasks.t 2025-04-30 15:10:52.000000000 +0200 @@ -626,7 +626,7 @@ $t->app->minion->job($id)->retry({delay => 0}); # retries=6 perform_minion_jobs($t->app->minion); - is $job->info->{state}, 'failed', 'Job finally failed'; + is $job->info->{state}, 'finished', 'job finished successfully'; like $job->info->{notes}->{stop_reason}, qr{Could not find GruTask '\d+' after 6 retries.*}, 'Message is logged as job result'; is $job->info->{retries}, 6, 'job retried because there is no GruTasks entry'; @@ -864,6 +864,11 @@ }; }; +subtest 'marking Minion jobs as obsolete' => sub { + my $job_id = $app->minion->jobs->next->{id}; + $app->gru->obsolete_minion_jobs([$job_id]); + ok $app->minion->job($job_id)->info->{notes}->{obsolete}, "job $job_id marked as obsolete"; +}; done_testing(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/t/15-assets.t new/openQA-5.1746018652.10b1e438/t/15-assets.t --- old/openQA-5.1745500773.055f94fe/t/15-assets.t 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/t/15-assets.t 2025-04-30 15:10:52.000000000 +0200 @@ -346,6 +346,9 @@ }; subtest 'concurrent asset creation' => sub { + my $minion = $t->app->minion; + $minion->reset({all => 1}); + # allow configuring a delay so this test will always trigger the deadlock case my $delay = $ENV{OPENQA_ASSET_TESTS_DELAY} // 1; my $jobs_mock = Test::MockModule->new('OpenQA::Schema::ResultSet::Jobs'); @@ -362,8 +365,8 @@ = (DISTRI => 'sle', VERSION => '12-SP5', FLAVOR => 'Server-DVD-Updates', ARCH => 'x86_64', TEST => 'base'); my $asset_name_1 = 'SLES-12-SP5-x86_64-mru-install-desktop-with-addons-Build20250211-1.qcow2'; my $asset_name_2 = 'SLES-12-SP5-x86_64-mru-install-desktop-with-addons-Build20250211-2.qcow2'; - my %settings_1 = (%base_settings, TEST => 'job1', HDD_1 => $asset_name_1); - my %settings_2 = (%base_settings, TEST => 'job2', HDD_1 => $asset_name_2); + my %settings_1 = (%base_settings, TEST => 'job1', HDD_1 => $asset_name_1, HDD_1_URL => "http://foo/$asset_name_1"); + my %settings_2 = (%base_settings, TEST => 'job2', HDD_1 => $asset_name_2, HDD_1_URL => "http://foo/$asset_name_2"); # define functions to create jobs using the web API my $post_job = sub ($delay, @settings) { @@ -422,6 +425,22 @@ subtest 'posting a single set of jobs' => sub { $create_jobs->($post_jobs_1, $post_jobs_2) }; subtest 'scheduling a product' => sub { $create_jobs->($schedule_product_1, $schedule_product_2) }; subtest 'track coverage of helpers' => sub { $_->(0, \%base_settings) for $post_job, $schedule_product }; + + subtest 'no leftover Minion jobs after handling deadlocks' => sub { + my $jobs = $minion->jobs; + my $count = 0; + my $gru_tasks = $schema->resultset('GruTasks'); + while (my $info = $jobs->next) { + next if $info->{notes}->{obsolete}; + my $job_id = $info->{id}; + my $gru_id = $info->{notes}->{gru_id}; + ++$count; + is $info->{task}, 'download_asset', "Minion job $job_id is of expected task"; + ok $gru_tasks->find($gru_id), "Minion job $job_id refers to Gru task with valid ID $gru_id" + or always_explain $info; + } + is $count, 8, 'one Minion job per openQA job, excluding obsolete jobs'; + }; }; done_testing(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/tools/ci/run_unit_tests.sh new/openQA-5.1746018652.10b1e438/tools/ci/run_unit_tests.sh --- old/openQA-5.1745500773.055f94fe/tools/ci/run_unit_tests.sh 2025-04-24 15:19:33.000000000 +0200 +++ new/openQA-5.1746018652.10b1e438/tools/ci/run_unit_tests.sh 2025-04-30 15:10:52.000000000 +0200 @@ -22,4 +22,5 @@ export OPENQA_TEST_TIMEOUT_SCALE_CI=3 export EXTRA_PROVE_ARGS="-v" export OPENQA_FULLSTACK_TEMP_DIR=$PWD/test-results/fullstack +export PROVE="tools/prove_wrapper" make test-$target diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1745500773.055f94fe/tools/prove_wrapper new/openQA-5.1746018652.10b1e438/tools/prove_wrapper --- old/openQA-5.1745500773.055f94fe/tools/prove_wrapper 1970-01-01 01:00:00.000000000 +0100 +++ new/openQA-5.1746018652.10b1e438/tools/prove_wrapper 2025-04-30 15:10:52.000000000 +0200 @@ -0,0 +1,31 @@ +#!/bin/bash + +set -euo pipefail + +OUTPUT=$(mktemp) + +echo "Running prove with TAP output check ..." + +prove "$@" 2>&1 | tee "$OUTPUT" +STATUS=${PIPESTATUS[0]} + +if [ "$STATUS" -ne 0 ]; then + echo "not ok - prove failed" + exit "$STATUS" +fi + +sed -E ' + s/^\[[0-9]{2}:[0-9]{2}:[0-9]{2}\][[:space:]]*// + /^All tests successful\./,$d +' "$OUTPUT" > "$OUTPUT.processed" + +UNHANDLED=$(grep -vE '^t/.*([0-9]{2}-|)([[:alpha:]]|_|-)+\.t \.+' "$OUTPUT.processed" || true) + +if [ -n "$UNHANDLED" ]; then + echo "not ok - unhandled output found" + echo "Run with PROVE_COMMAND=tools/prove_wrapper to reproduce locally" + exit 1 +else + echo "ok - no unhandled output found" + exit 0 +fi ++++++ openQA.obsinfo ++++++ --- /var/tmp/diff_new_pack.8GdElH/_old 2025-05-02 15:02:57.426923236 +0200 +++ /var/tmp/diff_new_pack.8GdElH/_new 2025-05-02 15:02:57.426923236 +0200 @@ -1,5 +1,5 @@ name: openQA -version: 5.1745500773.055f94fe -mtime: 1745500773 -commit: 055f94fee5dbce696c292af7344c2343d96a3852 +version: 5.1746018652.10b1e438 +mtime: 1746018652 +commit: 10b1e43840bddcc9839be91ebb46fb422effe601