From ef29c090aff7a044ad37b122b4283913c6a57e23 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Sun, 4 Aug 2024 20:04:40 +0100 Subject: [PATCH] Add Alma Linux and Rocky Linux runners (#7424) * Add RHEL image * Use Fedora config for RHEL * Use script to activate RHEL * Mirror mount args * Set RHEL username and password * Pass RHEL build args * Pass RHEL login by file * Use RHEL 9 for newer Python * Source RHEL login * Add case for RHEL Python deps * Add `--deactivate` * Do PIP user install * Upgrade PIP * Add RHEL config * Introduce 'command-pre' * Inherit fedora deps for RHEL and only strip sudo on non-empty command * Add RHEL 9 runner * Use RHEL 9 codeready * Add AlmaLinux EL9 * Add support for RHEL-like * Add EPEL for Alma * Enable power tools on Alma * Fix missing semicolon * Install EPEL before power tools * Inherit Alma deps from RHEL * Switch from `powertools` to `crb` * Abandon RHEL for now (no Qt 6 support) * Don't pass required when getting distro key * Correct key name for Rocky Linux * Add Repology badge * Restore original `build-push-action` * Exclude unsupported Repology entries * Update ChangeLog --- .github/workflows/build-containers.yml | 12 +++++++ .github/workflows/ci.yml | 8 +++++ ChangeLog | 1 + README.md | 12 +++++++ config.yaml | 36 ++++++++++++++++----- scripts/install_deps.py | 34 ++++++++++--------- scripts/lib/config.py | 45 ++++++++++++++++---------- scripts/lib/env.py | 12 ++++++- scripts/lib/linux.py | 14 ++++++++ 9 files changed, 133 insertions(+), 41 deletions(-) diff --git a/.github/workflows/build-containers.yml b/.github/workflows/build-containers.yml index 4818a877e..bf2cf056e 100644 --- a/.github/workflows/build-containers.yml +++ b/.github/workflows/build-containers.yml @@ -68,6 +68,18 @@ jobs: base-image: fedora:39 platform: amd64 + - name: rockylinux-9-amd64 + runs-on: ubuntu-latest + config-dir: fedora + base-image: rockylinux:9 + platform: amd64 + + - name: almalinux-9-amd64 + runs-on: ubuntu-latest + config-dir: fedora + base-image: almalinux:9 + platform: amd64 + - name: opensuse-amd64 runs-on: ubuntu-latest config-dir: opensuse diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3e2c193b..4547b4b8d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -248,6 +248,14 @@ jobs: container: symless/synergy-core:opensuse-amd64 runs-on: ubuntu-latest + - name: rockylinux-9-amd64 + container: symless/synergy-core:rockylinux-9-amd64 + runs-on: ubuntu-latest + + - name: almalinux-9-amd64 + container: symless/synergy-core:almalinux-9-amd64 + runs-on: ubuntu-latest + - name: archlinux-amd64 container: symless/synergy-core:archlinux-amd64 runs-on: ubuntu-latest diff --git a/ChangeLog b/ChangeLog index 687c98780..956a3488e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -67,6 +67,7 @@ Enhancements: - #7419 Introduce 'Advanced' tab to Preferences window - #7422 Handle empty value for computer name setting - #7423 Refactor local/global save/load and show dev thanks message +- #7424 Add Alma Linux and Rocky Linux runners # 1.14.6 diff --git a/README.md b/README.md index 2a1f9f541..9e8bde14e 100644 --- a/README.md +++ b/README.md @@ -55,3 +55,15 @@ cmake --build build -j8 ``` ./build/bin/unittests ``` + +## Packages + +To get Synergy, either your favorite package manager to install: +- `synergy` for Synergy 1 (this repo) +- `synergy3` for Synergy 3 (non-free) + +Alternatively, use the [official packages](https://symless.com/synergy/download). + +Synergy 2 is no longer in development and should not be provided. + +[![Repology](https://repology.org/badge/vertical-allrepos/synergy.svg?exclude_unsupported=1)](https://repology.org/project/synergy/versions) diff --git a/config.yaml b/config.yaml index 0d59c2830..fa0235b7a 100644 --- a/config.yaml +++ b/config.yaml @@ -23,7 +23,8 @@ config: linux: debian: &debian dependencies: - command: sudo apt-get update; \ + command-pre: sudo apt-get update + command: | sudo apt-get install -y \ cmake \ make \ @@ -45,8 +46,9 @@ config: <<: *debian fedora: &fedora - dependencies: - command: sudo dnf check-update; \ + dependencies: &fedora_deps + command-pre: sudo dnf check-update + command: | sudo dnf install -y \ cmake \ make \ @@ -59,14 +61,34 @@ config: libxkbfile-devel \ qt6-qtbase-devel \ qt6-qttools-devel \ - qt6-qt5compat-devel \ gtk3-devel \ rpm-build + # RHEL is not actually supported yet, since it doesn't have Qt6 libs. + # We simply use it as a base for Alma Linux and Rocky Linux. + rhel: &rhel + <<: *fedora + dependencies: &rhel_deps + <<: *fedora_deps + command-pre: | + sudo dnf check-update; + sudo dnf install -y epel-release; + dnf config-manager --set-enabled crb + + rocky: + <<: *rhel + dependencies: + <<: *rhel_deps + + almalinux: + <<: *rhel + dependencies: + <<: *rhel_deps + opensuse-tumbleweed: &opensuse-tumbleweed dependencies: - command: sudo zypper refresh; \ - sudo zypper install -y --force-resolution \ + command-pre: sudo zypper refresh + command: sudo zypper install -y --force-resolution \ cmake \ make \ gcc-c++ \ @@ -78,7 +100,6 @@ config: libxkbfile-devel \ qt6-base-devel \ qt6-tools-devel \ - qt6-qt5compat-devel \ gtk3-devel \ rpm-build @@ -96,7 +117,6 @@ config: libxkbfile \ qt6-base \ qt6-tools \ - qt6-5compat \ gtk3 manjaro: diff --git a/scripts/install_deps.py b/scripts/install_deps.py index b58dd4876..8333dd723 100755 --- a/scripts/install_deps.py +++ b/scripts/install_deps.py @@ -92,7 +92,7 @@ class Dependencies: edit_config, skip_packages = self.config.get_windows_ci_config() choco.remove_from_config(edit_config, skip_packages) - command = self.config.get_deps_command() + command = self.config.get_os_deps_command() choco.install(command, self.ci_env) def mac(self): @@ -112,7 +112,7 @@ class Dependencies: env_vars_set += mac.set_env_var(cmake_prefix_env_var, qt_dir) env_vars_set += mac.set_env_var(path_env_var, qt_bin_dir) - command = self.config.get_os_deps_value("command") + command = self.config.get_os_deps_command() cmd_utils.run(command, shell=True, print_cmd=True) if env_vars_set: @@ -120,25 +120,29 @@ class Dependencies: def linux(self): """Installs dependencies on Linux.""" + import lib.linux as linux - distro, _distro_like, _distro_version = env.get_linux_distro() + distro, distro_like, _distro_version = env.get_linux_distro() if not distro: raise RuntimeError("Unable to detect Linux distro") - command = self.config.get_linux_deps_command(distro) + command_pre = self.config.get_os_deps_command_pre( + linux_distro=distro, required=False + ) + if command_pre: + print("Running dependencies prerequisites command") - has_sudo = cmd_utils.has_command("sudo") - if "sudo" in command and not has_sudo: - # assume we're running as root if sudo is not found (common on older distros). - # a space char is intentionally added after "sudo" for intentionality. - # possible limitation with stripping "sudo" is that if any packages with "sudo" in the - # name are added to the list (probably very unlikely), this will have undefined behavior. - print("The 'sudo' command was not found, stripping sudo from command") - command = command.replace("sudo ", "").strip() + check = True + if distro_like and "fedora" in distro_like: + print("Fedora-like detected, ignoring return code") + # On Fedora, dnf update returns code 100 when updates are available. + check = False - # On Fedora, dnf update returns code 100 when updates are available, but the last command - # run should be dnf install, so the return code should always be 0. - cmd_utils.run(command, shell=True, print_cmd=True) + linux.run_command(command_pre, check) + + command = self.config.get_os_deps_command(linux_distro=distro) + print("Running dependencies command") + linux.run_command(command, check=True) if __name__ == "__main__": diff --git a/scripts/lib/config.py b/scripts/lib/config.py index 0bc29c42c..dcb89c416 100644 --- a/scripts/lib/config.py +++ b/scripts/lib/config.py @@ -5,6 +5,9 @@ import lib.cmd_utils as cmd_utils config_file = "config.yaml" root_key = "config" deps_key = "dependencies" +command_key = "command" +command_pre_key = "command-pre" +arrow = " ➤ " class ConfigKeyError(RuntimeError): @@ -20,7 +23,7 @@ def _get(dict, key, key_parent=None, required=True): value = dict.get(key) if required and not value: - key_path = f"{root_key}:{key_parent}:{key}" if key_parent else key + key_path = f"{root_key}{arrow}{key_parent}{arrow}{key}" if key_parent else key raise ConfigKeyError(config_file, key_path) return value @@ -40,14 +43,19 @@ class Config: root = _get(data, root_key) self.os = _get(root, self.os_name) - def get_os_value(self, key): - return _get(self.os, key, self.os_name) + def get_os_value(self, key, required=True, linux_distro=None): + if linux_distro: + # recurse with the linux distro as the key parameter to get the base distro key. + distro = self.get_os_value(key=linux_distro) + return _get(distro, key, f"{self.os_name}{arrow}{linux_distro}", required) + else: + return _get(self.os, key, self.os_name, required) def get_qt_config(self): qt_key = "qt" qt = self.get_os_deps_value(qt_key) - parent_key = f"{self.os_name}:{deps_key}" + parent_key = f"{self.os_name}{arrow}{deps_key}" mirror_url = _get(qt, "mirror", parent_key) version = _get(qt, "version", parent_key) base_dir = _get(qt, "base-dir", parent_key) @@ -55,26 +63,29 @@ class Config: return mirror_url, version, base_dir, modules - def get_os_deps_value(self, key): - deps = self.get_os_value(deps_key) - return _get(deps, key, f"{self.os_name}:{deps_key}") + def get_os_deps_value(self, key, required=True, linux_distro=None): + deps = self.get_os_value(deps_key, required, linux_distro) + if linux_distro: + key_parent = f"{self.os_name}{arrow}{linux_distro}{arrow}{deps_key}" + else: + key_parent = f"{self.os_name}{arrow}{deps_key}" + return _get(deps, key, key_parent, required) - def get_deps_command(self): - deps = self.get_os_value(deps_key) - command = _get(deps, "command", f"{self.os_name}:{deps_key}") - return cmd_utils.strip_continuation_sequences(command) + def get_os_deps_command(self, key=command_key, required=True, linux_distro=None): + command = self.get_os_deps_value(key, required, linux_distro) + if command: + return cmd_utils.strip_continuation_sequences(command) + else: + return None - def get_linux_deps_command(self, distro): - distro_data = self.get_os_value(distro) - deps = _get(distro_data, deps_key, f"{self.os_name}:{distro}") - command = _get(deps, "command", f"{self.os_name}:{distro}:{deps_key}") - return cmd_utils.strip_continuation_sequences(command) + def get_os_deps_command_pre(self, required=True, linux_distro=None): + return self.get_os_deps_command(command_pre_key, required, linux_distro) def get_windows_ci_config(self): choco_ci_key = "ci" choco_ci = self.get_os_deps_value(choco_ci_key) - choco_ci_path = f"{self.os_name}:{deps_key}:{choco_ci_key}" + choco_ci_path = f"{self.os_name}{arrow}{deps_key}{arrow}{choco_ci_key}" edit_config = _get(choco_ci, "edit-config", choco_ci_path) skip_packages = _get(choco_ci, "skip-packages", choco_ci_path) diff --git a/scripts/lib/env.py b/scripts/lib/env.py index 4f4883fc5..c783b6f0a 100644 --- a/scripts/lib/env.py +++ b/scripts/lib/env.py @@ -132,6 +132,13 @@ def install_requirements(): check_dependencies(raise_error=True) + print("Updating pip...") + cmd_utils.run( + [sys.executable, "-m", "pip", "install", "--upgrade", "pip"], + shell=False, + print_cmd=True, + ) + print("Installing required modules...") cmd_utils.run( [sys.executable, "-m", "pip", "install", "-e", "scripts"], @@ -182,7 +189,10 @@ def ensure_dependencies(): update_cmd = None install_cmd = None - if "debian" in distro_like: + if distro == "rhel" or "rhel" in distro_like: + update_cmd = "yum check-update" + install_cmd = "yum install -y python3-pip" # rhel-like has venv already + elif "debian" in distro_like: update_cmd = "apt update" install_cmd = "apt install -y python3-pip python3-venv" elif "fedora" in distro_like: diff --git a/scripts/lib/linux.py b/scripts/lib/linux.py index 5ac324b82..aecc6b384 100644 --- a/scripts/lib/linux.py +++ b/scripts/lib/linux.py @@ -16,6 +16,20 @@ package_name = "synergy" test_cmd = "synergys --version" +def run_command(command, check=True): + + has_sudo = cmd_utils.has_command("sudo") + if "sudo" in command and not has_sudo: + # assume we're running as root if sudo is not found (common on older distros). + # a space char is intentionally added after "sudo" for intentionality. + # possible limitation with stripping "sudo" is that if any packages with "sudo" in the + # name are added to the list (probably very unlikely), this will have undefined behavior. + print("The 'sudo' command was not found, stripping sudo from command") + command = command.replace("sudo ", "").strip() + + cmd_utils.run(command, check, shell=True, print_cmd=True) + + def package(filename_base, package_type: PackageType): extension, cmd = get_package_info(package_type)