Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 223 additions & 0 deletions JIRA_INTEGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
# Jira Cloud Integration

This document describes how to set up and use the Jira Cloud integration with Wellcode CLI as an alternative to Linear for issue tracking metrics.

## Overview

The Jira Cloud integration provides comprehensive issue tracking analytics including:

- **Issue Flow Metrics**: Creation, completion, and in-progress tracking
- **Issue Type Analysis**: Bugs, Stories, Tasks, and Epics breakdown
- **Cycle Time Metrics**: Time from creation to resolution
- **Estimation Accuracy**: Story points vs actual time analysis
- **Project Performance**: Per-project metrics and health indicators
- **Assignee Performance**: Individual contributor metrics
- **Priority Distribution**: Issue priority analysis
- **Component & Version Tracking**: Component and fix version metrics

## Prerequisites

1. **Jira Cloud Instance**: You need access to a Jira Cloud instance (*.atlassian.net)
2. **API Token**: Generate an API token from your Atlassian account
3. **Permissions**: Read access to projects and issues you want to analyze

## Setup Instructions

### 1. Generate Jira API Token

1. Go to [Atlassian Account Security](https://id.atlassian.com/manage-profile/security/api-tokens)
2. Click "Create API token"
3. Give it a descriptive name (e.g., "Wellcode CLI")
4. Copy the generated token (you won't be able to see it again)

### 2. Configure Wellcode CLI

Run the configuration command:

```bash
wellcode-cli config
```

When prompted for Jira configuration, provide:

- **Domain**: Your Jira domain (e.g., `mycompany` for `mycompany.atlassian.net`)
- **Email**: Your Atlassian account email address
- **API Token**: The token you generated in step 1

The CLI will test the connection and save your configuration if successful.

### 3. Verify Setup

Test your configuration by running:

```bash
wellcode-cli review
```

You should see Jira metrics alongside your GitHub metrics.

## Usage

### Basic Usage

```bash
# Review last 7 days (default)
wellcode-cli review

# Review specific date range
wellcode-cli review --start-date 2024-01-01 --end-date 2024-01-31

# Review specific user's issues
wellcode-cli review --user "john.doe@company.com"
```

### Filtering Options

- `--user`: Filter by assignee (use email address or Jira username)
- `--start-date`: Start date for analysis (YYYY-MM-DD format)
- `--end-date`: End date for analysis (YYYY-MM-DD format)

## Metrics Explained

### Issue Flow Metrics

- **Issues Created**: Total issues created in the time period
- **Issues Completed**: Issues moved to "Done" status
- **Completion Rate**: Percentage of created issues that were completed
- **Issue Types**: Breakdown by Bugs, Stories, Tasks, and Epics

### Cycle Time Metrics

- **Average Cycle Time**: Mean time from creation to resolution
- **Median Cycle Time**: 50th percentile cycle time
- **95th Percentile**: 95th percentile cycle time (helps identify outliers)
- **Resolution Time**: Time to close/resolve issues

### Estimation Accuracy

- **Accuracy Rate**: Percentage of estimates within 25% of actual time
- **Underestimates**: Issues that took longer than estimated
- **Overestimates**: Issues that took less time than estimated
- **Variance**: Average percentage difference between estimate and actual

### Project Performance

- **Completion Rate**: Per-project completion percentage
- **Issue Distribution**: Breakdown by issue types per project
- **Assignee Involvement**: Number of people working on each project
- **Project Lead**: Project lead information
- **Project Type**: Software, Business, etc.

## Customization

### Story Points Field

The integration looks for story points in the `customfield_10016` field by default. If your Jira instance uses a different field for story points, you can modify this in the code:

```python
# In src/wellcode_cli/jira/models/metrics.py
story_points = fields.get("customfield_XXXXX") # Replace XXXXX with your field ID
```

To find your story points field ID:
1. Go to Jira Settings → Issues → Custom Fields
2. Find your Story Points field
3. Note the field ID (usually in the format `customfield_XXXXX`)

### Time Estimation

The integration supports both:
- **Story Points**: Converted to hours (1 point = 4 hours by default)
- **Time Estimates**: Original time estimates in Jira

## Troubleshooting

### Common Issues

1. **Authentication Failed**
- Verify your email address is correct
- Ensure your API token is valid and not expired
- Check that your domain is correct (without .atlassian.net)

2. **No Issues Found**
- Verify the date range includes issues
- Check that you have read permissions for the projects
- Ensure issues exist in the specified time period

3. **Missing Metrics**
- Some metrics require specific Jira configurations (story points, time tracking)
- Ensure your Jira instance has the required fields enabled

### Debug Mode

Enable debug logging to troubleshoot issues:

```bash
export WELLCODE_DEBUG=1
wellcode-cli review
```

### API Rate Limits

Jira Cloud has API rate limits:
- 300 requests per minute for most endpoints
- The integration uses pagination to handle large datasets efficiently

## Security

- API tokens are stored locally in `~/.wellcode/config.json`
- Tokens are transmitted over HTTPS only
- No data is sent to external services except Jira Cloud

## Comparison with Linear

| Feature | Jira Cloud | Linear |
|---------|------------|--------|
| Issue Types | Bugs, Stories, Tasks, Epics | Issues with Labels |
| Projects | Native project support | Team-based organization |
| Time Tracking | Built-in time tracking | Estimation-based |
| Custom Fields | Extensive customization | Limited custom fields |
| Workflow | Configurable workflows | Fixed workflow states |
| API Rate Limits | 300/minute | 1000/hour |

## Advanced Configuration

### Environment Variables

You can also configure Jira using environment variables:

```bash
export JIRA_DOMAIN="mycompany"
export JIRA_EMAIL="user@company.com"
export JIRA_API_KEY="your-api-token"
```

### JQL Customization

The integration uses JQL (Jira Query Language) to fetch issues. The default query is:

```jql
created >= 'YYYY-MM-DD' AND created <= 'YYYY-MM-DD'
```

For advanced users, you can modify the JQL in `src/wellcode_cli/jira/jira_metrics.py`.

## Support

For issues with the Jira integration:

1. Check the troubleshooting section above
2. Enable debug mode for detailed logs
3. Verify your Jira permissions and configuration
4. Create an issue in the Wellcode CLI repository with debug logs

## Contributing

To contribute to the Jira integration:

1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Submit a pull request

The Jira integration follows the same patterns as other integrations in the codebase for consistency and maintainability.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<strong>Engineering Metrics Powered by AI</strong>
</p>
<p align="center">
Free, open-source CLI tool that integrates with GitHub, Linear, and Split.io to gather and analyze engineering team metrics.
Free, open-source CLI tool that integrates with GitHub, Linear, Jira Cloud, and Split.io to gather and analyze engineering team metrics.
</p>

## 🚀 Installation
Expand All @@ -27,6 +27,7 @@ wellcode-cli config
This will guide you through:
- GitHub App installation for your organization
- Optional Linear integration
- Optional Jira Cloud integration
- Optional Split.io integration
- Optional Anthropic integration (for AI-powered insights)

Expand Down Expand Up @@ -88,6 +89,7 @@ wellcode-cli

### Optional Integrations
- **Linear**: Issue tracking metrics
- **Jira Cloud**: Issue tracking metrics (alternative to Linear)
Copy link

Copilot AI May 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README mentions Jira Cloud integration but lacks a link to the detailed JIRA_INTEGRATION.md guide. Add a reference or hyperlink under Optional Integrations or Documentation for users to access the full instructions.

Suggested change
- **Jira Cloud**: Issue tracking metrics (alternative to Linear)
- **Jira Cloud**: Issue tracking metrics (alternative to Linear). See the [Jira Cloud Integration Guide](JIRA_INTEGRATION.md) for setup instructions.

Copilot uses AI. Check for mistakes.
- **Split.io**: Feature flag analytics
- **Anthropic**: AI-powered insights

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ rich>=13.3.5
plotly
markdown
cryptography>=43.0.1
requests
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Pin the requests dependency version for security and stability.

Adding requests without version constraints poses security and stability risks. Most other dependencies in this file are properly pinned (e.g., setuptools==75.6.0, cryptography>=43.0.1).

Apply this diff to pin to a recent stable version:

-requests
+requests>=2.31.0,<3.0.0

Let me verify the latest stable version of requests:


🌐 Web query:

What is the latest stable version of requests library and any recent security advisories?

💡 Result:

Latest Stable Version of Requests

The latest stable version of the Python Requests library is 2.32.3[4]. This version is compatible with Python 3.8 and above, as officially supported[1][5].

Recent Security Advisories

2024–2025 Security Advisories

  • CVE-2024-35195: A recent moderate severity vulnerability in Requests was addressed where "subsequent requests to the same host ignore cert verification", potentially exposing connections to man-in-the-middle attacks if certificate verification is bypassed. This issue affected some distributions (e.g., Red Hat Enterprise Linux 8) and has been patched in recent updates[6].

Significant Past Vulnerabilities

  • CVE-2023-32681: Requests versions 2.3.0 to 2.30.0 had a flaw that could leak Proxy-Authorization headers to destination servers when following HTTPS redirects. This exposed proxy credentials if proxies were configured with authentication. The issue was patched in version 2.31.0, and users relying on proxies with credentials were strongly advised to upgrade and rotate credentials[7][9].

No additional Requests-specific vulnerabilities have been reported in 2025 as of this writing[9].

Recommendations

  • Upgrade to the latest version, 2.32.3, to benefit from security and bug fixes.
  • If you use authenticated proxies, ensure you’re running at least version 2.31.0 to avoid credential leaks[7][9].
  • Check your operating system’s package repositories for patched versions if installing via system packages (e.g., RHEL)[6].

Summary Table

Version Release Date Key Security Patches
2.32.3 2025 Latest stable, moderate cert verification fix[4][6]
2.31.0+ 2023-05 Proxy-Authorization leak fixed (CVE-2023-32681)[7][9]

Stay up to date with the latest releases to ensure security and stability.

Citations:


Pin requests to the latest secure version (≥2.32.3,<3.0.0)

Unpinned dependencies expose you to security risks and breaking changes. The Requests library has recent advisories—CVE-2024-35195 (cert-verification bypass) and CVE-2023-32681 (proxy-auth header leak)—that are fixed in 2.32.3. We should pin Requests accordingly.

• File: requirements.txt, line 13
• Change from unpinned to a range that includes the latest patch but excludes a potential v3 release

-requests
+requests>=2.32.3,<3.0.0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
requests
-requests
+requests>=2.32.3,<3.0.0
🤖 Prompt for AI Agents
In requirements.txt at line 13, the requests dependency is currently unpinned,
which poses security and stability risks. Update the line to pin requests to a
secure and stable version range by specifying "requests>=2.32.3,<3.0.0" to
include the latest patched version 2.32.3 and exclude any potential breaking
changes from a major version 3 release.

types-requests
types-python-dateutil
pandas-stubs
Expand Down
83 changes: 80 additions & 3 deletions src/wellcode_cli/commands/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ..github.app_config import WELLCODE_APP
from ..github.auth import clear_user_token, get_user_token
from ..github.client import GithubClient
from ..jira.jira_metrics import test_jira_connection

console = Console()
CONFIG_FILE = Path.home() / ".wellcode" / "config.json"
Expand Down Expand Up @@ -111,13 +112,19 @@ def config():
# Optional integrations with secret masking
optional_configs = {
"Linear": ("LINEAR_API_KEY", "Enter your Linear API key"),
"Jira": ("JIRA_API_KEY", "Enter your Jira API key"),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Update the dictionary entry to reflect Jira's multi-field requirement.

The entry for Jira in optional_configs is misleading as it shows "JIRA_API_KEY" as the key, but the actual implementation requires three fields (JIRA_DOMAIN, JIRA_EMAIL, JIRA_API_KEY). Consider updating this to better reflect the actual requirement.

Apply this diff to clarify the Jira configuration entry:

-            "Jira": ("JIRA_API_KEY", "Enter your Jira API key"),
+            "Jira": ("JIRA_CONFIG", "Configure Jira integration"),

Alternatively, you could document this as a comment:

             "Linear": ("LINEAR_API_KEY", "Enter your Linear API key"),
-            "Jira": ("JIRA_API_KEY", "Enter your Jira API key"),
+            "Jira": ("JIRA_API_KEY", "Enter your Jira API key"),  # Note: Jira requires 3 fields
             "Split.io": ("SPLIT_API_KEY", "Enter your Split.io API key"),

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/wellcode_cli/commands/config.py at line 115, the Jira entry in the
optional_configs dictionary currently lists only "JIRA_API_KEY" as the key,
which is misleading since the implementation requires three fields:
"JIRA_DOMAIN", "JIRA_EMAIL", and "JIRA_API_KEY". Update this dictionary entry to
either list all three required keys or add a clarifying comment explaining the
multi-field requirement for Jira configuration to accurately reflect the actual
setup.

"Split.io": ("SPLIT_API_KEY", "Enter your Split.io API key"),
"Anthropic": ("ANTHROPIC_API_KEY", "Enter your Anthropic API key"),
}

for name, (key, prompt) in optional_configs.items():
console.print(f"\n[bold cyan]{name} Configuration[/]")
handle_sensitive_config(config_data, name, key, prompt)

# Special handling for Jira to get additional required fields
if name == "Jira":
handle_jira_config(config_data)
else:
handle_sensitive_config(config_data, name, key, prompt)

# Save configuration
CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True)
Expand All @@ -134,8 +141,14 @@ def config():
console.print("[green]✓ GitHub App installed and configured[/]")

for name, (key, _) in optional_configs.items():
status = "✓" if key in config_data else "✗"
color = "green" if key in config_data else "red"
if name == "Jira":
# Special check for Jira which requires multiple fields
has_jira = all(k in config_data for k in ["JIRA_DOMAIN", "JIRA_EMAIL", "JIRA_API_KEY"])
status = "✓" if has_jira else "✗"
color = "green" if has_jira else "red"
else:
status = "✓" if key in config_data else "✗"
color = "green" if key in config_data else "red"
console.print(f"[{color}]{status} {name}[/]")

console.print("\n✅ [green]Configuration saved successfully![/]")
Expand Down Expand Up @@ -184,3 +197,67 @@ def handle_sensitive_config(config_data, name, key, prompt_text):
value = Prompt.ask(prompt_text)
if value:
config_data[key] = value


def handle_jira_config(config_data):
"""Handle Jira configuration with domain, email, and API key"""
has_jira_config = all(key in config_data for key in ["JIRA_DOMAIN", "JIRA_EMAIL", "JIRA_API_KEY"])

if has_jira_config:
console.print("[yellow]Jira integration is already configured[/]")
choice = Prompt.ask(
"Would you like to reconfigure Jira?",
choices=["y", "n", "clear"],
default="n",
)

if choice == "y":
configure_jira_details(config_data)
elif choice == "clear":
for key in ["JIRA_DOMAIN", "JIRA_EMAIL", "JIRA_API_KEY"]:
if key in config_data:
del config_data[key]
console.print("[yellow]Jira configuration cleared[/]")
else:
if Confirm.ask("Would you like to configure Jira integration?", default=False):
configure_jira_details(config_data)


def configure_jira_details(config_data):
"""Configure Jira domain, email, and API key"""
console.print("\n[bold]Jira Cloud Configuration[/]")
console.print("You'll need:")
console.print("1. Your Jira domain (e.g., 'mycompany' for mycompany.atlassian.net)")
console.print("2. Your email address")
console.print("3. An API token from https://id.atlassian.com/manage-profile/security/api-tokens")

# Get domain
current_domain = config_data.get("JIRA_DOMAIN", "")
domain = Prompt.ask("Enter your Jira domain", default=current_domain)
if not domain:
console.print("[red]Domain is required for Jira integration[/]")
return

# Get email
current_email = config_data.get("JIRA_EMAIL", "")
email = Prompt.ask("Enter your email address", default=current_email)
if not email:
console.print("[red]Email is required for Jira integration[/]")
return

# Get API key
api_key = Prompt.ask("Enter your Jira API token")
if not api_key:
console.print("[red]API token is required for Jira integration[/]")
return

# Test the connection
console.print("\n[yellow]Testing Jira connection...[/]")
if test_jira_connection(domain, email, api_key):
config_data["JIRA_DOMAIN"] = domain
config_data["JIRA_EMAIL"] = email
config_data["JIRA_API_KEY"] = api_key
console.print("[green]✓ Jira configuration saved successfully![/]")
else:
console.print("[red]✗ Jira connection failed. Configuration not saved.[/]")
console.print("Please check your domain, email, and API token.")
Loading
Loading