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-14 18:49:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openQA (Old) and /work/SRC/openSUSE:Factory/.openQA.new.3698736 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openQA" Wed Oct 14 18:49:05 2026 rev:889 rq:1384806 version:5.1791966007.170875a4 Changes: -------- --- /work/SRC/openSUSE:Factory/openQA/openQA.changes 2026-10-12 22:08:02.649365282 +0200 +++ /work/SRC/openSUSE:Factory/.openQA.new.3698736/openQA.changes 2026-10-14 18:49:24.289815699 +0200 @@ -1,0 +2,20 @@ +Wed Oct 14 10:31:51 UTC 2026 - [email protected] + +- Update to version 5.1791966007.170875a4: + * fix(manpages): Remove encoding workaround + * chore(deps): bump helm/kind-action (#7943) + * chore(deps-dev): bump @humanfs/node from 0.16.7 to 0.16.8 + * chore(deps): Dependency cron 2026-10-13 + * feat: allow custom developer mode connection hint per worker + * ci(mergify): adjust expected checks after openQA-devel-test move + * feat(overview): Avoid redirect when doing special job restarts + * feat: highlight deleted primary match needles in webUI + +------------------------------------------------------------------- +Mon Oct 12 17:54:25 UTC 2026 - [email protected] + +- Update to version 5.1791822848.9b0ae67e: + * feat(ui): Fix filter hydration and add clear filter button + * feat: Add RSS feed for job groups + +------------------------------------------------------------------- Old: ---- openQA-5.1791790842.db5f7862.obscpio New: ---- openQA-5.1791966007.170875a4.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openQA-client-test.spec ++++++ --- /var/tmp/diff_new_pack.WQYcOB/_old 2026-10-14 18:49:29.535035264 +0200 +++ /var/tmp/diff_new_pack.WQYcOB/_new 2026-10-14 18:49:29.538035389 +0200 @@ -18,7 +18,7 @@ %define short_name openQA-client Name: %{short_name}-test -Version: 5.1791790842.db5f7862 +Version: 5.1791966007.170875a4 Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA-test.spec ++++++ --- /var/tmp/diff_new_pack.WQYcOB/_old 2026-10-14 18:49:29.572036812 +0200 +++ /var/tmp/diff_new_pack.WQYcOB/_new 2026-10-14 18:49:29.574036896 +0200 @@ -18,7 +18,7 @@ %define short_name openQA Name: %{short_name}-test -Version: 5.1791790842.db5f7862 +Version: 5.1791966007.170875a4 Release: 0 Summary: Test package for openQA License: GPL-2.0-or-later ++++++ openQA-worker-test.spec ++++++ --- /var/tmp/diff_new_pack.WQYcOB/_old 2026-10-14 18:49:29.611038445 +0200 +++ /var/tmp/diff_new_pack.WQYcOB/_new 2026-10-14 18:49:29.614038571 +0200 @@ -18,7 +18,7 @@ %define short_name openQA-worker Name: %{short_name}-test -Version: 5.1791790842.db5f7862 +Version: 5.1791966007.170875a4 Release: 0 Summary: Test package for %{short_name} License: GPL-2.0-or-later ++++++ openQA.spec ++++++ --- /var/tmp/diff_new_pack.WQYcOB/_old 2026-10-14 18:49:29.652040161 +0200 +++ /var/tmp/diff_new_pack.WQYcOB/_new 2026-10-14 18:49:29.653040203 +0200 @@ -104,7 +104,7 @@ %define devel_requires %devel_no_selenium_requires chromedriver Name: openQA -Version: 5.1791790842.db5f7862 +Version: 5.1791966007.170875a4 Release: 0 Summary: Framework for automated system-level testing (web-frontend, scheduler and tools) Group: Development/Tools/Other ++++++ node_modules.obscpio ++++++ Binary files old/@humanfs-core-0.19.1.tgz and new/@humanfs-core-0.19.1.tgz differ Binary files old/@humanfs-core-0.19.2.tgz and new/@humanfs-core-0.19.2.tgz differ Binary files old/@humanfs-node-0.16.7.tgz and new/@humanfs-node-0.16.7.tgz differ Binary files old/@humanfs-node-0.16.8.tgz and new/@humanfs-node-0.16.8.tgz differ Binary files old/@humanfs-types-0.15.0.tgz and new/@humanfs-types-0.15.0.tgz differ ++++++ node_modules.spec.inc ++++++ --- /var/tmp/diff_new_pack.WQYcOB/_old 2026-10-14 18:49:30.723084995 +0200 +++ /var/tmp/diff_new_pack.WQYcOB/_new 2026-10-14 18:49:30.737085581 +0200 @@ -18,237 +18,238 @@ Source1017: https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz#/@eslint-object-schema-3.0.5.tgz Source1018: https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz#/@eslint-plugin-kit-0.7.2.tgz Source1019: https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz#/@fortawesome-fontawesome-free-6.7.2.tgz -Source1020: https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz#/@humanfs-core-0.19.1.tgz -Source1021: https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz#/@humanfs-node-0.16.7.tgz -Source1022: https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#/@humanwhocodes-module-importer-1.0.1.tgz -Source1023: https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz#/@humanwhocodes-retry-0.4.3.tgz -Source1024: https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz#/@keyv-bigmap-1.3.1.tgz -Source1025: https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz#/@keyv-serialize-1.1.1.tgz -Source1026: https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#/@nodelib-fs.scandir-2.1.5.tgz -Source1027: https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#/@nodelib-fs.stat-2.0.5.tgz -Source1028: https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#/@nodelib-fs.walk-1.2.8.tgz -Source1029: https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz#/@pkgr-core-0.3.6.tgz -Source1030: https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz#/@popperjs-core-2.11.8.tgz -Source1031: https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz#/@sindresorhus-merge-streams-4.0.0.tgz -Source1032: https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-5.1.0.tgz#/@stylistic-stylelint-plugin-5.1.0.tgz -Source1033: https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz#/@types-esrecurse-4.3.1.tgz -Source1034: https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz#/@types-estree-1.0.9.tgz -Source1035: https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz#/@types-json-schema-7.0.15.tgz -Source1036: https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.6.tgz#/ace-builds-1.43.6.tgz -Source1037: https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz#/acorn-8.16.0.tgz -Source1038: https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#/acorn-jsx-5.3.2.tgz -Source1039: https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz#/ajv-6.14.0.tgz -Source1040: https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz#/ajv-8.18.0.tgz -Source1041: https://registry.npmjs.org/anser/-/anser-2.3.5.tgz#/anser-2.3.5.tgz -Source1042: https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#/ansi-regex-5.0.1.tgz -Source1043: https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz#/ansi-regex-6.2.2.tgz -Source1044: https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#/ansi-styles-4.3.0.tgz -Source1045: https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#/argparse-2.0.1.tgz -Source1046: https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz#/astral-regex-2.0.0.tgz -Source1047: https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz#/balanced-match-4.0.4.tgz -Source1048: https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz#/bootstrap-5.3.8.tgz -Source1049: https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz#/brace-expansion-5.0.7.tgz -Source1050: https://registry.npmjs.org/braces/-/braces-3.0.3.tgz#/braces-3.0.3.tgz -Source1051: https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz#/cacheable-2.5.0.tgz -Source1052: https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#/callsites-3.1.0.tgz -Source1053: https://registry.npmjs.org/chosen-js/-/chosen-js-1.8.7.tgz#/chosen-js-1.8.7.tgz -Source1054: https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#/color-convert-2.0.1.tgz -Source1055: https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#/color-name-1.1.4.tgz -Source1056: https://registry.npmjs.org/colord/-/colord-2.9.3.tgz#/colord-2.9.3.tgz -Source1057: https://registry.npmjs.org/commander/-/commander-7.2.0.tgz#/commander-7.2.0.tgz -Source1058: https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz#/cosmiconfig-9.0.2.tgz -Source1059: https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz#/cross-spawn-7.0.6.tgz -Source1060: https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz#/css-functions-list-3.3.3.tgz -Source1061: https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz#/css-tree-3.2.1.tgz -Source1062: https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#/cssesc-3.0.0.tgz -Source1063: https://registry.npmjs.org/d3/-/d3-7.9.0.tgz#/d3-7.9.0.tgz -Source1064: https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz#/d3-array-3.2.4.tgz -Source1065: https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz#/d3-axis-3.0.0.tgz -Source1066: https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz#/d3-brush-3.0.0.tgz -Source1067: https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz#/d3-chord-3.0.1.tgz -Source1068: https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz#/d3-color-3.1.0.tgz -Source1069: https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz#/d3-contour-4.0.2.tgz -Source1070: https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz#/d3-delaunay-6.0.4.tgz -Source1071: https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz#/d3-dispatch-3.0.1.tgz -Source1072: https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz#/d3-drag-3.0.0.tgz -Source1073: https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz#/d3-dsv-3.0.1.tgz -Source1074: https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz#/d3-ease-3.0.1.tgz -Source1075: https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz#/d3-fetch-3.0.1.tgz -Source1076: https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz#/d3-force-3.0.0.tgz -Source1077: https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz#/d3-format-3.1.2.tgz -Source1078: https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz#/d3-geo-3.1.1.tgz -Source1079: https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#/d3-hierarchy-3.1.2.tgz -Source1080: https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz#/d3-interpolate-3.0.1.tgz -Source1081: https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz#/d3-path-3.1.0.tgz -Source1082: https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz#/d3-polygon-3.0.1.tgz -Source1083: https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz#/d3-quadtree-3.0.1.tgz -Source1084: https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz#/d3-random-3.0.1.tgz -Source1085: https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz#/d3-scale-4.0.2.tgz -Source1086: https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#/d3-scale-chromatic-3.1.0.tgz -Source1087: https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz#/d3-selection-3.0.0.tgz -Source1088: https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz#/d3-shape-3.2.0.tgz -Source1089: https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz#/d3-time-3.1.0.tgz -Source1090: https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz#/d3-time-format-4.1.0.tgz -Source1091: https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz#/d3-timer-3.0.1.tgz -Source1092: https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz#/d3-transition-3.0.1.tgz -Source1093: https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz#/d3-zoom-3.0.0.tgz -Source1094: https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz#/dagre-0.8.5.tgz -Source1095: https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz#/dagre-d3-0.6.4.tgz -Source1096: https://registry.npmjs.org/datatables.net/-/datatables.net-2.3.7.tgz#/datatables.net-2.3.7.tgz -Source1097: https://registry.npmjs.org/datatables.net-bs5/-/datatables.net-bs5-2.3.7.tgz#/datatables.net-bs5-2.3.7.tgz -Source1098: https://registry.npmjs.org/debug/-/debug-4.4.3.tgz#/debug-4.4.3.tgz -Source1099: https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#/deep-is-0.1.4.tgz -Source1100: https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz#/delaunator-5.1.0.tgz -Source1101: https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#/emoji-regex-8.0.0.tgz -Source1102: https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz#/env-paths-2.2.1.tgz -Source1103: https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz#/error-ex-1.3.4.tgz -Source1104: https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#/escape-string-regexp-4.0.0.tgz -Source1105: https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz#/eslint-10.2.1.tgz -Source1106: https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz#/eslint-config-prettier-10.1.8.tgz -Source1107: https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz#/eslint-plugin-prettier-5.5.5.tgz -Source1108: https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz#/eslint-scope-9.1.2.tgz -Source1109: https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#/eslint-visitor-keys-3.4.3.tgz -Source1110: https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#/eslint-visitor-keys-5.0.1.tgz -Source1111: https://registry.npmjs.org/espree/-/espree-11.2.0.tgz#/espree-11.2.0.tgz -Source1112: https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz#/esquery-1.7.0.tgz -Source1113: https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz#/esrecurse-4.3.0.tgz -Source1114: https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz#/estraverse-5.3.0.tgz -Source1115: https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#/esutils-2.0.3.tgz -Source1116: https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#/fast-deep-equal-3.1.3.tgz -Source1117: https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz#/fast-diff-1.3.0.tgz -Source1118: https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz#/fast-glob-3.3.3.tgz -Source1119: https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#/fast-json-stable-stringify-2.1.0.tgz -Source1120: https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#/fast-levenshtein-2.0.6.tgz -Source1121: https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz#/fast-uri-3.1.7.tgz -Source1122: https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#/fastest-levenshtein-1.0.16.tgz -Source1123: https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz#/fastq-1.20.1.tgz -Source1124: https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz#/file-entry-cache-11.1.5.tgz -Source1125: https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz#/file-entry-cache-8.0.0.tgz -Source1126: https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz#/fill-range-7.1.1.tgz -Source1127: https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz#/find-up-5.0.0.tgz -Source1128: https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz#/flat-cache-4.0.1.tgz -Source1129: https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz#/flat-cache-6.1.23.tgz -Source1130: https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz#/flatted-3.4.2.tgz -Source1131: https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz#/get-east-asian-width-1.6.0.tgz -Source1132: https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#/glob-parent-5.1.2.tgz -Source1133: https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz#/glob-parent-6.0.2.tgz -Source1134: https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz#/global-modules-2.0.0.tgz -Source1135: https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz#/global-prefix-3.0.0.tgz -Source1136: https://registry.npmjs.org/globals/-/globals-17.4.0.tgz#/globals-17.4.0.tgz -Source1137: https://registry.npmjs.org/globby/-/globby-16.2.2.tgz#/globby-16.2.2.tgz -Source1138: https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz#/globjoin-0.1.4.tgz -Source1139: https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz#/graphlib-2.1.8.tgz -Source1140: https://registry.npmjs.org/has-flag/-/has-flag-5.0.1.tgz#/has-flag-5.0.1.tgz -Source1141: https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz#/hashery-1.5.1.tgz -Source1142: https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz#/hookified-1.15.1.tgz -Source1143: https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz#/hookified-2.2.0.tgz -Source1144: https://registry.npmjs.org/html-tags/-/html-tags-5.1.0.tgz#/html-tags-5.1.0.tgz -Source1145: https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz#/iconv-lite-0.6.3.tgz -Source1146: https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz#/ignore-5.3.2.tgz -Source1147: https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz#/ignore-7.0.5.tgz -Source1148: https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz#/import-fresh-3.3.1.tgz -Source1149: https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz#/import-meta-resolve-4.2.0.tgz -Source1150: https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#/imurmurhash-0.1.4.tgz -Source1151: https://registry.npmjs.org/ini/-/ini-1.3.8.tgz#/ini-1.3.8.tgz -Source1152: https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz#/internmap-2.0.3.tgz -Source1153: https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz#/is-arrayish-0.2.1.tgz -Source1154: https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#/is-extglob-2.1.1.tgz -Source1155: https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#/is-fullwidth-code-point-3.0.0.tgz -Source1156: https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz#/is-glob-4.0.3.tgz -Source1157: https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#/is-number-7.0.0.tgz -Source1158: https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz#/is-path-inside-4.0.0.tgz -Source1159: https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz#/is-plain-object-5.0.0.tgz -Source1160: https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#/isexe-2.0.0.tgz -Source1161: https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz#/jquery-3.7.1.tgz -Source1162: https://registry.npmjs.org/jquery/-/jquery-4.0.0.tgz#/jquery-4.0.0.tgz -Source1163: https://registry.npmjs.org/jquery-ujs/-/jquery-ujs-1.2.3.tgz#/jquery-ujs-1.2.3.tgz -Source1164: https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#/js-tokens-4.0.0.tgz -Source1165: https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz#/js-yaml-4.3.2.tgz -Source1166: https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz#/json-buffer-3.0.1.tgz -Source1167: https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#/json-parse-even-better-errors-2.3.1.tgz -Source1168: https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#/json-schema-traverse-0.4.1.tgz -Source1169: https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#/json-schema-traverse-1.0.0.tgz -Source1170: https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#/json-stable-stringify-without-jsonify-1.0.1.tgz -Source1171: https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz#/keyv-4.5.4.tgz -Source1172: https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz#/keyv-5.6.0.tgz -Source1173: https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz#/kind-of-6.0.3.tgz -Source1174: https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz#/known-css-properties-0.37.0.tgz -Source1175: https://registry.npmjs.org/levn/-/levn-0.4.1.tgz#/levn-0.4.1.tgz -Source1176: https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz#/lines-and-columns-1.2.4.tgz -Source1177: https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz#/locate-path-6.0.0.tgz -Source1178: https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz#/lodash-4.18.1.tgz -Source1179: https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz#/lodash.truncate-4.4.2.tgz -Source1180: https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-4.0.0.tgz#/mathml-tag-names-4.0.0.tgz -Source1181: https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz#/mdn-data-2.27.1.tgz -Source1182: https://registry.npmjs.org/meow/-/meow-14.1.0.tgz#/meow-14.1.0.tgz -Source1183: https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz#/merge2-1.4.1.tgz -Source1184: https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz#/micromatch-4.0.8.tgz -Source1185: https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz#/minimatch-10.2.4.tgz -Source1186: https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#/ms-2.1.3.tgz -Source1187: https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz#/nanoid-3.3.16.tgz -Source1188: https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#/natural-compare-1.4.0.tgz -Source1189: https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#/normalize-path-3.0.0.tgz -Source1190: https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz#/optionator-0.9.4.tgz -Source1191: https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz#/p-limit-3.1.0.tgz -Source1192: https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz#/p-locate-5.0.0.tgz -Source1193: https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz#/parent-module-1.0.1.tgz -Source1194: https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz#/parse-json-5.2.0.tgz -Source1195: https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#/path-exists-4.0.0.tgz -Source1196: https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz#/path-key-3.1.1.tgz -Source1197: https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz#/picocolors-1.1.1.tgz -Source1198: https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz#/picomatch-2.3.2.tgz -Source1199: https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz#/postcss-8.5.23.tgz -Source1200: https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#/postcss-media-query-parser-0.2.3.tgz -Source1201: https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz#/postcss-resolve-nested-selector-0.1.6.tgz -Source1202: https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz#/postcss-safe-parser-7.0.1.tgz -Source1203: https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz#/postcss-scss-4.0.9.tgz -Source1204: https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz#/postcss-selector-parser-7.1.4.tgz -Source1205: https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#/postcss-value-parser-4.2.0.tgz -Source1206: https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#/prelude-ls-1.2.1.tgz -Source1207: https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz#/prettier-3.9.6.tgz -Source1208: https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz#/prettier-linter-helpers-1.0.1.tgz -Source1209: https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz#/punycode-2.3.1.tgz -Source1210: https://registry.npmjs.org/qified/-/qified-0.10.1.tgz#/qified-0.10.1.tgz -Source1211: https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz#/queue-microtask-1.2.3.tgz -Source1212: https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz#/require-from-string-2.0.2.tgz -Source1213: https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz#/resolve-from-4.0.0.tgz -Source1214: https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz#/reusify-1.1.0.tgz -Source1215: https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz#/robust-predicates-3.0.2.tgz -Source1216: https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz#/run-parallel-1.2.0.tgz -Source1217: https://registry.npmjs.org/rw/-/rw-1.3.3.tgz#/rw-1.3.3.tgz -Source1218: https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#/safer-buffer-2.1.2.tgz -Source1219: https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz#/shebang-command-2.0.0.tgz -Source1220: https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz#/shebang-regex-3.0.0.tgz -Source1221: https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz#/signal-exit-4.1.0.tgz -Source1222: https://registry.npmjs.org/slash/-/slash-5.1.0.tgz#/slash-5.1.0.tgz -Source1223: https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz#/slice-ansi-4.0.0.tgz -Source1224: https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz#/source-map-js-1.2.1.tgz -Source1225: https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#/string-width-4.2.3.tgz -Source1226: https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz#/string-width-8.2.2.tgz -Source1227: https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#/strip-ansi-6.0.1.tgz -Source1228: https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz#/strip-ansi-7.2.0.tgz -Source1229: https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz#/style-search-0.1.0.tgz -Source1230: https://registry.npmjs.org/stylelint/-/stylelint-17.14.1.tgz#/stylelint-17.14.1.tgz -Source1231: https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-18.0.0.tgz#/stylelint-config-recommended-18.0.0.tgz -Source1232: https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-17.0.0.tgz#/stylelint-config-recommended-scss-17.0.0.tgz -Source1233: https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-40.0.0.tgz#/stylelint-config-standard-40.0.0.tgz -Source1234: https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-17.0.0.tgz#/stylelint-config-standard-scss-17.0.0.tgz -Source1235: https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.3.tgz#/stylelint-prettier-5.0.3.tgz -Source1236: https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-7.0.0.tgz#/stylelint-scss-7.0.0.tgz -Source1237: https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz#/supports-color-10.2.2.tgz -Source1238: https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-4.5.0.tgz#/supports-hyperlinks-4.5.0.tgz -Source1239: https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz#/svg-tags-1.0.0.tgz -Source1240: https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz#/synckit-0.11.13.tgz -Source1241: https://registry.npmjs.org/table/-/table-6.9.0.tgz#/table-6.9.0.tgz -Source1242: https://registry.npmjs.org/timeago.js/-/timeago.js-4.0.2.tgz#/timeago.js-4.0.2.tgz -Source1243: https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#/to-regex-range-5.0.1.tgz -Source1244: https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz#/type-check-0.4.0.tgz -Source1245: https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz#/unicorn-magic-0.4.0.tgz -Source1246: https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#/uri-js-4.4.1.tgz -Source1247: https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#/util-deprecate-1.0.2.tgz -Source1248: https://registry.npmjs.org/which/-/which-1.3.1.tgz#/which-1.3.1.tgz -Source1249: https://registry.npmjs.org/which/-/which-2.0.2.tgz#/which-2.0.2.tgz -Source1250: https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz#/word-wrap-1.2.5.tgz -Source1251: https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz#/write-file-atomic-7.0.1.tgz -Source1252: https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#/yocto-queue-0.1.0.tgz +Source1020: https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz#/@humanfs-core-0.19.2.tgz +Source1021: https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz#/@humanfs-node-0.16.8.tgz +Source1022: https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz#/@humanfs-types-0.15.0.tgz +Source1023: https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#/@humanwhocodes-module-importer-1.0.1.tgz +Source1024: https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz#/@humanwhocodes-retry-0.4.3.tgz +Source1025: https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz#/@keyv-bigmap-1.3.1.tgz +Source1026: https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz#/@keyv-serialize-1.1.1.tgz +Source1027: https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#/@nodelib-fs.scandir-2.1.5.tgz +Source1028: https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#/@nodelib-fs.stat-2.0.5.tgz +Source1029: https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#/@nodelib-fs.walk-1.2.8.tgz +Source1030: https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz#/@pkgr-core-0.3.6.tgz +Source1031: https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz#/@popperjs-core-2.11.8.tgz +Source1032: https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz#/@sindresorhus-merge-streams-4.0.0.tgz +Source1033: https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-5.1.0.tgz#/@stylistic-stylelint-plugin-5.1.0.tgz +Source1034: https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz#/@types-esrecurse-4.3.1.tgz +Source1035: https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz#/@types-estree-1.0.9.tgz +Source1036: https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz#/@types-json-schema-7.0.15.tgz +Source1037: https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.6.tgz#/ace-builds-1.43.6.tgz +Source1038: https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz#/acorn-8.16.0.tgz +Source1039: https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#/acorn-jsx-5.3.2.tgz +Source1040: https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz#/ajv-6.14.0.tgz +Source1041: https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz#/ajv-8.18.0.tgz +Source1042: https://registry.npmjs.org/anser/-/anser-2.3.5.tgz#/anser-2.3.5.tgz +Source1043: https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#/ansi-regex-5.0.1.tgz +Source1044: https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz#/ansi-regex-6.2.2.tgz +Source1045: https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#/ansi-styles-4.3.0.tgz +Source1046: https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#/argparse-2.0.1.tgz +Source1047: https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz#/astral-regex-2.0.0.tgz +Source1048: https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz#/balanced-match-4.0.4.tgz +Source1049: https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz#/bootstrap-5.3.8.tgz +Source1050: https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz#/brace-expansion-5.0.7.tgz +Source1051: https://registry.npmjs.org/braces/-/braces-3.0.3.tgz#/braces-3.0.3.tgz +Source1052: https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz#/cacheable-2.5.0.tgz +Source1053: https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#/callsites-3.1.0.tgz +Source1054: https://registry.npmjs.org/chosen-js/-/chosen-js-1.8.7.tgz#/chosen-js-1.8.7.tgz +Source1055: https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#/color-convert-2.0.1.tgz +Source1056: https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#/color-name-1.1.4.tgz +Source1057: https://registry.npmjs.org/colord/-/colord-2.9.3.tgz#/colord-2.9.3.tgz +Source1058: https://registry.npmjs.org/commander/-/commander-7.2.0.tgz#/commander-7.2.0.tgz +Source1059: https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz#/cosmiconfig-9.0.2.tgz +Source1060: https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz#/cross-spawn-7.0.6.tgz +Source1061: https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz#/css-functions-list-3.3.3.tgz +Source1062: https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz#/css-tree-3.2.1.tgz +Source1063: https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#/cssesc-3.0.0.tgz +Source1064: https://registry.npmjs.org/d3/-/d3-7.9.0.tgz#/d3-7.9.0.tgz +Source1065: https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz#/d3-array-3.2.4.tgz +Source1066: https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz#/d3-axis-3.0.0.tgz +Source1067: https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz#/d3-brush-3.0.0.tgz +Source1068: https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz#/d3-chord-3.0.1.tgz +Source1069: https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz#/d3-color-3.1.0.tgz +Source1070: https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz#/d3-contour-4.0.2.tgz +Source1071: https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz#/d3-delaunay-6.0.4.tgz +Source1072: https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz#/d3-dispatch-3.0.1.tgz +Source1073: https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz#/d3-drag-3.0.0.tgz +Source1074: https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz#/d3-dsv-3.0.1.tgz +Source1075: https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz#/d3-ease-3.0.1.tgz +Source1076: https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz#/d3-fetch-3.0.1.tgz +Source1077: https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz#/d3-force-3.0.0.tgz +Source1078: https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz#/d3-format-3.1.2.tgz +Source1079: https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz#/d3-geo-3.1.1.tgz +Source1080: https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#/d3-hierarchy-3.1.2.tgz +Source1081: https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz#/d3-interpolate-3.0.1.tgz +Source1082: https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz#/d3-path-3.1.0.tgz +Source1083: https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz#/d3-polygon-3.0.1.tgz +Source1084: https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz#/d3-quadtree-3.0.1.tgz +Source1085: https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz#/d3-random-3.0.1.tgz +Source1086: https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz#/d3-scale-4.0.2.tgz +Source1087: https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#/d3-scale-chromatic-3.1.0.tgz +Source1088: https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz#/d3-selection-3.0.0.tgz +Source1089: https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz#/d3-shape-3.2.0.tgz +Source1090: https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz#/d3-time-3.1.0.tgz +Source1091: https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz#/d3-time-format-4.1.0.tgz +Source1092: https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz#/d3-timer-3.0.1.tgz +Source1093: https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz#/d3-transition-3.0.1.tgz +Source1094: https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz#/d3-zoom-3.0.0.tgz +Source1095: https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz#/dagre-0.8.5.tgz +Source1096: https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz#/dagre-d3-0.6.4.tgz +Source1097: https://registry.npmjs.org/datatables.net/-/datatables.net-2.3.7.tgz#/datatables.net-2.3.7.tgz +Source1098: https://registry.npmjs.org/datatables.net-bs5/-/datatables.net-bs5-2.3.7.tgz#/datatables.net-bs5-2.3.7.tgz +Source1099: https://registry.npmjs.org/debug/-/debug-4.4.3.tgz#/debug-4.4.3.tgz +Source1100: https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#/deep-is-0.1.4.tgz +Source1101: https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz#/delaunator-5.1.0.tgz +Source1102: https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#/emoji-regex-8.0.0.tgz +Source1103: https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz#/env-paths-2.2.1.tgz +Source1104: https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz#/error-ex-1.3.4.tgz +Source1105: https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#/escape-string-regexp-4.0.0.tgz +Source1106: https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz#/eslint-10.2.1.tgz +Source1107: https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz#/eslint-config-prettier-10.1.8.tgz +Source1108: https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz#/eslint-plugin-prettier-5.5.5.tgz +Source1109: https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz#/eslint-scope-9.1.2.tgz +Source1110: https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#/eslint-visitor-keys-3.4.3.tgz +Source1111: https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#/eslint-visitor-keys-5.0.1.tgz +Source1112: https://registry.npmjs.org/espree/-/espree-11.2.0.tgz#/espree-11.2.0.tgz +Source1113: https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz#/esquery-1.7.0.tgz +Source1114: https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz#/esrecurse-4.3.0.tgz +Source1115: https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz#/estraverse-5.3.0.tgz +Source1116: https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#/esutils-2.0.3.tgz +Source1117: https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#/fast-deep-equal-3.1.3.tgz +Source1118: https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz#/fast-diff-1.3.0.tgz +Source1119: https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz#/fast-glob-3.3.3.tgz +Source1120: https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#/fast-json-stable-stringify-2.1.0.tgz +Source1121: https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#/fast-levenshtein-2.0.6.tgz +Source1122: https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz#/fast-uri-3.1.7.tgz +Source1123: https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#/fastest-levenshtein-1.0.16.tgz +Source1124: https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz#/fastq-1.20.1.tgz +Source1125: https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz#/file-entry-cache-11.1.5.tgz +Source1126: https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz#/file-entry-cache-8.0.0.tgz +Source1127: https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz#/fill-range-7.1.1.tgz +Source1128: https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz#/find-up-5.0.0.tgz +Source1129: https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz#/flat-cache-4.0.1.tgz +Source1130: https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz#/flat-cache-6.1.23.tgz +Source1131: https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz#/flatted-3.4.2.tgz +Source1132: https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz#/get-east-asian-width-1.6.0.tgz +Source1133: https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#/glob-parent-5.1.2.tgz +Source1134: https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz#/glob-parent-6.0.2.tgz +Source1135: https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz#/global-modules-2.0.0.tgz +Source1136: https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz#/global-prefix-3.0.0.tgz +Source1137: https://registry.npmjs.org/globals/-/globals-17.4.0.tgz#/globals-17.4.0.tgz +Source1138: https://registry.npmjs.org/globby/-/globby-16.2.2.tgz#/globby-16.2.2.tgz +Source1139: https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz#/globjoin-0.1.4.tgz +Source1140: https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz#/graphlib-2.1.8.tgz +Source1141: https://registry.npmjs.org/has-flag/-/has-flag-5.0.1.tgz#/has-flag-5.0.1.tgz +Source1142: https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz#/hashery-1.5.1.tgz +Source1143: https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz#/hookified-1.15.1.tgz +Source1144: https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz#/hookified-2.2.0.tgz +Source1145: https://registry.npmjs.org/html-tags/-/html-tags-5.1.0.tgz#/html-tags-5.1.0.tgz +Source1146: https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz#/iconv-lite-0.6.3.tgz +Source1147: https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz#/ignore-5.3.2.tgz +Source1148: https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz#/ignore-7.0.5.tgz +Source1149: https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz#/import-fresh-3.3.1.tgz +Source1150: https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz#/import-meta-resolve-4.2.0.tgz +Source1151: https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#/imurmurhash-0.1.4.tgz +Source1152: https://registry.npmjs.org/ini/-/ini-1.3.8.tgz#/ini-1.3.8.tgz +Source1153: https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz#/internmap-2.0.3.tgz +Source1154: https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz#/is-arrayish-0.2.1.tgz +Source1155: https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#/is-extglob-2.1.1.tgz +Source1156: https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#/is-fullwidth-code-point-3.0.0.tgz +Source1157: https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz#/is-glob-4.0.3.tgz +Source1158: https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#/is-number-7.0.0.tgz +Source1159: https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz#/is-path-inside-4.0.0.tgz +Source1160: https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz#/is-plain-object-5.0.0.tgz +Source1161: https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#/isexe-2.0.0.tgz +Source1162: https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz#/jquery-3.7.1.tgz +Source1163: https://registry.npmjs.org/jquery/-/jquery-4.0.0.tgz#/jquery-4.0.0.tgz +Source1164: https://registry.npmjs.org/jquery-ujs/-/jquery-ujs-1.2.3.tgz#/jquery-ujs-1.2.3.tgz +Source1165: https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#/js-tokens-4.0.0.tgz +Source1166: https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz#/js-yaml-4.3.2.tgz +Source1167: https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz#/json-buffer-3.0.1.tgz +Source1168: https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#/json-parse-even-better-errors-2.3.1.tgz +Source1169: https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#/json-schema-traverse-0.4.1.tgz +Source1170: https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#/json-schema-traverse-1.0.0.tgz +Source1171: https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#/json-stable-stringify-without-jsonify-1.0.1.tgz +Source1172: https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz#/keyv-4.5.4.tgz +Source1173: https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz#/keyv-5.6.0.tgz +Source1174: https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz#/kind-of-6.0.3.tgz +Source1175: https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz#/known-css-properties-0.37.0.tgz +Source1176: https://registry.npmjs.org/levn/-/levn-0.4.1.tgz#/levn-0.4.1.tgz +Source1177: https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz#/lines-and-columns-1.2.4.tgz +Source1178: https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz#/locate-path-6.0.0.tgz +Source1179: https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz#/lodash-4.18.1.tgz +Source1180: https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz#/lodash.truncate-4.4.2.tgz +Source1181: https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-4.0.0.tgz#/mathml-tag-names-4.0.0.tgz +Source1182: https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz#/mdn-data-2.27.1.tgz +Source1183: https://registry.npmjs.org/meow/-/meow-14.1.0.tgz#/meow-14.1.0.tgz +Source1184: https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz#/merge2-1.4.1.tgz +Source1185: https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz#/micromatch-4.0.8.tgz +Source1186: https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz#/minimatch-10.2.4.tgz +Source1187: https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#/ms-2.1.3.tgz +Source1188: https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz#/nanoid-3.3.16.tgz +Source1189: https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#/natural-compare-1.4.0.tgz +Source1190: https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#/normalize-path-3.0.0.tgz +Source1191: https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz#/optionator-0.9.4.tgz +Source1192: https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz#/p-limit-3.1.0.tgz +Source1193: https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz#/p-locate-5.0.0.tgz +Source1194: https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz#/parent-module-1.0.1.tgz +Source1195: https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz#/parse-json-5.2.0.tgz +Source1196: https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#/path-exists-4.0.0.tgz +Source1197: https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz#/path-key-3.1.1.tgz +Source1198: https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz#/picocolors-1.1.1.tgz +Source1199: https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz#/picomatch-2.3.2.tgz +Source1200: https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz#/postcss-8.5.23.tgz +Source1201: https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#/postcss-media-query-parser-0.2.3.tgz +Source1202: https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz#/postcss-resolve-nested-selector-0.1.6.tgz +Source1203: https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz#/postcss-safe-parser-7.0.1.tgz +Source1204: https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz#/postcss-scss-4.0.9.tgz +Source1205: https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz#/postcss-selector-parser-7.1.4.tgz +Source1206: https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#/postcss-value-parser-4.2.0.tgz +Source1207: https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#/prelude-ls-1.2.1.tgz +Source1208: https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz#/prettier-3.9.6.tgz +Source1209: https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz#/prettier-linter-helpers-1.0.1.tgz +Source1210: https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz#/punycode-2.3.1.tgz +Source1211: https://registry.npmjs.org/qified/-/qified-0.10.1.tgz#/qified-0.10.1.tgz +Source1212: https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz#/queue-microtask-1.2.3.tgz +Source1213: https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz#/require-from-string-2.0.2.tgz +Source1214: https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz#/resolve-from-4.0.0.tgz +Source1215: https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz#/reusify-1.1.0.tgz +Source1216: https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz#/robust-predicates-3.0.2.tgz +Source1217: https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz#/run-parallel-1.2.0.tgz +Source1218: https://registry.npmjs.org/rw/-/rw-1.3.3.tgz#/rw-1.3.3.tgz +Source1219: https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#/safer-buffer-2.1.2.tgz +Source1220: https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz#/shebang-command-2.0.0.tgz +Source1221: https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz#/shebang-regex-3.0.0.tgz +Source1222: https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz#/signal-exit-4.1.0.tgz +Source1223: https://registry.npmjs.org/slash/-/slash-5.1.0.tgz#/slash-5.1.0.tgz +Source1224: https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz#/slice-ansi-4.0.0.tgz +Source1225: https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz#/source-map-js-1.2.1.tgz +Source1226: https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#/string-width-4.2.3.tgz +Source1227: https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz#/string-width-8.2.2.tgz +Source1228: https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#/strip-ansi-6.0.1.tgz +Source1229: https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz#/strip-ansi-7.2.0.tgz +Source1230: https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz#/style-search-0.1.0.tgz +Source1231: https://registry.npmjs.org/stylelint/-/stylelint-17.14.1.tgz#/stylelint-17.14.1.tgz +Source1232: https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-18.0.0.tgz#/stylelint-config-recommended-18.0.0.tgz +Source1233: https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-17.0.0.tgz#/stylelint-config-recommended-scss-17.0.0.tgz +Source1234: https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-40.0.0.tgz#/stylelint-config-standard-40.0.0.tgz +Source1235: https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-17.0.0.tgz#/stylelint-config-standard-scss-17.0.0.tgz +Source1236: https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.3.tgz#/stylelint-prettier-5.0.3.tgz +Source1237: https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-7.0.0.tgz#/stylelint-scss-7.0.0.tgz +Source1238: https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz#/supports-color-10.2.2.tgz +Source1239: https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-4.5.0.tgz#/supports-hyperlinks-4.5.0.tgz +Source1240: https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz#/svg-tags-1.0.0.tgz +Source1241: https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz#/synckit-0.11.13.tgz +Source1242: https://registry.npmjs.org/table/-/table-6.9.0.tgz#/table-6.9.0.tgz +Source1243: https://registry.npmjs.org/timeago.js/-/timeago.js-4.0.2.tgz#/timeago.js-4.0.2.tgz +Source1244: https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#/to-regex-range-5.0.1.tgz +Source1245: https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz#/type-check-0.4.0.tgz +Source1246: https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz#/unicorn-magic-0.4.0.tgz +Source1247: https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#/uri-js-4.4.1.tgz +Source1248: https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#/util-deprecate-1.0.2.tgz +Source1249: https://registry.npmjs.org/which/-/which-1.3.1.tgz#/which-1.3.1.tgz +Source1250: https://registry.npmjs.org/which/-/which-2.0.2.tgz#/which-2.0.2.tgz +Source1251: https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz#/word-wrap-1.2.5.tgz +Source1252: https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz#/write-file-atomic-7.0.1.tgz +Source1253: https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#/yocto-queue-0.1.0.tgz ++++++ openQA-5.1791790842.db5f7862.obscpio -> openQA-5.1791966007.170875a4.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/.github/workflows/check-helm-chart.yml new/openQA-5.1791966007.170875a4/.github/workflows/check-helm-chart.yml --- old/openQA-5.1791790842.db5f7862/.github/workflows/check-helm-chart.yml 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/.github/workflows/check-helm-chart.yml 2026-10-14 10:20:07.000000000 +0200 @@ -56,7 +56,7 @@ uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2 - name: Create kind cluster - uses: helm/kind-action@06c1ae10762d3b9c1644e7fe69596ae519e015a2 # v1.15.0 + uses: helm/kind-action@1544676c07bb3570fcb70166beaa07c4528fd4aa # v1.15.1 - name: Download images run: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/.mergify.yml new/openQA-5.1791966007.170875a4/.mergify.yml --- old/openQA-5.1791790842.db5f7862/.mergify.yml 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/.mergify.yml 2026-10-14 10:20:07.000000000 +0200 @@ -13,7 +13,7 @@ # "unresolvable" is not reported in general: # https://trello.com/c/0N3jHq5M/2257-report-back-to-scm-when-build-results-arent-failed-and-succeeded # So we need to require the number of tests explicitly: - - "#check-success>=41" + - "#check-success>=39" - status-success=static-check-containers - status-success=webui-docker-compose - "#check-failure=0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/Makefile new/openQA-5.1791966007.170875a4/Makefile --- old/openQA-5.1791790842.db5f7862/Makefile 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/Makefile 2026-10-14 10:20:07.000000000 +0200 @@ -104,8 +104,11 @@ .PHONY: generate-manpages generate-manpages: ## Regenerate manpage from public/openqa-cli.yaml mkdir -p contrib/manpages - echo -e "=encoding utf8\n" >contrib/manpages/openqa-cli.pod - (appspec pod public/openqa-cli.yaml 2>/dev/null || echo "=head1 No manpage available") >> contrib/manpages/openqa-cli.pod + @if perl -wE 'use App::Spec v0.17.0'; then \ + appspec pod public/openqa-cli.yaml > contrib/manpages/openqa-cli.pod; \ + else \ + echo "=head1 No manpage available" > contrib/manpages/openqa-cli.pod; \ + fi pod2man contrib/manpages/openqa-cli.pod > contrib/manpages/openqa-cli.1 .PHONY: generate-completions diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/assets/javascripts/filter_form.js new/openQA-5.1791966007.170875a4/assets/javascripts/filter_form.js --- old/openQA-5.1791790842.db5f7862/assets/javascripts/filter_form.js 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/assets/javascripts/filter_form.js 2026-10-14 10:20:07.000000000 +0200 @@ -1,3 +1,5 @@ +const NO_FILTER_LABEL = 'no filter present, click to toggle filter form'; + function setupFilterForm(options) { // make filter form expandable const cardHeader = document.querySelector('#filter-panel .card-header'); @@ -23,69 +25,68 @@ }); }); - if (options && options.preventLoadingIndication) { - return; - } - const filterForm = document.getElementById('filter-form'); - if (filterForm) { - filterForm.addEventListener('submit', function (event) { - event.preventDefault(); - const currentQuery = window.location.search.substring(1); - const formData = new FormData(filterForm); + const applyFilterForm = function () { + const currentQuery = window.location.search.substring(1); + const formData = new FormData(filterForm); - // optimize results and states to use negative filters if shorter - ['result', 'state'].forEach(key => { - const checkboxes = Array.from(filterForm.querySelectorAll(`input[name="${key}"]:not(.filter-meta)`)); - const checked = checkboxes.filter(cb => cb.checked); - const unchecked = checkboxes.filter(cb => !cb.checked); - if (checked.length > 1 && unchecked.length > 0 && unchecked.length < checked.length) { - formData.delete(key); - unchecked.forEach(cb => formData.append(`${key}__not`, cb.value)); - } - }); + // optimize results and states to use negative filters if shorter + ['result', 'state'].forEach(key => { + const checkboxes = Array.from(filterForm.querySelectorAll(`input[name="${key}"]:not(.filter-meta)`)); + const checked = checkboxes.filter(cb => cb.checked); + const unchecked = checkboxes.filter(cb => !cb.checked); + if (checked.length > 1 && unchecked.length > 0 && unchecked.length < checked.length) { + formData.delete(key); + unchecked.forEach(cb => formData.append(`${key}__not`, cb.value)); + } + }); - const params = new URLSearchParams(formData); + const params = new URLSearchParams(formData); - // remove redundant constituent values if meta-values are present - if (options && options.metaMapping) { - ['result', 'state'].forEach(key => { - const mapping = options.metaMapping[key]; - if (!mapping) return; - const currentValues = params.getAll(key); - if (currentValues.length === 0) return; - - let newValues = [...currentValues]; - Object.keys(mapping).forEach(metaValue => { - if (currentValues.includes(metaValue)) { - const constituents = mapping[metaValue]; - newValues = newValues.filter(val => !constituents.includes(val)); - } - }); + // remove redundant constituent values if meta-values are present + if (options && options.metaMapping) { + ['result', 'state'].forEach(key => { + const mapping = options.metaMapping[key]; + if (!mapping) return; + const currentValues = params.getAll(key); + if (currentValues.length === 0) return; - if (newValues.length !== currentValues.length) { - params.delete(key); - newValues.forEach(val => params.append(key, val)); + let newValues = [...currentValues]; + Object.keys(mapping).forEach(metaValue => { + if (currentValues.includes(metaValue)) { + const constituents = mapping[metaValue]; + newValues = newValues.filter(val => !constituents.includes(val)); } }); - } - const newQuery = new URLSearchParams(Array.from(params).filter(([, value]) => value !== '')) - .toString() - .replace(/\+/g, '%20'); - - if (newQuery !== currentQuery) { - // show progress indication - filterForm.hidden = true; - const cardBody = document.querySelector('#filter-panel .card-body'); - if (cardBody) { - const progress = document.createElement('span'); - progress.id = 'filter-progress'; - progress.innerHTML = '<i class="fa-solid fa-gear fa-spin fa-2x fa-fw"></i> <span>Applying filter…</span>'; - cardBody.appendChild(progress); + if (newValues.length !== currentValues.length) { + params.delete(key); + newValues.forEach(val => params.append(key, val)); } - window.location.search = newQuery; + }); + } + + const newQuery = new URLSearchParams(Array.from(params).filter(([, value]) => value !== '')) + .toString() + .replace(/\+/g, '%20'); + + if (newQuery !== currentQuery) { + // show progress indication + filterForm.hidden = true; + const cardBody = document.querySelector('#filter-panel .card-body'); + if (cardBody) { + const progress = document.createElement('span'); + progress.id = 'filter-progress'; + progress.innerHTML = '<i class="fa-solid fa-gear fa-spin fa-2x fa-fw"></i> <span>Applying filter…</span>'; + cardBody.appendChild(progress); } + window.location.search = newQuery; + } + }; + if (filterForm && (!options || !options.preventLoadingIndication)) { + filterForm.addEventListener('submit', function (event) { + event.preventDefault(); + applyFilterForm(); }); } @@ -93,24 +94,26 @@ if (resetBtn) { resetBtn.addEventListener('click', function () { if (!filterForm) return; - filterForm.querySelectorAll('input[type="text"], input[type="number"]').forEach(input => { - input.value = ''; - }); + filterForm + .querySelectorAll('input[type="text"]:not([hidden]), input[type="number"]:not([hidden])') + .forEach(input => { + input.value = ''; + }); filterForm.querySelectorAll('input[type="checkbox"]').forEach(input => { input.checked = false; input.indeterminate = false; }); - filterForm.querySelectorAll('input[hidden]').forEach(input => { - input.remove(); - }); filterForm.querySelectorAll('select').forEach(select => { Array.from(select.options).forEach(opt => (opt.selected = false)); if (typeof jQuery !== 'undefined' && typeof jQuery.fn.chosen === 'function') { $(select).trigger('chosen:updated'); } }); - document.querySelector('#filter-panel .card-header span').textContent = - 'no filter present, click to toggle filter form'; + const headerSpan = document.querySelector('#filter-panel .card-header span'); + if (headerSpan) { + headerSpan.textContent = NO_FILTER_LABEL; + } + applyFilterForm(); }); } @@ -213,8 +216,7 @@ form.append(...hiddenInputs); } - if (filterLabels.length > 0) { - document.querySelector('#filter-panel .card-header span').textContent = 'current: ' + filterLabels.join(', '); - } + const headerSpan = document.querySelector('#filter-panel .card-header span'); + headerSpan.textContent = filterLabels.length > 0 ? 'current: ' + filterLabels.join(', ') : NO_FILTER_LABEL; return filterLabels; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/assets/javascripts/openqa.js new/openQA-5.1791966007.170875a4/assets/javascripts/openqa.js --- old/openQA-5.1791790842.db5f7862/assets/javascripts/openqa.js 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/assets/javascripts/openqa.js 2026-10-14 10:20:07.000000000 +0200 @@ -313,6 +313,54 @@ return ul; } +function isOverviewPage() { + return ( + (typeof urlWithBase === 'function' && + window.location.pathname.replace(/\/$/, '') === urlWithBase('/tests/overview').replace(/\/$/, '')) || + Boolean(document.querySelector('table.overview') && document.getElementById('summary')) + ); +} + +function updateOverviewRestartedJobs(newIdMap) { + if (!isOverviewPage() || !newIdMap || typeof newIdMap !== 'object') { + return; + } + Object.entries(newIdMap).forEach(([key, value]) => { + const restarted = document.querySelector('.restart[data-jobid="' + key + '"]'); + if (!restarted) { + return; + } + restarted.textContent = ''; // hide the icon + const td = restarted.closest('td'); + const icon = td?.querySelector('.status'); + if (icon) { + icon.classList.remove('state_done', 'state_cancelled'); + icon.classList.add('state_scheduled'); + icon.title = 'Scheduled'; + + // remove the result class + td.querySelectorAll('.result_passed, .result_failed, .result_softfailed').forEach(el => { + el.classList.remove('result_passed', 'result_failed', 'result_softfailed'); + }); + + // If the API call returns a new id, a new job have been created to replace + // the old one. In other case, the old job is being reused + if (value) { + const link = icon.closest('a'); + if (link) { + const oldId = restarted.dataset.jobid; + const newUrl = link.getAttribute('href').replace(oldId, value); + link.setAttribute('href', newUrl); + link.classList.add('restarted'); + } + } + + icon.style.opacity = 0.5; + setTimeout(() => (icon.style.opacity = 1.0), 500); + } + }); +} + function showJobRestartResults(responseJSON, newJobUrl, retryFunction, targetElement) { const hasResponse = typeof responseJSON === 'object'; const errors = hasResponse ? responseJSON.errors : ['Server returned invalid response']; @@ -400,12 +448,13 @@ restartLink.click(); } -function restartJob(ajaxUrl, jobIds, comment) { +function restartJob(ajaxUrl, jobIds, comment, options = {}) { let singleJobId; if (!Array.isArray(jobIds)) { singleJobId = jobIds; jobIds = [jobIds]; } + const shouldRedirect = options.redirect !== undefined ? options.redirect : !isOverviewPage(); const showError = function (reason) { let errorMessage = '<strong>Unable to restart job'; if (reason) { @@ -452,9 +501,10 @@ showJobRestartResults( json, newJobUrl, - restartJob.bind(undefined, addParam(ajaxUrl, 'force', '1'), jobIds, comment) + restartJob.bind(undefined, addParam(ajaxUrl, 'force', '1'), jobIds, comment, options) ) ) { + updateOverviewRestartedJobs(json.result?.[0]); return; } if (newJobUrl) { @@ -463,12 +513,15 @@ 'info', 'The jobs have been restarted. <a href="javascript: location.reload()">Reload</a> the page to show changes.' ); + } else if (!shouldRedirect) { + addFlash('info', `The job has been restarted. Go to <a href="${newJobUrl}">new job</a>.`); } else { window.location.replace(newJobUrl); } } else { throw 'URL for new job not available'; } + updateOverviewRestartedJobs(json.result?.[0]); }) .catch(error => { showError(error); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/assets/javascripts/overview.js new/openQA-5.1791966007.170875a4/assets/javascripts/overview.js --- old/openQA-5.1791790842.db5f7862/assets/javascripts/overview.js 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/assets/javascripts/overview.js 2026-10-14 10:20:07.000000000 +0200 @@ -139,42 +139,32 @@ addFlash('danger', '<strong>Unable to restart job.</strong>'); return; } - showJobRestartResults(xhr, undefined, forceJobRestartViaRestartLink.bind(undefined, event.currentTarget)); - const newId = xhr.result[0]; - const oldId = 0; - const newIdMap = xhr.result[0]; - Object.entries(newIdMap).forEach(([key, value]) => { - const restarted = document.querySelector('.restart[data-jobid="' + key + '"]'); - if (!restarted) { - return; + let newJobUrl; + try { + const jobId = event.currentTarget.dataset.jobid; + newJobUrl = xhr.test_url?.[0]?.[jobId]; + if (!newJobUrl && Array.isArray(xhr.test_url) && xhr.test_url[0]) { + newJobUrl = Object.values(xhr.test_url[0])[0]; } - restarted.textContent = ''; // hide the icon - const td = restarted.closest('td'); - const icon = td.querySelector('.status'); - if (icon) { - icon.classList.remove('state_done', 'state_cancelled'); - icon.classList.add('state_scheduled'); - icon.title = 'Scheduled'; - - // remove the result class - td.querySelectorAll('.result_passed, .result_failed, .result_softfailed').forEach(el => { - el.classList.remove('result_passed', 'result_failed', 'result_softfailed'); - }); - - // If the API call returns a new id, a new job have been created to replace - // the old one. In other case, the old job is being reused - if (value) { - const link = icon.closest('a'); - const oldId = restarted.dataset.jobid; - const newUrl = link.getAttribute('href').replace(oldId, value); - link.setAttribute('href', newUrl); - link.classList.add('restarted'); + } catch { + // Intentionally ignore all errors + } + const hasRestartResults = showJobRestartResults( + xhr, + newJobUrl, + forceJobRestartViaRestartLink.bind(undefined, event.currentTarget) + ); + const newIdMap = xhr.result[0]; + if (newIdMap) { + updateOverviewRestartedJobs(newIdMap); + if (!hasRestartResults && event.currentTarget.href.includes('force=1')) { + if (newJobUrl) { + addFlash('info', `The job has been restarted. Go to <a href="${newJobUrl}">new job</a>.`); + } else { + addFlash('info', 'The job has been restarted.'); } - - icon.style.opacity = 0.5; - setTimeout(() => (icon.style.opacity = 1.0), 500); } - }); + } }); const dependencies = document.getElementsByClassName('dependency'); for (let i = 0; i < dependencies.length; i++) { @@ -261,7 +251,7 @@ } return formatFilter(val); } else { - const input = document.getElementById('filter-' + key.replace(/_/g, '-')) || form.elements[key]; + const input = form.elements[key] || document.getElementById('filter-' + key.replace(/_/g, '-')); if (input && input.value !== undefined) { input.value += input.value.length > 0 ? `,${val}` : val; return val; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/assets/javascripts/running.js new/openQA-5.1791966007.170875a4/assets/javascripts/running.js --- old/openQA-5.1791790842.db5f7862/assets/javascripts/running.js 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/assets/javascripts/running.js 2026-10-14 10:20:07.000000000 +0200 @@ -511,6 +511,7 @@ develSessionDeveloper: undefined, // name of the user in possession the development session develSessionStartedAt: undefined, // time stamp when the development session was created develSessionTabCount: undefined, // number of open web socket connections by the developer + developerConnectionHint: undefined, // custom connection hint configured for the worker // returns whether we're currently connecting isConnecting: function () { @@ -1231,6 +1232,18 @@ }); } } + + // handle developer connection hint; messages from older live handlers reset it + if (data && ('developer_connection_hint' in data || 'vnc_arg' in data)) { + const hint = data.developer_connection_hint?.trim() || undefined; + if (hint !== developerMode.developerConnectionHint) { + developerMode.developerConnectionHint = hint; + somethingChanged = true; + Array.from(document.getElementsByClassName('developer-connection-hint-text')).forEach(e => { + e.textContent = hint || ''; + }); + } + } } if (somethingChanged) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/docs/Pitfalls.md new/openQA-5.1791966007.170875a4/docs/Pitfalls.md --- old/openQA-5.1791790842.db5f7862/docs/Pitfalls.md 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/docs/Pitfalls.md 2026-10-14 10:20:07.000000000 +0200 @@ -130,3 +130,8 @@ 5. It can also help to look at the [architecture diagram](images/architecture.svg) which shows which component needs access to which other components and the ports used by default. + +6. If the VNC instructions shown in the developer mode are not reachable from your machine, + e.g. because the SUT runs behind a jump host, set `DEVELOPER_CONNECTION_HINT` in + [the worker configuration](GettingStarted.md#worker-configuration) to describe how to connect. + See [connecting to the SUT via VNC](UsersGuide.md#connecting-to-the-sut-via-vnc). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/docs/UsersGuide.md new/openQA-5.1791966007.170875a4/docs/UsersGuide.md --- old/openQA-5.1791790842.db5f7862/docs/UsersGuide.md 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/docs/UsersGuide.md 2026-10-14 10:20:07.000000000 +0200 @@ -630,6 +630,23 @@ Related issue: <a href="https://progress.opensuse.org/issues/11052" id="11052">https://progress.opensuse.org/issues/11052</a> +### RSS news feed for job groups + +An RSS feed is available for each job group and parent group by appending `.rss` +to the overview URL: + + http://openqa/group_overview/1.rss + http://openqa/parent_group_overview/1.rss + +The feed provides build updates (build label, timestamp, and a link to the test +overview for that build). Query parameters like `limit_builds` can be passed to +control how many builds are returned in the feed (defaulting to 10): + + http://openqa/group_overview/1.rss?limit_builds=1 + +Group overview pages also provide an "RSS" button and autodiscovery tags for +browsers and feed readers. + ### Test result badges <a href="https://github.com/os-autoinst/openQA/pull/5022" id="5022">gh</a> For build results or individual job results including the latest job result @@ -761,6 +778,15 @@ In case the developer mode in not working on your instance, try to follow the [steps for debugging the developer mode under 'Pitfalls'](Pitfalls.md#debugdevelmode). +#### Connecting to the SUT via VNC + +While a test is paused, the developer mode shows how to connect to the SUT via VNC, +e.g. `vncviewer <host>:<port> -Shared`. The address is derived from the +`WORKER_HOSTNAME` of the worker running the test. If this address is not reachable +from your machine, the administrator of the worker can set `DEVELOPER_CONNECTION_HINT` +in the [worker configuration](GettingStarted.md#worker-configuration). The configured text +replaces the default VNC notice and is shown as plain text, e.g. an SSH tunnel command. + #### Workflow for creating or updating needles 1. In case a new needles should be created, add the corresponding `assert_screen` calls diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/etc/openqa/workers.ini new/openQA-5.1791966007.170875a4/etc/openqa/workers.ini --- old/openQA-5.1791790842.db5f7862/etc/openqa/workers.ini 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/etc/openqa/workers.ini 2026-10-14 10:20:07.000000000 +0200 @@ -33,6 +33,16 @@ # sufficient) #WORKER_HOSTNAME = openqa-worker.example.host +# Plain text shown in the developer mode of the web UI, while the test is paused, +# instead of the default VNC hint. Only set this if the default VNC address derived +# from WORKER_HOSTNAME is not reachable from the browser or the user's machine, e.g. +# when the SUT runs on another host behind a jump host or the port is firewalled. +# Describe how to connect instead, e.g.: +#DEVELOPER_CONNECTION_HINT = ssh -L 5903:sut.example.com:5903 jump.example.com +# If no connection is possible at all, state that instead of a connection method, e.g.: +#DEVELOPER_CONNECTION_HINT = No VNC access to the SUT is possible for this worker +# An empty value counts as unset and shows the default VNC hint. + # Optimize asset uploads. Enabled by default. When enabled the worker will # try to copy assets on the file system instead of uploading them to the # webui via HTTP, for much better performance (webui and worker need to be diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/lib/OpenQA/LiveHandler/Controller/LiveViewHandler.pm new/openQA-5.1791966007.170875a4/lib/OpenQA/LiveHandler/Controller/LiveViewHandler.pm --- old/openQA-5.1791790842.db5f7862/lib/OpenQA/LiveHandler/Controller/LiveViewHandler.pm 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/lib/OpenQA/LiveHandler/Controller/LiveViewHandler.pm 2026-10-14 10:20:07.000000000 +0200 @@ -471,7 +471,7 @@ push @$java_script_transactions_for_current_job, $java_script_tx; # determine url to os-autoinst command server - my ($cmd_srv_raw_url, $vnc_arg) = $self->determine_connection_params_for_job($job); + my ($cmd_srv_raw_url, $conn_params) = $self->determine_connection_params_for_job($job); if (!$cmd_srv_raw_url) { $app->log->debug('attempt to open ws proxy for job ' . $job->name . ' (' @@ -487,7 +487,7 @@ } # start opening a websocket connection to os-autoinst instantly - $self->connect_to_cmd_srv($job_id, $cmd_srv_raw_url, {vnc_arg => $vnc_arg}) if $cmd_srv_raw_url; + $self->connect_to_cmd_srv($job_id, $cmd_srv_raw_url, $conn_params) if $cmd_srv_raw_url; # don't react to any messages from the JavaScript client if serving the status-only route if ($status_only) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/lib/OpenQA/Schema/Result/Workers.pm new/openQA-5.1791966007.170875a4/lib/OpenQA/Schema/Result/Workers.pm --- old/openQA-5.1791790842.db5f7862/lib/OpenQA/Schema/Result/Workers.pm 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/lib/OpenQA/Schema/Result/Workers.pm 2026-10-14 10:20:07.000000000 +0200 @@ -4,6 +4,7 @@ package OpenQA::Schema::Result::Workers; use Mojo::Base 'DBIx::Class::Core', -signatures; +use Mojo::Util 'trim'; use DBIx::Class::Timestamps 'now'; use Feature::Compat::Try; @@ -354,4 +355,9 @@ return "$hostname:$instance"; } +sub developer_connection_hint ($self) { + my $hint = trim($self->get_property('DEVELOPER_CONNECTION_HINT') // ''); + return length $hint ? $hint : undef; +} + 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/lib/OpenQA/Shared/Plugin/SharedHelpers.pm new/openQA-5.1791966007.170875a4/lib/OpenQA/Shared/Plugin/SharedHelpers.pm --- old/openQA-5.1791790842.db5f7862/lib/OpenQA/Shared/Plugin/SharedHelpers.pm 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/lib/OpenQA/Shared/Plugin/SharedHelpers.pm 2026-10-14 10:20:07.000000000 +0200 @@ -26,7 +26,7 @@ $app->helper(via_domain => \&_via_domain); } -# returns the isotovideo command server web socket URL and the VNC argument for the given job or undef if not available +# returns the isotovideo command server web socket URL and connection params for the given job or undef sub _determine_connection_params_for_job ($c, $job) { return undef unless $job->state eq OpenQA::Jobs::Constants::RUNNING; @@ -39,7 +39,12 @@ my $cmd_srv_raw_url = $worker->get_property('CMD_SRV_URL') or return undef; my $cmd_srv_url = Mojo::URL->new($cmd_srv_raw_url); my $port = $cmd_srv_url->port() or return undef; - return ("ws://$host:$port/$job_token/ws", $worker->vnc_argument); + return ( + "ws://$host:$port/$job_token/ws", + { + vnc_arg => $worker->vnc_argument, + developer_connection_hint => $worker->developer_connection_hint, + }); } sub _determine_os_autoinst_web_socket_url ($c, $job) { (_determine_connection_params_for_job($c, $job))[0] } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI/Controller/API/V1/Worker.pm new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI/Controller/API/V1/Worker.pm --- old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI/Controller/API/V1/Worker.pm 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI/Controller/API/V1/Worker.pm 2026-10-14 10:20:07.000000000 +0200 @@ -184,10 +184,10 @@ sub create ($self) { my $validation = $self->validation; my @validation_params - = qw(cpu_arch cpu_modelname cpu_opmode cpu_flags mem_max isotovideo_interface_version websocket_api_version worker_class parallel_one_host_only); + = qw(cpu_arch cpu_modelname cpu_opmode cpu_flags mem_max isotovideo_interface_version websocket_api_version worker_class parallel_one_host_only developer_connection_hint); $validation->required($_) for qw(host instance cpu_arch mem_max worker_class); $validation->optional($_) for qw(cpu_modelname cpu_opmode cpu_flags isotovideo_interface_version job_id - websocket_api_version parallel_one_host_only); + websocket_api_version parallel_one_host_only developer_connection_hint); return $self->reply->validation_error({format => 'json'}) if $validation->has_error; my $host = $validation->param('host'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI/Controller/Main.pm new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI/Controller/Main.pm --- old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI/Controller/Main.pm 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI/Controller/Main.pm 2026-10-14 10:20:07.000000000 +0200 @@ -98,7 +98,43 @@ $self->stash(error_message => $error); $self->respond_to( json => {json => {error => $error}, status => 400}, - html => {template => 'main/specific_not_found', status => 400}, + any => sub ($self) { $self->render(template => 'main/specific_not_found', format => 'html', status => 400) }, + ); +} + +sub _render_group_feed ($self, $group, $build_results, $children = []) { + my $group_id = $group->{id}; + my @group_ids = @$children ? (map { $_->{id} } @$children) : ($group_id); + my @items; + for my $build_res (@$build_results) { + my ($version, $build) = ($build_res->{version}, $build_res->{build}); + my $label + = ($build_res->{version_count} > 1 || $group->{always_show_version}) + ? "$version-Build$build" + : "Build$build"; + # Build the link for the result. A single Build can contain multiple distris, but only one version + my $link = $self->url_for('tests_overview')->query( + distri => [sort keys %{$build_res->{distris}}], + version => $version, + build => $build, + groupid => \@group_ids, + )->to_abs->to_string; + + push @items, + { + title => $label, + link => $link, + guid => "$group_id-$build_res->{key}", + date => time2str('%a, %d %b %Y %T +0000', $build_res->{date}->epoch, 'UTC'), + }; + } + my $route = $group->{is_parent} ? 'parent_group_overview' : 'group_overview'; + $self->render( + template => 'main/group_feed', + format => 'rss', + feed_items => \@items, + feed_link => $self->url_for($route, groupid => $group_id)->to_abs->to_string, + feed_self_link => $self->url_for($route, groupid => $group_id, format => 'rss')->to_abs->to_string, ); } @@ -251,6 +287,9 @@ pinned_comments => \@pinned_comments_hashes, }); }, + rss => sub ($self) { + $self->_render_group_feed($group_hash, $build_results, $children); + }, html => sub ($self) { $self->render(template => $template); }); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI/Controller/Step.pm new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI/Controller/Step.pm --- old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI/Controller/Step.pm 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI/Controller/Step.pm 2026-10-14 10:20:07.000000000 +0200 @@ -500,8 +500,11 @@ my $append_needle_info = sub ($tags, $needle_info) { # add timestamps and URLs from database - $self->populate_hash_with_needle_timestamps_and_urls( - $needles_rs->find_needle($real_needle_dir, "$needle_info->{name}.json"), $needle_info); + my $db_needle + = $needles_rs->find_needle($real_needle_dir, "$needle_info->{name}.json") + || $needles_rs->find_needle($needle_dir, "$needle_info->{name}.json") + || $needles_rs->search({filename => "$needle_info->{name}.json"})->first; + $self->populate_hash_with_needle_timestamps_and_urls($db_needle, $needle_info); # handle case when the needle has (for some reason) no tags if (!$tags) { @@ -540,6 +543,25 @@ $primary_match = _calc_matches($info, $module_detail->{area}); $append_needle_info->($needleinfo->{tags} => $info); } + else { + my $db_needle + = $needles_rs->find_needle($real_needle_dir, "$needle.json") + || $needles_rs->find_needle($needle_dir, "$needle.json") + || $needles_rs->search({filename => "$needle.json"})->first; + my $info = { + name => $needle, + needledir => undef, + image => undef, + areas => [], + error => $module_detail->{error}, + matches => [], + primary_match => 1, + selected => 1, + deleted => $db_needle ? 1 : 0, + }; + $primary_match = _calc_matches($info, $module_detail->{area}); + $append_needle_info->(($module_detail->{tags} // []) => $info); + } } # load other needle matches diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI/Plugin/MIMETypes.pm new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI/Plugin/MIMETypes.pm --- old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI/Plugin/MIMETypes.pm 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI/Plugin/MIMETypes.pm 2026-10-14 10:20:07.000000000 +0200 @@ -9,6 +9,7 @@ $types->type(yaml => 'text/yaml;charset=UTF-8'); $types->type(bz2 => 'application/x-bzip2'); $types->type(xz => 'application/x-xz'); + $types->type(rss => 'application/rss+xml;charset=UTF-8'); } 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI.pm new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI.pm --- old/openQA-5.1791790842.db5f7862/lib/OpenQA/WebAPI.pm 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/lib/OpenQA/WebAPI.pm 2026-10-14 10:20:07.000000000 +0200 @@ -210,12 +210,12 @@ # but this route is actually matched (in case apache is not catching this earlier) # due to the split md5_dirname having a / $r->get('/image/:md5_1/:md5_2/.thumbs/#md5_basename')->to('file#thumb_image'); - $r->get('/group_overview/<groupid:num>' => [format => ['json', 'html']])->name('group_overview') + $r->get('/group_overview/<groupid:num>' => [format => ['json', 'html', 'rss']])->name('group_overview') ->to('main#job_group_overview', format => undef); $r->get('/group_overview/<groupid:num>/comments_ajax' => [format => ['html']])->name('job_group_comments_ajax') ->to('main#job_group_comments_ajax', format => undef); - $r->get('/parent_group_overview/<groupid:num>' => [format => ['json', 'html']])->name('parent_group_overview') - ->to('main#parent_group_overview', format => undef); + $r->get('/parent_group_overview/<groupid:num>' => [format => ['json', 'html', 'rss']]) + ->name('parent_group_overview')->to('main#parent_group_overview', format => undef); $r->get('/parent_group_overview/<groupid:num>/comments_ajax' => [format => ['html']]) ->name('parent_group_comments_ajax')->to('main#parent_group_comments_ajax', format => undef); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/lib/OpenQA/Worker.pm new/openQA-5.1791966007.170875a4/lib/OpenQA/Worker.pm --- old/openQA-5.1791790842.db5f7862/lib/OpenQA/Worker.pm 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/lib/OpenQA/Worker.pm 2026-10-14 10:20:07.000000000 +0200 @@ -258,6 +258,8 @@ # TODO: check installed qemu and kvm? } $caps->{parallel_one_host_only} = $global_settings->{PARALLEL_ONE_HOST_ONLY}; + $caps->{developer_connection_hint} = $global_settings->{DEVELOPER_CONNECTION_HINT} + if defined $global_settings->{DEVELOPER_CONNECTION_HINT}; return $self->{_caps} = $caps; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/package-lock.json new/openQA-5.1791966007.170875a4/package-lock.json --- old/openQA-5.1791790842.db5f7862/package-lock.json 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/package-lock.json 2026-10-14 10:20:07.000000000 +0200 @@ -420,28 +420,42 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.1", + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/17-build_tagging.t new/openQA-5.1791966007.170875a4/t/17-build_tagging.t --- old/openQA-5.1791790842.db5f7862/t/17-build_tagging.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/17-build_tagging.t 2026-10-14 10:20:07.000000000 +0200 @@ -361,6 +361,9 @@ $t->get_ok('/group_overview/1001.json')->status_is(200)->content_type_is('application/json;charset=UTF-8'); $t->get_ok('/group_overview/1001' => {Accept => 'application/json'})->status_is(200) ->content_type_is('application/json;charset=UTF-8'); + $t->get_ok('/group_overview/1001.rss')->status_is(200)->content_type_is('application/rss+xml;charset=UTF-8'); + $t->get_ok('/group_overview/1001' => {Accept => 'application/rss+xml'})->status_is(200) + ->content_type_is('application/rss+xml;charset=UTF-8'); }; subtest 'tags with datetime' => sub { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/22-dashboard.t new/openQA-5.1791966007.170875a4/t/22-dashboard.t --- old/openQA-5.1791790842.db5f7862/t/22-dashboard.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/22-dashboard.t 2026-10-14 10:20:07.000000000 +0200 @@ -34,6 +34,7 @@ is $t->app->types->type('yaml'), 'text/yaml;charset=UTF-8', 'right type'; is $t->app->types->type('bz2'), 'application/x-bzip2', 'right type'; is $t->app->types->type('xz'), 'application/x-xz', 'right type'; + is $t->app->types->type('rss'), 'application/rss+xml;charset=UTF-8', 'right type'; }; # regular job groups shown @@ -59,6 +60,10 @@ ->content_like(qr/Erroneous parameters.*comments_limit/); $t->get_ok('/group_overview/1002?group=$*')->status_is(400) ->content_like(qr/group parameter is invalid.*matches null string many times/i); + $t->get_ok('/group_overview/1002.rss?limit_builds=a')->status_is(400)->content_type_like(qr{application/rss\+xml}) + ->content_like(qr/Erroneous parameters.*limit_builds/); + $t->get_ok('/group_overview/1002.rss?group=$*')->status_is(400) + ->content_like(qr/group parameter is invalid.*matches null string many times/i); my $id = $test_parent->id; $t->get_ok("/parent_group_overview/$id?limit_builds=a")->status_is(400) @@ -693,6 +698,66 @@ ->json_is('/limit_exceeded' => 2); }; +subtest 'RSS feed for job groups' => sub { + $t->get_ok('/group_overview/999999.rss')->status_is(404); + + $t->get_ok('/group_overview/1001.rss')->status_is(200)->content_type_is('application/rss+xml;charset=UTF-8'); + my $dom = Mojo::DOM->new->xml(1)->parse($t->tx->res->body); + is $dom->at('rss')->attr('version'), '2.0', 'RSS 2.0 root'; + like $dom->at('channel > title')->text, qr/opensuse/, 'channel title has group name'; + like $dom->at('channel > link')->text, qr{/group_overview/1001$}, 'channel link is group overview URL'; + like $dom->at('channel > atom\:link')->attr('href'), qr{^https?://.+/group_overview/1001\.rss$}, 'self atom link'; + like $dom->at('channel > description')->text, qr/opensuse/, 'channel description'; + + my @items = $dom->find('channel > item')->each; + ok scalar @items > 0, 'items returned'; + is $dom->at('channel > lastBuildDate')->text, $items[0]->at('pubDate')->text, 'lastBuildDate matches latest item'; + + for my $item (@items) { + ok $item->at('title')->text, 'item has title'; + like $item->at('link')->text, qr{/tests/overview\?}, 'item has tests overview link'; + like $item->at('link')->text, qr{groupid=1001}, 'item link has groupid'; + like $item->at('guid')->text, qr{^1001-}, 'item has guid'; + is $item->at('guid')->attr('isPermaLink'), 'false', 'guid is not permalink'; + like $item->at('pubDate')->text, qr/^\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} \+0000$/, + 'valid RFC-822 pubDate'; + } + + $t->get_ok('/group_overview/1001.rss?limit_builds=1')->status_is(200); + my $dom_limit1 = Mojo::DOM->new->xml(1)->parse($t->tx->res->body); + is scalar $dom_limit1->find('channel > item')->each, 1, 'only latest build returned with limit_builds=1'; + + my $empty_group = $job_groups->create({name => 'empty_feed_group'}); + $t->get_ok('/group_overview/' . $empty_group->id . '.rss')->status_is(200); + my $dom_empty = Mojo::DOM->new->xml(1)->parse($t->tx->res->body); + is scalar $dom_empty->find('channel > item')->each, 0, 'empty group has 0 items'; + ok !$dom_empty->at('channel > lastBuildDate'), 'empty group has no lastBuildDate'; + $empty_group->delete; +}; + +subtest 'RSS feed for parent groups' => sub { + $t->get_ok('/parent_group_overview/1.rss')->status_is(200)->content_type_is('application/rss+xml;charset=UTF-8'); + my $dom = Mojo::DOM->new->xml(1)->parse($t->tx->res->body); + is $dom->at('rss')->attr('version'), '2.0', 'RSS 2.0 root'; + like $dom->at('channel > link')->text, qr{/parent_group_overview/1$}, 'channel link is parent group overview URL'; + like $dom->at('channel > atom\:link')->attr('href'), qr{^https?://.+/parent_group_overview/1\.rss$}, + 'self atom link'; + my @items = $dom->find('channel > item')->each; + if (@items) { + like $items[0]->at('link')->text, qr{groupid=}, 'parent group item link has child group query'; + } +}; + +subtest 'RSS feed discoverability' => sub { + $t->get_ok('/group_overview/1001')->status_is(200) + ->element_exists('link[rel="alternate"][type="application/rss+xml"][href$="/group_overview/1001.rss"]') + ->element_exists('a#rss-feed-link[href$="/group_overview/1001.rss"]'); + + $t->get_ok('/parent_group_overview/1')->status_is(200) + ->element_exists('link[rel="alternate"][type="application/rss+xml"][href$="/parent_group_overview/1.rss"]') + ->element_exists('a#rss-feed-link[href$="/parent_group_overview/1.rss"]'); +}; + subtest 'dashboard_build_results coverage' => sub { my $build_results_mock = Test::MockModule->new('OpenQA::BuildResults'); $build_results_mock->redefine( @@ -868,6 +933,8 @@ ->content_like(qr{13\.1-BuildCOVERAGE_BUILD}); $t->get_ok('/dashboard_build_results?time_limit_days=99999')->status_is(200) ->content_like(qr{13\.1-BuildCOVERAGE_BUILD}); + $t->get_ok('/group_overview/1001.rss?time_limit_days=99999')->status_is(200) + ->content_like(qr{13\.1-BuildCOVERAGE_BUILD}); $group->update({always_show_version => undef}); }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/24-worker-overall.t new/openQA-5.1791966007.170875a4/t/24-worker-overall.t --- old/openQA-5.1791790842.db5f7862/t/24-worker-overall.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/24-worker-overall.t 2026-10-14 10:20:07.000000000 +0200 @@ -237,6 +237,16 @@ }; delete $worker->{_caps}; + subtest 'capabilities include DEVELOPER_CONNECTION_HINT setting if present' => sub { + my $hint = 'worker-host.example.com:5903'; + $global_settings->{DEVELOPER_CONNECTION_HINT} = $hint; + $capabilities = $worker->capabilities; + is $capabilities->{developer_connection_hint}, $hint, + 'capabilities contain configured developer connection hint'; + delete $global_settings->{DEVELOPER_CONNECTION_HINT}; + }; + delete $worker->{_caps}; + subtest 'deduce worker class from CPU architecture' => sub { delete $global_settings->{WORKER_CLASS}; $global_settings->{ARCH} = 'aarch64'; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/27-errorpages.t new/openQA-5.1791966007.170875a4/t/27-errorpages.t --- old/openQA-5.1791790842.db5f7862/t/27-errorpages.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/27-errorpages.t 2026-10-14 10:20:07.000000000 +0200 @@ -24,10 +24,41 @@ }; subtest 'error pages shown for OpenQA::WebAPI::Controller::Step' => sub { + my $schema = $t->app->schema; + my $job = $schema->resultset('Jobs')->find(99946); + my $real_needle_dir = Mojo::File->new($job->needle_dir)->realpath->to_string; + my $dir = $schema->resultset('NeedleDirs')->find_or_create( + { + path => $real_needle_dir, + name => 'fixtures' + }); + $schema->resultset('Needles')->find_or_create( + { + dir_id => $dir->id, + filename => 'inst-timezone-text.json', + }); + my $existing_job = 99946; $t->get_ok("/tests/$existing_job/modules/installer_timezone/steps/1")->status_is(302, 'redirection'); + + my $needle_path = "$real_needle_dir/inst-timezone-text.json"; + Mojo::File->new($real_needle_dir)->make_path; + Mojo::File->new('t/data/default-needle.json')->copy_to($needle_path); + + $t->get_ok("/tests/$existing_job/modules/installer_timezone/steps/1", {'X-Requested-With' => 'XMLHttpRequest'}) + ->status_is(200, 'step viewimg loads with needle present') + ->content_like(qr/inst-timezone-text/, 'needle name is shown') + ->content_unlike(qr/<span class="badge bg-danger text-light ms-1">deleted<\/span>/, + 'needle is not marked deleted') + ->content_like(qr/inst-timezone-text.*show-needle-info/s, 'needle info action icon is displayed'); + + unlink $needle_path or die "Failed to remove needle: $!"; + $t->get_ok("/tests/$existing_job/modules/installer_timezone/steps/1", {'X-Requested-With' => 'XMLHttpRequest'}) - ->status_is(200); + ->status_is(200, 'step viewimg loads with deleted needle') + ->content_like(qr/inst-timezone-text/, 'needle name is shown') + ->content_like(qr/<span class="badge bg-danger text-light ms-1">deleted<\/span>/, 'needle is marked deleted') + ->content_unlike(qr/inst-timezone-text.*show-needle-info/s, 'needle info action icon is hidden'); $t->get_ok("/tests/$existing_job/modules/installer_timezone/steps/1/src")->status_is(200) ->content_type_is('text/html;charset=UTF-8'); $t->get_ok("/tests/$existing_job/modules/installer_timezone/steps/1/src.txt")->status_is(200) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/34-developer_mode-unit.t new/openQA-5.1791966007.170875a4/t/34-developer_mode-unit.t --- old/openQA-5.1791790842.db5f7862/t/34-developer_mode-unit.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/34-developer_mode-unit.t 2026-10-14 10:20:07.000000000 +0200 @@ -94,6 +94,9 @@ # just copy the cookie with the required token from the regular user agent $t_livehandler->ua->cookie_jar($t->ua->cookie_jar); +my $developer_hint = 'worker-host.example.com:5903'; +sub connection_info ($hint = undef) { {vnc_arg => 'remotehost.qa:5991', developer_connection_hint => $hint} } + # login as arthur sub login ($user_name) { $test_case->login($t, $user_name); @@ -568,6 +571,14 @@ $app->determine_os_autoinst_web_socket_url($job), 'ws://remotehost.qa:20013/token99961/ws', 'URL for job with assigned worker and WORKER_HOSTNAME property'; + my $cmd_srv_url = 'ws://remotehost.qa:20013/token99961/ws'; + is_deeply [$app->determine_connection_params_for_job($job)], [$cmd_srv_url, connection_info()], + 'connection params without developer connection hint'; + $worker->set_property(DEVELOPER_CONNECTION_HINT => $developer_hint); + is_deeply [$app->determine_connection_params_for_job($job)], + [$cmd_srv_url, connection_info($developer_hint)], + 'connection params with developer connection hint'; + $worker->delete_properties(['DEVELOPER_CONNECTION_HINT']); is determine_web_ui_web_socket_url(99961), 'liveviewhandler/tests/99961/developer/ws-proxy', 'URL for livehandler'; @@ -719,7 +730,7 @@ { type => 'info', what => 'connecting to os-autoinst command server at ws://remotehost.qa:20013/token99961/ws', - data => {vnc_arg => 'remotehost.qa:5991'}, + data => connection_info(), }); $t_livehandler->message_ok('another message received'); $t_livehandler->json_message_is( @@ -764,7 +775,7 @@ { type => 'info', what => 'connecting to os-autoinst command server at ws://remotehost.qa:20013/token99961/ws', - data => {vnc_arg => 'remotehost.qa:5991'}, + data => connection_info(), }); $t_livehandler->message_ok('another message received'); $t_livehandler->json_message_is( @@ -819,7 +830,7 @@ { type => 'info', what => 'connecting to os-autoinst command server at ws://remotehost.qa:20013/token99961/ws', - data => {vnc_arg => 'remotehost.qa:5991'}, + data => connection_info(), }); $t_livehandler->message_ok('another message received'); $t_livehandler->json_message_is( @@ -892,7 +903,7 @@ { type => 'info', what => 'connecting to os-autoinst command server at ws://remotehost.qa:20013/token99961/ws', - data => {vnc_arg => 'remotehost.qa:5991'}, + data => connection_info(), }); $t_livehandler->message_ok('another message received'); $t_livehandler->json_message_is( @@ -916,6 +927,24 @@ 0, 'status only js transactions cleaned'; }; + subtest 'connecting message includes developer connection hint if configured' => sub { + my $worker = $workers->find({job_id => 99961}); + $worker->set_property(DEVELOPER_CONNECTION_HINT => $developer_hint); + $t_livehandler->websocket_ok( + '/liveviewhandler/tests/99961/developer/ws-proxy/status', + 'establish status-only ws connection from JavaScript to livehandler' + ); + $t_livehandler->message_ok('message received'); + $t_livehandler->json_message_is( + { + type => 'info', + what => 'connecting to os-autoinst command server at ws://remotehost.qa:20013/token99961/ws', + data => connection_info($developer_hint), + }); + $t_livehandler->finish_ok(); + $worker->delete_properties(['DEVELOPER_CONNECTION_HINT']); + }; + subtest 'error handling' => sub { $t_livehandler->get_ok('/some/route')->status_is(404)->content_is('Not found'); }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/38-workers-table.t new/openQA-5.1791966007.170875a4/t/38-workers-table.t --- old/openQA-5.1791790842.db5f7862/t/38-workers-table.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/38-workers-table.t 2026-10-14 10:20:07.000000000 +0200 @@ -133,6 +133,20 @@ is $worker->vnc_argument, 'remotehost.foo.bar:5991', 'WORKER_HOSTNAME used if set'; }; +subtest 'developer connection hint' => sub { + my $worker = $workers->first; + my $hint = 'worker-host.example.com:5903'; + $worker->delete_properties(['DEVELOPER_CONNECTION_HINT']); + is $worker->developer_connection_hint, undef, 'developer_connection_hint returns undef when unset'; + $worker->set_property(DEVELOPER_CONNECTION_HINT => ''); + is $worker->developer_connection_hint, undef, 'developer_connection_hint returns undef when empty'; + $worker->set_property(DEVELOPER_CONNECTION_HINT => ' '); + is $worker->developer_connection_hint, undef, 'developer_connection_hint returns undef when whitespace only'; + $worker->set_property(DEVELOPER_CONNECTION_HINT => $hint); + is $worker->developer_connection_hint, $hint, 'developer_connection_hint returns configured hint'; + $worker->delete_properties(['DEVELOPER_CONNECTION_HINT']); +}; + subtest 'worker reservation model' => sub { my $worker = $workers->first; $worker->delete_properties([RESERVATION_PROPERTIES]); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/api/01-workers.t new/openQA-5.1791966007.170875a4/t/api/01-workers.t --- old/openQA-5.1791790842.db5f7862/t/api/01-workers.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/api/01-workers.t 2026-10-14 10:20:07.000000000 +0200 @@ -516,6 +516,26 @@ $schema->txn_rollback; }; +subtest 'developer connection hint registration' => sub { + my %reg_params = ( + host => 'hint-host', + instance => 1, + cpu_arch => 'x86_64', + mem_max => 4096, + worker_class => 'qemu', + websocket_api_version => WEBSOCKET_API_VERSION, + ); + my $stored_hint = sub { $workers->find({host => 'hint-host', instance => 1})->developer_connection_hint }; + + $t->post_ok('/api/v1/workers', form => {%reg_params, developer_connection_hint => 'worker-host.example.com:5903'}) + ->status_is(200, 'worker registered with developer connection hint'); + is $stored_hint->(), 'worker-host.example.com:5903', 'developer connection hint stored on registration'; + + $t->post_ok('/api/v1/workers', form => \%reg_params)->status_is(200, 'worker re-registered without hint'); + is $stored_hint->(), undef, 'stale developer connection hint cleared when re-registered without one'; + $workers->find({host => 'hint-host', instance => 1})->delete; +}; + subtest 'worker registration reservation inheritance' => sub { $schema->txn_begin; my $users = $schema->resultset('Users'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/ui/10-tests_overview.t new/openQA-5.1791966007.170875a4/t/ui/10-tests_overview.t --- old/openQA-5.1791790842.db5f7862/t/ui/10-tests_overview.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/ui/10-tests_overview.t 2026-10-14 10:20:07.000000000 +0200 @@ -452,6 +452,24 @@ my $jobs = $driver->execute_script($query_all_job_ids_sorted); is_deeply $jobs, [qw(jobid_td_99938 jobid_td_99946)], 'expected jobs present'; }; + + subtest 'module filter is populated in the form and clear filter button resets it' => sub { + $driver->get("/tests/overview?arch=&distri=opensuse&modules=$module"); + is element_prop('modules'), $module, 'module filter is populated in form'; + wait_for_element( + selector => qq{//*[\@id='filter-panel']/*[\@class='card-header']/span[text()='current: $module']}, + method => 'xpath', + desc => "module filter '$module' visible on form header", + ); + $driver->find_element('#filter-panel .card-header')->click(); + $driver->find_element_by_id('filter-reset-button')->click(); + wait_until sub { $driver->get_current_url !~ /modules=$module/ }, + 'clear filter button removes module filter from URL', 10; + like $driver->get_current_url, qr/distri=opensuse/, 'clear filter button keeps page context parameters in URL'; + is element_prop_by_selector('#filter-panel .card-header span', 'textContent'), + 'no filter present, click to toggle filter form', + 'clear filter button resets filter form header text'; + }; }; subtest 'filtering by module_re' => sub { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/ui/14-dashboard.t new/openQA-5.1791966007.170875a4/t/ui/14-dashboard.t --- old/openQA-5.1791790842.db5f7862/t/ui/14-dashboard.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/ui/14-dashboard.t 2026-10-14 10:20:07.000000000 +0200 @@ -173,6 +173,17 @@ is $driver->get_current_url, $url, 'URL parameters for filter are correct'; }; +subtest 'clear filter button on index page' => sub { + $driver->get('/?group=opensuse'); + wait_for_ajax; + (my $base_url = $driver->get_current_url) =~ s/\?.*//; + $driver->find_element('#filter-panel .card-header')->click(); + $driver->find_element_by_id('filter-reset-button')->click(); + wait_until sub { $driver->get_current_url !~ /group=opensuse/ }, + 'clear filter button removes group parameter from URL', 10; + like $driver->get_current_url, qr{^\Q$base_url\E\??}, 'clear filter button leaves a URL without query parameters'; +}; + subtest 'Ignore job groups on dashboard' => sub { my $job_groups = $schema->resultset('JobGroups'); my $parent_groups = $schema->resultset('JobGroupParents'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/ui/18-tests-details.t new/openQA-5.1791966007.170875a4/t/ui/18-tests-details.t --- old/openQA-5.1791790842.db5f7862/t/ui/18-tests-details.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/ui/18-tests-details.t 2026-10-14 10:20:07.000000000 +0200 @@ -10,12 +10,13 @@ use lib "$FindBin::Bin/../lib", "$FindBin::Bin/../../external/os-autoinst-common/lib"; use Test::Mojo; use Test::Warnings qw(:all :report_warnings); +use Date::Format 'time2str'; use Mojo::Base -signatures; use Mojo::JSON qw(decode_json encode_json); use Mojo::File qw(path); use Mojo::IOLoop; use Mojo::URL; -use OpenQA::Test::TimeLimit '40'; +use OpenQA::Test::TimeLimit '60'; use OpenQA::Test::Case; use OpenQA::Test::Utils qw(prepare_clean_needles_dir prepare_default_needle wait_for); use OpenQA::Client; @@ -67,6 +68,19 @@ my $assets = $schema->resultset('Assets'); $assets->find({type => 'iso', name => 'openSUSE-13.1-DVD-i586-Build0091-Media.iso'})->update({size => 0}); + + $schema->resultset('Needles')->create( + { + dir_id => 1, + filename => 'inst-timezone.json', + last_seen_module_id => 10, + last_seen_time => time2str('%Y-%m-%d %H:%M:%S', time - 100000, 'UTC'), + last_matched_module_id => 9, + last_matched_time => time2str('%Y-%m-%d %H:%M:%S', time - 50000, 'UTC'), + file_present => 1, + t_created => time2str('%Y-%m-%d %H:%M:%S', time - 200000, 'UTC'), + t_updated => time2str('%Y-%m-%d %H:%M:%S', time - 200000, 'UTC'), + }); } prepare_database; @@ -172,9 +186,34 @@ }; subtest 'displaying image result with candidates' => sub { - $driver->find_element('[href="#step/bootloader/1"]')->click(); + my $step_el = $driver->find_element('[href="#step/bootloader/1"]'); + $step_el->click(); + my $needles = find_candidate_needles; + is_deeply $needles, {'inst-bootmenu' => ['100%: bootmenu-dvd-12.3']}, 'correct tags displayed' + or always_explain $needles; + $step_el->click(); +}; + +subtest 'displaying image result with deleted candidate' => sub { + my $step_el = $driver->find_element('[href="#step/installer_timezone/1"]'); + $step_el->click(); + my $needles = find_candidate_needles; + my $inst_timezone_list = $needles->{'inst-timezone'} // []; + is scalar @$inst_timezone_list, 1, 'exactly one candidate for inst-timezone'; + like $inst_timezone_list->[0], qr/inst-timezone\s+deleted/, 'inst-timezone has deleted badge'; + $step_el->click(); +}; + +subtest 'displaying image result with present candidate' => sub { + $driver->get('/tests/99946'); + my $step_el = $driver->find_element('[href="#step/installer_timezone/1"]'); + $step_el->click(); my $needles = find_candidate_needles; - is_deeply $needles, {'inst-bootmenu' => []}, 'correct tags displayed' or always_explain $needles; + my $inst_timezone_list = $needles->{'inst-timezone'} // []; + is scalar @$inst_timezone_list, 1, 'exactly one candidate for inst-timezone'; + like $inst_timezone_list->[0], qr/inst-timezone-text$/, 'inst-timezone-text candidate has no deleted badge'; + unlike $inst_timezone_list->[0], qr/deleted/, 'inst-timezone-text candidate does not have deleted badge'; + $driver->get('/tests/99937'); }; subtest 'filtering' => sub { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/ui/25-developer_mode.t new/openQA-5.1791966007.170875a4/t/ui/25-developer_mode.t --- old/openQA-5.1791790842.db5f7862/t/ui/25-developer_mode.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/ui/25-developer_mode.t 2026-10-14 10:20:07.000000000 +0200 @@ -76,6 +76,16 @@ inject_java_script(qq{handleMessageFromWebsocketConnection(developerMode.wsConnection, { data: "$message" });}); } +# returns the "connecting" message as sent by the live view handler, optionally with a developer connection hint +sub connecting_message ($hint = undef) { + my $hint_field = defined $hint ? qq(,\\"developer_connection_hint\\":\\"$hint\\") : ''; + return +qq({\\"type\\":\\"info\\",\\"what\\":\\"connecting\\",\\"data\\":{\\"vnc_arg\\":\\"remotehost:5991\\"$hint_field}}); +} + +my $default_vnc_notice + = qr/You might be able to connect to the SUT at remotehost:5991 via VNC with shared mode enabled \(eg\. vncviewer remotehost:5991 -Shared for TigerVNC\)\./; + # checks whether the commands sent by the JavaScript since the last call matches the expected commands sub assert_sent_commands ($expected, $test_name) { my $sent_cmds @@ -186,8 +196,7 @@ element_hidden('#developer-panel .card-body'); # fake "connecting" message which contains VNC argument - my $connecting = '{\"type\":\"info\",\"what\":\"connecting\",\"data\":{\"vnc_arg\":\"remotehost:5991\"}}'; - fake_message_from_ws_connection($connecting); + fake_message_from_ws_connection(connecting_message()); # running, current module known fake_state(developerMode => {currentModule => '"installation-welcome"'}); @@ -221,10 +230,26 @@ # currently paused fake_state(developerMode => {isPaused => '"some reason"'}); - element_visible( - '#developer-vnc-notice', -qr/You might be able to connect to the SUT at remotehost:5991 via VNC with shared mode enabled \(eg\. vncviewer remotehost:5991 -Shared for TigerVNC\)\./, - ); + element_visible('#developer-vnc-notice', $default_vnc_notice); + element_hidden('#developer-connection-hint-notice'); + + fake_message_from_ws_connection(connecting_message('worker-host.example.com:5903')); + element_hidden('#developer-vnc-notice'); + element_visible('#developer-connection-hint-notice', qr/worker-host\.example\.com\:5903/); + + fake_message_from_ws_connection(connecting_message('<b>custom plain hint</b>')); + element_hidden('#developer-vnc-notice'); + element_visible('#developer-connection-hint-notice', qr/<b>custom plain hint<\/b>/); + is scalar @{$driver->find_elements('#developer-connection-hint-notice b')}, 0, + 'custom hint plain text is not rendered as HTML elements'; + + fake_message_from_ws_connection(connecting_message('')); + element_visible('#developer-vnc-notice', $default_vnc_notice); + element_hidden('#developer-connection-hint-notice'); + + fake_message_from_ws_connection(connecting_message()); + element_visible('#developer-vnc-notice', $default_vnc_notice); + element_hidden('#developer-connection-hint-notice'); element_visible( '#developer-panel .card-header', qr/paused at module: installation-welcome/, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/t/ui/26-jobs_restart.t new/openQA-5.1791966007.170875a4/t/ui/26-jobs_restart.t --- old/openQA-5.1791790842.db5f7862/t/ui/26-jobs_restart.t 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/t/ui/26-jobs_restart.t 2026-10-14 10:20:07.000000000 +0200 @@ -361,6 +361,64 @@ expected_job_id_regex(++$i), "restarted link for $_ is correct" for @cluster_jobs; }; + + subtest 'no automatic redirect on restart parent skipping OK children and force restart' => sub { + my $cleanup = scope_guard sub { + $job_deps->search({parent_job_id => 99900, child_job_id => 99901})->update({dependency => CHAINED}); + $jobs->search({id => [99900 .. 99903]})->update({clone_id => undef}); + $jobs->search({id => {'>' => 99981}})->delete; + }; + + ensure_asset_exists('00099900-openSUSE-13.1-DVD-i586-Build0091-Media.iso'); + $job_deps->search({parent_job_id => 99900, child_job_id => 99901})->update({dependency => DIRECTLY_CHAINED}); + $jobs->search({id => [99900 .. 99903]})->update({clone_id => undef}); + $jobs->search({id => {'>' => 99981}})->delete; + + subtest 'restart parent skipping OK children shows flash notice without redirecting' => sub { + is $driver->get('/tests/overview?distri=opensuse&version=13.1&build=0091&groupid=1001'), + 1, 'refresh test overview page'; + update_last_job_id; + $driver->find_element('#res_DVD_i586_support_server .restart')->click(); + wait_for_ajax(msg => 'fail to restart job because of directly chained parent'); + wait_until(sub { flash_messages =~ m/Direct parent 99900 needs to be cloned as well/s }, + 'direct parent error shown', 20); + verify_parent_skip_ok_button(click => 1) or return; + wait_for_ajax(msg => 'parent job restarted skipping OK children'); + like $driver->get_current_url, qr{/tests/overview}, 'stays on overview page without automatic redirect'; + wait_until(sub { flash_messages =~ m/The job has been restarted/s }, 'notice flash message shown'); + my $clone_id = $jobs->find(99900)->clone_id; + like + $driver->find_element_by_link_text('new job')->get_attribute('href'), + qr{/tests/$clone_id$}, + 'link to new job is correct in flash message'; + is $driver->find_element('#res_DVD_i586_create_hdd .fa-solid.fa-circle')->get_attribute('title'), + 'Scheduled', + 'create_hdd is marked as restarted'; + }; + + subtest 'force restart shows flash notice without redirecting' => sub { + $jobs->search({id => [99900 .. 99903]})->update({clone_id => undef}); + + is $driver->get('/tests/overview?distri=opensuse&version=13.1&build=0091&groupid=1001'), + 1, 'refresh test overview page'; + $driver->find_element('#res_DVD_i586_support_server .restart')->click(); + wait_for_ajax(msg => 'fail to restart job because of directly chained parent'); + wait_until(sub { flash_messages =~ m/Direct parent 99900 needs to be cloned as well/s }, + 'direct parent error shown', 20); + $driver->find_element('#flash-messages button.force-restart')->click(); + wait_for_ajax(msg => 'forced job restart in overview page'); + like $driver->get_current_url, qr{/tests/overview}, 'stays on overview page without automatic redirect'; + wait_until(sub { flash_messages =~ m/The job has been restarted/s }, 'notice flash message shown'); + my $clone_id = $jobs->find(99901)->clone_id; + like + $driver->find_element_by_link_text('new job')->get_attribute('href'), + qr{/tests/$clone_id$}, + 'link to new job is correct in flash message'; + is $driver->find_element('#res_DVD_i586_support_server .fa-solid.fa-circle')->get_attribute('title'), + 'Scheduled', + 'support_server is marked as restarted'; + }; + }; }; subtest 'wait_for_element error handling' => sub { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/templates/webapi/main/_filter_form_buttons.html.ep new/openQA-5.1791966007.170875a4/templates/webapi/main/_filter_form_buttons.html.ep --- old/openQA-5.1791790842.db5f7862/templates/webapi/main/_filter_form_buttons.html.ep 1970-01-01 01:00:00.000000000 +0100 +++ new/openQA-5.1791966007.170875a4/templates/webapi/main/_filter_form_buttons.html.ep 2026-10-14 10:20:07.000000000 +0200 @@ -0,0 +1,2 @@ +<button type="submit" class="btn btn-primary" id="filter-apply-button">Apply</button> +<button type="button" id="filter-reset-button" class="btn btn-secondary">Clear filter</button> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/templates/webapi/main/group_feed.rss.ep new/openQA-5.1791966007.170875a4/templates/webapi/main/group_feed.rss.ep --- old/openQA-5.1791790842.db5f7862/templates/webapi/main/group_feed.rss.ep 1970-01-01 01:00:00.000000000 +0100 +++ new/openQA-5.1791966007.170875a4/templates/webapi/main/group_feed.rss.ep 2026-10-14 10:20:07.000000000 +0200 @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> + <channel> + <title><%= $appname %>: <%= $group->{full_name} %></title> + <link><%= $feed_link %></link> + <atom:link href="<%= $feed_self_link %>" rel="self" type="application/rss+xml"/> + <description>Recent builds of <%= $group->{full_name} %></description> +% if (my $first = $feed_items->[0]) { + <lastBuildDate><%= $first->{date} %></lastBuildDate> +% } +% for my $item (@$feed_items) { + <item> + <title><%= $item->{title} %></title> + <link><%= $item->{link} %></link> + <guid isPermaLink="false"><%= $item->{guid} %></guid> + <pubDate><%= $item->{date} %></pubDate> + </item> +% } + </channel> +</rss> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/templates/webapi/main/group_overview.html.ep new/openQA-5.1791966007.170875a4/templates/webapi/main/group_overview.html.ep --- old/openQA-5.1791790842.db5f7862/templates/webapi/main/group_overview.html.ep 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/templates/webapi/main/group_overview.html.ep 2026-10-14 10:20:07.000000000 +0200 @@ -3,6 +3,11 @@ %= include 'layouts/info' +% content_for 'head' => begin + <link rel="alternate" type="application/rss+xml" title="<%= $group->{full_name} %> builds" + href="<%= url_for('group_overview', groupid => $group->{id}, format => 'rss') %>"> +% end + % content_for 'ready_function' => begin updateTimeago(); toggleFullscreenMode(<%= $fullscreen %>); @@ -19,6 +24,12 @@ </button> </form> % } +<div class="corner-buttons"> + <a id="rss-feed-link" class="btn btn-light" title="Subscribe to the RSS feed of this job group" + href="<%= url_for('group_overview', groupid => $group->{id}, format => 'rss') %>"> + <i class="fa-solid fa-rss"></i> RSS + </a> +</div> <h2> Last Builds for % if ($group->{parent_id}) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/templates/webapi/main/index.html.ep new/openQA-5.1791966007.170875a4/templates/webapi/main/index.html.ep --- old/openQA-5.1791790842.db5f7862/templates/webapi/main/index.html.ep 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/templates/webapi/main/index.html.ep 2026-10-14 10:20:07.000000000 +0200 @@ -93,7 +93,7 @@ <label class="form-label p-2" for="filter-autorefresh-interval">seconds</label> </p> </div> - <button type="submit" class="btn btn-primary" id="filter-apply-button">Apply</button> + %= include 'main/_filter_form_buttons' </form> </div> </div> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/templates/webapi/main/parent_group_overview.html.ep new/openQA-5.1791966007.170875a4/templates/webapi/main/parent_group_overview.html.ep --- old/openQA-5.1791790842.db5f7862/templates/webapi/main/parent_group_overview.html.ep 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/templates/webapi/main/parent_group_overview.html.ep 2026-10-14 10:20:07.000000000 +0200 @@ -3,6 +3,11 @@ %= include 'layouts/info' +% content_for 'head' => begin + <link rel="alternate" type="application/rss+xml" title="<%= $group->{full_name} %> builds" + href="<%= url_for('parent_group_overview', groupid => $group->{id}, format => 'rss') %>"> +% end + % content_for 'ready_function' => begin updateTimeago(); alignBuildLabels(); @@ -18,6 +23,12 @@ </button> </form> % } +<div class="corner-buttons"> + <a id="rss-feed-link" class="btn btn-light" title="Subscribe to the RSS feed of this job group" + href="<%= url_for('parent_group_overview', groupid => $group->{id}, format => 'rss') %>"> + <i class="fa-solid fa-rss"></i> RSS + </a> +</div> <h2 class="mb-4"> Last Builds for <%= $group->{name} %> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/templates/webapi/step/viewimg.html.ep new/openQA-5.1791966007.170875a4/templates/webapi/step/viewimg.html.ep --- old/openQA-5.1791790842.db5f7862/templates/webapi/step/viewimg.html.ep 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/templates/webapi/step/viewimg.html.ep 2026-10-14 10:20:07.000000000 +0200 @@ -53,8 +53,12 @@ </td> <td> %= $needle->{name} + % if ($needle->{deleted}) { + <span class="badge bg-danger text-light ms-1">deleted</span> + % } </td> <td> + % if (!$needle->{deleted}) { <i class="fa-solid fa-image trigger-diff" title="View area-only diff" data-diff="area-only-diff"> @@ -72,6 +76,7 @@ <div><span>Last seen:</span><span><%= popover_link $needle->{last_seen}, $needle->{last_seen_link} %></span></div> </div>"> </i> + % } </td> </tr> % } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/templates/webapi/test/live.html.ep new/openQA-5.1791966007.170875a4/templates/webapi/test/live.html.ep --- old/openQA-5.1791790842.db5f7862/templates/webapi/test/live.html.ep 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/templates/webapi/test/live.html.ep 2026-10-14 10:20:07.000000000 +0200 @@ -45,9 +45,12 @@ </div> <div class="row"> <div class="col-sm-12" id="developer-flash-messages"> - <div id="developer-vnc-notice" class="alert alert-secondary developer-mode-element" role="alert" data-visible-on="isPaused,vncArg"> + <div id="developer-vnc-notice" class="alert alert-secondary developer-mode-element" role="alert" data-visible-on="isPaused,vncArg" data-hidden-on="developerConnectionHint"> You might be able to connect to the SUT at <span class="vnc-arg">?</span> via VNC with shared mode enabled (eg. <code>vncviewer <span class="vnc-arg">?</span> -Shared</code> for TigerVNC). </div> + <div id="developer-connection-hint-notice" class="alert alert-secondary developer-mode-element" role="alert" data-visible-on="isPaused,developerConnectionHint"> + <span class="developer-connection-hint-text"></span> + </div> </div> </div> </div> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/templates/webapi/test/overview.html.ep new/openQA-5.1791966007.170875a4/templates/webapi/test/overview.html.ep --- old/openQA-5.1791790842.db5f7862/templates/webapi/test/overview.html.ep 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/templates/webapi/test/overview.html.ep 2026-10-14 10:20:07.000000000 +0200 @@ -203,7 +203,7 @@ </div> </div> </div> - <button type="submit" class="btn btn-primary">Apply</button> + %= include 'main/_filter_form_buttons' </form> </div> </div> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openQA-5.1791790842.db5f7862/tools/ci/autoinst.sha new/openQA-5.1791966007.170875a4/tools/ci/autoinst.sha --- old/openQA-5.1791790842.db5f7862/tools/ci/autoinst.sha 2026-10-12 09:40:42.000000000 +0200 +++ new/openQA-5.1791966007.170875a4/tools/ci/autoinst.sha 2026-10-14 10:20:07.000000000 +0200 @@ -1 +1 @@ -5.044000-2b02af1759f2aece404e97b9a79ded32695b77f3 \ No newline at end of file +5.044000-3b85101553bc9ee20b29916a47d5ce879de2f2f1 \ No newline at end of file ++++++ openQA.obsinfo ++++++ --- /var/tmp/diff_new_pack.WQYcOB/_old 2026-10-14 18:49:42.700586373 +0200 +++ /var/tmp/diff_new_pack.WQYcOB/_new 2026-10-14 18:49:42.706586624 +0200 @@ -1,5 +1,5 @@ name: openQA -version: 5.1791790842.db5f7862 -mtime: 1791790842 -commit: db5f7862843ed4dd9359f8b9c10f78c3b77571f5 +version: 5.1791966007.170875a4 +mtime: 1791966007 +commit: 170875a488414cd9d9e967ce386c221aa51aad88
