From fd4ad2841308c86adb1c5c0a6d8f40b84b2b9fb1 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 14:52:54 +0100 Subject: [PATCH 01/51] feat: `dnf` module --- modules/dnf/README.md | 29 +++++++ modules/dnf/dnf.sh | 189 +++++++++++++++++++++++++++++++++++++++++ modules/dnf/dnf.tsp | 33 +++++++ modules/dnf/module.yml | 25 ++++++ 4 files changed, 276 insertions(+) create mode 100644 modules/dnf/README.md create mode 100644 modules/dnf/dnf.sh create mode 100644 modules/dnf/dnf.tsp create mode 100644 modules/dnf/module.yml diff --git a/modules/dnf/README.md b/modules/dnf/README.md new file mode 100644 index 0000000..6ba70c1 --- /dev/null +++ b/modules/dnf/README.md @@ -0,0 +1,29 @@ +# `dnf` + +The [`dnf`](https://docs.fedoraproject.org/en-US/quick-docs/dnf/) module offers pseudo-declarative package and repository management using `dnf`. + +The module first downloads the repository files from URLs 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/). + +You can also add repository files directly into your git repository if URLs are not provided. For example: +```yml +repos: + - my-repository.repo # copies in .repo file from files/dnf/my-repository.repo to /etc/yum.repos.d/ +``` +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 `dnf install`, it removes the packages declared under `remove:` using `dnf remove`. If there are packages declared under both `install:` and `remove:` a hybrid command `dnf 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. + +If an RPM is not available in a repository or as an URL, you can also install it directly from a file in your git repository. For example: +```yml +install: + - weird-package.rpm # tries to install files/dnf/weird-package.rpm +``` +The module can also replace base RPM packages with packages from COPR repo. Under `replace:`, the module finds every pair of keys `- from-repo:` and `packages:`. (Multiple pairs are supported.) The module downloads the COPR repository file declared by `- from-repo:` into `/etc/yum.repos.d/`, and from that repository replaces packages declared under `packages:` using the command `dnf replace`. The COPR repository file is then deleted. The magic string `%OS_VERSION%` is substituted with the current VERSION_ID (major Fedora version) as already said above. At the moment, only COPR repo is supported. + +:::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 `dnf` module supports a fix for packages that install into `/opt/`. Installation for packages that install into folder names declared under `optfix:` are fixed using some symlinks. Directory path in `/opt/` for those packages should be provided in recipe, like in Example Configuration. \ No newline at end of file diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh new file mode 100644 index 0000000..266814c --- /dev/null +++ b/modules/dnf/dnf.sh @@ -0,0 +1,189 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -euo pipefail + +# Pull in repos +get_json_array REPOS 'try .["repos"][]' "$1" +if [[ ${#REPOS[@]} -gt 0 ]]; then + echo "Adding repositories" + for REPO in "${REPOS[@]}"; do + REPO="${REPO//%OS_VERSION%/${OS_VERSION}}" + REPO="${REPO//[$'\t\r\n ']}" + + # If it's the COPR repo, then download the repo normally + # If it's not, then download the repo with URL in it's filename, to avoid duplicate repo name issue + if [[ "${REPO}" =~ ^https?:\/\/.* ]] && [[ "${REPO}" == "https://copr.fedorainfracloud.org/coprs/"* ]]; then + echo "Downloading repo file ${REPO}" + curl -fLs --create-dirs -O "${REPO}" --output-dir "/etc/yum.repos.d/" + echo "Downloaded repo file ${REPO}" + elif [[ "${REPO}" =~ ^https?:\/\/.* ]] && [[ "${REPO}" != "https://copr.fedorainfracloud.org/coprs/"* ]]; then + CLEAN_REPO_NAME=$(echo "${REPO}" | sed -E 's|^https?://([^?]+)(\?.*)?$|\1|') + CLEAN_REPO_NAME="${CLEAN_REPO_NAME//\//.}" + + echo "Downloading repo file ${REPO}" + curl -fLs --create-dirs "${REPO}" -o "/etc/yum.repos.d/${CLEAN_REPO_NAME}" + echo "Downloaded repo file ${REPO}" + elif [[ ! "${REPO}" =~ ^https?:\/\/.* ]] && [[ "${REPO}" == *".repo" ]] && [[ -f "${CONFIG_DIRECTORY}/rpm-ostree/${REPO}" ]]; then + cp "${CONFIG_DIRECTORY}/rpm-ostree/${REPO}" "/etc/yum.repos.d/${REPO##*/}" + fi + done +fi + +get_json_array KEYS 'try .["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_json_array OPTFIX 'try .["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#\"}" + mkdir -p "/usr/lib/opt/${OPTPKG}" + ln -s "../../usr/lib/opt/${OPTPKG}" "/var/opt/${OPTPKG}" + echo "Created symlinks for ${OPTPKG}" + done +fi + +get_json_array INSTALL_PKGS 'try .["install"][]' "$1" +get_json_array REMOVE_PKGS 'try .["remove"][]' "$1" + +CLASSIC_INSTALL=false +HTTPS_INSTALL=false +LOCAL_INSTALL=false + +# Install and remove RPM packages +# Sort classic, URL & local packages +if [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then + for i in "${!INSTALL_PKGS[@]}"; do + PKG="${INSTALL_PKGS[$i]}" + if [[ "${PKG}" =~ ^https?:\/\/.* ]]; then + INSTALL_PKGS[$i]="${PKG//%OS_VERSION%/${OS_VERSION}}" + HTTPS_INSTALL=true + HTTPS_PKGS+=("${INSTALL_PKGS[$i]}") + elif [[ ! "${PKG}" =~ ^https?:\/\/.* ]] && [[ -f "${CONFIG_DIRECTORY}/rpm-ostree/${PKG}" ]]; then + LOCAL_INSTALL=true + LOCAL_PKGS+=("${CONFIG_DIRECTORY}/rpm-ostree/${PKG}") + else + CLASSIC_INSTALL=true + CLASSIC_PKGS+=("${PKG}") + fi + done +fi + +echo_rpm_install() { + if ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then + echo "Installing: ${CLASSIC_PKGS[*]}" + elif ! ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then + echo "Installing package(s) directly from URL: ${HTTPS_PKGS[*]}" + elif ! ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then + echo "Installing local package(s): ${LOCAL_PKGS[*]}" + elif ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then + echo "Installing: ${CLASSIC_PKGS[*]}" + echo "Installing package(s) directly from URL: ${HTTPS_PKGS[*]}" + elif ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then + echo "Installing: ${CLASSIC_PKGS[*]}" + echo "Installing local package(s): ${LOCAL_PKGS[*]}" + elif ! ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then + echo "Installing package(s) directly from URL: ${HTTPS_PKGS[*]}" + echo "Installing local package(s): ${LOCAL_PKGS[*]}" + elif ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then + echo "Installing: ${CLASSIC_PKGS[*]}" + echo "Installing package(s) directly from URL: ${HTTPS_PKGS[*]}" + echo "Installing local package(s): ${LOCAL_PKGS[*]}" + fi +} + +if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then + echo "Installing & Removing RPMs" + echo_rpm_install + echo "Removing: ${REMOVE_PKGS[*]}" + # Doing both actions in one command allows for replacing required packages with alternatives + # When --install= flag is used, URLs & local packages are not supported + if ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then + rpm-ostree override remove "${REMOVE_PKGS[@]}" $(printf -- "--install=%s " "${CLASSIC_PKGS[@]}") + elif ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then + rpm-ostree override remove "${REMOVE_PKGS[@]}" $(printf -- "--install=%s " "${CLASSIC_PKGS[@]}") + rpm-ostree install "${HTTPS_PKGS[@]}" + elif ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then + rpm-ostree override remove "${REMOVE_PKGS[@]}" $(printf -- "--install=%s " "${CLASSIC_PKGS[@]}") + rpm-ostree install "${LOCAL_PKGS[@]}" + elif ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then + rpm-ostree override remove "${REMOVE_PKGS[@]}" $(printf -- "--install=%s " "${CLASSIC_PKGS[@]}") + rpm-ostree install "${HTTPS_PKGS[@]}" "${LOCAL_PKGS[@]}" + elif ! ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then + rpm-ostree override remove "${REMOVE_PKGS[@]}" + rpm-ostree install "${LOCAL_PKGS[@]}" + elif ! ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then + rpm-ostree override remove "${REMOVE_PKGS[@]}" + rpm-ostree install "${HTTPS_PKGS[@]}" + elif ! ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then + rpm-ostree override remove "${REMOVE_PKGS[@]}" + rpm-ostree install "${HTTPS_PKGS[@]}" "${LOCAL_PKGS[@]}" + fi +elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then + echo "Installing RPMs" + echo_rpm_install + rpm-ostree install "${INSTALL_PKGS[@]}" +elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then + echo "Removing RPMs" + echo "Removing: ${REMOVE_PKGS[*]}" + rpm-ostree override remove "${REMOVE_PKGS[@]}" +fi + +get_json_array REPLACE 'try .["replace"][]' "$1" + +# Override-replace RPM packages +if [[ ${#REPLACE[@]} -gt 0 ]]; then + for REPLACEMENT in "${REPLACE[@]}"; do + + # Get repository + REPO=$(echo "${REPLACEMENT}" | jq -r 'try .["from-repo"]') + REPO="${REPO//%OS_VERSION%/${OS_VERSION}}" + + # Ensure repository is provided + if [[ "${REPO}" == "null" ]]; then + echo "Error: Key 'from-repo' was declared, but repository URL was not provided." + exit 1 + fi + + # Get info from repository URL + MAINTAINER=$(awk -F'/' '{print $5}' <<< "${REPO}") + REPO_NAME=$(awk -F'/' '{print $6}' <<< "${REPO}") + FILE_NAME=$(awk -F'/' '{print $9}' <<< "${REPO}" | sed 's/\?.*//') # Remove params after '?' + + # Get packages to replace + get_json_array PACKAGES 'try .["packages"][]' "${REPLACEMENT}" + REPLACE_STR="$(echo "${PACKAGES[*]}" | tr -d '\n')" + + # Ensure packages are provided + if [[ ${#PACKAGES[@]} == 0 ]]; then + echo "Error: No packages were provided for repository '${REPO_NAME}'." + exit 1 + fi + + echo "Replacing packages from COPR repository: '${REPO_NAME}' owned by '${MAINTAINER}'" + echo "Replacing: ${REPLACE_STR}" + + REPO_URL="${REPO//[$'\t\r\n ']}" + + echo "Downloading repo file ${REPO_URL}" + curl -fLs --create-dirs -O "${REPO_URL}" --output-dir "/etc/yum.repos.d/" + echo "Downloaded repo file ${REPO_URL}" + + rpm-ostree override replace --experimental --from "repo=copr:copr.fedorainfracloud.org:${MAINTAINER}:${REPO_NAME}" ${REPLACE_STR} + rm "/etc/yum.repos.d/${FILE_NAME}" + + done +fi diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp new file mode 100644 index 0000000..c5e257b --- /dev/null +++ b/modules/dnf/dnf.tsp @@ -0,0 +1,33 @@ +import "@typespec/json-schema"; +using TypeSpec.JsonSchema; + +@jsonSchema("/modules/dnf.json") +model RpmOstreeModule { + /** The dnf module offers pseudo-declarative package and repository management using dnf. + * https://blue-build.org/reference/modules/dnf/ + */ + type: "dnf"; + + /** List of links to .repo files to download into /etc/yum.repos.d/. */ + repos?: Array; + + /** List of links to key files to import for installing from custom repositories. */ + keys?: Array; + + /** List of folder names under /opt/ to enable for installing into. */ + optfix?: Array; + + /** List of RPM packages to install. */ + install?: Array; + + /** List of RPM packages to remove. */ + remove?: Array; + + /** List of configurations for `rpm-ostree override replace`ing packages. */ + replace?: Array<{ + /** URL to the source COPR repo for the new packages. */ + "from-repo": string, + /** List of packages to replace using packages from the defined repo. */ + packages: Array, + }>; +} \ No newline at end of file diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml new file mode 100644 index 0000000..b32eae4 --- /dev/null +++ b/modules/dnf/module.yml @@ -0,0 +1,25 @@ +name: dnf +shortdesc: The dnf module offers pseudo-declarative package and repository management using dnf. +example: | + type: dnf + 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://brave-browser-rpm-release.s3.brave.com/brave-browser.repo + keys: + - https://brave-browser-rpm-release.s3.brave.com/brave-core.asc + optfix: + - Tabby # needed because tabby installs into /opt/Tabby + - brave.com + install: + - starship + - brave-browser + - https://github.com/Eugeny/tabby/releases/download/v1.0.209/tabby-1.0.209-linux-x64.rpm + remove: + - firefox + - firefox-langpacks + replace: + - from-repo: https://copr.fedorainfracloud.org/coprs/trixieua/mutter-patched/repo/fedora-%OS_VERSION%/trixieua-mutter-patched-fedora-%OS_VERSION%.repo + packages: + - mutter + - mutter-common + - gdm From cd91b057b0ed8bd9fc69cfda5c688372a7220d96 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 16:31:46 +0100 Subject: [PATCH 02/51] chore: Add support for native installation of repos --- modules/dnf/README.md | 3 +++ modules/dnf/dnf.sh | 55 +++++++++++++++++++++++++----------------- modules/dnf/module.yml | 2 +- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index 6ba70c1..ba3a999 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -9,6 +9,9 @@ You can also add repository files directly into your git repository if URLs are repos: - my-repository.repo # copies in .repo file from files/dnf/my-repository.repo to /etc/yum.repos.d/ ``` + +Specific COPR repositories can also be specified in `copr: user/project` format. + 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 `dnf install`, it removes the packages declared under `remove:` using `dnf remove`. If there are packages declared under both `install:` and `remove:` a hybrid command `dnf remove --install ` is used, which should allow you to switch required packages for other ones. diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 266814c..e9b0176 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -3,31 +3,42 @@ # Tell build process to exit if there are any errors. set -euo pipefail +# Fail the build if dnf5 isn't installed +if ! rpm -q dnf5 &>/dev/null; then + echo "ERROR: Main dependency 'dnf5' is not installed. Install 'dnf5' before using this module to solve this error." + exit 1 +fi + +# Fail the build if dnf5 plugins aren't installed +if ! rpm -q dnf5-plugins &>/dev/null; then + echo "ERROR: Dependency 'dnf5-plugins' is not installed. It is needed for cleanly adding COPR repositories. + echo " Install 'dnf5-plugins' before using this module to solve this error." + exit 1 +fi + # Pull in repos get_json_array REPOS 'try .["repos"][]' "$1" if [[ ${#REPOS[@]} -gt 0 ]]; then - echo "Adding repositories" - for REPO in "${REPOS[@]}"; do - REPO="${REPO//%OS_VERSION%/${OS_VERSION}}" - REPO="${REPO//[$'\t\r\n ']}" - - # If it's the COPR repo, then download the repo normally - # If it's not, then download the repo with URL in it's filename, to avoid duplicate repo name issue - if [[ "${REPO}" =~ ^https?:\/\/.* ]] && [[ "${REPO}" == "https://copr.fedorainfracloud.org/coprs/"* ]]; then - echo "Downloading repo file ${REPO}" - curl -fLs --create-dirs -O "${REPO}" --output-dir "/etc/yum.repos.d/" - echo "Downloaded repo file ${REPO}" - elif [[ "${REPO}" =~ ^https?:\/\/.* ]] && [[ "${REPO}" != "https://copr.fedorainfracloud.org/coprs/"* ]]; then - CLEAN_REPO_NAME=$(echo "${REPO}" | sed -E 's|^https?://([^?]+)(\?.*)?$|\1|') - CLEAN_REPO_NAME="${CLEAN_REPO_NAME//\//.}" - - echo "Downloading repo file ${REPO}" - curl -fLs --create-dirs "${REPO}" -o "/etc/yum.repos.d/${CLEAN_REPO_NAME}" - echo "Downloaded repo file ${REPO}" - elif [[ ! "${REPO}" =~ ^https?:\/\/.* ]] && [[ "${REPO}" == *".repo" ]] && [[ -f "${CONFIG_DIRECTORY}/rpm-ostree/${REPO}" ]]; then - cp "${CONFIG_DIRECTORY}/rpm-ostree/${REPO}" "/etc/yum.repos.d/${REPO##*/}" - fi - done + echo "Adding repositories" + # Substitute %OS_VERSION% & remove newlines/whitespaces from all repo entries + for i in "${!REPOS[@]}"; do + repo="${REPOS[$i]}" + repo="${repo//%OS_VERSION%/${OS_VERSION}}" + REPOS[$i]="${repo//[$'\t\r\n ']}" + done + # dnf config-manager & dnf copr don't support adding multiple repositories at once, hence why for/done loop is used + for repo in "${REPOS[@]}"; do + if [[ "${repo}" =~ ^https?:\/\/.* ]]; then + echo "Adding repository URL: '${repo}'" + dnf config-manager addrepo --from-repofile="${repo}" + elif [[ "${repo}" == *".repo" ]] && [[ -f "${CONFIG_DIRECTORY}/dnf/${repo}" ]]; then + echo "Adding repository file: '${repo}'" + dnf config-manager addrepo --from-repofile="${repo}" + elif [[ "${repo}" == "copr: "* ]]; then + echo "Adding COPR repository: '${repo#copr: }'" + dnf copr enable "${repo#copr: }" + fi + done fi get_json_array KEYS 'try .["keys"][]' "$1" diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index b32eae4..883b3cb 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -3,7 +3,7 @@ shortdesc: The dnf module offers pseudo-declarative package and repository manag example: | type: dnf 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 + - copr: atim/starship - https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo keys: - https://brave-browser-rpm-release.s3.brave.com/brave-core.asc From cf3d4959326de38ac3a099d3cb20b94720f5c0f9 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 16:33:54 +0100 Subject: [PATCH 03/51] docs: Revise the note about %OS_VERSION% in repos --- modules/dnf/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index ba3a999..acda3f9 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -2,7 +2,7 @@ The [`dnf`](https://docs.fedoraproject.org/en-US/quick-docs/dnf/) module offers pseudo-declarative package and repository management using `dnf`. -The module first downloads the repository files from URLs 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/). +The module first downloads the repository files from URLs declared under `repos:` into `/etc/yum.repos.d/`. The magic string `%OS_VERSION%` can be substituted with the current VERSION_ID (major Fedora version), which can be used, for example, for pulling correct versions of repositories which have fixed Fedora version in the URL. You can also add repository files directly into your git repository if URLs are not provided. For example: ```yml @@ -29,4 +29,4 @@ The module can also replace base RPM packages with packages from COPR repo. Unde [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 `dnf` module supports a fix for packages that install into `/opt/`. Installation for packages that install into folder names declared under `optfix:` are fixed using some symlinks. Directory path in `/opt/` for those packages should be provided in recipe, like in Example Configuration. \ No newline at end of file +Additionally, the `dnf` module supports a fix for packages that install into `/opt/`. Installation for packages that install into folder names declared under `optfix:` are fixed using some symlinks. Directory path in `/opt/` for those packages should be provided in recipe, like in Example Configuration. From 2f392e73b897fd6b3c1d76fada99f8cbb7b2a2c7 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 16:37:17 +0100 Subject: [PATCH 04/51] fix: missing quote in echo --- modules/dnf/dnf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index e9b0176..71566bf 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -11,7 +11,7 @@ fi # Fail the build if dnf5 plugins aren't installed if ! rpm -q dnf5-plugins &>/dev/null; then - echo "ERROR: Dependency 'dnf5-plugins' is not installed. It is needed for cleanly adding COPR repositories. + echo "ERROR: Dependency 'dnf5-plugins' is not installed. It is needed for cleanly adding COPR repositories." echo " Install 'dnf5-plugins' before using this module to solve this error." exit 1 fi From 6d1047f7ca37a6cb0f238510b384831f0dbc8ae6 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 17:57:58 +0100 Subject: [PATCH 05/51] fix: Get raw COPR repos array elements without JSON brackets --- modules/dnf/dnf.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 71566bf..49edf90 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -24,8 +24,13 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then for i in "${!REPOS[@]}"; do repo="${REPOS[$i]}" repo="${repo//%OS_VERSION%/${OS_VERSION}}" - REPOS[$i]="${repo//[$'\t\r\n ']}" - done + # Extract copr repo array element properly here without JSON brackets (jq doesn't extract elements with spaces properly like yq does) + if [[ "${repo}" == "{\"copr\":\""*"\"}" ]]; then + REPOS[$i]="$(echo "copr: $(echo "${repo}" | jq -r '.copr')")" + else + # Trim all whitespaces/newlines for other repos + REPOS[$i]="${repo//[$'\t\r\n ']}" + fi done # dnf config-manager & dnf copr don't support adding multiple repositories at once, hence why for/done loop is used for repo in "${REPOS[@]}"; do if [[ "${repo}" =~ ^https?:\/\/.* ]]; then From 9d13c87ea3178908848d118838497c9aa40dc1eb Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 18:08:14 +0100 Subject: [PATCH 06/51] chore: Auto-confirm prompts (`-y`) when adding repos --- modules/dnf/dnf.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 49edf90..2603313 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -35,13 +35,13 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then for repo in "${REPOS[@]}"; do if [[ "${repo}" =~ ^https?:\/\/.* ]]; then echo "Adding repository URL: '${repo}'" - dnf config-manager addrepo --from-repofile="${repo}" + dnf -y config-manager addrepo --from-repofile="${repo}" elif [[ "${repo}" == *".repo" ]] && [[ -f "${CONFIG_DIRECTORY}/dnf/${repo}" ]]; then echo "Adding repository file: '${repo}'" - dnf config-manager addrepo --from-repofile="${repo}" + dnf -y config-manager addrepo --from-repofile="${repo}" elif [[ "${repo}" == "copr: "* ]]; then echo "Adding COPR repository: '${repo#copr: }'" - dnf copr enable "${repo#copr: }" + dnf -y copr enable "${repo#copr: }" fi done fi From 1396a18099e9684793022dbbf64cd25b8d853ad3 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 18:10:00 +0100 Subject: [PATCH 07/51] fix: Accidental syntax error for `done` --- modules/dnf/dnf.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 2603313..91699f6 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -30,7 +30,8 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then else # Trim all whitespaces/newlines for other repos REPOS[$i]="${repo//[$'\t\r\n ']}" - fi done + fi + done # dnf config-manager & dnf copr don't support adding multiple repositories at once, hence why for/done loop is used for repo in "${REPOS[@]}"; do if [[ "${repo}" =~ ^https?:\/\/.* ]]; then From b898af29af37c3536204ddd4c480b0bd1e008bb9 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 18:15:23 +0100 Subject: [PATCH 08/51] chore: Remove useless echo --- modules/dnf/dnf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 91699f6..4687416 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -26,7 +26,7 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then repo="${repo//%OS_VERSION%/${OS_VERSION}}" # Extract copr repo array element properly here without JSON brackets (jq doesn't extract elements with spaces properly like yq does) if [[ "${repo}" == "{\"copr\":\""*"\"}" ]]; then - REPOS[$i]="$(echo "copr: $(echo "${repo}" | jq -r '.copr')")" + REPOS[$i]="copr: $(echo "${repo}" | jq -r '.copr')" else # Trim all whitespaces/newlines for other repos REPOS[$i]="${repo//[$'\t\r\n ']}" From 652397936a744f3d7909f4c50937af7c5559f871 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 18:42:09 +0100 Subject: [PATCH 09/51] chore: Install & remove using `dnf` in single operation cases --- modules/dnf/dnf.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 4687416..52ed7f6 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -17,7 +17,7 @@ if ! rpm -q dnf5-plugins &>/dev/null; then fi # Pull in repos -get_json_array REPOS 'try .["repos"][]' "$1" +get_json_array REPOS 'try .["repos"][]' "${1}" if [[ ${#REPOS[@]} -gt 0 ]]; then echo "Adding repositories" # Substitute %OS_VERSION% & remove newlines/whitespaces from all repo entries @@ -47,7 +47,7 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then done fi -get_json_array KEYS 'try .["keys"][]' "$1" +get_json_array KEYS 'try .["keys"][]' "${1}" if [[ ${#KEYS[@]} -gt 0 ]]; then echo "Adding keys" for KEY in "${KEYS[@]}"; do @@ -57,7 +57,7 @@ if [[ ${#KEYS[@]} -gt 0 ]]; then fi # Create symlinks to fix packages that create directories in /opt -get_json_array OPTFIX 'try .["optfix"][]' "$1" +get_json_array OPTFIX 'try .["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 @@ -73,8 +73,8 @@ if [[ ${#OPTFIX[@]} -gt 0 ]]; then done fi -get_json_array INSTALL_PKGS 'try .["install"][]' "$1" -get_json_array REMOVE_PKGS 'try .["remove"][]' "$1" +get_json_array INSTALL_PKGS 'try .["install"][]' "${1}" +get_json_array REMOVE_PKGS 'try .["remove"][]' "${1}" CLASSIC_INSTALL=false HTTPS_INSTALL=false @@ -152,11 +152,11 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" echo_rpm_install - rpm-ostree install "${INSTALL_PKGS[@]}" + dnf -y install "${INSTALL_PKGS[@]}" elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" - rpm-ostree override remove "${REMOVE_PKGS[@]}" + dnf -y remove "${REMOVE_PKGS[@]}" fi get_json_array REPLACE 'try .["replace"][]' "$1" From 97566b81e2331b0bf2a693560f9657bb91cb06e4 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 19:57:50 +0100 Subject: [PATCH 10/51] docs: Add note that URL is not preferred for copr repos --- modules/dnf/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index acda3f9..321a580 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -10,7 +10,7 @@ repos: - my-repository.repo # copies in .repo file from files/dnf/my-repository.repo to /etc/yum.repos.d/ ``` -Specific COPR repositories can also be specified in `copr: user/project` format. +Specific COPR repositories can also be specified in `copr: user/project` format & is prefered over using direct COPR URL. 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`. From 0bb79d0d0e087afd5fa48ed354114ed4c44f14b3 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 20:18:00 +0100 Subject: [PATCH 11/51] fix: `/opt` symlink issue & migrate removal + install to `dnf` --- modules/dnf/dnf.sh | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 52ed7f6..0c80c11 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -62,7 +62,7 @@ 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" + ln -snf "/var/opt" "/opt" # Create symlinks for each directory specified in recipe.yml for OPTPKG in "${OPTFIX[@]}"; do OPTPKG="${OPTPKG%\"}" @@ -124,31 +124,10 @@ echo_rpm_install() { if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Installing & Removing RPMs" - echo_rpm_install echo "Removing: ${REMOVE_PKGS[*]}" - # Doing both actions in one command allows for replacing required packages with alternatives - # When --install= flag is used, URLs & local packages are not supported - if ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then - rpm-ostree override remove "${REMOVE_PKGS[@]}" $(printf -- "--install=%s " "${CLASSIC_PKGS[@]}") - elif ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then - rpm-ostree override remove "${REMOVE_PKGS[@]}" $(printf -- "--install=%s " "${CLASSIC_PKGS[@]}") - rpm-ostree install "${HTTPS_PKGS[@]}" - elif ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then - rpm-ostree override remove "${REMOVE_PKGS[@]}" $(printf -- "--install=%s " "${CLASSIC_PKGS[@]}") - rpm-ostree install "${LOCAL_PKGS[@]}" - elif ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then - rpm-ostree override remove "${REMOVE_PKGS[@]}" $(printf -- "--install=%s " "${CLASSIC_PKGS[@]}") - rpm-ostree install "${HTTPS_PKGS[@]}" "${LOCAL_PKGS[@]}" - elif ! ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then - rpm-ostree override remove "${REMOVE_PKGS[@]}" - rpm-ostree install "${LOCAL_PKGS[@]}" - elif ! ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then - rpm-ostree override remove "${REMOVE_PKGS[@]}" - rpm-ostree install "${HTTPS_PKGS[@]}" - elif ! ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then - rpm-ostree override remove "${REMOVE_PKGS[@]}" - rpm-ostree install "${HTTPS_PKGS[@]}" "${LOCAL_PKGS[@]}" - fi + echo_rpm_install + dnf -y remove "${REMOVE_PKGS[@]}" + dnf -y install "${INSTALL_PKGS[@]}" elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" echo_rpm_install From 70c5766c3249a90a884c0fbdcc15c71b6d4e096d Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 20:24:26 +0100 Subject: [PATCH 12/51] chore: Document code some more --- modules/dnf/dnf.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 0c80c11..48bd631 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -62,7 +62,7 @@ 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 -snf "/var/opt" "/opt" + ln -snf "/var/opt" "/opt" # Create symlinks for each directory specified in recipe.yml for OPTPKG in "${OPTFIX[@]}"; do OPTPKG="${OPTPKG%\"}" @@ -80,8 +80,7 @@ CLASSIC_INSTALL=false HTTPS_INSTALL=false LOCAL_INSTALL=false -# Install and remove RPM packages -# Sort classic, URL & local packages +# Sort classic, URL & local install packages if [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then for i in "${!INSTALL_PKGS[@]}"; do PKG="${INSTALL_PKGS[$i]}" @@ -99,6 +98,7 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then done fi +# Function to inform the user about which type of packages is he installing echo_rpm_install() { if ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then echo "Installing: ${CLASSIC_PKGS[*]}" @@ -122,8 +122,9 @@ echo_rpm_install() { fi } +# Remove & install RPM packages if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then - echo "Installing & Removing RPMs" + echo "Removing & Installing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" echo_rpm_install dnf -y remove "${REMOVE_PKGS[@]}" From e01ed4065156e679c8ec1f97cdbfc29db430df33 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 20:26:36 +0100 Subject: [PATCH 13/51] docs: Fix note about using install & remove at the same time --- modules/dnf/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index 321a580..b221095 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -14,7 +14,7 @@ Specific COPR repositories can also be specified in `copr: user/project` format 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 `dnf install`, it removes the packages declared under `remove:` using `dnf remove`. If there are packages declared under both `install:` and `remove:` a hybrid command `dnf remove --install ` is used, which should allow you to switch required packages for other ones. +Then the module installs the packages declared under `install:` using `dnf install`, it removes the packages declared under `remove:` using `dnf remove`. If there are packages declared under both `install:` and `remove:` then removal is performed 1st & install 2nd. 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. From 7d4aff918baf6a69622aa689912149d35f6c823c Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 20:34:37 +0100 Subject: [PATCH 14/51] chore: Add `dnf` to `modules.json` --- modules.json | 1 + 1 file changed, 1 insertion(+) diff --git a/modules.json b/modules.json index 66afaa8..b597ad2 100644 --- a/modules.json +++ b/modules.json @@ -10,6 +10,7 @@ "https://raw.githubusercontent.com/blue-build/modules/main/modules/gschema-overrides/module.yml", "https://raw.githubusercontent.com/blue-build/modules/main/modules/justfiles/module.yml", "https://raw.githubusercontent.com/blue-build/modules/main/modules/rpm-ostree/module.yml", + "https://raw.githubusercontent.com/blue-build/modules/main/modules/dnf/module.yml", "https://raw.githubusercontent.com/blue-build/modules/main/modules/initramfs/module.yml", "https://raw.githubusercontent.com/blue-build/modules/main/modules/script/module.yml", "https://raw.githubusercontent.com/blue-build/modules/main/modules/signing/module.yml", From a4e9ba435f89df9487a66b706eaf572d1321d604 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 21:08:49 +0100 Subject: [PATCH 15/51] chore: Add support for replacing packages --- modules/dnf/README.md | 4 ++-- modules/dnf/dnf.sh | 25 +++++++------------------ modules/dnf/module.yml | 2 +- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index b221095..dff1f8b 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -14,7 +14,7 @@ Specific COPR repositories can also be specified in `copr: user/project` format 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 `dnf install`, it removes the packages declared under `remove:` using `dnf remove`. If there are packages declared under both `install:` and `remove:` then removal is performed 1st & install 2nd. +Then the module installs the packages declared under `install:` using `dnf -y install`, it removes the packages declared under `remove:` using `dnf -y remove`. If there are packages declared under both `install:` and `remove:` then removal is performed 1st & install 2nd. 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. @@ -23,7 +23,7 @@ If an RPM is not available in a repository or as an URL, you can also install it install: - weird-package.rpm # tries to install files/dnf/weird-package.rpm ``` -The module can also replace base RPM packages with packages from COPR repo. Under `replace:`, the module finds every pair of keys `- from-repo:` and `packages:`. (Multiple pairs are supported.) The module downloads the COPR repository file declared by `- from-repo:` into `/etc/yum.repos.d/`, and from that repository replaces packages declared under `packages:` using the command `dnf replace`. The COPR repository file is then deleted. The magic string `%OS_VERSION%` is substituted with the current VERSION_ID (major Fedora version) as already said above. At the moment, only COPR repo is supported. +The module can also replace base RPM packages with packages from any repo. Under `replace:`, the module finds every pair of keys `- from-repo:` and `packages:`. (Multiple pairs are supported.) The module uses `- from-repo:` key to gather the repo for package replacement, then it replaces packages declared under `packages:` using the command `dnf -y distro-sync --refresh --repo "${repo}" "${packages}"`. The magic string `%OS_VERSION%` is substituted with the current VERSION_ID (major Fedora version) as already said above. You need to assure that you provided the repo in `repos:` before using replacement functionality. To gather the repo ID that you need to input, you can use `dnf repo list` command. :::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. diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 48bd631..1a9506d 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -47,6 +47,7 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then done fi +# Install RPM keys if they are provided get_json_array KEYS 'try .["keys"][]' "${1}" if [[ ${#KEYS[@]} -gt 0 ]]; then echo "Adding keys" @@ -141,13 +142,14 @@ fi get_json_array REPLACE 'try .["replace"][]' "$1" -# Override-replace RPM packages +# Replace RPM packages from any repository if [[ ${#REPLACE[@]} -gt 0 ]]; then for REPLACEMENT in "${REPLACE[@]}"; do # Get repository REPO=$(echo "${REPLACEMENT}" | jq -r 'try .["from-repo"]') REPO="${REPO//%OS_VERSION%/${OS_VERSION}}" + REPO="${REPO//[$'\t\r\n ']}" # Ensure repository is provided if [[ "${REPO}" == "null" ]]; then @@ -155,32 +157,19 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then exit 1 fi - # Get info from repository URL - MAINTAINER=$(awk -F'/' '{print $5}' <<< "${REPO}") - REPO_NAME=$(awk -F'/' '{print $6}' <<< "${REPO}") - FILE_NAME=$(awk -F'/' '{print $9}' <<< "${REPO}" | sed 's/\?.*//') # Remove params after '?' - # Get packages to replace get_json_array PACKAGES 'try .["packages"][]' "${REPLACEMENT}" - REPLACE_STR="$(echo "${PACKAGES[*]}" | tr -d '\n')" # Ensure packages are provided if [[ ${#PACKAGES[@]} == 0 ]]; then - echo "Error: No packages were provided for repository '${REPO_NAME}'." + echo "Error: No packages were provided for repository '${REPO}'." exit 1 fi - echo "Replacing packages from COPR repository: '${REPO_NAME}' owned by '${MAINTAINER}'" + echo "Replacing packages from repository: '${REPO}'" echo "Replacing: ${REPLACE_STR}" - REPO_URL="${REPO//[$'\t\r\n ']}" - - echo "Downloading repo file ${REPO_URL}" - curl -fLs --create-dirs -O "${REPO_URL}" --output-dir "/etc/yum.repos.d/" - echo "Downloaded repo file ${REPO_URL}" - - rpm-ostree override replace --experimental --from "repo=copr:copr.fedorainfracloud.org:${MAINTAINER}:${REPO_NAME}" ${REPLACE_STR} - rm "/etc/yum.repos.d/${FILE_NAME}" + dnf -y distro-sync --refresh --repo "${REPO}" "${PACKEGES[@]}" done -fi +fi \ No newline at end of file diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index 883b3cb..c27ab03 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -18,7 +18,7 @@ example: | - firefox - firefox-langpacks replace: - - from-repo: https://copr.fedorainfracloud.org/coprs/trixieua/mutter-patched/repo/fedora-%OS_VERSION%/trixieua-mutter-patched-fedora-%OS_VERSION%.repo + - from-repo: copr:copr.fedorainfracloud.org:trixieua:mutter-patched packages: - mutter - mutter-common From 7da24f52d3176a66015aab5e0185453cfb69cdbc Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 21:41:35 +0100 Subject: [PATCH 16/51] chore: Add option to enable or disable installation of weak dependencies --- modules/dnf/README.md | 5 ++++- modules/dnf/dnf.sh | 19 ++++++++++++++----- modules/dnf/dnf.tsp | 3 +++ modules/dnf/module.yml | 1 + 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index dff1f8b..f738171 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -23,10 +23,13 @@ If an RPM is not available in a repository or as an URL, you can also install it install: - weird-package.rpm # tries to install files/dnf/weird-package.rpm ``` + +Additionally, the `dnf` module supports a fix for packages that install into `/opt/`. Installation for packages that install into folder names declared under `optfix:` are fixed using some symlinks. Directory path in `/opt/` for those packages should be provided in recipe, like in Example Configuration. + The module can also replace base RPM packages with packages from any repo. Under `replace:`, the module finds every pair of keys `- from-repo:` and `packages:`. (Multiple pairs are supported.) The module uses `- from-repo:` key to gather the repo for package replacement, then it replaces packages declared under `packages:` using the command `dnf -y distro-sync --refresh --repo "${repo}" "${packages}"`. The magic string `%OS_VERSION%` is substituted with the current VERSION_ID (major Fedora version) as already said above. You need to assure that you provided the repo in `repos:` before using replacement functionality. To gather the repo ID that you need to input, you can use `dnf repo list` command. :::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 `dnf` module supports a fix for packages that install into `/opt/`. Installation for packages that install into folder names declared under `optfix:` are fixed using some symlinks. Directory path in `/opt/` for those packages should be provided in recipe, like in Example Configuration. +There is also a 'weak-dependencies:' option to enable or disable installation of weak dependencies for every install operation. Weak dependencies are installed by default. Which kind of dependencies are considered weak can be seen [here](https://docs.fedoraproject.org/en-US/packaging-guidelines/WeakDependencies/). \ No newline at end of file diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 1a9506d..ac127b7 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -16,6 +16,15 @@ if ! rpm -q dnf5-plugins &>/dev/null; then exit 1 fi +# Check if option for weak dependencies is enabled or disabled +WEAK_DEPENDENCIES=$(echo "${1}" | jq -r 'try .["weak-dependencies"]') + +if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then + WEAK_DEPS_FLAG="--setopt=install_weak_deps=True" +elif [[ "${WEAK_DEPENDENCIES}" == false ]]; then + WEAK_DEPS_FLAG="--setopt=install_weak_deps=False" +fi + # Pull in repos get_json_array REPOS 'try .["repos"][]' "${1}" if [[ ${#REPOS[@]} -gt 0 ]]; then @@ -128,16 +137,16 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing & Installing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" echo_rpm_install - dnf -y remove "${REMOVE_PKGS[@]}" - dnf -y install "${INSTALL_PKGS[@]}" + dnf -y "${WEAK_DEPS_FLAG}" remove "${REMOVE_PKGS[@]}" + dnf -y "${WEAK_DEPS_FLAG}" install "${INSTALL_PKGS[@]}" elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" echo_rpm_install - dnf -y install "${INSTALL_PKGS[@]}" + dnf -y "${WEAK_DEPS_FLAG}" install "${INSTALL_PKGS[@]}" elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" - dnf -y remove "${REMOVE_PKGS[@]}" + dnf -y "${WEAK_DEPS_FLAG}" remove "${REMOVE_PKGS[@]}" fi get_json_array REPLACE 'try .["replace"][]' "$1" @@ -169,7 +178,7 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then echo "Replacing packages from repository: '${REPO}'" echo "Replacing: ${REPLACE_STR}" - dnf -y distro-sync --refresh --repo "${REPO}" "${PACKEGES[@]}" + dnf -y "${WEAK_DEPS_FLAG}" distro-sync --refresh --repo "${REPO}" "${PACKEGES[@]}" done fi \ No newline at end of file diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index c5e257b..25b3494 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -30,4 +30,7 @@ model RpmOstreeModule { /** List of packages to replace using packages from the defined repo. */ packages: Array, }>; + + /** Whether to install weak dependencies during install operation or not. */ + "weak-dependencies"?: boolean = true; } \ No newline at end of file diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index c27ab03..f9b43e0 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -2,6 +2,7 @@ name: dnf shortdesc: The dnf module offers pseudo-declarative package and repository management using dnf. example: | type: dnf + weak-dependencies: true repos: - copr: atim/starship - https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo From d495b6a576d1c211fa721ab41071096c41ce3711 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 21:47:34 +0100 Subject: [PATCH 17/51] docs: Style backtick fix --- modules/dnf/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index f738171..c0f833c 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -32,4 +32,4 @@ The module can also replace base RPM packages with packages from any repo. Under [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. ::: -There is also a 'weak-dependencies:' option to enable or disable installation of weak dependencies for every install operation. Weak dependencies are installed by default. Which kind of dependencies are considered weak can be seen [here](https://docs.fedoraproject.org/en-US/packaging-guidelines/WeakDependencies/). \ No newline at end of file +There is also a `weak-dependencies:` option to enable or disable installation of weak dependencies for every install operation. Weak dependencies are installed by default. Which kind of dependencies are considered weak can be seen [here](https://docs.fedoraproject.org/en-US/packaging-guidelines/WeakDependencies/). From 1137c8b670853a3504f4460011800f0b49f889f0 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 22:03:57 +0100 Subject: [PATCH 18/51] fix(rpm-ostree): Symlinking `/opt/` multiple times caused an error --- modules/rpm-ostree/rpm-ostree.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rpm-ostree/rpm-ostree.sh b/modules/rpm-ostree/rpm-ostree.sh index 266814c..87318b7 100644 --- a/modules/rpm-ostree/rpm-ostree.sh +++ b/modules/rpm-ostree/rpm-ostree.sh @@ -45,7 +45,7 @@ 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" + ln -snf "/var/opt" "/opt" # Create symlinks for each directory specified in recipe.yml for OPTPKG in "${OPTFIX[@]}"; do OPTPKG="${OPTPKG%\"}" From eb522e37980f0e5c94f3ce81e4a12b1f7c7e9c44 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 22:12:02 +0100 Subject: [PATCH 19/51] chore: Rename `weak-dependencies` to `install-weak-dependencies` & add `--refresh` for install operation --- modules/dnf/README.md | 2 +- modules/dnf/dnf.sh | 6 +++--- modules/dnf/dnf.tsp | 2 +- modules/dnf/module.yml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index c0f833c..77941e2 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -14,7 +14,7 @@ Specific COPR repositories can also be specified in `copr: user/project` format 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 `dnf -y install`, it removes the packages declared under `remove:` using `dnf -y remove`. If there are packages declared under both `install:` and `remove:` then removal is performed 1st & install 2nd. +Then the module installs the packages declared under `install:` using `dnf -y install --refresh`, it removes the packages declared under `remove:` using `dnf -y remove`. If there are packages declared under both `install:` and `remove:` then removal is performed 1st & install 2nd. 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. diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index ac127b7..dac0ca9 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -17,7 +17,7 @@ if ! rpm -q dnf5-plugins &>/dev/null; then fi # Check if option for weak dependencies is enabled or disabled -WEAK_DEPENDENCIES=$(echo "${1}" | jq -r 'try .["weak-dependencies"]') +WEAK_DEPENDENCIES=$(echo "${1}" | jq -r 'try .["install-weak-dependencies"]') if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then WEAK_DEPS_FLAG="--setopt=install_weak_deps=True" @@ -138,11 +138,11 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing: ${REMOVE_PKGS[*]}" echo_rpm_install dnf -y "${WEAK_DEPS_FLAG}" remove "${REMOVE_PKGS[@]}" - dnf -y "${WEAK_DEPS_FLAG}" install "${INSTALL_PKGS[@]}" + dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${INSTALL_PKGS[@]}" elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" echo_rpm_install - dnf -y "${WEAK_DEPS_FLAG}" install "${INSTALL_PKGS[@]}" + dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${INSTALL_PKGS[@]}" elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index 25b3494..bba46e7 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -32,5 +32,5 @@ model RpmOstreeModule { }>; /** Whether to install weak dependencies during install operation or not. */ - "weak-dependencies"?: boolean = true; + "install-weak-dependencies"?: boolean = true; } \ No newline at end of file diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index f9b43e0..6fc2c62 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -2,14 +2,14 @@ name: dnf shortdesc: The dnf module offers pseudo-declarative package and repository management using dnf. example: | type: dnf - weak-dependencies: true + install-weak-dependencies: true repos: - copr: atim/starship - https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo keys: - https://brave-browser-rpm-release.s3.brave.com/brave-core.asc optfix: - - Tabby # needed because tabby installs into /opt/Tabby + - Tabby # needed because tabby installs into /opt/Tabby/ - brave.com install: - starship From 57f8b228648b4139e1fc1d6bc3b87f377fa307c0 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 22:19:50 +0100 Subject: [PATCH 20/51] chore: Change `copr: user/project` formt to `COPR user/project` --- modules/dnf/README.md | 2 +- modules/dnf/dnf.sh | 13 ++++--------- modules/dnf/module.yml | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index 77941e2..e0f22c3 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -10,7 +10,7 @@ repos: - my-repository.repo # copies in .repo file from files/dnf/my-repository.repo to /etc/yum.repos.d/ ``` -Specific COPR repositories can also be specified in `copr: user/project` format & is prefered over using direct COPR URL. +Specific COPR repositories can also be specified in `COPR user/project` format & is prefered over using direct COPR URL. 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`. diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index dac0ca9..2dd51b5 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -33,12 +33,7 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then for i in "${!REPOS[@]}"; do repo="${REPOS[$i]}" repo="${repo//%OS_VERSION%/${OS_VERSION}}" - # Extract copr repo array element properly here without JSON brackets (jq doesn't extract elements with spaces properly like yq does) - if [[ "${repo}" == "{\"copr\":\""*"\"}" ]]; then - REPOS[$i]="copr: $(echo "${repo}" | jq -r '.copr')" - else - # Trim all whitespaces/newlines for other repos - REPOS[$i]="${repo//[$'\t\r\n ']}" + REPOS[$i]="${repo//[$'\t\r\n ']}" fi done # dnf config-manager & dnf copr don't support adding multiple repositories at once, hence why for/done loop is used @@ -49,9 +44,9 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then elif [[ "${repo}" == *".repo" ]] && [[ -f "${CONFIG_DIRECTORY}/dnf/${repo}" ]]; then echo "Adding repository file: '${repo}'" dnf -y config-manager addrepo --from-repofile="${repo}" - elif [[ "${repo}" == "copr: "* ]]; then - echo "Adding COPR repository: '${repo#copr: }'" - dnf -y copr enable "${repo#copr: }" + elif [[ "${repo}" == "COPR "* ]]; then + echo "Adding COPR repository: '${repo#COPR }'" + dnf -y copr enable "${repo#COPR }" fi done fi diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index 6fc2c62..3e486e6 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -4,7 +4,7 @@ example: | type: dnf install-weak-dependencies: true repos: - - copr: atim/starship + - COPR atim/starship - https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo keys: - https://brave-browser-rpm-release.s3.brave.com/brave-core.asc From 7a5bceafd1c3bc7e4f85b93b4f4709ea62f9034f Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 22:26:07 +0100 Subject: [PATCH 21/51] fix: Syntax error due to redundant `fi` --- modules/dnf/dnf.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 2dd51b5..c5476fb 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -34,7 +34,6 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then repo="${REPOS[$i]}" repo="${repo//%OS_VERSION%/${OS_VERSION}}" REPOS[$i]="${repo//[$'\t\r\n ']}" - fi done # dnf config-manager & dnf copr don't support adding multiple repositories at once, hence why for/done loop is used for repo in "${REPOS[@]}"; do @@ -176,4 +175,4 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then dnf -y "${WEAK_DEPS_FLAG}" distro-sync --refresh --repo "${REPO}" "${PACKEGES[@]}" done -fi \ No newline at end of file +fi From c7ae4301ad8440493a9e357e10a18a243435fb0c Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 22:36:34 +0100 Subject: [PATCH 22/51] fix: Restore logic about not removing any newlines to COPR repos --- modules/dnf/dnf.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index c5476fb..bbb2086 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -34,6 +34,12 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then repo="${REPOS[$i]}" repo="${repo//%OS_VERSION%/${OS_VERSION}}" REPOS[$i]="${repo//[$'\t\r\n ']}" + # Remove spaces/newlines for all repos other than COPR + if [[ "${repo}" != "COPR "* ]]; then + REPOS[$i]="${repo//[$'\t\r\n ']}" + else + REPOS[$i]="${repo}" + fi done # dnf config-manager & dnf copr don't support adding multiple repositories at once, hence why for/done loop is used for repo in "${REPOS[@]}"; do From b1a7c6ff63209934fd21eda9a9e1f990b6ec930f Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:08:44 +0100 Subject: [PATCH 23/51] feat: Add removal & installation of RPM groups --- modules/dnf/README.md | 4 +++- modules/dnf/dnf.sh | 24 ++++++++++++++++++++++-- modules/dnf/dnf.tsp | 6 ++++++ modules/dnf/module.yml | 4 ++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index e0f22c3..4e1eede 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -26,10 +26,12 @@ install: Additionally, the `dnf` module supports a fix for packages that install into `/opt/`. Installation for packages that install into folder names declared under `optfix:` are fixed using some symlinks. Directory path in `/opt/` for those packages should be provided in recipe, like in Example Configuration. +There is an option to install & remove RPM groups if desired in `group-install:` & `group-remove:`. RPM groups removal & installation always run before packages removal & installation. To see the list of all available RPM groups, you can use `dnf group list` command. + The module can also replace base RPM packages with packages from any repo. Under `replace:`, the module finds every pair of keys `- from-repo:` and `packages:`. (Multiple pairs are supported.) The module uses `- from-repo:` key to gather the repo for package replacement, then it replaces packages declared under `packages:` using the command `dnf -y distro-sync --refresh --repo "${repo}" "${packages}"`. The magic string `%OS_VERSION%` is substituted with the current VERSION_ID (major Fedora version) as already said above. You need to assure that you provided the repo in `repos:` before using replacement functionality. To gather the repo ID that you need to input, you can use `dnf repo list` command. :::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. ::: -There is also a `weak-dependencies:` option to enable or disable installation of weak dependencies for every install operation. Weak dependencies are installed by default. Which kind of dependencies are considered weak can be seen [here](https://docs.fedoraproject.org/en-US/packaging-guidelines/WeakDependencies/). +There is also an `install-weak-dependencies:` option to enable or disable installation of weak dependencies for every install operation. Weak dependencies are installed by default. Which kind of dependencies are considered weak can be seen [here](https://docs.fedoraproject.org/en-US/packaging-guidelines/WeakDependencies/). diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index bbb2086..5a16da1 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -83,6 +83,26 @@ if [[ ${#OPTFIX[@]} -gt 0 ]]; then done fi +# Install & remove group packages +get_json_array GROUP_INSTALL 'try .["group-install"][]' "${1}" +get_json_array GROUP_REMOVE 'try .["group-remove"][]' "${1}" + +if [[ ${#GROUP_INSTALL[@]} -gt 0 && ${#GROUP_REMOVE[@]} -gt 0 ]]; then + echo "Removing & Installing RPM groups" + echo "Removing: ${GROUP_REMOVE[*]}" + echo "Installing: ${GROUP_INSTALL[*]}" + dnf -y group remove "${GROUP_REMOVE[@]}" + dnf -y "${WEAK_DEPS_FLAG}" group install --refresh "${GROUP_INSTALL[@]}" +elif [[ ${#GROUP_INSTALL[@]} -gt 0 ]]; then + echo "Installing RPM groups" + echo "Installing: ${GROUP_INSTALL[*]}" + dnf -y "${WEAK_DEPS_FLAG}" group install --refresh "${GROUP_INSTALL[@]}" +elif [[ ${#GROUP_REMOVE[@]} -gt 0 ]]; then + echo "Removing RPM groups" + echo "Removing: ${GROUP_REMOVE[*]}" + dnf -y remove "${GROUP_REMOVE[@]}" +fi + get_json_array INSTALL_PKGS 'try .["install"][]' "${1}" get_json_array REMOVE_PKGS 'try .["remove"][]' "${1}" @@ -137,7 +157,7 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing & Installing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" echo_rpm_install - dnf -y "${WEAK_DEPS_FLAG}" remove "${REMOVE_PKGS[@]}" + dnf -y remove "${REMOVE_PKGS[@]}" dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${INSTALL_PKGS[@]}" elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" @@ -146,7 +166,7 @@ elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" - dnf -y "${WEAK_DEPS_FLAG}" remove "${REMOVE_PKGS[@]}" + dnf -y remove "${REMOVE_PKGS[@]}" fi get_json_array REPLACE 'try .["replace"][]' "$1" diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index bba46e7..33c0ded 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -23,6 +23,12 @@ model RpmOstreeModule { /** List of RPM packages to remove. */ remove?: Array; + /** List of RPM groups to install. */ + "group-install"?: Array; + + /** List of RPM groups to remove. */ + "group-remove"?: Array; + /** List of configurations for `rpm-ostree override replace`ing packages. */ replace?: Array<{ /** URL to the source COPR repo for the new packages. */ diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index 3e486e6..1e126a4 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -11,6 +11,10 @@ example: | optfix: - Tabby # needed because tabby installs into /opt/Tabby/ - brave.com + group-install: + - cosmic-desktop + - cosmic-desktop-apps # Install Cosmic desktop environment + - window-managers install: - starship - brave-browser From b7c0206fc18bbb26eb5ce82f2325f16792abfdd9 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:29:04 +0100 Subject: [PATCH 24/51] docs: Style fix --- modules/dnf/module.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index 1e126a4..08e7d23 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -13,7 +13,7 @@ example: | - brave.com group-install: - cosmic-desktop - - cosmic-desktop-apps # Install Cosmic desktop environment + - cosmic-desktop-apps # Installs Cosmic desktop environment - window-managers install: - starship From feb0d71afd791e2a26e3051f7ee79bd56970a4e5 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:31:55 +0100 Subject: [PATCH 25/51] chore: Make sorting order in typespec better --- modules/dnf/dnf.tsp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index 33c0ded..1ed7ced 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -8,6 +8,9 @@ model RpmOstreeModule { */ type: "dnf"; + /** Whether to install weak dependencies during install operation or not. */ + "install-weak-dependencies"?: boolean = true; + /** List of links to .repo files to download into /etc/yum.repos.d/. */ repos?: Array; @@ -17,17 +20,17 @@ model RpmOstreeModule { /** List of folder names under /opt/ to enable for installing into. */ optfix?: Array; - /** List of RPM packages to install. */ - install?: Array; - - /** List of RPM packages to remove. */ - remove?: Array; + /** List of RPM groups to remove. */ + "group-remove"?: Array; /** List of RPM groups to install. */ "group-install"?: Array; - /** List of RPM groups to remove. */ - "group-remove"?: Array; + /** List of RPM packages to remove. */ + remove?: Array; + + /** List of RPM packages to install. */ + install?: Array; /** List of configurations for `rpm-ostree override replace`ing packages. */ replace?: Array<{ @@ -36,7 +39,4 @@ model RpmOstreeModule { /** List of packages to replace using packages from the defined repo. */ packages: Array, }>; - - /** Whether to install weak dependencies during install operation or not. */ - "install-weak-dependencies"?: boolean = true; -} \ No newline at end of file +} From fba38408681876d87cd924f6de34d308b04d3725 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:32:40 +0100 Subject: [PATCH 26/51] typespec: Minor leftover fix --- modules/dnf/dnf.tsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index 1ed7ced..d9a014d 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -2,7 +2,7 @@ import "@typespec/json-schema"; using TypeSpec.JsonSchema; @jsonSchema("/modules/dnf.json") -model RpmOstreeModule { +model DnfModule { /** The dnf module offers pseudo-declarative package and repository management using dnf. * https://blue-build.org/reference/modules/dnf/ */ From e27ba39bf852711727e14e7ab5cc3eb0c8f2ad97 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:41:57 +0100 Subject: [PATCH 27/51] chore: Fix typespec replace definition --- modules/dnf/dnf.tsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index d9a014d..0db3e07 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -32,7 +32,7 @@ model DnfModule { /** List of RPM packages to install. */ install?: Array; - /** List of configurations for `rpm-ostree override replace`ing packages. */ + /** List of configurations for replacing packages from another repo. */ replace?: Array<{ /** URL to the source COPR repo for the new packages. */ "from-repo": string, From a53dd5bafcdabd43263673ba2b7c31b4c01ea55a Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:42:46 +0100 Subject: [PATCH 28/51] chore: Add mutter-patched COPR to module.yml --- modules/dnf/module.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index 08e7d23..b631fea 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -5,6 +5,7 @@ example: | install-weak-dependencies: true repos: - COPR atim/starship + - COPR trixieua/mutter-patched - https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo keys: - https://brave-browser-rpm-release.s3.brave.com/brave-core.asc From 1a816097cf080a3367b0c07d06cb639cdae238bc Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 08:22:50 +0100 Subject: [PATCH 29/51] fix: Forgot to replace `rpm-ostree` to `dnf` when checking for local packages --- modules/dnf/dnf.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 5a16da1..a251a0e 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -118,9 +118,9 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then INSTALL_PKGS[$i]="${PKG//%OS_VERSION%/${OS_VERSION}}" HTTPS_INSTALL=true HTTPS_PKGS+=("${INSTALL_PKGS[$i]}") - elif [[ ! "${PKG}" =~ ^https?:\/\/.* ]] && [[ -f "${CONFIG_DIRECTORY}/rpm-ostree/${PKG}" ]]; then + elif [[ ! "${PKG}" =~ ^https?:\/\/.* ]] && [[ -f "${CONFIG_DIRECTORY}/dnf/${PKG}" ]]; then LOCAL_INSTALL=true - LOCAL_PKGS+=("${CONFIG_DIRECTORY}/rpm-ostree/${PKG}") + LOCAL_PKGS+=("${CONFIG_DIRECTORY}/dnf/${PKG}") else CLASSIC_INSTALL=true CLASSIC_PKGS+=("${PKG}") From a72ae5cb4a1490a4d789385cd04411b5b5b0e72a Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 08:43:04 +0100 Subject: [PATCH 30/51] fix: Adding local file repos --- modules/dnf/dnf.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index a251a0e..3d49fd3 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -47,8 +47,8 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then echo "Adding repository URL: '${repo}'" dnf -y config-manager addrepo --from-repofile="${repo}" elif [[ "${repo}" == *".repo" ]] && [[ -f "${CONFIG_DIRECTORY}/dnf/${repo}" ]]; then - echo "Adding repository file: '${repo}'" - dnf -y config-manager addrepo --from-repofile="${repo}" + echo "Adding repository file: '${repo##*/}'" + dnf -y config-manager addrepo --from-repofile="${CONFIG_DIRECTORY}/dnf/${repo}" elif [[ "${repo}" == "COPR "* ]]; then echo "Adding COPR repository: '${repo#COPR }'" dnf -y copr enable "${repo#COPR }" From 279012362a2744d001db14cfafcfd7d267f3c3a7 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 09:06:03 +0100 Subject: [PATCH 31/51] fix: Replacing packages --- modules/dnf/dnf.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 3d49fd3..96527ec 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -190,15 +190,15 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then get_json_array PACKAGES 'try .["packages"][]' "${REPLACEMENT}" # Ensure packages are provided - if [[ ${#PACKAGES[@]} == 0 ]]; then + if [[ ${#PACKAGES[@]} -eq 0 ]]; then echo "Error: No packages were provided for repository '${REPO}'." exit 1 fi echo "Replacing packages from repository: '${REPO}'" - echo "Replacing: ${REPLACE_STR}" + echo "Replacing: ${PACKAGES[*]}" - dnf -y "${WEAK_DEPS_FLAG}" distro-sync --refresh --repo "${REPO}" "${PACKEGES[@]}" + dnf -y "${WEAK_DEPS_FLAG}" distro-sync --refresh --repo "${REPO}" "${PACKAGES[@]}" done fi From ecffeae553aee38faef1e278a9f1e5ff19b7b1c6 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 09:15:27 +0100 Subject: [PATCH 32/51] chore: Make error message consistent --- modules/dnf/dnf.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 96527ec..e67063d 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -181,8 +181,8 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then REPO="${REPO//[$'\t\r\n ']}" # Ensure repository is provided - if [[ "${REPO}" == "null" ]]; then - echo "Error: Key 'from-repo' was declared, but repository URL was not provided." + if [[ "${REPO}" == "null" ]] || [[ -z "${REPO}" ]]; then + echo "ERROR: Key 'from-repo' was declared, but repository URL was not provided." exit 1 fi @@ -191,7 +191,7 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then # Ensure packages are provided if [[ ${#PACKAGES[@]} -eq 0 ]]; then - echo "Error: No packages were provided for repository '${REPO}'." + echo "ERROR: No packages were provided for repository '${REPO}'." exit 1 fi From 84f89d0ef172c7382c1ee80818d97dea89328b03 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 10:07:53 +0100 Subject: [PATCH 33/51] chore: Begin implementation of specific flag options for every install & remove operation (1st done on replace) --- modules/dnf/dnf.sh | 55 +++++++++++++++++++++++++++++++++------------ modules/dnf/dnf.tsp | 11 ++++++--- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index e67063d..d0001e9 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -16,15 +16,6 @@ if ! rpm -q dnf5-plugins &>/dev/null; then exit 1 fi -# Check if option for weak dependencies is enabled or disabled -WEAK_DEPENDENCIES=$(echo "${1}" | jq -r 'try .["install-weak-dependencies"]') - -if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then - WEAK_DEPS_FLAG="--setopt=install_weak_deps=True" -elif [[ "${WEAK_DEPENDENCIES}" == false ]]; then - WEAK_DEPS_FLAG="--setopt=install_weak_deps=False" -fi - # Pull in repos get_json_array REPOS 'try .["repos"][]' "${1}" if [[ ${#REPOS[@]} -gt 0 ]]; then @@ -92,11 +83,11 @@ if [[ ${#GROUP_INSTALL[@]} -gt 0 && ${#GROUP_REMOVE[@]} -gt 0 ]]; then echo "Removing: ${GROUP_REMOVE[*]}" echo "Installing: ${GROUP_INSTALL[*]}" dnf -y group remove "${GROUP_REMOVE[@]}" - dnf -y "${WEAK_DEPS_FLAG}" group install --refresh "${GROUP_INSTALL[@]}" + dnf -y group install --refresh "${GROUP_INSTALL[@]}" elif [[ ${#GROUP_INSTALL[@]} -gt 0 ]]; then echo "Installing RPM groups" echo "Installing: ${GROUP_INSTALL[*]}" - dnf -y "${WEAK_DEPS_FLAG}" group install --refresh "${GROUP_INSTALL[@]}" + dnf -y group install --refresh "${GROUP_INSTALL[@]}" elif [[ ${#GROUP_REMOVE[@]} -gt 0 ]]; then echo "Removing RPM groups" echo "Removing: ${GROUP_REMOVE[*]}" @@ -158,11 +149,11 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing: ${REMOVE_PKGS[*]}" echo_rpm_install dnf -y remove "${REMOVE_PKGS[@]}" - dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${INSTALL_PKGS[@]}" + dnf -y install --refresh "${INSTALL_PKGS[@]}" elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" echo_rpm_install - dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${INSTALL_PKGS[@]}" + dnf -y install --refresh "${INSTALL_PKGS[@]}" elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" @@ -195,10 +186,46 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then exit 1 fi + # Get if 'install-weak-dependencies' is provided + WEAK_DEPENDENCIES=$(echo "${REPLACEMENT}" | jq -r 'try .["install-weak-dependencies"]') + + if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then + WEAK_DEPS_FLAG="--setopt=install_weak_deps=True" + elif [[ "${WEAK_DEPENDENCIES}" == "false" ]]; then + WEAK_DEPS_FLAG="--setopt=install_weak_deps=False" + fi + + # Get if 'skip-unavailable-packages' is provided + SKIP_UNAVAILABLE=$(echo "${REPLACEMENT}" | jq -r 'try .["skip-unavailable-packages"]') + + if [[ -z "${SKIP_UNAVAILABLE}" ]] || [[ "${SKIP_UNAVAILABLE}" == "null" ]] || [[ "${SKIP_UNAVAILABLE}" == "false" ]]; then + SKIP_UNAVAILABLE_FLAG="" + elif [[ "${SKIP_UNAVAILABLE}" == "true" ]]; then + SKIP_UNAVAILABLE_FLAG="--skip-unavailable" + fi + + # Get if 'skip-broken-packages' is provided + SKIP_BROKEN=$(echo "${REPLACEMENT}" | jq -r 'try .["skip-broken-packages"]') + + if [[ -z "${SKIP_BROKEN}" ]] || [[ "${SKIP_BROKEN}" == "null" ]] || [[ "${SKIP_BROKEN}" == "false" ]]; then + SKIP_BROKEN_FLAG="" + elif [[ "${SKIP_BROKEN}" == "true" ]]; then + SKIP_BROKEN_FLAG="--skip-broken" + fi + + # Get if 'allow-erasing-packages' is provided + ALLOW_ERASING=$(echo "${REPLACEMENT}" | jq -r 'try .["allow-erasing-packages"]') + + if [[ -z "${ALLOW_ERASING}" ]] || [[ "${ALLOW_ERASING}" == "null" ]] || [[ "${ALLOW_ERASING}" == "false" ]]; then + ALLOW_ERASING_FLAG="" + elif [[ "${ALLOW_ERASING}" == "true" ]]; then + ALLOW_ERASING_FLAG="--allowerasing" + fi + echo "Replacing packages from repository: '${REPO}'" echo "Replacing: ${PACKAGES[*]}" - dnf -y "${WEAK_DEPS_FLAG}" distro-sync --refresh --repo "${REPO}" "${PACKAGES[@]}" + dnf -y "${WEAK_DEPS_FLAG}" distro-sync --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" --repo "${REPO}" "${PACKAGES[@]}" done fi diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index 0db3e07..2371629 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -8,9 +8,6 @@ model DnfModule { */ type: "dnf"; - /** Whether to install weak dependencies during install operation or not. */ - "install-weak-dependencies"?: boolean = true; - /** List of links to .repo files to download into /etc/yum.repos.d/. */ repos?: Array; @@ -38,5 +35,13 @@ model DnfModule { "from-repo": string, /** List of packages to replace using packages from the defined repo. */ packages: Array, + /** Whether to install weak dependencies during the replacement or not. */ + "install-weak-dependencies"?: boolean = true, + /** Whether to continue with the replacement if there are no packages available on the system to replace. */ + "skip-unavailable-packages"?: boolean = false, + /** Whether to continue with the replacement if there are broken packages in the system during the replacement. */ + "skip-broken-packages"?: boolean = false, + /** Whether to allow erasing (removal) of packages in case of dependency problems during the replacement. */ + "allow-erasing-packages"?: boolean = false; }>; } From 5d7f34b24904a325de0ed18092f193276c8ac807 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:52:24 +0100 Subject: [PATCH 34/51] chore: Simplify printing log message for install packages Co-authored-by: xyny <60004820+xynydev@users.noreply.github.com> --- modules/dnf/dnf.sh | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index d0001e9..ee0e729 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -121,24 +121,13 @@ fi # Function to inform the user about which type of packages is he installing echo_rpm_install() { - if ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then - echo "Installing: ${CLASSIC_PKGS[*]}" - elif ! ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then - echo "Installing package(s) directly from URL: ${HTTPS_PKGS[*]}" - elif ! ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then - echo "Installing local package(s): ${LOCAL_PKGS[*]}" - elif ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ! ${LOCAL_INSTALL}; then - echo "Installing: ${CLASSIC_PKGS[*]}" - echo "Installing package(s) directly from URL: ${HTTPS_PKGS[*]}" - elif ${CLASSIC_INSTALL} && ! ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then - echo "Installing: ${CLASSIC_PKGS[*]}" - echo "Installing local package(s): ${LOCAL_PKGS[*]}" - elif ! ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then - echo "Installing package(s) directly from URL: ${HTTPS_PKGS[*]}" - echo "Installing local package(s): ${LOCAL_PKGS[*]}" - elif ${CLASSIC_INSTALL} && ${HTTPS_INSTALL} && ${LOCAL_INSTALL}; then + if ${CLASSIC_INSTALL}; then echo "Installing: ${CLASSIC_PKGS[*]}" + fi + if ${HTTPS_INSTALL}; then echo "Installing package(s) directly from URL: ${HTTPS_PKGS[*]}" + fi + if ${LOCAL_INSTALL}; then echo "Installing local package(s): ${LOCAL_PKGS[*]}" fi } From 7fc5a24601ac7647e8c085b9d5833b74366edb76 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 21:44:04 +0100 Subject: [PATCH 35/51] feat: Add dnf flags to all operations --- modules/dnf/README.md | 21 ++++++++- modules/dnf/dnf.sh | 100 +++++++++++++++++++++++++++++++++++------ modules/dnf/dnf.tsp | 44 ++++++++++++++---- modules/dnf/module.yml | 23 ++++++---- 4 files changed, 156 insertions(+), 32 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index 4e1eede..3f60442 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -34,4 +34,23 @@ The module can also replace base RPM packages with packages from any repo. Under [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. ::: -There is also an `install-weak-dependencies:` option to enable or disable installation of weak dependencies for every install operation. Weak dependencies are installed by default. Which kind of dependencies are considered weak can be seen [here](https://docs.fedoraproject.org/en-US/packaging-guidelines/WeakDependencies/). +## Package manager behavior options + +There are several options that can be enabled during the package/group install & during package replace, which modify the behavior of the package manager during those operations. +Those include: + - `install-weak-dependencies` (`--setopt=install_weak_deps=True/False` flag) + - `skip-unavailable-packages` (`--skip-unavailable` flag) + - `skip-broken-packages` (`--skip-broken` flag) + - `allow-erasing-packages` (`--allowerasing` flag) + +### `install-weak-dependencies` +`install-weak-dependencies` option is used to enable or disable installation of weak dependencies for every install & replace operation. By default, this option is true, which means that weak dependencies are installed by default. Which kind of dependencies are considered weak can be seen [here](https://docs.fedoraproject.org/en-US/packaging-guidelines/WeakDependencies/). + +### `skip-unavailable-packages` +`skip-unavailable-packages` option is used to continue or abort install/replace operation if there are no packages available in the repo in install operation, or if they are not available in the system in replace operation. By default, this option is false, which means that install/replace operation aborts in case of unavailable packages. + +### `skip-broken-packages` +`skip-broken-packages` option is used to continue or abort install/replace operation if there are broken packages in the system. By default, this option is false, which means that install/replace operation aborts in case of broken packages. + +### `allow-erasing-packages` +`allow-erasing-packages` option is used to allow erasing/removing problematic packages if they cause issues in install/replace operation. By default, this option is false, which means that problematic packages won't be removed & operation will be aborted. diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index ee0e729..507fec2 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -75,27 +75,99 @@ if [[ ${#OPTFIX[@]} -gt 0 ]]; then fi # Install & remove group packages -get_json_array GROUP_INSTALL 'try .["group-install"][]' "${1}" -get_json_array GROUP_REMOVE 'try .["group-remove"][]' "${1}" +get_json_array GROUP_INSTALL 'try .["group-install"].["packages"][]' "${1}" +get_json_array GROUP_REMOVE 'try .["group-remove"].["packages"][]' "${1}" + +# Get if 'install-weak-dependencies' is provided for group-install +WEAK_DEPENDENCIES=$(echo "${1}" | jq -r 'try .["group-install"].["install-weak-dependencies"]') + +if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then + WEAK_DEPS_FLAG="--setopt=install_weak_deps=True" +elif [[ "${WEAK_DEPENDENCIES}" == "false" ]]; then + WEAK_DEPS_FLAG="--setopt=install_weak_deps=False" +fi + +# Get if 'skip-unavailable-packages' is provided for group-install +SKIP_UNAVAILABLE=$(echo "${1}" | jq -r 'try .["group-install"].["skip-unavailable-packages"]') + +if [[ -z "${SKIP_UNAVAILABLE}" ]] || [[ "${SKIP_UNAVAILABLE}" == "null" ]] || [[ "${SKIP_UNAVAILABLE}" == "false" ]]; then + SKIP_UNAVAILABLE_FLAG="" +elif [[ "${SKIP_UNAVAILABLE}" == "true" ]]; then + SKIP_UNAVAILABLE_FLAG="--skip-unavailable" +fi + +# Get if 'skip-broken-packages' is provided for group-install +SKIP_BROKEN=$(echo "${1}" | jq -r 'try .["group-install"].["skip-broken-packages"]') + +if [[ -z "${SKIP_BROKEN}" ]] || [[ "${SKIP_BROKEN}" == "null" ]] || [[ "${SKIP_BROKEN}" == "false" ]]; then + SKIP_BROKEN_FLAG="" +elif [[ "${SKIP_BROKEN}" == "true" ]]; then + SKIP_BROKEN_FLAG="--skip-broken" +fi + +# Get if 'allow-erasing-packages' is provided for group-install +ALLOW_ERASING=$(echo "${1}" | jq -r 'try .["group-install"].["allow-erasing-packages"]') + +if [[ -z "${ALLOW_ERASING}" ]] || [[ "${ALLOW_ERASING}" == "null" ]] || [[ "${ALLOW_ERASING}" == "false" ]]; then + ALLOW_ERASING_FLAG="" +elif [[ "${ALLOW_ERASING}" == "true" ]]; then + ALLOW_ERASING_FLAG="--allowerasing" +fi if [[ ${#GROUP_INSTALL[@]} -gt 0 && ${#GROUP_REMOVE[@]} -gt 0 ]]; then echo "Removing & Installing RPM groups" echo "Removing: ${GROUP_REMOVE[*]}" echo "Installing: ${GROUP_INSTALL[*]}" dnf -y group remove "${GROUP_REMOVE[@]}" - dnf -y group install --refresh "${GROUP_INSTALL[@]}" + dnf -y "${WEAK_DEPS_FLAG}" group install --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" "${GROUP_INSTALL[@]}" elif [[ ${#GROUP_INSTALL[@]} -gt 0 ]]; then echo "Installing RPM groups" echo "Installing: ${GROUP_INSTALL[*]}" - dnf -y group install --refresh "${GROUP_INSTALL[@]}" + dnf -y "${WEAK_DEPS_FLAG}" group install --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" "${GROUP_INSTALL[@]}" elif [[ ${#GROUP_REMOVE[@]} -gt 0 ]]; then echo "Removing RPM groups" echo "Removing: ${GROUP_REMOVE[*]}" dnf -y remove "${GROUP_REMOVE[@]}" fi -get_json_array INSTALL_PKGS 'try .["install"][]' "${1}" -get_json_array REMOVE_PKGS 'try .["remove"][]' "${1}" +get_json_array INSTALL_PKGS 'try .["install"].["packages"][]' "${1}" +get_json_array REMOVE_PKGS 'try .["remove"].["packages"][]' "${1}" + +# Get if 'install-weak-dependencies' is provided for package install +WEAK_DEPENDENCIES=$(echo "${1}" | jq -r 'try .["install"].["install-weak-dependencies"]') + +if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then + WEAK_DEPS_FLAG="--setopt=install_weak_deps=True" +elif [[ "${WEAK_DEPENDENCIES}" == "false" ]]; then + WEAK_DEPS_FLAG="--setopt=install_weak_deps=False" +fi + +# Get if 'skip-unavailable-packages' is provided for package install +SKIP_UNAVAILABLE=$(echo "${1}" | jq -r 'try .["install"].["skip-unavailable-packages"]') + +if [[ -z "${SKIP_UNAVAILABLE}" ]] || [[ "${SKIP_UNAVAILABLE}" == "null" ]] || [[ "${SKIP_UNAVAILABLE}" == "false" ]]; then + SKIP_UNAVAILABLE_FLAG="" +elif [[ "${SKIP_UNAVAILABLE}" == "true" ]]; then + SKIP_UNAVAILABLE_FLAG="--skip-unavailable" +fi + +# Get if 'skip-broken-packages' is provided for package install +SKIP_BROKEN=$(echo "${1}" | jq -r 'try .["install"].["skip-broken-packages"]') + +if [[ -z "${SKIP_BROKEN}" ]] || [[ "${SKIP_BROKEN}" == "null" ]] || [[ "${SKIP_BROKEN}" == "false" ]]; then + SKIP_BROKEN_FLAG="" +elif [[ "${SKIP_BROKEN}" == "true" ]]; then + SKIP_BROKEN_FLAG="--skip-broken" +fi + +# Get if 'allow-erasing-packages' is provided for package install +ALLOW_ERASING=$(echo "${1}" | jq -r 'try .["install"].["allow-erasing-packages"]') + +if [[ -z "${ALLOW_ERASING}" ]] || [[ "${ALLOW_ERASING}" == "null" ]] || [[ "${ALLOW_ERASING}" == "false" ]]; then + ALLOW_ERASING_FLAG="" +elif [[ "${ALLOW_ERASING}" == "true" ]]; then + ALLOW_ERASING_FLAG="--allowerasing" +fi CLASSIC_INSTALL=false HTTPS_INSTALL=false @@ -138,11 +210,11 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing: ${REMOVE_PKGS[*]}" echo_rpm_install dnf -y remove "${REMOVE_PKGS[@]}" - dnf -y install --refresh "${INSTALL_PKGS[@]}" + dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" "${INSTALL_PKGS[@]}" elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" echo_rpm_install - dnf -y install --refresh "${INSTALL_PKGS[@]}" + dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" "${INSTALL_PKGS[@]}" elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" @@ -175,7 +247,7 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then exit 1 fi - # Get if 'install-weak-dependencies' is provided + # Get if 'install-weak-dependencies' is provided for package replace WEAK_DEPENDENCIES=$(echo "${REPLACEMENT}" | jq -r 'try .["install-weak-dependencies"]') if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then @@ -184,7 +256,7 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then WEAK_DEPS_FLAG="--setopt=install_weak_deps=False" fi - # Get if 'skip-unavailable-packages' is provided + # Get if 'skip-unavailable-packages' is provided for package replace SKIP_UNAVAILABLE=$(echo "${REPLACEMENT}" | jq -r 'try .["skip-unavailable-packages"]') if [[ -z "${SKIP_UNAVAILABLE}" ]] || [[ "${SKIP_UNAVAILABLE}" == "null" ]] || [[ "${SKIP_UNAVAILABLE}" == "false" ]]; then @@ -193,23 +265,23 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then SKIP_UNAVAILABLE_FLAG="--skip-unavailable" fi - # Get if 'skip-broken-packages' is provided + # Get if 'skip-broken-packages' is provided for package replace SKIP_BROKEN=$(echo "${REPLACEMENT}" | jq -r 'try .["skip-broken-packages"]') if [[ -z "${SKIP_BROKEN}" ]] || [[ "${SKIP_BROKEN}" == "null" ]] || [[ "${SKIP_BROKEN}" == "false" ]]; then SKIP_BROKEN_FLAG="" elif [[ "${SKIP_BROKEN}" == "true" ]]; then SKIP_BROKEN_FLAG="--skip-broken" - fi + fi - # Get if 'allow-erasing-packages' is provided + # Get if 'allow-erasing-packages' is provided for package replace ALLOW_ERASING=$(echo "${REPLACEMENT}" | jq -r 'try .["allow-erasing-packages"]') if [[ -z "${ALLOW_ERASING}" ]] || [[ "${ALLOW_ERASING}" == "null" ]] || [[ "${ALLOW_ERASING}" == "false" ]]; then ALLOW_ERASING_FLAG="" elif [[ "${ALLOW_ERASING}" == "true" ]]; then ALLOW_ERASING_FLAG="--allowerasing" - fi + fi echo "Replacing packages from repository: '${REPO}'" echo "Replacing: ${PACKAGES[*]}" diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index 2371629..d459e43 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -17,17 +17,45 @@ model DnfModule { /** List of folder names under /opt/ to enable for installing into. */ optfix?: Array; - /** List of RPM groups to remove. */ - "group-remove"?: Array; + /** Configuration of RPM groups removal. */ + "group-remove"?: { + /** List of RPM groups to remove. */ + packages?: string; + }; - /** List of RPM groups to install. */ - "group-install"?: Array; + /** Configuration of RPM groups install. */ + "group-install"?: { + /** List of RPM groups to install. */ + packages?: string, + /** Whether to install weak dependencies during the RPM group install or not. */ + "install-weak-dependencies"?: boolean = true, + /** Whether to continue with the RPM group install if there are no packages available in the repository. */ + "skip-unavailable-packages"?: boolean = false, + /** Whether to continue with the RPM group install if there are broken packages. */ + "skip-broken-packages"?: boolean = false, + /** Whether to allow erasing (removal) of packages in case of dependency problems during the RPM group install. */ + "allow-erasing-packages"?: boolean = false; + }; - /** List of RPM packages to remove. */ - remove?: Array; + /** Configuration of RPM packages removal. */ + "remove"?: { + /** List of RPM packages to remove. */ + packages?: string; + }; - /** List of RPM packages to install. */ - install?: Array; + /** Configuration of RPM packages install. */ + "install"?: { + /** List of RPM packages to install. */ + packages?: string, + /** Whether to install weak dependencies during the RPM package install or not. */ + "install-weak-dependencies"?: boolean = true, + /** Whether to continue with the RPM package install if there are no packages available in the repository. */ + "skip-unavailable-packages"?: boolean = false, + /** Whether to continue with the RPM package install if there are broken packages. */ + "skip-broken-packages"?: boolean = false, + /** Whether to allow erasing (removal) of packages in case of dependency problems during the RPM package install. */ + "allow-erasing-packages"?: boolean = false; + }; /** List of configurations for replacing packages from another repo. */ replace?: Array<{ diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index b631fea..1c66587 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -12,20 +12,25 @@ example: | optfix: - Tabby # needed because tabby installs into /opt/Tabby/ - brave.com - group-install: - - cosmic-desktop - - cosmic-desktop-apps # Installs Cosmic desktop environment - - window-managers + group-install: + packages: + - cosmic-desktop + - cosmic-desktop-apps # Installs Cosmic desktop environment + - window-managers install: - - starship - - brave-browser - - https://github.com/Eugeny/tabby/releases/download/v1.0.209/tabby-1.0.209-linux-x64.rpm + packages: + - starship + - brave-browser + - https://github.com/Eugeny/tabby/releases/download/v1.0.209/tabby-1.0.209-linux-x64.rpm + install-weak-dependencies: false # doesn't install weak dependencies for those packages remove: - - firefox - - firefox-langpacks + packages: + - firefox + - firefox-langpacks replace: - from-repo: copr:copr.fedorainfracloud.org:trixieua:mutter-patched packages: - mutter - mutter-common - gdm + skip-unavailable-packages: true # replacement will proceed even if 'mutter' or 'gdm' is not installed in the system \ No newline at end of file From 63f745b2b39e5018d9e8978e00aa09765e2d28e8 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:17:17 +0100 Subject: [PATCH 36/51] feat: Add `remove-unused-dependencies` option for package removal --- modules/dnf/README.md | 26 ++++++++++++++++++++------ modules/dnf/dnf.sh | 13 +++++++++++-- modules/dnf/dnf.tsp | 4 +++- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index 3f60442..7715ec6 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -34,23 +34,37 @@ The module can also replace base RPM packages with packages from any repo. Under [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. ::: -## Package manager behavior options +## `dnf` behavior options + +There are several options that can be enabled during the package/group install + removal & during package replace, which modify the behavior of the package manager during those operations. -There are several options that can be enabled during the package/group install & during package replace, which modify the behavior of the package manager during those operations. Those include: + +Install operation: - `install-weak-dependencies` (`--setopt=install_weak_deps=True/False` flag) - `skip-unavailable-packages` (`--skip-unavailable` flag) - `skip-broken-packages` (`--skip-broken` flag) - `allow-erasing-packages` (`--allowerasing` flag) -### `install-weak-dependencies` +Remove operation: + - `remove-unused-dependencies` (`--no-autoremove` flag) + + +### `dnf` install/replace behavior options + +#### `install-weak-dependencies` `install-weak-dependencies` option is used to enable or disable installation of weak dependencies for every install & replace operation. By default, this option is true, which means that weak dependencies are installed by default. Which kind of dependencies are considered weak can be seen [here](https://docs.fedoraproject.org/en-US/packaging-guidelines/WeakDependencies/). -### `skip-unavailable-packages` +#### `skip-unavailable-packages` `skip-unavailable-packages` option is used to continue or abort install/replace operation if there are no packages available in the repo in install operation, or if they are not available in the system in replace operation. By default, this option is false, which means that install/replace operation aborts in case of unavailable packages. -### `skip-broken-packages` +#### `skip-broken-packages` `skip-broken-packages` option is used to continue or abort install/replace operation if there are broken packages in the system. By default, this option is false, which means that install/replace operation aborts in case of broken packages. -### `allow-erasing-packages` +#### `allow-erasing-packages` `allow-erasing-packages` option is used to allow erasing/removing problematic packages if they cause issues in install/replace operation. By default, this option is false, which means that problematic packages won't be removed & operation will be aborted. + +### `dnf` package (non-group) removal behavior options + +#### `remove-unused-dependencies` +`remove-unused-dependencies` option is used to control the behavior of removing unused dependencies when some main packages are removed. By default, this option is true. Only compatible with removing packages, not compatible with removing RPM groups. \ No newline at end of file diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 507fec2..4630bf5 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -169,6 +169,15 @@ elif [[ "${ALLOW_ERASING}" == "true" ]]; then ALLOW_ERASING_FLAG="--allowerasing" fi +# Get if 'remove-unused-dependencies' is provided for package removal +REMOVE_UNUSED_DEPS=$(echo "${1}" | jq -r 'try .["remove"].["remove-unused-dependencies"]') + +if [[ -z "${REMOVE_UNUSED_DEPS}" ]] || [[ "${REMOVE_UNUSED_DEPS}" == "null" ]] || [[ "${REMOVE_UNUSED_DEPS}" == "true" ]]; then + REMOVE_UNUSED_DEPS_FLAG="" +elif [[ "${REMOVE_UNUSED_DEPS}" == "false" ]]; then + REMOVE_UNUSED_DEPS_FLAG="--no-autoremove" +fi + CLASSIC_INSTALL=false HTTPS_INSTALL=false LOCAL_INSTALL=false @@ -209,7 +218,7 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing & Installing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" echo_rpm_install - dnf -y remove "${REMOVE_PKGS[@]}" + dnf -y remove "${REMOVE_UNUSED_DEPS_FLAG}" "${REMOVE_PKGS[@]}" dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" "${INSTALL_PKGS[@]}" elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" @@ -218,7 +227,7 @@ elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" - dnf -y remove "${REMOVE_PKGS[@]}" + dnf -y remove "${REMOVE_UNUSED_DEPS_FLAG}" "${REMOVE_PKGS[@]}" fi get_json_array REPLACE 'try .["replace"][]' "$1" diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index d459e43..da4ba5a 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -40,7 +40,9 @@ model DnfModule { /** Configuration of RPM packages removal. */ "remove"?: { /** List of RPM packages to remove. */ - packages?: string; + packages?: string, + /** Whether to remove unused dependencies during removal operation. */ + "remove-unused-dependencies"?: boolean = true; }; /** Configuration of RPM packages install. */ From b474a5a70c10fd5154e8e9136e95de0318b1c2e6 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:33:38 +0100 Subject: [PATCH 37/51] chore: Fix group-remove typespec Co-authored-by: Gerald Pinder --- modules/dnf/dnf.tsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index da4ba5a..1e433d1 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -20,7 +20,7 @@ model DnfModule { /** Configuration of RPM groups removal. */ "group-remove"?: { /** List of RPM groups to remove. */ - packages?: string; + packages: Array; }; /** Configuration of RPM groups install. */ From 770bb335897dec5633bd282530cceae5f8955569 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:33:54 +0100 Subject: [PATCH 38/51] chore: Fix group-install typespec Co-authored-by: Gerald Pinder --- modules/dnf/dnf.tsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index 1e433d1..be56738 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -26,7 +26,7 @@ model DnfModule { /** Configuration of RPM groups install. */ "group-install"?: { /** List of RPM groups to install. */ - packages?: string, + packages: Array, /** Whether to install weak dependencies during the RPM group install or not. */ "install-weak-dependencies"?: boolean = true, /** Whether to continue with the RPM group install if there are no packages available in the repository. */ From d8a900608126e12fde70877bab5a64be38d128dc Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:34:11 +0100 Subject: [PATCH 39/51] chore: Fix remove typespec Co-authored-by: Gerald Pinder --- modules/dnf/dnf.tsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index be56738..6ed20ec 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -40,7 +40,7 @@ model DnfModule { /** Configuration of RPM packages removal. */ "remove"?: { /** List of RPM packages to remove. */ - packages?: string, + packages: Array, /** Whether to remove unused dependencies during removal operation. */ "remove-unused-dependencies"?: boolean = true; }; From 33065b4f5f2594098cb6af9c9de9d60967c1dddb Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:34:22 +0100 Subject: [PATCH 40/51] chore: Fix install typespec Co-authored-by: Gerald Pinder --- modules/dnf/dnf.tsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index 6ed20ec..7084205 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -48,7 +48,7 @@ model DnfModule { /** Configuration of RPM packages install. */ "install"?: { /** List of RPM packages to install. */ - packages?: string, + packages: Array, /** Whether to install weak dependencies during the RPM package install or not. */ "install-weak-dependencies"?: boolean = true, /** Whether to continue with the RPM package install if there are no packages available in the repository. */ From 342319063ed9ade0c321ea3c65a40c04226528a9 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:36:52 +0100 Subject: [PATCH 41/51] chore: Remove leftover global `install-weak-dependencies` option Co-authored-by: Gerald Pinder --- modules/dnf/module.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index 1c66587..c37d028 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -2,7 +2,6 @@ name: dnf shortdesc: The dnf module offers pseudo-declarative package and repository management using dnf. example: | type: dnf - install-weak-dependencies: true repos: - COPR atim/starship - COPR trixieua/mutter-patched From f176120368dd4b35c502c03bbaf55e4b70bfbd32 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:38:58 +0100 Subject: [PATCH 42/51] chore: Remove redundant dnf5 plugin check --- modules/dnf/dnf.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 4630bf5..09204e0 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -9,13 +9,6 @@ if ! rpm -q dnf5 &>/dev/null; then exit 1 fi -# Fail the build if dnf5 plugins aren't installed -if ! rpm -q dnf5-plugins &>/dev/null; then - echo "ERROR: Dependency 'dnf5-plugins' is not installed. It is needed for cleanly adding COPR repositories." - echo " Install 'dnf5-plugins' before using this module to solve this error." - exit 1 -fi - # Pull in repos get_json_array REPOS 'try .["repos"][]' "${1}" if [[ ${#REPOS[@]} -gt 0 ]]; then From 7458b4be057bf2e8aaf3dfac8267fa91583ee774 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:42:48 +0100 Subject: [PATCH 43/51] fix: dnf group remove command missed `group` prefix Co-authored-by: Gerald Pinder --- modules/dnf/dnf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 09204e0..8318b67 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -120,7 +120,7 @@ elif [[ ${#GROUP_INSTALL[@]} -gt 0 ]]; then elif [[ ${#GROUP_REMOVE[@]} -gt 0 ]]; then echo "Removing RPM groups" echo "Removing: ${GROUP_REMOVE[*]}" - dnf -y remove "${GROUP_REMOVE[@]}" + dnf -y group remove "${GROUP_REMOVE[@]}" fi get_json_array INSTALL_PKGS 'try .["install"].["packages"][]' "${1}" From ce4163cdb1717f9caa9fb28ec8fd68832be674d8 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Tue, 24 Dec 2024 12:59:28 +0100 Subject: [PATCH 44/51] fix: Don't quote the flags, else dnf will see it as an empty argument part 1 Co-authored-by: Gerald Pinder --- modules/dnf/dnf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 8318b67..d3fa233 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -112,7 +112,7 @@ if [[ ${#GROUP_INSTALL[@]} -gt 0 && ${#GROUP_REMOVE[@]} -gt 0 ]]; then echo "Removing: ${GROUP_REMOVE[*]}" echo "Installing: ${GROUP_INSTALL[*]}" dnf -y group remove "${GROUP_REMOVE[@]}" - dnf -y "${WEAK_DEPS_FLAG}" group install --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" "${GROUP_INSTALL[@]}" + dnf -y ${WEAK_DEPS_FLAG} group install --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} "${GROUP_INSTALL[@]}" elif [[ ${#GROUP_INSTALL[@]} -gt 0 ]]; then echo "Installing RPM groups" echo "Installing: ${GROUP_INSTALL[*]}" From c8043a493d3265dd914f310c71289bc80fdb877a Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Tue, 24 Dec 2024 12:59:53 +0100 Subject: [PATCH 45/51] fix: Don't quote the flags, else dnf will see it as an empty argument part 2 Co-authored-by: Gerald Pinder --- modules/dnf/dnf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index d3fa233..2e4fea4 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -116,7 +116,7 @@ if [[ ${#GROUP_INSTALL[@]} -gt 0 && ${#GROUP_REMOVE[@]} -gt 0 ]]; then elif [[ ${#GROUP_INSTALL[@]} -gt 0 ]]; then echo "Installing RPM groups" echo "Installing: ${GROUP_INSTALL[*]}" - dnf -y "${WEAK_DEPS_FLAG}" group install --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" "${GROUP_INSTALL[@]}" + dnf -y ${WEAK_DEPS_FLAG} group install --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} "${GROUP_INSTALL[@]}" elif [[ ${#GROUP_REMOVE[@]} -gt 0 ]]; then echo "Removing RPM groups" echo "Removing: ${GROUP_REMOVE[*]}" From aa92efffcfd994481073413b98a63b915de96e20 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:00:10 +0100 Subject: [PATCH 46/51] fix: Don't quote the flags, else dnf will see it as an empty argument part 3 Co-authored-by: Gerald Pinder --- modules/dnf/dnf.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 2e4fea4..dd425b5 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -211,8 +211,8 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing & Installing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" echo_rpm_install - dnf -y remove "${REMOVE_UNUSED_DEPS_FLAG}" "${REMOVE_PKGS[@]}" - dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" "${INSTALL_PKGS[@]}" + dnf -y remove ${REMOVE_UNUSED_DEPS_FLAG} "${REMOVE_PKGS[@]}" + dnf -y ${WEAK_DEPS_FLAG} install --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} "${INSTALL_PKGS[@]}" elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" echo_rpm_install From 8265b8524ee637f3c5ef1306234fc326b4e1d085 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:00:51 +0100 Subject: [PATCH 47/51] fix: Don't quote the flags, else dnf will see it as an empty argument part 4 Co-authored-by: Gerald Pinder --- modules/dnf/dnf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index dd425b5..b00e07d 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -216,7 +216,7 @@ if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then echo "Installing RPMs" echo_rpm_install - dnf -y "${WEAK_DEPS_FLAG}" install --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" "${INSTALL_PKGS[@]}" + dnf -y ${WEAK_DEPS_FLAG} install --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} "${INSTALL_PKGS[@]}" elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" From c9f4fb0002c61586902f22d190bbb6c1cc5d05e4 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:01:07 +0100 Subject: [PATCH 48/51] fix: Don't quote the flags, else dnf will see it as an empty argument part 5 Co-authored-by: Gerald Pinder --- modules/dnf/dnf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index b00e07d..39739a8 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -220,7 +220,7 @@ elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then echo "Removing RPMs" echo "Removing: ${REMOVE_PKGS[*]}" - dnf -y remove "${REMOVE_UNUSED_DEPS_FLAG}" "${REMOVE_PKGS[@]}" + dnf -y remove ${REMOVE_UNUSED_DEPS_FLAG} "${REMOVE_PKGS[@]}" fi get_json_array REPLACE 'try .["replace"][]' "$1" From 92df6a0c6c2e597df1a7dd08ad50ede86d37d0d2 Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:01:22 +0100 Subject: [PATCH 49/51] fix: Don't quote the flags, else dnf will see it as an empty argument part 6 Co-authored-by: Gerald Pinder --- modules/dnf/dnf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 39739a8..cb0a37c 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -288,7 +288,7 @@ if [[ ${#REPLACE[@]} -gt 0 ]]; then echo "Replacing packages from repository: '${REPO}'" echo "Replacing: ${PACKAGES[*]}" - dnf -y "${WEAK_DEPS_FLAG}" distro-sync --refresh "${SKIP_UNAVAILABLE_FLAG}" "${SKIP_BROKEN_FLAG}" "${ALLOW_ERASING_FLAG}" --repo "${REPO}" "${PACKAGES[@]}" + dnf -y ${WEAK_DEPS_FLAG} distro-sync --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} --repo "${REPO}" "${PACKAGES[@]}" done fi From 4920cc46f09fc93ca1a7eab54332b31164f995aa Mon Sep 17 00:00:00 2001 From: fiftydinar <65243233+fiftydinar@users.noreply.github.com> Date: Wed, 25 Dec 2024 15:26:31 +0100 Subject: [PATCH 50/51] chore: Add separate `copr` array --- modules/dnf/README.md | 2 +- modules/dnf/dnf.sh | 26 ++++++++++++++++---------- modules/dnf/dnf.tsp | 3 +++ modules/dnf/module.yml | 5 +++-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/modules/dnf/README.md b/modules/dnf/README.md index 7715ec6..ad353a4 100644 --- a/modules/dnf/README.md +++ b/modules/dnf/README.md @@ -10,7 +10,7 @@ repos: - my-repository.repo # copies in .repo file from files/dnf/my-repository.repo to /etc/yum.repos.d/ ``` -Specific COPR repositories can also be specified in `COPR user/project` format & is prefered over using direct COPR URL. +Specific COPR repositories can also be specified in `user/project` format in `copr:` array. 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`. diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index cb0a37c..98c5bb6 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -18,14 +18,8 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then repo="${REPOS[$i]}" repo="${repo//%OS_VERSION%/${OS_VERSION}}" REPOS[$i]="${repo//[$'\t\r\n ']}" - # Remove spaces/newlines for all repos other than COPR - if [[ "${repo}" != "COPR "* ]]; then - REPOS[$i]="${repo//[$'\t\r\n ']}" - else - REPOS[$i]="${repo}" - fi done - # dnf config-manager & dnf copr don't support adding multiple repositories at once, hence why for/done loop is used + # dnf config-manager doesn't support adding multiple repositories at once, hence why for/done loop is used for repo in "${REPOS[@]}"; do if [[ "${repo}" =~ ^https?:\/\/.* ]]; then echo "Adding repository URL: '${repo}'" @@ -33,9 +27,21 @@ if [[ ${#REPOS[@]} -gt 0 ]]; then elif [[ "${repo}" == *".repo" ]] && [[ -f "${CONFIG_DIRECTORY}/dnf/${repo}" ]]; then echo "Adding repository file: '${repo##*/}'" dnf -y config-manager addrepo --from-repofile="${CONFIG_DIRECTORY}/dnf/${repo}" - elif [[ "${repo}" == "COPR "* ]]; then - echo "Adding COPR repository: '${repo#COPR }'" - dnf -y copr enable "${repo#COPR }" + fi + done +fi + +# Pull in COPR repos +get_json_array COPR_REPOS 'try .["copr"][]' "${1}" +if [[ ${#COPR_REPOS[@]} -gt 0 ]]; then + echo "Adding COPR repositories" + for repo in "${COPR_REPOS[@]}"; do + if [[ "${repo}" == *"/"* ]]; then + echo "Adding COPR repository: '${repo}'" + dnf copr enable "${repo}" + else + echo "ERROR: You didn't provide COPR repository in proper format, it should be in 'user/project' format." + exit 1 fi done fi diff --git a/modules/dnf/dnf.tsp b/modules/dnf/dnf.tsp index 7084205..349cafc 100644 --- a/modules/dnf/dnf.tsp +++ b/modules/dnf/dnf.tsp @@ -11,6 +11,9 @@ model DnfModule { /** List of links to .repo files to download into /etc/yum.repos.d/. */ repos?: Array; + /** List of COPR project repos to download into /etc/yum.repos.d/. */ + copr?: Array; + /** List of links to key files to import for installing from custom repositories. */ keys?: Array; diff --git a/modules/dnf/module.yml b/modules/dnf/module.yml index c37d028..8b0957e 100644 --- a/modules/dnf/module.yml +++ b/modules/dnf/module.yml @@ -3,9 +3,10 @@ shortdesc: The dnf module offers pseudo-declarative package and repository manag example: | type: dnf repos: - - COPR atim/starship - - COPR trixieua/mutter-patched - https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo + copr: + - atim/starship + - trixieua/mutter-patched keys: - https://brave-browser-rpm-release.s3.brave.com/brave-core.asc optfix: From 7612cc27889bafc84c9dbf7a5f3cac6577025896 Mon Sep 17 00:00:00 2001 From: Gerald Pinder Date: Thu, 26 Dec 2024 16:43:59 -0500 Subject: [PATCH 51/51] fix: Assume yes for copr enable --- modules/dnf/dnf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnf/dnf.sh b/modules/dnf/dnf.sh index 98c5bb6..2cff5eb 100644 --- a/modules/dnf/dnf.sh +++ b/modules/dnf/dnf.sh @@ -38,7 +38,7 @@ if [[ ${#COPR_REPOS[@]} -gt 0 ]]; then for repo in "${COPR_REPOS[@]}"; do if [[ "${repo}" == *"/"* ]]; then echo "Adding COPR repository: '${repo}'" - dnf copr enable "${repo}" + dnf -y copr enable "${repo}" else echo "ERROR: You didn't provide COPR repository in proper format, it should be in 'user/project' format." exit 1