TITLE: Install gha_runner Python Library DESCRIPTION: This command installs the `gha_runner` library from PyPI, allowing you to use its functionalities for managing GitHub Action runners. SOURCE: https://gha-runner.readthedocs.io/en/latest/index LANGUAGE: Shell CODE: ``` pip install gha-runner ``` ---------------------------------------- TITLE: GitHub Actions Workflow for AWS Self-Hosted Runner Lifecycle DESCRIPTION: This YAML workflow demonstrates how to provision, use, and de-provision self-hosted GitHub Actions runners on AWS. It includes steps to start an EC2 instance using `omsf/start-aws-gha-runner`, run tests on the provisioned runner, and then stop the instance using `omsf/stop-aws-gha-runner`, ensuring proper cleanup and credential management via AWS OIDC. SOURCE: https://gha-runner.readthedocs.io/en/latest/aws/index LANGUAGE: YAML CODE: ``` name: Test Self-Hosted Runner on: workflow_dispatch: jobs: start-aws-runner: runs-on: ubuntu-latest permissions: id-token: write contents: read outputs: mapping: ${{ steps.aws-start.outputs.mapping }} instances: ${{ steps.aws-start.outputs.instances }} steps: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: aws-region: - name: Create cloud runner id: aws-start uses: omsf/start-aws-gha-runner@v1.0.0 with: aws_image_id: aws_instance_type: aws_home_dir: /home/ubuntu env: GH_PAT: ${{ secrets.GH_PAT }} self-hosted-test: runs-on: ${{ fromJSON(needs.start-aws-runner.outputs.instances) }} # This ensures that you only run on the instances you just provisioned needs: - start-aws-runner steps: - uses: actions/checkout@v4 - name: Print disk usage run: "df -h" - name: Print Docker details run: "docker version || true" stop-aws-runner: runs-on: ubuntu-latest permissions: id-token: write contents: read needs: - start-aws-runner - self-hosted-test if: ${{ always() }} steps: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: aws-region: - name: Stop instances uses: omsf/stop-aws-gha-runner@v1.0.0 with: instance_mapping: ${{ needs.start-aws-runner.outputs.mapping }} env: GH_PAT: ${{ secrets.GH_PAT }} ``` ---------------------------------------- TITLE: Example Usage of EnvVarBuilder for Environment Variable Parsing DESCRIPTION: Demonstrates how to initialize `EnvVarBuilder` with environment variables and use its fluent interface (`with_var` and `build`) to parse and transform string values into a structured dictionary, including type conversion and JSON parsing. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/helper/input/index LANGUAGE: python CODE: ``` >>> env = {"MY_VAR": "123", "JSON_VAR": '{"key": "value"}'} >>> builder = EnvVarBuilder(env) >>> result = (builder ... .with_var("MY_VAR", "my_key", type_hint=int) ... .with_var("JSON_VAR", "json_key", is_json=True) ... .build()) >>> # result = {"my_key": 123, "json_key": {"key": "value"}} ``` ---------------------------------------- TITLE: Stop GitHub Actions Runner Instances Function DESCRIPTION: This snippet details the `stop_runner_instances` function, which is responsible for stopping GitHub Actions runner instances and waiting for their complete removal. It includes steps for removing runners from GitHub, terminating cloud instances, and robust error handling for various scenarios like missing runners or instance removal failures. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: Python CODE: ``` stop_runner_instances() ``` LANGUAGE: Python CODE: ``` def stop_runner_instances(self): """Stop the runner instances. This function stops the runner instances and waits for them to be removed. """ print("Shutting down...") try: # Get the instance mapping from our input mappings = self.provider.get_instance_mapping() except Exception as e: error(title="Malformed instance mapping", message=e) exit(1) # Remove the runners and instances print("Removing GitHub Actions Runner") instance_ids = list(mappings.keys()) labels = list(mappings.values()) for label in labels: try: print(f"Removing runner {label}") self.gh.remove_runner(label) # This occurs when we have a runner that might already be shutdown. # Since we are mainly using the ephemeral runners, we expect this to happen except MissingRunnerLabel: print(f"Runner {label} does not exist, skipping...") continue # This is more of the case when we have a failure to remove the runner # This is not a concern for the user (because we will remove the instance anyways), # but we should log it for debugging purposes. except Exception as e: warning(title="Failed to remove runner", message=e) print("Removing instances...") self.provider.remove_instances(instance_ids) print("Waiting for instance to be removed...") try: self.provider.wait_until_removed(instance_ids) except Exception as e: # Print to stdout print( f"Failed to remove instances check your provider console: {e}" ) # Print to Annotations error( title="Failed to remove instances, check your provider console", message=e, ) exit(1) else: print("Instances removed!") ``` ---------------------------------------- TITLE: Define AWS IAM Policy for GitHub Actions Runner DESCRIPTION: This JSON policy grants the necessary permissions for an IAM entity to manage EC2 instances, specifically allowing actions like running, terminating, and describing instances and images. This policy is essential for the GitHub Actions runner to dynamically provision and deprovision EC2 instances. SOURCE: https://gha-runner.readthedocs.io/en/latest/aws/index LANGUAGE: JSON CODE: ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:RunInstances", "ec2:TerminateInstances", "ec2:DescribeInstances", "ec2:DescribeInstanceStatus", "ec2:DescribeImages" ], "Resource": "*" } ] } ``` ---------------------------------------- TITLE: Python: Implementation of start_runner_instances Method DESCRIPTION: Python implementation of the `start_runner_instances` method within the `DeployInstance` class. This method orchestrates the creation, readiness check, and GitHub registration of cloud-based GitHub Actions runners. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: Python CODE: ``` def start_runner_instances(self): """Start the runner instances. This function starts the runner instances and waits for them to be ready. """ print("Starting up...") # Create a GitHub instance print("Creating GitHub Actions Runner") mappings = self.provider.create_instances() instance_ids = list(mappings.keys()) github_labels = list(mappings.values()) # Output the instance mapping and labels so the stop action can use them self.provider.set_instance_mapping(mappings) # Wait for the instance to be ready print("Waiting for instance to be ready...") self.provider.wait_until_ready(instance_ids) print("Instance is ready!") # Confirm the runner is registered with GitHub for label in github_labels: print(f"Waiting for {label}...") self.gh.wait_for_runner(label, self.timeout) ``` ---------------------------------------- TITLE: Define Abstract Base Class for Stopping Cloud Instances (Python) DESCRIPTION: Defines the `StopCloudInstance` abstract base class, outlining the interface for managing the lifecycle of cloud instances, specifically for removal operations. It includes abstract methods for removing instances, waiting for their removal, and retrieving instance mappings. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: python CODE: ``` class StopCloudInstance(ABC): """Abstract base class for stopping a cloud instance. This class defines the interface for stopping a cloud instance. """ @abstractmethod def remove_instances(self, ids: list[str]): """Remove instances from the cloud provider. Parameters ---------- ids : list[str] A list of instance IDs to remove. """ raise NotImplementedError @abstractmethod def wait_until_removed(self, ids: list[str], **kwargs): """Wait until instances are removed. Parameters ---------- ids : list[str] A list of instance IDs to wait for. **kwargs : dict, optional Additional arguments to pass to the waiter. """ raise NotImplementedError @abstractmethod def get_instance_mapping(self) -> dict[str, str]: """Get the instance mapping from the environment. Returns ------- dict[str, str] A dictionary of instance IDs and their corresponding github runner labels. """ raise NotImplementedError ``` ---------------------------------------- TITLE: Set an Output Variable in GitHub Actions Workflow DESCRIPTION: This function sets an output variable that can be consumed by subsequent steps or jobs within the same GitHub Actions workflow. It appends the specified name-value pair to the GITHUB_OUTPUT environment file, making the variable accessible. This is essential for passing data between different parts of a workflow. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/helper/workflow_cmds/index LANGUAGE: APIDOC CODE: ``` output(name: str, value: str) ``` LANGUAGE: Python CODE: ``` def output(name: str, value: str): with open(os.environ["GITHUB_OUTPUT"], "a") as output: output.write(f"{name}={value}\n") ``` ---------------------------------------- TITLE: Retrieve All Self-Hosted GitHub Runners DESCRIPTION: Fetches a paginated list of all self-hosted runners configured for a GitHub repository. It handles pagination automatically, retrieves runner details, and constructs `SelfHostedRunner` objects from the API response. Raises `RunnerListError` on API or response parsing issues. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` get_runners() -> list[SelfHostedRunner] | None Returns: list[SelfHostedRunner] | None A list of self-hosted runners in the repository if they exist, otherwise None. Raises: RunnerListError If there is an error getting the list of runners. Either because of an error in the request or the response is not a mapping object. ``` LANGUAGE: Python CODE: ``` def get_runners(self) -> list[SelfHostedRunner] | None: runners = [] per_page = 30 # GH API default page = 1 total_runners = float("inf") # paginate through the pages until we have all the runners while (len(runners) < total_runners): try: res = self.get(f"repos/{self.repo}/actions/runners?per_page={per_page}&page={page}") # This allows for arbitrary mappable objects to be used if not isinstance(res, collections.abc.Mapping): # This could be related to the API or the request itself. # ie the response is not a JSON object raise RunnerListError(f"Did not receive mapping object: {res}") total_runners = res["total_count"] page += 1 # protect from bug/issue where total_count is higher than actual # of runners if len(res["runners"]) < 1: break for runner in res["runners"]: id = runner["id"] name = runner["name"] os = runner["os"] labels = [label["name"] for label in runner["labels"]] runners.append(SelfHostedRunner(id, name, os, labels)) except RuntimeError as e: # This occurs when we receive a status code is > 400 raise RunnerListError(f"Error getting runners: {e}") # Other exceptions are bubbled up to the caller return runners if len(runners) > 0 else None ``` ---------------------------------------- TITLE: Define Abstract Base Class for Cloud Instance Management DESCRIPTION: This abstract base class (`CreateCloudInstance`) defines the interface for managing cloud instances, including methods for creation, readiness checks, and mapping instance IDs to GitHub runner labels. Implementations must provide concrete logic for these operations. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: Python CODE: ``` class CreateCloudInstance(ABC): """Abstract base class for starting a cloud instance. This class defines the interface for starting a cloud instance. """ @abstractmethod def create_instances(self) -> dict[str, str]: """Create instances in the cloud provider and return their IDs. The number of instances to create is defined by the implementation. Returns ------- dict[str, str] A dictionary of instance IDs and their corresponding github runner labels. """ raise NotImplementedError @abstractmethod def wait_until_ready(self, ids: list[str], **kwargs): """Wait until instances are in a ready state. Parameters ---------- ids : list[str] A list of instance IDs to wait for. **kwargs : dict, optional Additional arguments to pass to the waiter. """ raise NotImplementedError @abstractmethod def set_instance_mapping(self, mapping: dict[str, str]): """Set the instance mapping in the environment. Parameters ---------- mapping : dict[str, str] A dictionary of instance IDs and their corresponding github runner labels. """ raise NotImplementedError ``` ---------------------------------------- TITLE: Python Implementation of GitHubInstance Class DESCRIPTION: Full Python source code for the `GitHubInstance` class, including its constructor, helper methods for API requests (`_headers`, `_do_request`), and public methods for generating runner tokens (`create_runner_tokens`, `create_runner_token`) and making HTTP requests (`post`, `get`, `delete`). This class facilitates interaction with the GitHub API for repository management. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: python CODE: ``` class GitHubInstance: """Class to manage GitHub repository actions through the GitHub API. Parameters ---------- token : str GitHub API token for authentication. repo : str Full name of the GitHub repository in the format "owner/repo". Attributes ---------- headers : dict Headers for HTTP requests to GitHub API. github : Github Instance of Github object for interacting with the GitHub API. """ BASE_URL = "https://api.github.com" def __init__(self, token: str, repo: str): self.token = token self.headers = self._headers({}) self.repo = repo def _headers(self, header_kwargs): """Generate headers for API requests, adding authorization and specific API version. Can be removed if this is added into PyGitHub. Parameters ---------- header_kwargs : dict Additional headers to include in the request. Returns ------- dict Headers including authorization, API version, and any additional headers. """ headers = { "Authorization": f"Bearer {self.token}", "X-Github-Api-Version": "2022-11-28", "Accept": "application/vnd.github+json", } headers.update(header_kwargs) return headers def _do_request(self, func, endpoint, **kwargs): """Make a request to the GitHub API. This can be removed if this is added into PyGitHub. """ endpoint_url = urllib.parse.urljoin(self.BASE_URL, endpoint) headers = self.headers resp: requests.Response = func(endpoint_url, headers=headers, **kwargs) if not resp.ok: raise RuntimeError( f"Error in API call for {endpoint_url}: " f"{resp.content}" ) else: try: return resp.json() except JSONDecodeError: return resp.content def create_runner_tokens(self, count: int) -> list[str]: """Generate registration tokens for GitHub Actions runners. This can be removed if this is added into PyGitHub. Parameters ---------- count : int The number of runner tokens to generate. Returns ------- list[str] A list of runner registration tokens. Raises ------ TokenCreationError If there is an error generating the tokens. """ tokens = [] for _ in range(count): token = self.create_runner_token() tokens.append(token) return tokens def create_runner_token(self) -> str: """Generate a registration token for GitHub Actions runners. This can be removed if this is added into PyGitHub. Returns ------- str A runner registration token. Raises ------ TokenRetrievalError If there is an error generating the token. """ try: res = self.post( f"repos/{self.repo}/actions/runners/registration-token" ) return res["token"] except Exception as e: raise TokenRetrievalError(f"Error creating runner token: {e}") def post(self, endpoint, **kwargs): """Make a POST request to the GitHub API. This can be removed if this is added into PyGitHub. Parameters ---------- endpoint : str The endpoint to make the request to. **kwargs : dict, optional Additional keyword arguments to pass to the request. See the requests.post documentation for more information. """ return self._do_request(requests.post, endpoint, **kwargs) def get(self, endpoint, **kwargs): """Make a GET request to the GitHub API. Parameters ---------- endpoint : str The endpoint to make the request to. **kwargs : dict, optional Additional keyword arguments to pass to the request. See the requests.get documentation for more information. """ return self._do_request(requests.get, endpoint, **kwargs) def delete(self, endpoint, **kwargs): """Make a DELETE request to the GitHub API. Parameters ---------- endpoint : str ``` ---------------------------------------- TITLE: Update Builder State with a Single Parameter DESCRIPTION: This function updates the state of an `EnvVarBuilder` by parsing a single environment variable parameter. It supports JSON parsing and type conversion, with options to allow empty strings. It returns the builder instance for method chaining and raises `ValueError` on parsing failures. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/helper/input/index LANGUAGE: APIDOC CODE: ``` update_state(var_name: str, key: str, is_json: bool = False, allow_empty: bool = False, type_hint: Type = str) -> EnvVarBuilder Returns: - `EnvVarBuilder` – Returns self for method chaining Raises: - `ValueError` – If any configured environment variable parsing fails Notes: - Empty strings are ignored by default unless allow_empty is True - JSON parsing is performed before type conversion if is_json is True ``` LANGUAGE: python CODE: ``` def update_state( self, var_name: str, key: str, is_json: bool = False, allow_empty: bool = False, type_hint: Type = str, ) -> "EnvVarBuilder": """Update the state of the builder with a single parameter. Returns ------- EnvVarBuilder Returns self for method chaining Raises ------ ValueError If any configured environment variable parsing fails Notes ----- - Empty strings are ignored by default unless allow_empty is True - JSON parsing is performed before type conversion if is_json is True """ config = ParamConfig(var_name, key, is_json, allow_empty, type_hint) self._parse_single_param(config) return self ``` ---------------------------------------- TITLE: Python Implementation of TeardownInstance Class DESCRIPTION: The complete Python source code for the `TeardownInstance` class, demonstrating its constructor, `__post_init__` method for provider initialization, and `stop_runner_instances` method for orchestrating the shutdown of GitHub runners and cloud instances. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: Python CODE: ``` @dataclass class TeardownInstance: """Class that is used to teardown instances and runners. Parameters ---------- provider_type : Type[StopCloudInstance] The type of cloud provider to use. cloud_params : dict The parameters to pass to the cloud provider. gh : GitHubInstance The GitHub instance to use. Attributes ---------- provider : StopCloudInstance The cloud provider instance provider_type : Type[StopCloudInstance] cloud_params : dict gh : GitHub """ provider_type: Type[StopCloudInstance] cloud_params: dict gh: GitHubInstance provider: StopCloudInstance = field(init=False) def __post_init__(self): """Initialize the cloud provider. This function is called after the object is created to correctly stop the provider. """ self.provider = self.provider_type(**self.cloud_params) def stop_runner_instances(self): """Stop the runner instances. This function stops the runner instances and waits for them to be removed. """ print("Shutting down...") try: # Get the instance mapping from our input mappings = self.provider.get_instance_mapping() except Exception as e: error(title="Malformed instance mapping", message=e) exit(1) # Remove the runners and instances print("Removing GitHub Actions Runner") instance_ids = list(mappings.keys()) labels = list(mappings.values()) for label in labels: try: print(f"Removing runner {label}") self.gh.remove_runner(label) # This occurs when we have a runner that might already be shutdown. # Since we are mainly using the ephemeral runners, we expect this to happen except MissingRunnerLabel: print(f"Runner {label} does not exist, skipping...") continue # This is more of the case when we have a failure to remove the runner # This is not a concern for the user (because we will remove the instance anyways), # but we should log it for debugging purposes. except Exception as e: warning(title="Failed to remove runner", message=e) print("Removing instances...") self.provider.remove_instances(instance_ids) print("Waiting for instance to be removed...") try: self.provider.wait_until_removed(instance_ids) except Exception as e: # Print to stdout print( f"Failed to remove instances check your provider console: {e}" ) # Print to Annotations error( title="Failed to remove instances, check your provider console", message=e, ) exit(1) else: print("Instances removed!") ``` ---------------------------------------- TITLE: Check for Required Environment Variables DESCRIPTION: This function validates if a list of specified environment variables are present in the provided environment dictionary. It raises a `ValueError` if any of the required variables are missing. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/helper/input/index LANGUAGE: APIDOC CODE: ``` check_required(env: Dict[str, str], required: list[str]) Parameters: - `env` (`Dict[str, str]`) – The environment variables. - `required` (`list[str]`) – A list of required environment variables. Raises: - `ValueError` – If any required environment variables are missing. ``` LANGUAGE: python CODE: ``` def check_required(env: Dict[str, str], required: list[str]): """Check if required environment variables are set. Parameters ---------- env : Dict[str, str] The environment variables. required : list[str] A list of required environment variables. Raises ------ ValueError If any required environment variables are missing. """ missing = [var for var in required if not env.get(var)] if missing: raise ValueError(f"Missing required environment variables: {missing}") ``` ---------------------------------------- TITLE: API Reference and Implementation for wait_until_ready DESCRIPTION: This abstract method blocks execution until a given list of cloud instances transitions into a ready state. It supports additional keyword arguments for custom waiting behavior. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: APIDOC CODE: ``` wait_until_ready(ids: list[str], **kwargs) Parameters: ids (list[str]) - A list of instance IDs to wait for. **kwargs (dict, default: {}) - Additional arguments to pass to the waiter. ``` LANGUAGE: Python CODE: ``` @abstractmethod def wait_until_ready(self, ids: list[str], **kwargs): """Wait until instances are in a ready state. Parameters ---------- ids : list[str] A list of instance IDs to wait for. **kwargs : dict, optional Additional arguments to pass to the waiter. """ raise NotImplementedError ``` ---------------------------------------- TITLE: API Reference and Implementation for create_instances DESCRIPTION: This abstract method is responsible for creating new cloud instances and returning a dictionary of their IDs mapped to GitHub runner labels. The specific number of instances created is determined by the concrete implementation of the `CreateCloudInstance` class. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: APIDOC CODE: ``` create_instances() -> dict[str, str] Returns: dict[str, str] - A dictionary of instance IDs and their corresponding github runner labels. ``` LANGUAGE: Python CODE: ``` @abstractmethod def create_instances(self) -> dict[str, str]: """Create instances in the cloud provider and return their IDs. The number of instances to create is defined by the implementation. Returns ------- dict[str, str] A dictionary of instance IDs and their corresponding github runner labels. """ raise NotImplementedError ``` ---------------------------------------- TITLE: Generate Multiple GitHub Actions Runner Registration Tokens DESCRIPTION: Offers a method to generate a specified count of registration tokens for GitHub Actions runners. This is useful for bulk registration of self-hosted runners. It includes both the API signature and the Python implementation. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` create_runner_tokens(count: int) -> list[str] Generate registration tokens for GitHub Actions runners. This can be removed if this is added into PyGitHub. Parameters: - **`count`** (`int`) – The number of runner tokens to generate. Returns: - `list[str]` – A list of runner registration tokens. Raises: - `TokenCreationError` – If there is an error generating the tokens. ``` LANGUAGE: python CODE: ``` def create_runner_tokens(self, count: int) -> list[str]: """Generate registration tokens for GitHub Actions runners. This can be removed if this is added into PyGitHub. Parameters ---------- count : int The number of runner tokens to generate. Returns ------- list[str] A list of runner registration tokens. Raises ------- TokenCreationError If there is an error generating the tokens. """ tokens = [] for _ in range(count): token = self.create_runner_token() tokens.append(token) return tokens ``` ---------------------------------------- TITLE: List All GitHub Actions Self-Hosted Runners (Python) DESCRIPTION: Fetches a comprehensive list of all self-hosted GitHub Actions runners configured for the repository. The function handles pagination to ensure all runners are retrieved and raises an error if the API response is malformed or an issue occurs during the request. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` get_runners() -> list[SelfHostedRunner] | None Description: Get a list of self-hosted runners in the repository. Returns: list[SelfHostedRunner] | None: A list of self-hosted runners in the repository if they exist, otherwise None. Raises: RunnerListError: If there is an error getting the list of runners. Either because of an error in the request or the response is not a mapping object. ``` LANGUAGE: Python CODE: ``` def get_runners(self) -> list[SelfHostedRunner] | None: """Get a list of self-hosted runners in the repository. Returns ------- list[SelfHostedRunner] | None A list of self-hosted runners in the repository if they exist, otherwise None. Raises ------ RunnerListError If there is an error getting the list of runners. Either because of an error in the request or the response is not a mapping object. """ runners = [] per_page = 30 # GH API default page = 1 total_runners = float("inf") # paginate through the pages until we have all the runners while (len(runners) < total_runners): try: res = self.get(f"repos/{self.repo}/actions/runners?per_page={per_page}&page={page}") # This allows for arbitrary mappable objects to be used if not isinstance(res, collections.abc.Mapping): # This could be related to the API or the request itself. # ie the response is not a JSON object raise RunnerListError(f"Did not receive mapping object: {res}") total_runners = res["total_count"] page += 1 # protect from bug/issue where total_count is higher than actual # of runners if len(res["runners"]) < 1: break for runner in res["runners"]: id = runner["id"] name = runner["name"] os = runner["os"] labels = [label["name"] for label in runner["labels"]] runners.append(SelfHostedRunner(id, name, os, labels)) except RuntimeError as e: # This occurs when we receive a status code is > 400 raise RunnerListError(f"Error getting runners: {e}") # Other exceptions are bubbled up to the caller return runners if len(runners) > 0 else None ``` ---------------------------------------- TITLE: Generate Single GitHub Actions Runner Registration Token DESCRIPTION: Provides functionality to generate a single registration token for GitHub Actions runners. This token is used to register a self-hosted runner with GitHub. It includes both the API signature and the Python implementation. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` create_runner_token() -> str Generate a registration token for GitHub Actions runners. This can be removed if this is added into PyGitHub. Returns: - `str` – A runner registration token. Raises: - `TokenRetrievalError` – If there is an error generating the token. ``` LANGUAGE: python CODE: ``` def create_runner_token(self) -> str: """Generate a registration token for GitHub Actions runners. This can be removed if this is added into PyGitHub. Returns ------- str A runner registration token. Raises ------ TokenRetrievalError If there is an error generating the token. """ try: res = self.post( f"repos/{self.repo}/actions/runners/registration-token" ) return res["token"] except Exception as e: raise TokenRetrievalError(f"Error creating runner token: {e}") ``` ---------------------------------------- TITLE: Perform a DELETE Request to GitHub API DESCRIPTION: Executes a DELETE request to a specified GitHub API endpoint, passing additional keyword arguments to the underlying `requests.delete` call. This method is typically used for resource removal. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` delete(endpoint: str, **kwargs) endpoint: str The endpoint to make the request to. **kwargs: dict, optional Additional keyword arguments to pass to the request. See the requests.delete documentation for more information. ``` LANGUAGE: Python CODE: ``` def delete(self, endpoint: str, **kwargs): return self._do_request(requests.delete, endpoint, **kwargs) ``` ---------------------------------------- TITLE: GitHub API: Make DELETE Request DESCRIPTION: This function sends a DELETE request to a specified GitHub API endpoint. It supports additional keyword arguments for customizing the request, which are passed directly to `requests.delete`. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` delete(endpoint, **kwargs) Make a DELETE request to the GitHub API. Parameters: endpoint (str): The endpoint to make the request to. **kwargs (dict, default: {}): Additional keyword arguments to pass to the request. See the requests.delete documentation for more information. ``` LANGUAGE: Python CODE: ``` def delete(self, endpoint, **kwargs): """Make a DELETE request to the GitHub API. Parameters ---------- endpoint : str The endpoint to make the request to. **kwargs : dict, optional Additional keyword arguments to pass to the request. See the requests.delete documentation for more information. """ return self._do_request(requests.delete, endpoint, **kwargs) ``` ---------------------------------------- TITLE: Remove Cloud Instances from Provider DESCRIPTION: Defines the interface and documentation for removing specified cloud instances from the cloud provider. This operation is fundamental for cleaning up resources after use. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: APIDOC CODE: ``` remove_instances(ids: list[str]) Parameters: ids (list[str]) – A list of instance IDs to remove. ``` LANGUAGE: python CODE: ``` @abstractmethod def remove_instances(self, ids: list[str]): """Remove instances from the cloud provider. Parameters ---------- ids : list[str] A list of instance IDs to remove. """ raise NotImplementedError ``` ---------------------------------------- TITLE: GitHub API: Make GET Request DESCRIPTION: This function sends a GET request to a specified GitHub API endpoint. It allows passing additional keyword arguments for customizing the request, which are forwarded to `requests.get`. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` get(endpoint, **kwargs) Make a GET request to the GitHub API. Parameters: endpoint (str): The endpoint to make the request to. **kwargs (dict, default: {}): Additional keyword arguments to pass to the request. See the requests.get documentation for more information. ``` LANGUAGE: Python CODE: ``` def get(self, endpoint, **kwargs): """Make a GET request to the GitHub API. Parameters ---------- endpoint : str The endpoint to make the request to. **kwargs : dict, optional Additional keyword arguments to pass to the request. See the requests.get documentation for more information. """ return self._do_request(requests.get, endpoint, **kwargs) ``` ---------------------------------------- TITLE: Make a POST Request to GitHub API (Python) DESCRIPTION: Performs a POST request to a specified GitHub API endpoint. This utility function wraps the underlying HTTP request mechanism and can be extended or replaced if similar functionality becomes available in the PyGitHub library. It accepts additional keyword arguments to customize the request. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` post(endpoint, **kwargs) Description: Make a POST request to the GitHub API. Parameters: endpoint (str): The endpoint to make the request to. **kwargs (dict, default: {}): Additional keyword arguments to pass to the request. See the requests.post documentation for more information. ``` LANGUAGE: Python CODE: ``` def post(self, endpoint, **kwargs): """Make a POST request to the GitHub API. This can be removed if this is added into PyGitHub. Parameters ---------- endpoint : str The endpoint to make the request to. **kwargs : dict, optional Additional keyword arguments to pass to the request. See the requests.post documentation for more information. """ return self._do_request(requests.post, endpoint, **kwargs) ``` ---------------------------------------- TITLE: Remove a Self-Hosted GitHub Runner by Label DESCRIPTION: Deletes a self-hosted runner from the repository using its label. It first retrieves the runner's ID via `get_runner` and then makes a DELETE request to the GitHub API. Raises `RuntimeError` if the runner cannot be found or if an error occurs during removal. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` remove_runner(label: str) Parameters: label: str The label of the runner to remove. Raises: RuntimeError If there is an error removing the runner or the runner is not found. ``` LANGUAGE: Python CODE: ``` def remove_runner(self, label: str): runner = self.get_runner(label) try: self.delete(f"repos/{self.repo}/actions/runners/{runner.id}") except Exception as e: raise RuntimeError(f"Error removing runner {label}. Error: {e}") ``` ---------------------------------------- TITLE: Wait for Cloud Instances to be Removed DESCRIPTION: Provides methods and documentation for synchronously waiting until a list of specified cloud instances have been successfully removed from the cloud provider, with support for additional waiter arguments. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: APIDOC CODE: ``` wait_until_removed(ids: list[str], **kwargs) Parameters: ids (list[str]) – A list of instance IDs to wait for. **kwargs (dict, default: {}) – Additional arguments to pass to the waiter. ``` LANGUAGE: python CODE: ``` @abstractmethod def wait_until_removed(self, ids: list[str], **kwargs): """Wait until instances are removed. Parameters ---------- ids : list[str] A list of instance IDs to wait for. **kwargs : dict, optional Additional arguments to pass to the waiter. """ raise NotImplementedError ``` ---------------------------------------- TITLE: GitHub Actions Runner: Generate Random Label DESCRIPTION: This static method generates a unique, random label for a GitHub Actions runner. The label follows the format 'runner-', where the random string is 8 characters long and consists of lowercase letters and digits. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` generate_random_label() -> str Generate a random label for a runner. Returns: str: A random label for a runner. The label is in the format "runner-". The random string is 8 characters long and consists of lowercase letters and digits. ``` LANGUAGE: Python CODE: ``` @staticmethod def generate_random_label() -> str: """Generate a random label for a runner. Returns ------- str A random label for a runner. The label is in the format "runner-". The random string is 8 characters long and consists of lowercase letters and digits. """ letters = string.ascii_lowercase + string.digits result_str = "".join(random.choice(letters) for i in range(8)) return f"runner-{result_str}" ``` ---------------------------------------- TITLE: Manage GitHub Actions Runner Labels and Releases DESCRIPTION: This snippet contains Python functions for generating unique runner labels and retrieving the latest GitHub Actions runner release assets based on platform and architecture. It includes helper methods for fetching general repository releases. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: python CODE: ``` letters = string.ascii_lowercase + string.digits result_str = "".join(random.choice(letters) for i in range(8)) return f"runner-{result_str}" def _get_latest_release(self, repo: str) -> dict: """Get the latest release for a repository. Parameters ---------- repo : str The repository to get the latest release for. Returns ------- str The tag name of the latest release. """ try: release = self.get(f"repos/{repo}/releases/latest") return release except Exception as e: raise RuntimeError(f"Error getting latest release: {e}") def get_latest_runner_release( self, platform: str, architecture: str ) -> str: """Return the latest runner for the given platform and architecture. Parameters ---------- platform : str The platform of the runner to download. architecture : str The architecture of the runner to download. Returns ------- str The download URL of the runner. Raises ------ RuntimeError If the runner is not found for the given platform and architecture. ValueError If the platform or architecture is not supported. """ repo = "actions/runner" supported_platforms = {"linux": ["x64", "arm", "arm64"]} if platform not in supported_platforms: raise ValueError( f"Platform '{platform}' not supported. " f"Supported platforms are {list(supported_platforms)}" ) if architecture not in supported_platforms[platform]: raise ValueError( f"Architecture '{architecture}' not supported for platform '{platform}'. " f"Supported architectures are {supported_platforms[platform]}" ) release = self._get_latest_release(repo) assets = release["assets"] for asset in assets: if platform in asset["name"] and architecture in asset["name"]: return asset["browser_download_url"] raise RuntimeError( f"Runner release not found for platform {platform} and architecture {architecture}" ) ``` ---------------------------------------- TITLE: Python: Implement remove_runner Method DESCRIPTION: Python implementation for removing a GitHub Actions runner. It retrieves the runner by label and then calls the GitHub API to delete it, handling potential errors by raising a `RuntimeError`. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: Python CODE: ``` def remove_runner(self, label: str): """Remove a runner by a given label. Parameters ---------- label : str The label of the runner to remove. Raises ------ RuntimeError If there is an error removing the runner or the runner is not found. """ runner = self.get_runner(label) try: self.delete(f"repos/{self.repo}/actions/runners/{runner.id}") except Exception as e: raise RuntimeError(f"Error removing runner {label}. Error: {e}") ``` ---------------------------------------- TITLE: Generate a Random Label for a GitHub Runner DESCRIPTION: A static method that generates a unique random string suitable for use as a self-hosted runner label. This can be used to ensure new runners have distinct identifiers. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` generate_random_label() -> str Returns: str ``` LANGUAGE: Python CODE: ``` @staticmethod def generate_random_label() -> str: """Generate a random label for a runner. Returns ------- str """ ``` ---------------------------------------- TITLE: GitHub Actions Runner: Get Latest Release URL DESCRIPTION: This function retrieves the download URL for the latest GitHub Actions runner release, based on the specified platform and architecture. It validates the provided platform and architecture against supported values and raises errors if the runner is not found or inputs are invalid. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` get_latest_runner_release(platform: str, architecture: str) -> str Return the latest runner for the given platform and architecture. Parameters: platform (str): The platform of the runner to download. architecture (str): The architecture of the runner to download. Returns: str: The download URL of the runner. Raises: RuntimeError: If the runner is not found for the given platform and architecture. ValueError: If the platform or architecture is not supported. ``` LANGUAGE: Python CODE: ``` def get_latest_runner_release( self, platform: str, architecture: str ) -> str: """Return the latest runner for the given platform and architecture. Parameters ---------- platform : str The platform of the runner to download. architecture : str The architecture of the runner to download. Returns ------- str The download URL of the runner. Raises ------ RuntimeError If the runner is not found for the given platform and architecture. ValueError If the platform or architecture is not supported. """ repo = "actions/runner" supported_platforms = {"linux": ["x64", "arm", "arm64"]} if platform not in supported_platforms: raise ValueError( f"Platform '{platform}' not supported. " f"Supported platforms are {list(supported_platforms)}" ) if architecture not in supported_platforms[platform]: raise ValueError( f"Architecture '{architecture}' not supported for platform '{platform}'. " f"Supported architectures are {supported_platforms[platform]}" ) release = self._get_latest_release(repo) assets = release["assets"] for asset in assets: if platform in asset["name"] and architecture in asset["name"]: return asset["browser_download_url"] raise RuntimeError( f"Runner release not found for platform {platform} and architecture {architecture}" ) ``` ---------------------------------------- TITLE: Get a GitHub Actions Self-Hosted Runner by Label (Python) DESCRIPTION: Retrieves a specific self-hosted GitHub Actions runner from the repository based on its label. This function iterates through all available runners to find a match. It raises an error if no runner with the specified label is found. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` get_runner(label: str) -> SelfHostedRunner Description: Get a runner by a given label for a repository. Returns: SelfHostedRunner: The runner with the given label. Raises: MissingRunnerLabel: If the runner with the given label is not found. ``` LANGUAGE: Python CODE: ``` def get_runner(self, label: str) -> SelfHostedRunner: """Get a runner by a given label for a repository. Returns ------- SelfHostedRunner The runner with the given label. Raises ------ MissingRunnerLabel If the runner with the given label is not found. """ runners = self.get_runners() if runners is not None: for runner in runners: if label in runner.labels: return runner raise MissingRunnerLabel(f"Runner {label} not found") ``` ---------------------------------------- TITLE: Retrieve a Specific Self-Hosted GitHub Runner by Label DESCRIPTION: Retrieves a single self-hosted runner from the repository by its unique label. It first fetches all runners using `get_runners` and then filters them. Raises `MissingRunnerLabel` if the runner is not found. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` get_runner(label: str) -> SelfHostedRunner Returns: SelfHostedRunner The runner with the given label. Raises: MissingRunnerLabel If the runner with the given label is not found. ``` LANGUAGE: Python CODE: ``` def get_runner(self, label: str) -> SelfHostedRunner: runners = self.get_runners() if runners is not None: for runner in runners: if label in runner.labels: return runner raise MissingRunnerLabel(f"Runner {label} not found") ``` ---------------------------------------- TITLE: Python: Implement wait_for_runner Method DESCRIPTION: Python implementation to poll for a GitHub Actions runner's online status. It repeatedly checks for the runner until it's found or a timeout is reached, raising a `RuntimeError` on timeout. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: Python CODE: ``` def wait_for_runner( self, label: str, timeout: int, wait: int = 15 ) -> SelfHostedRunner: """Wait for the runner with the given label to be online. Parameters ---------- label : str The label of the runner to wait for. wait : int The time in seconds to wait between checks. Defaults to 15 seconds. timeout : int The maximum time in seconds to wait for the runner to be online. Returns ------- SelfHostedRunner The runner with the given label. """ max = time.time() + timeout try: runner = self.get_runner(label) return runner except MissingRunnerLabel: print(f"Waiting for runner {label}...") while True: if time.time() > max: raise RuntimeError( f"Timeout reached: Runner {label} not found" ) try: runner = self.get_runner(label) return runner except MissingRunnerLabel: print(f"Runner {label} not found. Waiting...") time.sleep(wait) ``` ---------------------------------------- TITLE: Wait for a Self-Hosted GitHub Runner to Come Online DESCRIPTION: Polls the GitHub API to check for a specific self-hosted runner to become available. It uses `get_runner` repeatedly with a configurable wait interval and a maximum timeout. Raises a `RuntimeError` if the timeout is reached before the runner is found. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` wait_for_runner(label: str, timeout: int, wait: int = 15) -> SelfHostedRunner Parameters: label: str The label of the runner to wait for. wait: int The time in seconds to wait between checks. Defaults to 15 seconds. timeout: int The maximum time in seconds to wait for the runner to be online. Returns: SelfHostedRunner The runner with the given label. ``` LANGUAGE: Python CODE: ``` def wait_for_runner( self, label: str, timeout: int, wait: int = 15 ) -> SelfHostedRunner: max = time.time() + timeout try: runner = self.get_runner(label) return runner except MissingRunnerLabel: print(f"Waiting for runner {label}...") while True: if time.time() > max: raise RuntimeError( f"Timeout reached: Runner {label} not found" ) try: runner = self.get_runner(label) return runner except MissingRunnerLabel: print(f"Runner {label} not found. Waiting...") time.sleep(wait) ``` ---------------------------------------- TITLE: EnvVarBuilder Class API Reference DESCRIPTION: Comprehensive API documentation for the `EnvVarBuilder` class, detailing its purpose, attributes, constructor, and methods for parsing and transforming environment variables into a structured dictionary. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/helper/input/index LANGUAGE: APIDOC CODE: ``` class EnvVarBuilder: description: A builder class for constructing a dictionary of parameters from environment variables. This class provides a fluent interface for parsing and transforming environment variables into a structured dictionary, with support for JSON parsing and type conversion. attributes: env (Dict[str, str]): The environment variables. params (dict): The dictionary of parsed parameters. parameters: env (Dict[str, str]): The environment variables. methods: __init__(self, env: Dict[str, str]): description: Initializes the EnvVarBuilder with environment variables. parameters: env (Dict[str, str]): The environment variables. _parse_value(self, value: str, is_json: bool, type_hint: Optional[Type]) -> Any: description: Parse the value based on the configuration. parameters: value (str): The value to parse. is_json (bool): If True, parse the value as JSON, by default False. type_hint (Type): Type to convert the value to (if not JSON), by default str. returns: Any: The parsed value as the specified type or JSON object. notes: - JSON parsing is performed before type conversion if is_json is True. _parse_single_param(self, config: ParamConfig): description: Parse a single parameter from the environment variables. _update_params(self, key: str, value: Any): description: Updates the internal parameters dictionary, ensuring deep copies. update_state(self, var_name: str, key: str, is_json: bool = False, allow_empty: bool = False, type_hint: Type = str) -> "EnvVarBuilder": description: Update the state of the builder with a single parameter. parameters: var_name (str): The name of the environment variable. key (str): The key to store the parsed value under in the result dictionary. is_json (bool): If True, parse the value as JSON. allow_empty (bool): If True, include empty strings. type_hint (Type): Type to convert the value to. returns: EnvVarBuilder: Returns self for method chaining. raises: ValueError: If any configured environment variable parsing fails. notes: - Empty strings are ignored by default unless allow_empty is True. - JSON parsing is performed before type conversion if is_json is True. params (property) -> dict: description: Returns a copy of the dictionary of parsed parameters. returns: dict: A deep copy of the parsed parameters. ``` ---------------------------------------- TITLE: Log an Error Message in GitHub Actions Workflow DESCRIPTION: This function logs an error message that will appear in the GitHub Actions workflow run log. It is used to indicate a critical issue or failure within a workflow step. The function requires a descriptive title for the error and the specific error message content. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/helper/workflow_cmds/index LANGUAGE: APIDOC CODE: ``` error(title: str, message) ``` LANGUAGE: Python CODE: ``` def error(title: str, message): print(f"::error title={title}::{message}") ``` ---------------------------------------- TITLE: Log a Warning Message in GitHub Actions Workflow DESCRIPTION: This function logs a warning message to the GitHub Actions workflow run log. Warnings are used to highlight potential issues or non-critical problems that should be noted but do not necessarily halt the workflow execution. It requires a title for the warning and the warning message content. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/helper/workflow_cmds/index LANGUAGE: APIDOC CODE: ``` warning(title: str, message) ``` LANGUAGE: Python CODE: ``` def warning(title: str, message): print(f"::warning title={title}::{message}") ``` ---------------------------------------- TITLE: Manage Cloud Instance ID to Runner Label Mapping DESCRIPTION: Provides methods to retrieve a mapping of cloud instance IDs to their corresponding GitHub runner labels from the environment. This is crucial for tracking and managing instances within a CI/CD setup. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: APIDOC CODE: ``` get_instance_mapping() -> dict[str, str] Returns: dict[str, str] – A dictionary of instance IDs and their corresponding github runner labels. ``` LANGUAGE: python CODE: ``` @abstractmethod def get_instance_mapping(self) -> dict[str, str]: """Get the instance mapping from the environment. Returns ------- dict[str, str] A dictionary of instance IDs and their corresponding github runner labels. """ raise NotImplementedError ``` ---------------------------------------- TITLE: Define Configuration for a Single Parameter DESCRIPTION: This `NamedTuple` class defines the configuration structure for a single environment variable parameter. It encapsulates details like the environment variable name, key, JSON parsing flag, empty string allowance, and type hint. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/helper/input/index LANGUAGE: APIDOC CODE: ``` ParamConfig Bases: `NamedTuple` Configuration for a single parameter. ``` LANGUAGE: python CODE: ``` class ParamConfig(NamedTuple): """Configuration for a single parameter.""" env_var: str key: str is_json: bool allow_empty: bool type_val: Type ``` ---------------------------------------- TITLE: API Reference and Implementation for set_instance_mapping DESCRIPTION: This abstract method is used to set the mapping between cloud instance IDs and their corresponding GitHub runner labels within the environment. This mapping is crucial for associating runners with specific instances. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: APIDOC CODE: ``` set_instance_mapping(mapping: dict[str, str]) Parameters: mapping (dict[str, str]) - A dictionary of instance IDs and their corresponding github runner labels. ``` LANGUAGE: Python CODE: ``` @abstractmethod def set_instance_mapping(self, mapping: dict[str, str]): """Set the instance mapping in the environment. Parameters ---------- mapping : dict[str, str] A dictionary of instance IDs and their corresponding github runner labels. """ raise NotImplementedError ``` ---------------------------------------- TITLE: TeardownInstance Class API Reference DESCRIPTION: Detailed API documentation for the `TeardownInstance` class, which manages the shutdown and removal of cloud instances and GitHub Actions runners. It includes constructor parameters, attributes, and methods for stopping resources. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: APIDOC CODE: ``` class TeardownInstance: # Description Class that is used to teardown instances and runners. # Parameters Parameters: provider_type (Type[StopCloudInstance]): The type of cloud provider to use. cloud_params (dict): The parameters to pass to the cloud provider. gh (GitHubInstance): The GitHub instance to use. # Attributes Attributes: provider (StopCloudInstance): The cloud provider instance provider_type (Type[StopCloudInstance]): cloud_params (dict): gh (GitHub): # Methods __post_init__(): Description: Initialize the cloud provider. This function is called after the object is created to correctly stop the provider. Returns: None stop_runner_instances(): Description: Stop the runner instances. This function stops the runner instances and waits for them to be removed. Returns: None Raises: Exception: On malformed instance mapping or failure to remove instances. MissingRunnerLabel: If a runner label does not exist. ``` ---------------------------------------- TITLE: DeployInstance Class API Reference DESCRIPTION: Detailed API documentation for the `DeployInstance` class, including its constructor parameters, attributes, and methods for deploying and managing cloud instances as GitHub Actions runners. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/clouddeployment/index LANGUAGE: APIDOC CODE: ``` DeployInstance Class: Description: Class that is used to deploy instances and runners. Source: gha_runner/clouddeployment.py Parameters: provider_type (Type[CreateCloudInstance]): The type of cloud provider to use. cloud_params (dict): The parameters to pass to the cloud provider. gh (GitHubInstance): The GitHub instance to use. count (int): The number of instances to create. timeout (int): The timeout to use when waiting for the runner to come online. Attributes: provider (CreateCloudInstance): The cloud provider instance. provider_type (Type[CreateCloudInstance]): The type of cloud provider to use. cloud_params (dict): The parameters to pass to the cloud provider. gh (GitHubInstance): The GitHub instance to use. count (int): The number of instances to use. timeout (int): The timeout to use when waiting for the runner to come online. Methods: __post_init__(): Description: Initialize the cloud provider. Details: This function is called after the object is created to correctly init the provider. It creates runner tokens, gets the latest runner release, and initializes the cloud provider instance. start_runner_instances(): Description: Start the runner instances. Details: This function starts the runner instances and waits for them to be ready. It orchestrates instance creation, setting instance mappings, waiting for readiness, and confirming runner registration with GitHub. ``` ---------------------------------------- TITLE: GitHubInstance Class API Reference DESCRIPTION: Reference documentation for the `GitHubInstance` class, detailing its purpose, initialization parameters, and attributes for managing GitHub repository actions via the API. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` GitHubInstance: Description: Class to manage GitHub repository actions through the GitHub API. Parameters: token (str): GitHub API token for authentication. repo (str): Full name of the GitHub repository in the format "owner/repo". Attributes: headers (dict): Headers for HTTP requests to GitHub API. github (Github): Instance of Github object for interacting with the GitHub API. ``` ---------------------------------------- TITLE: API Reference: wait_for_runner Method DESCRIPTION: Provides the API signature and details for the `wait_for_runner` method, which waits for a self-hosted GitHub Actions runner with a specific label to come online within a given timeout. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` wait_for_runner(label: str, timeout: int, wait: int = 15) -> SelfHostedRunner Wait for the runner with the given label to be online. Parameters: label (str): The label of the runner to wait for. wait (int, default: 15): The time in seconds to wait between checks. Defaults to 15 seconds. timeout (int): The maximum time in seconds to wait for the runner to be online. Returns: SelfHostedRunner: The runner with the given label. ``` ---------------------------------------- TITLE: API Reference: remove_runner Method DESCRIPTION: Provides the API signature and details for the `remove_runner` method, which is used to remove a self-hosted GitHub Actions runner by its label. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` remove_runner(label: str) Remove a runner by a given label. Parameters: label (str): The label of the runner to remove. Raises: RuntimeError: If there is an error removing the runner or the runner is not found. ``` ---------------------------------------- TITLE: Python: Define RunnerListError Exception DESCRIPTION: Python class definition for `RunnerListError`, a custom exception indicating a failure to retrieve the list of runners. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: Python CODE: ``` class RunnerListError(Exception): """Exception raised when there is an error getting the list of runners.""" ``` ---------------------------------------- TITLE: Python: Define TokenRetrievalError Exception DESCRIPTION: Python class definition for `TokenRetrievalError`, a custom exception indicating a failure to retrieve an authentication token from GitHub. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: Python CODE: ``` class TokenRetrievalError(Exception): """Exception raised when there is an error retrieving a token from GitHub.""" ``` ---------------------------------------- TITLE: Python: Define MissingRunnerLabel Exception DESCRIPTION: Python class definition for `MissingRunnerLabel`, a custom exception indicating that a runner with the specified label was not found. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: Python CODE: ``` class MissingRunnerLabel(Exception): """Exception raised when a runner does not exist in the repository.""" ``` ---------------------------------------- TITLE: API Reference: TokenRetrievalError Exception DESCRIPTION: Provides the API definition for `TokenRetrievalError`, an exception raised when an error occurs during the retrieval of an authentication token from GitHub. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` TokenRetrievalError Bases: Exception Exception raised when there is an error retrieving a token from GitHub. ``` ---------------------------------------- TITLE: API Reference: RunnerListError Exception DESCRIPTION: Provides the API definition for `RunnerListError`, an exception raised when an error occurs while attempting to retrieve the list of GitHub Actions runners. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` RunnerListError Bases: Exception Exception raised when there is an error getting the list of runners. ``` ---------------------------------------- TITLE: API Reference: MissingRunnerLabel Exception DESCRIPTION: Provides the API definition for `MissingRunnerLabel`, an exception raised when a specified GitHub Actions runner label does not correspond to an existing runner in the repository. SOURCE: https://gha-runner.readthedocs.io/en/latest/api/gh/index LANGUAGE: APIDOC CODE: ``` MissingRunnerLabel Bases: Exception Exception raised when a runner does not exist in the repository. ```