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/"