fix: detect Gitea issues with null pull request metadata
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
@@ -30,6 +31,8 @@ def main(
|
|||||||
ctx: typer.Context,
|
ctx: typer.Context,
|
||||||
config: Annotated[Path, typer.Option("--config", "-c", help="Path to YAML config.")] = Path("config.yaml"),
|
config: Annotated[Path, typer.Option("--config", "-c", help="Path to YAML config.")] = Path("config.yaml"),
|
||||||
) -> None:
|
) -> None:
|
||||||
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
|
||||||
|
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||||
ctx.obj = CliContext(config)
|
ctx.obj = CliContext(config)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class GiteaClient:
|
|||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
issues: list[GiteaIssue] = []
|
issues: list[GiteaIssue] = []
|
||||||
for item in response.json():
|
for item in response.json():
|
||||||
if "pull_request" in item:
|
if item.get("pull_request"):
|
||||||
continue
|
continue
|
||||||
issues.append(
|
issues.append(
|
||||||
GiteaIssue(
|
GiteaIssue(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from .agents import CommandRunner, read_report, render_command, write_prompt
|
from .agents import CommandRunner, read_report, render_command, write_prompt
|
||||||
@@ -21,6 +22,9 @@ from .state import validate_transition
|
|||||||
from .workspace import WorkspaceManager, safe_branch_name
|
from .workspace import WorkspaceManager, safe_branch_name
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def sync_repositories(db: Database, config: AppConfig, client: GiteaClient) -> list[RepositoryRecord]:
|
def sync_repositories(db: Database, config: AppConfig, client: GiteaClient) -> list[RepositoryRecord]:
|
||||||
synced: list[RepositoryRecord] = []
|
synced: list[RepositoryRecord] = []
|
||||||
discovered = client.list_owned_repositories()
|
discovered = client.list_owned_repositories()
|
||||||
@@ -89,10 +93,19 @@ class TaskRunner:
|
|||||||
|
|
||||||
def worker_loop(self) -> None:
|
def worker_loop(self) -> None:
|
||||||
while True:
|
while True:
|
||||||
sync_repositories(self.db, self.config, self.gitea)
|
try:
|
||||||
scan_issues(self.db, self.config, self.gitea)
|
repos = sync_repositories(self.db, self.config, self.gitea)
|
||||||
task = self.run_once()
|
logger.info("synced %d repositories", len(repos))
|
||||||
if task is None:
|
task_ids = scan_issues(self.db, self.config, self.gitea)
|
||||||
|
logger.info("created %d tasks from issue scan", len(task_ids))
|
||||||
|
task = self.run_once()
|
||||||
|
if task is None:
|
||||||
|
logger.info("no task available; sleeping %d seconds", self.config.scheduler.interval_seconds)
|
||||||
|
time.sleep(self.config.scheduler.interval_seconds)
|
||||||
|
else:
|
||||||
|
logger.info("task %d finished in state %s", task.id, task.state.value)
|
||||||
|
except Exception:
|
||||||
|
logger.exception("worker iteration failed")
|
||||||
time.sleep(self.config.scheduler.interval_seconds)
|
time.sleep(self.config.scheduler.interval_seconds)
|
||||||
|
|
||||||
def run_claimed(self, task: TaskRecord) -> TaskRecord:
|
def run_claimed(self, task: TaskRecord) -> TaskRecord:
|
||||||
|
|||||||
@@ -89,6 +89,36 @@ def test_sync_and_scan_with_mocked_gitea(db, tmp_path):
|
|||||||
assert len(task_ids) == 1
|
assert len(task_ids) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_open_issues_keeps_normal_issues_with_null_pull_request():
|
||||||
|
def handler(request: httpx.Request) -> httpx.Response:
|
||||||
|
assert request.url.path == "/api/v1/repos/acme/service/issues"
|
||||||
|
return httpx.Response(
|
||||||
|
200,
|
||||||
|
json=[
|
||||||
|
{
|
||||||
|
"number": 1,
|
||||||
|
"title": "Normal issue",
|
||||||
|
"body": "Body",
|
||||||
|
"state": "open",
|
||||||
|
"labels": [{"name": "agent:ready"}],
|
||||||
|
"pull_request": None,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": 2,
|
||||||
|
"title": "PR issue",
|
||||||
|
"body": "Body",
|
||||||
|
"state": "open",
|
||||||
|
"labels": [{"name": "agent:ready"}],
|
||||||
|
"pull_request": {"url": "https://gitea.test/pr/2"},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
issues = make_client(handler).list_open_issues("acme", "service")
|
||||||
|
|
||||||
|
assert [issue.number for issue in issues] == [1]
|
||||||
|
|
||||||
|
|
||||||
class FakeWorkspaceManager:
|
class FakeWorkspaceManager:
|
||||||
def __init__(self, root: Path, *, diff: bool = True):
|
def __init__(self, root: Path, *, diff: bool = True):
|
||||||
self.root = root
|
self.root = root
|
||||||
|
|||||||
Reference in New Issue
Block a user