gitflow-analytics 1.3.11__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 +803 -135
  4. gitflow_analytics/config/loader.py +39 -1
  5. gitflow_analytics/config/schema.py +1 -0
  6. gitflow_analytics/core/cache.py +20 -0
  7. gitflow_analytics/core/data_fetcher.py +1051 -117
  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.11.dist-info → gitflow_analytics-3.3.0.dist-info}/METADATA +2 -1
  43. {gitflow_analytics-1.3.11.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.11.dist-info → gitflow_analytics-3.3.0.dist-info}/WHEEL +0 -0
  46. {gitflow_analytics-1.3.11.dist-info → gitflow_analytics-3.3.0.dist-info}/entry_points.txt +0 -0
  47. {gitflow_analytics-1.3.11.dist-info → gitflow_analytics-3.3.0.dist-info}/licenses/LICENSE +0 -0
  48. {gitflow_analytics-1.3.11.dist-info → gitflow_analytics-3.3.0.dist-info}/top_level.txt +0 -0
@@ -560,6 +560,7 @@ class ConfigLoader:
560
560
  ml_categorization=ml_categorization_config,
561
561
  commit_classification=commit_classification_config,
562
562
  llm_classification=llm_classification_config,
563
+ security=analysis_data.get("security", {}),
563
564
  )
564
565
 
565
566
  @classmethod
@@ -842,10 +843,14 @@ class ConfigLoader:
842
843
  platforms_data = pm_integration_data.get("platforms", {})
843
844
 
844
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
+
845
850
  platforms_config[platform_name] = PMPlatformConfig(
846
851
  enabled=platform_data.get("enabled", True),
847
852
  platform_type=platform_data.get("platform_type", platform_name),
848
- config=platform_data.get("config", {}),
853
+ config=resolved_config,
849
854
  )
850
855
 
851
856
  # Parse correlation settings with defaults
@@ -890,6 +895,39 @@ class ConfigLoader:
890
895
 
891
896
  return value
892
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
+
893
931
  @staticmethod
894
932
  def validate_config(config: Config) -> list[str]:
895
933
  """Validate configuration and return list of warnings.
@@ -314,6 +314,7 @@ class AnalysisConfig:
314
314
  default_factory=CommitClassificationConfig
315
315
  )
316
316
  llm_classification: LLMClassificationConfig = field(default_factory=LLMClassificationConfig)
317
+ security: Optional[dict[str, Any]] = field(default_factory=dict) # Security configuration
317
318
 
318
319
 
319
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", []),