gitflow-analytics 1.0.0__py3-none-any.whl → 1.0.3__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 (58) hide show
  1. gitflow_analytics/__init__.py +11 -9
  2. gitflow_analytics/_version.py +2 -2
  3. gitflow_analytics/cli.py +691 -243
  4. gitflow_analytics/cli_rich.py +353 -0
  5. gitflow_analytics/config.py +389 -96
  6. gitflow_analytics/core/analyzer.py +175 -78
  7. gitflow_analytics/core/branch_mapper.py +132 -132
  8. gitflow_analytics/core/cache.py +242 -173
  9. gitflow_analytics/core/identity.py +214 -178
  10. gitflow_analytics/extractors/base.py +13 -11
  11. gitflow_analytics/extractors/story_points.py +70 -59
  12. gitflow_analytics/extractors/tickets.py +111 -88
  13. gitflow_analytics/integrations/github_integration.py +91 -77
  14. gitflow_analytics/integrations/jira_integration.py +284 -0
  15. gitflow_analytics/integrations/orchestrator.py +99 -72
  16. gitflow_analytics/metrics/dora.py +183 -179
  17. gitflow_analytics/models/database.py +191 -54
  18. gitflow_analytics/qualitative/__init__.py +30 -0
  19. gitflow_analytics/qualitative/classifiers/__init__.py +13 -0
  20. gitflow_analytics/qualitative/classifiers/change_type.py +468 -0
  21. gitflow_analytics/qualitative/classifiers/domain_classifier.py +399 -0
  22. gitflow_analytics/qualitative/classifiers/intent_analyzer.py +436 -0
  23. gitflow_analytics/qualitative/classifiers/risk_analyzer.py +412 -0
  24. gitflow_analytics/qualitative/core/__init__.py +13 -0
  25. gitflow_analytics/qualitative/core/llm_fallback.py +653 -0
  26. gitflow_analytics/qualitative/core/nlp_engine.py +373 -0
  27. gitflow_analytics/qualitative/core/pattern_cache.py +457 -0
  28. gitflow_analytics/qualitative/core/processor.py +540 -0
  29. gitflow_analytics/qualitative/models/__init__.py +25 -0
  30. gitflow_analytics/qualitative/models/schemas.py +272 -0
  31. gitflow_analytics/qualitative/utils/__init__.py +13 -0
  32. gitflow_analytics/qualitative/utils/batch_processor.py +326 -0
  33. gitflow_analytics/qualitative/utils/cost_tracker.py +343 -0
  34. gitflow_analytics/qualitative/utils/metrics.py +347 -0
  35. gitflow_analytics/qualitative/utils/text_processing.py +243 -0
  36. gitflow_analytics/reports/analytics_writer.py +25 -8
  37. gitflow_analytics/reports/csv_writer.py +60 -32
  38. gitflow_analytics/reports/narrative_writer.py +21 -15
  39. gitflow_analytics/tui/__init__.py +5 -0
  40. gitflow_analytics/tui/app.py +721 -0
  41. gitflow_analytics/tui/screens/__init__.py +8 -0
  42. gitflow_analytics/tui/screens/analysis_progress_screen.py +487 -0
  43. gitflow_analytics/tui/screens/configuration_screen.py +547 -0
  44. gitflow_analytics/tui/screens/loading_screen.py +358 -0
  45. gitflow_analytics/tui/screens/main_screen.py +304 -0
  46. gitflow_analytics/tui/screens/results_screen.py +698 -0
  47. gitflow_analytics/tui/widgets/__init__.py +7 -0
  48. gitflow_analytics/tui/widgets/data_table.py +257 -0
  49. gitflow_analytics/tui/widgets/export_modal.py +301 -0
  50. gitflow_analytics/tui/widgets/progress_widget.py +192 -0
  51. gitflow_analytics-1.0.3.dist-info/METADATA +490 -0
  52. gitflow_analytics-1.0.3.dist-info/RECORD +62 -0
  53. gitflow_analytics-1.0.0.dist-info/METADATA +0 -201
  54. gitflow_analytics-1.0.0.dist-info/RECORD +0 -30
  55. {gitflow_analytics-1.0.0.dist-info → gitflow_analytics-1.0.3.dist-info}/WHEEL +0 -0
  56. {gitflow_analytics-1.0.0.dist-info → gitflow_analytics-1.0.3.dist-info}/entry_points.txt +0 -0
  57. {gitflow_analytics-1.0.0.dist-info → gitflow_analytics-1.0.3.dist-info}/licenses/LICENSE +0 -0
  58. {gitflow_analytics-1.0.0.dist-info → gitflow_analytics-1.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,192 @@
1
+ """Progress widget with ETA for GitFlow Analytics TUI."""
2
+
3
+ import time
4
+ from typing import Optional
5
+ from datetime import datetime, timedelta
6
+
7
+ from textual.widgets import ProgressBar, Label
8
+ from textual.containers import Container, Vertical
9
+ from textual.reactive import reactive
10
+ from rich.text import Text
11
+
12
+
13
+ class AnalysisProgressWidget(Container):
14
+ """
15
+ Custom progress widget that shows progress with ETA calculation.
16
+
17
+ WHY: Standard progress bars don't provide time estimates which are crucial
18
+ for long-running analysis operations. This widget combines progress tracking
19
+ with ETA calculations to give users better feedback.
20
+
21
+ DESIGN DECISION: Uses reactive attributes for real-time updates and
22
+ calculates ETA based on average processing speed rather than simple linear
23
+ extrapolation for more accurate estimates.
24
+ """
25
+
26
+ DEFAULT_CSS = """
27
+ AnalysisProgressWidget {
28
+ height: auto;
29
+ border: solid $primary;
30
+ margin: 1;
31
+ padding: 1;
32
+ }
33
+
34
+ .progress-title {
35
+ text-style: bold;
36
+ color: $primary;
37
+ margin-bottom: 1;
38
+ }
39
+
40
+ .progress-status {
41
+ color: $text;
42
+ margin-top: 1;
43
+ }
44
+
45
+ .progress-eta {
46
+ color: $accent;
47
+ text-style: italic;
48
+ }
49
+ """
50
+
51
+ progress = reactive(0.0)
52
+ total = reactive(100.0)
53
+ status_text = reactive("Initializing...")
54
+
55
+ def __init__(
56
+ self,
57
+ title: str,
58
+ total: float = 100.0,
59
+ *,
60
+ name: Optional[str] = None,
61
+ id: Optional[str] = None,
62
+ classes: Optional[str] = None
63
+ ) -> None:
64
+ super().__init__(name=name, id=id, classes=classes)
65
+ self.title = title
66
+ self.total = total
67
+ self.start_time = time.time()
68
+ self.last_update_time = time.time()
69
+ self.progress_history = []
70
+
71
+ def compose(self):
72
+ """Compose the progress widget."""
73
+ yield Label(self.title, classes="progress-title")
74
+ yield ProgressBar(total=self.total, id="progress-bar")
75
+ yield Label(self.status_text, classes="progress-status", id="status-label")
76
+ yield Label("", classes="progress-eta", id="eta-label")
77
+
78
+ def update_progress(self, value: float, status: str = "") -> None:
79
+ """
80
+ Update progress and status with ETA calculation.
81
+
82
+ WHY: Provides comprehensive progress updates including time estimates
83
+ which are essential for user experience during long operations.
84
+
85
+ @param value: Current progress value
86
+ @param status: Status message to display
87
+ """
88
+ current_time = time.time()
89
+
90
+ # Update reactive values
91
+ self.progress = value
92
+ if status:
93
+ self.status_text = status
94
+
95
+ # Update progress bar
96
+ progress_bar = self.query_one("#progress-bar", ProgressBar)
97
+ progress_bar.update(progress=value)
98
+
99
+ # Update status label
100
+ status_label = self.query_one("#status-label", Label)
101
+ status_label.update(status)
102
+
103
+ # Calculate and update ETA
104
+ eta_text = self._calculate_eta(value, current_time)
105
+ eta_label = self.query_one("#eta-label", Label)
106
+ eta_label.update(eta_text)
107
+
108
+ # Store progress history for better ETA calculation
109
+ self.progress_history.append({
110
+ 'time': current_time,
111
+ 'progress': value
112
+ })
113
+
114
+ # Keep only recent history (last 10 updates)
115
+ if len(self.progress_history) > 10:
116
+ self.progress_history = self.progress_history[-10:]
117
+
118
+ def _calculate_eta(self, current_progress: float, current_time: float) -> str:
119
+ """
120
+ Calculate estimated time of arrival based on progress history.
121
+
122
+ WHY: Uses historical data points to calculate a more accurate ETA
123
+ than simple linear extrapolation, accounting for variations in
124
+ processing speed.
125
+ """
126
+ if current_progress <= 0 or current_progress >= self.total:
127
+ return ""
128
+
129
+ # Need at least 2 data points for calculation
130
+ if len(self.progress_history) < 2:
131
+ return "Calculating ETA..."
132
+
133
+ # Calculate average rate from recent history
134
+ recent_history = self.progress_history[-5:] # Last 5 updates
135
+ if len(recent_history) < 2:
136
+ return "Calculating ETA..."
137
+
138
+ time_span = recent_history[-1]['time'] - recent_history[0]['time']
139
+ progress_span = recent_history[-1]['progress'] - recent_history[0]['progress']
140
+
141
+ if time_span <= 0 or progress_span <= 0:
142
+ return "Calculating ETA..."
143
+
144
+ # Calculate rate (progress per second)
145
+ rate = progress_span / time_span
146
+
147
+ # Calculate remaining work and time
148
+ remaining_progress = self.total - current_progress
149
+ estimated_seconds = remaining_progress / rate
150
+
151
+ # Format ETA
152
+ if estimated_seconds < 60:
153
+ return f"ETA: {estimated_seconds:.0f}s"
154
+ elif estimated_seconds < 3600:
155
+ minutes = estimated_seconds / 60
156
+ return f"ETA: {minutes:.1f}m"
157
+ else:
158
+ hours = estimated_seconds / 3600
159
+ return f"ETA: {hours:.1f}h"
160
+
161
+ def reset(self) -> None:
162
+ """Reset the progress widget to initial state."""
163
+ self.progress = 0.0
164
+ self.status_text = "Initializing..."
165
+ self.start_time = time.time()
166
+ self.progress_history = []
167
+
168
+ # Reset UI elements
169
+ progress_bar = self.query_one("#progress-bar", ProgressBar)
170
+ progress_bar.update(progress=0)
171
+
172
+ status_label = self.query_one("#status-label", Label)
173
+ status_label.update("Initializing...")
174
+
175
+ eta_label = self.query_one("#eta-label", Label)
176
+ eta_label.update("")
177
+
178
+ def complete(self, final_message: str = "Complete!") -> None:
179
+ """Mark progress as complete."""
180
+ self.update_progress(self.total, final_message)
181
+
182
+ # Calculate total elapsed time
183
+ total_time = time.time() - self.start_time
184
+ if total_time < 60:
185
+ time_str = f"{total_time:.1f}s"
186
+ elif total_time < 3600:
187
+ time_str = f"{total_time/60:.1f}m"
188
+ else:
189
+ time_str = f"{total_time/3600:.1f}h"
190
+
191
+ eta_label = self.query_one("#eta-label", Label)
192
+ eta_label.update(f"Completed in {time_str}")
@@ -0,0 +1,490 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitflow-analytics
3
+ Version: 1.0.3
4
+ Summary: Analyze Git repositories for developer productivity insights
5
+ Author-email: Bob Matyas <bobmatnyc@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/bobmatnyc/gitflow-analytics
8
+ Project-URL: Documentation, https://github.com/bobmatnyc/gitflow-analytics/blob/main/README.md
9
+ Project-URL: Repository, https://github.com/bobmatnyc/gitflow-analytics
10
+ Project-URL: Issues, https://github.com/bobmatnyc/gitflow-analytics/issues
11
+ Keywords: git,analytics,productivity,metrics,development
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Version Control :: Git
20
+ Classifier: Topic :: Software Development :: Quality Assurance
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: click>=8.1
25
+ Requires-Dist: gitpython>=3.1
26
+ Requires-Dist: tqdm>=4.65
27
+ Requires-Dist: sqlalchemy>=2.0
28
+ Requires-Dist: pandas>=2.0
29
+ Requires-Dist: pyyaml>=6.0
30
+ Requires-Dist: python-dateutil>=2.8
31
+ Requires-Dist: python-dotenv>=1.0
32
+ Requires-Dist: rich>=13.0.0
33
+ Requires-Dist: spacy>=3.7.0
34
+ Requires-Dist: scikit-learn>=1.3.0
35
+ Requires-Dist: openai>=1.30.0
36
+ Requires-Dist: tiktoken>=0.7.0
37
+ Requires-Dist: numpy>=1.24.0
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest>=7.0; extra == "dev"
40
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
41
+ Requires-Dist: pytest-mock>=3.0; extra == "dev"
42
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
43
+ Requires-Dist: mypy>=1.0; extra == "dev"
44
+ Requires-Dist: black>=23.0; extra == "dev"
45
+ Requires-Dist: isort>=5.0; extra == "dev"
46
+ Requires-Dist: bandit[toml]>=1.7; extra == "dev"
47
+ Requires-Dist: safety>=2.0; extra == "dev"
48
+ Requires-Dist: python-semantic-release>=8.0.0; extra == "dev"
49
+ Requires-Dist: types-PyYAML>=6.0; extra == "dev"
50
+ Requires-Dist: types-requests>=2.28; extra == "dev"
51
+ Provides-Extra: github
52
+ Requires-Dist: pygithub>=1.58; extra == "github"
53
+ Provides-Extra: tui
54
+ Requires-Dist: textual>=0.41.0; extra == "tui"
55
+ Provides-Extra: all
56
+ Requires-Dist: gitflow-analytics[github,tui]; extra == "all"
57
+ Dynamic: license-file
58
+
59
+ # GitFlow Analytics
60
+
61
+ [![PyPI version](https://badge.fury.io/py/gitflow-analytics.svg)](https://badge.fury.io/py/gitflow-analytics)
62
+ [![Python Support](https://img.shields.io/pypi/pyversions/gitflow-analytics.svg)](https://pypi.org/project/gitflow-analytics/)
63
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
64
+
65
+ A Python package for analyzing Git repositories to generate comprehensive developer productivity reports. It extracts data directly from Git history and GitHub APIs, providing weekly summaries, productivity insights, and gap analysis.
66
+
67
+ ## Features
68
+
69
+ - 🚀 **Multi-repository analysis** with project grouping
70
+ - 🏢 **Organization-based repository discovery** from GitHub
71
+ - 👥 **Developer identity resolution** and normalization
72
+ - 📊 **Work volume analysis** (absolute vs relative effort)
73
+ - 🎯 **Story point extraction** from commit messages and PR descriptions
74
+ - 🎫 **Multi-platform ticket tracking** (JIRA, GitHub Issues, ClickUp, Linear)
75
+ - 📈 **Weekly CSV reports** with productivity metrics
76
+ - 🔒 **Data anonymization** for external sharing
77
+ - ⚡ **Smart caching** for fast repeated analyses
78
+ - 🔄 **Batch processing** for large repositories
79
+
80
+ ## Quick Start
81
+
82
+ ### Installation
83
+
84
+ **From PyPI (Recommended):**
85
+
86
+ ```bash
87
+ pip install gitflow-analytics
88
+ ```
89
+
90
+ **From Source (Development):**
91
+
92
+ ```bash
93
+ git clone https://github.com/bobmatnyc/gitflow-analytics.git
94
+ cd gitflow-analytics
95
+ pip install -e ".[dev]"
96
+ ```
97
+
98
+ ### Basic Usage
99
+
100
+ 1. Create a configuration file (`config.yaml`):
101
+
102
+ **Option A: Organization-based (Automatic Repository Discovery)**
103
+ ```yaml
104
+ version: "1.0"
105
+
106
+ github:
107
+ token: "${GITHUB_TOKEN}"
108
+ organization: "myorg" # Automatically discovers all repositories
109
+
110
+ analysis:
111
+ story_point_patterns:
112
+ - "(?:story\\s*points?|sp|pts?)\\s*[:=]\\s*(\\d+)"
113
+ - "\\[(\\d+)\\s*(?:sp|pts?)\\]"
114
+ ```
115
+
116
+ **Option B: Repository-based (Manual Configuration)**
117
+ ```yaml
118
+ version: "1.0"
119
+
120
+ github:
121
+ token: "${GITHUB_TOKEN}"
122
+ owner: "${GITHUB_OWNER}"
123
+
124
+ repositories:
125
+ - name: "frontend"
126
+ path: "~/repos/frontend"
127
+ github_repo: "myorg/frontend"
128
+ project_key: "FRONTEND"
129
+
130
+ - name: "backend"
131
+ path: "~/repos/backend"
132
+ github_repo: "myorg/backend"
133
+ project_key: "BACKEND"
134
+
135
+ analysis:
136
+ story_point_patterns:
137
+ - "(?:story\\s*points?|sp|pts?)\\s*[:=]\\s*(\\d+)"
138
+ - "\\[(\\d+)\\s*(?:sp|pts?)\\]"
139
+ ```
140
+
141
+ 2. Create a `.env` file in the same directory as your `config.yaml`:
142
+
143
+ ```bash
144
+ # .env
145
+ GITHUB_TOKEN=ghp_your_github_token_here
146
+ GITHUB_OWNER=your_github_org # Only for repository-based setup
147
+ ```
148
+
149
+ 3. Run the analysis:
150
+
151
+ ```bash
152
+ gitflow-analytics analyze -c config.yaml
153
+ ```
154
+
155
+ ## Configuration Options
156
+
157
+ ### Environment Variables and Credentials
158
+
159
+ GitFlow Analytics automatically loads environment variables from a `.env` file in the same directory as your configuration YAML. This is the recommended approach for managing credentials securely.
160
+
161
+ #### Step 1: Create a `.env` file
162
+
163
+ Create a `.env` file next to your configuration YAML:
164
+
165
+ ```bash
166
+ # .env file (same directory as your config.yaml)
167
+ # GitHub credentials (required)
168
+ GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
169
+ GITHUB_OWNER=myorg # Optional: default owner for repositories
170
+
171
+ # JIRA credentials (optional - only if using JIRA integration)
172
+ JIRA_ACCESS_USER=your.email@company.com
173
+ JIRA_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxx
174
+
175
+ # Other optional tokens
176
+ CLICKUP_TOKEN=pk_xxxxxxxxxxxx
177
+ LINEAR_TOKEN=lin_api_xxxxxxxxxxxx
178
+ ```
179
+
180
+ #### Step 2: Reference in YAML configuration
181
+
182
+ Use `${VARIABLE_NAME}` syntax in your YAML to reference environment variables:
183
+
184
+ ```yaml
185
+ # config.yaml
186
+ version: "1.0"
187
+
188
+ github:
189
+ token: "${GITHUB_TOKEN}" # Required
190
+ owner: "${GITHUB_OWNER}" # Optional
191
+ organization: "${GITHUB_ORG}" # Optional (for org-based discovery)
192
+
193
+ # Optional: JIRA integration
194
+ jira:
195
+ access_user: "${JIRA_ACCESS_USER}"
196
+ access_token: "${JIRA_ACCESS_TOKEN}"
197
+ base_url: "https://yourcompany.atlassian.net"
198
+
199
+ # Optional: Configure which JIRA fields contain story points
200
+ jira_integration:
201
+ story_point_fields:
202
+ - "Story Points"
203
+ - "customfield_10016" # Your custom field ID
204
+ ```
205
+
206
+ #### Important Notes:
207
+
208
+ - **Never commit `.env` files** to version control (add to `.gitignore`)
209
+ - If credentials are not found in the `.env` file, the tool will exit with an informative error
210
+ - The `.env` file must be in the same directory as your YAML configuration
211
+ - All configured services must have corresponding environment variables set
212
+
213
+ ### Organization vs Repository-based Setup
214
+
215
+ GitFlow Analytics supports two main configuration approaches:
216
+
217
+ #### Organization-based Configuration (Recommended)
218
+
219
+ Automatically discovers all non-archived repositories from a GitHub organization:
220
+
221
+ ```yaml
222
+ version: "1.0"
223
+
224
+ github:
225
+ token: "${GITHUB_TOKEN}"
226
+ organization: "myorg" # Your GitHub organization name
227
+
228
+ # Optional: Customize analysis settings
229
+ analysis:
230
+ story_point_patterns:
231
+ - "(?:story\\s*points?|sp|pts?)\\s*[:=]\\s*(\\d+)"
232
+
233
+ exclude:
234
+ authors:
235
+ - "dependabot[bot]"
236
+ - "github-actions[bot]"
237
+ ```
238
+
239
+ **Benefits:**
240
+ - Automatically discovers new repositories as they're added to the organization
241
+ - No need to manually configure each repository
242
+ - Simplified configuration management
243
+ - Perfect for teams with many repositories
244
+
245
+ **Requirements:**
246
+ - Your GitHub token must have organization read access
247
+ - Repositories will be automatically cloned to local directories if they don't exist
248
+
249
+ #### Repository-based Configuration
250
+
251
+ Manually specify each repository to analyze:
252
+
253
+ ```yaml
254
+ version: "1.0"
255
+
256
+ github:
257
+ token: "${GITHUB_TOKEN}"
258
+ owner: "${GITHUB_OWNER}" # Default owner for repositories
259
+
260
+ repositories:
261
+ - name: "frontend"
262
+ path: "~/repos/frontend"
263
+ github_repo: "myorg/frontend"
264
+ project_key: "FRONTEND"
265
+
266
+ - name: "backend"
267
+ path: "~/repos/backend"
268
+ github_repo: "myorg/backend"
269
+ project_key: "BACKEND"
270
+
271
+ analysis:
272
+ story_point_patterns:
273
+ - "(?:story\\s*points?|sp|pts?)\\s*[:=]\\s*(\\d+)"
274
+ ```
275
+
276
+ **Benefits:**
277
+ - Fine-grained control over which repositories to analyze
278
+ - Custom project keys and local paths
279
+ - Works with mixed-ownership repositories
280
+ - Compatible with existing configurations
281
+
282
+ ### Directory Defaults
283
+
284
+ GitFlow Analytics now defaults cache and report directories to be relative to the configuration file location:
285
+
286
+ - **Reports**: Default to same directory as config file (unless overridden with `--output`)
287
+ - **Cache**: Default to `.gitflow-cache/` in config file directory
288
+ - **Backward compatibility**: Absolute paths in configuration continue to work as before
289
+
290
+ Example directory structure:
291
+ ```
292
+ /project/
293
+ ├── config.yaml # Configuration file
294
+ ├── weekly_metrics.csv # Reports generated here by default
295
+ ├── summary.csv
296
+ └── .gitflow-cache/ # Cache directory
297
+ ├── gitflow_cache.db
298
+ └── identities.db
299
+ ```
300
+
301
+ ## Command Line Interface
302
+
303
+ ### Main Commands
304
+
305
+ ```bash
306
+ # Analyze repositories
307
+ gitflow-analytics analyze -c config.yaml --weeks 12 --output ./reports
308
+
309
+ # Show cache statistics
310
+ gitflow-analytics cache-stats -c config.yaml
311
+
312
+ # List known developers
313
+ gitflow-analytics list-developers -c config.yaml
314
+
315
+ # Merge developer identities
316
+ gitflow-analytics merge-identity -c config.yaml dev1_id dev2_id
317
+
318
+ # Discover JIRA story point fields
319
+ gitflow-analytics discover-jira-fields -c config.yaml
320
+ ```
321
+
322
+ ### Options
323
+
324
+ - `--weeks, -w`: Number of weeks to analyze (default: 12)
325
+ - `--output, -o`: Output directory for reports (default: ./reports)
326
+ - `--anonymize`: Anonymize developer information
327
+ - `--no-cache`: Disable caching for fresh analysis
328
+ - `--clear-cache`: Clear cache before analysis
329
+ - `--validate-only`: Validate configuration without running
330
+
331
+ ## Complete Configuration Example
332
+
333
+ Here's a complete example showing `.env` file and corresponding YAML configuration:
334
+
335
+ ### `.env` file
336
+ ```bash
337
+ # GitHub Configuration
338
+ GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
339
+ GITHUB_ORG=EWTN-Global
340
+
341
+ # JIRA Configuration
342
+ JIRA_ACCESS_USER=developer@ewtn.com
343
+ JIRA_ACCESS_TOKEN=ATATT3xxxxxxxxxxx
344
+
345
+ # Optional: Other integrations
346
+ # CLICKUP_TOKEN=pk_xxxxxxxxxxxx
347
+ # LINEAR_TOKEN=lin_api_xxxxxxxxxxxx
348
+ ```
349
+
350
+ ### `config.yaml` file
351
+ ```yaml
352
+ version: "1.0"
353
+
354
+ # GitHub configuration with organization discovery
355
+ github:
356
+ token: "${GITHUB_TOKEN}"
357
+ organization: "${GITHUB_ORG}"
358
+
359
+ # JIRA integration for story points
360
+ jira:
361
+ access_user: "${JIRA_ACCESS_USER}"
362
+ access_token: "${JIRA_ACCESS_TOKEN}"
363
+ base_url: "https://ewtn.atlassian.net"
364
+
365
+ jira_integration:
366
+ enabled: true
367
+ fetch_story_points: true
368
+ story_point_fields:
369
+ - "Story point estimate" # Your field name
370
+ - "customfield_10016" # Fallback field ID
371
+
372
+ # Analysis configuration
373
+ analysis:
374
+ # Only track JIRA tickets (ignore GitHub issues, etc.)
375
+ ticket_platforms:
376
+ - jira
377
+
378
+ # Exclude bot commits and boilerplate files
379
+ exclude:
380
+ authors:
381
+ - "dependabot[bot]"
382
+ - "renovate[bot]"
383
+ paths:
384
+ - "**/node_modules/**"
385
+ - "**/*.min.js"
386
+ - "**/package-lock.json"
387
+
388
+ # Developer identity consolidation
389
+ identity:
390
+ similarity_threshold: 0.85
391
+ manual_mappings:
392
+ - primary_email: "john.doe@company.com"
393
+ aliases:
394
+ - "jdoe@oldcompany.com"
395
+ - "john@personal.com"
396
+
397
+ # Output configuration
398
+ output:
399
+ directory: "./reports"
400
+ formats:
401
+ - csv
402
+ - markdown
403
+ ```
404
+
405
+ ## Output Reports
406
+
407
+ The tool generates three CSV reports:
408
+
409
+ 1. **Weekly Metrics** (`weekly_metrics_YYYYMMDD.csv`)
410
+ - Week-by-week developer productivity
411
+ - Story points, commits, lines changed
412
+ - Ticket coverage percentages
413
+ - Per-project breakdown
414
+
415
+ 2. **Summary Statistics** (`summary_YYYYMMDD.csv`)
416
+ - Overall project statistics
417
+ - Platform-specific ticket counts
418
+ - Top contributors
419
+
420
+ 3. **Developer Report** (`developers_YYYYMMDD.csv`)
421
+ - Complete developer profiles
422
+ - Total contributions
423
+ - Identity aliases
424
+
425
+ ## Story Point Patterns
426
+
427
+ Configure custom regex patterns to match your team's story point format:
428
+
429
+ ```yaml
430
+ story_point_patterns:
431
+ - "SP: (\\d+)" # SP: 5
432
+ - "\\[([0-9]+) pts\\]" # [3 pts]
433
+ - "estimate: (\\d+)" # estimate: 8
434
+ ```
435
+
436
+ ## Ticket Platform Support
437
+
438
+ Automatically detects and tracks tickets from:
439
+ - **JIRA**: `PROJ-123`
440
+ - **GitHub**: `#123`, `GH-123`
441
+ - **ClickUp**: `CU-abc123`
442
+ - **Linear**: `ENG-123`
443
+
444
+ ### JIRA Integration
445
+
446
+ GitFlow Analytics can fetch story points directly from JIRA tickets. Configure your JIRA instance:
447
+
448
+ ```yaml
449
+ jira:
450
+ access_user: "${JIRA_ACCESS_USER}"
451
+ access_token: "${JIRA_ACCESS_TOKEN}"
452
+ base_url: "https://your-company.atlassian.net"
453
+
454
+ jira_integration:
455
+ enabled: true
456
+ story_point_fields:
457
+ - "Story point estimate" # Your custom field name
458
+ - "customfield_10016" # Or use field ID
459
+ ```
460
+
461
+ To discover your JIRA story point fields:
462
+ ```bash
463
+ gitflow-analytics discover-jira-fields -c config.yaml
464
+ ```
465
+
466
+ ## Caching
467
+
468
+ The tool uses SQLite for intelligent caching:
469
+ - Commit analysis results
470
+ - Developer identity mappings
471
+ - Pull request data
472
+
473
+ Cache is automatically managed with configurable TTL.
474
+
475
+ ## Developer Identity Resolution
476
+
477
+ Intelligently merges developer identities across:
478
+ - Different email addresses
479
+ - Name variations
480
+ - GitHub usernames
481
+
482
+ Manual overrides supported in configuration.
483
+
484
+ ## Contributing
485
+
486
+ Contributions are welcome! Please feel free to submit a Pull Request.
487
+
488
+ ## License
489
+
490
+ This project is licensed under the MIT License - see the LICENSE file for details.