gitflow-analytics 3.3.0__py3-none-any.whl → 3.4.7__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 (33) hide show
  1. gitflow_analytics/_version.py +1 -1
  2. gitflow_analytics/cli.py +164 -15
  3. gitflow_analytics/cli_wizards/__init__.py +10 -0
  4. gitflow_analytics/cli_wizards/install_wizard.py +936 -0
  5. gitflow_analytics/cli_wizards/run_launcher.py +343 -0
  6. gitflow_analytics/config/schema.py +12 -0
  7. gitflow_analytics/constants.py +75 -0
  8. gitflow_analytics/core/cache.py +7 -3
  9. gitflow_analytics/core/data_fetcher.py +66 -30
  10. gitflow_analytics/core/git_timeout_wrapper.py +6 -4
  11. gitflow_analytics/core/progress.py +2 -4
  12. gitflow_analytics/core/subprocess_git.py +31 -5
  13. gitflow_analytics/identity_llm/analysis_pass.py +13 -3
  14. gitflow_analytics/identity_llm/analyzer.py +14 -2
  15. gitflow_analytics/identity_llm/models.py +7 -1
  16. gitflow_analytics/qualitative/classifiers/llm/openai_client.py +5 -3
  17. gitflow_analytics/security/config.py +6 -6
  18. gitflow_analytics/security/extractors/dependency_checker.py +14 -14
  19. gitflow_analytics/security/extractors/secret_detector.py +8 -14
  20. gitflow_analytics/security/extractors/vulnerability_scanner.py +9 -9
  21. gitflow_analytics/security/llm_analyzer.py +10 -10
  22. gitflow_analytics/security/security_analyzer.py +17 -17
  23. gitflow_analytics/tui/screens/analysis_progress_screen.py +1 -1
  24. gitflow_analytics/ui/progress_display.py +36 -29
  25. gitflow_analytics/verify_activity.py +23 -26
  26. {gitflow_analytics-3.3.0.dist-info → gitflow_analytics-3.4.7.dist-info}/METADATA +1 -1
  27. {gitflow_analytics-3.3.0.dist-info → gitflow_analytics-3.4.7.dist-info}/RECORD +31 -29
  28. gitflow_analytics/security/reports/__init__.py +0 -5
  29. gitflow_analytics/security/reports/security_report.py +0 -358
  30. {gitflow_analytics-3.3.0.dist-info → gitflow_analytics-3.4.7.dist-info}/WHEEL +0 -0
  31. {gitflow_analytics-3.3.0.dist-info → gitflow_analytics-3.4.7.dist-info}/entry_points.txt +0 -0
  32. {gitflow_analytics-3.3.0.dist-info → gitflow_analytics-3.4.7.dist-info}/licenses/LICENSE +0 -0
  33. {gitflow_analytics-3.3.0.dist-info → gitflow_analytics-3.4.7.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
1
  """Version information for gitflow-analytics."""
2
2
 
3
- __version__ = "3.3.0"
3
+ __version__ = "3.4.7"
4
4
  __version_info__ = tuple(int(x) for x in __version__.split("."))
gitflow_analytics/cli.py CHANGED
@@ -33,6 +33,8 @@ from .reports.weekly_trends_writer import WeeklyTrendsWriter
33
33
  from .training.pipeline import CommitClassificationTrainer
34
34
  from .ui.progress_display import create_progress_display
35
35
 
36
+ logger = logging.getLogger(__name__)
37
+
36
38
 
37
39
  class RichHelpFormatter:
38
40
  """Rich help formatter for enhanced CLI help display."""
@@ -48,8 +50,19 @@ class RichHelpFormatter:
48
50
  return help_text
49
51
 
50
52
  @staticmethod
51
- def format_option_help(description: str, default: Any = None, choices: list = None) -> str:
52
- """Format option help with default and choices."""
53
+ def format_option_help(
54
+ description: str, default: Optional[str] = None, choices: Optional[list[str]] = None
55
+ ) -> str:
56
+ """Format option help with default and choices.
57
+
58
+ Args:
59
+ description: Option description text
60
+ default: Default value to display (optional)
61
+ choices: List of valid choices (optional)
62
+
63
+ Returns:
64
+ Formatted help text string
65
+ """
53
66
  help_text = description
54
67
  if default is not None:
55
68
  help_text += f" [default: {default}]"
@@ -281,12 +294,18 @@ class TUIAsDefaultGroup(click.Group):
281
294
  if args and args[0].startswith("-"):
282
295
  # Check if TUI dependencies are available
283
296
  try:
284
- import textual
297
+ import importlib.util
285
298
 
299
+ textual_spec = importlib.util.find_spec("textual")
286
300
  # TUI is available - route to TUI
287
- new_args = ["tui"] + args
288
- return super().parse_args(ctx, new_args)
289
- except ImportError:
301
+ if textual_spec is not None:
302
+ new_args = ["tui"] + args
303
+ return super().parse_args(ctx, new_args)
304
+ else:
305
+ # TUI not available - fallback to analyze
306
+ new_args = ["analyze"] + args
307
+ return super().parse_args(ctx, new_args)
308
+ except (ImportError, ValueError):
290
309
  # TUI not available - fallback to analyze
291
310
  new_args = ["analyze"] + args
292
311
  return super().parse_args(ctx, new_args)
@@ -1066,10 +1085,7 @@ def analyze(
1066
1085
  )
1067
1086
 
1068
1087
  # Extract commits from the raw data
1069
- if raw_data and raw_data.get("commits"):
1070
- commits = raw_data["commits"]
1071
- else:
1072
- commits = []
1088
+ commits = raw_data["commits"] if raw_data and raw_data.get("commits") else []
1073
1089
  all_commits.extend(commits)
1074
1090
 
1075
1091
  if not all_commits:
@@ -4460,6 +4476,114 @@ def merge_identity(config: Path, dev1: str, dev2: str) -> None:
4460
4476
  sys.exit(1)
4461
4477
 
4462
4478
 
4479
+ @cli.command(name="run")
4480
+ @click.option(
4481
+ "--config",
4482
+ "-c",
4483
+ type=click.Path(exists=True, path_type=Path),
4484
+ help="Path to configuration file (optional, will search for default)",
4485
+ )
4486
+ def run_launcher(config: Optional[Path]) -> None:
4487
+ """Interactive launcher for gitflow-analytics.
4488
+
4489
+ \b
4490
+ This interactive command guides you through:
4491
+ • Repository selection (multi-select)
4492
+ • Analysis period configuration
4493
+ • Cache management
4494
+ • Identity analysis preferences
4495
+ • Preferences storage
4496
+
4497
+ \b
4498
+ EXAMPLES:
4499
+ # Launch interactive mode
4500
+ gitflow-analytics run
4501
+
4502
+ # Launch with specific config
4503
+ gitflow-analytics run -c config.yaml
4504
+
4505
+ \b
4506
+ PREFERENCES:
4507
+ Your selections are saved to the launcher section
4508
+ in your configuration file for future use.
4509
+
4510
+ \b
4511
+ WORKFLOW:
4512
+ 1. Select repositories to analyze
4513
+ 2. Choose analysis period (weeks)
4514
+ 3. Configure cache clearing
4515
+ 4. Set identity analysis preference
4516
+ 5. Run analysis with your selections
4517
+ """
4518
+ try:
4519
+ from .cli_wizards.run_launcher import run_interactive_launcher
4520
+
4521
+ success = run_interactive_launcher(config_path=config)
4522
+ sys.exit(0 if success else 1)
4523
+
4524
+ except Exception as e:
4525
+ click.echo(f"❌ Launcher failed: {e}", err=True)
4526
+ logger.error(f"Launcher error: {type(e).__name__}")
4527
+ sys.exit(1)
4528
+
4529
+
4530
+ @cli.command(name="install")
4531
+ @click.option(
4532
+ "--output-dir",
4533
+ type=click.Path(path_type=Path),
4534
+ default=".",
4535
+ help="Directory for config files (default: current directory)",
4536
+ )
4537
+ @click.option(
4538
+ "--skip-validation",
4539
+ is_flag=True,
4540
+ help="Skip credential validation (for testing)",
4541
+ )
4542
+ def install_command(output_dir: Path, skip_validation: bool) -> None:
4543
+ """Interactive installation wizard for GitFlow Analytics.
4544
+
4545
+ \b
4546
+ This wizard will guide you through setting up GitFlow Analytics:
4547
+ • GitHub credentials and repository configuration
4548
+ • Optional JIRA integration
4549
+ • Optional AI-powered insights (OpenRouter/ChatGPT)
4550
+ • Analysis settings and defaults
4551
+
4552
+ \b
4553
+ EXAMPLES:
4554
+ # Run installation wizard in current directory
4555
+ gitflow-analytics install
4556
+
4557
+ # Install to specific directory
4558
+ gitflow-analytics install --output-dir ./my-config
4559
+
4560
+ \b
4561
+ The wizard will:
4562
+ 1. Validate all credentials before saving
4563
+ 2. Generate config.yaml and .env files
4564
+ 3. Set secure permissions on .env (0600)
4565
+ 4. Update .gitignore if in a git repository
4566
+ 5. Test the configuration
4567
+ 6. Optionally run initial analysis
4568
+
4569
+ \b
4570
+ SECURITY NOTES:
4571
+ • .env file contains sensitive credentials
4572
+ • Never commit .env to version control
4573
+ • File permissions set to owner-only (0600)
4574
+ """
4575
+ try:
4576
+ from .cli_wizards.install_wizard import InstallWizard
4577
+
4578
+ wizard = InstallWizard(output_dir=Path(output_dir), skip_validation=skip_validation)
4579
+ success = wizard.run()
4580
+ sys.exit(0 if success else 1)
4581
+
4582
+ except Exception as e:
4583
+ click.echo(f"❌ Installation failed: {e}", err=True)
4584
+ sys.exit(1)
4585
+
4586
+
4463
4587
  @cli.command(name="discover-storypoint-fields")
4464
4588
  @click.option(
4465
4589
  "--config",
@@ -4672,16 +4796,41 @@ def identities(config: Path, weeks: int, apply: bool) -> None:
4672
4796
  # Show suggestions
4673
4797
  click.echo(f"\n⚠️ Found {len(identity_result.clusters)} potential identity clusters:")
4674
4798
 
4675
- # Display all mappings
4799
+ # Display all mappings with confidence scores
4676
4800
  if suggested_config.get("analysis", {}).get("manual_identity_mappings"):
4677
4801
  click.echo("\n📋 Suggested identity mappings:")
4678
- for mapping in suggested_config["analysis"]["manual_identity_mappings"]:
4679
- canonical = mapping["canonical_email"]
4802
+ for i, mapping in enumerate(
4803
+ suggested_config["analysis"]["manual_identity_mappings"], 1
4804
+ ):
4805
+ canonical = mapping["primary_email"]
4680
4806
  aliases = mapping.get("aliases", [])
4807
+ confidence = mapping.get("confidence", 0.0)
4808
+ reasoning = mapping.get("reasoning", "")
4809
+
4810
+ # Color-code based on confidence (90%+ threshold)
4811
+ if confidence >= 0.95:
4812
+ confidence_indicator = "🟢" # Very high confidence
4813
+ elif confidence >= 0.90:
4814
+ confidence_indicator = "🟡" # High confidence (above threshold)
4815
+ else:
4816
+ confidence_indicator = "🟠" # Medium confidence (below threshold)
4817
+
4681
4818
  if aliases:
4682
- click.echo(f" {canonical}")
4819
+ click.echo(
4820
+ f"\n {confidence_indicator} Cluster {i} "
4821
+ f"(Confidence: {confidence:.1%}):"
4822
+ )
4823
+ click.echo(f" Primary: {canonical}")
4683
4824
  for alias in aliases:
4684
- click.echo(f"{alias}")
4825
+ click.echo(f" Alias: {alias}")
4826
+
4827
+ # Show reasoning if available
4828
+ if reasoning:
4829
+ # Truncate reasoning for display
4830
+ display_reasoning = (
4831
+ reasoning if len(reasoning) <= 80 else reasoning[:77] + "..."
4832
+ )
4833
+ click.echo(f" Reason: {display_reasoning}")
4685
4834
 
4686
4835
  # Check for bot exclusions
4687
4836
  if suggested_config.get("exclude", {}).get("authors"):
@@ -0,0 +1,10 @@
1
+ """CLI subpackage for GitFlow Analytics.
2
+
3
+ This package contains CLI-related modules including the installation wizard
4
+ and interactive launcher.
5
+ """
6
+
7
+ from .install_wizard import InstallWizard
8
+ from .run_launcher import InteractiveLauncher, run_interactive_launcher
9
+
10
+ __all__ = ["InstallWizard", "InteractiveLauncher", "run_interactive_launcher"]