-
Notifications
You must be signed in to change notification settings - Fork 0
Added jira integration #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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. |
| Original file line number | Diff line number | Diff line change | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,6 +10,7 @@ rich>=13.3.5 | ||||||||||||||||
| plotly | |||||||||||||||||
| markdown | |||||||||||||||||
| cryptography>=43.0.1 | |||||||||||||||||
| requests | |||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainPin the requests dependency version for security and stability. Adding Apply this diff to pin to a recent stable version: -requests
+requests>=2.31.0,<3.0.0Let me verify the latest stable version of requests: 🌐 Web query: 💡 Result: Latest Stable Version of RequestsThe 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 Advisories2024–2025 Security Advisories
Significant Past Vulnerabilities
No additional Requests-specific vulnerabilities have been reported in 2025 as of this writing[9]. Recommendations
Summary Table
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 -requests
+requests>=2.32.3,<3.0.0📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
|||||||||||||||||
| types-requests | |||||||||||||||||
| types-python-dateutil | |||||||||||||||||
| pandas-stubs | |||||||||||||||||
|
|
|||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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" | ||
|
|
@@ -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"), | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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"),
🤖 Prompt for AI Agents |
||
| "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) | ||
|
|
@@ -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![/]") | ||
|
|
@@ -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.") | ||
There was a problem hiding this comment.
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.