Skip to content

Flatpak Support #737

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

Open
paerbac opened this issue Jun 3, 2022 · 32 comments · May be fixed by #2047
Open

Flatpak Support #737

paerbac opened this issue Jun 3, 2022 · 32 comments · May be fixed by #2047
Assignees
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@paerbac
Copy link

paerbac commented Jun 3, 2022

Would prefer a flatpak distribution option be supported

@bschelst
Copy link

same here, it would be handy for the steamdeck!

@tdworz
Copy link

tdworz commented Jul 5, 2023

There are 3 competitor apps on Flathub already.

  1. https://flathub.org/apps/app.ytmdesktop.ytmdesktop
  2. https://flathub.org/apps/io.gitlab.zehkira.Monophony
  3. https://flathub.org/apps/org.kde.audiotube

However this is my favorite YouTube Music desktop app and I wish it was there as well.

@tdworz
Copy link

tdworz commented Jul 5, 2023

I created a request for this app in the Flathub forums: https://discourse.flathub.org/t/th-ch-youtube-music/4527

@razzeee
Copy link

razzeee commented Jul 7, 2023

There is also https://github.com/vixalien/muzika coming up to flathub soonish, just for your list.

@JellyBrick JellyBrick added the enhancement New feature or request label Oct 7, 2023
@JellyBrick
Copy link
Collaborator

Is there anyone interested in doing this task?

@JellyBrick JellyBrick added the help wanted Extra attention is needed label Oct 9, 2023
@justin13888
Copy link

I strongly believe that for the sake of cross compatibility across all desktop Linux distros, flatpak should be a supported method of installation. But also one thing to be careful of is ensuring plugins like Discord works.

@justin13888
Copy link

Also adding this link for reference to support using Discord Flatpak, although that's something more for users using the Discord Flatpak to worry about: https://github.com/flathub/com.discordapp.Discord/wiki/Rich-Precense-(discord-rpc)

@ArjixWasTaken ArjixWasTaken self-assigned this Nov 30, 2023
@inson1
Copy link
Contributor

inson1 commented Feb 14, 2024

Github action for building flatpak https://github.com/flatpak/flatpak-github-actions

@razzeee
Copy link

razzeee commented Feb 14, 2024

You actually should use https://github.com/flathub-infra/flatpak-github-actions for flathub - but getting the flatpak building is the first step

@xynydev
Copy link

xynydev commented Feb 22, 2024

I see that this project uses electron-builder for releases. They have a Flatpak build target too, but that doesn't support publishing to Flathub. It would probably be pretty easy to add that build target, though, so that Flatpak users on stuff like immutable Linux distributions would have at least some way of installing.

@justin13888
Copy link

There are 3 competitor apps on Flathub already.

1. https://flathub.org/apps/app.ytmdesktop.ytmdesktop

2. https://flathub.org/apps/io.gitlab.zehkira.Monophony

3. https://flathub.org/apps/org.kde.audiotube

However this is my favorite YouTube Music desktop app and I wish it was there as well.

Currently, ytmdesktop (first link) seems no longer maintained on FlatHub. But doesn't matter cuz I like th-ch/youtube-music more

@justin13888
Copy link

I see that this project uses electron-builder for releases. They have a Flatpak build target too, but that doesn't support publishing to Flathub. It would probably be pretty easy to add that build target, though, so that Flatpak users on stuff like immutable Linux distributions would have at least some way of installing.

Is anybody working on this currently? Otherwise, I could probably do it lol: https://www.electron.build/configuration/flatpak.html

@Grafcube Grafcube linked a pull request May 11, 2024 that will close this issue
@Grafcube
Copy link

I've just opened a PR to add Flatpak support at #2047

@KweezyCode
Copy link

any news?

@DrWafflePhD
Copy link

Has this been added to the flathub yet? If not, how do I install the flatpak?

@ArjixWasTaken
Copy link
Contributor

Has this been added to the flathub yet? If not, how do I install the flatpak?

#2047 (comment)

@JellyBrick
Copy link
Collaborator

Partially implemented at b668730

(flatpak single bundle)

@vixalien
Copy link

vixalien commented Feb 5, 2025

Would be nice if this was on flathub. Maybe I can work towards that...

@ygypt
Copy link

ygypt commented Mar 22, 2025

Dropping in to say that I'm on an immutable distro, flatpak is basically my package manager, love this app and a flatpak bundle would be lovely

@ArjixWasTaken
Copy link
Contributor

For now I wrote this script for my personal usage:

#!/bin/env bash

DOWNLOAD_DIR="$HOME/.local/share/youtube-music-updater"
mkdir -p "$DOWNLOAD_DIR"

latest=$(wget 'https://github.com/th-ch/youtube-music/releases/latest/download/latest-linux.yml' -q -O -)
version=$(echo "$latest" | grep 'version' | awk '{ print $2 }')

echo "Downloading YouTube Music version $version"
wget "https://github.com/th-ch/youtube-music/releases/latest/download/YouTube-Music-$version-x86_64.flatpak" \
    -q --show-progress \
    -O "$DOWNLOAD_DIR/YouTube-Music-$version-x86_64.flatpak"

flatpak remove --user --assumeyes --noninteractive com.github.th_ch.youtube_music
flatpak install --user --assumeyes --noninteractive "$DOWNLOAD_DIR/YouTube-Music-$version-x86_64.flatpak"

feel free to improve it

@hanthor
Copy link

hanthor commented Mar 28, 2025

I made some AI-aided improvements (using aria2 for downloading since wget was slow, and adding an option of putting it on a daily timer):

#!/bin/env bash

# Strict mode: exit on errors, undefined variables, and pipe failures
set -euo pipefail

# --- Configuration ---
APP_ID="com.github.th_ch.youtube_music"
REPO_OWNER="th-ch"
REPO_NAME="youtube-music"
DOWNLOAD_DIR="$HOME/.local/share/youtube-music-updater"
ARCH="x86_64" # Assuming x86_64, adjust if needed
SCRIPT_NAME="update-youtube-music" # Base name for service/timer files
SYSTEMD_USER_DIR="$HOME/.config/systemd/user"
SERVICE_FILE="$SYSTEMD_USER_DIR/$SCRIPT_NAME.service"
TIMER_FILE="$SYSTEMD_USER_DIR/$SCRIPT_NAME.timer"


# --- Helper Functions ---
info() {
    echo "[INFO] $1"
}

warn() {
    echo "[WARN] $1" >&2
}

error() {
    echo "[ERROR] $1" >&2
    exit 1
}

check_command() {
    command -v "$1" >/dev/null 2>&1
}

# --- Systemd Timer Setup Function ---
setup_timer() {
    info "Starting systemd timer setup..."

    # Check if systemctl --user is available
    if ! check_command "systemctl"; then
        error "systemctl command not found. Cannot manage systemd user units."
    fi
    # Attempt a basic user command to ensure user instance is running
    if ! systemctl --user list-units > /dev/null 2>&1; then
         error "Cannot connect to systemd user instance. Ensure it's running (loginctl enable-linger $USER may be needed if you're not logged in graphically)."
    fi


    # Check if files already exist
    if [[ -f "$SERVICE_FILE" && -f "$TIMER_FILE" ]]; then
        info "Systemd service ($SERVICE_FILE) and timer ($TIMER_FILE) files already exist."
        info "To apply changes or restart, you can use:"
        info "  systemctl --user daemon-reload"
        info "  systemctl --user restart $SCRIPT_NAME.timer"
        exit 0
    fi

    # Get the absolute path to this script
    # Using BASH_SOURCE is generally reliable when the script is executed directly
    # realpath might not be installed, so try BASH_SOURCE first
    local script_path
    if [[ -n "${BASH_SOURCE[0]}" ]]; then
        script_path=$(realpath "${BASH_SOURCE[0]}")
    else
        # Fallback attempt if BASH_SOURCE is empty (less common)
        script_path=$(realpath "$0") || error "Could not determine the absolute path of this script. Cannot create systemd service."
    fi

    info "Script absolute path determined as: $script_path"
    info "Creating systemd user directory: $SYSTEMD_USER_DIR"
    mkdir -p "$SYSTEMD_USER_DIR"

    # Create Service File
    info "Creating service file: $SERVICE_FILE"
    # Quoting 'EOF' prevents variable expansion inside the heredoc
    cat << 'EOF' > "$SERVICE_FILE"
[Unit]
Description=Update YouTube Music Flatpak
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
# Note: %f in ExecStart will be replaced by the script path
ExecStart=%f
EOF
    # Replace placeholder %f with the actual script path (escape slashes for sed)
    local escaped_script_path
    escaped_script_path=$(echo "$script_path" | sed 's/\//\\\//g')
    sed -i "s/%f/$escaped_script_path/" "$SERVICE_FILE"


    # Create Timer File
    info "Creating timer file: $TIMER_FILE"
    cat << 'EOF' > "$TIMER_FILE"
[Unit]
Description=Run YouTube Music Flatpak updater daily
# Ensures the timer unit itself is correctly tracked
RefuseManualStart=no
RefuseManualStop=no

[Timer]
# Run daily at 3 AM; adjust as needed (e.g., '*-*-* 03:00:00')
# Or simply 'daily' for midnight
OnCalendar=daily
# Run shortly after boot if missed, and randomized delay to avoid thundering herd
RandomizedDelaySec=10m
Persistent=true

[Install]
WantedBy=timers.target
EOF

    info "Reloading systemd user daemon..."
    if systemctl --user daemon-reload; then
        info "Daemon reloaded successfully."
    else
        warn "systemctl daemon-reload failed. Manual reload might be needed."
    fi

    info "Enabling and starting the timer ($SCRIPT_NAME.timer)..."
    # Use enable --now to both enable on boot and start immediately
    if systemctl --user enable --now "$SCRIPT_NAME.timer"; then
        info "Timer enabled and started successfully."
        info "Update check will run daily (check timer file for exact schedule)."
        info "Check status with: systemctl --user status $SCRIPT_NAME.timer"
    else
        error "Failed to enable or start the timer. Check systemctl/journalctl logs for errors."
    fi

    exit 0 # Exit after successful setup
}


# --- Argument Parsing ---
if [[ "${1:-}" == "--setup-timer" ]]; then
    setup_timer
    # setup_timer exits on its own, but added exit here for clarity
    exit 0
fi

# --- Main Script ---
info "Starting YouTube Music update check..."

# --- Offer Timer Setup ---
# Check if timer exists during a normal run and suggest setup if not
if ! [[ -f "$TIMER_FILE" ]]; then
    # Check if we are in an interactive terminal before suggesting
    if [[ -t 1 ]]; then
         # Try to get script name robustly
         current_script_name="${BASH_SOURCE[0]:-$0}"
         info "Systemd timer file ($TIMER_FILE) not found."
         info "To set up automatic daily updates, run this script with the --setup-timer flag:"
         info "  $current_script_name --setup-timer"
         # Add a small pause so the user sees the message
         sleep 1
    fi
fi

# Create download directory
mkdir -p "$DOWNLOAD_DIR"
info "Using download directory: $DOWNLOAD_DIR"

# Fetch latest version info from GitHub releases
LATEST_YML_URL="https://github.com/$REPO_OWNER/$REPO_NAME/releases/latest/download/latest-linux.yml"
info "Fetching latest version info from $LATEST_YML_URL"
latest_yml_content=$(curl -sL "$LATEST_YML_URL") || error "Failed to fetch latest version info. Check network or URL."

latest_version=$(echo "$latest_yml_content" | grep 'version:' | awk '{ print $2 }')
if [ -z "$latest_version" ]; then
    error "Could not parse latest version from the yml file."
fi
info "Latest available version: $latest_version"

# Check currently installed version
installed_version=$(flatpak info "$APP_ID" 2>/dev/null | grep Version | awk '{print $2}' || echo "none")

if [[ "$installed_version" == "$latest_version" ]]; then
    info "YouTube Music is already up to date (version $installed_version)."
    exit 0
elif [[ "$installed_version" == "none" ]]; then
    info "YouTube Music is not currently installed."
else
    info "Installed version ($installed_version) differs from latest ($latest_version). Proceeding with update."
fi

# Determine downloader (prefer aria2c)
downloader=""
if check_command "aria2c"; then
    info "Using aria2c for download."
    downloader="aria2c"
else
    warn "aria2c not found. Attempting to install or find fallback..."
    # (Installation attempt/recommendation logic remains the same)
    if check_command "brew"; then
        info "Detected Homebrew. Trying 'brew install aria2'..."
        if brew install aria2; then
            if check_command "aria2c"; then
                 info "Successfully installed aria2c via Homebrew."
                 downloader="aria2c"
            else
                 warn "Homebrew install command succeeded but aria2c still not found."
            fi
        else
            warn "Failed to install aria2 via Homebrew."
        fi
    elif check_command "apt"; then
        warn "Detected apt. Recommend installing aria2 manually: sudo apt update && sudo apt install aria2"
    elif check_command "dnf"; then
        warn "Detected dnf. Recommend installing aria2 manually: sudo dnf install aria2"
    elif check_command "pacman"; then
        warn "Detected pacman. Recommend installing aria2 manually: sudo pacman -S aria2"
    elif check_command "zypper"; then
        warn "Detected zypper. Recommend installing aria2 manually: sudo zypper install aria2"
    else
        warn "Could not find brew or common Linux package managers to install aria2."
    fi

    if [[ -z "$downloader" ]]; then
        if check_command "wget"; then
            warn "Falling back to wget for download."
            downloader="wget"
        else
            error "Neither aria2c nor wget found. Cannot download the file."
        fi
    fi
fi

# Prepare download URL and filename
FILENAME="YouTube-Music-$latest_version-$ARCH.flatpak"
DOWNLOAD_URL="https://github.com/$REPO_OWNER/$REPO_NAME/releases/latest/download/$FILENAME"
OUTPUT_PATH="$DOWNLOAD_DIR/$FILENAME"

info "Downloading YouTube Music version $latest_version..."

# Download using the selected tool
download_success=false
if [[ "$downloader" == "aria2c" ]]; then
    if aria2c -c -x 1 -s 1 --dir="$DOWNLOAD_DIR" -o "$FILENAME" "$DOWNLOAD_URL"; then
        download_success=true
    else
        warn "aria2c download failed."
    fi
elif [[ "$downloader" == "wget" ]]; then
    # Using -nv (non-verbose) instead of --show-progress for better timer logs
    if wget -c -nv -O "$OUTPUT_PATH" "$DOWNLOAD_URL"; then
        download_success=true
    else
        warn "wget download failed."
    fi
fi

if ! $download_success; then
     error "Download failed. Please check network connection or logs."
fi

info "Download complete: $OUTPUT_PATH"

# Install the Flatpak
info "Removing previous version (if exists)..."
flatpak remove --user --assumeyes --noninteractive "$APP_ID" || true

info "Installing new version $latest_version..."
if flatpak install --user --assumeyes --noninteractive "$OUTPUT_PATH"; then
    info "Successfully installed YouTube Music version $latest_version."
else
    error "Flatpak installation failed."
fi

# Cleanup old downloads
info "Cleaning up old downloads..."
find "$DOWNLOAD_DIR" -maxdepth 1 -name "YouTube-Music-*.flatpak" -not -name "$FILENAME" -delete

info "Update process finished successfully."
exit 0

@mio-19
Copy link

mio-19 commented Apr 9, 2025

Currently there is only x86_64. It would be great if aarch64 can be supported

@ArjixWasTaken
Copy link
Contributor

ArjixWasTaken commented Apr 9, 2025

Since the flatpak bundle does not contain version information, it is seemingly impossible to compare the local version with the latest version from a shell script.

BUT I did find a messy workaround 🤣

strings ~/.local/share/flatpak/app/com.github.th_ch.youtube_music/current/active/files/lib/com.github.th_ch.youtube_music/resources/app.asar | rg -o -U '"name":\s*"youtube-music"(?:.|\n)+"version":\s*"(.+)"'

Image

--

I'll soon update my script

@ArjixWasTaken
Copy link
Contributor

ArjixWasTaken commented Apr 9, 2025

New script:

#!/bin/env amber

import { env_const_get, printf, styled } from "std/env"
import { file_download } from "std/http"

fun info(message: Text): Null {
    const BOLD = 1
    const FG_WHITE = 37
    const BG_BLACK = 40

    const tag = styled("info", BOLD, FG_WHITE, BG_BLACK)
    printf("[{tag}]: %s\n", [message])
}

fun error(message: Text): Null {
    const BOLD = 1
    const FG_RED = 31
    const BG_BLACK = 40

    const tag = styled("error", BOLD, FG_RED, BG_BLACK)
    printf("[{tag}]: %s\n", [message])
    exit 1
}

const download_dir = trust env_const_get("HOME") + "/.local/share/youtube-music-updater"
$ mkdir -p "{download_dir}" $ failed {
    error("Failed to create download directory: {download_dir}")
}

fun remote_version() {
    info("Fetching latest release info from GitHub...")
    
    const latest_release = "https://github.com/th-ch/youtube-music/releases/latest/download/latest-linux.yml"
    const latest_yaml_path = "{download_dir}/latest-linux.yml"

    if not silent file_download(latest_release, latest_yaml_path) {
        error("Failed to download latest release info from {latest_release}")
    }

    return trust $ yq '.version' "{latest_yaml_path}" -r $
}

fun local_version() {
    info("Fetching local version info...")

    const strings = $ strings ~/.local/share/flatpak/app/com.github.th_ch.youtube_music/current/active/files/lib/com.github.th_ch.youtube_music/resources/app.asar $ failed {
        error("Failed to read local version info")
    }

    const package_json = $ echo "{strings}" | rg -o -U '"name":\s*"youtube-music"(?:.|\n)+"version":\s*"(.+)"' $ failed {
        error("Failed to find local version info")
    }

    const version = $ echo "{package_json}" | rg -o -U '"version":\s*"(.+)"' | rg -o '\d+\.\d+\.\d+' $ failed {
        error("Failed to extract local version info")
    }

    return version
}

const version = remote_version()
if version == local_version() {
    info("YouTube Music is up to date.")
    exit
}

info("Downloading YouTube Music version {version}...")

const download_path = "{download_dir}/YouTube-Music-{version}-x86_64.flatpak"
if not file_download("https://github.com/th-ch/youtube-music/releases/latest/download/YouTube-Music-{version}-x86_64.flatpak", download_path) {
    error("Failed to download YouTube Music version {version}")
}

$ flatpak remove --user --assumeyes --noninteractive com.github.th_ch.youtube_music $ failed {
    error("Failed to remove old version of YouTube Music")
}

$ flatpak install --user --assumeyes --noninteractive "{download_path}" $ failed {
    error("Failed to install YouTube Music version {version}")
}

It is written using Amber, and is much more verbose yet more elegant and safe.


script dependencies:

  • yq: a jq preprocessor for yaml files
  • flatpak: obviously
  • strings: a utility that reads all ASCII from a binary
  • curl, wget or aria2

@b1ek
Copy link

b1ek commented Apr 9, 2025

safe

only if you have bshchk installed, otherwise its just as safe as bash. also we haven't completely figured out the whole runtime type system and if it is safe yet

and amber is also in a very early stage so i'd advise against using it for now, unless you're fine with rewriting your code to update to the next version

@ArjixWasTaken
Copy link
Contributor

safe

only if you have bshchk installed, otherwise its just as safe as bash. also we haven't completely figured out the whole runtime type system and if it is safe yet

well, I meant "safe" as in "safe from programmer mistakes", just like typescript isn't safe if you are not honest with it

@ygypt
Copy link

ygypt commented Apr 19, 2025

What does it take to get the flatpak onto flathub?

@olumolu
Copy link

olumolu commented Apr 20, 2025

When this app will be on flatpak?

@ygypt
Copy link

ygypt commented Apr 20, 2025

When this app will be on flatpak?

There's a flatpak in the latest releases page

It's not on Flathub tho

@ArjixWasTaken
Copy link
Contributor

The current flatpak we have does not allow incremental updates, and I don't think it will be accepted by flathub.

@olumolu
Copy link

olumolu commented Apr 20, 2025

When this app will be on flatpak?

There's a flatpak in the latest releases page

It's not on Flathub tho

if the app is not in flathub or somewhere like this it is not reliable to install that as it will be not updated i have to do this manually.

@ArjixWasTaken
Copy link
Contributor

When this app will be on flatpak?

There's a flatpak in the latest releases page

It's not on Flathub tho

if the app is not in flathub or somewhere like this it is not reliable to install that as it will be not updated i have to do this manually.

I simply have a systemd service that runs this script when my user logs in.

#737 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.