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-22 15:51:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.2252680 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Thu Oct 22 15:51:12 2026 rev:896 rq:1387001 version:5.1792607148.117af9ef

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2026-10-21 
20:59:06.752070671 +0200
+++ /work/SRC/openSUSE:Factory/.openQA.new.2252680/openQA.changes       
2026-10-22 15:54:58.719879809 +0200
@@ -1,0 +2,14 @@
+Wed Oct 21 18:26:05 UTC 2026 - [email protected]
+
+- Update to version 5.1792607148.117af9ef:
+  * feat: Add seasonal Halloween decorations
+  * fix(webapi): Validate all appearance fields
+  * refactor(ui): Move theme init script to bundle
+
+-------------------------------------------------------------------
+Wed Oct 21 06:37:05 UTC 2026 - [email protected]
+
+- Update to version 5.1792563360.efc0128c:
+  * chore(deps): Dependency cron 2026-10-21
+
+-------------------------------------------------------------------

Old:
----
  openQA-5.1792527840.d945a1a7.obscpio

New:
----
  openQA-5.1792607148.117af9ef.obscpio

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

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.uL0K9A/_old  2026-10-22 15:55:02.738048239 +0200
+++ /var/tmp/diff_new_pack.uL0K9A/_new  2026-10-22 15:55:02.743048449 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1792527840.d945a1a7
+Version:        5.1792607148.117af9ef
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.uL0K9A/_old  2026-10-22 15:55:02.784050167 +0200
+++ /var/tmp/diff_new_pack.uL0K9A/_new  2026-10-22 15:55:02.785050209 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1792527840.d945a1a7
+Version:        5.1792607148.117af9ef
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.uL0K9A/_old  2026-10-22 15:55:02.818051593 +0200
+++ /var/tmp/diff_new_pack.uL0K9A/_new  2026-10-22 15:55:02.821051718 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1792527840.d945a1a7
+Version:        5.1792607148.117af9ef
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.uL0K9A/_old  2026-10-22 15:55:02.889054569 +0200
+++ /var/tmp/diff_new_pack.uL0K9A/_new  2026-10-22 15:55:02.895054821 +0200
@@ -104,7 +104,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1792527840.d945a1a7
+Version:        5.1792607148.117af9ef
 Release:        0
 Summary:        Framework for automated system-level testing (web-frontend, 
scheduler and tools)
 Group:          Development/Tools/Other

++++++ openQA-5.1792527840.d945a1a7.obscpio -> 
openQA-5.1792607148.117af9ef.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1792527840.d945a1a7/assets/assetpack.def 
new/openQA-5.1792607148.117af9ef/assets/assetpack.def
--- old/openQA-5.1792527840.d945a1a7/assets/assetpack.def       2026-10-20 
22:24:00.000000000 +0200
+++ new/openQA-5.1792607148.117af9ef/assets/assetpack.def       2026-10-21 
20:25:48.000000000 +0200
@@ -149,6 +149,7 @@
 < javascripts/fullscreen.js
 < javascripts/obs_rsync.js
 < javascripts/parent_group_overview.js
+< javascripts/theme.js
 < ../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js
 < ../node_modules/chosen-js/chosen.jquery.js
 < ../node_modules/jquery-ujs/src/rails.js
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1792527840.d945a1a7/assets/javascripts/theme.js 
new/openQA-5.1792607148.117af9ef/assets/javascripts/theme.js
--- old/openQA-5.1792527840.d945a1a7/assets/javascripts/theme.js        
1970-01-01 01:00:00.000000000 +0100
+++ new/openQA-5.1792607148.117af9ef/assets/javascripts/theme.js        
2026-10-21 20:25:48.000000000 +0200
@@ -0,0 +1,6 @@
+(() => {
+  const html = document.documentElement;
+  let theme = html.dataset.themePreference;
+  if (theme === 'detect') theme = window.matchMedia('(prefers-color-scheme: 
dark)').matches ? 'dark' : 'light';
+  html.dataset.bsTheme = theme;
+})();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1792527840.d945a1a7/assets/stylesheets/halloween.scss 
new/openQA-5.1792607148.117af9ef/assets/stylesheets/halloween.scss
--- old/openQA-5.1792527840.d945a1a7/assets/stylesheets/halloween.scss  
1970-01-01 01:00:00.000000000 +0100
+++ new/openQA-5.1792607148.117af9ef/assets/stylesheets/halloween.scss  
2026-10-21 20:25:48.000000000 +0200
@@ -0,0 +1,242 @@
+// Seasonal decorations: cartoonish, unobtrusive decorations layered behind 
the content.
+// The layout renders the decoration markup only when decorations are enabled 
(the
+// "Seasonal decorations" setting is on, or auto during October) and the theme 
is not
+// light, so pages in light mode and pages outside the season ship no 
decoration markup.
+// The activation key is the server-provided data-seasonal-decorations; CSS 
resolves the
+// browser preference of a "detect" user with the dark color scheme media 
query, so the
+// client never adds a theme state the server did not decide.
+// AssetPack serves assets below /asset/<checksum>/, so a relative url() in 
the bundled
+// CSS would resolve to the CSS asset itself and an absolute path breaks under 
a baseurl,
+// so the cursor has to stay an inline data URI.
+#hw-defs {
+  display: none;
+}
+#halloween-overlay {
+  display: none;
+  position: fixed;
+  inset: 0;
+  z-index: 0;
+  overflow: hidden;
+  pointer-events: none;
+  opacity: 0.45;
+  > div {
+    position: absolute;
+  }
+  .hw-svg {
+    width: 100%;
+    height: 100%;
+  }
+  .hw-web {
+    width: 130px;
+    height: 130px;
+    color: #8a8a8a;
+    animation: hw-sway 6s ease-in-out infinite;
+  }
+  .hw-tl {
+    top: 0;
+    left: 0;
+  }
+  .hw-tr {
+    top: 0;
+    right: 0;
+    .hw-svg {
+      transform: scaleX(-1);
+    }
+  }
+  .hw-bl {
+    bottom: 0;
+    left: 0;
+    .hw-svg {
+      transform: scaleY(-1);
+    }
+  }
+  .hw-br {
+    bottom: 0;
+    right: 0;
+    .hw-svg {
+      transform: scale(-1, -1);
+    }
+  }
+  .hw-spider {
+    top: 0;
+    right: 18vw;
+    width: 40px;
+    height: 120px;
+    color: #444;
+    transform-origin: top center;
+    animation: hw-swing 4s ease-in-out infinite;
+  }
+  .hw-bat {
+    width: 34px;
+    height: 17px;
+    color: #777;
+    animation: hw-fly 18s linear infinite;
+    .hw-svg {
+      animation: hw-flap 0.4s ease-in-out infinite;
+    }
+  }
+  .hw-bat1 {
+    top: 12vh;
+  }
+  .hw-bat2 {
+    top: 22vh;
+    animation-delay: -6s;
+    animation-duration: 22s;
+  }
+  .hw-bat3 {
+    top: 8vh;
+    animation-delay: -12s;
+    animation-duration: 26s;
+  }
+  .hw-bat4 {
+    top: 18vh;
+    animation-delay: -9s;
+    animation-duration: 24s;
+  }
+  .hw-bat5 {
+    top: 26vh;
+    animation-delay: -3s;
+    animation-duration: 20s;
+  }
+  .hw-ghost {
+    top: 30vh;
+    right: 12vw;
+    width: 50px;
+    height: 66px;
+    color: #cdd6ff;
+    opacity: 0.7;
+    animation: hw-bob 4s ease-in-out infinite;
+  }
+  .hw-pumpkin {
+    bottom: 0;
+    width: 70px;
+    height: 63px;
+    animation: hw-flicker 3s ease-in-out infinite;
+  }
+  .hw-pumpkin-bl {
+    left: 2vw;
+  }
+  .hw-pumpkin-br {
+    right: 2vw;
+    animation-delay: -1.5s;
+  }
+  .hw-zombie {
+    bottom: 0;
+    left: 50%;
+    width: 60px;
+    height: 45px;
+    animation: hw-peek 5s ease-in-out infinite;
+  }
+}
+@mixin seasonal-active {
+  body {
+    // cursor is inherited by all descendants
+    /* stylelint-disable @stylistic/selector-list-comma-space-after */
+    cursor:
+      url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' 
width='28' height='28' viewBox='0 0 24 24'><path fill='%23ff7b00' d='M12 8C6 8 
2 12 2 17c0 5 4 7 10 7s10-2 10-7C22 12 18 8 12 8Z'/><path fill='%232e7d32' 
d='M11 8q1-3 3-3-1 1.5-1 3Z'/><path fill='%23111' d='M8 14h3l-1.5 4ZM13 
14h3l-1.5 4ZM7 20q3 2 6 0 3 2 6 0l-1 1.5q-3 2-5 0-3 2-5 0Z'/><g stroke='%23111' 
stroke-width='0.8' fill='none'><circle cx='12' cy='4' r='1.5' 
fill='%23111'/><path d='M12 4 8 1M12 4 16 1M12 4 7 4M12 4 17 4M12 5 8 7M12 5 16 
7'/></g></svg>")
+        12 1,
+      auto;
+    /* stylelint-enable @stylistic/selector-list-comma-space-after */
+  }
+  .card, .navbar, .footer, .progress, .well {
+    box-shadow: 0 0 10px rgba(255, 120, 0, 18%);
+  }
+  #content, .footer {
+    position: relative;
+    z-index: 2;
+  }
+  .navbar {
+    position: relative;
+    z-index: 10;
+  }
+  #halloween-overlay {
+    display: block;
+  }
+}
+html[data-seasonal-decorations='true'][data-theme-preference='dark'] {
+  @include seasonal-active;
+}
+@media (prefers-color-scheme: dark) {
+  html[data-seasonal-decorations='true'][data-theme-preference='detect'] {
+    @include seasonal-active;
+  }
+}
+@keyframes hw-sway {
+  0% {
+    transform: rotate(0deg);
+  }
+  50% {
+    transform: rotate(1.5deg);
+  }
+  100% {
+    transform: rotate(0deg);
+  }
+}
+@keyframes hw-fly {
+  0% {
+    transform: translateX(-12vw);
+  }
+  100% {
+    transform: translateX(112vw);
+  }
+}
+@keyframes hw-flap {
+  0% {
+    transform: scaleY(1);
+  }
+  50% {
+    transform: scaleY(0.55);
+  }
+  100% {
+    transform: scaleY(1);
+  }
+}
+@keyframes hw-bob {
+  0% {
+    transform: translateY(0);
+  }
+  50% {
+    transform: translateY(-14px);
+  }
+  100% {
+    transform: translateY(0);
+  }
+}
+@keyframes hw-flicker {
+  0% {
+    opacity: 0.55;
+  }
+  50% {
+    opacity: 0.85;
+  }
+  100% {
+    opacity: 0.55;
+  }
+}
+@keyframes hw-peek {
+  0% {
+    transform: translateY(18px);
+  }
+  50% {
+    transform: translateY(0);
+  }
+  100% {
+    transform: translateY(18px);
+  }
+}
+@keyframes hw-swing {
+  0% {
+    transform: rotate(-6deg);
+  }
+  50% {
+    transform: rotate(6deg);
+  }
+  100% {
+    transform: rotate(-6deg);
+  }
+}
+@media (prefers-reduced-motion: reduce) {
+  #halloween-overlay, #halloween-overlay * {
+    animation: none !important;
+  }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1792527840.d945a1a7/assets/stylesheets/openqa.scss 
new/openQA-5.1792607148.117af9ef/assets/stylesheets/openqa.scss
--- old/openQA-5.1792527840.d945a1a7/assets/stylesheets/openqa.scss     
2026-10-20 22:24:00.000000000 +0200
+++ new/openQA-5.1792607148.117af9ef/assets/stylesheets/openqa.scss     
2026-10-21 20:25:48.000000000 +0200
@@ -24,3 +24,4 @@
 @import 'comments';
 @import 'overview';
 @import 'parent_group_overview';
+@import 'halloween';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1792527840.d945a1a7/lib/OpenQA/WebAPI/Controller/Appearance.pm 
new/openQA-5.1792607148.117af9ef/lib/OpenQA/WebAPI/Controller/Appearance.pm
--- old/openQA-5.1792527840.d945a1a7/lib/OpenQA/WebAPI/Controller/Appearance.pm 
2026-10-20 22:24:00.000000000 +0200
+++ new/openQA-5.1792607148.117af9ef/lib/OpenQA/WebAPI/Controller/Appearance.pm 
2026-10-21 20:25:48.000000000 +0200
@@ -11,10 +11,14 @@
 sub save ($self) {
     my $validation = $self->validation;
     $validation->required('theme')->in('light', 'dark', 'detect');
-    return $self->reply->exception('Invalid theme settings') unless 
$validation->is_valid;
+    $validation->optional('seasonal_decorations')->in('auto', 'on', 'off');
+    # is_valid would only look at the last validated field
+    return $self->reply->exception('Invalid theme settings') if 
$validation->has_error;
 
     my $theme = $validation->param('theme');
     $self->session->{theme} = $theme;
+    my $seasonal = $validation->param('seasonal_decorations');
+    $self->session->{seasonal_decorations} = $seasonal if defined $seasonal;
     $self->flash(info => 'Theme preferences updated');
 
     $self->redirect_to('appearance');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1792527840.d945a1a7/lib/OpenQA/WebAPI/Plugin/Helpers.pm 
new/openQA-5.1792607148.117af9ef/lib/OpenQA/WebAPI/Plugin/Helpers.pm
--- old/openQA-5.1792527840.d945a1a7/lib/OpenQA/WebAPI/Plugin/Helpers.pm        
2026-10-20 22:24:00.000000000 +0200
+++ new/openQA-5.1792607148.117af9ef/lib/OpenQA/WebAPI/Plugin/Helpers.pm        
2026-10-21 20:25:48.000000000 +0200
@@ -81,6 +81,13 @@
 
     $app->helper(current_job => sub ($c) { $c->stash('job') });
     $app->helper(current_theme => sub ($c) { $c->session->{theme} || 'light' 
});
+    $app->helper(seasonal_decorations => sub ($c) { 
$c->session->{seasonal_decorations} || 'auto' });
+    $app->helper(is_seasonal_period => sub ($c = undef) { (localtime)[4] == 9 
});
+    $app->helper(
+        seasonal_decorations_enabled => sub ($c) {
+            my $mode = $c->seasonal_decorations;
+            $mode eq 'on' || ($mode eq 'auto' && $c->is_seasonal_period);
+        });
     $app->helper(is_operator_js => sub ($c) { 
Mojo::ByteStream->new($c->helpers->is_operator ? 'true' : 'false') });
     $app->helper(is_admin_js => sub ($c) { 
Mojo::ByteStream->new($c->helpers->is_admin ? 'true' : 'false') });
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1792527840.d945a1a7/t/ui/04-appearance.t 
new/openQA-5.1792607148.117af9ef/t/ui/04-appearance.t
--- old/openQA-5.1792527840.d945a1a7/t/ui/04-appearance.t       2026-10-20 
22:24:00.000000000 +0200
+++ new/openQA-5.1792607148.117af9ef/t/ui/04-appearance.t       2026-10-21 
20:25:48.000000000 +0200
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 
 use Test::Most;
+use Mojo::Base -signatures;
 
 use FindBin;
 use lib "$FindBin::Bin/../lib", 
"$FindBin::Bin/../../external/os-autoinst-common/lib";
@@ -14,50 +15,86 @@
 $test_case->init_data(fixtures_glob => '03-users.pl');
 
 my $t = Test::Mojo->new('OpenQA::WebAPI');
+my $season = $t->app->is_seasonal_period ? 'true' : 'false';
+
+sub check_form ($theme, $mode) {
+    $t->get_ok('/appearance')->status_is(200)->element_exists(qq{select#theme 
option[selected][value="$theme"]})
+      ->element_exists(qq{select#seasonal_decorations 
option[selected][value="$mode"]});
+}
+
+sub check_page ($theme, $enabled, $overlay) {
+    
$t->get_ok('/')->status_is(200)->element_exists(qq{html[data-theme-preference="$theme"]})
+      ->element_exists(qq{html[data-seasonal-decorations="$enabled"]});
+    if ($overlay) {
+        $t->element_exists('div#halloween-overlay');
+    }
+    else {
+        $t->element_exists_not('div#halloween-overlay');
+    }
+}
 
 subtest 'No login, no themes' => sub {
     $t->get_ok('/appearance')->status_is(302);
 };
 
-subtest 'So lets grab the CSRF token and login as Percival' => sub {
+subtest 'Login as Percival' => sub {
     $t->get_ok('/tests');
-    my $token = $t->tx->res->dom->at('meta[name=csrf-token]')->attr('content');
     $test_case->login($t, 'percival');
+    $t->ua->max_redirects(5);
 };
 
-subtest 'Default theme is light' => sub {
-    $t->get_ok('/appearance')->status_is(200)->element_exists('select 
option[selected][value="light"]');
+subtest 'Default is light theme with seasonal decorations enabled during 
October' => sub {
+    check_form('light', 'auto');
+    check_page('light', $season, 0);
 };
 
-subtest 'We can switch to dark theme' => sub {
-    $t->ua->max_redirects(5);
-    $t->get_ok('/appearance')->status_is(200)->element_exists('select 
option[selected][value="light"]')
-      ->element_exists_not('select option[selected][value="dark"]');
-    $t->post_ok('/appearance' => form => {theme => 'dark'})->status_is(200)
-      ->element_exists('select option[selected][value="dark"]')
-      ->element_exists_not('select option[selected][value="light"]');
-    $t->get_ok('/appearance')->status_is(200)->element_exists('select 
option[selected][value="dark"]')
-      ->element_exists_not('select option[selected][value="light"]');
-};
-
-subtest 'We can switch to theme detection' => sub {
-    $t->get_ok('/appearance')->status_is(200)->element_exists('select 
option[selected][value="dark"]')
-      ->element_exists_not('select option[selected][value="detect"]');
-    $t->post_ok('/appearance' => form => {theme => 'detect'})->status_is(200)
-      ->element_exists('select option[selected][value="detect"]')
-      ->element_exists_not('select option[selected][value="dark"]');
-    $t->get_ok('/appearance')->status_is(200)->element_exists('select 
option[selected][value="detect"]')
-      ->element_exists_not('select option[selected][value="dark"]');
-};
-
-subtest 'We can switch back to light theme' => sub {
-    $t->get_ok('/appearance')->status_is(200)->element_exists('select 
option[selected][value="detect"]')
-      ->element_exists_not('select option[selected][value="light"]');
-    $t->post_ok('/appearance' => form => {theme => 'light'})->status_is(200)
-      ->element_exists('select option[selected][value="light"]')
-      ->element_exists_not('select option[selected][value="detect"]');
-    $t->get_ok('/appearance')->status_is(200)->element_exists('select 
option[selected][value="light"]')
-      ->element_exists_not('select option[selected][value="detect"]');
+subtest 'Explicit dark theme gets decorations during October' => sub {
+    $t->post_ok('/appearance' => form => {theme => 'dark', 
seasonal_decorations => 'auto'})->status_is(200);
+    check_form('dark', 'auto');
+    check_page('dark', $season, $season eq 'true');
+};
+
+subtest 'Theme detection is resolved by the browser, so the markup is shipped 
during October' => sub {
+    $t->post_ok('/appearance' => form => {theme => 'detect', 
seasonal_decorations => 'auto'})->status_is(200);
+    check_form('detect', 'auto');
+    check_page('detect', $season, $season eq 'true');
+};
+
+subtest 'Seasonal decorations can be enabled all year' => sub {
+    $t->post_ok('/appearance' => form => {theme => 'dark', 
seasonal_decorations => 'on'})->status_is(200);
+    check_form('dark', 'on');
+    check_page('dark', 'true', 1);
+};
+
+subtest 'Seasonal decorations can be disabled' => sub {
+    $t->post_ok('/appearance' => form => {theme => 'dark', 
seasonal_decorations => 'off'})->status_is(200);
+    check_form('dark', 'off');
+    check_page('dark', 'false', 0);
+};
+
+subtest 'Seasonal decorations are not shown in light mode' => sub {
+    $t->post_ok('/appearance' => form => {theme => 'light', 
seasonal_decorations => 'on'})->status_is(200);
+    check_form('light', 'on');
+    check_page('light', 'true', 0);
+};
+
+subtest 'Omission of seasonal_decorations preserves existing preference' => 
sub {
+    $t->post_ok('/appearance' => form => {theme => 'dark'})->status_is(200);
+    check_form('dark', 'on');
+    check_page('dark', 'true', 1);
+};
+
+subtest 'Seasonal decoration labels are sentence case' => sub {
+    $t->get_ok('/appearance')->status_is(200);
+    is $t->tx->res->dom->at('label[for=seasonal_decorations]')->text, 
'Seasonal decorations', 'label is sentence case';
+    is $t->tx->res->dom->at('select#seasonal_decorations 
option[value=auto]')->text,
+      'Automatically during October', 'auto option is sentence case';
+};
+
+subtest 'Invalid parameters are rejected' => sub {
+    $t->post_ok('/appearance' => form => {theme => 'dark', 
seasonal_decorations => 'bogus'})->status_is(500);
+    $t->post_ok('/appearance' => form => {theme => 'bogus', 
seasonal_decorations => 'auto'})->status_is(500);
+    check_form('dark', 'on');
 };
 
 done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1792527840.d945a1a7/templates/webapi/appearance/index.html.ep 
new/openQA-5.1792607148.117af9ef/templates/webapi/appearance/index.html.ep
--- old/openQA-5.1792527840.d945a1a7/templates/webapi/appearance/index.html.ep  
2026-10-20 22:24:00.000000000 +0200
+++ new/openQA-5.1792607148.117af9ef/templates/webapi/appearance/index.html.ep  
2026-10-21 20:25:48.000000000 +0200
@@ -7,8 +7,8 @@
         <div class="card-body">
             %= form_for appearance => (method => 'post') => begin
                 <div class="mb-3">
-                    <label class="form-label" for="expiration">Theme</label>
-                    <select name="theme" class="form-select">
+                    <label class="form-label" for="theme">Theme</label>
+                    <select name="theme" id="theme" class="form-select">
                       % my $theme = current_theme;
                       <option value="light"<%= $theme eq 'light' ? ' selected' 
: '' %>>Light mode</option>
                       <option value="dark"<%= $theme eq 'dark' ? ' selected' : 
'' %>>Dark mode</option>
@@ -16,6 +16,15 @@
                     </select>
                 </div>
                 <div class="mb-3">
+                    <label class="form-label" 
for="seasonal_decorations">Seasonal decorations</label>
+                    <select name="seasonal_decorations" 
id="seasonal_decorations" class="form-select">
+                      % my $mode = seasonal_decorations;
+                      <option value="auto"<%= $mode eq 'auto' ? ' selected' : 
'' %>>Automatically during October</option>
+                      <option value="on"<%= $mode eq 'on' ? ' selected' : '' 
%>>Always</option>
+                      <option value="off"<%= $mode eq 'off' ? ' selected' : '' 
%>>Never</option>
+                    </select>
+                </div>
+                <div class="mb-3">
                     %= submit_button 'Save', class => 'btn btn-primary'
                 </div>
             % end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1792527840.d945a1a7/templates/webapi/layouts/bootstrap.html.ep 
new/openQA-5.1792607148.117af9ef/templates/webapi/layouts/bootstrap.html.ep
--- old/openQA-5.1792527840.d945a1a7/templates/webapi/layouts/bootstrap.html.ep 
2026-10-20 22:24:00.000000000 +0200
+++ new/openQA-5.1792607148.117af9ef/templates/webapi/layouts/bootstrap.html.ep 
2026-10-21 20:25:48.000000000 +0200
@@ -1,5 +1,7 @@
+% my $theme = current_theme;
+% my $decorations = seasonal_decorations_enabled;
 <!DOCTYPE html>
-<html lang="en">
+<html lang="en" data-theme-preference="<%= $theme %>" 
data-seasonal-decorations="<%= $decorations ? 'true' : 'false' %>">
   <head>
       <!-- Meta, title, CSS, favicons, etc. -->
       <meta charset="utf-8">
@@ -77,10 +79,8 @@
               </div>
             </div>
       </footer>
-      <script>
-        let theme = '<%= current_theme %>';
-        if (theme === 'detect') theme = 
window.matchMedia('(prefers-color-scheme: dark)').matches === true ? 'dark' : 
'light';
-        document.documentElement.dataset.bsTheme = theme;
-      </script>
+% if ($decorations && $theme ne 'light') {
+%= include 'layouts/halloween'
+% }
   </body>
 </html>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1792527840.d945a1a7/templates/webapi/layouts/halloween.html.ep 
new/openQA-5.1792607148.117af9ef/templates/webapi/layouts/halloween.html.ep
--- old/openQA-5.1792527840.d945a1a7/templates/webapi/layouts/halloween.html.ep 
1970-01-01 01:00:00.000000000 +0100
+++ new/openQA-5.1792607148.117af9ef/templates/webapi/layouts/halloween.html.ep 
2026-10-21 20:25:48.000000000 +0200
@@ -0,0 +1,55 @@
+<svg id="hw-defs" aria-hidden="true">
+  <defs>
+    <symbol id="hw-web" viewBox="0 0 100 100">
+      <g fill="none" stroke="currentColor" stroke-width="1.4">
+        <path d="M0 0 100 0M0 0 96.6 25.9M0 0 86.6 50M0 0 70.7 70.7M0 0 50 
86.6M0 0 25.9 96.6M0 0 0 100" />
+        <path d="M30 0A30 30 0 0 1 0 30M60 0A60 60 0 0 1 0 60M90 0A90 90 0 0 1 
0 90M100 0A100 100 0 0 1 0 100" />
+      </g>
+    </symbol>
+    <symbol id="hw-bat" viewBox="0 0 100 50">
+      <path fill="currentColor" d="M50 18C42 9 27 7 16 16c7-4 13-2 15 4C21 18 
12 24 8 32c10-6 18-4 24 2 8-6 14-6 18-2 4-4 10-4 18 2 6-6 14-8 
22-2-4-8-13-14-23-12 2-6 8-8 15-4C73 7 58 9 50 18Z" />
+      <path fill="currentColor" d="M46 12 50 5 54 12Z" />
+    </symbol>
+    <symbol id="hw-ghost" viewBox="0 0 60 80">
+      <path fill="currentColor" d="M30 4C15 4 8 19 8 33v27l6-6 6 10 10-10 10 
10 6-10 6 6V33C52 19 45 4 30 4Z" />
+      <circle cx="22" cy="28" r="4" fill="#111" />
+      <circle cx="38" cy="28" r="4" fill="#111" />
+      <path d="M24 40q6 6 12 0" stroke="#111" stroke-width="2" fill="none" />
+    </symbol>
+    <symbol id="hw-pumpkin" viewBox="0 0 100 90">
+      <path fill="#ff7b00" d="M50 18C30 18 12 34 12 54c0 20 18 32 38 32s38-12 
38-32C88 34 70 18 50 18Z" />
+      <path fill="#2e7d32" d="M48 18q2-12 6-12-2 6-2 12Z" />
+      <path fill="#111" d="M35 45h10l-5 12ZM55 45h10l-5 12ZM30 62q10 8 20 0 10 
8 20 0l-2 6q-10 8-18 0-10 8-18 0Z" />
+    </symbol>
+    <symbol id="hw-zombie" viewBox="0 0 80 60">
+      <path fill="#7cb342" d="M10 60V30C10 12 30 6 40 6s30 6 30 24v30Z" />
+      <circle cx="28" cy="32" r="6" fill="#fff" />
+      <circle cx="52" cy="32" r="6" fill="#fff" />
+      <circle cx="28" cy="32" r="2.5" fill="#222" />
+      <circle cx="52" cy="32" r="2.5" fill="#222" />
+      <path d="M22 48q18 10 36 0" stroke="#222" stroke-width="3" fill="none" />
+    </symbol>
+    <symbol id="hw-spider" viewBox="0 0 40 60">
+      <line x1="20" y1="0" x2="20" y2="26" stroke="currentColor" 
stroke-width="1" />
+      <ellipse cx="20" cy="34" rx="6" ry="8" fill="currentColor" />
+      <circle cx="20" cy="26" r="3.5" fill="currentColor" />
+      <path d="M20 28 8 18M20 28 32 18M20 30 6 30M20 30 34 30M20 36 8 46M20 36 
32 46M20 38 12 52M20 38 28 52" stroke="currentColor" stroke-width="1.2" 
fill="none" />
+    </symbol>
+  </defs>
+</svg>
+<div id="halloween-overlay" aria-hidden="true">
+  <div class="hw-web hw-tl"><svg class="hw-svg"><use href="#hw-web" 
/></svg></div>
+  <div class="hw-web hw-tr"><svg class="hw-svg"><use href="#hw-web" 
/></svg></div>
+  <div class="hw-web hw-bl"><svg class="hw-svg"><use href="#hw-web" 
/></svg></div>
+  <div class="hw-web hw-br"><svg class="hw-svg"><use href="#hw-web" 
/></svg></div>
+  <div class="hw-spider"><svg class="hw-svg"><use href="#hw-spider" 
/></svg></div>
+  <div class="hw-bat hw-bat1"><svg class="hw-svg"><use href="#hw-bat" 
/></svg></div>
+  <div class="hw-bat hw-bat2"><svg class="hw-svg"><use href="#hw-bat" 
/></svg></div>
+  <div class="hw-bat hw-bat3"><svg class="hw-svg"><use href="#hw-bat" 
/></svg></div>
+  <div class="hw-bat hw-bat4"><svg class="hw-svg"><use href="#hw-bat" 
/></svg></div>
+  <div class="hw-bat hw-bat5"><svg class="hw-svg"><use href="#hw-bat" 
/></svg></div>
+  <div class="hw-ghost"><svg class="hw-svg"><use href="#hw-ghost" 
/></svg></div>
+  <div class="hw-pumpkin hw-pumpkin-bl"><svg class="hw-svg"><use 
href="#hw-pumpkin" /></svg></div>
+  <div class="hw-pumpkin hw-pumpkin-br"><svg class="hw-svg"><use 
href="#hw-pumpkin" /></svg></div>
+  <div class="hw-zombie"><svg class="hw-svg"><use href="#hw-zombie" 
/></svg></div>
+</div>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1792527840.d945a1a7/tools/ci/autoinst.sha 
new/openQA-5.1792607148.117af9ef/tools/ci/autoinst.sha
--- old/openQA-5.1792527840.d945a1a7/tools/ci/autoinst.sha      2026-10-20 
22:24:00.000000000 +0200
+++ new/openQA-5.1792607148.117af9ef/tools/ci/autoinst.sha      2026-10-21 
20:25:48.000000000 +0200
@@ -1 +1 @@
-5.044000-2bd94ba81d9b441255ddd19aad6368f900501724
\ No newline at end of file
+5.044000-82c2f16f64f0a38f9fe932524c90636826be875f
\ No newline at end of file

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.uL0K9A/_old  2026-10-22 15:55:15.547585178 +0200
+++ /var/tmp/diff_new_pack.uL0K9A/_new  2026-10-22 15:55:15.555585514 +0200
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1792527840.d945a1a7
-mtime: 1792527840
-commit: d945a1a7467aaf6ac963b16bb77b4e53836bb996
+version: 5.1792607148.117af9ef
+mtime: 1792607148
+commit: 117af9ef0fc009cf9afa792d2e3915730183000f
 

Reply via email to