From 24eba2d6fceec26859ed4e7d4a0401511de3b190 Mon Sep 17 00:00:00 2001 From: Tristan Theroux <70530866+KernelChief@users.noreply.github.com> Date: Sun, 3 May 2026 21:25:23 -0400 Subject: [PATCH 01/11] feat: add Fedora 44 support, GNOME/GDM compatibility, and app/UX fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platform support: - Add Fedora 44 to CI matrix (builds RPMs for both 43 and 44) - Remove KDE-only language throughout; app now officially supports KDE Plasma and GNOME (GDM) - Update README badge, platform section, spec summary/description, subtitle, and website copy App changes: - Replace JetBrains Toolbox with PyCharm Community Edition (tar.gz install to /opt/pycharm-ce, symlink + .desktop) - Add OpenOffice (Flatpak: org.openoffice.OpenOffice) to Apps tab - Fix Element Flatpak ID: io.element.Element → im.riot.Riot - Remove KDE Connect (already bundled with KDE; unnecessary for GNOME users) - Add post-install reboot warning dialog for AppImageLauncher, Heroic, and CurseForge AppImage entries Bug fixes: - Fix dark-theme subtext (desc labels): palette(mid) → palette(placeholderText) - Fix scrollbar over-scroll: replace AlignTop layout flag with addStretch(1) in all scroll areas - Fix Pulsemeeter install detection: add python_module check kind; works for both DNF and pip installs CI: - Remove "-kde-" from artifact names (rpm-f43-release, rpm-f44-release) - Release step downloads all rpm-f*-release artifacts via pattern match - Update PR beta comment to list both f43/f44 artifact names --- .github/workflows/build-rpm.yml | 16 ++++--- README.md | 10 ++--- docs/index.html | 32 +++++++------- src/packaging/polaris.spec | 4 +- src/polaris | 75 ++++++++++++++++++++++++--------- src/polaris-helper | 45 ++++++++++++++------ 6 files changed, 118 insertions(+), 64 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index f91d202..dd2c8ca 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -56,13 +56,13 @@ jobs: additional_files: src/polaris-helper build: - name: Build (Fedora ${{ matrix.fedora }} KDE) + name: Build (Fedora ${{ matrix.fedora }}) runs-on: ubuntu-latest needs: [lint, shellcheck] if: github.actor != 'dependabot[bot]' && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation')) strategy: matrix: - fedora: [43] + fedora: [43, 44] container: image: fedora:${{ matrix.fedora }} @@ -176,7 +176,7 @@ jobs: - name: Upload RPM artifacts uses: actions/upload-artifact@v7 with: - name: rpm-f${{ matrix.fedora }}-kde-${{ github.event_name == 'pull_request' && format('pr{0}', github.event.pull_request.number) || 'release' }} + name: rpm-f${{ matrix.fedora }}-${{ github.event_name == 'pull_request' && format('pr{0}', github.event.pull_request.number) || 'release' }} path: dist/*.rpm release: @@ -211,11 +211,12 @@ jobs: echo "do_release=false" >> "$GITHUB_OUTPUT" fi - - name: Download Fedora 43 KDE artifacts + - name: Download RPM artifacts if: steps.resolve_tag.outputs.do_release == 'true' uses: actions/download-artifact@v4 with: - name: rpm-f43-kde-release + pattern: rpm-f*-release + merge-multiple: true path: dist - name: List files (debug) @@ -253,7 +254,8 @@ jobs: > the package is not yet signed with a GPG key. ### Assets - - Fedora 43 KDE RPM + - Fedora 43 RPM + - Fedora 44 RPM pr-beta-comment: name: Comment beta RPM location on PR @@ -278,4 +280,4 @@ jobs: sudo dnf install ./polaris-*.noarch.rpm ``` - Artifact name: `rpm-f43-kde-pr${{ github.event.pull_request.number }}` + Artifact names: `rpm-f43-pr${{ github.event.pull_request.number }}`, `rpm-f44-pr${{ github.event.pull_request.number }}` diff --git a/README.md b/README.md index e0676b4..058b671 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/Made%20with-Python-3776AB?logo=python&logoColor=white)](https://www.python.org/) [![Shell](https://img.shields.io/badge/Script-Shell-4EAA25?logo=gnu-bash&logoColor=white)](https://www.gnu.org/software/bash/) -[![Fedora](https://img.shields.io/badge/Platform-Fedora%2043%20KDE-51A2DA?logo=fedora&logoColor=white)](https://fedoraproject.org/) +[![Fedora](https://img.shields.io/badge/Platform-Fedora%2043%20%2F%2044-51A2DA?logo=fedora&logoColor=white)](https://fedoraproject.org/) [![Buy Me A Coffee](https://img.shields.io/badge/Support-Buy%20Me%20A%20Coffee-orange?logo=buy-me-a-coffee)](https://www.buymeacoffee.com/ttheroux) [![Stars](https://img.shields.io/github/stars/KernelChief/polaris?style=social)](https://github.com/KernelChief/polaris/stargazers) Setting up a Linux workstation shouldn’t be a chore. -**Polaris** is a **PySide6 (Qt6)** desktop application that simplifies setting up a fresh Fedora KDE installation. It wraps essential post-install tasks, such as enabling repositories, installing drivers, and deploying apps, into a clean, point-and-click interface. +**Polaris** is a **PySide6 (Qt6)** desktop application that simplifies setting up a fresh Fedora installation. It wraps essential post-install tasks, such as enabling repositories, installing drivers, and deploying apps, into a clean, point-and-click interface. **Why Polaris?** Polaris is the north star: always there, always reliable. It’s the first thing you find when you’re navigating a new install. @@ -44,7 +44,7 @@ sudo dnf install ./polaris-*.noarch.rpm ## 🧩 Supported Platform -Polaris is built specifically for **Fedora 43 KDE Workstation (Plasma 6)**. It leverages `dnf5`, Btrfs-specific tools, and KDE-native configurations to provide a seamless experience. +Polaris is built and tested on **Fedora 43 and 44** with KDE Plasma and GNOME (GDM). It leverages `dnf5` and Btrfs-specific tools to provide a seamless post-install experience. ## 🧰 Included Features @@ -77,10 +77,10 @@ The app auto-detects what is already on your system and organizes tools into ded ### System Tools * **Hardware**: LACT (AMD Control), CoolerControl, OpenRGB, Piper (Mice). * **Filesystem**: Btrfs Assistant & Snapper for snapshot management. -* **Utilities**: KDE Connect, Flatseal, Warehouse. +* **Utilities**: Flatseal, Warehouse. ### Media & Apps -* **Productivity**: VS Code, JetBrains Toolbox, LibreOffice. +* **Productivity**: VS Code, PyCharm Community Edition, LibreOffice, OpenOffice. * **Communication**: Discord (RPM), Vesktop, Slack, Signal, Telegram, Element, Mattermost. * **Media**: OBS Studio, VLC, EasyEffects, Pulsemeeter, Flameshot. * **Graphics**: GIMP, Kdenlive. diff --git a/docs/index.html b/docs/index.html index 7563dd0..92c2564 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,10 +3,10 @@ - Polaris - One-Click Fedora KDE Setup Tool - + Polaris - One-Click Fedora Setup Tool + - + @@ -14,15 +14,15 @@ - - + + - - + + @@ -39,7 +39,7 @@ "name": "Polaris", "operatingSystem": "Linux", "applicationCategory": "UtilitiesApplication", - "description": "A PySide6 desktop application that simplifies post-install setup for Fedora KDE workstations. Install drivers, repositories, gaming tools, and apps with a single click.", + "description": "A PySide6 desktop application that simplifies post-install setup for Fedora workstations (43 and 44). Install drivers, repositories, gaming tools, and apps with a single click.", "url": "https://kernelchief.github.io/Polaris/", "downloadUrl": "https://github.com/KernelChief/Polaris/releases", "softwareVersion": "1.0.1", @@ -594,8 +594,8 @@

Polaris

-

Your Ultimate Companion for Fedora KDE Setup

-

Transform your fresh Fedora KDE installation into a powerful daily rig with Polaris. This intuitive PySide6 (Qt6) desktop application streamlines post-install tasks, from essential drivers and repositories to your favorite apps, all through a simple point-and-click interface.

+

Your Ultimate Companion for Fedora Setup

+

Transform your fresh Fedora installation into a powerful daily rig with Polaris. This intuitive PySide6 (Qt6) desktop application streamlines post-install tasks, from essential drivers and repositories to your favorite apps, all through a simple point-and-click interface.

Get Polaris Now Explore on GitHub @@ -619,18 +619,18 @@

Polaris

Why Polaris?

-

Setting up a Linux workstation shouldn't be a chore. Polaris was born from the desire to make Fedora KDE accessible and powerful for everyone, from seasoned users to those just making the switch. It's your reliable guide, ensuring a smooth and optimized experience.

+

Setting up a Linux workstation shouldn't be a chore. Polaris was born from the desire to make Fedora accessible and powerful for everyone, from seasoned users to those just making the switch. It's your reliable guide, ensuring a smooth and optimized experience.

North Star Reliability

-

Polaris is the essential first tool for navigating a new Fedora KDE install, guiding you through configurations with ease and ensuring your setup starts on the right path.

+

Polaris is the essential first tool for navigating a new Fedora install, guiding you through configurations with ease and ensuring your setup starts on the right path.

-

KDE-Native Experience

-

Built with PySide6 (Qt6), Polaris integrates seamlessly into your KDE Plasma desktop. Enjoy a native look and feel that respects your system's aesthetics and performance.

+

Qt-Native Experience

+

Built with PySide6 (Qt6), Polaris integrates seamlessly into your desktop — whether you're running KDE Plasma or GNOME. Enjoy a native look and feel that respects your system's aesthetics and performance.

@@ -712,7 +712,7 @@

Creativity & Communication

Get Started with Polaris

-

The easiest way to install and keep Polaris updated is via our official COPR repository. Follow these simple steps to begin your optimized Fedora KDE experience.

+

The easiest way to install and keep Polaris updated is via our official COPR repository. Follow these simple steps to begin your optimized Fedora experience.

@@ -736,7 +736,7 @@

3. Launch the Application

-

Important Note: Polaris is specifically built and optimized for Fedora 43 KDE Workstation (Plasma 6). While it might function on other Fedora versions, optimal performance and full feature compatibility are guaranteed only on the target platform.

+

Supported Platforms: Polaris is built and tested on Fedora 43 and 44 with both KDE Plasma and GNOME (GDM). It is a Fedora-only project — other distributions are not supported.

Alternative: Manual RPM Installation

diff --git a/src/packaging/polaris.spec b/src/packaging/polaris.spec index ba77c9d..4e115fd 100644 --- a/src/packaging/polaris.spec +++ b/src/packaging/polaris.spec @@ -4,7 +4,7 @@ Name: polaris %{!?app_version:%global app_version 1.0.2} Version: %{app_version} Release: 1%{?dist} -Summary: One-click workstation setup assistant for Fedora KDE +Summary: One-click workstation setup assistant for Fedora License: GPL-3.0-or-later URL: https://github.com/KernelChief/polaris BuildArch: noarch @@ -21,7 +21,7 @@ Requires: dnf5 Source0: https://github.com/KernelChief/Polaris/archive/refs/tags/v%{version}.tar.gz %description -Polaris is a Qt-based graphical utility for Fedora 43 KDE workstations. +Polaris is a Qt-based graphical utility for Fedora workstations (43 and 44). It provides one-click install/remove actions for common workstation packages, drivers, and Flatpak apps using a PolicyKit-protected helper. diff --git a/src/polaris b/src/polaris index d8c9574..51ef23d 100644 --- a/src/polaris +++ b/src/polaris @@ -137,7 +137,7 @@ def _load_logo(size: int) -> QPixmap: Qt.TransformationMode.SmoothTransformation) PROTON_PASS_URL = "https://proton.me/download/pass/linux/proton-pass-1.34.2-1.x86_64.rpm" -JETBRAINS_TOOLBOX_URL = "https://data.services.jetbrains.com/products/download?platform=linux&code=TBA" +PYCHARM_CE_URL = "https://data.services.jetbrains.com/products/download?platform=linux&code=PCC" APPIMAGELAUNCHER_URL = "https://github.com/TheAssassin/AppImageLauncher/releases/download/v3.0.0-beta-3/appimagelauncher_3.0.0-beta-2-gha287.96cb937_x86_64.rpm" HEROIC_URL = "https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases/download/v2.19.1/Heroic-2.19.1-linux-x86_64.AppImage" CURSEFORGE_URL = "https://curseforge.overwolf.com/downloads/curseforge-latest-linux.AppImage" @@ -295,6 +295,11 @@ FEATURES = [ "install": [["install_url_rpm", APPIMAGELAUNCHER_URL]], "remove": [["remove_pkg", "appimagelauncher"]], "check": {"kind": "rpm", "pkg": "appimagelauncher"}, + "post_install_note": ( + "AppImageLauncher is installed.\n\n" + "⚠️ A reboot (or log out and back in) is required for AppImages to be " + "integrated into your application menu." + ), }, { "id": "heroic_appimage", @@ -304,6 +309,11 @@ FEATURES = [ ["install_appimage", HEROIC_URL, "Heroic-2.19.1-linux-x86_64.AppImage"]], "remove": [["remove_appimage_glob", "*Heroic*.AppImage"]], "check": {"kind": "appimage_glob", "pattern": "*Heroic*.AppImage"}, + "post_install_note": ( + "Heroic Games Launcher has been downloaded.\n\n" + "⚠️ A reboot (or log out and back in) is required for it to appear " + "in your application menu." + ), }, { "id": "curseforge_appimage", @@ -314,6 +324,11 @@ FEATURES = [ "remove": [["remove_appimage_glob", "*curse*forge*.AppImage"]], "check": {"kind": "appimage_glob_any", "patterns": ["*curse*forge*.AppImage", "*Curse*Forge*.AppImage"]}, + "post_install_note": ( + "CurseForge has been downloaded.\n\n" + "⚠️ A reboot (or log out and back in) is required for it to appear " + "in your application menu." + ), }, {"id": "input_remapper", "name": "🕹️ Input Remapper", "desc": "Remap keyboard, mouse and gamepad inputs", "install": [["install_pkg", "input-remapper"]], "remove": [["remove_pkg", "input-remapper"]], @@ -347,9 +362,7 @@ FEATURES = [ {"id": "btrfs_assistant", "name": "🗂️ Btrfs Assistant", "desc": "GUI tools for Btrfs snapshot management", "install": [["install_pkg", "btrfs-assistant"]], "remove": [["remove_pkg", "btrfs-assistant"]], "check": {"kind": "rpm", "pkg": "btrfs-assistant"}}, - {"id": "kdeconnect", "name": "📱 KDE Connect", "desc": "Link your Android or iOS phone to your KDE desktop", - "install": [["install_pkg", "kdeconnect"]], "remove": [["remove_pkg", "kdeconnect"]], - "check": {"kind": "rpm", "pkg": "kdeconnect"}}, + {"id": "piper", "name": "🖱️ Piper", "desc": "GUI for configuring gaming mice via libratbag", "install": [["install_pkg", "piper"]], "remove": [["remove_pkg", "piper"]], "check": {"kind": "rpm", "pkg": "piper"}}, @@ -372,7 +385,7 @@ FEATURES = [ "check": {"kind": "rpm", "pkg": "easyeffects"}}, {"id": "pulsemeeter_audio", "name": "🔊 Pulsemeeter", "desc": "Advanced audio routing controls", "install": [["install_pulsemeeter"]], "remove": [["remove_pulsemeeter"]], - "check": {"kind": "rpm", "pkg": "pulsemeeter"}}, + "check": {"kind": "python_module", "module": "pulsemeeter"}}, {"id": "flameshot", "name": "📸 Flameshot", "desc": "Screenshot tool with annotation support", "install": [["install_pkg", "flameshot"]], "remove": [["remove_pkg", "flameshot"]], "check": {"kind": "rpm", "pkg": "flameshot"}}, @@ -404,8 +417,10 @@ FEATURES = [ "check": {"kind": "flatpak", "appid": "com.slack.Slack"}}, {"id": "flatpak_mattermost", "name": "🗨️ Mattermost (Flatpak)", "desc": "Self-hosted team chat", "check": {"kind": "flatpak", "appid": "com.mattermost.Desktop"}}, - {"id": "flatpak_libreoffice", "name": "📄 LibreOffice (Flatpak)", "desc": "Full office suite", + {"id": "flatpak_libreoffice", "name": "📄 LibreOffice (Flatpak)", "desc": "Full office suite", "check": {"kind": "flatpak", "appid": "org.libreoffice.LibreOffice"}}, + {"id": "flatpak_openoffice", "name": "📄 OpenOffice (Flatpak)", "desc": "Apache OpenOffice — classic open-source office suite", + "check": {"kind": "flatpak", "appid": "org.openoffice.OpenOffice"}}, {"id": "flatpak_gimp", "name": "🖌️ GIMP (Flatpak)", "desc": "GNU Image Manipulation Program", "check": {"kind": "flatpak", "appid": "org.gimp.GIMP"}}, {"id": "flatpak_kdenlive", "name": "🎬 Kdenlive (Flatpak)", "desc": "Open-source video editor", @@ -413,16 +428,16 @@ FEATURES = [ {"id": "flatpak_signal", "name": "🔒 Signal (Flatpak)", "desc": "Secure end-to-end encrypted messaging", "check": {"kind": "flatpak", "appid": "org.signal.Signal"}}, {"id": "flatpak_element", "name": "💬 Element (Flatpak)", "desc": "Matrix / Element chat client (self-hostable)", - "check": {"kind": "flatpak", "appid": "io.element.Element"}}, + "check": {"kind": "flatpak", "appid": "im.riot.Riot"}}, {"id": "flatpak_telegram", "name": "✈️ Telegram (Flatpak)", "desc": "Telegram desktop messaging app", "check": {"kind": "flatpak", "appid": "org.telegram.desktop"}}, { - "id": "jetbrains_toolbox", - "name": "🧰 JetBrains Toolbox", - "desc": "Manage all JetBrains IDEs (PyCharm, IntelliJ, Rider…) from one launcher", - "install": [["install_jetbrains_toolbox"]], - "remove": [["remove_jetbrains_toolbox"]], - "check": {"kind": "file", "path": "/usr/local/bin/jetbrains-toolbox"}, + "id": "pycharm_ce", + "name": "🐍 PyCharm Community Edition", + "desc": "Free Python IDE by JetBrains — full-featured, no subscription required", + "install": [["install_pycharm_ce"]], + "remove": [["remove_pycharm_ce"]], + "check": {"kind": "file", "path": "/usr/local/bin/pycharm"}, }, ] @@ -448,12 +463,12 @@ TABS = [ "flatpak_prismlauncher"]), ("📦 Containers", ["podman", "distrobox", "flatpak_boxbuddy", "flatpak_podman_desktop"]), ("🛠️ Tools", ["lact", "coolercontrol", "openrgbtool", "btrfs_assistant", - "kdeconnect", "piper", "snapper", "flatpak_flatseal", "flatpak_warehouse"]), + "piper", "snapper", "flatpak_flatseal", "flatpak_warehouse"]), ("🎬 Media", ["obs_studio", "vlc", "easyeffects", "pulsemeeter_audio", "flameshot"]), - ("💻 Apps", ["chrome", "zoom_rpm", "vscode", "jetbrains_toolbox", + ("💻 Apps", ["chrome", "zoom_rpm", "vscode", "pycharm_ce", "flatpak_spotify", "discord", "flatpak_vesktop", "flatpak_slack", "flatpak_mattermost", - "flatpak_libreoffice", "flatpak_gimp", "flatpak_kdenlive", + "flatpak_libreoffice", "flatpak_openoffice", "flatpak_gimp", "flatpak_kdenlive", "flatpak_signal", "flatpak_element", "flatpak_telegram"]), ] @@ -565,7 +580,7 @@ class Polaris(QMainWindow): vbox.addLayout(title_row) subtitle = QLabel( - "Set up your Fedora 43 KDE workstation in a few clicks. " + "Set up your Fedora 43 / 44 workstation in a few clicks. " "New here? Hit Recommended Setup — it handles the essentials automatically. " "Then explore the tabs for more." ) @@ -643,9 +658,9 @@ class Polaris(QMainWindow): all_rows_layout = QVBoxLayout(all_inner) all_rows_layout.setContentsMargins(4, 4, 4, 4) all_rows_layout.setSpacing(4) - all_rows_layout.setAlignment(Qt.AlignmentFlag.AlignTop) for f in FEATURES: self._add_row(f, all_rows_layout, target_store=self.all_rows) + all_rows_layout.addStretch(1) all_scroll.setWidget(all_inner) all_layout.addWidget(all_scroll) tabs.addTab(all_widget, "🔍 All") @@ -664,12 +679,12 @@ class Polaris(QMainWindow): rows_layout = QVBoxLayout(scroll_inner) rows_layout.setContentsMargins(4, 4, 4, 4) rows_layout.setSpacing(4) - rows_layout.setAlignment(Qt.AlignmentFlag.AlignTop) for fid in feature_ids: f = FEATURE_BY_ID.get(fid) if f: self._add_row(f, rows_layout) + rows_layout.addStretch(1) scroll.setWidget(scroll_inner) tab_layout.addWidget(scroll) @@ -712,7 +727,7 @@ class Polaris(QMainWindow): name_lbl = QLabel(f["name"]) name_lbl.setStyleSheet("font-weight: bold;") desc_lbl = QLabel(f["desc"]) - desc_lbl.setStyleSheet("color: palette(mid);") + desc_lbl.setStyleSheet("color: palette(placeholderText);") desc_lbl.setWordWrap(True) info_vbox.addWidget(name_lbl) info_vbox.addWidget(desc_lbl) @@ -874,6 +889,11 @@ class Polaris(QMainWindow): return False if kind == "file": return Path(check["path"]).exists() + if kind == "python_module": + return subprocess.run( + [sys.executable, "-c", f"import {check['module']}"], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + ).returncode == 0 return False # ── State refresh ────────────────────────────────────────────────────── @@ -1012,7 +1032,20 @@ class Polaris(QMainWindow): label = "Removing…" if d["applied"] else "Installing…" self._set_busy(fid, True, label) - self._run_action_sequence(actions, on_done=lambda: self._done(fid), on_abort=lambda: self._done(fid)) + + is_install = not d["applied"] + note = d["feature"].get("post_install_note") if is_install else None + + def on_install_done(): + self._done(fid) + if note: + QMessageBox.information(self, "Reboot Required", note) + + self._run_action_sequence( + actions, + on_done=on_install_done if note else lambda: self._done(fid), + on_abort=lambda: self._done(fid), + ) # ── Busy state ───────────────────────────────────────────────────────── diff --git a/src/polaris-helper b/src/polaris-helper index f0372d8..4eacdee 100644 --- a/src/polaris-helper +++ b/src/polaris-helper @@ -306,26 +306,45 @@ remove_flathub() { flatpak remote-delete --system flathub 2>/dev/null || true } -JETBRAINS_TOOLBOX_URL="https://data.services.jetbrains.com/products/download?platform=linux&code=TBA" +PYCHARM_CE_URL="https://data.services.jetbrains.com/products/download?platform=linux&code=PCC" -install_jetbrains_toolbox() { +install_pycharm_ce() { local tmpdir tmpdir="$(mktemp -d)" trap 'rm -rf "${tmpdir}"' EXIT - log "Downloading JetBrains Toolbox..." - curl -fsSL -o "${tmpdir}/toolbox.tar.gz" "${JETBRAINS_TOOLBOX_URL}" - tar -xzf "${tmpdir}/toolbox.tar.gz" -C "${tmpdir}" + log "Downloading PyCharm Community Edition..." + curl -fsSL -o "${tmpdir}/pycharm-ce.tar.gz" "${PYCHARM_CE_URL}" + tar -xzf "${tmpdir}/pycharm-ce.tar.gz" -C "${tmpdir}" - local binary - binary="$(find "${tmpdir}" -name "jetbrains-toolbox" -type f | head -1)" - [[ -n "${binary}" ]] || { echo "ERROR: jetbrains-toolbox binary not found in archive" >&2; exit 2; } + local extracted + extracted="$(find "${tmpdir}" -maxdepth 1 -type d -name "pycharm-*" | head -1)" + [[ -n "${extracted}" ]] || { echo "ERROR: PyCharm directory not found in archive" >&2; exit 2; } - install -D -m 0755 "${binary}" /usr/local/bin/jetbrains-toolbox + rm -rf /opt/pycharm-ce + mv "${extracted}" /opt/pycharm-ce + ln -sf /opt/pycharm-ce/bin/pycharm /usr/local/bin/pycharm + + install -D -m 0644 /opt/pycharm-ce/bin/pycharm.png /usr/share/pixmaps/pycharm-ce.png 2>/dev/null || true + cat >/usr/share/applications/pycharm-ce.desktop <<'DESKTOP' +[Desktop Entry] +Name=PyCharm Community Edition +Comment=Python IDE for Professional Developers +Exec=/opt/pycharm-ce/bin/pycharm +Icon=pycharm-ce +Terminal=false +Type=Application +Categories=Development;IDE; +StartupWMClass=jetbrains-pycharm-ce +DESKTOP + chmod 0644 /usr/share/applications/pycharm-ce.desktop } -remove_jetbrains_toolbox() { - rm -f /usr/local/bin/jetbrains-toolbox +remove_pycharm_ce() { + rm -f /usr/local/bin/pycharm + rm -rf /opt/pycharm-ce + rm -f /usr/share/applications/pycharm-ce.desktop + rm -f /usr/share/pixmaps/pycharm-ce.png } install_flatpak_app() { @@ -400,8 +419,8 @@ case "${action}" in remove_appimage_glob) remove_appimage_glob "${2:-}" ;; setup_flathub) setup_flathub ;; remove_flathub) remove_flathub ;; - install_jetbrains_toolbox) install_jetbrains_toolbox ;; - remove_jetbrains_toolbox) remove_jetbrains_toolbox ;; + install_pycharm_ce) install_pycharm_ce ;; + remove_pycharm_ce) remove_pycharm_ce ;; install_flatpak_app) install_flatpak_app "${2:-}" "${3:-system}" ;; remove_flatpak_app) remove_flatpak_app "${2:-}" ;; *) From d0ff80c2afd283318c7a9ce2b4650fdec5c230cf Mon Sep 17 00:00:00 2001 From: Tristan Theroux <70530866+KernelChief@users.noreply.github.com> Date: Sun, 3 May 2026 21:27:36 -0400 Subject: [PATCH 02/11] chore: bump spec to v1.0.3 with changelog entry --- src/packaging/polaris.spec | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/packaging/polaris.spec b/src/packaging/polaris.spec index 4e115fd..1aad203 100644 --- a/src/packaging/polaris.spec +++ b/src/packaging/polaris.spec @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later Name: polaris -%{!?app_version:%global app_version 1.0.2} +%{!?app_version:%global app_version 1.0.3} Version: %{app_version} Release: 1%{?dist} Summary: One-click workstation setup assistant for Fedora @@ -52,6 +52,12 @@ install -D -m 0644 LICENSE \ %{_datadir}/licenses/%{name}/LICENSE %changelog +* Sat May 03 2026 KernelChief - 1.0.3-1 +- Add Fedora 44 support and GNOME/GDM compatibility +- Replace JetBrains Toolbox with PyCharm Community Edition +- Add OpenOffice (Flatpak), fix Element Flatpak ID +- Remove KDE Connect, add AppImage reboot warning dialog +- Fix dark-theme subtext, scrollbar over-scroll, Pulsemeeter detection * Sat May 03 2026 KernelChief - 1.0.2-1 - Update to v1.0.2: Add Polaris branding and logo * Sun Apr 26 2026 KernelChief - 1.0.1-1 From 89e9a4f3d767cb28cf88ddb217478341a33cca24 Mon Sep 17 00:00:00 2001 From: Tristan Theroux <70530866+KernelChief@users.noreply.github.com> Date: Mon, 4 May 2026 13:51:56 -0400 Subject: [PATCH 03/11] =?UTF-8?q?fix:=20remove=20desc=20label=20color=20ov?= =?UTF-8?q?erride=20=E2=80=94=20inherits=20theme=20text=20color=20correctl?= =?UTF-8?q?y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/polaris | 1 - 1 file changed, 1 deletion(-) diff --git a/src/polaris b/src/polaris index 51ef23d..82499ad 100644 --- a/src/polaris +++ b/src/polaris @@ -727,7 +727,6 @@ class Polaris(QMainWindow): name_lbl = QLabel(f["name"]) name_lbl.setStyleSheet("font-weight: bold;") desc_lbl = QLabel(f["desc"]) - desc_lbl.setStyleSheet("color: palette(placeholderText);") desc_lbl.setWordWrap(True) info_vbox.addWidget(name_lbl) info_vbox.addWidget(desc_lbl) From cbe03be22e0c2efa67376727807021eee144b187 Mon Sep 17 00:00:00 2001 From: ttheroux <70530866+KernelChief@users.noreply.github.com> Date: Tue, 26 May 2026 22:37:05 -0400 Subject: [PATCH 04/11] Add new Flatpak apps, expand Fedora version support, update README New apps: Bitwarden, Bottles, HandBrake, Thunderbird, LocalSend, Apache OpenOffice. Subtitle and README updated to cover Fedora 43/44 and non-KDE spins (primarily tested on KDE Plasma). Co-Authored-By: Claude Sonnet 4.6 --- README.md | 15 ++++++++------- src/polaris | 25 ++++++++++++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 058b671..373f139 100644 --- a/README.md +++ b/README.md @@ -62,12 +62,12 @@ The app auto-detects what is already on your system and organizes tools into ded * **AMD GPU Tools**: Monitoring (`radeontop`) and VA-API hardware acceleration. ### Security -* **Password Managers**: 1Password (official repo), Proton Pass (RPM). +* **Password Managers**: 1Password (official repo), Proton Pass (RPM), Bitwarden (Flatpak). * **VPN**: Tailscale mesh networking. ### Gaming -* **Launchers**: Steam, Lutris, Heroic (AppImage), CurseForge (AppImage), Prism Launcher (Flatpak). -* **Tools**: Wine, GameMode, Gamescope, MangoHud, GOverlay, ProtonUp-Qt. +* **Launchers**: Steam, Lutris, Heroic (AppImage), CurseForge (AppImage), Faugus Launcher, Prism Launcher (Flatpak). +* **Tools**: Wine, Bottles (Flatpak), GameMode, Gamescope, MangoHud, GOverlay, ProtonUp-Qt. * **Input**: Input Remapper for gamepads/mice. ### Containers @@ -80,10 +80,11 @@ The app auto-detects what is already on your system and organizes tools into ded * **Utilities**: Flatseal, Warehouse. ### Media & Apps -* **Productivity**: VS Code, PyCharm Community Edition, LibreOffice, OpenOffice. -* **Communication**: Discord (RPM), Vesktop, Slack, Signal, Telegram, Element, Mattermost. -* **Media**: OBS Studio, VLC, EasyEffects, Pulsemeeter, Flameshot. -* **Graphics**: GIMP, Kdenlive. +* **Productivity**: VS Code, JetBrains Toolbox, LibreOffice (Flatpak), Apache OpenOffice (Flatpak). +* **Communication**: Thunderbird (Flatpak), Discord (RPM), Vesktop, Slack, Signal, Telegram, Element, Mattermost. +* **Utilities**: Zoom, Google Chrome, LocalSend (Flatpak). +* **Media**: OBS Studio, VLC, HandBrake (Flatpak), EasyEffects, Pulsemeeter, Flameshot. +* **Graphics**: GIMP (Flatpak), Kdenlive (Flatpak). ## 🔐 Privilege & Security Model diff --git a/src/polaris b/src/polaris index 82499ad..3557dea 100644 --- a/src/polaris +++ b/src/polaris @@ -251,6 +251,8 @@ FEATURES = [ "remove": [["remove_pkg", "proton-pass"]], "check": {"kind": "rpm", "pkg": "proton-pass"}, }, + {"id": "flatpak_bitwarden", "name": "🔐 Bitwarden (Flatpak)", "desc": "Free, open-source password manager", + "check": {"kind": "flatpak", "appid": "com.bitwarden.desktop"}}, { "id": "tailscale", "name": "🌐 Tailscale", @@ -333,6 +335,8 @@ FEATURES = [ {"id": "input_remapper", "name": "🕹️ Input Remapper", "desc": "Remap keyboard, mouse and gamepad inputs", "install": [["install_pkg", "input-remapper"]], "remove": [["remove_pkg", "input-remapper"]], "check": {"kind": "rpm", "pkg": "input-remapper"}}, + {"id": "flatpak_bottles", "name": "🍾 Bottles (Flatpak)", "desc": "Run Windows apps and games in isolated Wine environments", + "check": {"kind": "flatpak", "appid": "com.usebottles.bottles"}}, {"id": "flatpak_protonupqt", "name": "⬆️ ProtonUp-Qt (Flatpak)", "desc": "Install and manage Proton-GE and Wine-GE versions", "check": {"kind": "flatpak", "appid": "net.davidotek.pupgui2"}}, {"id": "flatpak_prismlauncher", "name": "⛏️ Prism Launcher (Flatpak)", "desc": "Mod-friendly Minecraft launcher", @@ -374,6 +378,8 @@ FEATURES = [ {"id": "flatpak_warehouse", "name": "🏪 Warehouse (Flatpak)", "desc": "Browse and manage all installed Flatpaks", "check": {"kind": "flatpak", "appid": "io.github.flattool.Warehouse"}}, # ── MEDIA & UTILITIES ─────────────────────────────────────────────────── + {"id": "flatpak_handbrake", "name": "🎞️ HandBrake (Flatpak)", "desc": "Video transcoder — convert and compress video files", + "check": {"kind": "flatpak", "appid": "fr.handbrake.ghb"}}, {"id": "obs_studio", "name": "📺 OBS Studio", "desc": "Recording and streaming studio", "install": [["install_pkg", "obs-studio"]], "remove": [["remove_pkg", "obs-studio"]], "check": {"kind": "rpm", "pkg": "obs-studio"}}, @@ -405,6 +411,10 @@ FEATURES = [ "check": {"kind": "repo_and_pkg", "repo_prefix": "code", "repo_file": "/etc/yum.repos.d/vscode.repo", "pkg": "code"}, }, + {"id": "flatpak_thunderbird", "name": "🦅 Thunderbird (Flatpak)", "desc": "Mozilla email and calendar client", + "check": {"kind": "flatpak", "appid": "org.mozilla.Thunderbird"}}, + {"id": "flatpak_localsend", "name": "📡 LocalSend (Flatpak)", "desc": "Open-source AirDrop alternative for local network file sharing", + "check": {"kind": "flatpak", "appid": "org.localsend.localsend_app"}}, {"id": "flatpak_spotify", "name": "🎵 Spotify (Flatpak)", "desc": "Music streaming app", "check": {"kind": "flatpak", "appid": "com.spotify.Client"}}, {"id": "discord", "name": "💬 Discord", "desc": "Voice and chat — ⚠️ RPM Fusion Non-Free must be installed first", @@ -419,7 +429,7 @@ FEATURES = [ "check": {"kind": "flatpak", "appid": "com.mattermost.Desktop"}}, {"id": "flatpak_libreoffice", "name": "📄 LibreOffice (Flatpak)", "desc": "Full office suite", "check": {"kind": "flatpak", "appid": "org.libreoffice.LibreOffice"}}, - {"id": "flatpak_openoffice", "name": "📄 OpenOffice (Flatpak)", "desc": "Apache OpenOffice — classic open-source office suite", + {"id": "flatpak_openoffice", "name": "📄 Apache OpenOffice (Flatpak)", "desc": "Classic office suite — Writer, Calc, Impress and more", "check": {"kind": "flatpak", "appid": "org.openoffice.OpenOffice"}}, {"id": "flatpak_gimp", "name": "🖌️ GIMP (Flatpak)", "desc": "GNU Image Manipulation Program", "check": {"kind": "flatpak", "appid": "org.gimp.GIMP"}}, @@ -456,17 +466,17 @@ GAMING_BUNDLE = [ TABS = [ ("🚀 Get Started", ["rpmfusion", "flathub", "essential", "monitoring", "zram_profile"]), ("🔌 Drivers", ["nvidia_drivers", "amd_tools"]), - ("🔐 Security", ["onepassword", "proton_pass", "tailscale"]), + ("🔐 Security", ["onepassword", "proton_pass", "flatpak_bitwarden", "tailscale"]), ("🎮 Gaming", ["steam", "lutris", "wine", "gamemode", "gamescope", "mangohud", "goverlay", "faugus_launcher", "appimagelauncher", "heroic_appimage", "curseforge_appimage", - "input_remapper", "flatpak_protonupqt", + "input_remapper", "flatpak_bottles", "flatpak_protonupqt", "flatpak_prismlauncher"]), ("📦 Containers", ["podman", "distrobox", "flatpak_boxbuddy", "flatpak_podman_desktop"]), ("🛠️ Tools", ["lact", "coolercontrol", "openrgbtool", "btrfs_assistant", - "piper", "snapper", "flatpak_flatseal", "flatpak_warehouse"]), - ("🎬 Media", ["obs_studio", "vlc", "easyeffects", "pulsemeeter_audio", "flameshot"]), - ("💻 Apps", ["chrome", "zoom_rpm", "vscode", "pycharm_ce", - "flatpak_spotify", "discord", + "kdeconnect", "piper", "snapper", "flatpak_flatseal", "flatpak_warehouse"]), + ("🎬 Media", ["obs_studio", "vlc", "flatpak_handbrake", "easyeffects", "pulsemeeter_audio", "flameshot"]), + ("💻 Apps", ["chrome", "zoom_rpm", "vscode", "jetbrains_toolbox", + "flatpak_thunderbird", "flatpak_localsend", "flatpak_spotify", "discord", "flatpak_vesktop", "flatpak_slack", "flatpak_mattermost", "flatpak_libreoffice", "flatpak_openoffice", "flatpak_gimp", "flatpak_kdenlive", "flatpak_signal", "flatpak_element", "flatpak_telegram"]), @@ -581,6 +591,7 @@ class Polaris(QMainWindow): subtitle = QLabel( "Set up your Fedora 43 / 44 workstation in a few clicks. " + "Primarily tested on KDE Plasma — most features work on GNOME and other spins too. " "New here? Hit Recommended Setup — it handles the essentials automatically. " "Then explore the tabs for more." ) From 8b5fcb0167e30b87bcb3b52ab7a605d120819ec1 Mon Sep 17 00:00:00 2001 From: ttheroux <70530866+KernelChief@users.noreply.github.com> Date: Tue, 26 May 2026 22:59:35 -0400 Subject: [PATCH 05/11] ci: add COPR beta submission on PRs Collect SRPM from the f44 build matrix, submit it to tristantheroux/Polaris-beta on every PR via copr-cli. Requires COPR_CONFIG secret (copr-cli ini format). PR comment updated to include COPR install instructions. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/build-rpm.yml | 57 ++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index dd2c8ca..9044bbe 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -159,8 +159,9 @@ jobs: chmod +x src/packaging/build-rpm.sh ./src/packaging/build-rpm.sh "$VERSION" - # Collect RPMs into dist/ - find "$HOME/rpmbuild/RPMS" -type f -name "*.rpm" -exec cp -v {} "$DISTDIR/" \; + # Collect RPMs and SRPM into dist/ + find "$HOME/rpmbuild/RPMS" -type f -name "*.rpm" -exec cp -v {} "$DISTDIR/" \; + find "$HOME/rpmbuild/SRPMS" -type f -name "*.src.rpm" -exec cp -v {} "$DISTDIR/" \; - name: Smoke test — install RPM and verify files env: @@ -177,7 +178,41 @@ jobs: uses: actions/upload-artifact@v7 with: name: rpm-f${{ matrix.fedora }}-${{ github.event_name == 'pull_request' && format('pr{0}', github.event.pull_request.number) || 'release' }} - path: dist/*.rpm + path: dist/*.noarch.rpm + + - name: Upload SRPM artifact (f44 only — same source for all targets) + if: matrix.fedora == 44 + uses: actions/upload-artifact@v7 + with: + name: srpm-${{ github.event_name == 'pull_request' && format('pr{0}', github.event.pull_request.number) || 'release' }} + path: dist/*.src.rpm + + copr-beta: + name: Submit to COPR Beta + needs: build + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' && !contains(github.event.pull_request.labels.*.name, 'documentation') && secrets.COPR_CONFIG != '' + + steps: + - name: Download SRPM + uses: actions/download-artifact@v4 + with: + name: srpm-pr${{ github.event.pull_request.number }} + path: dist + + - name: Install copr-cli + run: | + sudo apt-get update -qq + sudo apt-get install -y python3-pip + pip install copr-cli + + - name: Write COPR config + run: | + mkdir -p ~/.config + printf '%s' "${{ secrets.COPR_CONFIG }}" > ~/.config/copr + + - name: Submit SRPM to Polaris-beta COPR + run: copr-cli build tristantheroux/Polaris-beta dist/*.src.rpm release: name: Release @@ -259,9 +294,9 @@ jobs: pr-beta-comment: name: Comment beta RPM location on PR - needs: build + needs: [build, copr-beta] + if: always() && github.actor != 'dependabot[bot]' && github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'documentation') runs-on: ubuntu-latest - if: github.actor != 'dependabot[bot]' && github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'documentation') steps: - name: Post new comment with beta RPM download link @@ -272,12 +307,18 @@ jobs: message: | ✅ Beta RPM built for commit `${{ github.sha }}`. - Download from this run's artifacts: + **Download artifacts from this run:** https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}#artifacts - Install with: + Artifact names: `rpm-f43-pr${{ github.event.pull_request.number }}`, `rpm-f44-pr${{ github.event.pull_request.number }}` + + **Install locally:** ```bash sudo dnf install ./polaris-*.noarch.rpm ``` - Artifact names: `rpm-f43-pr${{ github.event.pull_request.number }}`, `rpm-f44-pr${{ github.event.pull_request.number }}` + **Or via COPR beta** (if `COPR_CONFIG` secret is set): + ```bash + sudo dnf copr enable tristantheroux/Polaris-beta + sudo dnf install polaris + ``` From bf72879d37211a3cef59cdf7ce6aa00466e23787 Mon Sep 17 00:00:00 2001 From: ttheroux <70530866+KernelChief@users.noreply.github.com> Date: Tue, 26 May 2026 23:01:39 -0400 Subject: [PATCH 06/11] ci: fix COPR project name to Polaris-Testing Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/build-rpm.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index 9044bbe..264e686 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -211,8 +211,8 @@ jobs: mkdir -p ~/.config printf '%s' "${{ secrets.COPR_CONFIG }}" > ~/.config/copr - - name: Submit SRPM to Polaris-beta COPR - run: copr-cli build tristantheroux/Polaris-beta dist/*.src.rpm + - name: Submit SRPM to Polaris-Testing COPR + run: copr-cli build tristantheroux/Polaris-Testing dist/*.src.rpm release: name: Release @@ -317,8 +317,8 @@ jobs: sudo dnf install ./polaris-*.noarch.rpm ``` - **Or via COPR beta** (if `COPR_CONFIG` secret is set): + **Or via COPR Testing** (if `COPR_CONFIG` secret is set): ```bash - sudo dnf copr enable tristantheroux/Polaris-beta + sudo dnf copr enable tristantheroux/Polaris-Testing sudo dnf install polaris ``` From a06c0ac52cb300fdee9affa747583a305dfbbc0c Mon Sep 17 00:00:00 2001 From: ttheroux <70530866+KernelChief@users.noreply.github.com> Date: Tue, 26 May 2026 23:10:09 -0400 Subject: [PATCH 07/11] ci: align build pipeline with creative-installer pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - build-rpm.sh reads VERSION from env, handles -prerelease → RPM Release - spec: add %{?app_release} support for prerelease builds - workflow: PR version uses semver dash separator, SRPM upload PR-only, copr-beta uses COPR_LOGIN/COPR_TOKEN secrets with --nowait, smoke test uses *.noarch.rpm glob, pr-beta-comment checks build success Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/build-rpm.yml | 143 ++++++++++++++++---------------- src/packaging/build-rpm.sh | 63 ++++++++++---- src/packaging/polaris.spec | 3 +- 3 files changed, 120 insertions(+), 89 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index 264e686..ce15de9 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -11,7 +11,7 @@ on: tags: - "v*" pull_request: - types: [opened, synchronize, reopened, labeled, unlabeled] + types: [opened, synchronize, reopened, labeled, unlabeled, ready_for_review] permissions: contents: write @@ -24,7 +24,7 @@ jobs: lint: name: Lint Python runs-on: ubuntu-latest - if: github.actor != 'dependabot[bot]' && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation')) + if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation') steps: - name: Checkout source @@ -44,7 +44,7 @@ jobs: shellcheck: name: ShellCheck polaris-helper runs-on: ubuntu-latest - if: github.actor != 'dependabot[bot]' && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation')) + if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation') steps: - name: Checkout source @@ -53,13 +53,13 @@ jobs: - name: Run ShellCheck uses: ludeeus/action-shellcheck@2.0.0 with: - additional_files: src/polaris-helper + additional_files: src/polaris-helper src/packaging/build-rpm.sh build: name: Build (Fedora ${{ matrix.fedora }}) runs-on: ubuntu-latest needs: [lint, shellcheck] - if: github.actor != 'dependabot[bot]' && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation')) + if: github.event.pull_request.draft != true && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation')) strategy: matrix: fedora: [43, 44] @@ -91,8 +91,7 @@ jobs: # 1) workflow_dispatch explicit input wins if [ -n "${INPUT_VERSION}" ]; then - VERSION="${INPUT_VERSION}" - VERSION="$(printf '%s' "$VERSION" | sed 's/[^[:alnum:]._+~-]/./g')" + VERSION="${INPUT_VERSION#v}" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Resolved version from workflow input: ${VERSION}" exit 0 @@ -101,24 +100,23 @@ jobs: # 2) Tag pushes use tag name if [ "${GITHUB_REF#refs/tags/}" != "${GITHUB_REF}" ]; then VERSION="${GITHUB_REF#refs/tags/}" - VERSION="$(printf '%s' "$VERSION" | sed 's/[^[:alnum:]._+~-]/./g')" + VERSION="${VERSION#v}" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Resolved version from tag: ${VERSION}" exit 0 fi - # 3) PR builds create a clean beta version. - # RPM Version cannot include '-', so we use dots for prerelease label. + # 3) PR builds: semver prerelease string (dash separator so build-rpm.sh + # splits it into RPM Version + Release: 0.prerelease.1) if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then BASE_TAG="$(git tag --list 'v*' --sort=-v:refname | head -n 1 || true)" - BASE_VERSION="${BASE_TAG}" + BASE_VERSION="${BASE_TAG#v}" if [ -z "${BASE_VERSION}" ]; then - BASE_VERSION="v0.0.0" + BASE_VERSION="0.0.0" fi SHORT_SHA="$(printf '%s' "$GITHUB_SHA" | cut -c1-8)" - VERSION="${BASE_VERSION}.beta.pr${{ github.event.pull_request.number }}.${SHORT_SHA}" - VERSION="$(printf '%s' "$VERSION" | sed 's/[^[:alnum:]._+~]/./g')" + VERSION="${BASE_VERSION}-beta.pr${{ github.event.pull_request.number }}.${SHORT_SHA}" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Resolved version for PR beta build: ${VERSION}" exit 0 @@ -126,7 +124,7 @@ jobs: # 4) Fallback for branch manual runs without input VERSION="$(git tag --list 'v*' --sort=-v:refname | head -n 1 || true)" - VERSION="$(printf '%s' "$VERSION" | sed 's/[^[:alnum:]._+~-]/./g')" + VERSION="${VERSION#v}" if [ -z "${VERSION}" ]; then echo "Could not resolve a version (no tags found)." exit 1 @@ -143,31 +141,22 @@ jobs: GIT_DISCOVERY_ACROSS_FILESYSTEM: 1 run: | mkdir -p "$TOPDIR" "$DISTDIR" - # Ensure rpmbuild writes inside the shared workspace (not ~) export HOME="${{ github.workspace }}" mkdir -p "$HOME"/rpmbuild - echo "GITHUB_REF=$GITHUB_REF" - echo "GITHUB_REF_NAME=$GITHUB_REF_NAME" - echo "GITHUB_REF_TYPE=$GITHUB_REF_TYPE" - echo "VERSION (env)=$VERSION" - - if [ -z "$VERSION" ]; then - echo "Resolved VERSION is empty; aborting." - exit 1 - fi + git config --global --add safe.directory "$GITHUB_WORKSPACE" chmod +x src/packaging/build-rpm.sh - ./src/packaging/build-rpm.sh "$VERSION" + ./src/packaging/build-rpm.sh - # Collect RPMs and SRPM into dist/ find "$HOME/rpmbuild/RPMS" -type f -name "*.rpm" -exec cp -v {} "$DISTDIR/" \; - find "$HOME/rpmbuild/SRPMS" -type f -name "*.src.rpm" -exec cp -v {} "$DISTDIR/" \; + mkdir -p "$DISTDIR/srpms" + find "$HOME/rpmbuild/SRPMS" -type f -name "*.src.rpm" -exec cp -v {} "$DISTDIR/srpms/" \; - name: Smoke test — install RPM and verify files env: DISTDIR: ${{ github.workspace }}/dist run: | - dnf install -y --nogpgcheck "$DISTDIR"/*.rpm + dnf install -y --nogpgcheck "$DISTDIR"/*.noarch.rpm test -x /usr/bin/polaris || { echo "FAIL: /usr/bin/polaris missing"; exit 1; } test -x /usr/libexec/polaris-helper || { echo "FAIL: polaris-helper missing"; exit 1; } test -f /usr/share/applications/polaris.desktop || { echo "FAIL: .desktop file missing"; exit 1; } @@ -180,39 +169,12 @@ jobs: name: rpm-f${{ matrix.fedora }}-${{ github.event_name == 'pull_request' && format('pr{0}', github.event.pull_request.number) || 'release' }} path: dist/*.noarch.rpm - - name: Upload SRPM artifact (f44 only — same source for all targets) - if: matrix.fedora == 44 + - name: Upload SRPM artifact (f44 only, PRs only) + if: matrix.fedora == 44 && github.event_name == 'pull_request' uses: actions/upload-artifact@v7 - with: - name: srpm-${{ github.event_name == 'pull_request' && format('pr{0}', github.event.pull_request.number) || 'release' }} - path: dist/*.src.rpm - - copr-beta: - name: Submit to COPR Beta - needs: build - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' && !contains(github.event.pull_request.labels.*.name, 'documentation') && secrets.COPR_CONFIG != '' - - steps: - - name: Download SRPM - uses: actions/download-artifact@v4 with: name: srpm-pr${{ github.event.pull_request.number }} - path: dist - - - name: Install copr-cli - run: | - sudo apt-get update -qq - sudo apt-get install -y python3-pip - pip install copr-cli - - - name: Write COPR config - run: | - mkdir -p ~/.config - printf '%s' "${{ secrets.COPR_CONFIG }}" > ~/.config/copr - - - name: Submit SRPM to Polaris-Testing COPR - run: copr-cli build tristantheroux/Polaris-Testing dist/*.src.rpm + path: dist/srpms/*.src.rpm release: name: Release @@ -292,33 +254,68 @@ jobs: - Fedora 43 RPM - Fedora 44 RPM + copr-beta: + name: Submit to COPR Testing + needs: build + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'documentation') + + steps: + - name: Download SRPM + uses: actions/download-artifact@v4 + with: + name: srpm-pr${{ github.event.pull_request.number }} + path: dist + + - name: Install copr-cli + run: pip install copr-cli + + - name: Configure copr-cli + env: + COPR_LOGIN: ${{ secrets.COPR_LOGIN }} + COPR_TOKEN: ${{ secrets.COPR_TOKEN }} + run: | + mkdir -p ~/.config + cat > ~/.config/copr < The COPR build runs asynchronously — wait ~5 min after this comment before installing. + + **Option 2 — manual RPM download:** + https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}#artifacts + + Artifact names: `rpm-f43-pr${{ github.event.pull_request.number }}`, `rpm-f44-pr${{ github.event.pull_request.number }}` diff --git a/src/packaging/build-rpm.sh b/src/packaging/build-rpm.sh index fbd1db7..eac2011 100755 --- a/src/packaging/build-rpm.sh +++ b/src/packaging/build-rpm.sh @@ -2,38 +2,61 @@ # SPDX-License-Identifier: GPL-3.0-or-later set -euo pipefail -NAME="polaris" -VERSION="${1:-1.0}" -VERSION="${VERSION#v}" # strip leading 'v' — RPM Version field must not start with it +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +SPEC="${ROOT_DIR}/src/packaging/polaris.spec" -# Ensure rpmbuild tree exists command -v rpmdev-setuptree >/dev/null 2>&1 || { echo "ERROR: rpmdevtools not installed. Install: sudo dnf install rpmdevtools" >&2 exit 1 } -rpmdev-setuptree >/dev/null 2>&1 || true - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -SPEC="${ROOT_DIR}/src/packaging/${NAME}.spec" if [[ ! -f "${SPEC}" ]]; then echo "ERROR: Spec not found: ${SPEC}" >&2 exit 2 fi +NAME="polaris" + +VERSION="${VERSION:-}" +if [[ -z "${VERSION}" && "${GITHUB_REF_TYPE:-}" == "tag" && -n "${GITHUB_REF_NAME:-}" ]]; then + VERSION="${GITHUB_REF_NAME#v}" +fi +if [[ -z "${VERSION}" && -n "${GITHUB_REF:-}" && "${GITHUB_REF}" == refs/tags/* ]]; then + VERSION="${GITHUB_REF#refs/tags/}" + VERSION="${VERSION#v}" +fi +VERSION="${VERSION#v}" + +RPM_VERSION="${VERSION}" +RPM_PRERELEASE="" + +# Convert semver prerelease tags like 1.0.5-rc1 into RPM-friendly fields: +# Version: 1.0.5 +# Release: 0.rc1.1%{?dist} +if [[ "${VERSION}" == *-* ]]; then + RPM_VERSION="${VERSION%%-*}" + RPM_PRERELEASE="${VERSION#*-}" + RPM_PRERELEASE="${RPM_PRERELEASE//-/.}" +fi + +if [[ -z "${NAME}" || -z "${VERSION}" || -z "${RPM_VERSION}" ]]; then + echo "ERROR: Could not determine Name/Version. Set VERSION or run on a tag (e.g., v1.0.4)." >&2 + exit 3 +fi + +rpmdev-setuptree >/dev/null 2>&1 || true + TMPDIR="$(mktemp -d)" trap 'rm -rf "$TMPDIR"' EXIT # Directory name must match %setup -n Polaris-%{version} in the spec -# Tarball name must match the Source0 URL basename: v%{version}.tar.gz -SRC_DIR="${TMPDIR}/Polaris-${VERSION}" +SRC_DIR="${TMPDIR}/Polaris-${RPM_VERSION}" mkdir -p "${SRC_DIR}" -# Copy repo contents into tarball staging directory -# Exclude git + common junk rsync -a \ --exclude ".git" \ --exclude ".github" \ + --exclude ".idea" \ --exclude "*/__pycache__" \ --exclude "*.pyc" \ --exclude "*.pyo" \ @@ -41,12 +64,22 @@ rsync -a \ --exclude "rpmbuild" \ "${ROOT_DIR}/" "${SRC_DIR}/" -TARBALL="${HOME}/rpmbuild/SOURCES/v${VERSION}.tar.gz" -tar -C "${TMPDIR}" -czf "${TARBALL}" "Polaris-${VERSION}" +TARBALL="${HOME}/rpmbuild/SOURCES/v${RPM_VERSION}.tar.gz" +tar -C "${TMPDIR}" -czf "${TARBALL}" "Polaris-${RPM_VERSION}" echo "Created source tarball: ${TARBALL}" +echo "Building ${NAME} version ${VERSION} using spec: ${SPEC}" + +RPMBUILD_ARGS=( + -ba + --define "app_version ${RPM_VERSION}" +) + +if [[ -n "${RPM_PRERELEASE}" ]]; then + RPMBUILD_ARGS+=(--define "app_release 0.${RPM_PRERELEASE}.1") +fi -rpmbuild -ba "${SPEC}" --define "app_version ${VERSION}" +rpmbuild "${RPMBUILD_ARGS[@]}" "${SPEC}" echo "Done." echo "RPMs are in: ${HOME}/rpmbuild/RPMS/" diff --git a/src/packaging/polaris.spec b/src/packaging/polaris.spec index 1aad203..60037e7 100644 --- a/src/packaging/polaris.spec +++ b/src/packaging/polaris.spec @@ -2,8 +2,9 @@ Name: polaris %{!?app_version:%global app_version 1.0.3} +%{!?app_release:%global app_release 1} Version: %{app_version} -Release: 1%{?dist} +Release: %{app_release}%{?dist} Summary: One-click workstation setup assistant for Fedora License: GPL-3.0-or-later URL: https://github.com/KernelChief/polaris From 78e2d6c6f295481ec38765f50bfbb3bcb5b544d7 Mon Sep 17 00:00:00 2001 From: ttheroux <70530866+KernelChief@users.noreply.github.com> Date: Tue, 26 May 2026 23:13:26 -0400 Subject: [PATCH 08/11] ci: fix COPR config indentation using printf Heredoc inside a YAML run block gets leading spaces stripped into the file, breaking the INI section header. Use printf instead. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/build-rpm.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index ce15de9..b37da8c 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -276,13 +276,8 @@ jobs: COPR_TOKEN: ${{ secrets.COPR_TOKEN }} run: | mkdir -p ~/.config - cat > ~/.config/copr < ~/.config/copr - name: Submit SRPM to Polaris-Testing COPR run: | From 3ecca13b4f7dad111ee39b51b6568b31ac368562 Mon Sep 17 00:00:00 2001 From: ttheroux <70530866+KernelChief@users.noreply.github.com> Date: Tue, 26 May 2026 23:17:54 -0400 Subject: [PATCH 09/11] ci: mirror creative-installer heredoc for copr config Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/build-rpm.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index b37da8c..ce15de9 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -276,8 +276,13 @@ jobs: COPR_TOKEN: ${{ secrets.COPR_TOKEN }} run: | mkdir -p ~/.config - printf '[copr-cli]\nlogin = %s\nusername = tristantheroux\ntoken = %s\ncopr_url = https://copr.fedorainfracloud.org\n' \ - "${COPR_LOGIN}" "${COPR_TOKEN}" > ~/.config/copr + cat > ~/.config/copr < Date: Wed, 27 May 2026 09:09:02 -0400 Subject: [PATCH 10/11] fix: align Source0 URL and tarball filename for COPR compatibility COPR rebuilds the SRPM in a clean chroot and downloads Source0 to resolve the tarball. Use the shorter archive URL with a #/filename hint so COPR knows what to name the file locally, and rename the tarball produced by build-rpm.sh to match. Co-Authored-By: Claude Sonnet 4.6 --- src/packaging/build-rpm.sh | 2 +- src/packaging/polaris.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packaging/build-rpm.sh b/src/packaging/build-rpm.sh index eac2011..71dd406 100755 --- a/src/packaging/build-rpm.sh +++ b/src/packaging/build-rpm.sh @@ -64,7 +64,7 @@ rsync -a \ --exclude "rpmbuild" \ "${ROOT_DIR}/" "${SRC_DIR}/" -TARBALL="${HOME}/rpmbuild/SOURCES/v${RPM_VERSION}.tar.gz" +TARBALL="${HOME}/rpmbuild/SOURCES/Polaris-${RPM_VERSION}.tar.gz" tar -C "${TMPDIR}" -czf "${TARBALL}" "Polaris-${RPM_VERSION}" echo "Created source tarball: ${TARBALL}" diff --git a/src/packaging/polaris.spec b/src/packaging/polaris.spec index 60037e7..73db420 100644 --- a/src/packaging/polaris.spec +++ b/src/packaging/polaris.spec @@ -19,7 +19,7 @@ Requires: systemd Requires: dnf5 # Use the GitHub-generated tarball URL -Source0: https://github.com/KernelChief/Polaris/archive/refs/tags/v%{version}.tar.gz +Source0: https://github.com/KernelChief/Polaris/archive/v%{version}.tar.gz#/Polaris-%{version}.tar.gz %description Polaris is a Qt-based graphical utility for Fedora workstations (43 and 44). From c9d5ad1215b8ac573b655d2a71fcf20a9b6c52d8 Mon Sep 17 00:00:00 2001 From: ttheroux <70530866+KernelChief@users.noreply.github.com> Date: Wed, 27 May 2026 09:35:17 -0400 Subject: [PATCH 11/11] fix: bake version/release into spec so COPR SRPM is self-contained COPR rebuilds the SRPM in a clean chroot without passing --define flags, so it falls back to the spec defaults. For PR builds, the base version comes from the latest git tag (e.g. v1.0.2) while the spec defaults to the next release (1.0.3), causing a source tarball name mismatch. Replace --define flags with a sed substitution that embeds the resolved version and release directly into a temp copy of the spec before calling rpmbuild. The SRPM now carries the exact version it was built with, producing e.g. 1.0.2-0.beta.prNN.sha.1 in COPR Testing. Co-Authored-By: Claude Sonnet 4.6 --- src/packaging/build-rpm.sh | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/packaging/build-rpm.sh b/src/packaging/build-rpm.sh index 71dd406..2159f6e 100755 --- a/src/packaging/build-rpm.sh +++ b/src/packaging/build-rpm.sh @@ -70,16 +70,20 @@ tar -C "${TMPDIR}" -czf "${TARBALL}" "Polaris-${RPM_VERSION}" echo "Created source tarball: ${TARBALL}" echo "Building ${NAME} version ${VERSION} using spec: ${SPEC}" -RPMBUILD_ARGS=( - -ba - --define "app_version ${RPM_VERSION}" -) - +RPM_RELEASE="1" if [[ -n "${RPM_PRERELEASE}" ]]; then - RPMBUILD_ARGS+=(--define "app_release 0.${RPM_PRERELEASE}.1") + RPM_RELEASE="0.${RPM_PRERELEASE}.1" fi -rpmbuild "${RPMBUILD_ARGS[@]}" "${SPEC}" +# Bake version/release into a temp copy of the spec so the SRPM is +# self-contained: COPR rebuilds from the SRPM without --define flags. +BUILD_SPEC="${TMPDIR}/polaris.spec" +sed \ + -e "s|%{!?app_version:%global app_version [^}]*}|%global app_version ${RPM_VERSION}|" \ + -e "s|%{!?app_release:%global app_release [^}]*}|%global app_release ${RPM_RELEASE}|" \ + "${SPEC}" > "${BUILD_SPEC}" + +rpmbuild -ba "${BUILD_SPEC}" echo "Done." echo "RPMs are in: ${HOME}/rpmbuild/RPMS/"