diff --git a/aider_gitea/__init__.py b/aider_gitea/__init__.py index 4f356a5..0e6bd4a 100644 --- a/aider_gitea/__init__.py +++ b/aider_gitea/__init__.py @@ -527,6 +527,15 @@ def solve_issues_in_repository( seen_issues_db, issue_url, ) + + # Handle failing pipelines + handle_failing_pipelines( + repository_config, + issue_resolution.pull_request_id, + branch_name, + Path(repository_path), + client, + ) seen_issues_db.mark_as_seen(issue_url, str(issue_number)) seen_issues_db.update_pr_info( issue_url, @@ -581,3 +590,40 @@ def handle_pr_comments( check=False, ) run_cmd(['git', 'push', 'origin', branch_name], repository_path, check=False) + + +def handle_failing_pipelines( + repository_config: RepositoryConfig, + pr_number: str, + branch_name: str, + repository_path: Path, + client, +) -> None: + """Fetch failing pipelines for the given PR and resolve them via aider.""" + while True: + failed_runs = client.get_failed_pipelines( + repository_config.owner, + repository_config.repo, + pr_number, + ) + if not failed_runs: + break + for run_id in failed_runs: + log = client.get_pipeline_log( + repository_config.owner, + repository_config.repo, + run_id, + ) + lines = log.strip().split('\n') + context = '\n'.join(lines[-100:]) + issue = f'Resolve the following failing pipeline run {run_id}:\n\n{context}' + issue_solution_round(repository_path, issue) + run_cmd(['git', 'add', '.'], repository_path, check=False) + run_cmd( + ['git', 'commit', '-m', f'Resolve pipeline {run_id}'], + repository_path, + check=False, + ) + run_cmd( + ['git', 'push', 'origin', branch_name], repository_path, check=False, + ) diff --git a/aider_gitea/gitea_client.py b/aider_gitea/gitea_client.py index e239af1..9968845 100644 --- a/aider_gitea/gitea_client.py +++ b/aider_gitea/gitea_client.py @@ -169,6 +169,29 @@ class GiteaClient: response.raise_for_status() return response.json() + def get_failed_pipelines(self, owner: str, repo: str, pr_number: str) -> list[int]: + """Fetch pipeline runs for a PR and return IDs of failed runs.""" + url = f'{self.gitea_url}/repos/{owner}/{repo}/actions/runs' + response = self.session.get(url) + response.raise_for_status() + runs = response.json().get('workflow_runs', []) + failed = [] + for run in runs: + if any( + pr.get('number') == int(pr_number) + for pr in run.get('pull_requests', []) + ): + if run.get('conclusion') not in ('success',): + failed.append(run.get('id')) + return failed + + def get_pipeline_log(self, owner: str, repo: str, run_id: int) -> str: + """Download the logs for a pipeline run.""" + url = f'{self.gitea_url}/repos/{owner}/{repo}/actions/runs/{run_id}/logs' + response = self.session.get(url) + response.raise_for_status() + return response.text + def get_pull_request_comments( self, owner: str,