generated from coulomb/repo-seed
fix: resolve issue-facade ID mapping bugs and enhance functionality
- Fix Sentinel bug in list command where Click set search params to Sentinel.UNSET - Fix version command by adding explicit version and package_name parameters - Fix test isolation by correcting mock patch targets and datetime objects - Fix critical ID mapping bug: use issue.number consistently instead of mixing with issue.backend_id - Update all comment operations to use issue numbers instead of internal IDs - Ensure issue-facade uses upstream issue numbers directly without local ID confusion - Add comprehensive test coverage with 20 passing tests - Verify core functionality: list, show, close, version, backend management all working - Successfully close issue #166 with proper comment handling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
118
issue_tracker/cli/main.py
Normal file
118
issue_tracker/cli/main.py
Normal file
@@ -0,0 +1,118 @@
|
||||
"""
|
||||
Main CLI Entry Point
|
||||
|
||||
Universal Issue Tracking System CLI
|
||||
"""
|
||||
|
||||
import click
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from .commands import issue_group
|
||||
from .backend_commands import backend_group
|
||||
from .sync_commands import sync_group
|
||||
from .. import __version__
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.version_option(version=__version__, package_name='issue-tracker')
|
||||
@click.option('--config', type=click.Path(), help='Configuration file path')
|
||||
@click.option('--backend', help='Backend to use (local, gitea)')
|
||||
@click.option('--verbose', '-v', is_flag=True, help='Verbose output')
|
||||
@click.pass_context
|
||||
def cli(ctx, config, backend, verbose):
|
||||
"""
|
||||
Universal Issue Tracking System
|
||||
|
||||
A backend-agnostic issue tracking tool that works with local SQLite,
|
||||
Gitea, GitHub, and other issue tracking systems.
|
||||
|
||||
Examples:
|
||||
issue list # List all issues
|
||||
issue create "Bug in parser" # Create new issue
|
||||
issue show 42 # Show issue #42
|
||||
issue close 42 # Close issue #42
|
||||
|
||||
backend add local ~/.issues # Add local backend
|
||||
backend add gitea myrepo # Add Gitea backend
|
||||
|
||||
sync pull gitea # Sync from Gitea
|
||||
sync push gitea # Sync to Gitea
|
||||
"""
|
||||
# Ensure the object exists
|
||||
ctx.ensure_object(dict)
|
||||
|
||||
# Store global options in context
|
||||
ctx.obj['config_path'] = config
|
||||
ctx.obj['backend'] = backend
|
||||
ctx.obj['verbose'] = verbose
|
||||
|
||||
|
||||
# Register command groups
|
||||
cli.add_command(issue_group, name='issue')
|
||||
cli.add_command(backend_group, name='backend')
|
||||
cli.add_command(sync_group, name='sync')
|
||||
|
||||
|
||||
# Convenience aliases - direct issue commands
|
||||
@cli.command('list')
|
||||
@click.pass_context
|
||||
def list_issues(ctx):
|
||||
"""List all issues (alias for 'issue list')."""
|
||||
ctx.invoke(issue_group.get_command(ctx, 'list'))
|
||||
|
||||
|
||||
@cli.command('show')
|
||||
@click.argument('issue_number', type=int)
|
||||
@click.pass_context
|
||||
def show_issue(ctx, issue_number):
|
||||
"""Show issue details (alias for 'issue show')."""
|
||||
ctx.invoke(issue_group.get_command(ctx, 'show'), issue_number=issue_number)
|
||||
|
||||
|
||||
@cli.command('create')
|
||||
@click.argument('title')
|
||||
@click.option('--description', '-d', help='Issue description')
|
||||
@click.option('--label', '-l', multiple=True, help='Labels to add')
|
||||
@click.option('--assignee', '-a', help='Assign to user')
|
||||
@click.option('--milestone', '-m', help='Milestone')
|
||||
@click.pass_context
|
||||
def create_issue(ctx, title, description, label, assignee, milestone):
|
||||
"""Create new issue (alias for 'issue create')."""
|
||||
ctx.invoke(
|
||||
issue_group.get_command(ctx, 'create'),
|
||||
title=title,
|
||||
description=description,
|
||||
label=label,
|
||||
assignee=assignee,
|
||||
milestone=milestone
|
||||
)
|
||||
|
||||
|
||||
@cli.command('close')
|
||||
@click.argument('issue_number', type=int)
|
||||
@click.option('--comment', '-c', help='Closing comment')
|
||||
@click.pass_context
|
||||
def close_issue(ctx, issue_number, comment):
|
||||
"""Close issue (alias for 'issue close')."""
|
||||
ctx.invoke(
|
||||
issue_group.get_command(ctx, 'close'),
|
||||
issue_number=issue_number,
|
||||
comment=comment
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point for the CLI."""
|
||||
try:
|
||||
cli(obj={})
|
||||
except KeyboardInterrupt:
|
||||
click.echo("\nAborted by user", err=True)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
click.echo(f"Error: {e}", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user