diff --git a/src/charm.py b/src/charm.py index 0b59f00f6..58fa6f52f 100755 --- a/src/charm.py +++ b/src/charm.py @@ -12,7 +12,7 @@ import shutil import urllib.error from pathlib import Path -from typing import TYPE_CHECKING, Callable, Dict, Optional, TypeVar +from typing import Any, Callable, Dict, Optional, TypeVar import jinja2 from ops.charm import ( @@ -36,9 +36,6 @@ from runner_type import GitHubOrg, GitHubRepo, ProxySetting, VirtualMachineResources from utilities import bytes_with_unit_to_kib, execute_command, get_env_var, retry -if TYPE_CHECKING: - from ops.model import JsonObject # type: ignore - logger = logging.getLogger(__name__) @@ -546,7 +543,7 @@ def _on_stop(self, _: StopEvent) -> None: # Log but ignore error since we're stopping anyway. logger.exception("Failed to clear runners") - def _reconcile_runners(self, runner_manager: RunnerManager) -> Dict[str, "JsonObject"]: + def _reconcile_runners(self, runner_manager: RunnerManager) -> Dict[str, Any]: """Reconcile the current runners state and intended runner state. Args: diff --git a/src/runner.py b/src/runner.py index 7467e92e7..90bd6a0e1 100644 --- a/src/runner.py +++ b/src/runner.py @@ -16,6 +16,7 @@ import logging import pathlib import time +from dataclasses import dataclass from pathlib import Path from typing import Iterable, Optional, Sequence @@ -40,6 +41,19 @@ LXD_PROFILE_YAML = LXD_PROFILE_YAML.parent / "lxd-profile.yml" +@dataclass +class WgetExecutable: + """The executable to be installed through wget. + + Args: + url: The URL of the executable binary. + cmd: Executable command name. E.g. yq_linux_amd64 -> yq + """ + + url: str + cmd: str + + class Runner: """Single instance of GitHub self-hosted runner. @@ -53,7 +67,7 @@ class Runner: busy (bool): Whether GitHub marks this runner as busy. """ - runner_application = Path("/opt/github-runner") + runner_application = Path("/home/ubuntu/github-runner") env_file = runner_application / ".env" config_script = runner_application / "config.sh" runner_script = runner_application / "start.sh" @@ -373,8 +387,15 @@ def _install_binary(self, binary: Path) -> None: # TEMP: Install common tools used in GitHub Actions. This will be removed once virtual # machines are created from custom images/GitHub runner image. - self._apt_install(["docker.io", "npm", "python3-pip", "shellcheck", "jq"]) - self._snap_install(["yq"]) + self._apt_install(["docker.io", "npm", "python3-pip", "shellcheck", "jq", "wget"]) + self._wget_install( + [ + WgetExecutable( + url="https://github.com/mikefarah/yq/releases/download/v4.34.1/yq_linux_amd64", + cmd="yq", + ) + ] + ) # Add the user to docker group. self.instance.execute(["/usr/sbin/usermod", "-aG", "docker", "ubuntu"]) @@ -599,18 +620,20 @@ def _apt_install(self, packages: Iterable[str]) -> None: logger.info("Installing %s via APT...", pkg) self.instance.execute(["/usr/bin/apt-get", "install", "-yq", pkg]) - def _snap_install(self, packages: Iterable[str]) -> None: - """Installs the given snap packages. + def _wget_install(self, executables: Iterable[WgetExecutable]) -> None: + """Installs the given binaries. This is a temporary solution to provide tools not offered by the base ubuntu image. Custom images based on the GitHub action runner image will be used in the future. Args: - packages: Packages to be install via snap. + executables: The executables to download. """ if self.instance is None: raise RunnerError("Runner operation called prior to runner creation.") - for pkg in packages: - logger.info("Installing %s via snap...", pkg) - self.instance.execute(["/usr/bin/snap", "install", pkg]) + for executable in executables: + executable_path = f"/usr/bin/{executable.cmd}" + logger.info("Downloading %s via wget to %s...", executable.url, executable_path) + self.instance.execute(["/usr/bin/wget", executable.url, "-O", executable_path]) + self.instance.execute(["/usr/bin/chmod", "+x", executable_path]) diff --git a/src/runner_manager.py b/src/runner_manager.py index 85b9e7d6e..460f2369c 100644 --- a/src/runner_manager.py +++ b/src/runner_manager.py @@ -75,7 +75,7 @@ class RunnerInfo: class RunnerManager: """Manage a group of runners according to configuration.""" - runner_bin_path = Path("/opt/github-runner-app") + runner_bin_path = Path("/home/ubuntu/github-runner-app") def __init__( self, diff --git a/templates/start.j2 b/templates/start.j2 index 7d5e4bdf5..7e6979ce5 100644 --- a/templates/start.j2 +++ b/templates/start.j2 @@ -1,3 +1,3 @@ #!/bin/bash -(/opt/github-runner/run.sh; sudo systemctl halt -i) &>/dev/null & +(/home/ubuntu/github-runner/run.sh; sudo systemctl halt -i) &>/dev/null & diff --git a/tests/unit/test_runner.py b/tests/unit/test_runner.py index e4f9bf71b..00bfc0392 100644 --- a/tests/unit/test_runner.py +++ b/tests/unit/test_runner.py @@ -100,7 +100,7 @@ def test_create( if runner.config.proxies: instance = instances[0] - env_proxy = instance.files.read_file("/opt/github-runner/.env") + env_proxy = instance.files.read_file("/home/ubuntu/github-runner/.env") systemd_docker_proxy = instance.files.read_file( "/etc/systemd/system/docker.service.d/http-proxy.conf" )