diff --git a/config/scripts/install-atuin.sh b/config/scripts/install-atuin.sh index 6f71459..ecaac10 100644 --- a/config/scripts/install-atuin.sh +++ b/config/scripts/install-atuin.sh @@ -4,6 +4,4 @@ set -oue pipefail wget https://github.com/atuinsh/atuin/releases/download/v18.3.0/atuin-x86_64-unknown-linux-gnu.tar.gz -O /tmp/atuin.tar.gz tar -xf /tmp/atuin.tar.gz -C /tmp -ls -la /tmp -ls -la install -m 755 /tmp/atuin-x86_64-unknown-linux-gnu/atuin /usr/bin/atuin diff --git a/modules/rpm-opt-patch/README.md b/modules/rpm-opt-patch/README.md new file mode 100644 index 0000000..537fa8d --- /dev/null +++ b/modules/rpm-opt-patch/README.md @@ -0,0 +1,26 @@ +# `rpm-ostree` + +The [`rpm-ostree`](https://coreos.github.io/rpm-ostree/) module offers pseudo-declarative package and repository management using `rpm-ostree`. + +The module first downloads the repository files from repositories declared under `repos:` into `/etc/yum.repos.d/`. The magic string `%OS_VERSION%` is substituted with the current VERSION_ID (major Fedora version), which can be used, for example, for pulling correct versions of repositories from [Fedora's Copr](https://copr.fedorainfracloud.org/). + +If you use a repo that requires adding custom keys (eg. Brave Browser), you can import the keys by declaring the key URLs under `keys:`. The magic string acts the same as it does in `repos`. + +Then the module installs the packages declared under `install:` using `rpm-ostree install`, it removes the packages declared under `remove:` using `rpm-ostree override remove`. If there are packages declared under both `install:` and `remove:` a hybrid command `rpm-ostree remove --install ` is used, which should allow you to switch required packages for other ones. + +Installing RPM packages directly from a `http(s)` url that points to the RPM file is also supported, you can just put the URLs under `install:` and they'll be installed along with the other packages. The magic string `%OS_VERSION%` is substituted with the current VERSION_ID (major Fedora version) like with the `repos:` property. + +:::note +[Removed packages are still present in the underlying ostree repository](https://coreos.github.io/rpm-ostree/administrator-handbook/#removing-a-base-package), what `remove` does is kind of like hiding them from the system, it doesn't free up storage space. +::: + +Additionally, the `rpm-ostree` module supports a temporary (waiting for `rpm-ostree` issue [#233](https://github.com/coreos/rpm-ostree/issues/233)) fix for packages that install into `/opt/`. Installation for packages that install into folder names declared under `optfix:` are fixed using some symlinks. + +## Known issues + +When removing certain packages, some problem probably in upstream `rpm-ostree` causes a `depsolve` issue similar to below. +``` +Resolving dependencies...done +error: Could not depsolve transaction; 1 problem detected: +Problem: conflicting requests +``` diff --git a/modules/rpm-opt-patch/module.yml b/modules/rpm-opt-patch/module.yml new file mode 100644 index 0000000..860e389 --- /dev/null +++ b/modules/rpm-opt-patch/module.yml @@ -0,0 +1,17 @@ +name: rpm-opt-patch +shortdesc: The rpm-ostree module offers pseudo-declarative package and repository management using rpm-ostree. +readme: https://raw.githubusercontent.com/blue-build/modules/main/modules/rpm-ostree/README.md +example: | + type: rpm-ostree + repos: + - https://copr.fedorainfracloud.org/coprs/atim/starship/repo/fedora-%OS_VERSION%/atim-starship-fedora-%OS_VERSION%.repo # when including COPR repos, use the %OS_VERSION% magic string + - https://pkgs.tailscale.com/stable/fedora/tailscale.repo + - https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo + keys: + - https://brave-browser-rpm-release.s3.brave.com/brave-core.asc + install: + - python3-pip + - libadwaita + remove: + - firefox + - firefox-langpacks diff --git a/modules/rpm-opt-patch/rpm-opt-patch.sh b/modules/rpm-opt-patch/rpm-opt-patch.sh new file mode 100644 index 0000000..3a2f100 --- /dev/null +++ b/modules/rpm-opt-patch/rpm-opt-patch.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -euo pipefail + +# Pull in repos +get_yaml_array REPOS '.repos[]' "$1" +if [[ ${#REPOS[@]} -gt 0 ]]; then + echo "Adding repositories" + for REPO in "${REPOS[@]}"; do + REPO="${REPO//%OS_VERSION%/${OS_VERSION}}" + curl --output-dir "/etc/yum.repos.d/" -O "${REPO//[$'\t\r\n ']}" + done +fi + +get_yaml_array KEYS '.keys[]' "$1" +if [[ ${#KEYS[@]} -gt 0 ]]; then + echo "Adding keys" + for KEY in "${KEYS[@]}"; do + KEY="${KEY//%OS_VERSION%/${OS_VERSION}}" + rpm --import "${KEY//[$'\t\r\n ']}" + done +fi + +# Create symlinks to fix packages that create directories in /opt +get_yaml_array OPTFIX '.optfix[]' "$1" +if [[ ${#OPTFIX[@]} -gt 0 ]]; then + echo "Creating symlinks to fix packages that install to /opt" + # Create symlink for /opt to /var/opt since it is not created in the image yet + mkdir -p "/var/opt" + ln -s "/var/opt" "/opt" + # Create symlinks for each directory specified in recipe.yml + for OPTPKG in "${OPTFIX[@]}"; do + OPTPKG="${OPTPKG%\"}" + OPTPKG="${OPTPKG#\"}" + OPTPKG=$(printf "$OPTPKG") + mkdir -p "/usr/lib/opt/${OPTPKG}" + ln -s "/usr/lib/opt/${OPTPKG}" "/var/opt/${OPTPKG}" + echo "Created symlinks for ${OPTPKG}" + ls -la /var/ + ls -la /var/opt/ + ls -la / + ls -la /opt/ + done +fi + +get_yaml_array INSTALL '.install[]' "$1" +get_yaml_array REMOVE '.remove[]' "$1" + +if [[ ${#INSTALL[@]} -gt 0 ]]; then + for PKG in "${INSTALL[@]}"; do + if [[ "$PKG" =~ ^https?:\/\/.* ]]; then + REPLACED_PKG="${PKG//%OS_VERSION%/${OS_VERSION}}" + echo "Installing directly from URL: ${REPLACED_PKG}" + rpm-ostree install "$REPLACED_PKG" + INSTALL=( "${INSTALL[@]/$PKG}" ) # delete URL from install array + fi + done +fi + +# The installation is done with some wordsplitting hacks +# because of errors when doing array destructuring at the installation step. +# This is different from other ublue projects and could be investigated further. +INSTALL_STR=$(echo "${INSTALL[*]}" | tr -d '\n') +REMOVE_STR=$(echo "${REMOVE[*]}" | tr -d '\n') + +# Install and remove RPM packages +if [[ ${#INSTALL[@]} -gt 0 && ${#REMOVE[@]} -gt 0 ]]; then + echo "Installing & Removing RPMs" + echo "Installing: ${INSTALL_STR[*]}" + echo "Removing: ${REMOVE_STR[*]}" + # Doing both actions in one command allows for replacing required packages with alternatives + rpm-ostree override remove $REMOVE_STR $(printf -- "--install=%s " $INSTALL_STR) +elif [[ ${#INSTALL[@]} -gt 0 ]]; then + echo "Installing RPMs" + echo "Installing: ${INSTALL_STR[*]}" + rpm-ostree install $INSTALL_STR +elif [[ ${#REMOVE[@]} -gt 0 ]]; then + echo "Removing RPMs" + echo "Removing: ${REMOVE_STR[*]}" + rpm-ostree override remove $REMOVE_STR +fi diff --git a/recipes/recipe.yml b/recipes/recipe.yml index 8936577..408669b 100644 --- a/recipes/recipe.yml +++ b/recipes/recipe.yml @@ -19,7 +19,7 @@ modules: - type: script scripts: - install-atuin.sh - - type: rpm-ostree + - type: rpm-opt-patch repos: - https://copr.fedorainfracloud.org/coprs/atim/starship/repo/fedora-40/atim-starship-fedora-40.repo - https://copr.fedorainfracloud.org/coprs/varlad/zellij/repo/fedora-40/varlad-zellij-fedora-40.repo