markitect-main/issue-facade/cli/main.py

117 lines
3.4 KiB
Python
Raw Normal View History

"""
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
@click.group()
@click.version_option()
@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()