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.
- gitflow_analytics/_version.py +1 -1
- gitflow_analytics/classification/batch_classifier.py +156 -4
- gitflow_analytics/cli.py +897 -179
- gitflow_analytics/config/loader.py +40 -1
- gitflow_analytics/config/schema.py +4 -0
- gitflow_analytics/core/cache.py +20 -0
- gitflow_analytics/core/data_fetcher.py +1254 -228
- gitflow_analytics/core/git_auth.py +169 -0
- gitflow_analytics/core/git_timeout_wrapper.py +347 -0
- gitflow_analytics/core/metrics_storage.py +12 -3
- gitflow_analytics/core/progress.py +219 -18
- gitflow_analytics/core/subprocess_git.py +145 -0
- gitflow_analytics/extractors/ml_tickets.py +3 -2
- gitflow_analytics/extractors/tickets.py +93 -8
- gitflow_analytics/integrations/jira_integration.py +1 -1
- gitflow_analytics/integrations/orchestrator.py +47 -29
- gitflow_analytics/metrics/branch_health.py +3 -2
- gitflow_analytics/models/database.py +72 -1
- gitflow_analytics/pm_framework/adapters/jira_adapter.py +12 -5
- gitflow_analytics/pm_framework/orchestrator.py +8 -3
- gitflow_analytics/qualitative/classifiers/llm/openai_client.py +24 -4
- gitflow_analytics/qualitative/classifiers/llm_commit_classifier.py +3 -1
- gitflow_analytics/qualitative/core/llm_fallback.py +34 -2
- gitflow_analytics/reports/narrative_writer.py +118 -74
- gitflow_analytics/security/__init__.py +11 -0
- gitflow_analytics/security/config.py +189 -0
- gitflow_analytics/security/extractors/__init__.py +7 -0
- gitflow_analytics/security/extractors/dependency_checker.py +379 -0
- gitflow_analytics/security/extractors/secret_detector.py +197 -0
- gitflow_analytics/security/extractors/vulnerability_scanner.py +333 -0
- gitflow_analytics/security/llm_analyzer.py +347 -0
- gitflow_analytics/security/reports/__init__.py +5 -0
- gitflow_analytics/security/reports/security_report.py +358 -0
- gitflow_analytics/security/security_analyzer.py +414 -0
- gitflow_analytics/tui/app.py +3 -1
- gitflow_analytics/tui/progress_adapter.py +313 -0
- gitflow_analytics/tui/screens/analysis_progress_screen.py +407 -46
- gitflow_analytics/tui/screens/results_screen.py +219 -206
- gitflow_analytics/ui/__init__.py +21 -0
- gitflow_analytics/ui/progress_display.py +1477 -0
- gitflow_analytics/verify_activity.py +697 -0
- {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/METADATA +2 -1
- {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/RECORD +47 -31
- gitflow_analytics/cli_rich.py +0 -503
- {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/WHEEL +0 -0
- {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/entry_points.txt +0 -0
- {gitflow_analytics-1.3.6.dist-info → gitflow_analytics-3.3.0.dist-info}/licenses/LICENSE +0 -0
- {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=
|
|
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
|
gitflow_analytics/core/cache.py
CHANGED
|
@@ -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", []),
|