Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(default-flatpaks): version 2 (nushell) #336

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7e33425
feat: initial draft of default-flatpaks v2
xynydev Sep 22, 2024
851ecfd
chore: streamline logging
xynydev Sep 26, 2024
2cd4439
chore: replace json with yaml as generated config format
xynydev Sep 26, 2024
a45fc97
feat: set up groundwork for post boot scripts
xynydev Sep 26, 2024
1415893
feat: rename installations -> configurations, initial implementation …
xynydev Oct 11, 2024
da675a4
fix: put executable files into /usr/libexec/
xynydev Nov 10, 2024
6510afa
fix: improve fedora remote detection and removal
xynydev Nov 10, 2024
7185ef5
feat: implement notifications for system flatpak setup
xynydev Nov 10, 2024
28a0238
chore(default-flatpaks): No need to expose `DISPLAY` for notify-send
fiftydinar Nov 10, 2024
92f501a
Merge branch 'main' into nu-flatpaks
fiftydinar Nov 10, 2024
9498a79
chore(default-flatpaks): Update service & add timers to match v1
fiftydinar Nov 10, 2024
dd5ae9e
chore(default-flatpaks): Copy & enable timers instead of services
fiftydinar Nov 10, 2024
ed42c96
chore(default-flatpaks): Fix typo for copying `user-flatpak-setup` timer
fiftydinar Nov 10, 2024
81d210a
chore(default-flatpaks): Copy post-boot files directly instead of pla…
fiftydinar Nov 10, 2024
d83856d
chore(default-flatpaks): Forgot to remove copying step of post-boot f…
fiftydinar Nov 10, 2024
832041a
Merge branch 'main' into nu-flatpaks
fiftydinar Dec 4, 2024
5f13d9d
Merge branch 'main' into nu-flatpaks
xynydev Jan 6, 2025
97fea21
chore: update to be in accordance with cli support for nushell
xynydev Jan 6, 2025
4b23110
feat: allow usage of fedora flatpak remote, remove fedora flatpaks an…
xynydev Jan 19, 2025
2de6e0b
feat: refactor schema to support multiple versions of the module
xynydev Jan 19, 2025
ba33ac5
Merge branch 'main' into nu-flatpaks
xynydev Jan 19, 2025
56fa555
docs: separate docs for separate module versions
xynydev Jan 19, 2025
fefcde5
fix: copy user-flatpak-setup.timer to correct directory
xynydev Jan 19, 2025
44fb906
chore: correctly document default values in schema
xynydev Jan 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions modules/default-flatpaks/default-flatpaks.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ import "@typespec/json-schema";
using TypeSpec.JsonSchema;

@jsonSchema("/modules/default-flatpaks.json")
model DefaultFlatpaksModule {
union DefaultFlatpaksModule {
DefaultFlatpaksV1;
DefaultFlatpaksV2;
}

model DefaultFlatpaksV1 {
/** The default-flatpaks module can be used to install or uninstall flatpaks from a configurable remote on every boot.
* https://blue-build.org/reference/modules/default-flatpaks/
*/
type: "default-flatpaks";
*/
type: "default-flatpaks@v1";

/** Whether to send a notification after the install/uninstall is finished. */
notify?: boolean = false;
Expand Down Expand Up @@ -46,4 +51,34 @@ model DefaultFlatpaksModule {
/** List of Flatpak IDs to remove. */
remove?: Array<string>;
};
}

model DefaultFlatpaksV2 {
/** The default-flatpaks module can be used to install Flatpaks from a configurable remote on every boot.
* https://blue-build.org/reference/modules/default-flatpaks/
*/
type: "default-flatpaks@v2" | "default-flatpaks@latest" | "default-flatpaks";

configurations: Array<{
/** Whether to notify users about Flatpak installation. */
notify?: boolean = true;

/** Whether to perform this configuration for system-wide or separately for each user. */
scope?: "system" | "user" = "user";

/** Details of the Flatpak repository to set up. If omitted, Flathub will be used by default. */
repo?: {
/** Flatpak repository URL. */
url?: string = "https://dl.flathub.org/repo/flathub.flatpakrepo";

/** Flatpak repository name. */
name?: string = "flathub";

/** Flatpak repository formatted title. */
title?: string = "Flathub";
};

/** List of Flatpak IDs to install from the repo. */
install?: Array<string>;
}>;
}
86 changes: 52 additions & 34 deletions modules/default-flatpaks/module.yml
Original file line number Diff line number Diff line change
@@ -1,37 +1,55 @@
name: default-flatpaks
shortdesc: The default-flatpaks module can be used to install or uninstall flatpaks from a configurable remote on every boot.
example: |
modules: # configured multiple times to highlight how options are overridden
- type: default-flatpaks
notify: true # Send notification after install/uninstall is finished (true/false)
system:
# If no repo information is specified, Flathub will be used by default
repo-url: https://dl.flathub.org/repo/flathub.flatpakrepo
repo-name: flathub
repo-title: "Flathub (system-wide)" # Optional; this sets the remote's user-facing name in graphical frontends like GNOME Software
install:
- org.gnome.Loupe
- one.ablaze.floorp//lightning # This is an example of flatpak which has multiple branches in selection (flatpak//branch).
# Flatpak runtimes are not supported (like org.winehq.Wine//stable-23.08).
# Only normal flatpak applications are (like Floorp Lightning web browser in this example).
# Multiple install of same flatpaks with different branches is not supported.
remove:
- org.gnome.eog
# A flatpak repo can also be added without having to install flatpaks,
# as long as one of the repo- fields is present
user:
repo-name: flathub
versions:
- version: v1
example: |
modules: # configured multiple times to highlight how options are overridden
- type: default-flatpaks
notify: true # Send notification after install/uninstall is finished (true/false)
system:
# If no repo information is specified, Flathub will be used by default
repo-url: https://dl.flathub.org/repo/flathub.flatpakrepo
repo-name: flathub
repo-title: "Flathub (system-wide)" # Optional; this sets the remote's user-facing name in graphical frontends like GNOME Software
install:
- org.gnome.Loupe
- one.ablaze.floorp//lightning # This is an example of flatpak which has multiple branches in selection (flatpak//branch).
# Flatpak runtimes are not supported (like org.winehq.Wine//stable-23.08).
# Only normal flatpak applications are (like Floorp Lightning web browser in this example).
# Multiple install of same flatpaks with different branches is not supported.
remove:
- org.gnome.eog
# A flatpak repo can also be added without having to install flatpaks,
# as long as one of the repo- fields is present
user:
repo-name: flathub

# Assuming that the above example is configured first in a recipe,
# a subsequent usage might look like this:
- type: default-flatpaks
system:
# If the repo-* fields are omitted on the subsequent usage,
# the module will use the previously configured repo.
# Otherwise, it will overwrite the repo configuration.
install:
- org.kde.kdenlive # this Flatpak is appended to the install list
user:
# repo-name will overwrite the previously-configured repo-name for the user remote
repo-name: flathub-user
repo-title: "Flathub (User)
# Assuming that the above example is configured first in a recipe,
# a subsequent usage might look like this:
- type: default-flatpaks
system:
# If the repo-* fields are omitted on the subsequent usage,
# the module will use the previously configured repo.
# Otherwise, it will overwrite the repo configuration.
install:
- org.kde.kdenlive # this Flatpak is appended to the install list
user:
# repo-name will overwrite the previously-configured repo-name for the user remote
repo-name: flathub-user
repo-title: "Flathub (User
- version: v2
example: |
- type: default-flatpaks
configurations:
- notify: true
scope: user
repo:
title: Flathub (user)
install:
- io.gitlab.leesonwai.Sums
- io.github.nokse22.minitext
- notify: true
scope: system
install:
- xyz.splashmapper.Splash
- xyz.safeworlds.hiit
5 changes: 5 additions & 0 deletions modules/default-flatpaks/v2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# `default-flatpaks`

The `default-flatpaks` module can be used to install Flatpaks from a configurable remote on every boot.

This documentation page is a draft.
86 changes: 86 additions & 0 deletions modules/default-flatpaks/v2/default-flatpaks.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/libexec/bluebuild/nu/nu

const flathubURL = "https://dl.flathub.org/repo/flathub.flatpakrepo"

const defaultConfiguration = {
notify: true
scope: user
repo: {
url: $flathubURL
name: "flathub"
title: "Flathub"
}
install: []
}

const usrSharePath = "/usr/share/bluebuild/default-flatpaks"
const libExecPath = "/usr/libexec/bluebuild/default-flatpaks"
const configPath = $"($usrSharePath)/configuration.yaml"

def main [configStr: string] {
let config = $configStr | from yaml

let configurations = $config.configurations | each {|configuration|
mut merged = $defaultConfiguration | merge $configuration
$merged.repo = $defaultConfiguration.repo | merge $merged.repo # make sure all repo properties exist

print $"Validating configuration of (ansi default_italic)($merged.install | length)(ansi reset) Flatpaks from (ansi default_italic)($merged.repo.title)(ansi reset)"

if (not ($merged.scope == "system" or $merged.scope == "user")) {
print $"(ansi red_bold)Scope must be either(ansi reset) (ansi blue_italic)system(ansi reset) (ansi red_bold)or(ansi reset) (ansi blue_italic)user(ansi reset)"
print $"(ansi blue)Your input:(ansi reset) ($merged.scope)"
exit 1
}
if (not ($merged.notify == true or $merged.notify == false)) {
print $"(ansi red_bold)Notify must be either(ansi reset) (ansi blue_italic)true(ansi reset) (ansi red_bold)or(ansi reset) (ansi blue_italic)false(ansi reset)"
print $"(ansi blue)Your input:(ansi reset) ($merged.notify)"
exit 1
}
if ($merged.repo.url == $flathubURL) {
checkFlathub $merged.install
}

print $"Validation successful!"

$merged
}


if (not ($configPath | path exists)) {
mkdir ($configPath | path dirname)
'[]'| save $configPath
}

open $configPath
| append $configurations
| to yaml | save -f $configPath

print $"(ansi green_bold)Successfully generated following configurations:(ansi reset)"
print ($configurations | to yaml)

print "Setting up Flatpak setup services..."

cp $"($env.MODULE_DIRECTORY)/default-flatpaks/post-boot/system-flatpak-setup.service" /usr/lib/systemd/system/system-flatpak-setup.service
cp $"($env.MODULE_DIRECTORY)/default-flatpaks/post-boot/system-flatpak-setup.timer" /usr/lib/systemd/system/system-flatpak-setup.timer
cp $"($env.MODULE_DIRECTORY)/default-flatpaks/post-boot/user-flatpak-setup.service" /usr/lib/systemd/user/user-flatpak-setup.service
cp $"($env.MODULE_DIRECTORY)/default-flatpaks/post-boot/user-flatpak-setup.timer" /usr/lib/systemd/user/user-flatpak-setup.timer
systemctl enable --force system-flatpak-setup.timer
systemctl enable --force --global user-flatpak-setup.timer

cp $"($env.MODULE_DIRECTORY)/default-flatpaks/post-boot/system-flatpak-setup" $"($libExecPath)/system-flatpak-setup"
cp $"($env.MODULE_DIRECTORY)/default-flatpaks/post-boot/user-flatpak-setup" $"($libExecPath)/user-flatpak-setup"
chmod +x $"($libExecPath)/system-flatpak-setup"
chmod +x $"($libExecPath)/user-flatpak-setup"
}

def checkFlathub [packages: list<string>] {
print "Checking if configured packages exist on Flathub..."
$packages | each { |package|
try {
let _ = http get $"https://flathub.org/apps/($package)"
} catch {
print $"(ansi red_bold)Package(ansi reset) (ansi default_italic)($package)(ansi reset) (ansi red_bold)does not exist on Flathub, which is the specified repository for it to be installed from.(ansi reset)"
exit 1
}
}
}
64 changes: 64 additions & 0 deletions modules/default-flatpaks/v2/post-boot/system-flatpak-setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/libexec/bluebuild/nu/nu

const usrSharePath = "/usr/share/bluebuild/default-flatpaks"
const configPath = $"($usrSharePath)/configuration.yaml"

def main [] {
let configFile = open $configPath

let keepFedora = configFile.configurations | where scope == system | any {|config|
$config.repo.url == "oci+https://registry.fedoraproject.org"
}

let systemRemotes = (flatpak remotes --system --columns name | split row "\n")
if (not $keepFedora and $systemRemotes | any {|remote| $remote == "fedora" or $remote == "fedora-testing"}) {
/usr/bin/gnome-software --quit
/usr/lib/fedora-third-party/fedora-third-party-opt-out
/usr/bin/fedora-third-party disable

if ($systemRemotes | any {|remote| $remote == "fedora"}) {
flatpak remote-delete --system fedora --force
}
if ($systemRemotes | any {|remote| $remote == "fedora-testing"}) {
flatpak remote-delete --system fedora-testing --force
}

let fedoraApps = flatpak list --system --app --columns=origin,application | detect columns --no-headers | where column0 == fedora | get column1
if ($fedoraApps | length > 0) {
flatpak remove --system --noninteractive ...$fedoraApps
}

let fedoraRuntimes = flatpak list --system --runtime --columns=origin,application,arch,branch | detect columns --no-headers | where column0 == fedora | each {|i| $"($i.column1)/($i.column2)/($i.column3)" }
if ($fedoraRuntimes | length > 0) {
flatpak remove --system --noninteractive ...$fedoraRuntimes
}
}

$configFile.configurations | where scope == system | each { |config|
flatpak remote-add --system --if-not-exists $config.repo.name $config.repo.url --title $config.repo.title

if ($config.notify) {
(notify-send-as-user
"--app-name" "Automatic Flatpak Installation Service"
$"Starting automated installation of ($config.install | length) system Flatpak\(s) from ($config.repo.title)..."
)
}

flatpak install --system $config.repo.name ...$config.install

if ($config.notify) {
(notify-send-as-user
"--app-name" "Automatic Flatpak Installation Service"
$"Finished automated installation of ($config.install | length) system Flatpak\(s) from ($config.repo.title)!"
($config.install | str join ', ')
)
}
}
}

def notify-send-as-user [...args] {
let user_name = (loginctl list-sessions --json=short | from json | get user | get 0)
let uid = (loginctl list-sessions --json=short | from json | get uid | get 0)
let xdg_runtime_path = $"/run/user/($uid)"
sudo -u $user_name DBUS_SESSION_BUS_ADDRESS=unix:path=($xdg_runtime_path)/bus notify-send ...$args
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[Unit]
Description=Manage system flatpaks
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/libexec/bluebuild/default-flatpaks/system-flatpak-setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[Unit]
Description=Timer for system-flatpak-setup

[Timer]
OnBootSec=30

[Install]
WantedBy=timers.target
53 changes: 53 additions & 0 deletions modules/default-flatpaks/v2/post-boot/user-flatpak-setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/libexec/bluebuild/nu/nu

const usrSharePath = "/usr/share/bluebuild/default-flatpaks"
const configPath = $"($usrSharePath)/configuration.yaml"

def main [] {
let configFile = open $configPath

let keepFedora = configFile.configurations | where scope == user | any {|config|
$config.repo.url == "oci+https://registry.fedoraproject.org"
}

let userRemotes = (flatpak remotes --user --columns name | split row "\n")
if (not $keepFedora) {
if ($userRemotes | any {|remote| $remote == "fedora"}) {
flatpak remote-delete --user fedora --force
}
if ($userRemotes | any {|remote| $remote == "fedora-testing"}) {
flatpak remote-delete --user fedora-testing --force
}

let fedoraApps = flatpak list --user --app --columns=origin,application | detect columns --no-headers | where column0 == fedora | get column1
if ($fedoraApps | length > 0) {
flatpak remove --user --noninteractive ...$fedoraApps
}

let fedoraRuntimes = flatpak list --user --runtime --columns=origin,application,arch,branch | detect columns --no-headers | where column0 == fedora | each {|i| $"($i.column1)/($i.column2)/($i.column3)" }
if ($fedoraRuntimes | length > 0) {
flatpak remove --user --noninteractive ...$fedoraRuntimes
}
}

$configFile.configurations | where scope == user | each { |config|
flatpak remote-add --user --if-not-exists $config.repo.name $config.repo.url --title $config.repo.title

if ($config.notify) {
(notify-send
--app-name "Automatic Flatpak Installation Service"
$"Starting automated installation of ($config.install | length) user Flatpak\(s) from ($config.repo.title)..."
)
}

flatpak install --user $config.repo.name ...$config.install

if ($config.notify) {
(notify-send
--app-name "Automatic Flatpak Installation Service"
$"Finished automated installation of ($config.install | length) user Flatpak\(s) from ($config.repo.title)!"
($config.install | str join ', ')
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[Unit]
Description=Configure Flatpaks for current user
Wants=network-online.target
After=system-flatpak-setup.service

[Service]
Type=oneshot
ExecStart=/usr/libexec/bluebuild/default-flatpaks/user-flatpak-setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[Unit]
Description=Timer for user-flatpak-setup

[Timer]
OnBootSec=30

[Install]
WantedBy=timers.target
Loading