gitflow-analytics 3.7.0__tar.gz → 3.7.5__tar.gz
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.
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/PKG-INFO +1 -1
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/_version.py +1 -1
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/cli.py +244 -105
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config/repository.py +9 -1
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config/schema.py +48 -1
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/identity_llm/analysis_pass.py +7 -2
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics.egg-info/PKG-INFO +1 -1
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics.egg-info/SOURCES.txt +0 -39
- gitflow_analytics-3.7.0/docs/CLEANUP_SUMMARY.md +0 -184
- gitflow_analytics-3.7.0/docs/PROJECT_CLEANUP_REPORT.md +0 -233
- gitflow_analytics-3.7.0/docs/STORY_POINTS_CONFIG_SUMMARY.md +0 -107
- gitflow_analytics-3.7.0/docs/_archive/analysis-files/ewtn-critical-security-report.md +0 -180
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_engineer_20250915_085239_236.md +0 -100
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_engineer_20250915_114233_697.md +0 -78
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_engineer_20250915_115330_511.md +0 -80
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_engineer_20250915_120516_669.md +0 -78
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_engineer_20250915_124906_951.md +0 -87
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_engineer_20250915_175540_671.md +0 -78
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_engineer_20250915_214023_300.md +0 -95
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_engineer_20250916_130622_510.md +0 -76
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_ops_20250915_123323_419.md +0 -94
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_ops_20250915_134446_128.md +0 -96
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_ops_20250915_184656_725.md +0 -93
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_research_20250915_091233_023.md +0 -77
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_research_20250915_100404_339.md +0 -77
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/agent_research_20250915_110606_413.md +0 -86
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/system_prompt_20250915_084833_641.md +0 -2289
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/system_prompt_20250915_090830_660.md +0 -2303
- gitflow_analytics-3.7.0/docs/_archive/old-logs/prompts/system_prompt_20250916_130545_822.md +0 -2289
- gitflow_analytics-3.7.0/docs/_archive/old-reports/output/database_qualitative_report_20250630_20250824.md +0 -47
- gitflow_analytics-3.7.0/docs/_archive/old-reports/output/narrative_report_20250630_20250824.md +0 -142
- gitflow_analytics-3.7.0/docs/_archive/old-reports/reports-24week/database_qualitative_report_20250303_20250817.md +0 -55
- gitflow_analytics-3.7.0/docs/_archive/old-reports/reports-24week/narrative_report_20250303_20250817.md +0 -157
- gitflow_analytics-3.7.0/docs/_archive/old-reports/test-ewtn-reports/narrative_report_20250810.md +0 -70
- gitflow_analytics-3.7.0/docs/_archive/old-reports/test-reports/database_qualitative_report_20250908_20250914.md +0 -53
- gitflow_analytics-3.7.0/docs/_archive/old-reports/test-reports/narrative_report_20250908_20250914.md +0 -182
- gitflow_analytics-3.7.0/docs/_archive/old-reports/test-weekly-reports/database_qualitative_report_20250623_20250817.md +0 -67
- gitflow_analytics-3.7.0/docs/_archive/old-reports/test-weekly-reports/narrative_report_20250623_20250817.md +0 -169
- gitflow_analytics-3.7.0/docs/_archive/temp-files/FIX_SUMMARY.md +0 -147
- gitflow_analytics-3.7.0/docs/guides/LLM_CLASSIFICATION_GUIDE.md +0 -164
- gitflow_analytics-3.7.0/src/gitflow_analytics/security/reports/__init__.py +0 -5
- gitflow_analytics-3.7.0/src/gitflow_analytics/security/reports/security_report.py +0 -358
- gitflow_analytics-3.7.0/tests/debug_bulk_exists.py +0 -62
- gitflow_analytics-3.7.0/tests/debug_commit_story_points.py +0 -145
- gitflow_analytics-3.7.0/tests/debug_database_storage.py +0 -228
- gitflow_analytics-3.7.0/tests/debug_jira_enrichment.py +0 -110
- gitflow_analytics-3.7.0/tests/debug_story_points.py +0 -121
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/CHANGELOG.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/CLAUDE.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/LICENSE +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/MANIFEST.in +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/REFACTOR.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/SECURITY.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/STRUCTURE.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/_archive/temp-files/PROGRESS_TRACKING_FIXES.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/_archive/temp-files/SYNTAX_ERROR_FIX.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/architecture/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/architecture/branch-analysis-optimization.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/architecture/caching-strategy.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/architecture/llm-classifier-refactoring.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/architecture/ml-pipeline.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/configuration/configuration.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/deployment/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/design/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/design/circuit-breaker-implementation.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/design/commit-classification-design.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/design/git_pm_correlation_design.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/design/platform-agnostic-pm-framework.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/design/qualitative_data_extraction.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/developer/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/developer/contributing.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/developer/development-setup.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/developer/training-guide.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/examples/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/getting-started/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/getting-started/first-analysis.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/getting-started/installation.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/getting-started/quickstart.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/guides/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/guides/chatgpt-setup.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/guides/identity-resolution-enhanced.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/guides/interactive-launcher.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/guides/managing-aliases.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/guides/ml-categorization.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/guides/troubleshooting.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/quick-reference/launcher-and-identity.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/reference/README.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/reference/cache-system.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/reference/cli-commands.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/reference/configuration-schema.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/docs/reference/json-export-schema.md +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/pyproject.toml +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/setup.cfg +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/classification/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/classification/batch_classifier.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/classification/classifier.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/classification/feature_extractor.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/classification/linguist_analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/classification/model.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/cli_wizards/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/cli_wizards/install_wizard.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/cli_wizards/run_launcher.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config/aliases.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config/errors.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config/loader.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config/profiles.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config/validator.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/constants.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/branch_mapper.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/cache.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/data_fetcher.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/git_auth.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/git_timeout_wrapper.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/identity.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/metrics_storage.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/progress.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/schema_version.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/core/subprocess_git.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/extractors/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/extractors/base.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/extractors/ml_tickets.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/extractors/story_points.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/extractors/tickets.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/identity_llm/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/identity_llm/analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/identity_llm/models.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/integrations/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/integrations/github_integration.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/integrations/jira_integration.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/integrations/orchestrator.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/metrics/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/metrics/activity_scoring.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/metrics/branch_health.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/metrics/dora.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/models/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/models/database.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/pm_framework/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/pm_framework/adapters/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/pm_framework/adapters/jira_adapter.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/pm_framework/base.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/pm_framework/models.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/pm_framework/orchestrator.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/pm_framework/registry.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/chatgpt_analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/change_type.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/domain_classifier.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/intent_analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/llm/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/llm/base.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/llm/batch_processor.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/llm/cache.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/llm/cost_tracker.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/llm/openai_client.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/llm/prompts.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/llm/response_parser.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/llm_commit_classifier.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/classifiers/risk_analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/core/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/core/llm_fallback.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/core/nlp_engine.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/core/pattern_cache.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/core/processor.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/enhanced_analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/example_enhanced_usage.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/models/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/models/schemas.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/utils/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/utils/batch_processor.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/utils/cost_tracker.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/utils/metrics.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/qualitative/utils/text_processing.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/analytics_writer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/base.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/branch_health_writer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/classification_writer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/cli_integration.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/csv_writer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/data_models.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/database_report_generator.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/example_usage.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/factory.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/formatters.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/html_generator.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/interfaces.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/json_exporter.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/narrative_writer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/story_point_correlation.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/reports/weekly_trends_writer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/security/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/security/config.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/security/extractors/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/security/extractors/dependency_checker.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/security/extractors/secret_detector.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/security/extractors/vulnerability_scanner.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/security/llm_analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/security/security_analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/training/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/training/model_loader.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/training/pipeline.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/ui/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/ui/progress_display.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/verify_activity.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics.egg-info/dependency_links.txt +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics.egg-info/entry_points.txt +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics.egg-info/requires.txt +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics.egg-info/top_level.txt +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/conftest.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/core/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/core/test_analyzer.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/core/test_cache.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/core/test_data_fetcher.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/core/test_identity.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/core/test_progress.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/extractors/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/integrations/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/metrics/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/models/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/qualitative/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/qualitative/test_basic_integration.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/reports/__init__.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_atomic_caching.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_classification_system.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_cli.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_config.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_config_extends.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_config_profiles.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_config_story_points.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_jira_connection.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_llm_commit_classification.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_march_2025_comparison.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_metrics.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_ml_accuracy.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_ml_components.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_ml_comprehensive.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_ml_integration.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_pm_env_resolution.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_report_abstraction.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_reports.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_story_points_analysis.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_training_pipeline.py +0 -0
- {gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/tests/test_two_step_process.py +0 -0
|
@@ -944,7 +944,7 @@ def analyze(
|
|
|
944
944
|
data_fetcher = GitDataFetcher(
|
|
945
945
|
cache=cache,
|
|
946
946
|
branch_mapping_rules=cfg.analysis.branch_mapping_rules,
|
|
947
|
-
allowed_ticket_platforms=cfg.
|
|
947
|
+
allowed_ticket_platforms=cfg.get_effective_ticket_platforms(),
|
|
948
948
|
exclude_paths=cfg.analysis.exclude_paths,
|
|
949
949
|
)
|
|
950
950
|
|
|
@@ -1135,9 +1135,7 @@ def analyze(
|
|
|
1135
1135
|
analyzer = GitAnalyzer(
|
|
1136
1136
|
cache,
|
|
1137
1137
|
branch_mapping_rules=cfg.analysis.branch_mapping_rules,
|
|
1138
|
-
allowed_ticket_platforms=
|
|
1139
|
-
cfg.analysis, "ticket_platforms", ["jira", "github", "clickup", "linear"]
|
|
1140
|
-
),
|
|
1138
|
+
allowed_ticket_platforms=cfg.get_effective_ticket_platforms(),
|
|
1141
1139
|
exclude_paths=cfg.analysis.exclude_paths,
|
|
1142
1140
|
story_point_patterns=cfg.analysis.story_point_patterns,
|
|
1143
1141
|
ml_categorization_config=ml_config,
|
|
@@ -1164,9 +1162,28 @@ def analyze(
|
|
|
1164
1162
|
# Use a 'repos' directory in the config directory for cloned repositories
|
|
1165
1163
|
config_dir = Path(config).parent if config else Path.cwd()
|
|
1166
1164
|
repos_dir = config_dir / "repos"
|
|
1167
|
-
|
|
1165
|
+
|
|
1166
|
+
# Progress callback for repository discovery
|
|
1167
|
+
def discovery_progress(repo_name, count):
|
|
1168
|
+
if display and display._live:
|
|
1169
|
+
display.update_progress_task(
|
|
1170
|
+
"main",
|
|
1171
|
+
description=f"🔍 Discovering: {repo_name} ({count} repos checked)",
|
|
1172
|
+
completed=15 + min(count % 5, 4), # Show some movement
|
|
1173
|
+
)
|
|
1174
|
+
else:
|
|
1175
|
+
# Simple inline progress - just show count
|
|
1176
|
+
click.echo(f"\r 📦 Checking repositories... {count}", nl=False)
|
|
1177
|
+
|
|
1178
|
+
discovered_repos = cfg.discover_organization_repositories(
|
|
1179
|
+
clone_base_path=repos_dir, progress_callback=discovery_progress
|
|
1180
|
+
)
|
|
1168
1181
|
repositories_to_analyze = discovered_repos
|
|
1169
1182
|
|
|
1183
|
+
# Clear the progress line
|
|
1184
|
+
if not (display and display._live):
|
|
1185
|
+
click.echo("\r" + " " * 60 + "\r", nl=False) # Clear line
|
|
1186
|
+
|
|
1170
1187
|
if display and display._live:
|
|
1171
1188
|
# We're in full-screen mode, update progress and initialize repo list
|
|
1172
1189
|
display.update_progress_task(
|
|
@@ -1703,14 +1720,14 @@ def analyze(
|
|
|
1703
1720
|
"📊 No commits or batches found for date range - proceeding with data fetch"
|
|
1704
1721
|
)
|
|
1705
1722
|
|
|
1706
|
-
# PROCEED WITH
|
|
1723
|
+
# PROCEED WITH INITIAL FETCH if validation didn't pass
|
|
1707
1724
|
if not validation_passed:
|
|
1708
1725
|
if display:
|
|
1709
1726
|
display.print_status(
|
|
1710
|
-
"Data validation failed - running
|
|
1727
|
+
"Data validation failed - running initial data fetch", "warning"
|
|
1711
1728
|
)
|
|
1712
1729
|
else:
|
|
1713
|
-
click.echo("⚠️ Data validation failed - running
|
|
1730
|
+
click.echo("⚠️ Data validation failed - running initial data fetch")
|
|
1714
1731
|
|
|
1715
1732
|
# Force data fetch for all repositories since we have no batches
|
|
1716
1733
|
repos_needing_analysis = repositories_to_analyze
|
|
@@ -1719,12 +1736,12 @@ def analyze(
|
|
|
1719
1736
|
if repos_needing_analysis:
|
|
1720
1737
|
if display:
|
|
1721
1738
|
display.print_status(
|
|
1722
|
-
f"
|
|
1739
|
+
f"Initial fetch: Fetching data for {len(repos_needing_analysis)} repositories...",
|
|
1723
1740
|
"info",
|
|
1724
1741
|
)
|
|
1725
1742
|
else:
|
|
1726
1743
|
click.echo(
|
|
1727
|
-
f"🚨
|
|
1744
|
+
f"🚨 Initial fetch: Fetching data for {len(repos_needing_analysis)} repositories..."
|
|
1728
1745
|
)
|
|
1729
1746
|
click.echo(
|
|
1730
1747
|
" 📋 Reason: Need to ensure commits and batches exist for classification"
|
|
@@ -1760,89 +1777,163 @@ def analyze(
|
|
|
1760
1777
|
# Check if repo exists, clone if needed (critical for organization mode)
|
|
1761
1778
|
if not repo_path.exists():
|
|
1762
1779
|
if repo_config.github_repo and cfg.github.organization:
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1780
|
+
# Retry logic for cloning
|
|
1781
|
+
max_retries = 2
|
|
1782
|
+
retry_count = 0
|
|
1783
|
+
clone_success = False
|
|
1784
|
+
|
|
1785
|
+
while retry_count <= max_retries and not clone_success:
|
|
1786
|
+
if retry_count > 0:
|
|
1787
|
+
if display:
|
|
1788
|
+
display.print_status(
|
|
1789
|
+
f" 🔄 Retry {retry_count}/{max_retries}: {repo_config.github_repo}",
|
|
1790
|
+
"warning",
|
|
1791
|
+
)
|
|
1792
|
+
else:
|
|
1793
|
+
click.echo(
|
|
1794
|
+
f" 🔄 Retry {retry_count}/{max_retries}: {repo_config.github_repo}"
|
|
1795
|
+
)
|
|
1796
|
+
else:
|
|
1797
|
+
if display:
|
|
1798
|
+
display.print_status(
|
|
1799
|
+
f" 📥 Cloning {repo_config.github_repo} from GitHub...",
|
|
1800
|
+
"info",
|
|
1801
|
+
)
|
|
1802
|
+
else:
|
|
1803
|
+
click.echo(
|
|
1804
|
+
f" 📥 Cloning {repo_config.github_repo} from GitHub..."
|
|
1805
|
+
)
|
|
1806
|
+
|
|
1807
|
+
try:
|
|
1808
|
+
# Ensure parent directory exists
|
|
1809
|
+
repo_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1810
|
+
|
|
1811
|
+
# Build clone URL with authentication
|
|
1812
|
+
clone_url = (
|
|
1813
|
+
f"https://github.com/{repo_config.github_repo}.git"
|
|
1814
|
+
)
|
|
1815
|
+
if cfg.github.token:
|
|
1816
|
+
clone_url = f"https://{cfg.github.token}@github.com/{repo_config.github_repo}.git"
|
|
1817
|
+
|
|
1818
|
+
# Clone using subprocess for better control
|
|
1819
|
+
env = os.environ.copy()
|
|
1820
|
+
env["GIT_TERMINAL_PROMPT"] = "0"
|
|
1821
|
+
env["GIT_ASKPASS"] = ""
|
|
1822
|
+
env["GCM_INTERACTIVE"] = "never"
|
|
1823
|
+
env["GIT_PROGRESS"] = "1" # Force progress output
|
|
1824
|
+
|
|
1825
|
+
cmd = [
|
|
1826
|
+
"git",
|
|
1827
|
+
"clone",
|
|
1828
|
+
"--progress",
|
|
1829
|
+
"--config",
|
|
1830
|
+
"credential.helper=",
|
|
1831
|
+
]
|
|
1832
|
+
if repo_config.branch:
|
|
1833
|
+
cmd.extend(["-b", repo_config.branch])
|
|
1834
|
+
cmd.extend([clone_url, str(repo_path)])
|
|
1835
|
+
|
|
1836
|
+
# Track start time for timeout reporting
|
|
1837
|
+
import time
|
|
1838
|
+
|
|
1839
|
+
start_time = time.time()
|
|
1840
|
+
timeout_seconds = 300 # 5 minutes for large repos
|
|
1841
|
+
|
|
1842
|
+
# Run without capturing stderr to show git progress
|
|
1843
|
+
result = subprocess.run(
|
|
1844
|
+
cmd,
|
|
1845
|
+
env=env,
|
|
1846
|
+
stdout=subprocess.PIPE,
|
|
1847
|
+
stderr=None, # Let stderr (progress) flow to terminal
|
|
1848
|
+
text=True,
|
|
1849
|
+
timeout=timeout_seconds,
|
|
1850
|
+
)
|
|
1797
1851
|
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
if
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1852
|
+
elapsed = time.time() - start_time
|
|
1853
|
+
|
|
1854
|
+
if result.returncode != 0:
|
|
1855
|
+
error_msg = "Clone failed"
|
|
1856
|
+
if any(
|
|
1857
|
+
x in error_msg.lower()
|
|
1858
|
+
for x in [
|
|
1859
|
+
"authentication",
|
|
1860
|
+
"permission denied",
|
|
1861
|
+
"401",
|
|
1862
|
+
"403",
|
|
1863
|
+
]
|
|
1864
|
+
):
|
|
1865
|
+
if display:
|
|
1866
|
+
display.print_status(
|
|
1867
|
+
f" ❌ Authentication failed for {repo_config.github_repo}",
|
|
1868
|
+
"error",
|
|
1869
|
+
)
|
|
1870
|
+
else:
|
|
1871
|
+
click.echo(
|
|
1872
|
+
f" ❌ Authentication failed for {repo_config.github_repo}"
|
|
1873
|
+
)
|
|
1874
|
+
break # Don't retry auth failures
|
|
1875
|
+
else:
|
|
1876
|
+
raise subprocess.CalledProcessError(
|
|
1877
|
+
result.returncode,
|
|
1878
|
+
cmd,
|
|
1879
|
+
result.stdout,
|
|
1880
|
+
result.stderr,
|
|
1881
|
+
)
|
|
1882
|
+
else:
|
|
1883
|
+
clone_success = True
|
|
1804
1884
|
if display:
|
|
1805
1885
|
display.print_status(
|
|
1806
|
-
f"
|
|
1807
|
-
"
|
|
1886
|
+
f" ✅ Cloned {repo_config.github_repo} ({elapsed:.1f}s)",
|
|
1887
|
+
"success",
|
|
1808
1888
|
)
|
|
1809
1889
|
else:
|
|
1810
1890
|
click.echo(
|
|
1811
|
-
f"
|
|
1891
|
+
f" ✅ Cloned {repo_config.github_repo} ({elapsed:.1f}s)"
|
|
1812
1892
|
)
|
|
1813
|
-
|
|
1893
|
+
|
|
1894
|
+
except subprocess.TimeoutExpired:
|
|
1895
|
+
retry_count += 1
|
|
1896
|
+
if display:
|
|
1897
|
+
display.print_status(
|
|
1898
|
+
f" ⏱️ Clone timeout after {timeout_seconds}s: {repo_config.github_repo}",
|
|
1899
|
+
"error",
|
|
1900
|
+
)
|
|
1814
1901
|
else:
|
|
1815
|
-
|
|
1816
|
-
|
|
1902
|
+
click.echo(
|
|
1903
|
+
f" ⏱️ Clone timeout after {timeout_seconds}s: {repo_config.github_repo}"
|
|
1817
1904
|
)
|
|
1905
|
+
# Clean up partial clone
|
|
1906
|
+
if repo_path.exists():
|
|
1907
|
+
import shutil
|
|
1818
1908
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1909
|
+
shutil.rmtree(repo_path, ignore_errors=True)
|
|
1910
|
+
if retry_count > max_retries:
|
|
1911
|
+
if display:
|
|
1912
|
+
display.print_status(
|
|
1913
|
+
f" ❌ Skipping {repo_config.github_repo} after {max_retries} timeouts",
|
|
1914
|
+
"error",
|
|
1915
|
+
)
|
|
1916
|
+
else:
|
|
1917
|
+
click.echo(
|
|
1918
|
+
f" ❌ Skipping {repo_config.github_repo} after {max_retries} timeouts"
|
|
1919
|
+
)
|
|
1920
|
+
break
|
|
1921
|
+
continue # Try again
|
|
1922
|
+
|
|
1923
|
+
except Exception as e:
|
|
1924
|
+
retry_count += 1
|
|
1925
|
+
if display:
|
|
1926
|
+
display.print_status(
|
|
1927
|
+
f" ❌ Clone error: {e}", "error"
|
|
1928
|
+
)
|
|
1929
|
+
else:
|
|
1930
|
+
click.echo(f" ❌ Clone error: {e}")
|
|
1931
|
+
if retry_count > max_retries:
|
|
1932
|
+
break
|
|
1933
|
+
continue # Try again
|
|
1825
1934
|
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
display.print_status(
|
|
1829
|
-
f" ❌ Clone timeout for {repo_config.github_repo}",
|
|
1830
|
-
"error",
|
|
1831
|
-
)
|
|
1832
|
-
else:
|
|
1833
|
-
click.echo(f" ❌ Clone timeout for {repo_config.github_repo}")
|
|
1834
|
-
continue
|
|
1835
|
-
except Exception as e:
|
|
1836
|
-
if display:
|
|
1837
|
-
display.print_status(
|
|
1838
|
-
f" ❌ Failed to clone {repo_config.github_repo}: {e}",
|
|
1839
|
-
"error",
|
|
1840
|
-
)
|
|
1841
|
-
else:
|
|
1842
|
-
click.echo(
|
|
1843
|
-
f" ❌ Failed to clone {repo_config.github_repo}: {e}"
|
|
1844
|
-
)
|
|
1845
|
-
continue
|
|
1935
|
+
if not clone_success:
|
|
1936
|
+
continue # Skip this repo and move to next
|
|
1846
1937
|
else:
|
|
1847
1938
|
# No github_repo configured, can't clone
|
|
1848
1939
|
if display:
|
|
@@ -1928,15 +2019,15 @@ def analyze(
|
|
|
1928
2019
|
|
|
1929
2020
|
if display:
|
|
1930
2021
|
display.print_status(
|
|
1931
|
-
f"
|
|
2022
|
+
f"Initial fetch complete: {total_commits} commits, {total_tickets} tickets",
|
|
1932
2023
|
"success",
|
|
1933
2024
|
)
|
|
1934
2025
|
else:
|
|
1935
2026
|
click.echo(
|
|
1936
|
-
f"🚨
|
|
2027
|
+
f"🚨 Initial fetch complete: {total_commits} commits, {total_tickets} tickets"
|
|
1937
2028
|
)
|
|
1938
2029
|
|
|
1939
|
-
# RE-VALIDATE after
|
|
2030
|
+
# RE-VALIDATE after initial fetch
|
|
1940
2031
|
with cache.get_session() as session:
|
|
1941
2032
|
final_commits = (
|
|
1942
2033
|
session.query(CachedCommit)
|
|
@@ -1961,7 +2052,7 @@ def analyze(
|
|
|
1961
2052
|
)
|
|
1962
2053
|
|
|
1963
2054
|
if final_commits == 0:
|
|
1964
|
-
error_msg = "❌ CRITICAL:
|
|
2055
|
+
error_msg = "❌ CRITICAL: Initial fetch completed but still 0 commits stored in database"
|
|
1965
2056
|
if display:
|
|
1966
2057
|
display.print_status(error_msg, "error")
|
|
1967
2058
|
else:
|
|
@@ -1969,7 +2060,9 @@ def analyze(
|
|
|
1969
2060
|
click.echo(
|
|
1970
2061
|
f" 📅 Date range: {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}"
|
|
1971
2062
|
)
|
|
1972
|
-
click.echo(
|
|
2063
|
+
click.echo(
|
|
2064
|
+
f" 📊 Initial fetch stats: {total_commits} commits reported"
|
|
2065
|
+
)
|
|
1973
2066
|
click.echo(
|
|
1974
2067
|
f" 🗃️ Database result: {final_commits} commits, {final_batches} batches"
|
|
1975
2068
|
)
|
|
@@ -1983,7 +2076,7 @@ def analyze(
|
|
|
1983
2076
|
" - Repository has no commits in the specified time range"
|
|
1984
2077
|
)
|
|
1985
2078
|
raise click.ClickException(
|
|
1986
|
-
"
|
|
2079
|
+
"Initial fetch failed validation - no data available for classification"
|
|
1987
2080
|
)
|
|
1988
2081
|
|
|
1989
2082
|
if display:
|
|
@@ -2342,25 +2435,33 @@ def analyze(
|
|
|
2342
2435
|
env["GIT_TERMINAL_PROMPT"] = "0"
|
|
2343
2436
|
env["GIT_ASKPASS"] = ""
|
|
2344
2437
|
env["GCM_INTERACTIVE"] = "never"
|
|
2438
|
+
env["GIT_PROGRESS"] = "1" # Force progress output
|
|
2345
2439
|
|
|
2346
2440
|
# Build git clone command
|
|
2347
|
-
cmd = [
|
|
2441
|
+
cmd = [
|
|
2442
|
+
"git",
|
|
2443
|
+
"clone",
|
|
2444
|
+
"--progress",
|
|
2445
|
+
"--config",
|
|
2446
|
+
"credential.helper=",
|
|
2447
|
+
]
|
|
2348
2448
|
if repo_config.branch:
|
|
2349
2449
|
cmd.extend(["-b", repo_config.branch])
|
|
2350
2450
|
cmd.extend([clone_url, str(repo_config.path)])
|
|
2351
2451
|
|
|
2352
|
-
# Run with timeout to prevent hanging
|
|
2452
|
+
# Run with timeout to prevent hanging, let progress show on stderr
|
|
2353
2453
|
result = subprocess.run(
|
|
2354
2454
|
cmd,
|
|
2355
2455
|
env=env,
|
|
2356
|
-
|
|
2456
|
+
stdout=subprocess.PIPE,
|
|
2457
|
+
stderr=None, # Let stderr (progress) flow to terminal
|
|
2357
2458
|
text=True,
|
|
2358
|
-
timeout=
|
|
2459
|
+
timeout=120, # Increase timeout for large repos
|
|
2359
2460
|
)
|
|
2360
2461
|
|
|
2361
2462
|
if result.returncode != 0:
|
|
2362
2463
|
raise git.GitCommandError(
|
|
2363
|
-
cmd, result.returncode, stderr=
|
|
2464
|
+
cmd, result.returncode, stderr="Clone failed"
|
|
2364
2465
|
)
|
|
2365
2466
|
except subprocess.TimeoutExpired:
|
|
2366
2467
|
if display:
|
|
@@ -2409,13 +2510,19 @@ def analyze(
|
|
|
2409
2510
|
cmd = [
|
|
2410
2511
|
"git",
|
|
2411
2512
|
"clone",
|
|
2513
|
+
"--progress",
|
|
2412
2514
|
"--config",
|
|
2413
2515
|
"credential.helper=",
|
|
2414
2516
|
clone_url,
|
|
2415
2517
|
str(repo_config.path),
|
|
2416
2518
|
]
|
|
2417
2519
|
result = subprocess.run(
|
|
2418
|
-
cmd,
|
|
2520
|
+
cmd,
|
|
2521
|
+
env=env,
|
|
2522
|
+
stdout=subprocess.PIPE,
|
|
2523
|
+
stderr=None,
|
|
2524
|
+
text=True,
|
|
2525
|
+
timeout=120,
|
|
2419
2526
|
)
|
|
2420
2527
|
if result.returncode != 0:
|
|
2421
2528
|
raise git.GitCommandError(
|
|
@@ -4192,9 +4299,7 @@ def fetch(
|
|
|
4192
4299
|
data_fetcher = GitDataFetcher(
|
|
4193
4300
|
cache=cache,
|
|
4194
4301
|
branch_mapping_rules=getattr(cfg.analysis, "branch_mapping_rules", {}),
|
|
4195
|
-
allowed_ticket_platforms=
|
|
4196
|
-
cfg.analysis, "ticket_platforms", ["jira", "github", "clickup", "linear"]
|
|
4197
|
-
),
|
|
4302
|
+
allowed_ticket_platforms=cfg.get_effective_ticket_platforms(),
|
|
4198
4303
|
exclude_paths=getattr(cfg.analysis, "exclude_paths", None),
|
|
4199
4304
|
)
|
|
4200
4305
|
|
|
@@ -4217,9 +4322,23 @@ def fetch(
|
|
|
4217
4322
|
# Use a 'repos' directory in the config directory for cloned repositories
|
|
4218
4323
|
config_dir = Path(config).parent if config else Path.cwd()
|
|
4219
4324
|
repos_dir = config_dir / "repos"
|
|
4220
|
-
|
|
4325
|
+
|
|
4326
|
+
# Progress callback for repository discovery
|
|
4327
|
+
def discovery_progress(repo_name, count):
|
|
4328
|
+
if display:
|
|
4329
|
+
display.print_status(f" 📦 Checking: {repo_name} ({count})", "info")
|
|
4330
|
+
else:
|
|
4331
|
+
click.echo(f"\r 📦 Checking repositories... {count}", nl=False)
|
|
4332
|
+
|
|
4333
|
+
discovered_repos = cfg.discover_organization_repositories(
|
|
4334
|
+
clone_base_path=repos_dir, progress_callback=discovery_progress
|
|
4335
|
+
)
|
|
4221
4336
|
repositories_to_fetch = discovered_repos
|
|
4222
4337
|
|
|
4338
|
+
# Clear the progress line
|
|
4339
|
+
if not display:
|
|
4340
|
+
click.echo("\r" + " " * 60 + "\r", nl=False) # Clear line
|
|
4341
|
+
|
|
4223
4342
|
if display:
|
|
4224
4343
|
display.print_status(
|
|
4225
4344
|
f"Found {len(discovered_repos)} repositories in organization", "success"
|
|
@@ -4400,6 +4519,8 @@ def cache_stats(config: Path) -> None:
|
|
|
4400
4519
|
- Decide when to clear cache
|
|
4401
4520
|
- Troubleshoot slow analyses
|
|
4402
4521
|
"""
|
|
4522
|
+
from .core.cache import GitAnalysisCache
|
|
4523
|
+
|
|
4403
4524
|
try:
|
|
4404
4525
|
cfg = ConfigLoader.load(config)
|
|
4405
4526
|
cache = GitAnalysisCache(cfg.cache.directory)
|
|
@@ -4454,6 +4575,8 @@ def merge_identity(config: Path, dev1: str, dev2: str) -> None:
|
|
|
4454
4575
|
- Refreshes cached statistics
|
|
4455
4576
|
- Updates identity mappings
|
|
4456
4577
|
"""
|
|
4578
|
+
from .core.identity import DeveloperIdentityResolver
|
|
4579
|
+
|
|
4457
4580
|
try:
|
|
4458
4581
|
cfg = ConfigLoader.load(config)
|
|
4459
4582
|
identity_resolver = DeveloperIdentityResolver(cfg.cache.directory / "identities.db")
|
|
@@ -4719,6 +4842,7 @@ def discover_storypoint_fields(config: Path) -> None:
|
|
|
4719
4842
|
return
|
|
4720
4843
|
|
|
4721
4844
|
# Initialize PM integration (currently JIRA)
|
|
4845
|
+
from .core.cache import GitAnalysisCache
|
|
4722
4846
|
from .integrations.jira_integration import JIRAIntegration
|
|
4723
4847
|
|
|
4724
4848
|
# Create minimal cache for integration
|
|
@@ -4802,6 +4926,9 @@ def identities(config: Path, weeks: int, apply: bool) -> None:
|
|
|
4802
4926
|
Mappings are saved to 'analysis.identity.manual_mappings'
|
|
4803
4927
|
Bot exclusions go to 'analysis.exclude.authors'
|
|
4804
4928
|
"""
|
|
4929
|
+
from .core.analyzer import GitAnalyzer
|
|
4930
|
+
from .core.cache import GitAnalysisCache
|
|
4931
|
+
|
|
4805
4932
|
try:
|
|
4806
4933
|
cfg = ConfigLoader.load(config)
|
|
4807
4934
|
cache = GitAnalysisCache(cfg.cache.directory)
|
|
@@ -4862,9 +4989,7 @@ def identities(config: Path, weeks: int, apply: bool) -> None:
|
|
|
4862
4989
|
analyzer = GitAnalyzer(
|
|
4863
4990
|
cache,
|
|
4864
4991
|
branch_mapping_rules=cfg.analysis.branch_mapping_rules,
|
|
4865
|
-
allowed_ticket_platforms=
|
|
4866
|
-
cfg.analysis, "ticket_platforms", ["jira", "github", "clickup", "linear"]
|
|
4867
|
-
),
|
|
4992
|
+
allowed_ticket_platforms=cfg.get_effective_ticket_platforms(),
|
|
4868
4993
|
exclude_paths=cfg.analysis.exclude_paths,
|
|
4869
4994
|
story_point_patterns=cfg.analysis.story_point_patterns,
|
|
4870
4995
|
ml_categorization_config=ml_config,
|
|
@@ -5032,6 +5157,8 @@ def aliases_command(
|
|
|
5032
5157
|
"""
|
|
5033
5158
|
try:
|
|
5034
5159
|
from .config.aliases import AliasesManager, DeveloperAlias
|
|
5160
|
+
from .core.analyzer import GitAnalyzer
|
|
5161
|
+
from .core.cache import GitAnalysisCache
|
|
5035
5162
|
from .identity_llm.analyzer import LLMIdentityAnalyzer
|
|
5036
5163
|
|
|
5037
5164
|
# Load configuration
|
|
@@ -5099,9 +5226,7 @@ def aliases_command(
|
|
|
5099
5226
|
analyzer = GitAnalyzer(
|
|
5100
5227
|
cache,
|
|
5101
5228
|
branch_mapping_rules=cfg.analysis.branch_mapping_rules,
|
|
5102
|
-
allowed_ticket_platforms=
|
|
5103
|
-
cfg.analysis, "ticket_platforms", ["jira", "github", "clickup", "linear"]
|
|
5104
|
-
),
|
|
5229
|
+
allowed_ticket_platforms=cfg.get_effective_ticket_platforms(),
|
|
5105
5230
|
exclude_paths=cfg.analysis.exclude_paths,
|
|
5106
5231
|
story_point_patterns=cfg.analysis.story_point_patterns,
|
|
5107
5232
|
ml_categorization_config=ml_config,
|
|
@@ -5335,6 +5460,8 @@ def list_developers(config: Path) -> None:
|
|
|
5335
5460
|
- Finding developer email addresses
|
|
5336
5461
|
- Checking contribution statistics
|
|
5337
5462
|
"""
|
|
5463
|
+
from .core.identity import DeveloperIdentityResolver
|
|
5464
|
+
|
|
5338
5465
|
try:
|
|
5339
5466
|
cfg = ConfigLoader.load(config)
|
|
5340
5467
|
identity_resolver = DeveloperIdentityResolver(cfg.cache.directory / "identities.db")
|
|
@@ -5468,6 +5595,8 @@ def train(
|
|
|
5468
5595
|
- scikit-learn and pandas dependencies
|
|
5469
5596
|
- ~100MB disk space for model storage
|
|
5470
5597
|
"""
|
|
5598
|
+
from .core.cache import GitAnalysisCache
|
|
5599
|
+
from .integrations.orchestrator import IntegrationOrchestrator
|
|
5471
5600
|
|
|
5472
5601
|
# Configure logging
|
|
5473
5602
|
if log.upper() != "NONE":
|
|
@@ -5551,8 +5680,18 @@ def train(
|
|
|
5551
5680
|
try:
|
|
5552
5681
|
config_dir = Path(config).parent if config else Path.cwd()
|
|
5553
5682
|
repos_dir = config_dir / "repos"
|
|
5554
|
-
|
|
5683
|
+
|
|
5684
|
+
# Progress callback for repository discovery
|
|
5685
|
+
def discovery_progress(repo_name, count):
|
|
5686
|
+
click.echo(f"\r 📦 Checking repositories... {count}", nl=False)
|
|
5687
|
+
|
|
5688
|
+
discovered_repos = cfg.discover_organization_repositories(
|
|
5689
|
+
clone_base_path=repos_dir, progress_callback=discovery_progress
|
|
5690
|
+
)
|
|
5555
5691
|
repositories_to_analyze = discovered_repos
|
|
5692
|
+
|
|
5693
|
+
# Clear the progress line and show result
|
|
5694
|
+
click.echo("\r" + " " * 60 + "\r", nl=False)
|
|
5556
5695
|
click.echo(f"✅ Found {len(discovered_repos)} repositories in organization")
|
|
5557
5696
|
except Exception as e:
|
|
5558
5697
|
click.echo(f"❌ Failed to discover repositories: {e}")
|
{gitflow_analytics-3.7.0 → gitflow_analytics-3.7.5}/src/gitflow_analytics/config/repository.py
RENAMED
|
@@ -20,12 +20,13 @@ class RepositoryManager:
|
|
|
20
20
|
self.github_config = github_config
|
|
21
21
|
|
|
22
22
|
def discover_organization_repositories(
|
|
23
|
-
self, clone_base_path: Optional[Path] = None
|
|
23
|
+
self, clone_base_path: Optional[Path] = None, progress_callback=None
|
|
24
24
|
) -> list[RepositoryConfig]:
|
|
25
25
|
"""Discover repositories from GitHub organization.
|
|
26
26
|
|
|
27
27
|
Args:
|
|
28
28
|
clone_base_path: Base directory where repos should be cloned/found.
|
|
29
|
+
progress_callback: Optional callback function(repo_name, count) for progress updates.
|
|
29
30
|
|
|
30
31
|
Returns:
|
|
31
32
|
List of discovered repository configurations.
|
|
@@ -42,7 +43,14 @@ class RepositoryManager:
|
|
|
42
43
|
if clone_base_path is None:
|
|
43
44
|
raise ValueError("No base path available for repository cloning")
|
|
44
45
|
|
|
46
|
+
repo_count = 0
|
|
45
47
|
for repo in org.get_repos():
|
|
48
|
+
repo_count += 1
|
|
49
|
+
|
|
50
|
+
# Call progress callback if provided
|
|
51
|
+
if progress_callback:
|
|
52
|
+
progress_callback(repo.name, repo_count)
|
|
53
|
+
|
|
46
54
|
# Skip archived repositories
|
|
47
55
|
if repo.archived:
|
|
48
56
|
continue
|