Skip to content

Inactivity Check

The Inactivity Check verifies that a repository has not been inactive (no updates or commits) for a year. This helps ensure that repositories are actively maintained and not abandoned, which can be crucial for security and reliability.

GitHub Usage Policy Origin

Inspired by the GitHub Usage Policy, clause 5.3.9, in summary:

  • Repositories that have not been updated for a year should be archived by a Tech Lead / Senior Team Member.

Check Criteria

  • The check will analyse the updated_at timestamp of the repository.
  • If this timestamp indicates that the repository has not been updated for more than a year, the check will fail.
  • If the repository has been updated within the last year, the check will pass.
  • Should the updated_at timestamp be unavailable, the check will return an error status.

Reference

Check if a repository has been inactive for over a year.

Parameters:

Name Type Description Default
client Optional[GitHubRestClient]

An instance of the GitHubRestClient to use for API calls. Required if data is not provided. Defaults to None.

None
repository_name Optional[str]

The name of the repository to check. Required if data is not provided. Defaults to None.

None
data Optional[dict]

A dictionary containing data about the repository. This must contain the 'updated_at' field with the last update timestamp. If provided, client and repository_name are ignored. Defaults to None.

None

Returns:

Type Description
dict

A dictionary with the result of the check, including 'result' (pass/fail/error), 'message', and 'details'.

Source code in src/policy_methods_library/checks/inactivity.py
def check_inactivity(
    client: Optional[GitHubRestClient] = None,
    repository_name: Optional[str] = None,
    data: Optional[dict] = None,
) -> dict:
    """Check if a repository has been inactive for over a year.

    Args:
        client: An instance of the GitHubRestClient to use for API calls. Required if data is not provided. Defaults to None.
        repository_name: The name of the repository to check. Required if data is not provided. Defaults to None.
        data: A dictionary containing data about the repository. This must contain the 'updated_at' field with the last update timestamp. If provided, client and repository_name are ignored. Defaults to None.

    Returns:
        A dictionary with the result of the check, including 'result' (pass/fail/error), 'message', and 'details'.
    """

    if data is not None:
        if "updated_at" not in data:
            return {
                "result": "error",
                "message": "Data must include 'updated_at' field.",
                "details": {"data": data},
            }

        last_updated = data.get("updated_at")

    else:
        if client is None:
            return {
                "result": "error",
                "message": "GitHubRestClient instance is required if data is not provided.",
                "details": {},
            }
        if repository_name is None:
            return {
                "result": "error",
                "message": "Repository name is required if data is not provided.",
                "details": {},
            }

        try:
            response = client.make_request(
                "GET", f"/repos/{client.owner}/{repository_name}"
            )

            repository_info = response.json()
            last_updated = repository_info.get("updated_at")

            if last_updated is None:
                return {
                    "result": "error",
                    "message": "API response does not contain 'updated_at' field.",
                    "details": {"response": repository_info},
                }
        except Exception as e:
            return {
                "result": "error",
                "message": f"Error fetching repository data: {str(e)}",
                "details": {},
            }

    if not isinstance(last_updated, str):
        return {
            "result": "error",
            "message": "Invalid type for 'updated_at'. Expected ISO 8601 string.",
            "details": {"updated_at": last_updated},
        }

    try:
        last_updated_date = datetime.strptime(
            last_updated, "%Y-%m-%dT%H:%M:%SZ"
        ).replace(tzinfo=timezone.utc)
    except ValueError:
        return {
            "result": "error",
            "message": "Invalid date format for 'updated_at'. Expected ISO 8601 format.",
            "details": {"updated_at": last_updated},
        }

    one_year_ago = datetime.now(timezone.utc) - timedelta(days=365)

    if last_updated_date < one_year_ago:
        return {
            "result": "fail",
            "message": f"Repository has been inactive since {last_updated_date.strftime('%Y-%m-%d')}.",
            "details": {"last_updated": last_updated},
        }
    else:
        return {
            "result": "pass",
            "message": "Repository has been updated within the last year.",
            "details": {"last_updated": last_updated},
        }

Usage Example

With Data Passed Directly

from policy_methods_library.checks.inactivity import check_inactivity

# Collect Data (In a real implementation, this data would likely come from another API call).

data = {
    "updated_at": "2023-01-01T00:00:00Z"
}

# Run Check with Data Passed Directly

response = check_inactivity(data=data)

# Process response

result = response.get("result")
message = response.get("message")

match result:
    case "pass":
        print(f"Check Passed: {message}")
    case "fail":
        print(f"Check Failed: {message}")
    case "error":
        print(f"Check Error: {message}")
    case _:
        print("Unexpected result returned.")

With Data Retrieval

from policy_methods_library.checks.inactivity import check_inactivity
from policy_methods_library.github.clients import GitHubRestClient

# Setup GitHub Client

# Note: These credentials are placeholders. In a real implementation, 
# you would securely retrieve these from your environment or a secrets manager.
app_id = "your_app_id"
private_key = "your_private_key"
github_organisation = "your_github_organisation"

client = GitHubRestClient(
    owner=github_organisation,
    app_id=app_id,
    private_key=private_key,
)

# Run Check with Data Retrieval

response = check_inactivity(client=client, repository_name="your_repository_name")

# Process response

result = response.get("result")
message = response.get("message")

match result:
    case "pass":
        print(f"Check Passed: {message}")
    case "fail":
        print(f"Check Failed: {message}")
    case "error":
        print(f"Check Error: {message}")
    case _:
        print("Unexpected result returned.")

GitHub Integration Used

If the data is not passed directly, the check will use the GET /repos/{owner}/{repo} endpoint to retrieve the updated_at timestamp of the repository.

GitHub Documentation 🔗