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-07 19:32:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openQA (Old) and /work/SRC/openSUSE:Factory/.openQA.new.3698736 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openQA" Wed Oct 7 19:32:55 2026 rev:886 rq:1382887 version:5.1791317561.396de3fb Changes: -------- --- /work/SRC/openSUSE:Factory/openQA/openQA.changes 2026-10-06 19:16:15.305105669 +0200 +++ /work/SRC/openSUSE:Factory/.openQA.new.3698736/openQA.changes 2026-10-07 19:33:27.720787412 +0200 @@ -1,0 +2,19 @@ +Tue Oct 06 20:12:54 UTC 2026 - [email protected] + +- Update to version 5.1791317561.396de3fb: + * fix: Return secret on API key creation response + +------------------------------------------------------------------- +Tue Oct 06 13:20:17 UTC 2026 - [email protected] + +- Update to version 5.1791292805.aa7225b6: + * fix: test failure in t/37-limit_assets.t due to old mtimes + * feat(job-restart): Allow restarting chained parent + +------------------------------------------------------------------- +Mon Oct 05 23:20:26 UTC 2026 - [email protected] + +- Update to version 5.1791242414.a6759202: + * fix(openqa-bootstrap): Create tmpfiles.d entries without systemd + +------------------------------------------------------------------- Old: ---- openQA-5.1791003975.6dc1de2e.obscpio New: ---- openQA-5.1791317561.396de3fb.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openQA-client-test.spec ++++++ --- /var/tmp/diff_new_pack.ROgrfY/_old 2026-10-07 19:33:29.574864842 +0200 +++ /var/tmp/diff_new_pack.ROgrfY/_new 2026-10-07 19:33:29.575864884 +0200 @@ -18,7 +18,7 @@ %define short_name openQA-client Name: %{short_name}-test -Version: 5.1791003975.6dc1de2e +Version: 5.1791317561.396de3fb Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA-devel-test.spec ++++++ --- /var/tmp/diff_new_pack.ROgrfY/_old 2026-10-07 19:33:29.602866012 +0200 +++ /var/tmp/diff_new_pack.ROgrfY/_new 2026-10-07 19:33:29.604866095 +0200 @@ -18,7 +18,7 @@ %define short_name openQA-devel Name: %{short_name}-test -Version: 5.1791003975.6dc1de2e +Version: 5.1791317561.396de3fb Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA-test.spec ++++++ --- /var/tmp/diff_new_pack.ROgrfY/_old 2026-10-07 19:33:29.635867390 +0200 +++ /var/tmp/diff_new_pack.ROgrfY/_new 2026-10-07 19:33:29.637867473 +0200 @@ -18,7 +18,7 @@ %define short_name openQA Name: %{short_name}-test -Version: 5.1791003975.6dc1de2e +Version: 5.1791317561.396de3fb Release: 0 Summary: Test package for openQA License: GPL-2.0-or-later ++++++ openQA-worker-test.spec ++++++ --- /var/tmp/diff_new_pack.ROgrfY/_old 2026-10-07 19:33:29.664868601 +0200 +++ /var/tmp/diff_new_pack.ROgrfY/_new 2026-10-07 19:33:29.665868643 +0200 @@ -18,7 +18,7 @@ %define short_name openQA-worker Name: %{short_name}-test -Version: 5.1791003975.6dc1de2e +Version: 5.1791317561.396de3fb Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA.spec ++++++ --- /var/tmp/diff_new_pack.ROgrfY/_old 2026-10-07 19:33:29.698870021 +0200 +++ /var/tmp/diff_new_pack.ROgrfY/_new 2026-10-07 19:33:29.700870105 +0200 @@ -104,7 +104,7 @@ %define devel_requires %devel_no_selenium_requires chromedriver Name: openQA -Version: 5.1791003975.6dc1de2e +Version: 5.1791317561.396de3fb Release: 0 Summary: Framework for automated system-level testing (web-frontend, scheduler and tools) Group: Development/Tools/Other ++++++ openQA-5.1791003975.6dc1de2e.obscpio -> openQA-5.1791317561.396de3fb.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791003975.6dc1de2e/assets/javascripts/openqa.js new/openQA-5.1791317561.396de3fb/assets/javascripts/openqa.js --- old/openQA-5.1791003975.6dc1de2e/assets/javascripts/openqa.js 2026-10-03 07:06:15.000000000 +0200 +++ new/openQA-5.1791317561.396de3fb/assets/javascripts/openqa.js 2026-10-06 22:12:41.000000000 +0200 @@ -327,7 +327,9 @@ let parentId; if (Array.isArray(errors)) { for (const error of errors) { - const match = error.match(/Direct parent (\d+) needs to be cloned as well/); + const match = + error.match(/Direct parent (\d+) needs to be cloned as well/) || + error.match(/You may try to retrigger the parent jobs? (\d+)/); if (match) { parentId = match[1]; break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791003975.6dc1de2e/lib/OpenQA/Resource/Jobs.pm new/openQA-5.1791317561.396de3fb/lib/OpenQA/Resource/Jobs.pm --- old/openQA-5.1791003975.6dc1de2e/lib/OpenQA/Resource/Jobs.pm 2026-10-03 07:06:15.000000000 +0200 +++ new/openQA-5.1791317561.396de3fb/lib/OpenQA/Resource/Jobs.pm 2026-10-06 22:12:41.000000000 +0200 @@ -55,9 +55,12 @@ my $missing_assets = $job->missing_assets; if (@$missing_assets) { my $message = "Job $job_id misses the following mandatory assets: " . (join ', ', @$missing_assets); - if ($job->count_related('parents')) { + my @parent_ids = @{$job->parent_job_ids}; + if (@parent_ids) { + my $parent_text + = @parent_ids == 1 ? "parent job $parent_ids[0]" : ('parent jobs ' . join ', ', @parent_ids); $message - .= "\nYou may try to retrigger the parent job that should create the assets and will implicitly retrigger this job as well."; + .= "\nYou may try to retrigger the $parent_text that should create the assets and will implicitly retrigger this job as well."; } else { $message .= "\nEnsure to provide mandatory assets and/or force retriggering if necessary."; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791003975.6dc1de2e/lib/OpenQA/Schema/Result/Jobs.pm new/openQA-5.1791317561.396de3fb/lib/OpenQA/Schema/Result/Jobs.pm --- old/openQA-5.1791003975.6dc1de2e/lib/OpenQA/Schema/Result/Jobs.pm 2026-10-03 07:06:15.000000000 +0200 +++ new/openQA-5.1791317561.396de3fb/lib/OpenQA/Schema/Result/Jobs.pm 2026-10-06 22:12:41.000000000 +0200 @@ -551,7 +551,7 @@ # ignore UEFI_PFLASH_VARS; to keep scheduling simple it is present in lots of jobs which actually don't need it delete $assets_settings->{UEFI_PFLASH_VARS}; - my $parent_job_ids = $self->_parent_job_ids; + my $parent_job_ids = $self->parent_job_ids; # ignore repos, as they're not really clonable: see # https://github.com/os-autoinst/openQA/pull/2676#issuecomment-616312026 my @relevant_assets @@ -1522,8 +1522,9 @@ my %CHAINED_DEPENDENCY_QUERY = (dependency => {-in => [OpenQA::JobDependencies::Constants::CHAINED_DEPENDENCIES]}); -sub _parent_job_ids ($self) { - my @parents = $self->parents->search(\%CHAINED_DEPENDENCY_QUERY, {columns => ['parent_job_id']}); +sub parent_job_ids ($self) { + my @parents + = $self->parents->search(\%CHAINED_DEPENDENCY_QUERY, {columns => ['parent_job_id'], order_by => 'parent_job_id'}); return [map { $_->parent_job_id } @parents]; } @@ -1534,7 +1535,7 @@ return undef unless keys %assets; - my $parent_job_ids = $self->_parent_job_ids; + my $parent_job_ids = $self->parent_job_ids; # updated settings with actual file names my %updated; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791003975.6dc1de2e/lib/OpenQA/WebAPI/Controller/API/V1/User.pm new/openQA-5.1791317561.396de3fb/lib/OpenQA/WebAPI/Controller/API/V1/User.pm --- old/openQA-5.1791003975.6dc1de2e/lib/OpenQA/WebAPI/Controller/API/V1/User.pm 2026-10-03 07:06:15.000000000 +0200 +++ new/openQA-5.1791317561.396de3fb/lib/OpenQA/WebAPI/Controller/API/V1/User.pm 2026-10-06 22:12:41.000000000 +0200 @@ -66,6 +66,7 @@ =item create_api_key() Create a new API key. +Returns the key, secret, and expiration. =back @@ -85,7 +86,13 @@ ? DateTime::Format::Pg->parse_datetime($validation->param('expiration')) : DateTime->now->add(years => 1); my $apikey = $user->api_keys->create({t_expiration => $expiration}); - $self->render(json => {id => $apikey->id, key => $apikey->key, t_expiration => $apikey->t_expiration}); + $self->render( + json => { + id => $apikey->id, + key => $apikey->key, + secret => $apikey->secret, + t_expiration => $apikey->t_expiration + }); } =over 4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791003975.6dc1de2e/script/openqa-bootstrap new/openQA-5.1791317561.396de3fb/script/openqa-bootstrap --- old/openQA-5.1791003975.6dc1de2e/script/openqa-bootstrap 2026-10-03 07:06:15.000000000 +0200 +++ new/openQA-5.1791317561.396de3fb/script/openqa-bootstrap 2026-10-06 22:12:41.000000000 +0200 @@ -62,6 +62,8 @@ start-daemons() { if [[ -z $running_systemd ]]; then + # without systemd nothing processes tmpfiles.d, e.g. apache2 relies on it for /srv/www/htdocs + systemd-tmpfiles --create || true pgrep -f openqa-scheduler-daemon > /dev/null || su geekotest -c "$OPENQA_DIR/script/openqa-scheduler-daemon" & pgrep -f openqa-websockets-daemon > /dev/null || su geekotest -c "$OPENQA_DIR/script/openqa-websockets-daemon" & pgrep -f openqa-gru > /dev/null || su geekotest -c "$OPENQA_DIR/script/openqa-gru" & diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791003975.6dc1de2e/t/05-scheduler-restart-and-duplicate.t new/openQA-5.1791317561.396de3fb/t/05-scheduler-restart-and-duplicate.t --- old/openQA-5.1791003975.6dc1de2e/t/05-scheduler-restart-and-duplicate.t 2026-10-03 07:06:15.000000000 +0200 +++ new/openQA-5.1791317561.396de3fb/t/05-scheduler-restart-and-duplicate.t 2026-10-06 22:12:41.000000000 +0200 @@ -221,6 +221,30 @@ $current_jobs = $jobs; }; +subtest 'restart prevented by missing assets' => sub { + $schema->txn_begin; + my $job_deps = $schema->resultset('JobDependencies'); + my $res = OpenQA::Resource::Jobs::job_restart([99939]); + like $res->{errors}->[0], qr/Ensure to provide mandatory assets/, 'no parents message'; + is $res->{enforceable}, 1, 'enforceable'; + + $job_deps->create( + {child_job_id => 99939, parent_job_id => 99947, dependency => OpenQA::JobDependencies::Constants::CHAINED}); + $res = OpenQA::Resource::Jobs::job_restart([99939]); + like $res->{errors}->[0], qr/You may try to retrigger the parent job 99947 that should create the assets/, + 'single parent message'; + is $res->{enforceable}, 1, 'enforceable'; + + $job_deps->create( + {child_job_id => 99939, parent_job_id => 99926, dependency => OpenQA::JobDependencies::Constants::CHAINED}); + $res = OpenQA::Resource::Jobs::job_restart([99939]); + like $res->{errors}->[0], qr/You may try to retrigger the parent jobs 99926, 99947 that should create the assets/, + 'multiple parents message'; + is $res->{enforceable}, 1, 'enforceable'; + + $schema->txn_rollback; +}; + # check state before restarting job with parallel dependencies (that dependency is set in fixtures) is_deeply job_get_rs(99963)->cluster_jobs, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791003975.6dc1de2e/t/37-limit_assets.t new/openQA-5.1791317561.396de3fb/t/37-limit_assets.t --- old/openQA-5.1791003975.6dc1de2e/t/37-limit_assets.t 2026-10-03 07:06:15.000000000 +0200 +++ new/openQA-5.1791317561.396de3fb/t/37-limit_assets.t 2026-10-06 22:12:41.000000000 +0200 @@ -107,6 +107,9 @@ my $core72iso_path = assetdir() . '/iso/Core-7.2.iso'; Mojo::File->new($core72iso_path)->spew('foo') unless (-f $core72iso_path); +# touch all files to ensure they are "new" for the tests +path(assetdir())->list_tree({dir => 1})->each(sub { utime undef, undef, $_->to_string }); + # scan initially for untracked assets and refresh $schema->resultset('Assets')->scan_for_untracked_assets(); $schema->resultset('Assets')->refresh_assets(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791003975.6dc1de2e/t/api/15-users.t new/openQA-5.1791317561.396de3fb/t/api/15-users.t --- old/openQA-5.1791003975.6dc1de2e/t/api/15-users.t 2026-10-03 07:06:15.000000000 +0200 +++ new/openQA-5.1791317561.396de3fb/t/api/15-users.t 2026-10-06 22:12:41.000000000 +0200 @@ -37,6 +37,7 @@ my $res = $t->post_ok('/api/v1/users/me/api_keys')->status_is(200, 'create api key')->tx->res->json; ok $res->{key}, 'key returned'; +ok $res->{secret}, 'secret returned and non-empty'; my $expected_year = time2str('%Y', time + ONE_YEAR, 'UTC'); like $res->{t_expiration}, qr/^$expected_year-/, 'default expiration is set to 1 year from now'; my $key1 = $res->{key}; @@ -51,6 +52,7 @@ $res = $t->post_ok('/api/v1/users/me/api_keys' => form => {expiration => $expiration}) ->status_is(200, 'create api key with expiration')->tx->res->json; ok $res->{key}, 'key returned'; + ok $res->{secret}, 'secret returned on key creation with expiration'; my $expected_year = time2str('%Y', $expiration_time, 'UTC'); like $res->{t_expiration}, qr/^$expected_year-/, 'expiration matches expected year'; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791003975.6dc1de2e/t/ui/26-jobs_restart.t new/openQA-5.1791317561.396de3fb/t/ui/26-jobs_restart.t --- old/openQA-5.1791003975.6dc1de2e/t/ui/26-jobs_restart.t 2026-10-03 07:06:15.000000000 +0200 +++ new/openQA-5.1791317561.396de3fb/t/ui/26-jobs_restart.t 2026-10-06 22:12:41.000000000 +0200 @@ -23,6 +23,7 @@ my $schema = $test_case->init_data(schema_name => $schema_name, fixtures_glob => $fixtures); my $jobs = $schema->resultset('Jobs'); my $job_deps = $schema->resultset('JobDependencies'); +my $assets = $schema->resultset('Assets'); sub prepare_database () { # Populate more cluster jobs @@ -95,6 +96,17 @@ sub flash_messages () { $driver->find_element('#flash-messages')->get_text } +sub ensure_asset_exists ($name) { $assets->find_or_create({name => $name, type => 'iso', size => 0}) } + +sub verify_parent_skip_ok_button (%args) { + my $button = $driver->find_element('#flash-messages .restart-parent-skip-ok'); + ok $button, 'restart parent skipping OK children button is present' or return undef; + is $button->get_text, 'Restart parent job skipping passed/softfailed children', 'button text'; + $button->click if $args{click}; # click the button to restart parent job skipping OK children + return $button; +} + + subtest 'restart job from info panel in test results' => sub { subtest 'parent job shows options for advanced restart' => sub { $driver->get_ok('/tests/99900', 'go to job 99900'); @@ -133,8 +145,30 @@ $job_deps->create({child_job_id => 99939, parent_job_id => 99947, dependency => CHAINED}); is $driver->get('/tests/99939'), 1, 'go to job 99939'; $driver->find_element('#restart-result')->click(); - wait_until(sub { flash_messages =~ m/Job 99939 misses.*\.iso.*You may try to retrigger the parent job/s }, + wait_until(sub { flash_messages =~ m/Job 99939 misses.*\.iso.*You may try to retrigger the parent job 99947/s }, 'restarting job with missing asset results in an error', 20); + verify_parent_skip_ok_button; + }; + subtest 'restart parent skipping OK children option on regularly chained dependency error' => sub { + # cleanup after leaving subtest (not using txn here as the forked process needs to see changes) + my $cleanup = scope_guard sub { + $jobs->search({id => 99947})->update({clone_id => undef}); + $jobs->search({id => 99983})->delete; + $schema->storage->dbh->do('ALTER SEQUENCE jobs_id_seq RESTART WITH 99983'); + }; + + # ensure parent job's asset exists so it can be restarted + ensure_asset_exists('openSUSE-13.1-DVD-i586-Build0092-Media.iso'); + + is $driver->get('/tests/99939'), 1, 'go to job 99939 (regularly chained child)'; + $driver->find_element('#restart-result')->click(); + wait_for_ajax(msg => 'fail to restart job because of regularly chained parent'); + wait_until(sub { flash_messages =~ m/You may try to retrigger the parent job 99947/s }, + 'regularly chained parent error shown', 20); + verify_parent_skip_ok_button(click => 1) or return; + wait_for_ajax(msg => 'parent job restarted skipping OK children'); + wait_until(sub { $driver->get_current_url =~ qr{/tests/(\d+)} && $1 != 99939 }, + 'redirects to successfully restarted parent job'); }; subtest 'restart parent skipping OK children option on directly chained dependency error' => sub { # cleanup after leaving subtest (not using txn here as the forked process needs to see changes) @@ -147,12 +181,7 @@ }; # create a parent-prefixed asset to satisfy the missing asset check, change dependency to directly chained - $schema->resultset('Assets')->find_or_create( - { - name => '00099937-openSUSE-Factory-DVD-x86_64-Build0048-Media.iso', - type => 'iso', - size => 0, - }); + ensure_asset_exists('00099937-openSUSE-Factory-DVD-x86_64-Build0048-Media.iso'); $job_deps->search($job_deps_search)->update({dependency => DIRECTLY_CHAINED}); is $driver->get('/tests/99938'), 1, 'go to job 99938 (directly chained child)'; @@ -160,16 +189,10 @@ wait_for_ajax(msg => 'fail to restart job because of directly chained parent'); wait_until(sub { flash_messages =~ m/Direct parent 99937 needs to be cloned as well/s }, 'direct parent error shown', 20); - - my $button = $driver->find_element('#flash-messages .restart-parent-skip-ok'); - ok $button, 'restart parent skipping OK children button is present' or return; - is $button->get_text, 'Restart parent job skipping passed/softfailed children', 'button text'; - $button->click; # click the button to restart parent job skipping OK children - - # since it successfully restarts, it should redirect to the newly cloned parent job. + verify_parent_skip_ok_button(click => 1) or return; wait_for_ajax(msg => 'parent job restarted skipping OK children'); wait_until(sub { $driver->get_current_url =~ qr{/tests/(\d+)} && $1 != 99938 }, - 'redirects to restarted parent job'); + 'redirects to successfully restarted parent job'); }; subtest 'force restart' => sub { is $driver->get('/tests/99939'), 1, 'go to job 99939'; ++++++ openQA.obsinfo ++++++ --- /var/tmp/diff_new_pack.ROgrfY/_old 2026-10-07 19:33:44.346481740 +0200 +++ /var/tmp/diff_new_pack.ROgrfY/_new 2026-10-07 19:33:44.356482157 +0200 @@ -1,5 +1,5 @@ name: openQA -version: 5.1791003975.6dc1de2e -mtime: 1791003975 -commit: 6dc1de2e2de734eed0358a0e5a68e3880c04b144 +version: 5.1791317561.396de3fb +mtime: 1791317561 +commit: 396de3fb9b9e2176e430c817d5fa3f883a4ece0d
