maintenance.py
Automated maintenance loop for the gasclaw repository.
Overview
This module provides continuous maintenance capabilities for the gasclaw project:
- Check and merge open PRs automatically
- Fix open issues
- Improve test coverage
- Maintain code quality
Can be run as a standalone script or imported as a module.
Classes
CommandNotFoundError
Raised when a command binary is not found in PATH.
Inheritance: subprocess.CalledProcessError
Constructor
Parameters:
| Name | Type | Description |
|---|---|---|
cmd |
list[str] |
The command that was not found |
Attributes:
| Name | Type | Description |
|---|---|---|
binary |
str |
The binary name that was not found |
Functions
run_command()
Run a shell command and return the result.
def run_command(
cmd: list[str],
*,
check: bool = True,
timeout: int = 120
) -> subprocess.CompletedProcess[str]
Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
cmd |
list[str] |
— | Command and arguments as a list |
check |
bool |
True |
If True, raise CalledProcessError on non-zero exit |
timeout |
int |
120 |
Max seconds to wait for command |
Returns: CompletedProcess with returncode, stdout, stderr
Raises:
CommandNotFoundError: Ifcheck=Trueand command binary is not foundsubprocess.CalledProcessError: Ifcheck=Trueand command failssubprocess.TimeoutExpired: If command times out
get_open_prs()
Get list of open PRs from GitHub.
Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
timeout |
int |
120 |
Max seconds to wait for the command |
Returns: List of PR dicts with number, title, headRefName, and author
get_open_issues()
Get list of open issues from GitHub.
Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
timeout |
int |
120 |
Max seconds to wait for the command |
Returns: List of issue dicts with number and title
checkout_and_test_pr()
Checkout a PR branch and run tests.
Parameters:
| Name | Type | Description |
|---|---|---|
pr_number |
int |
The PR number |
branch |
str |
The branch name to checkout |
Returns: True if tests pass, False otherwise
merge_pr()
Merge a PR using squash merge.
Parameters:
| Name | Type | Description |
|---|---|---|
pr_number |
int |
The PR number to merge |
Returns: True if merge succeeded, False otherwise
process_open_prs()
Process all open PRs: test and merge if passing.
Returns: Dict with counts of merged, failed, and fixed PRs, plus total
Return Structure:
{
"merged": int, # Number of PRs successfully merged
"failed": int, # Number of PRs with failing tests
"fixed": int, # Number of PRs auto-fixed (placeholder)
"total": int # Total PRs processed
}
process_open_issues()
Process open issues by creating fix branches and PRs.
Returns: Dict with counts of issues processed
Return Structure:
run_maintenance_cycle()
Run a single maintenance cycle.
Returns: Dict with summary of all actions taken
Return Structure:
{
"prs": {
"merged": int,
"failed": int,
"fixed": int,
"total": int
},
"issues": {
"processed": int,
"total": int
}
}
maintenance_loop()
Run continuous maintenance loop.
Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
interval |
int |
300 |
Seconds between maintenance cycles |
Behavior:
- Runs indefinitely until interrupted
- Sends Telegram notifications for PR merges and errors
- Catches exceptions and continues looping
- Handles
KeyboardInterruptgracefully
main()
Run the maintenance script entry point.
Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
args |
list[str] \| None |
None |
Command line arguments (defaults to sys.argv[1:]) |
Command Line Usage:
# Run maintenance once
python -m gasclaw.maintenance --once
# Run continuous loop with custom interval
python -m gasclaw.maintenance --interval 600
Usage Examples
Run a Single Maintenance Cycle
from gasclaw.maintenance import run_maintenance_cycle
results = run_maintenance_cycle()
print(f"Merged: {results['prs']['merged']}")
print(f"Failed: {results['prs']['failed']}")
Get Open PRs
from gasclaw.maintenance import get_open_prs
prs = get_open_prs()
for pr in prs:
print(f"#{pr['number']}: {pr['title']}")
Run Continuous Loop
from gasclaw.maintenance import maintenance_loop
# Run every 5 minutes (default)
maintenance_loop()
# Run every 10 minutes
maintenance_loop(interval=600)
Constants
| Name | Value | Description |
|---|---|---|
REPO |
"gastown-publish/gasclaw" |
GitHub repository identifier |