roadmap-cli 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- roadmap/__init__.py +27 -0
- roadmap/adapters/__init__.py +1 -0
- roadmap/adapters/base_paginated_adapter.py +117 -0
- roadmap/adapters/cli/__init__.py +249 -0
- roadmap/adapters/cli/analysis/__init__.py +5 -0
- roadmap/adapters/cli/analysis/commands.py +370 -0
- roadmap/adapters/cli/analysis/presenter.py +125 -0
- roadmap/adapters/cli/archive_operations.py +86 -0
- roadmap/adapters/cli/cli_command_helpers.py +109 -0
- roadmap/adapters/cli/cli_confirmations.py +74 -0
- roadmap/adapters/cli/cli_error_handlers.py +146 -0
- roadmap/adapters/cli/cli_validators.py +39 -0
- roadmap/adapters/cli/commands/sync_status.py +308 -0
- roadmap/adapters/cli/comment/__init__.py +5 -0
- roadmap/adapters/cli/comment/commands.py +106 -0
- roadmap/adapters/cli/config/__init__.py +5 -0
- roadmap/adapters/cli/config/commands.py +198 -0
- roadmap/adapters/cli/console_exports.py +10 -0
- roadmap/adapters/cli/core.py +26 -0
- roadmap/adapters/cli/crud/__init__.py +47 -0
- roadmap/adapters/cli/crud/base_archive.py +208 -0
- roadmap/adapters/cli/crud/base_create.py +154 -0
- roadmap/adapters/cli/crud/base_delete.py +155 -0
- roadmap/adapters/cli/crud/base_restore.py +283 -0
- roadmap/adapters/cli/crud/base_update.py +193 -0
- roadmap/adapters/cli/crud/crud_helpers.py +206 -0
- roadmap/adapters/cli/crud/crud_utils.py +152 -0
- roadmap/adapters/cli/crud/entity_builders.py +374 -0
- roadmap/adapters/cli/data/__init__.py +8 -0
- roadmap/adapters/cli/data/commands.py +149 -0
- roadmap/adapters/cli/decorators.py +208 -0
- roadmap/adapters/cli/dtos/__init__.py +155 -0
- roadmap/adapters/cli/exception_handler.py +105 -0
- roadmap/adapters/cli/git/__init__.py +8 -0
- roadmap/adapters/cli/git/commands.py +475 -0
- roadmap/adapters/cli/git/handlers/__init__.py +1 -0
- roadmap/adapters/cli/git/handlers/git_authentication_handler.py +124 -0
- roadmap/adapters/cli/git/handlers/git_branch_handler.py +238 -0
- roadmap/adapters/cli/git/handlers/git_connectivity_handler.py +122 -0
- roadmap/adapters/cli/git/handlers/git_hooks_handler.py +105 -0
- roadmap/adapters/cli/git/hooks_config.py +327 -0
- roadmap/adapters/cli/git/status_display.py +158 -0
- roadmap/adapters/cli/health/__init__.py +8 -0
- roadmap/adapters/cli/health/db_integrity.py +204 -0
- roadmap/adapters/cli/health/enhancer.py +227 -0
- roadmap/adapters/cli/health/fixer.py +295 -0
- roadmap/adapters/cli/health/fixers/__init__.py +10 -0
- roadmap/adapters/cli/health/fixers/corrupted_comments_fixer.py +231 -0
- roadmap/adapters/cli/health/fixers/data_integrity_fixer.py +137 -0
- roadmap/adapters/cli/health/fixers/duplicate_issues_fixer.py +138 -0
- roadmap/adapters/cli/health/fixers/folder_structure_fixer.py +114 -0
- roadmap/adapters/cli/health/fixers/label_normalization_fixer.py +162 -0
- roadmap/adapters/cli/health/fixers/milestone_name_normalization_fixer.py +181 -0
- roadmap/adapters/cli/health/fixers/milestone_naming_compliance_fixer.py +244 -0
- roadmap/adapters/cli/health/fixers/milestone_parse_error_fixer.py +162 -0
- roadmap/adapters/cli/health/fixers/milestone_validation_fixer.py +211 -0
- roadmap/adapters/cli/health/fixers/old_backups_fixer.py +135 -0
- roadmap/adapters/cli/health/fixers/orphaned_issues_fixer.py +252 -0
- roadmap/adapters/cli/health/formatter.py +250 -0
- roadmap/adapters/cli/health/formatters.py +427 -0
- roadmap/adapters/cli/health/scan.py +293 -0
- roadmap/adapters/cli/init/__init__.py +5 -0
- roadmap/adapters/cli/init/commands.py +587 -0
- roadmap/adapters/cli/init.py +9 -0
- roadmap/adapters/cli/issues/__init__.py +70 -0
- roadmap/adapters/cli/issues/archive.py +137 -0
- roadmap/adapters/cli/issues/archive_class.py +253 -0
- roadmap/adapters/cli/issues/block.py +39 -0
- roadmap/adapters/cli/issues/close.py +216 -0
- roadmap/adapters/cli/issues/comment.py +178 -0
- roadmap/adapters/cli/issues/create.py +162 -0
- roadmap/adapters/cli/issues/delete.py +31 -0
- roadmap/adapters/cli/issues/deps.py +161 -0
- roadmap/adapters/cli/issues/issue_status_helpers.py +111 -0
- roadmap/adapters/cli/issues/link.py +308 -0
- roadmap/adapters/cli/issues/list.py +402 -0
- roadmap/adapters/cli/issues/lookup.py +96 -0
- roadmap/adapters/cli/issues/progress.py +102 -0
- roadmap/adapters/cli/issues/restore.py +96 -0
- roadmap/adapters/cli/issues/restore_class.py +57 -0
- roadmap/adapters/cli/issues/start.py +165 -0
- roadmap/adapters/cli/issues/sync_status.py +374 -0
- roadmap/adapters/cli/issues/unblock.py +43 -0
- roadmap/adapters/cli/issues/unlink.py +104 -0
- roadmap/adapters/cli/issues/update.py +120 -0
- roadmap/adapters/cli/issues/view.py +36 -0
- roadmap/adapters/cli/layout.py +220 -0
- roadmap/adapters/cli/mappers.py +200 -0
- roadmap/adapters/cli/milestones/__init__.py +52 -0
- roadmap/adapters/cli/milestones/archive.py +125 -0
- roadmap/adapters/cli/milestones/archive_class.py +236 -0
- roadmap/adapters/cli/milestones/assign.py +62 -0
- roadmap/adapters/cli/milestones/close.py +177 -0
- roadmap/adapters/cli/milestones/create.py +131 -0
- roadmap/adapters/cli/milestones/delete.py +27 -0
- roadmap/adapters/cli/milestones/kanban.py +123 -0
- roadmap/adapters/cli/milestones/list.py +87 -0
- roadmap/adapters/cli/milestones/recalculate.py +79 -0
- roadmap/adapters/cli/milestones/restore.py +87 -0
- roadmap/adapters/cli/milestones/restore_class.py +99 -0
- roadmap/adapters/cli/milestones/update.py +61 -0
- roadmap/adapters/cli/milestones/view.py +142 -0
- roadmap/adapters/cli/output_manager.py +319 -0
- roadmap/adapters/cli/presentation/base_presenter.py +121 -0
- roadmap/adapters/cli/presentation/cleanup_presenter.py +235 -0
- roadmap/adapters/cli/presentation/core_initialization_presenter.py +277 -0
- roadmap/adapters/cli/presentation/crud_presenter.py +134 -0
- roadmap/adapters/cli/presentation/daily_summary_presenter.py +266 -0
- roadmap/adapters/cli/presentation/issue_presenter.py +258 -0
- roadmap/adapters/cli/presentation/milestone_list_presenter.py +135 -0
- roadmap/adapters/cli/presentation/milestone_presenter.py +297 -0
- roadmap/adapters/cli/presentation/project_presenter.py +233 -0
- roadmap/adapters/cli/presentation/project_status_presenter.py +186 -0
- roadmap/adapters/cli/presentation/table_builders.py +95 -0
- roadmap/adapters/cli/projects/__init__.py +42 -0
- roadmap/adapters/cli/projects/archive.py +127 -0
- roadmap/adapters/cli/projects/archive_class.py +96 -0
- roadmap/adapters/cli/projects/close.py +94 -0
- roadmap/adapters/cli/projects/create.py +50 -0
- roadmap/adapters/cli/projects/delete.py +27 -0
- roadmap/adapters/cli/projects/list.py +227 -0
- roadmap/adapters/cli/projects/restore.py +87 -0
- roadmap/adapters/cli/projects/restore_class.py +56 -0
- roadmap/adapters/cli/projects/update.py +57 -0
- roadmap/adapters/cli/projects/view.py +157 -0
- roadmap/adapters/cli/services/__init__.py +1 -0
- roadmap/adapters/cli/services/daily_summary_service.py +313 -0
- roadmap/adapters/cli/services/export_manager.py +268 -0
- roadmap/adapters/cli/services/milestone_list_service.py +266 -0
- roadmap/adapters/cli/services/project_initialization_service.py +29 -0
- roadmap/adapters/cli/services/project_status_service.py +462 -0
- roadmap/adapters/cli/services/sync_service.py +62 -0
- roadmap/adapters/cli/status.py +408 -0
- roadmap/adapters/cli/styling.py +21 -0
- roadmap/adapters/cli/sync.py +1117 -0
- roadmap/adapters/cli/sync_context.py +432 -0
- roadmap/adapters/cli/sync_handlers/__init__.py +77 -0
- roadmap/adapters/cli/sync_handlers/apply_ops.py +522 -0
- roadmap/adapters/cli/sync_handlers/baseline_ops.py +366 -0
- roadmap/adapters/cli/sync_handlers/conflict_ops.py +161 -0
- roadmap/adapters/cli/sync_handlers/dry_run_display.py +237 -0
- roadmap/adapters/cli/sync_handlers/interactive_resolver.py +396 -0
- roadmap/adapters/cli/sync_handlers/progress_tracker.py +128 -0
- roadmap/adapters/cli/sync_metrics_command.py +190 -0
- roadmap/adapters/cli/sync_presenter.py +58 -0
- roadmap/adapters/cli/sync_validation.py +295 -0
- roadmap/adapters/cli/today.py +52 -0
- roadmap/adapters/cli/utils/click_options.py +38 -0
- roadmap/adapters/git/__init__.py +1 -0
- roadmap/adapters/git/git.py +208 -0
- roadmap/adapters/git/git_branch_manager.py +400 -0
- roadmap/adapters/git/git_command_executor.py +56 -0
- roadmap/adapters/git/git_commit_analyzer.py +334 -0
- roadmap/adapters/git/git_hooks.py +22 -0
- roadmap/adapters/git/git_hooks_manager.py +455 -0
- roadmap/adapters/git/git_repository_info.py +65 -0
- roadmap/adapters/git/hook_installer.py +106 -0
- roadmap/adapters/git/hook_registry.py +97 -0
- roadmap/adapters/git/hook_script_generator.py +58 -0
- roadmap/adapters/git/sync_monitor.py +409 -0
- roadmap/adapters/git/workflow_automation.py +286 -0
- roadmap/adapters/github/__init__.py +1 -0
- roadmap/adapters/github/github.py +360 -0
- roadmap/adapters/github/handlers/__init__.py +17 -0
- roadmap/adapters/github/handlers/base.py +337 -0
- roadmap/adapters/github/handlers/collaborators.py +165 -0
- roadmap/adapters/github/handlers/comments.py +118 -0
- roadmap/adapters/github/handlers/issues.py +150 -0
- roadmap/adapters/github/handlers/labels.py +164 -0
- roadmap/adapters/github/handlers/milestones.py +104 -0
- roadmap/adapters/persistence/__init__.py +35 -0
- roadmap/adapters/persistence/conflict_resolver.py +190 -0
- roadmap/adapters/persistence/database_manager.py +492 -0
- roadmap/adapters/persistence/entity_sync_coordinators.py +672 -0
- roadmap/adapters/persistence/file_locking.py +348 -0
- roadmap/adapters/persistence/file_parser.py +92 -0
- roadmap/adapters/persistence/file_synchronizer.py +107 -0
- roadmap/adapters/persistence/focused_managers.py +140 -0
- roadmap/adapters/persistence/git_history.py +330 -0
- roadmap/adapters/persistence/parser/__init__.py +20 -0
- roadmap/adapters/persistence/parser/frontmatter.py +152 -0
- roadmap/adapters/persistence/parser/issue.py +245 -0
- roadmap/adapters/persistence/parser/milestone.py +146 -0
- roadmap/adapters/persistence/parser/project.py +106 -0
- roadmap/adapters/persistence/persistence.py +288 -0
- roadmap/adapters/persistence/repositories/__init__.py +15 -0
- roadmap/adapters/persistence/repositories/issue_repository.py +223 -0
- roadmap/adapters/persistence/repositories/milestone_repository.py +140 -0
- roadmap/adapters/persistence/repositories/project_repository.py +168 -0
- roadmap/adapters/persistence/repositories/remote_link_repository.py +355 -0
- roadmap/adapters/persistence/repositories/sync_state_repository.py +66 -0
- roadmap/adapters/persistence/storage/__init__.py +36 -0
- roadmap/adapters/persistence/storage/conflicts.py +101 -0
- roadmap/adapters/persistence/storage/connection_manager.py +79 -0
- roadmap/adapters/persistence/storage/issue_storage.py +89 -0
- roadmap/adapters/persistence/storage/milestone_storage.py +80 -0
- roadmap/adapters/persistence/storage/project_storage.py +102 -0
- roadmap/adapters/persistence/storage/queries.py +227 -0
- roadmap/adapters/persistence/storage/state_manager.py +652 -0
- roadmap/adapters/persistence/storage/sync_state_storage.py +207 -0
- roadmap/adapters/persistence/sync_metrics_repository.py +342 -0
- roadmap/adapters/persistence/sync_orchestrator.py +293 -0
- roadmap/adapters/persistence/sync_state_tracker.py +86 -0
- roadmap/adapters/persistence/yaml_repositories.py +711 -0
- roadmap/adapters/sync/__init__.py +21 -0
- roadmap/adapters/sync/backend_factory.py +108 -0
- roadmap/adapters/sync/backends/__init__.py +15 -0
- roadmap/adapters/sync/backends/converters.py +209 -0
- roadmap/adapters/sync/backends/github_backend_helpers.py +380 -0
- roadmap/adapters/sync/backends/github_client.py +99 -0
- roadmap/adapters/sync/backends/github_sync_backend.py +792 -0
- roadmap/adapters/sync/backends/github_sync_ops.py +908 -0
- roadmap/adapters/sync/backends/services/__init__.py +1 -0
- roadmap/adapters/sync/backends/services/github_authentication_service.py +105 -0
- roadmap/adapters/sync/backends/services/github_issue_delete_service.py +423 -0
- roadmap/adapters/sync/backends/services/github_issue_dependency_service.py +63 -0
- roadmap/adapters/sync/backends/services/github_issue_fetch_service.py +158 -0
- roadmap/adapters/sync/backends/services/github_label_sync_service.py +126 -0
- roadmap/adapters/sync/backends/services/github_local_issue_sync_service.py +229 -0
- roadmap/adapters/sync/backends/services/github_milestone_fetch_service.py +204 -0
- roadmap/adapters/sync/backends/vanilla_git_sync_backend.py +198 -0
- roadmap/adapters/sync/services/__init__.py +11 -0
- roadmap/adapters/sync/services/baseline_state_handler.py +83 -0
- roadmap/adapters/sync/services/conflict_converter.py +85 -0
- roadmap/adapters/sync/services/issue_persistence_service.py +263 -0
- roadmap/adapters/sync/services/issue_state_service.py +243 -0
- roadmap/adapters/sync/services/local_change_filter.py +129 -0
- roadmap/adapters/sync/services/pull_result_processor.py +71 -0
- roadmap/adapters/sync/services/remote_issue_creation_service.py +112 -0
- roadmap/adapters/sync/services/sync_analysis_service.py +250 -0
- roadmap/adapters/sync/services/sync_authentication_service.py +57 -0
- roadmap/adapters/sync/services/sync_data_fetch_service.py +212 -0
- roadmap/adapters/sync/services/sync_linking_service.py +329 -0
- roadmap/adapters/sync/services/sync_report_service.py +62 -0
- roadmap/adapters/sync/services/sync_state_update_service.py +51 -0
- roadmap/adapters/sync/sync_cache_orchestrator.py +454 -0
- roadmap/adapters/sync/sync_merge_engine.py +416 -0
- roadmap/adapters/sync/sync_merge_orchestrator.py +1313 -0
- roadmap/adapters/sync/sync_retrieval_orchestrator.py +810 -0
- roadmap/application/services/__init__.py +1 -0
- roadmap/application/services/deduplicate_service.py +517 -0
- roadmap/application/use_cases/__init__.py +1 -0
- roadmap/common/__init__.py +308 -0
- roadmap/common/cache.py +209 -0
- roadmap/common/cli_errors.py +147 -0
- roadmap/common/configuration/__init__.py +33 -0
- roadmap/common/configuration/config_loader.py +264 -0
- roadmap/common/configuration/config_manager.py +164 -0
- roadmap/common/configuration/config_schema.py +145 -0
- roadmap/common/configuration/github/__init__.py +9 -0
- roadmap/common/configuration/github/config_manager.py +154 -0
- roadmap/common/configuration/github/token_resolver.py +84 -0
- roadmap/common/console.py +184 -0
- roadmap/common/constants.py +134 -0
- roadmap/common/datetime_parser.py +319 -0
- roadmap/common/error_formatter.py +84 -0
- roadmap/common/errors/__init__.py +143 -0
- roadmap/common/errors/error_base.py +73 -0
- roadmap/common/errors/error_file.py +82 -0
- roadmap/common/errors/error_git.py +67 -0
- roadmap/common/errors/error_handler.py +166 -0
- roadmap/common/errors/error_network.py +90 -0
- roadmap/common/errors/error_security.py +78 -0
- roadmap/common/errors/error_standards.py +561 -0
- roadmap/common/errors/error_validation.py +111 -0
- roadmap/common/errors/exceptions.py +432 -0
- roadmap/common/formatters/__init__.py +29 -0
- roadmap/common/formatters/base_table_formatter.py +96 -0
- roadmap/common/formatters/export/__init__.py +7 -0
- roadmap/common/formatters/export/issue_exporter.py +97 -0
- roadmap/common/formatters/helpers.py +28 -0
- roadmap/common/formatters/kanban/__init__.py +9 -0
- roadmap/common/formatters/kanban/layout.py +48 -0
- roadmap/common/formatters/kanban/organizer.py +81 -0
- roadmap/common/formatters/output/__init__.py +15 -0
- roadmap/common/formatters/tables/__init__.py +11 -0
- roadmap/common/formatters/tables/column_factory.py +312 -0
- roadmap/common/formatters/tables/issue_table.py +276 -0
- roadmap/common/formatters/tables/milestone_table.py +247 -0
- roadmap/common/formatters/tables/project_table.py +195 -0
- roadmap/common/formatters/text/__init__.py +57 -0
- roadmap/common/formatters/text/basic.py +217 -0
- roadmap/common/formatters/text/display.py +42 -0
- roadmap/common/formatters/text/duration.py +36 -0
- roadmap/common/formatters/text/operations.py +325 -0
- roadmap/common/formatters/text/status_badges.py +57 -0
- roadmap/common/initialization/github/__init__.py +11 -0
- roadmap/common/initialization/github/setup_service.py +238 -0
- roadmap/common/initialization/github/setup_validator.py +78 -0
- roadmap/common/logging/__init__.py +113 -0
- roadmap/common/logging/audit_logging.py +5 -0
- roadmap/common/logging/correlation.py +45 -0
- roadmap/common/logging/decorators.py +267 -0
- roadmap/common/logging/error_logging.py +217 -0
- roadmap/common/logging/formatters.py +124 -0
- roadmap/common/logging/loggers.py +68 -0
- roadmap/common/logging/performance_tracking.py +267 -0
- roadmap/common/logging/utils.py +335 -0
- roadmap/common/models/__init__.py +44 -0
- roadmap/common/models/cli_models.py +118 -0
- roadmap/common/models/config_models.py +199 -0
- roadmap/common/models/output_models.py +381 -0
- roadmap/common/observability/__init__.py +28 -0
- roadmap/common/observability/instrumentation.py +103 -0
- roadmap/common/observability/observability.py +76 -0
- roadmap/common/observability/otel_init.py +109 -0
- roadmap/common/output_formatter.py +393 -0
- roadmap/common/progress.py +379 -0
- roadmap/common/result.py +396 -0
- roadmap/common/security/__init__.py +48 -0
- roadmap/common/security/exceptions.py +13 -0
- roadmap/common/security/export_cleanup.py +79 -0
- roadmap/common/security/file_operations.py +104 -0
- roadmap/common/security/filename_sanitization.py +54 -0
- roadmap/common/security/logging.py +27 -0
- roadmap/common/security/path_validation.py +137 -0
- roadmap/common/security/temp_files.py +41 -0
- roadmap/common/services/__init__.py +65 -0
- roadmap/common/services/decorators.py +183 -0
- roadmap/common/services/logging_utils.py +208 -0
- roadmap/common/services/metrics.py +161 -0
- roadmap/common/services/performance.py +219 -0
- roadmap/common/services/profiling.py +288 -0
- roadmap/common/services/retry.py +288 -0
- roadmap/common/status_style_manager.py +114 -0
- roadmap/common/union_find.py +88 -0
- roadmap/common/update_constants.py +13 -0
- roadmap/common/utils/__init__.py +65 -0
- roadmap/common/utils/cli_helpers.py +381 -0
- roadmap/common/utils/file_utils.py +440 -0
- roadmap/common/utils/path_utils.py +38 -0
- roadmap/common/utils/status_utils.py +130 -0
- roadmap/common/utils/timezone_utils.py +480 -0
- roadmap/common/validation/__init__.py +37 -0
- roadmap/common/validation/field_validator.py +104 -0
- roadmap/common/validation/result.py +37 -0
- roadmap/common/validation/roadmap_validator.py +310 -0
- roadmap/common/validation/schema_validator.py +36 -0
- roadmap/common/validation/validators.py +50 -0
- roadmap/core/__init__.py +1 -0
- roadmap/core/domain/__init__.py +30 -0
- roadmap/core/domain/comment.py +24 -0
- roadmap/core/domain/health.py +15 -0
- roadmap/core/domain/issue.py +274 -0
- roadmap/core/domain/milestone.py +173 -0
- roadmap/core/domain/ports/__init__.py +1 -0
- roadmap/core/domain/ports/baseline_repository.py +24 -0
- roadmap/core/domain/ports/issue_repository.py +34 -0
- roadmap/core/domain/ports/remote_backend_port.py +31 -0
- roadmap/core/domain/project.py +130 -0
- roadmap/core/interfaces/__init__.py +109 -0
- roadmap/core/interfaces/assignee_validator.py +40 -0
- roadmap/core/interfaces/backend_factory.py +175 -0
- roadmap/core/interfaces/github.py +102 -0
- roadmap/core/interfaces/parsers.py +140 -0
- roadmap/core/interfaces/persistence.py +45 -0
- roadmap/core/interfaces/repositories.py +174 -0
- roadmap/core/interfaces/state_managers.py +111 -0
- roadmap/core/interfaces/state_storage.py +64 -0
- roadmap/core/interfaces/sync_backend.py +275 -0
- roadmap/core/interfaces/sync_services.py +119 -0
- roadmap/core/interfaces/sync_validators.py +180 -0
- roadmap/core/models/__init__.py +31 -0
- roadmap/core/models/sync_models.py +162 -0
- roadmap/core/models.py +115 -0
- roadmap/core/observability/__init__.py +17 -0
- roadmap/core/observability/sync_metrics.py +699 -0
- roadmap/core/repositories.py +200 -0
- roadmap/core/services/__init__.py +313 -0
- roadmap/core/services/baseline/__init__.py +1 -0
- roadmap/core/services/baseline/baseline_builder_progress.py +274 -0
- roadmap/core/services/baseline/baseline_retriever.py +63 -0
- roadmap/core/services/baseline/baseline_selector.py +248 -0
- roadmap/core/services/baseline/baseline_state_retriever.py +284 -0
- roadmap/core/services/baseline/optimized_baseline_builder.py +425 -0
- roadmap/core/services/comment/__init__.py +1 -0
- roadmap/core/services/comment/comment_service.py +277 -0
- roadmap/core/services/git/__init__.py +1 -0
- roadmap/core/services/git/git_hook_auto_sync_service.py +403 -0
- roadmap/core/services/github/__init__.py +1 -0
- roadmap/core/services/github/github_change_detector.py +162 -0
- roadmap/core/services/github/github_config_validator.py +148 -0
- roadmap/core/services/github/github_conflict_detector.py +179 -0
- roadmap/core/services/github/github_entity_classifier.py +51 -0
- roadmap/core/services/github/github_integration_service.py +439 -0
- roadmap/core/services/github/github_issue_client.py +346 -0
- roadmap/core/services/health/__init__.py +1 -0
- roadmap/core/services/health/backup_cleanup_service.py +202 -0
- roadmap/core/services/health/data_integrity_validator_service.py +90 -0
- roadmap/core/services/health/entity_health_scanner.py +460 -0
- roadmap/core/services/health/file_repair_service.py +193 -0
- roadmap/core/services/health/health_check_service.py +166 -0
- roadmap/core/services/health/health_models.py +80 -0
- roadmap/core/services/health/infrastructure_validator_service.py +328 -0
- roadmap/core/services/health/issue_health_scanner.py +263 -0
- roadmap/core/services/helpers/__init__.py +18 -0
- roadmap/core/services/helpers/status_change_helpers.py +88 -0
- roadmap/core/services/initialization/__init__.py +19 -0
- roadmap/core/services/initialization/utils.py +104 -0
- roadmap/core/services/initialization/validator.py +78 -0
- roadmap/core/services/initialization/workflow.py +182 -0
- roadmap/core/services/initialization_service.py +111 -0
- roadmap/core/services/issue/__init__.py +1 -0
- roadmap/core/services/issue/assignee_validation_service.py +312 -0
- roadmap/core/services/issue/issue_creation_service.py +309 -0
- roadmap/core/services/issue/issue_filter_service.py +302 -0
- roadmap/core/services/issue/issue_matching_service.py +127 -0
- roadmap/core/services/issue/issue_service.py +765 -0
- roadmap/core/services/issue/issue_update_service.py +144 -0
- roadmap/core/services/issue/start_issue_service.py +174 -0
- roadmap/core/services/issue_helpers/__init__.py +18 -0
- roadmap/core/services/issue_helpers/issue_filters.py +296 -0
- roadmap/core/services/milestone_service.py +438 -0
- roadmap/core/services/project/__init__.py +1 -0
- roadmap/core/services/project/project_service.py +434 -0
- roadmap/core/services/project/project_status_service.py +125 -0
- roadmap/core/services/project_init/__init__.py +22 -0
- roadmap/core/services/project_init/context_detection.py +146 -0
- roadmap/core/services/project_init/creation.py +76 -0
- roadmap/core/services/project_init/detection.py +51 -0
- roadmap/core/services/project_init/template.py +228 -0
- roadmap/core/services/status_change_service.py +88 -0
- roadmap/core/services/sync/__init__.py +1 -0
- roadmap/core/services/sync/batch_processor.py +290 -0
- roadmap/core/services/sync/conflict_resolver.py +154 -0
- roadmap/core/services/sync/dependency_resolver.py +367 -0
- roadmap/core/services/sync/duplicate_detector.py +771 -0
- roadmap/core/services/sync/duplicate_resolver.py +315 -0
- roadmap/core/services/sync/error_classification.py +470 -0
- roadmap/core/services/sync/performance.py +263 -0
- roadmap/core/services/sync/sync_change_computer.py +211 -0
- roadmap/core/services/sync/sync_checkpoint.py +348 -0
- roadmap/core/services/sync/sync_conflict_detector.py +147 -0
- roadmap/core/services/sync/sync_conflict_resolver.py +448 -0
- roadmap/core/services/sync/sync_errors.py +383 -0
- roadmap/core/services/sync/sync_key_normalizer.py +222 -0
- roadmap/core/services/sync/sync_metadata_service.py +361 -0
- roadmap/core/services/sync/sync_plan.py +171 -0
- roadmap/core/services/sync/sync_plan_executor.py +447 -0
- roadmap/core/services/sync/sync_report.py +296 -0
- roadmap/core/services/sync/sync_state.py +173 -0
- roadmap/core/services/sync/sync_state_comparator.py +690 -0
- roadmap/core/services/sync/sync_state_manager.py +431 -0
- roadmap/core/services/sync/sync_state_normalizer.py +98 -0
- roadmap/core/services/sync/sync_three_way.py +78 -0
- roadmap/core/services/sync/three_way_merger.py +178 -0
- roadmap/core/services/utils/__init__.py +1 -0
- roadmap/core/services/utils/configuration_service.py +113 -0
- roadmap/core/services/utils/critical_path_calculator.py +418 -0
- roadmap/core/services/utils/dependency_analyzer.py +360 -0
- roadmap/core/services/utils/field_conflict_detector.py +126 -0
- roadmap/core/services/utils/remote_fetcher.py +202 -0
- roadmap/core/services/utils/remote_state_normalizer.py +110 -0
- roadmap/core/services/utils/retry_policy.py +51 -0
- roadmap/core/services/validator_base.py +130 -0
- roadmap/core/services/validators/__init__.py +28 -0
- roadmap/core/services/validators/_utils.py +20 -0
- roadmap/core/services/validators/archivable_issues_validator.py +71 -0
- roadmap/core/services/validators/archivable_milestones_validator.py +69 -0
- roadmap/core/services/validators/backup_validator.py +89 -0
- roadmap/core/services/validators/data_integrity_validator.py +84 -0
- roadmap/core/services/validators/duplicate_issues_validator.py +75 -0
- roadmap/core/services/validators/duplicate_milestones_validator.py +141 -0
- roadmap/core/services/validators/folder_structure_validator.py +165 -0
- roadmap/core/services/validators/health_status_utils.py +28 -0
- roadmap/core/services/validators/milestone_naming_validator.py +146 -0
- roadmap/core/services/validators/missing_headlines_validator.py +97 -0
- roadmap/core/services/validators/orphaned_issues_validator.py +142 -0
- roadmap/core/services/validators/orphaned_milestones_validator.py +85 -0
- roadmap/core/utils/git_remote_parser.py +83 -0
- roadmap/core/utils/github_urls.py +66 -0
- roadmap/domain/validation.py +30 -0
- roadmap/infrastructure/__init__.py +55 -0
- roadmap/infrastructure/coordination/__init__.py +8 -0
- roadmap/infrastructure/coordination/coordinator_params.py +82 -0
- roadmap/infrastructure/coordination/core.py +446 -0
- roadmap/infrastructure/coordination/git_coordinator.py +160 -0
- roadmap/infrastructure/coordination/initialization.py +348 -0
- roadmap/infrastructure/coordination/issue_coordinator.py +154 -0
- roadmap/infrastructure/coordination/issue_operations.py +456 -0
- roadmap/infrastructure/coordination/milestone_coordinator.py +135 -0
- roadmap/infrastructure/coordination/milestone_operations.py +201 -0
- roadmap/infrastructure/coordination/project_coordinator.py +113 -0
- roadmap/infrastructure/coordination/project_operations.py +144 -0
- roadmap/infrastructure/coordination/team_coordinator.py +107 -0
- roadmap/infrastructure/coordination/user_operations.py +150 -0
- roadmap/infrastructure/coordination/validation_coordinator.py +249 -0
- roadmap/infrastructure/coordination_gateway.py +152 -0
- roadmap/infrastructure/git/__init__.py +6 -0
- roadmap/infrastructure/git/git_integration_ops.py +234 -0
- roadmap/infrastructure/git_gateway.py +35 -0
- roadmap/infrastructure/github_gateway.py +52 -0
- roadmap/infrastructure/maintenance/__init__.py +5 -0
- roadmap/infrastructure/maintenance/cleanup.py +483 -0
- roadmap/infrastructure/observability/__init__.py +7 -0
- roadmap/infrastructure/observability/health.py +196 -0
- roadmap/infrastructure/observability/health_formatter.py +73 -0
- roadmap/infrastructure/observability/specialized_health_checkers.py +188 -0
- roadmap/infrastructure/persistence_gateway.py +164 -0
- roadmap/infrastructure/security/__init__.py +1 -0
- roadmap/infrastructure/security/credentials.py +489 -0
- roadmap/infrastructure/sync_gateway.py +94 -0
- roadmap/infrastructure/validation/__init__.py +7 -0
- roadmap/infrastructure/validation/file_enumeration.py +219 -0
- roadmap/infrastructure/validation/github_assignee_validator.py +47 -0
- roadmap/infrastructure/validation/github_validator.py +101 -0
- roadmap/infrastructure/validation/milestone_consistency_validator.py +96 -0
- roadmap/infrastructure/validation/vanilla_assignee_validator.py +37 -0
- roadmap/infrastructure/validation_gateway.py +96 -0
- roadmap/presentation/formatters/sync_metrics_formatter.py +355 -0
- roadmap/settings.py +345 -0
- roadmap/templates/github_workflows/ci-cd-roadmap.yml +241 -0
- roadmap/templates/github_workflows/issue-lifecycle.yml +236 -0
- roadmap/templates/github_workflows/roadmap-integration.yml +137 -0
- roadmap/templates/github_workflows/roadmap-starter.yml +59 -0
- roadmap/version.py +381 -0
- roadmap_cli-0.1.1.dist-info/METADATA +448 -0
- roadmap_cli-0.1.1.dist-info/RECORD +521 -0
- roadmap_cli-0.1.1.dist-info/WHEEL +4 -0
- roadmap_cli-0.1.1.dist-info/entry_points.txt +2 -0
- roadmap_cli-0.1.1.dist-info/licenses/LICENSE.md +21 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
"""Git integration and workflow commands."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
import structlog
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
|
|
10
|
+
from roadmap.adapters.cli.cli_command_helpers import require_initialized
|
|
11
|
+
from roadmap.adapters.cli.cli_error_handlers import handle_cli_error
|
|
12
|
+
from roadmap.adapters.cli.git.handlers.git_authentication_handler import (
|
|
13
|
+
GitAuthenticationHandler,
|
|
14
|
+
)
|
|
15
|
+
from roadmap.adapters.cli.git.handlers.git_branch_handler import GitBranchHandler
|
|
16
|
+
from roadmap.adapters.cli.git.handlers.git_connectivity_handler import (
|
|
17
|
+
GitConnectivityHandler,
|
|
18
|
+
)
|
|
19
|
+
from roadmap.adapters.cli.git.handlers.git_hooks_handler import GitHooksHandler
|
|
20
|
+
from roadmap.adapters.cli.git.hooks_config import hooks_config
|
|
21
|
+
from roadmap.common.console import get_console
|
|
22
|
+
from roadmap.core.services.github.github_integration_service import (
|
|
23
|
+
GitHubIntegrationService,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from .status_display import GitStatusDisplay
|
|
27
|
+
|
|
28
|
+
console = Console()
|
|
29
|
+
log = structlog.get_logger()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@click.group()
|
|
33
|
+
def git():
|
|
34
|
+
"""Git integration and workflow management."""
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Basic git commands - full implementation would be extracted from main CLI
|
|
39
|
+
@git.command("setup")
|
|
40
|
+
@click.option(
|
|
41
|
+
"--auth",
|
|
42
|
+
is_flag=True,
|
|
43
|
+
help="Set up GitHub authentication for sync operations",
|
|
44
|
+
)
|
|
45
|
+
@click.option(
|
|
46
|
+
"--update-token",
|
|
47
|
+
is_flag=True,
|
|
48
|
+
help="Update stored GitHub token",
|
|
49
|
+
)
|
|
50
|
+
@click.option(
|
|
51
|
+
"--git-auth",
|
|
52
|
+
is_flag=True,
|
|
53
|
+
help="Test and verify Git repository connectivity for self-hosting",
|
|
54
|
+
)
|
|
55
|
+
@click.pass_context
|
|
56
|
+
@require_initialized
|
|
57
|
+
def setup_git(ctx: click.Context, auth: bool, update_token: bool, git_auth: bool):
|
|
58
|
+
"""Set up Git integration and authentication.
|
|
59
|
+
|
|
60
|
+
Configure GitHub authentication for sync operations or manage git workflow.
|
|
61
|
+
Supports both GitHub PAT tokens and vanilla Git self-hosting.
|
|
62
|
+
"""
|
|
63
|
+
core = ctx.obj["core"]
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
if auth or update_token:
|
|
67
|
+
_setup_github_auth(core, update_token)
|
|
68
|
+
elif git_auth:
|
|
69
|
+
_test_git_connectivity(core)
|
|
70
|
+
else:
|
|
71
|
+
console.print("โ๏ธ Git setup", style="green")
|
|
72
|
+
console.print("\nAvailable options:")
|
|
73
|
+
console.print(
|
|
74
|
+
" roadmap git setup --auth Set up GitHub authentication"
|
|
75
|
+
)
|
|
76
|
+
console.print(
|
|
77
|
+
" roadmap git setup --update-token Update stored GitHub token"
|
|
78
|
+
)
|
|
79
|
+
console.print(
|
|
80
|
+
" roadmap git setup --git-auth Test Git repository connectivity"
|
|
81
|
+
)
|
|
82
|
+
console.print(" roadmap git hooks-install Install git hooks")
|
|
83
|
+
except Exception as e:
|
|
84
|
+
log.error("git_setup_failed", error=str(e), error_type=type(e).__name__)
|
|
85
|
+
console.print(f"โ Setup failed: {e}", style="bold red")
|
|
86
|
+
ctx.exit(1)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _setup_github_auth(core, update_token: bool = False):
|
|
90
|
+
"""Set up or update GitHub authentication.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
core: RoadmapCore instance
|
|
94
|
+
update_token: If True, force update token; otherwise ask if exists
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
Exception: If authentication setup fails
|
|
98
|
+
"""
|
|
99
|
+
handler = GitAuthenticationHandler(console)
|
|
100
|
+
handler.setup_github_auth(update_token)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _test_git_connectivity(core):
|
|
104
|
+
"""Test and verify Git repository connectivity for self-hosting.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
core: RoadmapCore instance
|
|
108
|
+
|
|
109
|
+
Raises:
|
|
110
|
+
Exception: If git connectivity test fails
|
|
111
|
+
"""
|
|
112
|
+
handler = GitConnectivityHandler(console)
|
|
113
|
+
handler.test_git_connectivity(core)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@git.command("hooks-install")
|
|
117
|
+
@click.pass_context
|
|
118
|
+
@require_initialized
|
|
119
|
+
def install_hooks(ctx: click.Context):
|
|
120
|
+
"""Install Git hooks for roadmap integration.
|
|
121
|
+
|
|
122
|
+
Installs hooks that automatically track commits, branch changes, and integrate
|
|
123
|
+
with your roadmap workflow.
|
|
124
|
+
"""
|
|
125
|
+
core = ctx.obj["core"]
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
handler = GitHooksHandler(console)
|
|
129
|
+
handler.install_hooks(core)
|
|
130
|
+
except Exception:
|
|
131
|
+
ctx.exit(1)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@git.command("hooks-uninstall")
|
|
135
|
+
@click.pass_context
|
|
136
|
+
@require_initialized
|
|
137
|
+
def uninstall_hooks(ctx: click.Context):
|
|
138
|
+
"""Remove Git hooks for roadmap integration."""
|
|
139
|
+
core = ctx.obj["core"]
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
handler = GitHooksHandler(console)
|
|
143
|
+
handler.uninstall_hooks(core)
|
|
144
|
+
except Exception:
|
|
145
|
+
ctx.exit(1)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@git.command("hooks-status")
|
|
149
|
+
@click.pass_context
|
|
150
|
+
@require_initialized
|
|
151
|
+
def hooks_status(ctx: click.Context):
|
|
152
|
+
"""Show status of installed Git hooks."""
|
|
153
|
+
core = ctx.obj["core"]
|
|
154
|
+
|
|
155
|
+
try:
|
|
156
|
+
handler = GitHooksHandler(console)
|
|
157
|
+
handler.show_hooks_status(core)
|
|
158
|
+
except Exception:
|
|
159
|
+
ctx.exit(1)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@git.command("sync")
|
|
163
|
+
def _load_github_config(core) -> dict:
|
|
164
|
+
"""Load GitHub config and normalise to a plain dict."""
|
|
165
|
+
gh_service = GitHubIntegrationService(core, core.roadmap_dir / "config.yaml")
|
|
166
|
+
config_result = gh_service.get_github_config()
|
|
167
|
+
if isinstance(config_result, tuple):
|
|
168
|
+
token, owner, repo = config_result
|
|
169
|
+
return {"owner": owner, "repo": repo, "token": token}
|
|
170
|
+
return config_result or {}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _run_sync_apply(
|
|
174
|
+
orchestrator,
|
|
175
|
+
dry_run: bool,
|
|
176
|
+
verbose: bool,
|
|
177
|
+
force_local: bool,
|
|
178
|
+
force_github: bool,
|
|
179
|
+
console_inst,
|
|
180
|
+
) -> None:
|
|
181
|
+
"""Run a dry-run preview then, unless --dry-run, confirm and apply changes."""
|
|
182
|
+
report = orchestrator.sync_all_issues(dry_run=True)
|
|
183
|
+
if report.error:
|
|
184
|
+
console_inst.print(f"โ Sync error: {report.error}", style="bold red")
|
|
185
|
+
sys.exit(1)
|
|
186
|
+
|
|
187
|
+
if verbose:
|
|
188
|
+
report.display_verbose()
|
|
189
|
+
else:
|
|
190
|
+
report.display_brief()
|
|
191
|
+
console_inst.print()
|
|
192
|
+
|
|
193
|
+
if dry_run:
|
|
194
|
+
console_inst.print("[dim]Dry-run mode: No changes applied[/dim]")
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
if report.has_conflicts():
|
|
198
|
+
if force_local:
|
|
199
|
+
console_inst.print(
|
|
200
|
+
"[yellow]โ ๏ธ Conflicts detected - using --force-local[/yellow]"
|
|
201
|
+
)
|
|
202
|
+
elif force_github:
|
|
203
|
+
console_inst.print(
|
|
204
|
+
"[yellow]โ ๏ธ Conflicts detected - using --force-github[/yellow]"
|
|
205
|
+
)
|
|
206
|
+
else:
|
|
207
|
+
console_inst.print(
|
|
208
|
+
"[red]โ Conflicts detected. Use --force-local or --force-github[/red]"
|
|
209
|
+
)
|
|
210
|
+
sys.exit(1)
|
|
211
|
+
|
|
212
|
+
if report.has_changes() and not click.confirm("Apply these changes?"):
|
|
213
|
+
console_inst.print("โ Sync cancelled", style="red")
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
console_inst.print("[cyan]๐ Applying changes...[/cyan]")
|
|
217
|
+
apply_report = orchestrator.sync_all_issues(
|
|
218
|
+
dry_run=False, force_local=force_local, force_remote=force_github
|
|
219
|
+
)
|
|
220
|
+
if apply_report.error:
|
|
221
|
+
console_inst.print(
|
|
222
|
+
f"โ Error applying sync: {apply_report.error}", style="bold red"
|
|
223
|
+
)
|
|
224
|
+
sys.exit(1)
|
|
225
|
+
|
|
226
|
+
console_inst.print()
|
|
227
|
+
console_inst.print("[green]โ
Sync complete![/green]")
|
|
228
|
+
console_inst.print(f" โข {apply_report.issues_up_to_date} up-to-date")
|
|
229
|
+
console_inst.print(f" โข {apply_report.issues_needs_push} pushed")
|
|
230
|
+
console_inst.print(f" โข {apply_report.issues_needs_pull} pulled")
|
|
231
|
+
if apply_report.conflicts_detected > 0:
|
|
232
|
+
console_inst.print(f" โข {apply_report.conflicts_detected} conflicts resolved")
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@git.command("sync")
|
|
236
|
+
@click.option(
|
|
237
|
+
"--dry-run",
|
|
238
|
+
is_flag=True,
|
|
239
|
+
help="Preview changes without applying",
|
|
240
|
+
)
|
|
241
|
+
@click.option("--verbose", is_flag=True, help="Show detailed sync information")
|
|
242
|
+
@click.option(
|
|
243
|
+
"--force-local",
|
|
244
|
+
is_flag=True,
|
|
245
|
+
help="Resolve conflicts by keeping local changes",
|
|
246
|
+
)
|
|
247
|
+
@click.option(
|
|
248
|
+
"--force-github",
|
|
249
|
+
is_flag=True,
|
|
250
|
+
help="Resolve conflicts by keeping GitHub changes",
|
|
251
|
+
)
|
|
252
|
+
@click.option(
|
|
253
|
+
"--backend",
|
|
254
|
+
type=click.Choice(["github", "git"]),
|
|
255
|
+
help="Sync backend to use (github or git)",
|
|
256
|
+
)
|
|
257
|
+
@click.pass_context
|
|
258
|
+
@require_initialized
|
|
259
|
+
def sync_git(
|
|
260
|
+
ctx: click.Context,
|
|
261
|
+
dry_run: bool,
|
|
262
|
+
verbose: bool,
|
|
263
|
+
force_local: bool,
|
|
264
|
+
force_github: bool,
|
|
265
|
+
backend: str | None,
|
|
266
|
+
) -> None:
|
|
267
|
+
"""Sync roadmap with remote repository.
|
|
268
|
+
|
|
269
|
+
Supports multiple backends:
|
|
270
|
+
- github: GitHub issues API (requires GitHub config)
|
|
271
|
+
- git: Vanilla Git push/pull (works with any Git hosting)
|
|
272
|
+
|
|
273
|
+
Two-way sync:
|
|
274
|
+
- Push local changes to remote
|
|
275
|
+
- Pull remote changes to local
|
|
276
|
+
- Detect and resolve conflicts
|
|
277
|
+
|
|
278
|
+
Examples:
|
|
279
|
+
# Preview what will be synced
|
|
280
|
+
roadmap git sync --dry-run
|
|
281
|
+
|
|
282
|
+
# Sync all changes
|
|
283
|
+
roadmap git sync
|
|
284
|
+
|
|
285
|
+
# Sync with specific backend
|
|
286
|
+
roadmap git sync --backend=git
|
|
287
|
+
|
|
288
|
+
# Sync with conflict resolution
|
|
289
|
+
roadmap git sync --force-local
|
|
290
|
+
"""
|
|
291
|
+
from roadmap.adapters.cli.services.sync_service import get_sync_backend
|
|
292
|
+
from roadmap.adapters.sync import detect_backend_from_config
|
|
293
|
+
|
|
294
|
+
core = ctx.obj["core"]
|
|
295
|
+
console_inst = get_console()
|
|
296
|
+
|
|
297
|
+
try:
|
|
298
|
+
config = _load_github_config(core)
|
|
299
|
+
backend_type: Literal["github", "git"] = (
|
|
300
|
+
backend if backend else detect_backend_from_config(config) # type: ignore[assignment]
|
|
301
|
+
)
|
|
302
|
+
console_inst.print(
|
|
303
|
+
f"๐ Syncing with {backend_type.upper()} backend", style="bold cyan"
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
sync_backend = get_sync_backend(backend_type, core, config)
|
|
307
|
+
if not sync_backend:
|
|
308
|
+
console_inst.print(
|
|
309
|
+
f"โ Failed to initialize {backend_type} backend", style="bold red"
|
|
310
|
+
)
|
|
311
|
+
hint = (
|
|
312
|
+
" Ensure you're in a Git repository"
|
|
313
|
+
if backend_type == "git"
|
|
314
|
+
else " GitHub config may be missing or incomplete"
|
|
315
|
+
)
|
|
316
|
+
console_inst.print(hint, style="yellow")
|
|
317
|
+
sys.exit(1)
|
|
318
|
+
|
|
319
|
+
from roadmap.adapters.sync import SyncMergeOrchestrator
|
|
320
|
+
from roadmap.core.services.sync.sync_conflict_resolver import (
|
|
321
|
+
SyncConflictResolver,
|
|
322
|
+
)
|
|
323
|
+
from roadmap.core.services.sync.sync_state_comparator import SyncStateComparator
|
|
324
|
+
|
|
325
|
+
orchestrator = SyncMergeOrchestrator(
|
|
326
|
+
core,
|
|
327
|
+
sync_backend,
|
|
328
|
+
state_comparator=SyncStateComparator(),
|
|
329
|
+
conflict_resolver=SyncConflictResolver(),
|
|
330
|
+
)
|
|
331
|
+
_run_sync_apply(
|
|
332
|
+
orchestrator, dry_run, verbose, force_local, force_github, console_inst
|
|
333
|
+
)
|
|
334
|
+
except Exception as e:
|
|
335
|
+
handle_cli_error(
|
|
336
|
+
error=e,
|
|
337
|
+
operation="sync",
|
|
338
|
+
entity_type="git",
|
|
339
|
+
entity_id="repository",
|
|
340
|
+
context={},
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
@git.command("status")
|
|
345
|
+
@click.pass_context
|
|
346
|
+
@require_initialized
|
|
347
|
+
def git_status(ctx: click.Context):
|
|
348
|
+
"""Show Git repository status and roadmap integration info."""
|
|
349
|
+
core = ctx.obj["core"]
|
|
350
|
+
|
|
351
|
+
display = GitStatusDisplay(console)
|
|
352
|
+
|
|
353
|
+
try:
|
|
354
|
+
git_context = core.git.get_context()
|
|
355
|
+
|
|
356
|
+
if not git_context.get("is_git_repo", False):
|
|
357
|
+
display.show_not_git_repo()
|
|
358
|
+
return
|
|
359
|
+
|
|
360
|
+
display.show_header()
|
|
361
|
+
display.show_repository_info(git_context)
|
|
362
|
+
display.show_current_branch(git_context)
|
|
363
|
+
|
|
364
|
+
branch_issues = core.git.get_branch_linked_issues()
|
|
365
|
+
current_branch = git_context.get("current_branch", "")
|
|
366
|
+
display.show_branch_issue_links(branch_issues, current_branch, core)
|
|
367
|
+
|
|
368
|
+
display.show_recent_commits(core)
|
|
369
|
+
|
|
370
|
+
except Exception as e:
|
|
371
|
+
handle_cli_error(
|
|
372
|
+
error=e,
|
|
373
|
+
operation="git_status",
|
|
374
|
+
entity_type="git",
|
|
375
|
+
entity_id="repository",
|
|
376
|
+
context={},
|
|
377
|
+
fatal=False,
|
|
378
|
+
)
|
|
379
|
+
display.show_error(e)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
@git.command("branch")
|
|
383
|
+
@click.argument("issue_id")
|
|
384
|
+
@click.option(
|
|
385
|
+
"--checkout/--no-checkout", default=True, help="Checkout the branch after creation"
|
|
386
|
+
)
|
|
387
|
+
@click.pass_context
|
|
388
|
+
def git_branch(ctx: click.Context, issue_id: str, checkout: bool):
|
|
389
|
+
"""Create a Git branch for an issue."""
|
|
390
|
+
core = ctx.obj["core"]
|
|
391
|
+
|
|
392
|
+
handler = GitBranchHandler(console)
|
|
393
|
+
handler.create_branch(core, issue_id, checkout=checkout)
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def _validate_branch_environment(core) -> bool:
|
|
397
|
+
"""Validate roadmap and git environment for branch creation.
|
|
398
|
+
|
|
399
|
+
Args:
|
|
400
|
+
core: RoadmapCore instance
|
|
401
|
+
|
|
402
|
+
Returns:
|
|
403
|
+
True if environment is valid
|
|
404
|
+
"""
|
|
405
|
+
handler = GitBranchHandler(console)
|
|
406
|
+
return handler.validate_branch_environment(core)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def _get_and_validate_issue(core, issue_id: str):
|
|
410
|
+
"""Get and validate issue exists.
|
|
411
|
+
|
|
412
|
+
Args:
|
|
413
|
+
core: RoadmapCore instance
|
|
414
|
+
issue_id: Issue ID to retrieve
|
|
415
|
+
|
|
416
|
+
Returns:
|
|
417
|
+
Issue object or None if not found
|
|
418
|
+
"""
|
|
419
|
+
handler = GitBranchHandler(console)
|
|
420
|
+
return handler.get_and_validate_issue(core, issue_id)
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def _safe_create_branch(git, issue, checkout=True) -> bool:
|
|
424
|
+
"""Safely create branch with fallback attempts.
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
git: Git executor
|
|
428
|
+
issue: Issue object
|
|
429
|
+
checkout: Whether to checkout the new branch
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
True if branch was created
|
|
433
|
+
"""
|
|
434
|
+
handler = GitBranchHandler(console)
|
|
435
|
+
return handler._safe_create_branch(git, issue, checkout=checkout)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def _display_branch_success(branch_name: str, issue, checkout: bool) -> None:
|
|
439
|
+
"""Display success messages for branch creation.
|
|
440
|
+
|
|
441
|
+
Args:
|
|
442
|
+
branch_name: Name of created branch
|
|
443
|
+
issue: Issue object
|
|
444
|
+
checkout: Whether branch was checked out
|
|
445
|
+
"""
|
|
446
|
+
handler = GitBranchHandler(console)
|
|
447
|
+
handler._display_branch_success(branch_name, issue, checkout)
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
def _update_issue_status_if_needed(core, issue, issue_id: str) -> None:
|
|
451
|
+
"""Update issue status to in-progress if it's todo.
|
|
452
|
+
|
|
453
|
+
Args:
|
|
454
|
+
core: RoadmapCore instance
|
|
455
|
+
issue: Issue object
|
|
456
|
+
issue_id: Issue ID
|
|
457
|
+
"""
|
|
458
|
+
handler = GitBranchHandler(console)
|
|
459
|
+
handler._update_issue_status_if_needed(core, issue, issue_id)
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
@git.command("link")
|
|
463
|
+
@click.argument("issue_id")
|
|
464
|
+
@click.pass_context
|
|
465
|
+
@require_initialized
|
|
466
|
+
def git_link(ctx: click.Context, issue_id: str):
|
|
467
|
+
"""Link an issue to the current Git branch."""
|
|
468
|
+
core = ctx.obj["core"]
|
|
469
|
+
|
|
470
|
+
handler = GitBranchHandler(console)
|
|
471
|
+
handler.link_issue_to_branch(core, issue_id)
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
# Register hooks-config command
|
|
475
|
+
git.add_command(hooks_config, name="hooks-config")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Git command handlers for CLI operations."""
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Handler for GitHub authentication setup in CLI."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
import structlog
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
|
|
7
|
+
from roadmap.adapters.github.github import GitHubClient
|
|
8
|
+
from roadmap.infrastructure.security.credentials import CredentialManager
|
|
9
|
+
|
|
10
|
+
logger = structlog.get_logger()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class GitAuthenticationHandler:
|
|
14
|
+
"""Handles GitHub authentication setup and management."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, console: Console):
|
|
17
|
+
"""Initialize handler with console for output.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
console: Rich Console instance
|
|
21
|
+
"""
|
|
22
|
+
self.console = console
|
|
23
|
+
self.cred_manager = CredentialManager()
|
|
24
|
+
|
|
25
|
+
def setup_github_auth(self, update_token: bool = False):
|
|
26
|
+
"""Set up or update GitHub authentication.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
update_token: If True, force update token; otherwise ask if exists
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
Exception: If authentication setup fails
|
|
33
|
+
"""
|
|
34
|
+
existing_token = None
|
|
35
|
+
|
|
36
|
+
if not update_token:
|
|
37
|
+
try:
|
|
38
|
+
existing_token = self.cred_manager.get_token()
|
|
39
|
+
if existing_token:
|
|
40
|
+
self.console.print("๐ Found existing GitHub credentials")
|
|
41
|
+
if click.confirm("Use existing GitHub token?"):
|
|
42
|
+
logger.info("github_auth_using_existing")
|
|
43
|
+
self.console.print("โ
GitHub authentication configured")
|
|
44
|
+
return
|
|
45
|
+
elif not click.confirm("Update GitHub token?"):
|
|
46
|
+
self.console.print("Skipped GitHub authentication setup")
|
|
47
|
+
return
|
|
48
|
+
except Exception as e:
|
|
49
|
+
logger.debug(
|
|
50
|
+
"existing_token_check_failed",
|
|
51
|
+
error=str(e),
|
|
52
|
+
action="check_existing_token",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Get new token from user
|
|
56
|
+
self.console.print("๐ GitHub Authentication Setup", style="bold cyan")
|
|
57
|
+
self.console.print()
|
|
58
|
+
self.console.print(
|
|
59
|
+
"You'll need a Personal Access Token with 'repo' scope to sync with GitHub."
|
|
60
|
+
)
|
|
61
|
+
self.console.print("Create one here: https://github.com/settings/tokens/new")
|
|
62
|
+
self.console.print()
|
|
63
|
+
self.console.print(
|
|
64
|
+
"Required scopes: repo (full control of private repositories)",
|
|
65
|
+
style="dim",
|
|
66
|
+
)
|
|
67
|
+
self.console.print()
|
|
68
|
+
|
|
69
|
+
token = click.prompt("Enter your GitHub Personal Access Token", hide_input=True)
|
|
70
|
+
|
|
71
|
+
if not token or len(token.strip()) == 0:
|
|
72
|
+
self.console.print("โ Token cannot be empty", style="bold red")
|
|
73
|
+
logger.warning("github_auth_empty_token", severity="operational")
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
# Validate token
|
|
77
|
+
self.console.print("๐งช Validating GitHub token...", style="cyan")
|
|
78
|
+
logger.debug("github_token_validating")
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
client = GitHubClient(token)
|
|
82
|
+
# Test connection and authentication
|
|
83
|
+
user_data = client.test_authentication()
|
|
84
|
+
username = user_data.get("login", "user")
|
|
85
|
+
self.console.print(
|
|
86
|
+
f"โ
Token valid (authenticated as @{username})", style="green"
|
|
87
|
+
)
|
|
88
|
+
logger.info("github_token_valid", username=username)
|
|
89
|
+
except Exception as e:
|
|
90
|
+
self.console.print(f"โ Token validation failed: {e}", style="bold red")
|
|
91
|
+
logger.error(
|
|
92
|
+
"github_token_validation_error",
|
|
93
|
+
error=str(e),
|
|
94
|
+
error_type=type(e).__name__,
|
|
95
|
+
severity="infrastructure",
|
|
96
|
+
)
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
# Store token
|
|
100
|
+
try:
|
|
101
|
+
if self.cred_manager.store_token(token):
|
|
102
|
+
self.console.print("โ
GitHub authentication configured", style="green")
|
|
103
|
+
self.console.print(
|
|
104
|
+
"Token stored securely in system keychain",
|
|
105
|
+
style="dim",
|
|
106
|
+
)
|
|
107
|
+
logger.info("github_token_stored")
|
|
108
|
+
else:
|
|
109
|
+
self.console.print(
|
|
110
|
+
"โ ๏ธ Token validation succeeded but storage failed",
|
|
111
|
+
style="yellow",
|
|
112
|
+
)
|
|
113
|
+
logger.warning("github_token_storage_failed", severity="operational")
|
|
114
|
+
except Exception as e:
|
|
115
|
+
self.console.print(
|
|
116
|
+
f"โ ๏ธ Token validation succeeded but could not store: {e}",
|
|
117
|
+
style="yellow",
|
|
118
|
+
)
|
|
119
|
+
logger.warning(
|
|
120
|
+
"github_token_storage_error",
|
|
121
|
+
error=str(e),
|
|
122
|
+
error_type=type(e).__name__,
|
|
123
|
+
severity="system_error",
|
|
124
|
+
)
|