gitflow-analytics 1.3.6__py3-none-any.whl → 3.3.0__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.
Files changed (48) hide show
  1. gitflow_analytics/_version.py +1 -1
  2. gitflow_analytics/classification/batch_classifier.py +156 -4
  3. gitflow_analytics/cli.py +897 -179
  4. gitflow_analytics/config/loader.py +40 -1
  5. gitflow_analytics/config/schema.py +4 -0
  6. gitflow_analytics/core/cache.py +20 -0
  7. gitflow_analytics/core/data_fetcher.py +1254 -228
  8. gitflow_analytics/core/git_auth.py +169 -0
  9. gitflow_analytics/core/git_timeout_wrapper.py +347 -0
  10. gitflow_analytics/core/metrics_storage.py +12 -3
  11. gitflow_analytics/core/progress.py +219 -18
  12. gitflow_analytics/core/subprocess_git.py +145 -0
  13. gitflow_analytics/extractors/ml_tickets.py +3 -2
  14. gitflow_analytics/extractors/tickets.py +93 -8
  15. gitflow_analytics/integrations/jira_integration.py +1 -1
  16. gitflow_analytics/integrations/orchestrator.py +47 -29
  17. gitflow_analytics/metrics/branch_health.py +3 -2
  18. gitflow_analytics/models/database.py +72 -1
  19. gitflow_analytics/pm_framework/adapters/jira_adapter.py +12 -5
  20. gitflow_analytics/pm_framework/orchestrator.py +8 -3
  21. gitflow_analytics/qualitative/classifiers/llm/openai_client.py +24 -4
  22. gitflow_analytics/qualitative/classifiers/llm_commit_classifier.py +3 -1
  23. gitflow_analytics/qualitative/core/llm_fallback.py +34 -2
  24. gitflow_analytics/reports/narrative_writer.py +118 -74
  25. gitflow_analytics/security/__init__.py +11 -0
  26. gitflow_analytics/security/config.py +189 -0
  27. gitflow_analytics/security/extractors/__init__.py +7 -0
  28. gitflow_analytics/security/extractors/dependency_checker.py +379 -0
  29. gitflow_analytics/security/extractors/secret_detector.py +197 -0
  30. gitflow_analytics/security/extractors/vulnerability_scanner.py +333 -0
  31. gitflow_analytics/security/llm_analyzer.py +347 -0
  32. gitflow_analytics/security/reports/__init__.py +5 -0
  33. gitflow_analytics/security/reports/security_report.py +358 -0
  34. gitflow_analytics/security/security_analyzer.py +414 -0
  35. gitflow_analytics/tui/app.py +3 -1
  36. gitflow_analytics/tui/progress_adapter.py +313 -0
  37. gitflow_analytics/tui/screens/analysis_progress_screen.py +407 -46
  38. gitflow_analytics/tui/screens/results_screen.py +219 -206
  39. gitflow_analytics/ui/__init__.py +21 -0
  40. gitflow_analytics/ui/progress_display.py +1477 -0
  41. gitflow_analytics/verify_activity.py +697 -0
  42. {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/METADATA +2 -1
  43. {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/RECORD +47 -31
  44. gitflow_analytics/cli_rich.py +0 -503
  45. {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/WHEEL +0 -0
  46. {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/entry_points.txt +0 -0
  47. {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/licenses/LICENSE +0 -0
  48. {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/top_level.txt +0 -0
@@ -555,10 +555,12 @@ class ConfigLoader:
555
555
  branch_mapping_rules=analysis_data.get("branch_mapping_rules", {}),
556
556
  ticket_platforms=analysis_data.get("ticket_platforms"),
557
557
  auto_identity_analysis=analysis_data.get("identity", {}).get("auto_analysis", True),
558
+ branch_patterns=analysis_data.get("branch_patterns"),
558
559
  branch_analysis=branch_analysis_config,
559
560
  ml_categorization=ml_categorization_config,
560
561
  commit_classification=commit_classification_config,
561
562
  llm_classification=llm_classification_config,
563
+ security=analysis_data.get("security", {}),
562
564
  )
563
565
 
564
566
  @classmethod
@@ -841,10 +843,14 @@ class ConfigLoader:
841
843
  platforms_data = pm_integration_data.get("platforms", {})
842
844
 
843
845
  for platform_name, platform_data in platforms_data.items():
846
+ # Recursively resolve environment variables in config dictionary
847
+ config_data = platform_data.get("config", {})
848
+ resolved_config = cls._resolve_config_dict(config_data)
849
+
844
850
  platforms_config[platform_name] = PMPlatformConfig(
845
851
  enabled=platform_data.get("enabled", True),
846
852
  platform_type=platform_data.get("platform_type", platform_name),
847
- config=platform_data.get("config", {}),
853
+ config=resolved_config,
848
854
  )
849
855
 
850
856
  # Parse correlation settings with defaults
@@ -889,6 +895,39 @@ class ConfigLoader:
889
895
 
890
896
  return value
891
897
 
898
+ @classmethod
899
+ def _resolve_config_dict(cls, config_dict: dict[str, Any]) -> dict[str, Any]:
900
+ """Recursively resolve environment variables in a configuration dictionary.
901
+
902
+ Args:
903
+ config_dict: Dictionary that may contain environment variable references
904
+
905
+ Returns:
906
+ Dictionary with resolved environment variables
907
+ """
908
+ resolved = {}
909
+ for key, value in config_dict.items():
910
+ if isinstance(value, str):
911
+ # Resolve string values that might be environment variables
912
+ resolved[key] = cls._resolve_env_var(value)
913
+ elif isinstance(value, dict):
914
+ # Recursively resolve nested dictionaries
915
+ resolved[key] = cls._resolve_config_dict(value)
916
+ elif isinstance(value, list):
917
+ # Handle lists that might contain strings or nested dicts
918
+ resolved[key] = [
919
+ (
920
+ cls._resolve_env_var(item)
921
+ if isinstance(item, str)
922
+ else cls._resolve_config_dict(item) if isinstance(item, dict) else item
923
+ )
924
+ for item in value
925
+ ]
926
+ else:
927
+ # Keep other types as-is (numbers, booleans, None, etc.)
928
+ resolved[key] = value
929
+ return resolved
930
+
892
931
  @staticmethod
893
932
  def validate_config(config: Config) -> list[str]:
894
933
  """Validate configuration and return list of warnings.
@@ -305,12 +305,16 @@ class AnalysisConfig:
305
305
  branch_mapping_rules: dict[str, list[str]] = field(default_factory=dict)
306
306
  ticket_platforms: Optional[list[str]] = None
307
307
  auto_identity_analysis: bool = True # Enable automatic identity analysis by default
308
+ branch_patterns: Optional[list[str]] = (
309
+ None # Branch patterns to analyze (e.g., ["*"] for all branches)
310
+ )
308
311
  branch_analysis: BranchAnalysisConfig = field(default_factory=BranchAnalysisConfig)
309
312
  ml_categorization: MLCategorization = field(default_factory=MLCategorization)
310
313
  commit_classification: CommitClassificationConfig = field(
311
314
  default_factory=CommitClassificationConfig
312
315
  )
313
316
  llm_classification: LLMClassificationConfig = field(default_factory=LLMClassificationConfig)
317
+ security: Optional[dict[str, Any]] = field(default_factory=dict) # Security configuration
314
318
 
315
319
 
316
320
  @dataclass
@@ -186,6 +186,12 @@ class GitAnalysisCache:
186
186
  ),
187
187
  insertions=commit_data.get("insertions", 0),
188
188
  deletions=commit_data.get("deletions", 0),
189
+ filtered_insertions=commit_data.get(
190
+ "filtered_insertions", commit_data.get("insertions", 0)
191
+ ),
192
+ filtered_deletions=commit_data.get(
193
+ "filtered_deletions", commit_data.get("deletions", 0)
194
+ ),
189
195
  complexity_delta=commit_data.get("complexity_delta", 0.0),
190
196
  story_points=commit_data.get("story_points"),
191
197
  ticket_references=commit_data.get("ticket_references", []),
@@ -255,6 +261,12 @@ class GitAnalysisCache:
255
261
  ),
256
262
  insertions=commit_data.get("insertions", 0),
257
263
  deletions=commit_data.get("deletions", 0),
264
+ filtered_insertions=commit_data.get(
265
+ "filtered_insertions", commit_data.get("insertions", 0)
266
+ ),
267
+ filtered_deletions=commit_data.get(
268
+ "filtered_deletions", commit_data.get("deletions", 0)
269
+ ),
258
270
  complexity_delta=commit_data.get("complexity_delta", 0.0),
259
271
  story_points=commit_data.get("story_points"),
260
272
  ticket_references=commit_data.get("ticket_references", []),
@@ -880,6 +892,8 @@ class GitAnalysisCache:
880
892
  "files_changed": commit.files_changed,
881
893
  "insertions": commit.insertions,
882
894
  "deletions": commit.deletions,
895
+ "filtered_insertions": getattr(commit, "filtered_insertions", commit.insertions),
896
+ "filtered_deletions": getattr(commit, "filtered_deletions", commit.deletions),
883
897
  "complexity_delta": commit.complexity_delta,
884
898
  "story_points": commit.story_points,
885
899
  "ticket_references": commit.ticket_references or [],
@@ -963,6 +977,12 @@ class GitAnalysisCache:
963
977
  ),
964
978
  "insertions": commit_data.get("insertions", 0),
965
979
  "deletions": commit_data.get("deletions", 0),
980
+ "filtered_insertions": commit_data.get(
981
+ "filtered_insertions", commit_data.get("insertions", 0)
982
+ ),
983
+ "filtered_deletions": commit_data.get(
984
+ "filtered_deletions", commit_data.get("deletions", 0)
985
+ ),
966
986
  "complexity_delta": commit_data.get("complexity_delta", 0.0),
967
987
  "story_points": commit_data.get("story_points"),
968
988
  "ticket_references": commit_data.get("ticket_references", []),