From b131d7990ee6da6dfeaf69fd524f9bd405ddb8929c1d5a1d8981ae4a09f1b41d Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Fri, 21 Feb 2025 09:12:22 +0000 Subject: [PATCH 1/2] [info=783d2e3bb195c6409132c66eb04c36d0232372b201170fc36d853c9dbdd3cdb0] OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:cockpit/cockpit?expand=0&rev=214 --- _scmsync.obsinfo | 8 +- build.specials.obscpio | 2 +- cockpit.changes | 7 + cockpit.spec | 2 + packagekit-single-install.patch | 372 ++++++++++++++++++++++++++++++++ 5 files changed, 386 insertions(+), 5 deletions(-) create mode 100644 packagekit-single-install.patch diff --git a/_scmsync.obsinfo b/_scmsync.obsinfo index fd1acd9..2645d2a 100644 --- a/_scmsync.obsinfo +++ b/_scmsync.obsinfo @@ -1,5 +1,5 @@ -mtime: 1739521267 -commit: ba3323415857354d7a3517f77ac133fcd740ab3611acf123400d5cd9900a70f8 +mtime: 1740090299 +commit: 783d2e3bb195c6409132c66eb04c36d0232372b201170fc36d853c9dbdd3cdb0 url: https://src.opensuse.org/cockpit/cockpit.git -revision: ba3323415857354d7a3517f77ac133fcd740ab3611acf123400d5cd9900a70f8 -projectscmsync: https://src.opensuse.org/cockpit/_ObsPrj.git#0920f033fc9b63d4acd622ef39ae7f6faab099134f58a645d8c8a1f2c1a6b912 +revision: 783d2e3bb195c6409132c66eb04c36d0232372b201170fc36d853c9dbdd3cdb0 +projectscmsync: https://src.opensuse.org/cockpit/_ObsPrj.git#6afc009e3ae4f54a1bc4208d8bbab86c16397236aec2eca493700e2ac87e1ff4 diff --git a/build.specials.obscpio b/build.specials.obscpio index fc15e25..3fb75db 100644 --- a/build.specials.obscpio +++ b/build.specials.obscpio @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a38c0e7d7077887fbd767316dbb1727736b9ed522862fa2c0c006e2e42f4318 +oid sha256:726d587120395772861f0fced00a006f58ca3fc73b181607f2586588ddd8d6b1 size 256 diff --git a/cockpit.changes b/cockpit.changes index d1614f8..968e2c0 100644 --- a/cockpit.changes +++ b/cockpit.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Thu Feb 20 22:22:32 UTC 2025 - Miika Alikirri + +- Add functionality to cockpit-packagekit that allows selecting what updates + should be applied +- Added packagekit-single-install.patch file that adds this functionality + ------------------------------------------------------------------- Fri Feb 7 09:24:33 UTC 2025 - Alice Brooks diff --git a/cockpit.spec b/cockpit.spec index 786ac6f..f075575 100644 --- a/cockpit.spec +++ b/cockpit.spec @@ -76,6 +76,7 @@ Patch108: 0007-Remove-DynamicUser-setting-as-these-conflict-with-re.patch Patch103: 0004-leap-gnu18-removal.patch Patch104: selinux_libdir.patch Patch105: fix-libexecdir.patch +Patch106: packagekit-single-install.patch Patch201: remove_rh_links.patch @@ -212,6 +213,7 @@ BuildRequires: python3-pytest-timeout %patch -P 3 -p1 %patch -P 4 -p1 %patch -P 5 -p1 +%patch -P 106 -p1 # SLE Micro specific patches diff --git a/packagekit-single-install.patch b/packagekit-single-install.patch new file mode 100644 index 0000000..13d6372 --- /dev/null +++ b/packagekit-single-install.patch @@ -0,0 +1,372 @@ +From 291aba8127cb3e44e82b164e75d1063f3ae7fe9c Mon Sep 17 00:00:00 2001 +From: Miika Alikirri +Date: Wed, 29 Jan 2025 14:04:39 +0200 +Subject: pkg/pacagekit: Update individual packages + +Ability to select individual packages allows more control for updates. + +The exact behavior is distrobution specific. For example, on tumbleweed +packagekit backend will ignore the list of packages and run "zypper dup" +instead. + +The selection of individual packages is implemented by using a context +provider and a reducer to make the UI updates snappy. A more naive +approach that requires rendering the whole list of packages will freeze +up the UI for multiple seconds when there's hundreds of packages. And +tens of seconds when there are thousands of packages. +--- + pkg/packagekit/updates.jsx | 239 ++++++++++++++++++++++++++++++++---- + pkg/packagekit/updates.scss | 6 +- + 2 files changed, 219 insertions(+), 26 deletions(-) + +diff --git a/pkg/packagekit/updates.jsx b/pkg/packagekit/updates.jsx +index 1feb57a0f..4fb68847f 100644 +--- a/pkg/packagekit/updates.jsx ++++ b/pkg/packagekit/updates.jsx +@@ -77,6 +77,7 @@ import * as python from "python.js"; + import callTracerScript from './callTracer.py'; + + import "./updates.scss"; ++import { Checkbox } from '@patternfly/react-core'; + + const _ = cockpit.gettext; + +@@ -90,6 +91,7 @@ const UPDATES = { + ALL: 0, + SECURITY: 1, + KPATCHES: 2, ++ SELECTED: 3, + }; + + function init() { +@@ -114,6 +116,196 @@ function init() { + PK_STATUS_LOG_STRINGS[PK.Enum.STATUS_SIGCHECK] = _("Verified"); + } + ++/** ++ * @typedef SelecetedState ++ * @type {object} ++ * @property {boolean} allSelected - Are all items selected ++ * @property {Object.} selected - (Un)selected items. ++ * If allSelected is set, this refers to unselecetd ++ */ ++ ++/** ++ * @typedef SelecetedAction ++ * @type {object} ++ * @property {"ADD" | "REMOVE" | "ALL" | "NONE"} type - Type of reducer action ++ * @property {string=} id - Added removed item, only used by "ADD" and "REMOVE" ++ */ ++ ++const SelectedContext = React.createContext({selected: {}, allSelected: true}); ++ ++const SelectedStore = props => { ++ ++ /** ++ * @argument {SelecetedState} state ++ * @argument {SelecetedAction} action ++ */ ++ const reducer = (state, action) => { ++ switch (action.type) { ++ case "ADD": ++ if (action.id) { ++ if (state.allSelected) ++ delete state.selected[action.id]; ++ else ++ state.selected[action.id] = true; ++ } ++ break; ++ case "REMOVE": ++ if (action.id) { ++ if (state.allSelected) ++ state.selected[action.id] = true; ++ else ++ delete state.selected[action.id]; ++ } ++ break; ++ case "ALL": ++ state.allSelected = true; ++ state.selected = {}; ++ break; ++ case "NONE": ++ state.allSelected = false; ++ state.selected = {}; ++ break; ++ default: ++ break; ++ } ++ ++ return {...state}; ++ } ++ ++ const [state, dispatch] = React.useReducer(reducer, {selected: {}, allSelected: true}); ++ ++ return ; ++}; ++ ++/** ++ * @returns {{state: SelecetedState, dispatch: (arg: SelecetedAction) => void}} ++ */ ++export const useSelected = () => React.useContext(SelectedContext); ++ ++/** ++ * @param {{ ++ * onClick: (state: SelecetedState) => void ++ * updates: string[], ++ * num_updates: number ++ * }} props; ++ */ ++const SelectedButton = (props) => { ++ const { state, dispatch } = useSelected(); ++ const { ++ onClick, ++ updates, ++ num_updates, ++ } = props; ++ ++ ++ const buttonText = () => { ++ if (state.allSelected && Object.keys(state.selected).length == 0 || ++ !state.allSelected && Object.keys(state.selected).length == num_updates) ++ return _("Install all updates"); ++ ++ const selectLen = calculateSelected(updates, state).length; ++ return `${_("Install selected updates")} (${selectLen})`; ++ } ++ ++ return ( ++ ++ ); ++} ++ ++const SelectedAllButton = (props) => { ++ const { state, dispatch } = useSelected(); ++ ++ const dispatchSelect = () => { ++ if (state.allSelected) { ++ dispatch({type: "NONE"}); ++ } else { ++ dispatch({type: "ALL"}); ++ } ++ } ++ ++ return ( ++ ++ ); ++} ++ ++const SelectedSwitch = (props) => { ++ const { state, dispatch } = useSelected(); ++ ++ const dispatchChecked = checked => { ++ if (checked) { ++ dispatch({type: "ADD", id: props.id}); ++ } else { ++ dispatch({type: "REMOVE", id: props.id}); ++ } ++ } ++ ++ const isChecked = () => { ++ if (state.allSelected) { ++ return !!!state.selected[props.id]; ++ } else { ++ return !!state.selected[props.id]; ++ } ++ } ++ ++ return ( ++ dispatchChecked(checked)} /> ++ ); ++} ++ ++/** ++ * @param {{ ++* updates: string[], ++* }} props; ++*/ ++const WebConsoleRestartWarn = (props) => { ++ const { state } = useSelected(); ++ ++ if (calculateSelected(props.updates, state).findIndex((value) => value.includes("cockpit-ws")) === -1) ++ return null; ++ ++ return ( ++ ++ ++ ++ ++ {_("Danger alert:")} ++ {_("Web Console will restart")} ++ ++ ++ ++ ++ ++ ++ ++ ++ ); ++} ++ ++/** ++ * @param {string[]} allIds ++ * @param {SelecetedState} state ++ * @returns {string[]} ++ */ ++function calculateSelected(allIds, state) { ++ const selected = Object.keys(state.selected); ++ ++ if (!state.allSelected) { ++ return selected; ++ } ++ ++ if (selected.length === 0) { ++ return allIds; ++ } ++ ++ return allIds.filter((id) => !!!state.selected[id]); ++} ++ ++ + // parse CVEs from an arbitrary text (changelog) and return URL array + function parseCVEs(text) { + if (!text) +@@ -398,6 +590,7 @@ function updateItem(remarkable, info, pkgNames, key) { + { title: {info.version}, props: { className: "version" } }, + { title: {type}, props: { className: "type" } }, + { title: descriptionFirstLine, props: { className: "changelog" } }, ++ { title: , props: { className: "select-update" } }, + ], + props: { + key, +@@ -448,6 +641,7 @@ const UpdatesList = ({ updates }) => { + { title: _("Version"), transforms: [cellWidth(15)] }, + { title: _("Severity"), transforms: [cellWidth(15)] }, + { title: _("Details"), transforms: [cellWidth(30)] }, ++ { title: _("Select update") }, + ]} + rows={update_ids.map(id => updateItem(remarkable, updates[id], packageNames[id].sort((a, b) => a.name > b.name), id))} /> + ); +@@ -933,25 +1127,12 @@ class CardsPage extends React.Component { + id: "available-updates", + title: _("Available updates"), + actions: (
+- {this.props.cockpitUpdate && +- +- +- +- +- {_("Danger alert:")} +- {_("Web Console will restart")} +- +- +- +- +- +- +- +- } ++ + {this.props.applyKpatches} + {this.props.applySecurity} + {this.props.applyAll} ++ {this.props.applySelected} ++ {this.props.applySelectAll} +
), + containsList: true, + body: +@@ -1325,13 +1506,19 @@ class OsUpdates extends React.Component { + }); + } + +- applyUpdates(type) { ++ /** ++ * @param {SelecetedState=} selected ++ */ ++ applyUpdates(type, selected) { + let ids = Object.keys(this.state.updates); + if (type === UPDATES.SECURITY) + ids = ids.filter(id => this.state.updates[id].severity === PK.Enum.INFO_SECURITY); + if (type === UPDATES.KPATCHES) { + ids = ids.filter(id => isKpatchPackage(this.state.updates[id].name)); + } ++ if (type === UPDATES.SELECTED && selected) { ++ ids = calculateSelected(ids, selected); ++ } + + PK.transaction() + .then(transactionPath => { +@@ -1354,7 +1541,7 @@ class OsUpdates extends React.Component { + } + + renderContent() { +- let applySecurity, applyKpatches, applyAll; ++ let applySecurity, applyKpatches, applyAll, applySelected, applySelectAll; + + /* On unregistered RHEL systems we need some heuristics: If the "main" OS repos (which provide coreutils) require + * a subscription, then point this out and don't show available updates, even if there are some auxiliary +@@ -1409,12 +1596,8 @@ class OsUpdates extends React.Component { + const num_kpatches = count_kpatch_updates(this.state.updates); + const highest_severity = find_highest_severity(this.state.updates); + +- applyAll = ( +- ); ++ applySelected = this.applyUpdates(UPDATES.SELECTED, items) }/>; ++ applySelectAll = ; + + if (num_security_updates > 0 && num_updates > num_security_updates) { + applySecurity = ( +@@ -1455,6 +1638,8 @@ class OsUpdates extends React.Component { + { + document.title = cockpit.gettext(document.title); + init(); + const root = createRoot(document.getElementById('app')); +- root.render(); ++ root.render( ++ ++ ++ ++ ); + }); +diff --git a/pkg/packagekit/updates.scss b/pkg/packagekit/updates.scss +index 00718eff2..12bc5de2b 100644 +--- a/pkg/packagekit/updates.scss ++++ b/pkg/packagekit/updates.scss +@@ -72,7 +72,7 @@ + } + + &, p { +- max-inline-size: 60vw; ++ max-inline-size: 54vw; + margin-block-end: 0; // counter-act + overflow: hidden; + text-overflow: ellipsis; +@@ -273,3 +273,7 @@ table.header-buttons { + .ct-info-circle { + color: var(--pf-v5-global--info-color--100); + } ++ ++td.select-update { ++ min-width: 8vw; ++} +-- +2.48.1 + From 504fa493486ae06ad5fd02d134760928793267b38b3ed37c2d7d02c00cde061e Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Fri, 21 Feb 2025 09:29:38 +0000 Subject: [PATCH 2/2] [info=de4b8becd9c83bea352cf5f0f707807082e022a1e5473186a39cb1c5d58e2013] OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:cockpit/cockpit?expand=0&rev=215 --- _scmsync.obsinfo | 8 ++++---- build.specials.obscpio | 2 +- cockpit.changes | 7 +++++++ cockpit.spec | 3 +-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/_scmsync.obsinfo b/_scmsync.obsinfo index 2645d2a..328cbea 100644 --- a/_scmsync.obsinfo +++ b/_scmsync.obsinfo @@ -1,5 +1,5 @@ -mtime: 1740090299 -commit: 783d2e3bb195c6409132c66eb04c36d0232372b201170fc36d853c9dbdd3cdb0 +mtime: 1740129393 +commit: de4b8becd9c83bea352cf5f0f707807082e022a1e5473186a39cb1c5d58e2013 url: https://src.opensuse.org/cockpit/cockpit.git -revision: 783d2e3bb195c6409132c66eb04c36d0232372b201170fc36d853c9dbdd3cdb0 -projectscmsync: https://src.opensuse.org/cockpit/_ObsPrj.git#6afc009e3ae4f54a1bc4208d8bbab86c16397236aec2eca493700e2ac87e1ff4 +revision: de4b8becd9c83bea352cf5f0f707807082e022a1e5473186a39cb1c5d58e2013 +projectscmsync: https://src.opensuse.org/cockpit/_ObsPrj.git#64e9cfa9f6042fa7adfdd4b37913eb3942c31e4934277b1b3dd1de2176db4f01 diff --git a/build.specials.obscpio b/build.specials.obscpio index 3fb75db..3315a55 100644 --- a/build.specials.obscpio +++ b/build.specials.obscpio @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:726d587120395772861f0fced00a006f58ca3fc73b181607f2586588ddd8d6b1 +oid sha256:3bf7304920353eb3a6329abecbbaff3c30aae7147cf5408f58e23129a93f73bf size 256 diff --git a/cockpit.changes b/cockpit.changes index 968e2c0..83c39b3 100644 --- a/cockpit.changes +++ b/cockpit.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Feb 21 08:03:00 UTC 2025 - Alice Brooks + +- Always apply 0007-Remove-DynamicUser-setting-as-these-conflict-with-re.patch + for every build system. Fixes bsc#1237451 + ------------------------------------------------------------------- Thu Feb 20 22:22:32 UTC 2025 - Miika Alikirri @@ -59,6 +65,7 @@ Mon Nov 25 06:18:44 UTC 2024 - Luna D Dragon * 323: - login: Prevent multiple logins in a single browser session - Update documentation links + ------------------------------------------------------------------- Wed Oct 9 12:14:14 UTC 2024 - Alice Brooks diff --git a/cockpit.spec b/cockpit.spec index f075575..9e30b0e 100644 --- a/cockpit.spec +++ b/cockpit.spec @@ -214,7 +214,7 @@ BuildRequires: python3-pytest-timeout %patch -P 4 -p1 %patch -P 5 -p1 %patch -P 106 -p1 - +%patch -P 108 -p1 # SLE Micro specific patches %if 0%{?is_smo} @@ -230,7 +230,6 @@ BuildRequires: python3-pytest-timeout %patch -P 103 -p1 %patch -P 104 -p1 %patch -P 105 -p1 -%patch -P 108 -p1 %else %patch -P 107 -p1 %endif