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,56 @@
|
|
|
1
|
+
"""Low-level Git command executor."""
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class GitCommandExecutor:
|
|
8
|
+
"""Executes Git commands and handles subprocess interaction."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, repo_path: Path | None = None):
|
|
11
|
+
"""Initialize executor with repository path."""
|
|
12
|
+
self.repo_path = repo_path or Path.cwd()
|
|
13
|
+
self._git_dir = self._find_git_directory()
|
|
14
|
+
|
|
15
|
+
def _find_git_directory(self) -> Path | None:
|
|
16
|
+
"""Find the .git directory by walking up the directory tree."""
|
|
17
|
+
current = self.repo_path.resolve()
|
|
18
|
+
|
|
19
|
+
while current != current.parent:
|
|
20
|
+
git_dir = current / ".git"
|
|
21
|
+
if git_dir.exists():
|
|
22
|
+
return git_dir
|
|
23
|
+
current = current.parent
|
|
24
|
+
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
def is_git_repository(self) -> bool:
|
|
28
|
+
"""Check if current directory is in a Git repository."""
|
|
29
|
+
if self._git_dir is None:
|
|
30
|
+
self._git_dir = self._find_git_directory()
|
|
31
|
+
return self._git_dir is not None
|
|
32
|
+
|
|
33
|
+
def run(self, args: list[str], cwd: Path | None = None) -> str | None:
|
|
34
|
+
"""Run a git command and return the output.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
args: Git command arguments (without 'git' prefix)
|
|
38
|
+
cwd: Working directory for command execution
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Command output stripped of whitespace, or None if command fails
|
|
42
|
+
"""
|
|
43
|
+
if not self.is_git_repository():
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
result = subprocess.run(
|
|
48
|
+
["git"] + args,
|
|
49
|
+
cwd=cwd or self.repo_path,
|
|
50
|
+
capture_output=True,
|
|
51
|
+
text=True,
|
|
52
|
+
check=True,
|
|
53
|
+
)
|
|
54
|
+
return result.stdout.strip()
|
|
55
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
56
|
+
return None
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"""Git commit analysis and issue linking."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from structlog import get_logger
|
|
8
|
+
|
|
9
|
+
from roadmap.adapters.git.git import GitCommit
|
|
10
|
+
from roadmap.adapters.git.git_command_executor import GitCommandExecutor
|
|
11
|
+
from roadmap.common.datetime_parser import parse_datetime
|
|
12
|
+
|
|
13
|
+
logger = get_logger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class GitCommitAnalyzer:
|
|
17
|
+
"""Analyzes Git commits and links them to roadmap issues."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, repo_path: Path | None = None):
|
|
20
|
+
"""Initialize commit analyzer."""
|
|
21
|
+
self.executor = GitCommandExecutor(repo_path)
|
|
22
|
+
self.repo_path = repo_path or Path.cwd()
|
|
23
|
+
|
|
24
|
+
def _parse_commit_line(self, line: str) -> tuple | None:
|
|
25
|
+
"""Parse single commit log line.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
line: Commit log line in format: hash|author|date|message
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Tuple of (hash, author, date, message) or None if parsing fails
|
|
32
|
+
"""
|
|
33
|
+
if not line.strip():
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
hash_val, author, date_str, message = line.split("|", 3)
|
|
38
|
+
date = parse_datetime(date_str.replace(" ", "T"), "iso")
|
|
39
|
+
return (hash_val, author, date, message)
|
|
40
|
+
except Exception as e:
|
|
41
|
+
logger.debug("parse_commit_line_failed", line=line, error=str(e))
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
def _extract_file_stats(self, stat_output: str | None) -> tuple[list, int, int]:
|
|
45
|
+
"""Extract file changes and insertion/deletion counts from stat output.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
stat_output: Git show --stat output
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Tuple of (files_changed list, insertions count, deletions count)
|
|
52
|
+
"""
|
|
53
|
+
files_changed = []
|
|
54
|
+
insertions = deletions = 0
|
|
55
|
+
|
|
56
|
+
if not stat_output:
|
|
57
|
+
return files_changed, insertions, deletions
|
|
58
|
+
|
|
59
|
+
for stat_line in stat_output.split("\n"):
|
|
60
|
+
if " | " in stat_line:
|
|
61
|
+
file_path = stat_line.split(" | ")[0].strip()
|
|
62
|
+
files_changed.append(file_path)
|
|
63
|
+
elif "insertion" in stat_line or "deletion" in stat_line:
|
|
64
|
+
numbers = re.findall(r"(\d+) insertion", stat_line)
|
|
65
|
+
if numbers:
|
|
66
|
+
insertions = int(numbers[0])
|
|
67
|
+
numbers = re.findall(r"(\d+) deletion", stat_line)
|
|
68
|
+
if numbers:
|
|
69
|
+
deletions = int(numbers[0])
|
|
70
|
+
|
|
71
|
+
return files_changed, insertions, deletions
|
|
72
|
+
|
|
73
|
+
def _build_commit_object(
|
|
74
|
+
self,
|
|
75
|
+
hash_val: str,
|
|
76
|
+
author: str,
|
|
77
|
+
date,
|
|
78
|
+
message: str,
|
|
79
|
+
files_changed: list,
|
|
80
|
+
insertions: int,
|
|
81
|
+
deletions: int,
|
|
82
|
+
) -> GitCommit | None:
|
|
83
|
+
"""Build GitCommit object from parsed data.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
hash_val: Commit hash
|
|
87
|
+
author: Author name
|
|
88
|
+
date: Commit date
|
|
89
|
+
message: Commit message
|
|
90
|
+
files_changed: List of changed files
|
|
91
|
+
insertions: Number of insertions
|
|
92
|
+
deletions: Number of deletions
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
GitCommit object or None if date is invalid
|
|
96
|
+
"""
|
|
97
|
+
if date is None:
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
return GitCommit(
|
|
101
|
+
hash=hash_val,
|
|
102
|
+
author=author,
|
|
103
|
+
date=date,
|
|
104
|
+
message=message,
|
|
105
|
+
files_changed=files_changed,
|
|
106
|
+
insertions=insertions,
|
|
107
|
+
deletions=deletions,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def get_recent_commits(
|
|
111
|
+
self, count: int = 10, since: str | None = None
|
|
112
|
+
) -> list[GitCommit]:
|
|
113
|
+
"""Get recent commits with detailed information.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
count: Number of commits to retrieve
|
|
117
|
+
since: Optional date string to filter commits
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
List of GitCommit objects
|
|
121
|
+
"""
|
|
122
|
+
args = ["log", f"-{count}", "--pretty=format:%H|%an|%ad|%s", "--date=iso"]
|
|
123
|
+
if since:
|
|
124
|
+
args.extend(["--since", since])
|
|
125
|
+
|
|
126
|
+
output = self.executor.run(args)
|
|
127
|
+
if not output:
|
|
128
|
+
return []
|
|
129
|
+
|
|
130
|
+
commits = []
|
|
131
|
+
for line in output.split("\n"):
|
|
132
|
+
# Parse commit line
|
|
133
|
+
parsed = self._parse_commit_line(line)
|
|
134
|
+
if not parsed:
|
|
135
|
+
continue
|
|
136
|
+
|
|
137
|
+
hash_val, author, date, message = parsed
|
|
138
|
+
|
|
139
|
+
# Get file statistics
|
|
140
|
+
stat_output = self.executor.run(["show", "--stat", "--format=", hash_val])
|
|
141
|
+
files_changed, insertions, deletions = self._extract_file_stats(stat_output)
|
|
142
|
+
|
|
143
|
+
# Build and add commit object
|
|
144
|
+
commit = self._build_commit_object(
|
|
145
|
+
hash_val, author, date, message, files_changed, insertions, deletions
|
|
146
|
+
)
|
|
147
|
+
if commit:
|
|
148
|
+
commits.append(commit)
|
|
149
|
+
|
|
150
|
+
return commits
|
|
151
|
+
|
|
152
|
+
def get_commits_for_issue(
|
|
153
|
+
self, issue_id: str, since: str | None = None
|
|
154
|
+
) -> list[GitCommit]:
|
|
155
|
+
"""Get all commits that reference a specific issue.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
issue_id: Issue ID to search for
|
|
159
|
+
since: Optional date filter
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
List of commits referencing the issue
|
|
163
|
+
"""
|
|
164
|
+
commits = self.get_recent_commits(count=100, since=since)
|
|
165
|
+
return [
|
|
166
|
+
commit
|
|
167
|
+
for commit in commits
|
|
168
|
+
if issue_id in commit.extract_roadmap_references()
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
def parse_commit_message_for_updates(self, commit: GitCommit) -> dict[str, Any]:
|
|
172
|
+
"""Parse commit message for roadmap updates.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
commit: GitCommit object to analyze
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
Dictionary with potential updates (status, progress_percentage)
|
|
179
|
+
"""
|
|
180
|
+
updates = {}
|
|
181
|
+
|
|
182
|
+
# Extract progress
|
|
183
|
+
progress = commit.extract_progress_info()
|
|
184
|
+
if progress is not None:
|
|
185
|
+
updates["progress_percentage"] = min(100.0, max(0.0, progress))
|
|
186
|
+
# If progress is set but not 100%, assume work is in progress
|
|
187
|
+
if 0 < progress < 100:
|
|
188
|
+
updates["status"] = "in-progress"
|
|
189
|
+
|
|
190
|
+
# Check for completion indicators (enhanced patterns)
|
|
191
|
+
completion_patterns = [
|
|
192
|
+
# Original roadmap patterns
|
|
193
|
+
r"\[closes roadmap:[a-f0-9]{8}\]",
|
|
194
|
+
r"\[fixes roadmap:[a-f0-9]{8}\]",
|
|
195
|
+
# GitHub/GitLab style completion patterns
|
|
196
|
+
r"\b(?:fix|fixes|fixed|close|closes|closed|resolve|resolves|resolved)\s+#[a-f0-9]{8}",
|
|
197
|
+
# General completion indicators
|
|
198
|
+
r"\b(?:complete|completed|done|finished|finish)\b.*roadmap",
|
|
199
|
+
r"\b(?:close|closes|fix|fixes|resolve|resolves)\b.*roadmap",
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
for pattern in completion_patterns:
|
|
203
|
+
if re.search(pattern, commit.message, re.IGNORECASE):
|
|
204
|
+
updates["status"] = "closed"
|
|
205
|
+
updates["progress_percentage"] = 100.0
|
|
206
|
+
break
|
|
207
|
+
|
|
208
|
+
# Check for work-in-progress indicators
|
|
209
|
+
wip_patterns = [
|
|
210
|
+
r"\b(?:wip|work in progress|working on)\b",
|
|
211
|
+
r"\[wip\]",
|
|
212
|
+
r"start(?:ed|ing)?.*#[a-f0-9]{8}",
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
for pattern in wip_patterns:
|
|
216
|
+
if re.search(pattern, commit.message, re.IGNORECASE):
|
|
217
|
+
if "status" not in updates: # Don't override completion status
|
|
218
|
+
updates["status"] = "in-progress"
|
|
219
|
+
break
|
|
220
|
+
|
|
221
|
+
return updates
|
|
222
|
+
|
|
223
|
+
def _extract_commit_reference(self, commit: "GitCommit") -> dict:
|
|
224
|
+
"""Extract commit reference metadata."""
|
|
225
|
+
return {
|
|
226
|
+
"hash": commit.hash,
|
|
227
|
+
"message": commit.message,
|
|
228
|
+
"date": commit.date.isoformat() if commit.date else None,
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
def _build_update_data(self, issue, commit: "GitCommit", updates: dict) -> dict:
|
|
232
|
+
"""Build update data from commit and parsed updates."""
|
|
233
|
+
update_data = {}
|
|
234
|
+
|
|
235
|
+
# Apply status and progress updates
|
|
236
|
+
if "status" in updates:
|
|
237
|
+
update_data["status"] = updates["status"]
|
|
238
|
+
if "progress_percentage" in updates:
|
|
239
|
+
update_data["progress_percentage"] = updates["progress_percentage"]
|
|
240
|
+
|
|
241
|
+
# Add commit reference to content
|
|
242
|
+
commit_note = (
|
|
243
|
+
f"\n\n**Auto-updated from commit {commit.short_hash}:** {commit.message}"
|
|
244
|
+
)
|
|
245
|
+
if issue.content:
|
|
246
|
+
update_data["content"] = issue.content + commit_note
|
|
247
|
+
else:
|
|
248
|
+
update_data["content"] = commit_note.strip()
|
|
249
|
+
|
|
250
|
+
# Add commit to git_commits list if not already present
|
|
251
|
+
current_commits = issue.git_commits or []
|
|
252
|
+
commit_ref = self._extract_commit_reference(commit)
|
|
253
|
+
if not any(c.get("hash") == commit.hash for c in current_commits):
|
|
254
|
+
current_commits.append(commit_ref)
|
|
255
|
+
update_data["git_commits"] = current_commits
|
|
256
|
+
|
|
257
|
+
return update_data
|
|
258
|
+
|
|
259
|
+
def _process_single_issue(
|
|
260
|
+
self,
|
|
261
|
+
roadmap_core,
|
|
262
|
+
issue_id: str,
|
|
263
|
+
commit: "GitCommit",
|
|
264
|
+
updates: dict,
|
|
265
|
+
results: dict,
|
|
266
|
+
) -> None:
|
|
267
|
+
"""Process a single issue update from a commit."""
|
|
268
|
+
try:
|
|
269
|
+
# Load the issue
|
|
270
|
+
issue = roadmap_core.issues.get(issue_id)
|
|
271
|
+
if not issue:
|
|
272
|
+
results["errors"].append(f"Issue {issue_id} not found")
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
# Build and apply updates
|
|
276
|
+
update_data = self._build_update_data(issue, commit, updates)
|
|
277
|
+
roadmap_core.issues.update(issue_id, **update_data)
|
|
278
|
+
|
|
279
|
+
# Track result
|
|
280
|
+
if updates.get("status") == "closed":
|
|
281
|
+
results["closed"].append(issue_id)
|
|
282
|
+
else:
|
|
283
|
+
results["updated"].append(issue_id)
|
|
284
|
+
|
|
285
|
+
except Exception as e:
|
|
286
|
+
results["errors"].append(f"Error updating issue {issue_id}: {str(e)}")
|
|
287
|
+
|
|
288
|
+
def _process_commit_issues(
|
|
289
|
+
self, roadmap_core, commit: "GitCommit", results: dict
|
|
290
|
+
) -> None:
|
|
291
|
+
"""Process all issues referenced in a commit."""
|
|
292
|
+
try:
|
|
293
|
+
# Get referenced issues
|
|
294
|
+
issue_ids = commit.extract_roadmap_references()
|
|
295
|
+
if not issue_ids:
|
|
296
|
+
return
|
|
297
|
+
|
|
298
|
+
# Parse updates from commit message
|
|
299
|
+
updates = self.parse_commit_message_for_updates(commit)
|
|
300
|
+
if not updates:
|
|
301
|
+
return
|
|
302
|
+
|
|
303
|
+
# Update each issue
|
|
304
|
+
for issue_id in issue_ids:
|
|
305
|
+
self._process_single_issue(
|
|
306
|
+
roadmap_core, issue_id, commit, updates, results
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
except Exception as e:
|
|
310
|
+
results["errors"].append(
|
|
311
|
+
f"Error processing commit {commit.short_hash}: {str(e)}"
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
def auto_update_issues_from_commits(
|
|
315
|
+
self, roadmap_core, commits: list["GitCommit"] | None = None
|
|
316
|
+
) -> dict[str, list[str]]:
|
|
317
|
+
"""Automatically update issues based on commit messages.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
roadmap_core: RoadmapCore instance for issue operations
|
|
321
|
+
commits: List of commits to process. If None, processes recent commits.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
Dictionary with 'updated', 'closed', and 'errors' lists
|
|
325
|
+
"""
|
|
326
|
+
if commits is None:
|
|
327
|
+
commits = self.get_recent_commits(count=10)
|
|
328
|
+
|
|
329
|
+
results = {"updated": [], "closed": [], "errors": []}
|
|
330
|
+
|
|
331
|
+
for commit in commits:
|
|
332
|
+
self._process_commit_issues(roadmap_core, commit, results)
|
|
333
|
+
|
|
334
|
+
return results
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Git hooks and workflow automation for roadmap integration.
|
|
2
|
+
|
|
3
|
+
This module provides re-exports of hook management and workflow automation
|
|
4
|
+
classes for backward compatibility. New code should import from the specific
|
|
5
|
+
modules directly:
|
|
6
|
+
- git_hooks_manager.GitHookManager
|
|
7
|
+
- workflow_automation.WorkflowAutomation
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from roadmap.adapters.persistence.parser import IssueParser
|
|
11
|
+
|
|
12
|
+
from .git import GitCommit, GitIntegration
|
|
13
|
+
from .git_hooks_manager import GitHookManager
|
|
14
|
+
from .workflow_automation import WorkflowAutomation
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"GitHookManager",
|
|
18
|
+
"WorkflowAutomation",
|
|
19
|
+
"GitIntegration",
|
|
20
|
+
"GitCommit",
|
|
21
|
+
"IssueParser",
|
|
22
|
+
]
|