@theihtisham/dev-pulse 1.0.0 → 1.1.0

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 (40) hide show
  1. package/.editorconfig +12 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.yml +43 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.yml +33 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +18 -0
  5. package/.github/dependabot.yml +16 -0
  6. package/.github/workflows/ci.yml +33 -0
  7. package/CODE_OF_CONDUCT.md +27 -0
  8. package/Dockerfile +8 -0
  9. package/LICENSE +21 -21
  10. package/README.md +135 -39
  11. package/SECURITY.md +22 -0
  12. package/devpulse/__init__.py +4 -4
  13. package/devpulse/api/__init__.py +1 -1
  14. package/devpulse/api/app.py +371 -371
  15. package/devpulse/cli/__init__.py +1 -1
  16. package/devpulse/cli/dashboard.py +131 -131
  17. package/devpulse/cli/main.py +678 -678
  18. package/devpulse/cli/render.py +175 -175
  19. package/devpulse/core/__init__.py +34 -34
  20. package/devpulse/core/analytics.py +487 -487
  21. package/devpulse/core/config.py +77 -77
  22. package/devpulse/core/database.py +612 -612
  23. package/devpulse/core/github_client.py +281 -281
  24. package/devpulse/core/models.py +142 -142
  25. package/devpulse/core/report_generator.py +454 -454
  26. package/devpulse/static/.gitkeep +1 -1
  27. package/devpulse/templates/report.html +64 -64
  28. package/package.json +35 -35
  29. package/pyproject.toml +80 -80
  30. package/requirements.txt +14 -14
  31. package/tests/__init__.py +1 -1
  32. package/tests/conftest.py +208 -208
  33. package/tests/test_analytics.py +284 -284
  34. package/tests/test_api.py +313 -313
  35. package/tests/test_cli.py +204 -204
  36. package/tests/test_config.py +47 -47
  37. package/tests/test_database.py +255 -255
  38. package/tests/test_models.py +107 -107
  39. package/tests/test_report_generator.py +173 -173
  40. package/jest.config.js +0 -7
@@ -1 +1 @@
1
- """CLI package for DevPulse."""
1
+ """CLI package for DevPulse."""
@@ -1,131 +1,131 @@
1
- """Interactive terminal dashboard for DevPulse."""
2
-
3
- from typing import Optional
4
-
5
- from rich.console import Console
6
- from rich.table import Table
7
- from rich.panel import Panel
8
- from rich.layout import Layout
9
- from rich.text import Text
10
-
11
- from devpulse.core.database import Database
12
- from devpulse.core.analytics import AnalyticsEngine
13
- from devpulse.core.report_generator import ReportGenerator
14
- from devpulse.cli.render import render_header, render_heatmap, render_insight_card
15
-
16
-
17
- def dashboard_cmd(
18
- author: Optional[str] = None,
19
- days: int = 30,
20
- repo: Optional[str] = None,
21
- ) -> None:
22
- """Launch the full interactive terminal dashboard."""
23
- console = Console()
24
- db = Database()
25
- engine = AnalyticsEngine(db=db)
26
- report_gen = ReportGenerator(db=db)
27
-
28
- render_header(console)
29
-
30
- # ── Section 1: Summary ───────────────────────────────────────────
31
- console.rule("[bold cyan]Overview[/bold cyan]")
32
-
33
- daily = report_gen.daily_report(author=author, repo=repo)
34
- console.print(f"\n Date: [bold]{daily['date']}[/bold]")
35
- console.print(f" {daily['summary']}\n")
36
-
37
- # ── Section 2: Team Metrics ──────────────────────────────────────
38
- console.rule("[bold cyan]Team Metrics[/bold cyan]")
39
- console.print()
40
-
41
- team = engine.team_metrics(days=days, repo=repo)
42
- if team:
43
- table = Table(show_header=True, header_style="bold cyan", expand=True)
44
- table.add_column("Developer", style="white", min_width=15)
45
- table.add_column("Commits", justify="right")
46
- table.add_column("C/D", justify="right", style="dim")
47
- table.add_column("PRs", justify="right")
48
- table.add_column("Reviews", justify="right")
49
- table.add_column("Merge(h)", justify="right")
50
- table.add_column("+/- Lines", justify="right")
51
-
52
- for m in team[:10]:
53
- table.add_row(
54
- m.author,
55
- str(m.commits_count),
56
- str(m.commits_per_day),
57
- str(m.prs_created),
58
- str(m.reviews_given),
59
- str(m.avg_pr_merge_time_hours),
60
- f"+{m.lines_added}/-{m.lines_removed}",
61
- )
62
- console.print(table)
63
- else:
64
- console.print("[dim]No team data yet. Run 'devpulse sync' to fetch data.[/dim]")
65
-
66
- # ── Section 3: Team Health ───────────────────────────────────────
67
- console.rule("[bold cyan]Team Health[/bold cyan]")
68
- console.print()
69
-
70
- health = engine.team_health(days=days, repo=repo)
71
- score_color = "green" if health.overall_score >= 70 else "yellow" if health.overall_score >= 40 else "red"
72
- console.print(f" Health Score: [{score_color}]{health.overall_score}/100[/{score_color}]")
73
- console.print(f" Workload Balance: {health.workload_balance:.0%}")
74
- console.print(f" Collaboration: {health.collaboration_score:.0%}")
75
- console.print(f" Velocity: {health.velocity_trend}")
76
-
77
- if health.burnout_risk:
78
- console.print("\n [bold]Burnout Risk:[/bold]")
79
- for name, risk in sorted(health.burnout_risk.items(), key=lambda x: x[1], reverse=True):
80
- color = "red" if risk >= 0.6 else "yellow" if risk >= 0.3 else "green"
81
- bar_len = int(risk * 20)
82
- bar = "#" * bar_len + "-" * (20 - bar_len)
83
- console.print(f" {name:<15} [{color}]{bar}[/{color}] {risk:.0%}")
84
-
85
- # ── Section 4: AI Insights ───────────────────────────────────────
86
- console.rule("[bold cyan]AI Insights[/bold cyan]")
87
- console.print()
88
-
89
- insights = engine.generate_insights(days=days, repo=repo)
90
- for i, insight in enumerate(insights, 1):
91
- render_insight_card(console, insight, i)
92
-
93
- # ── Section 5: Goals ─────────────────────────────────────────────
94
- goals = db.get_goals(status="active")
95
- if goals:
96
- console.rule("[bold cyan]Active Goals[/bold cyan]")
97
- console.print()
98
- goal_table = Table(show_header=True, header_style="bold cyan")
99
- goal_table.add_column("Goal", style="white")
100
- goal_table.add_column("Metric")
101
- goal_table.add_column("Progress", justify="right")
102
- goal_table.add_column("Deadline")
103
- for g in goals:
104
- pct = (g["current_value"] / g["target_value"] * 100) if g["target_value"] > 0 else 0
105
- color = "green" if pct >= 75 else "yellow" if pct >= 25 else "red"
106
- goal_table.add_row(
107
- g["title"],
108
- g["metric"],
109
- f"[{color}]{pct:.0%}[/{color}]",
110
- g.get("deadline", "-"),
111
- )
112
- console.print(goal_table)
113
-
114
- # ── Section 6: Heatmap ───────────────────────────────────────────
115
- console.rule("[bold cyan]Activity Heatmap[/bold cyan]")
116
- console.print()
117
-
118
- heatmap_data = engine.activity_heatmap(author=author, days=90)
119
- if heatmap_data:
120
- render_heatmap(console, heatmap_data, days=90)
121
- else:
122
- console.print("[dim]No activity data. Run 'devpulse sync' to fetch commits.[/dim]")
123
-
124
- # ── Section 7: Recommendations ───────────────────────────────────
125
- console.rule("[bold cyan]Recommendations[/bold cyan]")
126
- console.print()
127
- for rec in health.recommendations:
128
- console.print(f" -> {rec}")
129
-
130
- console.print()
131
- console.print("[dim]Run 'devpulse sync' to refresh data | 'devpulse --help' for all commands[/dim]")
1
+ """Interactive terminal dashboard for DevPulse."""
2
+
3
+ from typing import Optional
4
+
5
+ from rich.console import Console
6
+ from rich.table import Table
7
+ from rich.panel import Panel
8
+ from rich.layout import Layout
9
+ from rich.text import Text
10
+
11
+ from devpulse.core.database import Database
12
+ from devpulse.core.analytics import AnalyticsEngine
13
+ from devpulse.core.report_generator import ReportGenerator
14
+ from devpulse.cli.render import render_header, render_heatmap, render_insight_card
15
+
16
+
17
+ def dashboard_cmd(
18
+ author: Optional[str] = None,
19
+ days: int = 30,
20
+ repo: Optional[str] = None,
21
+ ) -> None:
22
+ """Launch the full interactive terminal dashboard."""
23
+ console = Console()
24
+ db = Database()
25
+ engine = AnalyticsEngine(db=db)
26
+ report_gen = ReportGenerator(db=db)
27
+
28
+ render_header(console)
29
+
30
+ # ── Section 1: Summary ───────────────────────────────────────────
31
+ console.rule("[bold cyan]Overview[/bold cyan]")
32
+
33
+ daily = report_gen.daily_report(author=author, repo=repo)
34
+ console.print(f"\n Date: [bold]{daily['date']}[/bold]")
35
+ console.print(f" {daily['summary']}\n")
36
+
37
+ # ── Section 2: Team Metrics ──────────────────────────────────────
38
+ console.rule("[bold cyan]Team Metrics[/bold cyan]")
39
+ console.print()
40
+
41
+ team = engine.team_metrics(days=days, repo=repo)
42
+ if team:
43
+ table = Table(show_header=True, header_style="bold cyan", expand=True)
44
+ table.add_column("Developer", style="white", min_width=15)
45
+ table.add_column("Commits", justify="right")
46
+ table.add_column("C/D", justify="right", style="dim")
47
+ table.add_column("PRs", justify="right")
48
+ table.add_column("Reviews", justify="right")
49
+ table.add_column("Merge(h)", justify="right")
50
+ table.add_column("+/- Lines", justify="right")
51
+
52
+ for m in team[:10]:
53
+ table.add_row(
54
+ m.author,
55
+ str(m.commits_count),
56
+ str(m.commits_per_day),
57
+ str(m.prs_created),
58
+ str(m.reviews_given),
59
+ str(m.avg_pr_merge_time_hours),
60
+ f"+{m.lines_added}/-{m.lines_removed}",
61
+ )
62
+ console.print(table)
63
+ else:
64
+ console.print("[dim]No team data yet. Run 'devpulse sync' to fetch data.[/dim]")
65
+
66
+ # ── Section 3: Team Health ───────────────────────────────────────
67
+ console.rule("[bold cyan]Team Health[/bold cyan]")
68
+ console.print()
69
+
70
+ health = engine.team_health(days=days, repo=repo)
71
+ score_color = "green" if health.overall_score >= 70 else "yellow" if health.overall_score >= 40 else "red"
72
+ console.print(f" Health Score: [{score_color}]{health.overall_score}/100[/{score_color}]")
73
+ console.print(f" Workload Balance: {health.workload_balance:.0%}")
74
+ console.print(f" Collaboration: {health.collaboration_score:.0%}")
75
+ console.print(f" Velocity: {health.velocity_trend}")
76
+
77
+ if health.burnout_risk:
78
+ console.print("\n [bold]Burnout Risk:[/bold]")
79
+ for name, risk in sorted(health.burnout_risk.items(), key=lambda x: x[1], reverse=True):
80
+ color = "red" if risk >= 0.6 else "yellow" if risk >= 0.3 else "green"
81
+ bar_len = int(risk * 20)
82
+ bar = "#" * bar_len + "-" * (20 - bar_len)
83
+ console.print(f" {name:<15} [{color}]{bar}[/{color}] {risk:.0%}")
84
+
85
+ # ── Section 4: AI Insights ───────────────────────────────────────
86
+ console.rule("[bold cyan]AI Insights[/bold cyan]")
87
+ console.print()
88
+
89
+ insights = engine.generate_insights(days=days, repo=repo)
90
+ for i, insight in enumerate(insights, 1):
91
+ render_insight_card(console, insight, i)
92
+
93
+ # ── Section 5: Goals ─────────────────────────────────────────────
94
+ goals = db.get_goals(status="active")
95
+ if goals:
96
+ console.rule("[bold cyan]Active Goals[/bold cyan]")
97
+ console.print()
98
+ goal_table = Table(show_header=True, header_style="bold cyan")
99
+ goal_table.add_column("Goal", style="white")
100
+ goal_table.add_column("Metric")
101
+ goal_table.add_column("Progress", justify="right")
102
+ goal_table.add_column("Deadline")
103
+ for g in goals:
104
+ pct = (g["current_value"] / g["target_value"] * 100) if g["target_value"] > 0 else 0
105
+ color = "green" if pct >= 75 else "yellow" if pct >= 25 else "red"
106
+ goal_table.add_row(
107
+ g["title"],
108
+ g["metric"],
109
+ f"[{color}]{pct:.0%}[/{color}]",
110
+ g.get("deadline", "-"),
111
+ )
112
+ console.print(goal_table)
113
+
114
+ # ── Section 6: Heatmap ───────────────────────────────────────────
115
+ console.rule("[bold cyan]Activity Heatmap[/bold cyan]")
116
+ console.print()
117
+
118
+ heatmap_data = engine.activity_heatmap(author=author, days=90)
119
+ if heatmap_data:
120
+ render_heatmap(console, heatmap_data, days=90)
121
+ else:
122
+ console.print("[dim]No activity data. Run 'devpulse sync' to fetch commits.[/dim]")
123
+
124
+ # ── Section 7: Recommendations ───────────────────────────────────
125
+ console.rule("[bold cyan]Recommendations[/bold cyan]")
126
+ console.print()
127
+ for rec in health.recommendations:
128
+ console.print(f" -> {rec}")
129
+
130
+ console.print()
131
+ console.print("[dim]Run 'devpulse sync' to refresh data | 'devpulse --help' for all commands[/dim]")