CiManager#

class mobu.services.github_ci.ci_manager.CiManager(github_app_id, github_private_key, scopes, users, http_client, events, repo_manager, gafaelfawr_storage, logger)#

Bases: object

Manages processing work for GitHub CI checks.

This should be a process singleton. It is responsible for: * Creating background workers to process GitHub CI events * Ensuring they run at the appropriate level of concurrency given the number of available users * Ensuring GitHub CI checks are not left in a forever-in-progress state when mobu shuts down

Parameters:
  • users (list[User]) – A list of static users that are available to run jobs. Each of these users will get assigned to a worker, and will process one job at a time.

  • http_client (AsyncClient) – Shared HTTP client.

  • gafaelfawr_storage (GafaelfawrStorage) – Gafaelfawr storage client.

  • events (Events) – Event publishers.

  • logger (BoundLogger) – Global logger to use for process-wide (not monkey) logging.

  • github_app_id (int)

  • github_private_key (str)

  • scopes (list[str])

  • repo_manager (RepoManager)

Attributes Summary

Methods Summary

aclose()

Stop the workers and update GitHub CI checks for pending work.

enqueue(installation_id, repo_owner, ...)

Enqueue a job to run something for a given Git repo and commit.

start()

Start the workers for the CI manager.

summarize()

Attributes Documentation

shutdown_error_msg = 'Mobu stopped, try re-running this check.'#

Methods Documentation

async aclose()#

Stop the workers and update GitHub CI checks for pending work.

We initially fail in-progress jobs too because we don’t want any GitHub check runs to be forever in-progress if mobu gets killed before they finish. If they do end up finishing in time, then they’ll be re-concluded as successful.

We’d rather have false-negative GitHub checks than forever-in-progress checks, because: * There is no way to re-run in-progress checks from the GitHub UI * There is no way to know for sure from the GitHub UI that a check will never be concluded.

A failed check can easily be re-run by any user, so this is an acceptable tradeoff, assuming false-negatives happen infrequently.

Scenarios:

### Job completes :rtype: None

  1. Mobu is told to shut down

  2. Mobu tells GitHub that job has failed due to restart

  3. Job finishes before mobu is SIGKILLed

  4. Mobu tells GitHub that job is successful

  5. Mobu is SIGKILLed or exits cleanly

Result: GitHub check run displays success, which is corrcect. An incorrect failure status will have been displayed for a brief period of time. User action needed: None

### Job does not complete

  1. Mobu is told to shut down

  2. Mobu tells GitHub that job has failed due to restart

  3. Mobu is SIGKILLed

Result: GitHub check run displays failure status, which is correct. User action needed: Re-run check in GitHub UI

### Job completes, but mobu is killed before it can tell GitHub

This situation should be pretty rare. 1. Mobu is told to shut down 2. Mobu tells GitHub that job has failed due to restart 3. Job finishes before mobu is SIGKILLed 4. Mobu is SIGKILLed before it can tell GitHub the job has succeeded

Result: GitHub check run displays failure status, which is incorrect. User action needed: Re-run check in GitHub UI

async enqueue(installation_id, repo_owner, repo_name, ref, pull_number)#

Enqueue a job to run something for a given Git repo and commit.

Parameters:
  • installation_id (int) – The GitHub installation ID of the app that generated this work.

  • repo_owner. – A GitHub organization name.

  • repo_name (str) – A GitHub repo name.

  • ref (str) – A GitHub commit SHA.

  • pull_number (int) – The number that identifies a pull request.

  • repo_owner (str)

Returns:

Only used in unit tests.

Helpful for creating deterministic ordering scenarios when processing multiple jobs.

Return type:

JobLifecycle

async start()#

Start the workers for the CI manager.

Return type:

None

summarize()#
Return type:

CiManagerSummary