feat: Complete Issue #79 - Provide tddai issue_closer.py

Add dedicated issue closing functionality for easier issue management:

📄 New Module: tddai/issue_closer.py
• Dedicated IssueCloser class with programmatic API
• Command-line interface for manual and batch issue closure
• Enhanced functionality beyond existing tddai_cli.py close-issue
• Support for standardized completion messages
• Batch closure capability for multiple issues

🔧 Makefile Integration:
• close-issue-enhanced - Enhanced single issue closure with work completion
• close-issues-batch - Batch closure for multiple issues
• Proper help documentation and .PHONY declarations

 Key Features:
• Simple programmatic interface: IssueCloser().close_issue(42, "comment")
• CLI with multiple closure modes: comment, work-completed, batch
• Integration with existing tddai framework and issue tracking backends
• Comprehensive error handling and user feedback
• Verbose mode for detailed operation tracking

📋 Usage Examples:
• python3 tddai/issue_closer.py 42 -w "All tests passing"
• python3 tddai/issue_closer.py 42 43 44 -c "Batch closure"
• make close-issue-enhanced NUM=42 WORK="Implementation complete"
• make close-issues-batch NUMS="42 43 44" COMMENT="Sprint completion"

Provides the missing tddai function to close issues more easily with the selected issue tracking backend.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-02 22:30:53 +02:00
parent bddebbe005
commit bf84f206fe
2 changed files with 222 additions and 5 deletions

View File

@@ -1,7 +1,7 @@
# MarkiTect - Advanced Markdown Engine
# Makefile for common development tasks
.PHONY: help setup install test build clean update status dev lint format check-deps venv-status update-digest add-diary-entry list-issues show-issue list-open-issues close-issue test-from-issue tdd-start tdd-add-test tdd-finish tdd-status test-status test-new test-coverage test-arch test-foundation test-infrastructure test-integration test-domain test-service test-application test-presentation test-quick test-layers test-random test-random-seed test-random-repeat test-install-randomly test-clean test-tdd test-changed test-module test-cache-clean test-efficient cli-help
.PHONY: help setup install test build clean update status dev lint format check-deps venv-status update-digest add-diary-entry list-issues show-issue list-open-issues close-issue close-issue-enhanced close-issues-batch test-from-issue tdd-start tdd-add-test tdd-finish tdd-status test-status test-new test-coverage test-arch test-foundation test-infrastructure test-integration test-domain test-service test-application test-presentation test-quick test-layers test-random test-random-seed test-random-repeat test-install-randomly test-clean test-tdd test-changed test-module test-cache-clean test-efficient cli-help
# Default target
help:
@@ -66,7 +66,9 @@ help:
@echo " list-issues - Show all gitea issues with status and priority"
@echo " list-open-issues - Show only open issues (active backlog)"
@echo " show-issue NUM=X - Show detailed view of specific issue"
@echo " close-issue NUM=X - Close an issue and mark as completed"
@echo " close-issue NUM=X [COMMENT='reason'] - Close an issue and mark as completed"
@echo " close-issue-enhanced NUM=X [WORK='description'] - Close issue with enhanced tddai/issue_closer.py"
@echo " close-issues-batch NUMS='X Y Z' [COMMENT='reason'] - Close multiple issues at once"
@echo " issues-get - Export compact issue index to ISSUES.index"
@echo " issues-csv - Export issues as CSV for spreadsheet processing"
@echo " issues-json - Export issues as JSON for programmatic processing"
@@ -343,11 +345,46 @@ close-issue: $(VENV)/bin/activate
echo "❌ Please specify issue number: make close-issue NUM=5"; \
exit 1; \
fi
@echo "🔄 Closing issue #$(NUM)..."
@echo " Setting issue state to 'done'..."
@PYTHONPATH=. $(VENV_PYTHON) tddai_cli.py set-issue-state $(NUM) done
@if [ -n "$(COMMENT)" ]; then \
echo "🔄 Closing issue #$(NUM) with comment..."; \
PYTHONPATH=. $(VENV_PYTHON) tddai_cli.py close-issue $(NUM) --comment "$(COMMENT)"; \
else \
echo "🔄 Closing issue #$(NUM)..."; \
PYTHONPATH=. $(VENV_PYTHON) tddai_cli.py close-issue $(NUM); \
fi
@echo "✅ Issue #$(NUM) closed successfully!"
# Close issue using dedicated issue_closer.py script (enhanced functionality)
close-issue-enhanced: $(VENV)/bin/activate
@if [ -z "$(NUM)" ]; then \
echo "❌ Please specify issue number: make close-issue-enhanced NUM=5"; \
exit 1; \
fi
@if [ -n "$(WORK)" ]; then \
echo "🔄 Closing issue #$(NUM) with completion message..."; \
PYTHONPATH=. $(VENV_PYTHON) tddai/issue_closer.py $(NUM) --work-completed "$(WORK)"; \
elif [ -n "$(COMMENT)" ]; then \
echo "🔄 Closing issue #$(NUM) with comment..."; \
PYTHONPATH=. $(VENV_PYTHON) tddai/issue_closer.py $(NUM) --comment "$(COMMENT)"; \
else \
echo "🔄 Closing issue #$(NUM)..."; \
PYTHONPATH=. $(VENV_PYTHON) tddai/issue_closer.py $(NUM); \
fi
# Close multiple issues at once using issue_closer.py
close-issues-batch: $(VENV)/bin/activate
@if [ -z "$(NUMS)" ]; then \
echo "❌ Please specify issue numbers: make close-issues-batch NUMS='42 43 44'"; \
exit 1; \
fi
@if [ -n "$(COMMENT)" ]; then \
echo "🔄 Closing issues $(NUMS) with comment..."; \
PYTHONPATH=. $(VENV_PYTHON) tddai/issue_closer.py $(NUMS) --comment "$(COMMENT)"; \
else \
echo "🔄 Closing issues $(NUMS)..."; \
PYTHONPATH=. $(VENV_PYTHON) tddai/issue_closer.py $(NUMS); \
fi
# Export compact issue index to ISSUES.index file (TSV format)
issues-get: $(VENV)/bin/activate
@echo "📋 Fetching issue index from gitea..."

180
tddai/issue_closer.py Normal file
View File

@@ -0,0 +1,180 @@
#!/usr/bin/env python3
"""
TDDAi Issue Closer
A dedicated module for closing issues in the selected issue tracking backend.
Provides both programmatic API and CLI functionality for easy issue closure.
This module integrates with the existing tddai framework and provides:
- Simple programmatic interface for closing issues
- Command-line utility for manual issue closure
- Integration with existing issue tracking backends
- Proper error handling and user feedback
"""
import sys
import argparse
from pathlib import Path
from typing import Optional
# Add project root to path for imports
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))
from cli import CLIFramework
from services import IssueService
from tddai import TddaiError
class IssueCloser:
"""Dedicated class for closing issues with the configured backend."""
def __init__(self):
"""Initialize the issue closer with CLI framework."""
self.cli = CLIFramework()
self.service = IssueService()
def close_issue(self, issue_number: int, comment: str = "") -> bool:
"""
Close an issue with optional comment.
Args:
issue_number: The issue number to close
comment: Optional closing comment
Returns:
bool: True if issue was closed successfully, False otherwise
"""
try:
self.cli.close_issue(issue_number, comment)
return True
except TddaiError as e:
print(f"Error closing issue #{issue_number}: {e}")
return False
except Exception as e:
print(f"Unexpected error closing issue #{issue_number}: {e}")
return False
def close_with_completion_message(self, issue_number: int, completed_work: str) -> bool:
"""
Close an issue with a standardized completion message.
Args:
issue_number: The issue number to close
completed_work: Description of what was completed
Returns:
bool: True if issue was closed successfully, False otherwise
"""
completion_comment = f"✅ Completed: {completed_work}"
return self.close_issue(issue_number, completion_comment)
def close_multiple_issues(self, issue_numbers: list, comment: str = "") -> dict:
"""
Close multiple issues with the same comment.
Args:
issue_numbers: List of issue numbers to close
comment: Comment to add to all issues
Returns:
dict: Results with 'successful' and 'failed' lists
"""
results = {'successful': [], 'failed': []}
for issue_num in issue_numbers:
if self.close_issue(issue_num, comment):
results['successful'].append(issue_num)
else:
results['failed'].append(issue_num)
return results
def main():
"""Command-line interface for the issue closer."""
parser = argparse.ArgumentParser(
description="TDDAi Issue Closer - Close issues in the configured tracking backend",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python3 issue_closer.py 42 # Close issue #42
python3 issue_closer.py 42 -c "Fixed the bug" # Close with comment
python3 issue_closer.py 42 -w "All tests passing" # Close with completion message
python3 issue_closer.py 42 43 44 # Close multiple issues
python3 issue_closer.py 42 43 -c "Batch closure" # Close multiple with comment
Integration with existing tddai CLI:
python3 tddai_cli.py close-issue 42 --comment "Done" # Alternative method
"""
)
parser.add_argument(
'issue_numbers',
type=int,
nargs='+',
help='Issue number(s) to close'
)
parser.add_argument(
'-c', '--comment',
type=str,
default='',
help='Optional closing comment'
)
parser.add_argument(
'-w', '--work-completed',
type=str,
help='Description of completed work (creates standardized completion message)'
)
parser.add_argument(
'-v', '--verbose',
action='store_true',
help='Enable verbose output'
)
args = parser.parse_args()
# Initialize issue closer
closer = IssueCloser()
# Determine which closing method to use
if args.work_completed:
comment = f"✅ Completed: {args.work_completed}"
else:
comment = args.comment
# Handle single or multiple issues
if len(args.issue_numbers) == 1:
issue_num = args.issue_numbers[0]
if args.verbose:
print(f"Closing issue #{issue_num}...")
if comment:
print(f"Comment: {comment}")
success = closer.close_issue(issue_num, comment)
sys.exit(0 if success else 1)
else:
# Multiple issues
if args.verbose:
print(f"Closing {len(args.issue_numbers)} issues...")
if comment:
print(f"Comment: {comment}")
results = closer.close_multiple_issues(args.issue_numbers, comment)
if results['successful']:
print(f"✅ Successfully closed: {results['successful']}")
if results['failed']:
print(f"❌ Failed to close: {results['failed']}")
sys.exit(1)
print(f"✅ All {len(args.issue_numbers)} issues closed successfully!")
if __name__ == '__main__':
main()