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-08-17 16:59:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openQA (Old)
 and      /work/SRC/openSUSE:Factory/.openQA.new.1258 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openQA"

Mon Aug 17 16:59:01 2026 rev:874 rq:1371468 version:5.1786788019.aa348157

Changes:
--------
--- /work/SRC/openSUSE:Factory/openQA/openQA.changes    2026-08-14 
22:08:18.938910858 +0200
+++ /work/SRC/openSUSE:Factory/.openQA.new.1258/openQA.changes  2026-08-17 
17:02:18.271052682 +0200
@@ -1,0 +2,12 @@
+Mon Aug 17 01:54:40 UTC 2026 - [email protected]
+
+- Update to version 5.1786788019.aa348157:
+  * refactor(ui): remove jQuery from core utility scripts
+  * fix(layout): Avoid horizontal scrollbar on the whole page
+  * chore(deps): Dependency cron 2026-08-14
+  * refactor: remove deprecated job templates table view
+  * fix(storage): correct MD RAID0 setup and Agama schema validation
+  * feat: Add experimental log view mode to test details
+  * refactor(css): Use classes for preview containers
+
+-------------------------------------------------------------------

Old:
----
  openQA-5.1786629850.d1bdb83d.obscpio

New:
----
  openQA-5.1786788019.aa348157.obscpio

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

Other differences:
------------------
++++++ openQA-client-test.spec ++++++
--- /var/tmp/diff_new_pack.7eZTd5/_old  2026-08-17 17:02:19.921110982 +0200
+++ /var/tmp/diff_new_pack.7eZTd5/_new  2026-08-17 17:02:19.923111053 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-client
 Name:           %{short_name}-test
-Version:        5.1786629850.d1bdb83d
+Version:        5.1786788019.aa348157
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.7eZTd5/_old  2026-08-17 17:02:19.949111972 +0200
+++ /var/tmp/diff_new_pack.7eZTd5/_new  2026-08-17 17:02:19.952112078 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-devel
 Name:           %{short_name}-test
-Version:        5.1786629850.d1bdb83d
+Version:        5.1786788019.aa348157
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA-test.spec ++++++
--- /var/tmp/diff_new_pack.7eZTd5/_old  2026-08-17 17:02:19.983113173 +0200
+++ /var/tmp/diff_new_pack.7eZTd5/_new  2026-08-17 17:02:19.986113279 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA
 Name:           %{short_name}-test
-Version:        5.1786629850.d1bdb83d
+Version:        5.1786788019.aa348157
 Release:        0
 Summary:        Test package for openQA
 License:        GPL-2.0-or-later

++++++ openQA-worker-test.spec ++++++
--- /var/tmp/diff_new_pack.7eZTd5/_old  2026-08-17 17:02:20.018114410 +0200
+++ /var/tmp/diff_new_pack.7eZTd5/_new  2026-08-17 17:02:20.019114445 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name openQA-worker
 Name:           %{short_name}-test
-Version:        5.1786629850.d1bdb83d
+Version:        5.1786788019.aa348157
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ openQA.spec ++++++
--- /var/tmp/diff_new_pack.7eZTd5/_old  2026-08-17 17:02:20.055115717 +0200
+++ /var/tmp/diff_new_pack.7eZTd5/_new  2026-08-17 17:02:20.058115823 +0200
@@ -104,7 +104,7 @@
 %define devel_requires %devel_no_selenium_requires chromedriver
 
 Name:           openQA
-Version:        5.1786629850.d1bdb83d
+Version:        5.1786788019.aa348157
 Release:        0
 Summary:        Framework for automated system-level testing (web-frontend, 
scheduler and tools)
 Group:          Development/Tools/Other

++++++ openQA-5.1786629850.d1bdb83d.obscpio -> 
openQA-5.1786788019.aa348157.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/assets/javascripts/back_to_top.js 
new/openQA-5.1786788019.aa348157/assets/javascripts/back_to_top.js
--- old/openQA-5.1786629850.d1bdb83d/assets/javascripts/back_to_top.js  
2026-08-13 16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/assets/javascripts/back_to_top.js  
2026-08-15 12:00:19.000000000 +0200
@@ -1,17 +1,15 @@
 function backToTop() {
-  $(document).ready(function () {
-    $(window).scroll(function () {
-      // Increase the value to not show the button on shorter pages
-      if ($(this).scrollTop() > 50) {
-        $('#back-to-top').fadeIn();
-      } else {
-        $('#back-to-top').fadeOut();
-      }
-    });
-    $('#back-to-top').click(function () {
-      $('#back-to-top').tooltip('hide');
-      $('body, html').animate({scrollTop: 0}, 800);
-      return false;
-    });
+  const button = document.getElementById('back-to-top');
+  if (!button) return;
+
+  window.addEventListener('scroll', () => {
+    // Increase the value to not show the button on shorter pages
+    button.style.display = window.scrollY > 50 ? 'block' : 'none';
+  });
+  button.addEventListener('click', () => {
+    const tooltip = bootstrap.Tooltip.getInstance(button);
+    if (tooltip) tooltip.hide();
+    window.scrollTo({top: 0, behavior: 'smooth'});
+    return false;
   });
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/assets/javascripts/job_templates.js 
new/openQA-5.1786788019.aa348157/assets/javascripts/job_templates.js
--- old/openQA-5.1786629850.d1bdb83d/assets/javascripts/job_templates.js        
2026-08-13 16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/assets/javascripts/job_templates.js        
2026-08-15 12:00:19.000000000 +0200
@@ -1,342 +1,6 @@
-let job_templates_url;
-let job_group_id;
 let user_is_admin;
 let editor;
 
-function setupJobTemplates(url, id) {
-  job_templates_url = url;
-  job_group_id = id;
-  $.ajax(url + '?group_id=' + id).done(loadJobTemplates);
-}
-
-function loadJobTemplates(data) {
-  const mediagroups = {};
-  const groups = [];
-  $.each(data.JobTemplates, function (i, jt) {
-    let media = mediagroups[jt.product.group];
-    if (!media) {
-      groups.push(jt.product.group);
-      media = [];
-    }
-    media.push(jt);
-    mediagroups[jt.product.group] = media;
-  });
-  groups.sort();
-  $.each(groups, function (i, group) {
-    buildMediumGroup(group, mediagroups[group]);
-  });
-  const width = alignCols() - 16;
-  $('#loading').remove();
-  $('.chosen-select').chosen({width: width + 'px'});
-  $(document).on('change', '.chosen-select', chosenChanged);
-}
-
-function highlightChosen(chosen) {
-  const container = chosen.parent('td').find('.chosen-container');
-  container.fadeTo('fast', 0.3).fadeTo('fast', 1);
-}
-
-function templateRemoved(chosen, deselected) {
-  const jid = chosen.find('option[value="' + deselected + '"]').data('jid');
-  $.ajax({
-    url: job_templates_url + '/' + jid,
-    type: 'DELETE',
-    dataType: 'json'
-  })
-    .done(function () {
-      highlightChosen(chosen);
-    })
-    .fail(addFailed);
-}
-
-function addFailed(data) {
-  // display something without alert
-  if (Object.prototype.hasOwnProperty.call(data, 'responseJSON')) {
-    alert(data.responseJSON.error);
-  } else {
-    alert('unknown error');
-  }
-}
-
-function addSucceeded(chosen, selected, data) {
-  chosen.find('option[value="' + selected + '"]').data('jid', data['id']);
-  highlightChosen(chosen);
-}
-
-// after a machine was added the select is final
-function finalizeTest(tr) {
-  const test_select = tr.find('td.name select');
-  if (!test_select.length) return;
-
-  // disable select and assign the selected ID to the row
-  test_select.prop('disabled', true);
-  tr.data('test-id', test_select.find('option:selected').data('test-id'));
-
-  // make test unavailable in other selections
-  const tbody = tr.parents('tbody');
-  presentTests = findPresentTests(tbody);
-  tbody.find('td.name select').each(function (index, select) {
-    select = $(select);
-    if (!select.prop('disabled')) {
-      filterTestSelection(select, presentTests);
-    }
-  });
-}
-
-function formatPriority(prio) {
-  return !prio || prio.length === 0 ? 'inherit' : prio;
-}
-
-function templateAdded(chosen, selected) {
-  const tr = chosen.parents('tr');
-  finalizeTest(tr);
-  const postData = {
-    prio: formatPriority(tr.find('.prio input').val()),
-    group_id: job_group_id,
-    product_id: chosen.data('product-id'),
-    machine_id: chosen.find('option[value="' + selected + 
'"]').data('machine-id'),
-    test_suite_id: tr.data('test-id')
-  };
-
-  $.ajax({
-    url: job_templates_url,
-    type: 'POST',
-    dataType: 'json',
-    data: postData
-  })
-    .fail(addFailed)
-    .done(function (data) {
-      addSucceeded(chosen, selected, data);
-    });
-}
-
-function priorityChanged(priorityInput) {
-  const tr = priorityInput.parents('tr');
-
-  // just skip if there are no machines added anyways
-  const hasMachines = tr.find('td.arch select option:selected').length > 0;
-  if (!hasMachines) {
-    return;
-  }
-
-  $.ajax({
-    url: job_templates_url,
-    type: 'POST',
-    dataType: 'json',
-    data: {
-      prio: formatPriority(priorityInput.val()),
-      prio_only: true,
-      group_id: job_group_id,
-      test_suite_id: tr.data('test-id')
-    }
-  }).fail(addFailed);
-}
-
-function chosenChanged(evt, param) {
-  if (param.deselected) {
-    templateRemoved($(this), param.deselected);
-  } else {
-    templateAdded($(this), param.selected);
-  }
-}
-
-function testChanged() {
-  const select = $(this);
-  const selectedValue = select.find('option:selected').val();
-  const noSelection = !selectedValue || selectedValue.length === 0;
-  const tr = select.parents('tr');
-  const chosens = tr.find('.chosen-select');
-  const inputs = tr.find('input');
-  chosens.prop('disabled', noSelection).trigger('chosen:updated');
-  inputs.prop('disabled', noSelection);
-}
-
-function findPresentTests(table) {
-  const presentTests = [];
-  table.find('td.name').each(function (index, td) {
-    let test;
-    const select = $(td).find('select');
-    if (select.length && select.prop('disabled')) {
-      test = select.val();
-    } else {
-      test = td.innerText.trim();
-    }
-    if (test) {
-      presentTests.push(test);
-    }
-  });
-  return presentTests;
-}
-
-function filterTestSelection(select, presentTests) {
-  select.find('option').each(function (index, option) {
-    if (presentTests.indexOf(option.innerText.trim()) >= 0) {
-      $(option).remove();
-    }
-  });
-}
-
-function makePrioCell(prio, disabled) {
-  // use default priority if no prio passed; also disable the input in this 
case
-  const useDefaultPrio = !prio;
-  let defaultPrio = $('#editor-default-priority').data('initial-value');
-  if (!defaultPrio) {
-    defaultPrio = 50;
-  }
-  if (!prio) {
-    prio = defaultPrio;
-  }
-
-  const td = $('<td class="prio"></td>');
-  const prioInput = $('<input type="number"></input>');
-  if (!useDefaultPrio) {
-    prioInput.val(prio);
-  }
-  prioInput.change(function () {
-    priorityChanged($(this));
-  });
-  prioInput.prop('disabled', disabled);
-  prioInput.attr('placeholder', defaultPrio);
-  prioInput.appendTo(td);
-  return td;
-}
-
-function buildMediumGroup(group, media) {
-  const div = $('<div class="jobtemplate-medium"/>').appendTo('#media');
-  div.append('<div class="jobtemplate-header">' + group + '</div>');
-  const table = $('<table class="table table-striped mediagroup" id="' + group 
+ '"/>').appendTo(div);
-  const thead = $('<thead/>').appendTo(table);
-  const tr = $('<tr/>').appendTo(thead);
-  const tname = tr.append($('<th class="name">Test</th>'));
-  const prioHeading = $('<th class="prio">Prio</th>');
-  prioHeading.css('white-space', 'nowrap');
-  const prioHelpPopover = $(
-    '<a href="#" class="help_popover fa-solid fa-circle-question"" 
data-content="' +
-      'The priority can be set for each row specifically. However, the 
priority might be left empty as well. ' +
-      'In this case default priority for the whole job group is used 
(displayed in italic font)." data-bs-toggle="popover" ' +
-      'data-trigger="focus" role="button"></a>'
-  );
-  prioHelpPopover.popover({html: true});
-  prioHeading.append(prioHelpPopover);
-  tr.append(prioHeading);
-  const archs = {};
-  const tests = {};
-  const prio = 444;
-  $.each(media, function (index, temp) {
-    let a = archs[temp.product.arch];
-    if (!a) a = {};
-    if (!Object.prototype.hasOwnProperty.call(a, temp.test_suite.name)) {
-      a[temp.test_suite.name] = [];
-      table.data('product-' + temp.product.arch, temp.product.id);
-      a['_id'] = temp.product.id;
-    }
-    a[temp.test_suite.name].push(temp);
-    archs[temp.product.arch] = a;
-    tests[temp.test_suite.name] = {
-      prio: temp.prio,
-      id: temp.test_suite.id
-    };
-  });
-  const archnames = Object.keys(archs).sort();
-  table.data('archs', archnames);
-  const testnames = Object.keys(tests).sort();
-  $.each(archnames, function (index, arch) {
-    const a = $('<th class="arch arch_' + arch + '">' + arch + 
'</th>').appendTo(tr);
-  });
-  const tbody = $('<tbody/>').appendTo(table);
-  $.each(testnames, function (ti, test) {
-    const tr = $('<tr class="test_' + test + '"/>').appendTo(tbody);
-    tr.data('test-id', tests[test]['id']);
-    let shortname = test;
-    if (test.length >= 70) {
-      shortname = '<span title=' + test + '>' + test.substr(0, 67) + 
'…</span>';
-    }
-    $('<td class="name">' + shortname + '</td>').appendTo(tr);
-    makePrioCell(tests[test].prio, false).appendTo(tr);
-
-    $.each(archnames, function (archIndex, arch) {
-      const td = $('<td class="arch"/>').appendTo(tr);
-      const select = $('#machines-template').clone().appendTo(td);
-      select.attr('id', group + '-' + arch + '-' + test);
-      select.attr('data-product-id', archs[arch]['_id']);
-      select.addClass('chosen-select');
-      if (
-        Object.prototype.hasOwnProperty.call(archs, arch) &&
-        Object.prototype.hasOwnProperty.call(archs[arch], test)
-      ) {
-        $.each(archs[arch][test], function (mi, temp) {
-          const option = select.find("option[value='" + temp.machine.name + 
"']").prop('selected', true);
-          // remember the id for DELETE
-          option.data('jid', temp.id);
-        });
-      }
-    });
-  });
-}
-
-function addArchSpacer(table, position, method) {
-  $(table).find('thead th.arch').eq(position)[method]('<th 
class="arch">&nbsp;</th>');
-  $(table)
-    .find('tbody tr')
-    .each(function () {
-      $(this).find('td.arch').eq(position)[method]('<td 
class="arch">&nbsp;</td>');
-    });
-}
-
-function findHeaderWithAllArchitectures() {
-  let headerWithAllArchs = [];
-  $('table.mediagroup thead').each(function () {
-    const archs = $(this).find('th.arch');
-    if (archs.length > headerWithAllArchs.length) headerWithAllArchs = archs;
-  });
-  return headerWithAllArchs;
-}
-
-function fillEmptySpace(table, tableHead, headerWithAllArchs) {
-  if (tableHead.length < headerWithAllArchs.length) {
-    headerWithAllArchs.each(function (i) {
-      // Used all ths, fill the rest
-      if (tableHead.length == i) {
-        for (let j = i; j < headerWithAllArchs.length; j++) {
-          addArchSpacer(table, j - 1, 'after');
-        }
-        return false;
-      } else if (this.innerHTML != tableHead.get(i).innerHTML) {
-        addArchSpacer(table, i, 'before');
-        tableHead = $(table).find('thead th.arch');
-      }
-    });
-  }
-}
-
-function alignCols() {
-  // Set minimal width
-  $('th.name,th.prio').width('0');
-
-  // Find biggest minimal width
-  let namewidth = 450;
-  $('td.name').each(function (index, test) {
-    if ($(this).outerWidth() > namewidth) namewidth = $(this).outerWidth();
-  });
-  namewidth = Math.ceil(namewidth);
-
-  const headerWithAllArchs = findHeaderWithAllArchitectures();
-
-  // Fill empty space
-  $('table.mediagroup').each(function (index, table) {
-    fillEmptySpace(table, $(this).find('thead th.arch'), headerWithAllArchs);
-  });
-
-  // Compute arch width
-  let archwidth = $('.jobtemplate-header').outerWidth() - namewidth - 
$('th.prio').outerWidth();
-  archwidth = Math.floor(archwidth / headerWithAllArchs.length) - 1;
-
-  $('th.name').outerWidth(namewidth);
-  $('th.arch').outerWidth(archwidth);
-
-  return archwidth;
-}
-
 function toggleEdit() {
   $('#properties').toggle(250);
   validateJobGroupForm(document.getElementById('group_properties_form'));
@@ -349,13 +13,11 @@
   }
 }
 
-function toggleTemplateEditor() {
-  $('#media').toggle(250);
+function setupTemplateEditor() {
   const form = $('#editor-form');
-  form.toggle(250);
+  form.show();
   form.find('.buttons').hide();
   form.find('.progress-indication').show();
-  $('#toggle-yaml-editor').toggleClass('btn-secondary');
   if (editor === undefined) {
     editor = ace.edit('editor-template', {
       mode: 'ace/mode/yaml',
@@ -463,9 +125,6 @@
           value = data.changes;
           break;
         case 'save':
-          // Once a valid YAML template was saved we no longer offer the 
legacy editor
-          $('#toggle-yaml-editor').hide();
-          $('#media-add').hide();
           // Update the reference to the saved document
           form.data('reference', editor.getValue());
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/assets/javascripts/openqa.js 
new/openQA-5.1786788019.aa348157/assets/javascripts/openqa.js
--- old/openQA-5.1786629850.d1bdb83d/assets/javascripts/openqa.js       
2026-08-13 16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/assets/javascripts/openqa.js       
2026-08-15 12:00:19.000000000 +0200
@@ -19,8 +19,9 @@
   updateTimeago();
   document.querySelectorAll('[data-bs-toggle="popover"]').forEach(e => new 
bootstrap.Popover(e, {html: true}));
   document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(e => new 
bootstrap.Tooltip(e, {html: true}));
-  $.ajaxSetup({
-    headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}
+
+  window.jQuery?.ajaxSetup({
+    headers: {'X-CSRF-TOKEN': getCSRFToken()}
   });
 }
 
@@ -36,20 +37,36 @@
 }
 
 function makeFlashElement(text) {
-  return typeof text === 'string' ? '<span>' + text + '</span>' : text;
+  if (typeof text === 'string') {
+    const span = document.createElement('span');
+    span.innerHTML = text;
+    return span;
+  }
+  return text;
 }
 
 function addFlash(status, text, container, method = 'append') {
   // add flash messages by default on top of the page
   if (!container) {
-    container = $('#flash-messages');
+    container = document.getElementById('flash-messages');
   }
 
-  const div = $('<div class="alert alert-primary alert-dismissible fade show" 
role="alert"></div>');
-  div.append(makeFlashElement(text));
-  div.append('<button type="button" class="btn-close" data-bs-dismiss="alert" 
aria-label="Close"></button>');
-  div.addClass('alert-' + status);
-  container[method](div);
+  const div = document.createElement('div');
+  div.className = `alert alert-primary alert-dismissible fade show 
alert-${status}`;
+  div.setAttribute('role', 'alert');
+  div.appendChild(makeFlashElement(text));
+  const closeButton = document.createElement('button');
+  closeButton.type = 'button';
+  closeButton.className = 'btn-close';
+  closeButton.setAttribute('data-bs-dismiss', 'alert');
+  closeButton.setAttribute('aria-label', 'Close');
+  div.appendChild(closeButton);
+
+  if (method === 'prepend') {
+    container.prepend(div);
+  } else {
+    container.append(div);
+  }
   return div;
 }
 
@@ -61,21 +78,21 @@
   // update existing flash message
   const existingFlashMessage = window.uniqueFlashMessages[id];
   if (existingFlashMessage) {
-    
existingFlashMessage.find('span').first().replaceWith(makeFlashElement(text));
+    
existingFlashMessage.querySelector('span').replaceWith(makeFlashElement(text));
     return;
   }
 
   const msgElement = addFlash(status, text, container, method);
   window.uniqueFlashMessages[id] = msgElement;
-  msgElement.on('closed.bs.alert', function () {
+  msgElement.addEventListener('closed.bs.alert', function () {
     delete window.uniqueFlashMessages[id];
   });
 }
 
 function toggleChildGroups(link) {
-  const buildRow = $(link).parents('.build-row');
-  buildRow.toggleClass('children-collapsed');
-  buildRow.toggleClass('children-expanded');
+  const buildRow = link.closest('.build-row');
+  buildRow.classList.toggle('children-collapsed');
+  buildRow.classList.toggle('children-expanded');
   return false;
 }
 
@@ -97,8 +114,8 @@
   }
   const search = [];
   const hash = document.location.hash;
-  $.each(params, function (key, values) {
-    $.each(values, function (index, value) {
+  Object.entries(params).forEach(([key, values]) => {
+    values.forEach(value => {
       if (value === undefined) {
         search.push(encodeURIComponent(key));
       } else {
@@ -112,13 +129,13 @@
 function renderDataSize(sizeInByte) {
   let unitFactor = 1073741824; // one GiB
   let sizeWithUnit = 0;
-  $.each([' GiB', ' MiB', ' KiB', ' byte'], function (index, unit) {
+  for (const unit of [' GiB', ' MiB', ' KiB', ' byte']) {
     if (!unitFactor || sizeInByte >= unitFactor) {
       sizeWithUnit = Math.round((sizeInByte / unitFactor) * 100) / 100 + unit;
-      return false;
+      break;
     }
     unitFactor >>= 10;
-  });
+  }
   return sizeWithUnit;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/assets/javascripts/render.js 
new/openQA-5.1786788019.aa348157/assets/javascripts/render.js
--- old/openQA-5.1786629850.d1bdb83d/assets/javascripts/render.js       
2026-08-13 16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/assets/javascripts/render.js       
2026-08-15 12:00:19.000000000 +0200
@@ -121,12 +121,16 @@
   const srcElement = srcUrl ? E('a', [module.name], {href: srcUrl}) : 
E('span', [module.name]);
   const component = E('td', [E('div', [srcElement]), E('div', flags, {class: 
'flags'})], {class: 'component'});
 
-  const result = E('td', [module.result], {class: 'result ' + 
moduleResultCSS(module.result)});
+  const result = E('td', [module.result], {
+    class: 'result ' + moduleResultCSS(module.result),
+    style: 'position: relative'
+  });
   const showPreviewForLink = function () {
     setCurrentPreview($(this).parent()); // show the preview when clicking on 
step links
     return false;
   };
 
+  let hasTextResults = false;
   for (const idx in module.details) {
     const step = module.details[idx];
     const title = step.display_title;
@@ -202,6 +206,7 @@
       box.push(E('span', [content], {class: 'resborder ' + resborder}));
     }
     if (step.text && title !== 'Soft Failed') {
+      hasTextResults = true;
       const stepActions = E('span', [], {class: 'step_actions', style: 'float: 
right'});
       stepActions.innerHTML = renderTemplate(snippets.bug_actions, {MODULE: 
module.name, STEP: step.num});
 
@@ -214,6 +219,7 @@
       const link = E('a', box, {
         class: 'no_hover' + (title === 'wait_serial' ? ' 
serial-result-preview' : ''),
         'data-text': txt,
+        'data-textorig': textData,
         title: title,
         href: href
       });
@@ -237,6 +243,17 @@
     }
   }
 
+  if (hasTextResults) {
+    const expandIcon = E('i', [''], {class: 'fa fa-expand'});
+    const expandButton = E('button', [expandIcon], {
+      class: 'logview_expand_btn',
+      'aria-label': 'Expand row',
+      title: 'Expand row'
+    });
+    expandButton.onclick = () => showTextBoxes(expandButton);
+    result.firstChild.before(expandButton);
+  }
+
   const links = E('td', stepnodes, {class: 'links'});
   return E('tr', [component, result, links], {id: rowid});
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/assets/javascripts/test_result.js 
new/openQA-5.1786788019.aa348157/assets/javascripts/test_result.js
--- old/openQA-5.1786629850.d1bdb83d/assets/javascripts/test_result.js  
2026-08-13 16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/assets/javascripts/test_result.js  
2026-08-15 12:00:19.000000000 +0200
@@ -1,6 +1,8 @@
 // jshint multistr: true
 // jshint esversion: 6
 
+let details_mode = 'default';
+
 const testGitInfoRe = /TEST_GIT_HASH=([a-fA-F0-9]+) 
TEST_GIT_URL=([^\p{Cc}]+)/u;
 
 const testStatus = {
@@ -117,6 +119,13 @@
   // insert and initialize preview data
   pin.html(data);
   pout.insertAfter(stepPreviewContainer);
+  if (details_mode === 'log') {
+    const caretSpace = 15; // .fa-caret-up is positioned bottom: -25px
+    pout.css('top', stepPreviewContainer.position().top + 
stepPreviewContainer.outerHeight() + caretSpace);
+  } else {
+    pout.css('top', '');
+  }
+
   if (!(pin.find('pre').length || pin.find('audio').length)) {
     const imageSource = pin.find('#step_view').data('image');
     if (!imageSource) {
@@ -229,6 +238,13 @@
     stepPreviewContainer.addClass('current_preview');
     setPageHashAccordingToCurrentTab(link.attr('href'));
     const text = unescape(link.data('text'));
+    if (details_mode === 'log') {
+      hidePreviewContainer();
+      const log_container = stepPreviewContainer.get(0).nextElementSibling;
+      log_container.querySelector('div').innerHTML = text;
+      return;
+    }
+
     previewSuccess(stepPreviewContainer, text, force);
     return;
   }
@@ -248,6 +264,46 @@
   });
 }
 
+function showTextBoxes(el) {
+  setCurrentPreview(null);
+  const E = createElement;
+  const currentTd = el.closest('td');
+  const nextTd = currentTd.nextElementSibling;
+  const divs = nextTd.querySelectorAll('div.links_a');
+  divs.forEach(div => {
+    const cl = div.getAttribute('class');
+
+    if (details_mode === 'log') {
+      div.classList.remove('logview');
+    } else {
+      const link = div.querySelector('a');
+      const textData = link.dataset.textorig;
+      if (textData) {
+        const textresult = E('pre', [textData]);
+        const logbox_inner = E('div', [textresult], {class: 'log_container_in 
preview_container_inner'});
+        const logbox = E('div', [logbox_inner], {class: 'log_container_out 
preview_container_outer'});
+        div.after(logbox);
+      }
+      div.classList.add('logview');
+    }
+  });
+  el.firstChild.classList.toggle('fa-expand');
+  el.firstChild.classList.toggle('fa-compress');
+  if (details_mode === 'log') {
+    details_mode = 'default';
+    el.setAttribute('title', 'Expand row');
+    el.setAttribute('aria-lebel', 'Expand row');
+    const logdivs = nextTd.querySelectorAll('div.log_container_out');
+    logdivs.forEach(div => {
+      div.remove();
+    });
+  } else {
+    details_mode = 'log';
+    el.setAttribute('title', 'Collapse row');
+    el.setAttribute('aria-lebel', 'Collapse row');
+  }
+}
+
 function selectPreview(which) {
   const currentPreview = $('.current_preview');
   let linkContainer = currentPreview[which]();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/assets/stylesheets/dashboard.scss 
new/openQA-5.1786788019.aa348157/assets/stylesheets/dashboard.scss
--- old/openQA-5.1786629850.d1bdb83d/assets/stylesheets/dashboard.scss  
2026-08-13 16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/assets/stylesheets/dashboard.scss  
2026-08-15 12:00:19.000000000 +0200
@@ -173,6 +173,9 @@
 #results_filter label {
   vertical-align: top;
 }
+#results td.links {
+  max-width: 0; /* Forces cell to obey overflow rules of inner content */
+}
 .corner-buttons {
   display: inline-block;
   float: right;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/assets/stylesheets/result_preview.scss 
new/openQA-5.1786788019.aa348157/assets/stylesheets/result_preview.scss
--- old/openQA-5.1786629850.d1bdb83d/assets/stylesheets/result_preview.scss     
2026-08-13 16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/assets/stylesheets/result_preview.scss     
2026-08-15 12:00:19.000000000 +0200
@@ -1,13 +1,27 @@
-#preview_container_out {
+.logview_expand_btn {
   position: absolute;
-  z-index: 4;
-  display: none;
-  margin-top: 10px;
+  top: -2px;
+  right: 0;
+  background: transparent;
+  border: none;
+  cursor: pointer;
+  padding: 0;
+  color: grey;
+}
+div.log_container_out {
+  float: left;
+  width: 90%;
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+div.log_container_in {
+  position: relative;
+}
+div.preview_container_outer {
   margin-bottom: 7px;
 }
-#preview_container_in {
+div.preview_container_inner {
   padding: 5px;
-  position: absolute;
   right: 0;
   text-align: center;
   background-color: #f5f5f5;
@@ -36,6 +50,15 @@
     background-color: inherit;
   }
 }
+#preview_container_out {
+  z-index: 4;
+  position: absolute;
+  display: none;
+  margin-top: 10px;
+}
+#preview_container_in {
+  position: absolute;
+}
 [data-bs-theme='dark'] #preview_container_in {
   background-color: #0a0a0a;
 }
@@ -46,7 +69,11 @@
   color: $default-font-color-dark;
   background-color: $default-bg-color-dark;
 }
-.links > div {
+.links > div.logview {
+  clear: left;
+  float: left;
+}
+.links > div.links_a {
   display: inline-block;
   margin-top: 3px;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/contrib/agama-openqa-worker.jsonnet 
new/openQA-5.1786788019.aa348157/contrib/agama-openqa-worker.jsonnet
--- old/openQA-5.1786629850.d1bdb83d/contrib/agama-openqa-worker.jsonnet        
2026-08-13 16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/contrib/agama-openqa-worker.jsonnet        
2026-08-15 12:00:19.000000000 +0200
@@ -13,28 +13,38 @@
   std.filter(function(d) d.logicalname != os_disk, disks_with_size)
 );
 
-// Helper function to create a unique, safe alias from the device name (e.g., 
"/dev/sdb" -> "raid-sdb")
+// Helper function to create a unique, safe alias from the device name
 local raid_alias = function(dev_name) "raid-" + std.strReplace(dev_name, 
"/dev/", "");
 
+// Check if we actually have enough extra disks to form a RAID 0
+local has_enough_disks_for_raid = std.length(extra_disks) >= 2;
+
 // 1. Build the OS drive config
 local os_drive_config = if os_disk != null then [{
   search: os_disk,
-  partitions: [{ search: '*', delete: true }, { generate: 'default' }],
+  partitions: [{ search: {}, delete: true }, { generate: 'default' }],
 }] else [];
 
 // 2. Build the extra drives config dynamically
-// Omitting 'size' tells Agama to use the maximum available space on the disk 
for the partition.
 local extra_drives_config = std.map(
   function(disk) {
     search: disk,
-    partitions: [{ search: '*', delete: true }, { alias: raid_alias(disk) }] 
+    ptableType: 'gpt',
+    partitions: [
+      { search: {}, delete: true },
+      // If we have 2+ disks, prep them for RAID. Otherwise, prep as a 
standard Linux partition.
+      if has_enough_disks_for_raid then
+        { alias: raid_alias(disk), id: 'raid' }
+      else
+        { id: 'linux' }
+    ]
   },
   extra_disks
 );
 
-// 3. Build the mdRaids config using the generated aliases
+// 3. Build the mdRaids config ONLY if we have at least 2 disks
 local mdraids =
-  if std.length(extra_disks) > 0 then
+  if has_enough_disks_for_raid then
     [{
       devices: std.map(raid_alias, extra_disks),
       level: "raid0",
@@ -47,8 +57,8 @@
     id: 'openSUSE_Leap'
   },
   storage: {
-      // Concatenate the OS drive and the dynamically generated extra drives
       drives: os_drive_config + extra_drives_config,
+      // If mdraids is empty, Agama will just ignore it safely
       mdRaids: mdraids
   },
   localization: {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/lib/OpenQA/WebAPI/Controller/Admin/JobTemplate.pm
 
new/openQA-5.1786788019.aa348157/lib/OpenQA/WebAPI/Controller/Admin/JobTemplate.pm
--- 
old/openQA-5.1786629850.d1bdb83d/lib/OpenQA/WebAPI/Controller/Admin/JobTemplate.pm
  2026-08-13 16:04:10.000000000 +0200
+++ 
new/openQA-5.1786788019.aa348157/lib/OpenQA/WebAPI/Controller/Admin/JobTemplate.pm
  2026-08-15 12:00:19.000000000 +0200
@@ -9,20 +9,11 @@
     my $group = $schema->resultset('JobGroups')->find($self->param('groupid'));
     return $self->reply->not_found unless $group;
 
-    my $yaml = $group->template;
-    my $force_yaml_editor
-      = defined $yaml || $schema->resultset('JobTemplates')->search({group_id 
=> $group->id}, {rows => 1})->count == 0;
     $self->stash(
         group => $group,
-        yaml_template => $yaml,
-        force_yaml_editor => $force_yaml_editor,
+        yaml_template => $group->template,
     );
 
-    my @machines = $schema->resultset('Machines')->search(undef, {order_by => 
'name'});
-    $self->stash(machines => \@machines);
-    my @tests = $schema->resultset('TestSuites')->search(undef, {order_by => 
'name'});
-    $self->stash(tests => \@tests);
-
     $self->render('admin/job_template/index');
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1786629850.d1bdb83d/t/ui/13-admin.t 
new/openQA-5.1786788019.aa348157/t/ui/13-admin.t
--- old/openQA-5.1786629850.d1bdb83d/t/ui/13-admin.t    2026-08-13 
16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/t/ui/13-admin.t    2026-08-15 
12:00:19.000000000 +0200
@@ -494,10 +494,8 @@
     my ($yaml, $form);
     subtest 'open YAML editor for legacy group' => sub {
         $driver->get('/admin/job_templates/1001');
-        $form = $driver->find_element_by_id('editor-form');
-        ok $form->is_hidden(), 'editor form is not shown by default';
-        $driver->find_element_by_id('toggle-yaml-editor')->click();
         wait_for_ajax;
+        $form = $driver->find_element_by_id('editor-form');
         ok $form->is_displayed(), 'editor form is shown';
         ok $form->child('.progress-indication')->is_hidden(), 'spinner is 
hidden';
         $yaml = $driver->execute_script('return editor.getValue();');
@@ -560,8 +558,8 @@
       or always_explain $result->get_text();
 
     # Legacy UI is hidden and no longer available
-    ok $driver->find_element_by_id('toggle-yaml-editor')->is_hidden(), 'editor 
toggle hidden';
-    ok $driver->find_element_by_id('media')->is_hidden(), 'media editor 
hidden';
+    is scalar @{$driver->find_elements('toggle-yaml-editor', 'id')}, 0, 
'editor toggle not present';
+    is scalar @{$driver->find_elements('media', 'id')}, 0, 'media editor not 
present';
 
     # More changes on top of the previous ones
     $yaml .= "    - advanced_kde_high_prio:\n";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/templates/webapi/admin/job_template/index.html.ep
 
new/openQA-5.1786788019.aa348157/templates/webapi/admin/job_template/index.html.ep
--- 
old/openQA-5.1786629850.d1bdb83d/templates/webapi/admin/job_template/index.html.ep
  2026-08-13 16:04:10.000000000 +0200
+++ 
new/openQA-5.1786788019.aa348157/templates/webapi/admin/job_template/index.html.ep
  2026-08-15 12:00:19.000000000 +0200
@@ -6,41 +6,15 @@
 
 % title 'Job templates for ' . $group->name;
 
-% unless ($force_yaml_editor) {
-    <div class="alert alert-danger">
-        The old job group view is deprecated and will be removed from
-        future versions of openQA. Please save the job templates in YAML
-        format as soon as possible.
-    </div>
-% }
-
 % content_for 'ready_function' => begin
     user_is_admin = <%= is_admin_js %>;
-    % if ($force_yaml_editor) {
-        toggleTemplateEditor();
-    % }
-    % else {
-        setupJobTemplates("<%= url_for('apiv1_job_templates') %>", <%= 
$group->id %>);
-    % }
+    setupTemplateEditor();
     $('#expand-template').click(function() { submitTemplateEditor('expand'); 
});
     $('#preview-template').click(function() { submitTemplateEditor('preview'); 
});
     $('#save-template').click(function() { submitTemplateEditor('save'); });
 % end
 
         <form action="<%= url_for('admin_groups') %>" class="corner-buttons">
-            % if (!$force_yaml_editor) {
-            <button type="button" id="toggle-yaml-editor" class="btn 
btn-light" onclick="toggleTemplateEditor();">
-                <span>
-                    <i class="fa-solid fa-pen-to-square"></i>
-                    % if (is_admin) {
-                        Edit YAML
-                    % }
-                    % else {
-                        Show YAML
-                    % }
-                </span>
-            </button>
-            % }
             <button type="button" id="toggle-group-properties" class="btn 
btn-light" onclick="toggleEdit();">
                 <span>
                     <i class="fa-solid fa-pen-to-square"></i>
@@ -74,30 +48,6 @@
             <a 
href="https://open.qa/docs/#using-job-templates-to-automate-jobs-creation"; 
target="blank">the documentation</a>
             for more details.
         </p>
-        % if (!$force_yaml_editor) {
-            <div id="media">
-                <p id="loading"><i class="fa-solid fa-spinner fa-spin"></i> 
Loading…</p>
-
-                <select id="machines-template" multiple="true" disabled 
data-placeholder="None" style="display: none">
-                    % for my $machine (@$machines) {
-                        <option value="<%= $machine->name %>"
-                                data-machine-id="<%= $machine->id %>" >
-                            %= $machine->name
-                        </option>
-                    % }
-                </select>
-
-                <select id="tests-template" disabled style="display: none">
-                    <option value="">Select…</option>
-                    % for my $test (@$tests) {
-                        <option value="<%= $test->name %>" data-test-id="<%= 
$test->id %>">
-                            %= $test->name
-                        </option>
-                    % }
-                </select>
-
-            </div>
-        % }
         <form action="#" id="editor-form" class="form-horizontal" 
style="display: none;"
               data-put-url="<%= url_for('apiv1_job_templates_schedules' => (id 
=> $group->id)) %>" data-reference="<%= $yaml_template %>">
             <div class="row">
@@ -204,9 +154,3 @@
                 </div>
             </div>
         </form>
-
-        % if (!$force_yaml_editor && is_admin) {
-            <p>
-                <i class="fa-solid fa-plus-square"></i> Please save as YAML to 
add new medium as part of this group
-            </p>
-        % }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openQA-5.1786629850.d1bdb83d/templates/webapi/test/result.html.ep 
new/openQA-5.1786788019.aa348157/templates/webapi/test/result.html.ep
--- old/openQA-5.1786629850.d1bdb83d/templates/webapi/test/result.html.ep       
2026-08-13 16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/templates/webapi/test/result.html.ep       
2026-08-15 12:00:19.000000000 +0200
@@ -100,7 +100,7 @@
     </div>
 </div>
 
-<div id="preview_container_out">
-    <div id="preview_container_in" class="well well-lg">
+<div id="preview_container_out" class="preview_container_outer">
+    <div id="preview_container_in" class="well well-lg 
preview_container_inner">
     </div>
 </div>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openQA-5.1786629850.d1bdb83d/tools/ci/autoinst.sha 
new/openQA-5.1786788019.aa348157/tools/ci/autoinst.sha
--- old/openQA-5.1786629850.d1bdb83d/tools/ci/autoinst.sha      2026-08-13 
16:04:10.000000000 +0200
+++ new/openQA-5.1786788019.aa348157/tools/ci/autoinst.sha      2026-08-15 
12:00:19.000000000 +0200
@@ -1 +1 @@
-5.044000-93ba8ca76e07943f6f7c9873a02a87ecd7a483fc
\ No newline at end of file
+5.044000-b29247340708d3e6224cc2dad478bc7290c7ecf0
\ No newline at end of file

++++++ openQA.obsinfo ++++++
--- /var/tmp/diff_new_pack.7eZTd5/_old  2026-08-17 17:02:30.758493892 +0200
+++ /var/tmp/diff_new_pack.7eZTd5/_new  2026-08-17 17:02:30.766494174 +0200
@@ -1,5 +1,5 @@
 name: openQA
-version: 5.1786629850.d1bdb83d
-mtime: 1786629850
-commit: d1bdb83db24dcca85d541d11a9035a98f665d53a
+version: 5.1786788019.aa348157
+mtime: 1786788019
+commit: aa348157e5888e5e9ef30dc62039623d7ed9a7cb
 

Reply via email to