Pastery

gh_release_install.py +

  1# @Author: Kristinita  2# @Date: 2025-03-17 20:26:53  3# @Last Modified by: Kristinita  4# @Last Modified time: 2025-10-30 20:08:44  5"""[OVERVIEW] Install binaries of non-Node and non-Python packages from GitHub releases.  6  7######################  8# gh-release-install #  9###################### 10[OVERVIEW] gh-release-install — Python CLI utility for installation data from GitHub releases. 11https://github.com/jooola/gh-release-install 12 13[PURPOSE] Amazing Grace is the Node.js + Python project, but it also uses dependencies 14that not possible to install use Node.js and Python. 15One of the main principles of Amazing Grace is simplicity. 16So that users don’t have to pre-install any dependencies except Git, Node.js and Python, 17I installed non-Node and non-Python CLI dependencies use gh-release-install. 18 19[INFO] gh-release-install save binaries from GitHub releases to the PATH directory of Pipenv virtual environment. 20To launch commands, the user should use the syntax “pipenv run command”, 21for example, “pipenv run fd” or “pipenv run tidy”. 22 23 24[NOTE] gh-release-install hasn’t configuration file, “github_release_install.py” script is required: 25https://github.com/jooola/gh-release-install/issues/212 26 27[NOTE] As of March 2025, I can’t find good cross-platform package manager for GitHub releases. 28“fetch-github-release” and “install-release” doesn’t support Windows: 29https://github.com/terascope/fetch-github-release/issues/355 30https://github.com/Rishang/install-release 31I can’t run “grab-github-release”: 32https://github.com/prantlf/grab-github-release/issues/2 33""" 34from pathlib import Path 35from subprocess import Popen 36from sys import exit as sysexit 37from sys import platform, stderr 38 39# [LEARN][PYTHON] “sys.platform” — check current operating system. 40# Windows always has the value “win32”, macOS — “darwin”, Linux — “linux”: 41# https://docs.python.org/3/library/sys.html#sys.platform 42KIRA_PLATFORM_MACOS = "darwin" 43KIRA_PLATFORM_WINDOWS = "win32" 44 45 46def kira_save_binaries_from_github_releases() -> None: 47    """[FUNCTION_DESCRIPTION] Save non-Node/non-Python binaries from GitHub releases into Pipenv virtual environment. 48 49    Steps: 50        1. Set gh-release-install commands. 51        2. Run gh-release-install commands. 52        3. Exit “github_release_install.py” with the same exit code as exit codes of gh-release-install commands. 53    """ 54    kira_current_os_is_windows = platform == KIRA_PLATFORM_WINDOWS 55    kira_current_os_is_macos = platform == KIRA_PLATFORM_MACOS 56 57    # [NOTE] Pipenv has different paths for executable binaries for Linux/macOS and Windows. 58    # “.venv/bin” — is the path for Linux and macOS, “.venv/Scripts” — the path for Windows. 59    kira_destination_path = ".venv/Scripts" if kira_current_os_is_windows else ".venv/bin" 60 61    # [PURPOSE] Save binaries from unofficial HTML Tidy 5.9.20 release: 62    # https://github.com/Kristinita/tidy-html5/releases/tag/5.9.20 63    # Release contains solely binaries, not archives. 64    # 65    # [TIDY][NOTE] I created my own HTML Tidy release, because Tidy is no longer maintained, 66    # and the latest official Tidy versions contains critical bug: 67    # https://github.com/Kristinita/tidy-html5#2-why-it-was-created 68    # 69    # 70    # [INFO] Linux and macOS CLI command: 71    # gh-release-install Kristinita/tidy-html5 tidy .venv/bin --verbose 72    # 73    # Windows CLI command: 74    # gh-release-install Kristinita/tidy-html5 tidy.exe .venv/Scripts --verbose 75    kira_tidy_repository = "Kristinita/tidy-html5" 76    kira_tidy_executable_file = "tidy.exe" if kira_current_os_is_windows else "tidy" 77 78    # [LEARN][PYTHON][PERFORMANCE] Indexing tuples is faster than indexing lists. 79    # Use tuples, not lists, if you don’t need to modify your list: 80    # https://github.com/tonybaloney/perflint#w8301--use-tuple-instead-of-list-for-a-non-mutated-sequence-use-tuple-over-list 81    kira_gh_release_install_command_for_tidy = ( 82        "pipenv", "run", 83        "gh-release-install", kira_tidy_repository, kira_tidy_executable_file, kira_destination_path, 84        "--verbose") 85 86    # [PURPOSE] Save binaries from the latest fd release: 87    # https://github.com/sharkdp/fd/releases 88    # Archives unpacking is required. 89    # 90    # 91    # [INFO] Linux CLI command: 92    # gh-release-install sharkdp/fd "fd-{tag}-x86_64-unknown-linux-gnu.tar.gz" 93    # --extract "fd-{tag}-x86_64-unknown-linux-gnu/fd" .venv/bin/fd --verbose 94    # 95    # [INFO] macOS CLI command: 96    # gh-release-install sharkdp/fd "fd-{tag}-x86_64-apple-darwin.tar.gz" 97    # --extract "fd-{tag}-x86_64-apple-darwin.tar.gz/fd" .venv/bin/fd --verbose 98    # 99    # [INFO] Windows CLI command:100    # gh-release-install sharkdp/fd fd-{tag}-x86_64-pc-windows-gnu.zip101    # --extract fd-{tag}-x86_64-pc-windows-gnu/fd.exe .venv/Scripts/fd.exe --verbose102    kira_fd_repository = "sharkdp/fd"103    kira_fd_executable_file = "fd"104105    if kira_current_os_is_windows:106        kira_fd_archive = "fd-{tag}-x86_64-pc-windows-gnu.zip"107        kira_fd_extract = "fd-{tag}-x86_64-pc-windows-gnu/fd.exe"108        kira_fd_executable_file = "fd.exe"109110    elif kira_current_os_is_macos:111        kira_fd_archive = "fd-{tag}-x86_64-apple-darwin.tar.gz"112        kira_fd_extract = "fd-{tag}-x86_64-apple-darwin/fd"113114    else:115        kira_fd_archive = "fd-{tag}-x86_64-unknown-linux-gnu.tar.gz"116        kira_fd_extract = "fd-{tag}-x86_64-unknown-linux-gnu/fd"117118    # [LEARN][PYTHON][REFACTORING] Use “Path()” object instead of “os.path.join” for joining strings:119    # https://github.com/dosisod/refurb/blob/master/docs/checks.md#furb147-no-path-join120    kira_gh_release_install_command_for_fd = (121        "pipenv", "run",122        "gh-release-install", kira_fd_repository, kira_fd_archive,123        "--extract", kira_fd_extract, Path(kira_destination_path, kira_fd_executable_file),124        "--verbose")125126    # [PURPOSE] Run gh-release-install commands127    #128    # [LEARN][PYTHON] “subprocess.call” a blocking function — it waits the execution of a subprocess by default,129    # “subprocess.Popen” — isn’t a blocking function.130    # https://stackoverflow.com/a/59615896/5951529131    #132    # “subprocess.check_output” also a blocking function:133    # https://stackoverflow.com/a/40766307/5951529134    #135    # “subprocess.Popen” required, “subprocess.call” and “subprocess.check_output”136    # don’t allow running subprocesses in parallel.137    #138    # [PYLINT][NOTE] Use “subprocess.Popen” with “with” keyword to avoid “R1732” Pylint warning:139    # https://pylint.pycqa.org/en/latest/user_guide/messages/refactor/consider-using-with.html140    with Popen(kira_gh_release_install_command_for_tidy) as kira_tidy_process, Popen(141            kira_gh_release_install_command_for_fd) as kira_fd_process:142143        # [PURPOSE][LEARN][PYTHON] Wait until subprocesses are finished and return “returncode”:144        # https://stackoverflow.com/a/15108096/5951529145        # https://docs.python.org/3/library/subprocess.html#subprocess.Popen.wait146        kira_tidy_process.wait()147        kira_fd_process.wait()148149        # [PURPOSE][NOTE] “github_release_install.py” exits with exit code 0, if we’re not processing exit codes.150        # Desired behavior — if “kira_tidy_process” and/or “kira_fd_process” exited with non-zero exit code,151        # “github_release_install” should also exit with non-zero exit code.152        # The code below realize this behavior.153        #154        # [LEARN][PYTHON] “returncode” — get exit code of a subprocess:155        # https://stackoverflow.com/a/5631819/5951529156        kira_tidy_exit_code = kira_tidy_process.returncode157        kira_fd_exit_code = kira_fd_process.returncode158159        if kira_tidy_exit_code != 0:160161            # [LEARN][PYTHON] Prefer “stderr.write()” or “stdout.write()” to “print()” in a production code:162            # https://stackoverflow.com/a/2570272/5951529163            # https://stackoverflow.com/a/3264118/5951529164            stderr.write(f"Error: Tidy installation failed with exit code {kira_tidy_exit_code}")165        if kira_fd_exit_code != 0:166            stderr.write(f"Error: Fd installation failed with exit code {kira_fd_exit_code}")167168        if kira_tidy_exit_code != 0 or kira_fd_exit_code != 0:169170            # [LEARN][PYTHON][NOTE] “sys.exit()”, not “exit()” should be used in real Python scripts:171            # https://stackoverflow.com/a/6501134/5951529172            # https://stackoverflow.com/a/19747557/5951529173            sysexit(1)174        else:175            sysexit(0)176177178kira_save_binaries_from_github_releases()
New paste