""" Issue writing using the Gitea integration facade. This module now acts as an adapter to the new gitea package, maintaining backwards compatibility while using the cleaner API. """ import os from typing import Dict, Any, Optional from gitea import GiteaClient, GiteaConfig from .config import get_config from .exceptions import IssueError class IssueWriter: """Writes issue updates using the Gitea integration facade.""" def __init__(self, config=None, auth_token=None): self.config = config or get_config() self.auth_token = auth_token or os.getenv('GITEA_API_TOKEN') # Create Gitea client from tddai config gitea_config = GiteaConfig.from_tddai_config(self.config) if self.auth_token: gitea_config.auth_token = self.auth_token self.gitea_client = GiteaClient(gitea_config) def update_issue(self, issue_number: int, update_data: Dict[str, Any]) -> Dict[str, Any]: """Update an issue via the gitea integration.""" if not self.auth_token: raise IssueError("Authentication token required for issue updates") try: issue = self.gitea_client.issues.update(issue_number, **update_data) return self.gitea_client.issues.to_dict(issue) except Exception as e: raise IssueError(f"Failed to update issue #{issue_number}: {e}") def update_issue_title(self, issue_number: int, new_title: str) -> Dict[str, Any]: """Update only the title of an issue.""" try: issue = self.gitea_client.issues.update_title(issue_number, new_title) return self.gitea_client.issues.to_dict(issue) except Exception as e: raise IssueError(f"Failed to update issue title #{issue_number}: {e}") def update_issue_body(self, issue_number: int, new_body: str) -> Dict[str, Any]: """Update only the body of an issue.""" try: issue = self.gitea_client.issues.update_body(issue_number, new_body) return self.gitea_client.issues.to_dict(issue) except Exception as e: raise IssueError(f"Failed to update issue body #{issue_number}: {e}") def update_issue_state(self, issue_number: int, new_state: str) -> Dict[str, Any]: """Update only the state of an issue (open/closed).""" if new_state not in ['open', 'closed']: raise IssueError(f"Invalid state '{new_state}'. Must be 'open' or 'closed'") try: if new_state == 'closed': issue = self.gitea_client.issues.close(issue_number) else: issue = self.gitea_client.issues.reopen(issue_number) return self.gitea_client.issues.to_dict(issue) except Exception as e: raise IssueError(f"Failed to update issue state #{issue_number}: {e}") def close_issue(self, issue_number: int) -> Dict[str, Any]: """Close an issue.""" return self.update_issue_state(issue_number, 'closed') def reopen_issue(self, issue_number: int) -> Dict[str, Any]: """Reopen a closed issue.""" return self.update_issue_state(issue_number, 'open') def assign_to_milestone(self, issue_number: int, milestone_id: int) -> Dict[str, Any]: """Assign issue to a milestone (project).""" try: issue = self.gitea_client.issues.assign_to_milestone(issue_number, milestone_id) return self.gitea_client.issues.to_dict(issue) except Exception as e: raise IssueError(f"Failed to assign issue #{issue_number} to milestone: {e}") def remove_from_milestone(self, issue_number: int) -> Dict[str, Any]: """Remove issue from its current milestone.""" try: issue = self.gitea_client.issues.remove_from_milestone(issue_number) return self.gitea_client.issues.to_dict(issue) except Exception as e: raise IssueError(f"Failed to remove issue #{issue_number} from milestone: {e}") def update_labels(self, issue_number: int, labels: list) -> Dict[str, Any]: """Update issue labels completely.""" if not self.auth_token: raise IssueError("Authentication token required for label updates") try: issue = self.gitea_client.issues.set_labels(issue_number, labels) return self.gitea_client.issues.to_dict(issue) except Exception as e: raise IssueError(f"Failed to update labels for issue #{issue_number}: {e}") def add_labels(self, issue_number: int, new_labels: list) -> Dict[str, Any]: """Add labels to issue (preserving existing labels).""" try: issue = self.gitea_client.issues.add_labels(issue_number, new_labels) return self.gitea_client.issues.to_dict(issue) except Exception as e: raise IssueError(f"Failed to add labels to issue #{issue_number}: {e}") def remove_labels(self, issue_number: int, labels_to_remove: list) -> Dict[str, Any]: """Remove specific labels from issue.""" try: issue = self.gitea_client.issues.remove_labels(issue_number, labels_to_remove) return self.gitea_client.issues.to_dict(issue) except Exception as e: raise IssueError(f"Failed to remove labels from issue #{issue_number}: {e}")