Initial commit
This commit is contained in:
235
skills/jira/README.md
Normal file
235
skills/jira/README.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# Jira Integration Skill
|
||||
|
||||
Quick reference for using the Jira integration skill in PRISM.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Setup (First Time Only)
|
||||
|
||||
Generate your Jira API token:
|
||||
1. Visit: https://id.atlassian.com/manage-profile/security/api-tokens
|
||||
2. Click "Create API token"
|
||||
3. Name it (e.g., "PRISM Local Dev")
|
||||
4. Copy the token
|
||||
|
||||
Configure credentials:
|
||||
```bash
|
||||
# Create .env file in repository root
|
||||
cp .env.example .env
|
||||
|
||||
# Add your credentials to .env
|
||||
JIRA_EMAIL=your.email@resolve.io
|
||||
JIRA_API_TOKEN=your_token_here
|
||||
```
|
||||
|
||||
### 2. Usage
|
||||
|
||||
**Automatic Detection**:
|
||||
```
|
||||
User: "Let's work on PLAT-456"
|
||||
# Skill automatically detects and fetches PLAT-456
|
||||
```
|
||||
|
||||
**Explicit Command**:
|
||||
```
|
||||
User: "jira PLAT-789"
|
||||
# Fetches and displays PLAT-789 details
|
||||
```
|
||||
|
||||
**Proactive Inquiry**:
|
||||
```
|
||||
User: "Implement login feature"
|
||||
Agent: "Do you have a JIRA ticket number so I can get more context?"
|
||||
User: "PLAT-123"
|
||||
# Fetches and displays context
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- ✅ Automatic issue key detection (`PLAT-123`, `PROJ-456`)
|
||||
- ✅ Fetch full issue details with acceptance criteria
|
||||
- ✅ Show recent comments and context
|
||||
- ✅ Display linked issues and dependencies
|
||||
- ✅ Epic → Story → Task hierarchy
|
||||
- ✅ Session caching (fetch once, use multiple times)
|
||||
- ✅ Graceful degradation (continues if Jira unavailable)
|
||||
- ✅ Read-only (safe, non-invasive)
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `jira {key}` | Fetch and display issue details |
|
||||
| `jira-epic {key}` | Fetch epic with all child stories |
|
||||
| `jira-search {jql}` | Search issues with JQL query |
|
||||
|
||||
## Integration with Other Skills
|
||||
|
||||
The Jira skill enhances all PRISM skills:
|
||||
|
||||
- **Story Master (sm)**: Fetch epics for decomposition
|
||||
- **Developer (dev)**: Get story context for implementation
|
||||
- **Product Owner (po)**: Validate stories against tickets
|
||||
- **QA (qa)**: Get acceptance criteria for testing
|
||||
- **Support (support)**: Investigate bugs with full context
|
||||
- **Architect (architect)**: Review epic technical requirements
|
||||
- **Peer (peer)**: Verify implementation against AC
|
||||
|
||||
## Examples
|
||||
|
||||
### Decomposing an Epic
|
||||
|
||||
```
|
||||
User: "Decompose PLAT-789"
|
||||
|
||||
# Jira skill automatically:
|
||||
# 1. Fetches epic details
|
||||
# 2. Shows epic goal and AC
|
||||
# 3. Lists existing child stories (to avoid duplication)
|
||||
# 4. Provides context to Story Master skill
|
||||
```
|
||||
|
||||
### Implementing a Story
|
||||
|
||||
```
|
||||
User: "Implement PLAT-456"
|
||||
|
||||
# Jira skill automatically:
|
||||
# 1. Fetches story details
|
||||
# 2. Shows acceptance criteria
|
||||
# 3. Displays technical notes from comments
|
||||
# 4. Lists blocking issues
|
||||
# 5. Provides context to Developer skill
|
||||
```
|
||||
|
||||
### Investigating a Bug
|
||||
|
||||
```
|
||||
User: "Investigate bug PLAT-999"
|
||||
|
||||
# Jira skill automatically:
|
||||
# 1. Fetches bug details
|
||||
# 2. Shows reproduction steps
|
||||
# 3. Displays customer comments
|
||||
# 4. Lists related bugs
|
||||
# 5. Provides context to Support skill
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Jira authentication failed"
|
||||
|
||||
**Problem**: Invalid or missing credentials
|
||||
|
||||
**Solution**:
|
||||
1. Verify `.env` file exists in repository root
|
||||
2. Check `JIRA_EMAIL` is correct Atlassian email
|
||||
3. Generate new API token and update `JIRA_API_TOKEN`
|
||||
4. Restart terminal/IDE to reload environment
|
||||
|
||||
### "Access denied to PLAT-123"
|
||||
|
||||
**Problem**: You lack permission to view issue
|
||||
|
||||
**Solution**:
|
||||
1. Verify you can view issue in Jira web UI
|
||||
2. Request access from Jira administrator
|
||||
3. Check issue key spelling
|
||||
|
||||
### "Issue PLAT-123 not found"
|
||||
|
||||
**Problem**: Issue doesn't exist
|
||||
|
||||
**Solution**:
|
||||
1. Verify issue key spelling (uppercase, correct number)
|
||||
2. Check if issue was deleted or moved
|
||||
3. Try viewing in Jira web UI
|
||||
|
||||
### "Rate limit exceeded"
|
||||
|
||||
**Problem**: Too many requests in short time
|
||||
|
||||
**Solution**:
|
||||
1. Wait 60 seconds before retrying
|
||||
2. Use cached data from earlier in conversation
|
||||
3. Avoid fetching same issue multiple times
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration in [core-config.yaml](../../core-config.yaml):
|
||||
|
||||
```yaml
|
||||
jira:
|
||||
enabled: true # Master switch
|
||||
baseUrl: https://resolvesys.atlassian.net # Your Jira instance
|
||||
email: ${JIRA_EMAIL} # From .env file
|
||||
token: ${JIRA_API_TOKEN} # From .env file
|
||||
defaultProject: PLAT # Default project key
|
||||
issueKeyPattern: "[A-Z]+-\\d+" # Issue key regex
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
**Best Practices**:
|
||||
- ✅ Use environment variables (`.env` file)
|
||||
- ✅ Each developer has their own API token
|
||||
- ✅ `.env` file is gitignored (never commit!)
|
||||
- ✅ Rotate tokens every 90 days
|
||||
- ✅ Revoke unused tokens immediately
|
||||
|
||||
**Never**:
|
||||
- ❌ Hardcode credentials in code
|
||||
- ❌ Commit credentials to git
|
||||
- ❌ Share API tokens with teammates
|
||||
- ❌ Use passwords (API tokens only!)
|
||||
- ❌ Embed credentials in URLs
|
||||
|
||||
## Documentation
|
||||
|
||||
**Detailed Guides**:
|
||||
- [SKILL.md](./SKILL.md) - Complete skill overview
|
||||
- [API Reference](./reference/api-reference.md) - Jira REST API details
|
||||
- [Extraction Format](./reference/extraction-format.md) - Issue formatting standards
|
||||
- [Authentication](./reference/authentication.md) - Security and setup
|
||||
- [Error Handling](./reference/error-handling.md) - Troubleshooting guide
|
||||
|
||||
**Quick Links**:
|
||||
- [Generate API Token](https://id.atlassian.com/manage-profile/security/api-tokens)
|
||||
- [Jira Status](https://status.atlassian.com/)
|
||||
- [JQL Documentation](https://support.atlassian.com/jira-service-management-cloud/docs/use-advanced-search-with-jira-query-language-jql/)
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: Is this read-only?**
|
||||
A: Yes! The skill only fetches data, never creates or modifies issues.
|
||||
|
||||
**Q: Does this work automatically?**
|
||||
A: Yes! Just mention an issue key (PLAT-123) and it fetches automatically.
|
||||
|
||||
**Q: Can I disable auto-detection?**
|
||||
A: Yes, use `auto-detect off` command.
|
||||
|
||||
**Q: What if Jira is down?**
|
||||
A: The skill gracefully degrades. It informs you and continues without Jira context.
|
||||
|
||||
**Q: Do I need a Jira license?**
|
||||
A: You need access to view issues in Jira. A basic Jira Software license is sufficient.
|
||||
|
||||
**Q: Can I search for issues?**
|
||||
A: Yes! Use `jira-search "project = PLAT AND type = Bug"`
|
||||
|
||||
## Support
|
||||
|
||||
**Issues**:
|
||||
- Check [Error Handling Guide](./reference/error-handling.md)
|
||||
- Verify [Authentication Setup](./reference/authentication.md)
|
||||
- Review `.env` configuration
|
||||
|
||||
**Enhancement Requests**:
|
||||
- Propose in team wiki or project documentation
|
||||
- Consider custom field mappings for your Jira instance
|
||||
|
||||
---
|
||||
|
||||
**Skill Version**: 1.0.0
|
||||
**Last Updated**: 2025-11-20
|
||||
433
skills/jira/SKILL.md
Normal file
433
skills/jira/SKILL.md
Normal file
@@ -0,0 +1,433 @@
|
||||
---
|
||||
name: jira
|
||||
description: Jira integration for fetching issue context (Epics, Stories, Bugs) to enhance development workflows. Use for automatic issue detection, retrieving ticket details, acceptance criteria, and linked dependencies.
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
# Jira Integration
|
||||
|
||||
## When to Use
|
||||
|
||||
- User mentions a Jira issue key (e.g., "PLAT-123")
|
||||
- Need to fetch Epic details for decomposition
|
||||
- Retrieve story context for implementation
|
||||
- Get bug details and reproduction steps
|
||||
- Check acceptance criteria from tickets
|
||||
- Review linked issues and dependencies
|
||||
- Fetch customer comments and context
|
||||
|
||||
## What This Skill Does
|
||||
|
||||
**Provides read-only Jira integration** to enrich development workflows:
|
||||
|
||||
- **Automatic Detection**: Recognizes issue keys in conversation (PLAT-123, ISSUE-456)
|
||||
- **Context Fetching**: Retrieves full issue details via Jira REST API using curl
|
||||
- **Structured Formatting**: Presents issue data in clear, development-ready format
|
||||
- **Linked Issues**: Follows Epic → Story → Task relationships
|
||||
- **Comment History**: Shows recent comments and customer feedback
|
||||
- **Acceptance Criteria**: Extracts AC from description or custom fields
|
||||
- **Dependency Tracking**: Identifies blockers and related issues
|
||||
|
||||
## Core Principles
|
||||
|
||||
### 🎫 The Jira Integration Mindset
|
||||
|
||||
**Automated context retrieval** without leaving your workflow:
|
||||
|
||||
- **Proactive Detection**: Automatically spots issue keys in conversation
|
||||
- **Read-Only**: Safe, non-intrusive access to Jira data
|
||||
- **Privacy Respecting**: Only fetches explicitly mentioned or approved issues
|
||||
- **Session Caching**: Stores fetched data for conversation duration
|
||||
- **Graceful Degradation**: Continues without Jira if unavailable
|
||||
- **Security First**: Credentials via environment variables only
|
||||
|
||||
## Implementation Method
|
||||
|
||||
The skill uses **curl via Bash tool** to fetch Jira data:
|
||||
|
||||
```bash
|
||||
curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
|
||||
"https://resolvesys.atlassian.net/rest/api/3/issue/{issueKey}"
|
||||
```
|
||||
|
||||
**Why curl instead of WebFetch:**
|
||||
- WebFetch doesn't support custom authentication headers
|
||||
- curl can read credentials directly from environment variables
|
||||
- Direct API access with Basic Authentication
|
||||
- Reliable and proven approach
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Fetch an Issue
|
||||
|
||||
**When user mentions issue key:**
|
||||
|
||||
1. Detect issue key pattern `[A-Z]+-\d+`
|
||||
2. Use curl with Bash tool to fetch from Jira API
|
||||
3. Parse JSON response
|
||||
4. Format and display structured summary
|
||||
|
||||
**Example workflow:**
|
||||
```
|
||||
User: "jira PLAT-3213"
|
||||
|
||||
Agent executes:
|
||||
curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
|
||||
"https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-3213"
|
||||
|
||||
Parses response and displays formatted issue details
|
||||
```
|
||||
|
||||
### Automatic Issue Detection
|
||||
|
||||
**Standard workflow:**
|
||||
|
||||
1. User mentions issue key (e.g., "Let's work on PLAT-456")
|
||||
2. Skill detects pattern matching `[A-Z]+-\d+`
|
||||
3. Fetches issue details via curl
|
||||
4. Displays formatted summary
|
||||
5. Proceeds with requested task using context
|
||||
|
||||
### Proactive Inquiry
|
||||
|
||||
**When user describes work without ticket:**
|
||||
|
||||
```
|
||||
User: "I need to implement the login feature"
|
||||
Agent: "Great! Do you have a JIRA ticket number so I can get more context?"
|
||||
User: "PLAT-456"
|
||||
Agent: Fetches and displays issue details via curl
|
||||
```
|
||||
|
||||
## Available Commands
|
||||
|
||||
All Jira capabilities (when using this skill):
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| **Issue Retrieval** | |
|
||||
| `jira {issueKey}` | Fetch and display full issue details |
|
||||
| `jira-epic {epicKey}` | Fetch epic and all child stories/tasks |
|
||||
| `jira-search {jql}` | Search issues using JQL query |
|
||||
| **Workflow Integration** | |
|
||||
| `auto-detect` | Enable/disable automatic issue key detection |
|
||||
|
||||
→ [API Reference](./reference/api-reference.md)
|
||||
|
||||
## Issue Detection Patterns
|
||||
|
||||
The skill automatically detects these patterns:
|
||||
|
||||
- **Primary Project**: `PLAT-123` (from core-config.yaml defaultProject)
|
||||
- **Any Project**: `[A-Z]+-\d+` format (e.g., JIRA-456, DEV-789)
|
||||
- **Multiple Issues**: Detects all issue keys in single message
|
||||
|
||||
## Fetching Issues - Implementation
|
||||
|
||||
### Step 1: Detect Issue Key
|
||||
|
||||
Extract issue key from user message using regex:
|
||||
```regex
|
||||
[A-Z]+-\d+
|
||||
```
|
||||
|
||||
### Step 2: Fetch via curl
|
||||
|
||||
Use Bash tool to execute curl command:
|
||||
|
||||
```bash
|
||||
curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
|
||||
"https://resolvesys.atlassian.net/rest/api/3/issue/{ISSUE_KEY}" \
|
||||
2>&1
|
||||
```
|
||||
|
||||
**Critical points:**
|
||||
- Use `$JIRA_EMAIL` and `$JIRA_TOKEN` environment variables
|
||||
- Use `-u` flag for Basic Authentication
|
||||
- Use `-s` for silent mode (no progress bar)
|
||||
- Redirect stderr with `2>&1` to catch errors
|
||||
|
||||
### Step 3: Parse JSON Response
|
||||
|
||||
Use Python one-liner to extract key fields:
|
||||
|
||||
```bash
|
||||
curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
|
||||
"https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123" | \
|
||||
python -c "
|
||||
import json, sys
|
||||
data = json.load(sys.stdin)
|
||||
fields = data['fields']
|
||||
print('Key:', data['key'])
|
||||
print('Type:', fields['issuetype']['name'])
|
||||
print('Summary:', fields['summary'])
|
||||
print('Status:', fields['status']['name'])
|
||||
print('Assignee:', fields.get('assignee', {}).get('displayName', 'Unassigned'))
|
||||
"
|
||||
```
|
||||
|
||||
### Step 4: Format and Display
|
||||
|
||||
Format the extracted data as structured markdown:
|
||||
|
||||
```markdown
|
||||
## 📋 [{ISSUE_KEY}](https://resolvesys.atlassian.net/browse/{ISSUE_KEY})
|
||||
|
||||
**Type:** {Type} | **Status:** {Status} | **Priority:** {Priority}
|
||||
**Assignee:** {Assignee} | **Reporter:** {Reporter}
|
||||
|
||||
### Description
|
||||
{Description text}
|
||||
|
||||
### Acceptance Criteria
|
||||
{Extracted AC or "Not specified"}
|
||||
|
||||
### Related Issues
|
||||
- Blocks: {list}
|
||||
- Blocked by: {list}
|
||||
- Parent: [{PARENT}](link)
|
||||
|
||||
### Additional Context
|
||||
- Labels: {labels}
|
||||
- Components: {components}
|
||||
- Updated: {date}
|
||||
|
||||
[View in Jira](https://resolvesys.atlassian.net/browse/{ISSUE_KEY})
|
||||
```
|
||||
|
||||
## Extracted Information
|
||||
|
||||
When fetching issues, the skill extracts:
|
||||
|
||||
- **Core Details**: Issue Key, Type (Epic/Story/Bug/Task), Summary, Description
|
||||
- **Status**: Current status, Priority, Resolution
|
||||
- **People**: Assignee, Reporter
|
||||
- **Hierarchy**: Epic Link (for stories), Parent (for subtasks)
|
||||
- **Estimation**: Story Points, Original/Remaining Estimate
|
||||
- **Acceptance Criteria**: From description or custom fields
|
||||
- **Comments**: Last 3 most recent comments with authors
|
||||
- **Links**: Blocks, is blocked by, relates to, duplicates
|
||||
- **Metadata**: Labels, Components, Fix Versions
|
||||
|
||||
→ [Extraction Details](./reference/extraction-format.md)
|
||||
|
||||
## Integration with PRISM Skills
|
||||
|
||||
The Jira skill enhances other PRISM skills:
|
||||
|
||||
### Story Master (sm)
|
||||
- Fetch epic details when decomposing
|
||||
- Retrieve all child stories to avoid duplication
|
||||
- Extract epic acceptance criteria and goals
|
||||
|
||||
### Developer (dev)
|
||||
- Fetch story/bug implementation context
|
||||
- Review technical notes in comments
|
||||
- Check blocking/blocked issues
|
||||
|
||||
### Product Owner (po)
|
||||
- Fetch story details for validation
|
||||
- Check acceptance criteria completeness
|
||||
- Review linked dependencies
|
||||
|
||||
### QA (qa)
|
||||
- Fetch story acceptance criteria
|
||||
- Review test requirements from description
|
||||
- Check linked test issues
|
||||
|
||||
### Support (support)
|
||||
- Fetch bug details and reproduction steps
|
||||
- Check existing comments for customer info
|
||||
- Identify related bugs and patterns
|
||||
|
||||
### Architect (architect)
|
||||
- Fetch epic scope and technical requirements
|
||||
- Review architectural decisions in comments
|
||||
- Check component relationships
|
||||
|
||||
### Peer (peer)
|
||||
- Fetch story context for code review
|
||||
- Verify implementation matches acceptance criteria
|
||||
- Check for architectural alignment
|
||||
|
||||
## Authentication & Security
|
||||
|
||||
**Configuration:**
|
||||
|
||||
Credentials are configured via Windows environment variables:
|
||||
|
||||
```
|
||||
JIRA_EMAIL=your.email@resolve.io
|
||||
JIRA_TOKEN=your-jira-api-token
|
||||
```
|
||||
|
||||
**Core config reference** ([core-config.yaml](../../core-config.yaml)):
|
||||
|
||||
```yaml
|
||||
jira:
|
||||
enabled: true
|
||||
baseUrl: https://resolvesys.atlassian.net
|
||||
email: ${JIRA_EMAIL}
|
||||
token: ${JIRA_TOKEN}
|
||||
defaultProject: PLAT
|
||||
```
|
||||
|
||||
**Security Best Practices:**
|
||||
|
||||
- Credentials read from system environment variables
|
||||
- Never hardcode credentials in code
|
||||
- Basic Authentication via curl `-u` flag
|
||||
- Credentials passed securely to curl
|
||||
|
||||
**Setup:**
|
||||
|
||||
1. Set Windows environment variables (System level):
|
||||
- `JIRA_EMAIL` = your Atlassian email
|
||||
- `JIRA_TOKEN` = your API token
|
||||
2. Generate API token at: https://id.atlassian.com/manage-profile/security/api-tokens
|
||||
3. Restart terminal/IDE after setting variables
|
||||
|
||||
→ [Authentication Reference](./reference/authentication.md)
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Authentication Failed:**
|
||||
```bash
|
||||
# Response: "Client must be authenticated to access this resource."
|
||||
# Action: Verify JIRA_EMAIL and JIRA_TOKEN are set correctly
|
||||
```
|
||||
|
||||
**Issue Not Found (404):**
|
||||
```bash
|
||||
# Response: {"errorMessages":["Issue does not exist or you do not have permission to see it."]}
|
||||
# Action: Verify issue key spelling and user has permission
|
||||
```
|
||||
|
||||
**Network Error:**
|
||||
```bash
|
||||
# Response: curl connection error
|
||||
# Action: Check network connectivity and Jira availability
|
||||
```
|
||||
|
||||
**Graceful Degradation:**
|
||||
- Display error message to user
|
||||
- Offer to proceed without Jira context
|
||||
- Never block workflow on Jira failures
|
||||
|
||||
→ [Error Handling Guide](./reference/error-handling.md)
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Fetching Issues
|
||||
|
||||
✅ **DO:**
|
||||
- Always use environment variables for credentials
|
||||
- Format output in clear, structured markdown
|
||||
- Cache fetched issue data for the conversation session
|
||||
- Include clickable Jira links
|
||||
- Handle missing fields gracefully
|
||||
- Check authentication before attempting fetch
|
||||
|
||||
❌ **DON'T:**
|
||||
- Hardcode credentials in commands
|
||||
- Expose credentials in error messages
|
||||
- Skip error handling
|
||||
- Fetch entire project data at once
|
||||
- Ignore API rate limits
|
||||
|
||||
### Workflow Integration
|
||||
|
||||
✅ **DO:**
|
||||
- Proactively detect issue keys in user messages
|
||||
- Display issue summary before proceeding with task
|
||||
- Use issue context to inform implementation decisions
|
||||
- Reference Jira tickets in commit messages
|
||||
|
||||
❌ **DON'T:**
|
||||
- Skip issue detection to save time
|
||||
- Assume issue data is always current
|
||||
- Modify Jira issues (read-only integration)
|
||||
|
||||
→ [Best Practices Guide](../../shared/reference/best-practices.md#jira-integration)
|
||||
|
||||
## Example Implementation
|
||||
|
||||
### Complete Issue Fetch
|
||||
|
||||
```bash
|
||||
# Step 1: Fetch issue data
|
||||
ISSUE_DATA=$(curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
|
||||
"https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-3213")
|
||||
|
||||
# Step 2: Check for errors
|
||||
if echo "$ISSUE_DATA" | grep -q "errorMessages"; then
|
||||
echo "Error fetching issue"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 3: Extract and format
|
||||
echo "$ISSUE_DATA" | python -c "
|
||||
import json, sys
|
||||
data = json.load(sys.stdin)
|
||||
fields = data['fields']
|
||||
|
||||
print(f\"## 📋 [{data['key']}](https://resolvesys.atlassian.net/browse/{data['key']})\")
|
||||
print(f\"**Type:** {fields['issuetype']['name']} | **Status:** {fields['status']['name']}\")
|
||||
print(f\"**Assignee:** {fields.get('assignee', {}).get('displayName', 'Unassigned')}\")
|
||||
print(f\"\n### Summary\")
|
||||
print(fields['summary'])
|
||||
"
|
||||
```
|
||||
|
||||
## Reference Documentation
|
||||
|
||||
Core references (loaded as needed):
|
||||
|
||||
- **[API Reference](./reference/api-reference.md)** - Jira REST API endpoints and curl usage
|
||||
- **[Extraction Format](./reference/extraction-format.md)** - Issue data formatting and structure
|
||||
- **[Authentication](./reference/authentication.md)** - Security and credential management
|
||||
- **[Error Handling](./reference/error-handling.md)** - Handling API errors gracefully
|
||||
|
||||
Shared references:
|
||||
|
||||
- **[Commands (All Skills)](../../shared/reference/commands.md)** - Complete command reference
|
||||
- **[Dependencies (All Skills)](../../shared/reference/dependencies.md)** - Integration and file structure
|
||||
- **[Examples](../../shared/reference/examples.md)** - Real-world Jira integration workflows
|
||||
- **[Best Practices](../../shared/reference/best-practices.md)** - Security, privacy, and workflow practices
|
||||
|
||||
## Common Questions
|
||||
|
||||
**Q: Why use curl instead of WebFetch?**
|
||||
A: WebFetch doesn't support custom authentication headers needed for Jira API. curl with `-u` flag provides reliable Basic Authentication.
|
||||
|
||||
**Q: Do I need to manually invoke this skill?**
|
||||
A: No! The skill automatically activates when it detects Jira issue keys in conversation.
|
||||
|
||||
**Q: Is this read-only?**
|
||||
A: Yes. This integration only fetches data from Jira, it never creates or modifies issues.
|
||||
|
||||
**Q: What if I don't have credentials configured?**
|
||||
A: The skill gracefully degrades. It will inform you that Jira integration is unavailable and proceed without it.
|
||||
|
||||
**Q: How do I verify credentials are working?**
|
||||
A: Test with: `curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" "https://resolvesys.atlassian.net/rest/api/3/myself"`
|
||||
|
||||
**Q: Can I search for issues using JQL?**
|
||||
A: Yes! Use `jira-search "project = PLAT AND type = Bug"` to search using Jira Query Language.
|
||||
|
||||
## Triggers
|
||||
|
||||
This skill activates when you mention:
|
||||
- Jira issue keys (e.g., "PLAT-123", "JIRA-456")
|
||||
- "jira" command explicitly
|
||||
- "get issue" or "fetch ticket"
|
||||
- "check Jira" or "look up issue"
|
||||
- When other skills need issue context (SM decomposing epic, Dev implementing story)
|
||||
|
||||
---
|
||||
|
||||
**Skill Version**: 1.1.0
|
||||
**Integration Type**: Read-Only (curl + Bash)
|
||||
**Icon**: 🎫
|
||||
**Last Updated**: 2025-11-20
|
||||
**Method**: curl via Bash tool with Basic Authentication
|
||||
417
skills/jira/reference/api-reference.md
Normal file
417
skills/jira/reference/api-reference.md
Normal file
@@ -0,0 +1,417 @@
|
||||
# Jira REST API Reference
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides detailed information about using the Jira REST API v3 for fetching issue context in PRISM workflows.
|
||||
|
||||
## Base Configuration
|
||||
|
||||
From [core-config.yaml](../../../core-config.yaml):
|
||||
|
||||
```yaml
|
||||
jira:
|
||||
enabled: true
|
||||
baseUrl: https://resolvesys.atlassian.net
|
||||
email: ${JIRA_EMAIL}
|
||||
token: ${JIRA_API_TOKEN}
|
||||
defaultProject: PLAT
|
||||
issueKeyPattern: "[A-Z]+-\\d+"
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
All API requests require Basic Authentication:
|
||||
|
||||
```
|
||||
Authorization: Basic base64(email:token)
|
||||
```
|
||||
|
||||
Where:
|
||||
- `email`: Your Atlassian account email (from `JIRA_EMAIL` env var)
|
||||
- `token`: Your Jira API token (from `JIRA_API_TOKEN` env var)
|
||||
|
||||
**Security Notes:**
|
||||
- Never hardcode credentials in code
|
||||
- Never embed credentials in URLs
|
||||
- WebFetch tool handles authentication securely
|
||||
- Credentials are read from environment variables via core-config.yaml
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### 1. Get Issue Details
|
||||
|
||||
**Endpoint:**
|
||||
```
|
||||
GET /rest/api/3/issue/{issueKey}
|
||||
```
|
||||
|
||||
**URL Example:**
|
||||
```
|
||||
https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123
|
||||
```
|
||||
|
||||
**Response Fields:**
|
||||
- `key`: Issue key (e.g., "PLAT-123")
|
||||
- `fields.summary`: Issue title
|
||||
- `fields.description`: Full description (Atlassian Document Format)
|
||||
- `fields.issuetype.name`: Type (Epic, Story, Bug, Task, Subtask)
|
||||
- `fields.status.name`: Current status
|
||||
- `fields.priority.name`: Priority level
|
||||
- `fields.assignee`: Assignee details
|
||||
- `fields.reporter`: Reporter details
|
||||
- `fields.parent`: Parent issue (for Subtasks)
|
||||
- `fields.customfield_xxxxx`: Epic Link (custom field ID varies)
|
||||
- `fields.timetracking`: Original/remaining estimates
|
||||
- `fields.customfield_xxxxx`: Story Points (custom field ID varies)
|
||||
- `fields.comment.comments[]`: Array of comments
|
||||
- `fields.issuelinks[]`: Linked issues
|
||||
- `fields.labels[]`: Labels
|
||||
- `fields.components[]`: Components
|
||||
- `fields.fixVersions[]`: Fix versions
|
||||
|
||||
**Usage with WebFetch:**
|
||||
```
|
||||
WebFetch:
|
||||
url: https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123
|
||||
prompt: |
|
||||
Extract and format the following information from this Jira issue:
|
||||
- Issue Key and Type (Epic/Story/Bug/Task)
|
||||
- Summary and Description
|
||||
- Status and Priority
|
||||
- Assignee and Reporter
|
||||
- Epic Link (if applicable)
|
||||
- Story Points (if applicable)
|
||||
- Acceptance Criteria (from description or custom field)
|
||||
- Comments (last 3 most recent)
|
||||
- Linked Issues (blocks, is blocked by, relates to)
|
||||
- Labels and Components
|
||||
|
||||
Format as a clear, structured summary for development context.
|
||||
```
|
||||
|
||||
### 2. Search Issues (JQL)
|
||||
|
||||
**Endpoint:**
|
||||
```
|
||||
GET /rest/api/3/search?jql={query}
|
||||
```
|
||||
|
||||
**URL Example:**
|
||||
```
|
||||
https://resolvesys.atlassian.net/rest/api/3/search?jql=project=PLAT+AND+type=Epic
|
||||
```
|
||||
|
||||
**Common JQL Queries:**
|
||||
|
||||
**Get all epics in project:**
|
||||
```jql
|
||||
project = PLAT AND type = Epic
|
||||
```
|
||||
|
||||
**Get all child stories of an epic:**
|
||||
```jql
|
||||
parent = PLAT-789
|
||||
```
|
||||
|
||||
**Get all open bugs:**
|
||||
```jql
|
||||
project = PLAT AND type = Bug AND status != Done
|
||||
```
|
||||
|
||||
**Get issues assigned to me:**
|
||||
```jql
|
||||
project = PLAT AND assignee = currentUser()
|
||||
```
|
||||
|
||||
**Get recently updated issues:**
|
||||
```jql
|
||||
project = PLAT AND updated >= -7d
|
||||
```
|
||||
|
||||
**Response Structure:**
|
||||
```json
|
||||
{
|
||||
"total": 25,
|
||||
"maxResults": 50,
|
||||
"startAt": 0,
|
||||
"issues": [
|
||||
{
|
||||
"key": "PLAT-123",
|
||||
"fields": { ... }
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Usage with WebFetch:**
|
||||
```
|
||||
WebFetch:
|
||||
url: https://resolvesys.atlassian.net/rest/api/3/search?jql=parent=PLAT-789
|
||||
prompt: |
|
||||
List all issues returned from this search.
|
||||
For each issue, extract:
|
||||
- Issue Key
|
||||
- Type
|
||||
- Summary
|
||||
- Status
|
||||
- Assignee
|
||||
|
||||
Format as a numbered list.
|
||||
```
|
||||
|
||||
### 3. Get Epic Issues
|
||||
|
||||
**Endpoint:**
|
||||
```
|
||||
GET /rest/api/3/search?jql=parent={epicKey}
|
||||
```
|
||||
|
||||
**URL Example:**
|
||||
```
|
||||
https://resolvesys.atlassian.net/rest/api/3/search?jql=parent=PLAT-789
|
||||
```
|
||||
|
||||
**Purpose:**
|
||||
Retrieves all Stories, Tasks, and Subtasks that belong to a specific Epic.
|
||||
|
||||
**Usage:**
|
||||
Essential for Story Master when decomposing epics to:
|
||||
- See existing child stories
|
||||
- Avoid duplication
|
||||
- Understand epic scope
|
||||
- Identify gaps in decomposition
|
||||
|
||||
**Usage with WebFetch:**
|
||||
```
|
||||
WebFetch:
|
||||
url: https://resolvesys.atlassian.net/rest/api/3/search?jql=parent=PLAT-789
|
||||
prompt: |
|
||||
List all child stories/tasks for this epic.
|
||||
For each, extract:
|
||||
- Issue Key
|
||||
- Summary
|
||||
- Status
|
||||
- Story Points (if available)
|
||||
|
||||
Calculate total story points across all children.
|
||||
```
|
||||
|
||||
### 4. Get Issue Comments
|
||||
|
||||
**Endpoint:**
|
||||
```
|
||||
GET /rest/api/3/issue/{issueKey}/comment
|
||||
```
|
||||
|
||||
**URL Example:**
|
||||
```
|
||||
https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123/comment
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"comments": [
|
||||
{
|
||||
"id": "12345",
|
||||
"author": {
|
||||
"displayName": "John Doe",
|
||||
"emailAddress": "john@example.com"
|
||||
},
|
||||
"body": { ... },
|
||||
"created": "2025-01-15T10:30:00.000+0000",
|
||||
"updated": "2025-01-15T10:30:00.000+0000"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Comments are included in issue details response by default. Use this endpoint only if you need ALL comments (issue details returns recent comments only).
|
||||
|
||||
### 5. Get Issue Transitions
|
||||
|
||||
**Endpoint:**
|
||||
```
|
||||
GET /rest/api/3/issue/{issueKey}/transitions
|
||||
```
|
||||
|
||||
**Note:** This is a read-only integration. We do not modify issues, so transition endpoints are informational only.
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
Jira Cloud enforces rate limits:
|
||||
|
||||
**Limits:**
|
||||
- **Per-user**: 300 requests per minute
|
||||
- **Per-app**: Based on your plan
|
||||
|
||||
**Best Practices:**
|
||||
- Cache issue data for the conversation session
|
||||
- Avoid fetching same issue multiple times
|
||||
- Use search queries to fetch multiple issues in one request
|
||||
- Batch operations when possible
|
||||
|
||||
**Handling Rate Limits:**
|
||||
If you receive 429 (Too Many Requests):
|
||||
```
|
||||
Display: "Jira rate limit reached. Please wait a moment before fetching more issues."
|
||||
Action: Wait and retry, or proceed without additional Jira data
|
||||
```
|
||||
|
||||
## Custom Fields
|
||||
|
||||
Many Jira fields are custom and vary by instance:
|
||||
|
||||
**Common Custom Fields:**
|
||||
- **Epic Link**: `customfield_10014` (varies by instance)
|
||||
- **Story Points**: `customfield_10016` (varies by instance)
|
||||
- **Sprint**: `customfield_10020` (varies by instance)
|
||||
- **Epic Name**: `customfield_10011` (for Epic issues)
|
||||
|
||||
**Finding Custom Field IDs:**
|
||||
1. Fetch any issue and examine the response
|
||||
2. Look for `customfield_*` entries
|
||||
3. Match field names to IDs in your instance
|
||||
|
||||
**Usage Tip:**
|
||||
Use the WebFetch extraction prompt to handle custom fields generically:
|
||||
```
|
||||
Extract story points if available (may be in customfield_10016 or similar)
|
||||
```
|
||||
|
||||
The AI extraction will find the relevant field without hardcoding IDs.
|
||||
|
||||
## Response Formats
|
||||
|
||||
### Atlassian Document Format (ADF)
|
||||
|
||||
Jira descriptions and comments use ADF (JSON structure):
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "doc",
|
||||
"version": 1,
|
||||
"content": [
|
||||
{
|
||||
"type": "paragraph",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "This is the description"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Handling ADF:**
|
||||
Use WebFetch's AI extraction to convert ADF to readable text:
|
||||
```
|
||||
prompt: "Extract the description text from this issue and format as plain markdown"
|
||||
```
|
||||
|
||||
## Error Codes
|
||||
|
||||
**400 Bad Request:**
|
||||
- Invalid JQL syntax
|
||||
- Malformed request
|
||||
|
||||
**401 Unauthorized:**
|
||||
- Missing or invalid credentials
|
||||
- Expired API token
|
||||
|
||||
**403 Forbidden:**
|
||||
- User lacks permission to view issue
|
||||
- Issue is in restricted project
|
||||
|
||||
**404 Not Found:**
|
||||
- Issue key does not exist
|
||||
- Issue was deleted
|
||||
|
||||
**429 Too Many Requests:**
|
||||
- Rate limit exceeded
|
||||
- Wait and retry
|
||||
|
||||
**500 Internal Server Error:**
|
||||
- Jira service issue
|
||||
- Retry or proceed without Jira data
|
||||
|
||||
## Example WebFetch Usage
|
||||
|
||||
### Fetch Single Issue
|
||||
|
||||
```javascript
|
||||
// In Claude Code workflow
|
||||
WebFetch({
|
||||
url: "https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123",
|
||||
prompt: `
|
||||
Extract and format this Jira issue:
|
||||
|
||||
**[PLAT-123]**: {summary}
|
||||
|
||||
**Type**: {type}
|
||||
**Status**: {status}
|
||||
**Priority**: {priority}
|
||||
|
||||
**Description**:
|
||||
{description as markdown}
|
||||
|
||||
**Acceptance Criteria**:
|
||||
{extract AC from description if present}
|
||||
|
||||
**Assignee**: {assignee name}
|
||||
**Reporter**: {reporter name}
|
||||
|
||||
**Linked Issues**:
|
||||
- {list linked issues with relationship type}
|
||||
|
||||
**Comments** (last 3):
|
||||
- {author}: {comment text}
|
||||
`
|
||||
})
|
||||
```
|
||||
|
||||
### Search for Epic Children
|
||||
|
||||
```javascript
|
||||
WebFetch({
|
||||
url: "https://resolvesys.atlassian.net/rest/api/3/search?jql=parent=PLAT-789",
|
||||
prompt: `
|
||||
List all child stories for this epic:
|
||||
|
||||
1. [PLAT-XXX] {summary} - {status} - {story points}
|
||||
2. [PLAT-YYY] {summary} - {status} - {story points}
|
||||
|
||||
Total Story Points: {sum of all story points}
|
||||
Completed: {count of Done stories}
|
||||
In Progress: {count of In Progress stories}
|
||||
Todo: {count of To Do stories}
|
||||
`
|
||||
})
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
**Verify Configuration:**
|
||||
```bash
|
||||
# Check environment variables
|
||||
echo $JIRA_EMAIL
|
||||
echo $JIRA_API_TOKEN
|
||||
|
||||
# Test API connection
|
||||
curl -u $JIRA_EMAIL:$JIRA_API_TOKEN \
|
||||
https://resolvesys.atlassian.net/rest/api/3/myself
|
||||
```
|
||||
|
||||
**Test Issue Fetch:**
|
||||
```bash
|
||||
curl -u $JIRA_EMAIL:$JIRA_API_TOKEN \
|
||||
https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Jira REST API v3 Documentation](https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/)
|
||||
- [JQL (Jira Query Language)](https://support.atlassian.com/jira-service-management-cloud/docs/use-advanced-search-with-jira-query-language-jql/)
|
||||
- [Atlassian Document Format](https://developer.atlassian.com/cloud/jira/platform/apis/document/structure/)
|
||||
385
skills/jira/reference/authentication.md
Normal file
385
skills/jira/reference/authentication.md
Normal file
@@ -0,0 +1,385 @@
|
||||
# Jira Authentication Guide
|
||||
|
||||
## Overview
|
||||
|
||||
The Jira integration uses Basic Authentication with API tokens to securely access Jira Cloud. This document covers setup, security best practices, and troubleshooting.
|
||||
|
||||
## Authentication Method
|
||||
|
||||
**Jira Cloud REST API v3** uses Basic Authentication:
|
||||
|
||||
```
|
||||
Authorization: Basic base64(email:api_token)
|
||||
```
|
||||
|
||||
**NOT** username/password (deprecated and insecure).
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
### Step 1: Generate API Token
|
||||
|
||||
1. Log in to your Atlassian account
|
||||
2. Visit: https://id.atlassian.com/manage-profile/security/api-tokens
|
||||
3. Click **"Create API token"**
|
||||
4. Give it a name (e.g., "PRISM Local Development")
|
||||
5. Copy the generated token (you won't see it again!)
|
||||
|
||||
### Step 2: Configure Environment Variables
|
||||
|
||||
1. Navigate to your project repository root
|
||||
2. Copy the example environment file:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
3. Edit `.env` and add your credentials:
|
||||
```env
|
||||
JIRA_EMAIL=your.email@resolve.io
|
||||
JIRA_API_TOKEN=your_generated_api_token_here
|
||||
```
|
||||
|
||||
4. Verify `.env` is in `.gitignore` (it should be!)
|
||||
|
||||
### Step 3: Verify Configuration
|
||||
|
||||
Test your credentials:
|
||||
|
||||
```bash
|
||||
# Unix/Linux/Mac
|
||||
curl -u $JIRA_EMAIL:$JIRA_API_TOKEN \
|
||||
https://resolvesys.atlassian.net/rest/api/3/myself
|
||||
|
||||
# Windows PowerShell
|
||||
$env:JIRA_EMAIL
|
||||
$env:JIRA_API_TOKEN
|
||||
curl.exe -u "${env:JIRA_EMAIL}:${env:JIRA_API_TOKEN}" `
|
||||
https://resolvesys.atlassian.net/rest/api/3/myself
|
||||
```
|
||||
|
||||
**Expected Response**: JSON with your user details
|
||||
**Error Response**: 401 Unauthorized (check credentials)
|
||||
|
||||
## core-config.yaml Configuration
|
||||
|
||||
The Jira configuration in [core-config.yaml](../../../core-config.yaml):
|
||||
|
||||
```yaml
|
||||
jira:
|
||||
enabled: true
|
||||
baseUrl: https://resolvesys.atlassian.net
|
||||
email: ${JIRA_EMAIL}
|
||||
token: ${JIRA_API_TOKEN}
|
||||
defaultProject: PLAT
|
||||
issueKeyPattern: "[A-Z]+-\\d+"
|
||||
```
|
||||
|
||||
**Field Descriptions**:
|
||||
- `enabled`: Master switch for Jira integration
|
||||
- `baseUrl`: Your Jira Cloud instance URL
|
||||
- `email`: Environment variable reference for email
|
||||
- `token`: Environment variable reference for API token
|
||||
- `defaultProject`: Default project key for issue detection
|
||||
- `issueKeyPattern`: Regex pattern for detecting issue keys
|
||||
|
||||
**Placeholders** (`${VARIABLE}`):
|
||||
- Automatically replaced with environment variable values
|
||||
- Keeps secrets out of version control
|
||||
- Allows per-developer configuration
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### ✅ DO
|
||||
|
||||
**Store Credentials Securely:**
|
||||
- Use environment variables (`JIRA_EMAIL`, `JIRA_API_TOKEN`)
|
||||
- Use `.env` file for local development (gitignored)
|
||||
- Use secure secrets management for production (if applicable)
|
||||
|
||||
**Protect API Tokens:**
|
||||
- Treat API tokens like passwords
|
||||
- Never commit to version control
|
||||
- Rotate tokens periodically (every 90 days recommended)
|
||||
- Use descriptive token names (e.g., "PRISM Dev - John Laptop")
|
||||
- Revoke unused tokens immediately
|
||||
|
||||
**Limit Token Scope:**
|
||||
- Use account with read-only Jira access if possible
|
||||
- Create dedicated "service account" for integrations
|
||||
- Request minimum necessary permissions
|
||||
|
||||
**In Code:**
|
||||
- Never hardcode credentials in source files
|
||||
- Never embed credentials in URLs (`https://user:pass@domain.com`)
|
||||
- Use WebFetch tool which handles auth headers securely
|
||||
- Never log credentials in debug output
|
||||
|
||||
### ❌ DON'T
|
||||
|
||||
**Never:**
|
||||
- Commit `.env` file to git
|
||||
- Hardcode credentials in code
|
||||
- Share API tokens in chat, email, or docs
|
||||
- Use passwords (use API tokens only)
|
||||
- Embed credentials in URLs
|
||||
- Log credentials in debug output
|
||||
- Share credentials between developers (each gets their own)
|
||||
|
||||
**Avoid:**
|
||||
- Using personal accounts for shared integrations
|
||||
- Storing tokens in plaintext outside `.env`
|
||||
- Reusing tokens across multiple projects
|
||||
- Leaving old tokens active after switching machines
|
||||
|
||||
## WebFetch Authentication
|
||||
|
||||
Claude Code's WebFetch tool handles authentication automatically:
|
||||
|
||||
### How It Works
|
||||
|
||||
1. WebFetch reads `core-config.yaml`
|
||||
2. Resolves `${JIRA_EMAIL}` and `${JIRA_API_TOKEN}` from environment
|
||||
3. Constructs `Authorization: Basic base64(email:token)` header
|
||||
4. Includes header in all Jira API requests
|
||||
5. Credentials never exposed in logs or output
|
||||
|
||||
### Usage Example
|
||||
|
||||
```javascript
|
||||
// You don't need to handle auth manually!
|
||||
WebFetch({
|
||||
url: "https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123",
|
||||
prompt: "Extract issue details"
|
||||
})
|
||||
|
||||
// WebFetch automatically:
|
||||
// 1. Reads JIRA_EMAIL and JIRA_API_TOKEN from env
|
||||
// 2. Adds Authorization header
|
||||
// 3. Makes authenticated request
|
||||
```
|
||||
|
||||
### What You Don't Need to Do
|
||||
|
||||
❌ **Don't do this** (WebFetch handles it):
|
||||
```javascript
|
||||
// WRONG - Don't manually construct auth
|
||||
const auth = btoa(`${email}:${token}`);
|
||||
const headers = { Authorization: `Basic ${auth}` };
|
||||
```
|
||||
|
||||
✅ **Do this** (let WebFetch handle it):
|
||||
```javascript
|
||||
// RIGHT - Just provide the URL
|
||||
WebFetch({ url: jiraUrl, prompt: "..." })
|
||||
```
|
||||
|
||||
## Environment Variable Loading
|
||||
|
||||
### Local Development
|
||||
|
||||
**.env File** (in repository root):
|
||||
```env
|
||||
# Jira Integration
|
||||
JIRA_EMAIL=john.doe@resolve.io
|
||||
JIRA_API_TOKEN=ATATT3xFfGF0abc123xyz...
|
||||
|
||||
# Other services
|
||||
GITHUB_TOKEN=ghp_abc123...
|
||||
```
|
||||
|
||||
**Loading Priority**:
|
||||
1. System environment variables (if set)
|
||||
2. `.env` file in current directory
|
||||
3. `.env` file in parent directories (searches up)
|
||||
|
||||
**dotenv Support**:
|
||||
PRISM uses dotenv-style loading. Ensure your environment supports it.
|
||||
|
||||
### CI/CD / Production
|
||||
|
||||
For automated environments:
|
||||
|
||||
**GitHub Actions**:
|
||||
```yaml
|
||||
env:
|
||||
JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
|
||||
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
|
||||
```
|
||||
|
||||
**Docker**:
|
||||
```bash
|
||||
docker run \
|
||||
-e JIRA_EMAIL=$JIRA_EMAIL \
|
||||
-e JIRA_API_TOKEN=$JIRA_API_TOKEN \
|
||||
your-image
|
||||
```
|
||||
|
||||
**AWS/Cloud**:
|
||||
Use secure secrets management (AWS Secrets Manager, etc.)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### 401 Unauthorized
|
||||
|
||||
**Symptoms**:
|
||||
- "Invalid credentials" error
|
||||
- API returns 401 status code
|
||||
|
||||
**Causes**:
|
||||
1. Incorrect email address
|
||||
2. Incorrect or expired API token
|
||||
3. Token revoked in Atlassian account
|
||||
4. Using password instead of API token
|
||||
|
||||
**Solutions**:
|
||||
1. Verify `JIRA_EMAIL` matches your Atlassian account email
|
||||
2. Generate new API token and update `.env`
|
||||
3. Check token is active at https://id.atlassian.com/manage-profile/security/api-tokens
|
||||
4. Ensure using API token, not password
|
||||
|
||||
### 403 Forbidden
|
||||
|
||||
**Symptoms**:
|
||||
- "Access denied" error
|
||||
- API returns 403 status code
|
||||
|
||||
**Causes**:
|
||||
1. Account lacks permission to view issue
|
||||
2. Issue in restricted project
|
||||
3. Account lacks Jira license
|
||||
|
||||
**Solutions**:
|
||||
1. Verify you can view the issue in Jira web UI
|
||||
2. Request access to the project from Jira admin
|
||||
3. Ensure account has Jira Software license
|
||||
|
||||
### Environment Variables Not Found
|
||||
|
||||
**Symptoms**:
|
||||
- `${JIRA_EMAIL}` not replaced in config
|
||||
- Undefined variable errors
|
||||
|
||||
**Causes**:
|
||||
1. `.env` file missing
|
||||
2. `.env` in wrong location
|
||||
3. Environment variables not exported
|
||||
4. Typo in variable names
|
||||
|
||||
**Solutions**:
|
||||
1. Create `.env` file in repository root
|
||||
2. Verify `.env` contains `JIRA_EMAIL=...` and `JIRA_API_TOKEN=...`
|
||||
3. Restart terminal/IDE to reload environment
|
||||
4. Check variable names match exactly (case-sensitive)
|
||||
|
||||
**Test Variables**:
|
||||
```bash
|
||||
# Unix/Linux/Mac
|
||||
echo $JIRA_EMAIL
|
||||
echo $JIRA_API_TOKEN
|
||||
|
||||
# Windows PowerShell
|
||||
echo $env:JIRA_EMAIL
|
||||
echo $env:JIRA_API_TOKEN
|
||||
|
||||
# Windows CMD
|
||||
echo %JIRA_EMAIL%
|
||||
echo %JIRA_API_TOKEN%
|
||||
```
|
||||
|
||||
### Rate Limiting (429)
|
||||
|
||||
**Symptoms**:
|
||||
- "Rate limit exceeded" error
|
||||
- API returns 429 status code
|
||||
|
||||
**Causes**:
|
||||
- Too many requests in short time
|
||||
- Exceeded 300 requests/minute limit
|
||||
|
||||
**Solutions**:
|
||||
- Wait 60 seconds before retrying
|
||||
- Implement session caching to reduce duplicate requests
|
||||
- Batch operations when possible
|
||||
|
||||
## Permissions Required
|
||||
|
||||
**Minimum Jira Permissions**:
|
||||
- **Browse Projects**: View issues in project
|
||||
- **View Issues**: Read issue details
|
||||
- **View Comments**: Read issue comments
|
||||
|
||||
**NOT Required**:
|
||||
- Create/Edit issues (read-only integration)
|
||||
- Assign issues
|
||||
- Transition issues
|
||||
- Admin permissions
|
||||
|
||||
**Recommended Setup**:
|
||||
- Use account with "Jira Software" license
|
||||
- Ensure access to all projects you need to integrate
|
||||
- Consider dedicated "integration" account for team use
|
||||
|
||||
## Token Management
|
||||
|
||||
### Rotation Schedule
|
||||
|
||||
**Recommended**:
|
||||
- Rotate tokens every 90 days
|
||||
- Rotate immediately if:
|
||||
- Token potentially exposed
|
||||
- Developer leaves team
|
||||
- Device lost or stolen
|
||||
|
||||
**Rotation Process**:
|
||||
1. Generate new token in Atlassian
|
||||
2. Update `.env` with new token
|
||||
3. Test integration
|
||||
4. Revoke old token in Atlassian
|
||||
5. Document rotation in team wiki
|
||||
|
||||
### Multiple Tokens
|
||||
|
||||
You can create multiple tokens for different purposes:
|
||||
|
||||
**Example**:
|
||||
- "PRISM Dev - Laptop" (local development)
|
||||
- "PRISM Dev - Desktop" (work machine)
|
||||
- "PRISM CI/CD" (automated testing)
|
||||
|
||||
**Benefits**:
|
||||
- Revoke specific token without affecting others
|
||||
- Identify which integration is making requests
|
||||
- Isolate security incidents
|
||||
|
||||
## Team Collaboration
|
||||
|
||||
### Individual Credentials
|
||||
|
||||
**Each developer should**:
|
||||
1. Generate their own API token
|
||||
2. Configure their own `.env` file
|
||||
3. Never share tokens with teammates
|
||||
|
||||
**Why**:
|
||||
- Audit trail (know who accessed what)
|
||||
- Security (revoke individual access)
|
||||
- Accountability (track API usage per person)
|
||||
|
||||
### Shared Documentation
|
||||
|
||||
**Team wiki should include**:
|
||||
1. Link to this authentication guide
|
||||
2. Link to generate API tokens
|
||||
3. Where to put `.env` file
|
||||
4. Who to contact for access issues
|
||||
5. Jira projects available for integration
|
||||
|
||||
**Do NOT include**:
|
||||
- Actual API tokens
|
||||
- Actual email/password combinations
|
||||
- Shared credentials
|
||||
|
||||
## References
|
||||
|
||||
- [Atlassian API Token Management](https://id.atlassian.com/manage-profile/security/api-tokens)
|
||||
- [Jira Cloud REST API Authentication](https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/#authentication)
|
||||
- [Basic Authentication RFC 7617](https://tools.ietf.org/html/rfc7617)
|
||||
771
skills/jira/reference/error-handling.md
Normal file
771
skills/jira/reference/error-handling.md
Normal file
@@ -0,0 +1,771 @@
|
||||
# Jira Error Handling Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides comprehensive guidance on handling errors when integrating with Jira REST API, including error detection, graceful degradation, and user communication.
|
||||
|
||||
## Error Handling Principles
|
||||
|
||||
### 1. Graceful Degradation
|
||||
|
||||
**Never halt the entire workflow** due to Jira issues:
|
||||
- Inform user of Jira unavailability
|
||||
- Offer to proceed without Jira context
|
||||
- Log error details for troubleshooting
|
||||
- Continue with requested task when possible
|
||||
|
||||
### 2. User-Friendly Messages
|
||||
|
||||
**Avoid technical jargon** in user-facing messages:
|
||||
- ❌ "HTTP 403 Forbidden - Insufficient scopes"
|
||||
- ✅ "Access denied to PLAT-123. Please check Jira permissions."
|
||||
|
||||
### 3. Actionable Guidance
|
||||
|
||||
**Tell users what to do next**:
|
||||
- Verify issue key spelling
|
||||
- Check Jira permissions
|
||||
- Contact Jira admin
|
||||
- Proceed without Jira context
|
||||
- Retry after waiting
|
||||
|
||||
### 4. Privacy & Security
|
||||
|
||||
**Never expose sensitive details**:
|
||||
- Don't show API tokens in error messages
|
||||
- Don't log credentials in debug output
|
||||
- Don't reveal internal system details to users
|
||||
|
||||
## HTTP Status Codes
|
||||
|
||||
### 400 Bad Request
|
||||
|
||||
**Meaning**: Invalid request syntax or parameters
|
||||
|
||||
**Common Causes**:
|
||||
- Invalid JQL syntax in search queries
|
||||
- Malformed JSON in request body (not applicable for read-only)
|
||||
- Invalid issue key format
|
||||
|
||||
**Example Scenarios**:
|
||||
|
||||
**Invalid JQL**:
|
||||
```
|
||||
URL: /rest/api/3/search?jql=invalid syntax here
|
||||
Error: JQL query is invalid
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Invalid search query. Please check your JQL syntax.
|
||||
|
||||
You searched for: "invalid syntax here"
|
||||
|
||||
Common JQL format:
|
||||
- project = PLAT AND type = Bug
|
||||
- assignee = currentUser()
|
||||
- status != Done
|
||||
```
|
||||
|
||||
**Handling Code**:
|
||||
```javascript
|
||||
if (response.status === 400) {
|
||||
displayMessage(`
|
||||
Invalid Jira search query. The JQL syntax may be incorrect.
|
||||
|
||||
Would you like to:
|
||||
1. Try a simpler search
|
||||
2. View JQL examples
|
||||
3. Proceed without searching
|
||||
`);
|
||||
// Offer alternatives, don't halt
|
||||
}
|
||||
```
|
||||
|
||||
### 401 Unauthorized
|
||||
|
||||
**Meaning**: Missing, invalid, or expired credentials
|
||||
|
||||
**Common Causes**:
|
||||
- API token not set in environment
|
||||
- Incorrect email address
|
||||
- Expired or revoked API token
|
||||
- Using password instead of API token
|
||||
|
||||
**Example Scenarios**:
|
||||
|
||||
**Missing Credentials**:
|
||||
```
|
||||
Error: JIRA_EMAIL or JIRA_API_TOKEN not found in environment
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Jira integration not configured.
|
||||
|
||||
To enable Jira integration:
|
||||
1. Generate API token: https://id.atlassian.com/manage-profile/security/api-tokens
|
||||
2. Add to .env file:
|
||||
```
|
||||
JIRA_EMAIL=your.email@resolve.io
|
||||
JIRA_API_TOKEN=your_token_here
|
||||
```
|
||||
3. Restart your terminal/IDE
|
||||
|
||||
For now, I'll proceed without Jira context.
|
||||
```
|
||||
|
||||
**Invalid Credentials**:
|
||||
```
|
||||
Error: HTTP 401 from Jira API
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Jira authentication failed. Your credentials may be incorrect or expired.
|
||||
|
||||
Please verify:
|
||||
- JIRA_EMAIL matches your Atlassian account email
|
||||
- JIRA_API_TOKEN is a valid, active API token
|
||||
- Token hasn't been revoked
|
||||
|
||||
Generate new token: https://id.atlassian.com/manage-profile/security/api-tokens
|
||||
|
||||
Proceeding without Jira context for now.
|
||||
```
|
||||
|
||||
**Handling Code**:
|
||||
```javascript
|
||||
if (response.status === 401) {
|
||||
// Check if credentials are configured at all
|
||||
if (!hasJiraCredentials()) {
|
||||
displayMessage("Jira integration not configured. See setup instructions.");
|
||||
} else {
|
||||
displayMessage("Jira authentication failed. Please verify your credentials.");
|
||||
}
|
||||
|
||||
// Continue workflow without Jira
|
||||
return null; // Indicate no Jira data available
|
||||
}
|
||||
```
|
||||
|
||||
### 403 Forbidden
|
||||
|
||||
**Meaning**: Authenticated but lacks permission
|
||||
|
||||
**Common Causes**:
|
||||
- User lacks permission to view issue
|
||||
- Issue in restricted project
|
||||
- User lacks Jira license
|
||||
- Project permissions changed
|
||||
|
||||
**Example Scenarios**:
|
||||
|
||||
**Issue in Restricted Project**:
|
||||
```
|
||||
Error: You do not have permission to view this issue
|
||||
Issue: PLAT-123
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Access denied to [PLAT-123](https://resolvesys.atlassian.net/browse/PLAT-123).
|
||||
|
||||
This could mean:
|
||||
- The issue is in a restricted project
|
||||
- You don't have permission to view this issue
|
||||
- The project permissions recently changed
|
||||
|
||||
Please:
|
||||
- Verify you can access the issue in Jira web UI
|
||||
- Request access from your Jira administrator
|
||||
- Double-check the issue key
|
||||
|
||||
Would you like to proceed without this issue's context?
|
||||
```
|
||||
|
||||
**Handling Code**:
|
||||
```javascript
|
||||
if (response.status === 403) {
|
||||
displayMessage(`
|
||||
Access denied to ${issueKey}.
|
||||
|
||||
You may not have permission to view this issue.
|
||||
You can still view it in Jira web UI if accessible:
|
||||
${jiraUrl}/browse/${issueKey}
|
||||
|
||||
Proceed without Jira context? (y/n)
|
||||
`);
|
||||
|
||||
// Wait for user decision
|
||||
// Continue without Jira or halt if user requests
|
||||
}
|
||||
```
|
||||
|
||||
### 404 Not Found
|
||||
|
||||
**Meaning**: Issue does not exist
|
||||
|
||||
**Common Causes**:
|
||||
- Typo in issue key
|
||||
- Issue was deleted
|
||||
- Issue moved to different project (key changed)
|
||||
- Wrong Jira instance
|
||||
|
||||
**Example Scenarios**:
|
||||
|
||||
**Non-Existent Issue**:
|
||||
```
|
||||
Error: Issue does not exist
|
||||
Issue: PLAT-9999
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Could not find Jira issue [PLAT-9999](https://resolvesys.atlassian.net/browse/PLAT-9999).
|
||||
|
||||
Possible reasons:
|
||||
- Typo in issue key (check spelling and number)
|
||||
- Issue was deleted or moved
|
||||
- Issue is in a different project
|
||||
|
||||
Would you like to:
|
||||
1. Search for similar issues
|
||||
2. Verify the issue key
|
||||
3. Proceed without Jira context
|
||||
```
|
||||
|
||||
**Typo Detection**:
|
||||
```javascript
|
||||
if (response.status === 404) {
|
||||
// Suggest likely corrections
|
||||
const suggestions = findSimilarIssueKeys(issueKey);
|
||||
|
||||
displayMessage(`
|
||||
Issue ${issueKey} not found.
|
||||
|
||||
Did you mean:
|
||||
${suggestions.map(s => `- ${s}`).join('\n')}
|
||||
|
||||
Or proceed without Jira context?
|
||||
`);
|
||||
}
|
||||
```
|
||||
|
||||
### 429 Too Many Requests
|
||||
|
||||
**Meaning**: Rate limit exceeded
|
||||
|
||||
**Common Causes**:
|
||||
- Exceeded 300 requests per minute (per user)
|
||||
- Multiple rapid fetches in short time
|
||||
- Shared API token hitting combined limits
|
||||
|
||||
**Example Scenarios**:
|
||||
|
||||
**Rate Limit Hit**:
|
||||
```
|
||||
Error: Rate limit exceeded
|
||||
Retry-After: 60 seconds
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
⏱️ Jira rate limit reached. Please wait a moment.
|
||||
|
||||
Jira Cloud limits requests to 300 per minute per user.
|
||||
|
||||
I'll automatically retry in 60 seconds, or you can:
|
||||
- Wait and try again manually
|
||||
- Proceed without fetching additional Jira issues
|
||||
- Use cached issue data if available
|
||||
```
|
||||
|
||||
**Handling Code**:
|
||||
```javascript
|
||||
if (response.status === 429) {
|
||||
const retryAfter = response.headers['Retry-After'] || 60;
|
||||
|
||||
displayMessage(`
|
||||
Jira rate limit exceeded.
|
||||
Waiting ${retryAfter} seconds before retry...
|
||||
`);
|
||||
|
||||
// Implement exponential backoff
|
||||
await sleep(retryAfter * 1000);
|
||||
|
||||
// Retry request
|
||||
return retryRequest(url, maxRetries - 1);
|
||||
}
|
||||
```
|
||||
|
||||
**Prevention**:
|
||||
- Cache fetched issues for conversation session
|
||||
- Batch operations when possible
|
||||
- Avoid fetching same issue multiple times
|
||||
- Use search queries to fetch multiple issues at once
|
||||
|
||||
### 500 Internal Server Error
|
||||
|
||||
**Meaning**: Jira service error
|
||||
|
||||
**Common Causes**:
|
||||
- Jira service temporarily down
|
||||
- Database issues on Jira side
|
||||
- Unexpected server error
|
||||
- Maintenance window
|
||||
|
||||
**Example Scenarios**:
|
||||
|
||||
**Service Outage**:
|
||||
```
|
||||
Error: HTTP 500 Internal Server Error
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
⚠️ Jira service error. The Jira server may be temporarily unavailable.
|
||||
|
||||
This is typically a temporary issue on Jira's side.
|
||||
|
||||
You can:
|
||||
- Check Jira status: https://status.atlassian.com/
|
||||
- Retry in a few minutes
|
||||
- Proceed without Jira context for now
|
||||
|
||||
I'll continue with your request using available information.
|
||||
```
|
||||
|
||||
**Handling Code**:
|
||||
```javascript
|
||||
if (response.status >= 500) {
|
||||
displayMessage(`
|
||||
Jira service is temporarily unavailable.
|
||||
Check status: https://status.atlassian.com/
|
||||
|
||||
Proceeding without Jira context.
|
||||
`);
|
||||
|
||||
// Log error for troubleshooting
|
||||
logError('Jira 500 error', { issueKey, timestamp: new Date() });
|
||||
|
||||
// Continue workflow without Jira
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
### 502/503/504 Gateway/Service Errors
|
||||
|
||||
**Meaning**: Jira proxy or gateway issues
|
||||
|
||||
**Common Causes**:
|
||||
- Network connectivity issues
|
||||
- Jira proxy/gateway timeout
|
||||
- Temporary service degradation
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
⚠️ Unable to reach Jira. Network or service issue detected.
|
||||
|
||||
This is usually temporary. You can:
|
||||
- Retry in a few moments
|
||||
- Check your network connection
|
||||
- Check Jira status: https://status.atlassian.com/
|
||||
- Proceed without Jira context
|
||||
|
||||
Continuing with available information...
|
||||
```
|
||||
|
||||
## Network Errors
|
||||
|
||||
### Connection Timeout
|
||||
|
||||
**Meaning**: Request took too long to complete
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
⏱️ Jira request timed out. The service may be slow or unreachable.
|
||||
|
||||
You can:
|
||||
- Retry the request
|
||||
- Check your network connection
|
||||
- Proceed without Jira context
|
||||
|
||||
Continuing without Jira data...
|
||||
```
|
||||
|
||||
**Handling Code**:
|
||||
```javascript
|
||||
try {
|
||||
const response = await fetchWithTimeout(url, 30000); // 30s timeout
|
||||
} catch (error) {
|
||||
if (error.name === 'TimeoutError') {
|
||||
displayMessage('Jira request timed out. Proceeding without Jira context.');
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
```
|
||||
|
||||
### Connection Refused
|
||||
|
||||
**Meaning**: Cannot connect to Jira server
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Cannot connect to Jira. Network issue detected.
|
||||
|
||||
Please check:
|
||||
- Your internet connection
|
||||
- VPN connection (if required)
|
||||
- Firewall settings
|
||||
- Jira base URL in core-config.yaml
|
||||
|
||||
Proceeding without Jira integration.
|
||||
```
|
||||
|
||||
### DNS Resolution Failed
|
||||
|
||||
**Meaning**: Cannot resolve Jira hostname
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Cannot resolve Jira hostname.
|
||||
|
||||
Please verify:
|
||||
- Jira base URL in core-config.yaml: https://resolvesys.atlassian.net
|
||||
- DNS settings
|
||||
- Network connectivity
|
||||
|
||||
Proceeding without Jira context.
|
||||
```
|
||||
|
||||
## Configuration Errors
|
||||
|
||||
### Missing Configuration
|
||||
|
||||
**Scenario**: Jira not configured in core-config.yaml
|
||||
|
||||
**Detection**:
|
||||
```javascript
|
||||
if (!config.jira || !config.jira.enabled) {
|
||||
// Jira integration disabled or not configured
|
||||
}
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
ℹ️ Jira integration is not enabled.
|
||||
|
||||
To enable:
|
||||
1. Set `jira.enabled: true` in core-config.yaml
|
||||
2. Configure JIRA_EMAIL and JIRA_API_TOKEN in .env
|
||||
3. See: .prism/skills/jira/reference/authentication.md
|
||||
|
||||
Proceeding without Jira integration.
|
||||
```
|
||||
|
||||
### Invalid Base URL
|
||||
|
||||
**Scenario**: Malformed Jira base URL
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Invalid Jira base URL in configuration.
|
||||
|
||||
Current: {current_url}
|
||||
Expected format: https://your-domain.atlassian.net
|
||||
|
||||
Please correct in core-config.yaml.
|
||||
```
|
||||
|
||||
### Missing Environment Variables
|
||||
|
||||
**Scenario**: JIRA_EMAIL or JIRA_API_TOKEN not set
|
||||
|
||||
**Detection**:
|
||||
```javascript
|
||||
if (!process.env.JIRA_EMAIL || !process.env.JIRA_API_TOKEN) {
|
||||
// Credentials not configured
|
||||
}
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Jira credentials not configured.
|
||||
|
||||
Required environment variables:
|
||||
- JIRA_EMAIL
|
||||
- JIRA_API_TOKEN
|
||||
|
||||
Setup instructions: .prism/skills/jira/reference/authentication.md
|
||||
|
||||
Proceeding without Jira integration.
|
||||
```
|
||||
|
||||
## Issue-Specific Errors
|
||||
|
||||
### Invalid Issue Key Format
|
||||
|
||||
**Scenario**: Issue key doesn't match expected pattern
|
||||
|
||||
**Detection**:
|
||||
```javascript
|
||||
const issueKeyPattern = /^[A-Z]+-\d+$/;
|
||||
if (!issueKeyPattern.test(issueKey)) {
|
||||
// Invalid format
|
||||
}
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
❌ Invalid issue key format: "{issueKey}"
|
||||
|
||||
Jira issue keys follow this pattern:
|
||||
- PROJECT-123
|
||||
- ABC-456
|
||||
- PLAT-789
|
||||
|
||||
Format: {PROJECT_KEY}-{NUMBER}
|
||||
All letters uppercase, hyphen, then numbers.
|
||||
```
|
||||
|
||||
### Custom Field Not Found
|
||||
|
||||
**Scenario**: Expected custom field missing from issue
|
||||
|
||||
**Handling**:
|
||||
```javascript
|
||||
const storyPoints = issue.fields.customfield_10016 ||
|
||||
issue.fields.storyPoints ||
|
||||
null;
|
||||
|
||||
if (!storyPoints) {
|
||||
// Handle gracefully - don't error, just note missing
|
||||
displayField('Story Points', 'Not set');
|
||||
}
|
||||
```
|
||||
|
||||
**User Message**:
|
||||
```markdown
|
||||
## [PLAT-123] Story Title
|
||||
|
||||
...
|
||||
- **Story Points**: Not set
|
||||
...
|
||||
```
|
||||
|
||||
## Error Recovery Strategies
|
||||
|
||||
### 1. Retry with Exponential Backoff
|
||||
|
||||
For transient errors (429, 500, 503):
|
||||
|
||||
```javascript
|
||||
async function fetchWithRetry(url, maxRetries = 3) {
|
||||
for (let i = 0; i < maxRetries; i++) {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
|
||||
if (response.ok) {
|
||||
return response;
|
||||
}
|
||||
|
||||
// Retry on 429, 500, 503
|
||||
if ([429, 500, 503].includes(response.status)) {
|
||||
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
|
||||
await sleep(delay);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't retry on 401, 403, 404
|
||||
return response;
|
||||
|
||||
} catch (error) {
|
||||
if (i === maxRetries - 1) throw error;
|
||||
await sleep(Math.pow(2, i) * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Fallback to Cached Data
|
||||
|
||||
If fresh fetch fails, use cached data:
|
||||
|
||||
```javascript
|
||||
try {
|
||||
const freshData = await fetchIssue(issueKey);
|
||||
cacheIssue(issueKey, freshData);
|
||||
return freshData;
|
||||
} catch (error) {
|
||||
const cached = getCachedIssue(issueKey);
|
||||
if (cached) {
|
||||
displayMessage('⚠️ Using cached issue data (Jira temporarily unavailable)');
|
||||
return cached;
|
||||
}
|
||||
// No cached data, proceed without Jira
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Partial Success
|
||||
|
||||
For batch operations, handle individual failures:
|
||||
|
||||
```javascript
|
||||
async function fetchMultipleIssues(issueKeys) {
|
||||
const results = [];
|
||||
const failed = [];
|
||||
|
||||
for (const key of issueKeys) {
|
||||
try {
|
||||
const issue = await fetchIssue(key);
|
||||
results.push(issue);
|
||||
} catch (error) {
|
||||
failed.push({ key, error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
if (failed.length > 0) {
|
||||
displayMessage(`
|
||||
⚠️ Failed to fetch ${failed.length} issues:
|
||||
${failed.map(f => `- ${f.key}: ${f.error}`).join('\n')}
|
||||
|
||||
Continuing with ${results.length} successfully fetched issues.
|
||||
`);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Degrade Feature
|
||||
|
||||
If Jira unavailable, continue with reduced functionality:
|
||||
|
||||
```javascript
|
||||
if (!jiraAvailable) {
|
||||
displayMessage(`
|
||||
ℹ️ Jira integration unavailable. Continuing with limited context.
|
||||
|
||||
Please provide issue details manually if needed:
|
||||
- Summary
|
||||
- Acceptance Criteria
|
||||
- Technical requirements
|
||||
`);
|
||||
|
||||
// Continue workflow, prompt user for manual input
|
||||
return promptForManualIssueDetails();
|
||||
}
|
||||
```
|
||||
|
||||
## Logging & Debugging
|
||||
|
||||
### User-Facing Messages
|
||||
|
||||
**Keep concise and actionable**:
|
||||
```markdown
|
||||
✅ Good: "Access denied to PLAT-123. Please check permissions."
|
||||
❌ Bad: "HTTPError: 403 Forbidden - insufficient_scope - user lacks jira.issue.read"
|
||||
```
|
||||
|
||||
### Debug Logging
|
||||
|
||||
**Log details for troubleshooting** (not shown to user):
|
||||
|
||||
```javascript
|
||||
function logJiraError(error, context) {
|
||||
console.error('[Jira Integration Error]', {
|
||||
timestamp: new Date().toISOString(),
|
||||
issueKey: context.issueKey,
|
||||
url: context.url,
|
||||
status: error.status,
|
||||
message: error.message,
|
||||
// Never log credentials!
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Error Telemetry
|
||||
|
||||
**Track error patterns** for improvement:
|
||||
|
||||
```javascript
|
||||
function trackJiraError(errorType) {
|
||||
// Increment error counter
|
||||
// Store in session metrics
|
||||
// Help identify systemic issues
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Error Scenarios
|
||||
|
||||
### Manual Testing
|
||||
|
||||
Test each error condition:
|
||||
|
||||
```bash
|
||||
# 401 - Invalid credentials
|
||||
JIRA_EMAIL=wrong@email.com JIRA_API_TOKEN=invalid jira PLAT-123
|
||||
|
||||
# 403 - Access denied (use issue you don't have access to)
|
||||
jira RESTRICTED-999
|
||||
|
||||
# 404 - Not found
|
||||
jira PLAT-99999999
|
||||
|
||||
# Invalid format
|
||||
jira plat-123
|
||||
jira PLAT123
|
||||
jira 123
|
||||
```
|
||||
|
||||
### Automated Testing
|
||||
|
||||
Mock error responses:
|
||||
|
||||
```javascript
|
||||
describe('Jira Error Handling', () => {
|
||||
test('401 shows auth help message', async () => {
|
||||
mockFetch.mockResolvedValue({ status: 401 });
|
||||
const result = await fetchIssue('PLAT-123');
|
||||
expect(result).toBeNull();
|
||||
expect(displayedMessage).toContain('authentication failed');
|
||||
});
|
||||
|
||||
test('404 offers to search', async () => {
|
||||
mockFetch.mockResolvedValue({ status: 404 });
|
||||
await fetchIssue('PLAT-999');
|
||||
expect(displayedMessage).toContain('search for similar issues');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Best Practices Summary
|
||||
|
||||
### ✅ DO
|
||||
|
||||
- Provide clear, actionable error messages
|
||||
- Degrade gracefully (never halt entire workflow)
|
||||
- Offer alternatives (search, manual input, proceed without)
|
||||
- Cache data to reduce API calls and handle failures
|
||||
- Log errors for debugging (without exposing credentials)
|
||||
- Retry transient errors with exponential backoff
|
||||
- Respect rate limits
|
||||
|
||||
### ❌ DON'T
|
||||
|
||||
- Expose API tokens or credentials in errors
|
||||
- Show technical jargon to users
|
||||
- Halt workflow on Jira errors
|
||||
- Retry non-transient errors (401, 403, 404)
|
||||
- Ignore errors silently
|
||||
- Spam API with rapid retries
|
||||
- Assume Jira is always available
|
||||
|
||||
## References
|
||||
|
||||
- [Jira REST API Errors](https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/#error-responses)
|
||||
- [HTTP Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
|
||||
- [Atlassian Status Page](https://status.atlassian.com/)
|
||||
448
skills/jira/reference/extraction-format.md
Normal file
448
skills/jira/reference/extraction-format.md
Normal file
@@ -0,0 +1,448 @@
|
||||
# Issue Extraction Format
|
||||
|
||||
## Overview
|
||||
|
||||
This document defines the standard format for extracting and presenting Jira issue data in PRISM workflows.
|
||||
|
||||
## Standard Issue Summary Format
|
||||
|
||||
When fetching any Jira issue, use this consistent format:
|
||||
|
||||
```markdown
|
||||
## [{ISSUE-KEY}] {Summary}
|
||||
|
||||
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/{ISSUE-KEY})
|
||||
|
||||
### Details
|
||||
- **Type**: {Epic|Story|Bug|Task|Subtask}
|
||||
- **Status**: {Status Name}
|
||||
- **Priority**: {Priority Level}
|
||||
- **Assignee**: {Assignee Name or "Unassigned"}
|
||||
- **Reporter**: {Reporter Name}
|
||||
|
||||
### Description
|
||||
{Description text formatted as markdown}
|
||||
|
||||
### Acceptance Criteria
|
||||
{Extracted AC from description or custom field, formatted as checklist}
|
||||
- [ ] Criterion 1
|
||||
- [ ] Criterion 2
|
||||
- [ ] Criterion 3
|
||||
|
||||
### Estimation
|
||||
- **Story Points**: {Points or "Not estimated"}
|
||||
- **Original Estimate**: {Hours or "Not set"}
|
||||
- **Remaining**: {Hours or "Not set"}
|
||||
|
||||
### Linked Issues
|
||||
- **Blocks**: [{KEY}] {Summary}
|
||||
- **Is Blocked By**: [{KEY}] {Summary}
|
||||
- **Relates To**: [{KEY}] {Summary}
|
||||
- **Duplicates**: [{KEY}] {Summary}
|
||||
|
||||
### Components & Labels
|
||||
- **Components**: {Component list or "None"}
|
||||
- **Labels**: {Label list or "None"}
|
||||
- **Fix Versions**: {Version list or "None"}
|
||||
|
||||
### Recent Comments (Last 3)
|
||||
1. **{Author}** ({Date}):
|
||||
{Comment text}
|
||||
|
||||
2. **{Author}** ({Date}):
|
||||
{Comment text}
|
||||
|
||||
3. **{Author}** ({Date}):
|
||||
{Comment text}
|
||||
```
|
||||
|
||||
## Epic-Specific Format
|
||||
|
||||
When fetching an Epic, include additional hierarchy information:
|
||||
|
||||
```markdown
|
||||
## [EPIC-KEY] {Epic Name}
|
||||
|
||||
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/EPIC-KEY)
|
||||
|
||||
### Epic Overview
|
||||
- **Type**: Epic
|
||||
- **Status**: {Status}
|
||||
- **Epic Name**: {Epic custom field name}
|
||||
- **Total Child Stories**: {Count}
|
||||
- **Total Story Points**: {Sum of child story points}
|
||||
|
||||
### Epic Goal
|
||||
{Epic description/goal}
|
||||
|
||||
### Acceptance Criteria
|
||||
{Epic-level acceptance criteria}
|
||||
|
||||
### Child Stories
|
||||
1. [[STORY-1]] {Summary} - {Status} - {Story Points} SP
|
||||
2. [[STORY-2]] {Summary} - {Status} - {Story Points} SP
|
||||
3. [[STORY-3]] {Summary} - {Status} - {Story Points} SP
|
||||
|
||||
**Progress**:
|
||||
- ✅ Done: {count} ({percentage}%)
|
||||
- 🔄 In Progress: {count}
|
||||
- 📋 To Do: {count}
|
||||
|
||||
### Epic Dependencies
|
||||
{Linked issues that block or are blocked by this epic}
|
||||
|
||||
### Components & Scope
|
||||
- **Components**: {List}
|
||||
- **Fix Version**: {Target release}
|
||||
```
|
||||
|
||||
## Story-Specific Format
|
||||
|
||||
When fetching a Story:
|
||||
|
||||
```markdown
|
||||
## [STORY-KEY] {Story Title}
|
||||
|
||||
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/STORY-KEY)
|
||||
|
||||
### Story Details
|
||||
- **Type**: Story
|
||||
- **Epic**: [[EPIC-KEY]] {Epic Name}
|
||||
- **Status**: {Status}
|
||||
- **Priority**: {Priority}
|
||||
- **Assignee**: {Assignee}
|
||||
- **Story Points**: {Points} SP
|
||||
|
||||
### User Story
|
||||
{As a [user], I want [feature] so that [benefit]}
|
||||
|
||||
### Acceptance Criteria
|
||||
- [ ] {Criterion 1}
|
||||
- [ ] {Criterion 2}
|
||||
- [ ] {Criterion 3}
|
||||
|
||||
### Technical Notes
|
||||
{Extracted from description or comments}
|
||||
|
||||
### Subtasks
|
||||
- [[SUBTASK-1]] {Summary} - {Status}
|
||||
- [[SUBTASK-2]] {Summary} - {Status}
|
||||
|
||||
### Implementation Dependencies
|
||||
- **Blocks**: {List}
|
||||
- **Is Blocked By**: {List}
|
||||
- **Related Stories**: {List}
|
||||
|
||||
### Development Context
|
||||
{Any relevant technical comments, implementation notes, or decisions}
|
||||
```
|
||||
|
||||
## Bug-Specific Format
|
||||
|
||||
When fetching a Bug:
|
||||
|
||||
```markdown
|
||||
## [BUG-KEY] {Bug Summary}
|
||||
|
||||
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/BUG-KEY)
|
||||
|
||||
### Bug Details
|
||||
- **Type**: Bug
|
||||
- **Severity**: {Priority}
|
||||
- **Status**: {Status}
|
||||
- **Assignee**: {Assignee}
|
||||
- **Reporter**: {Reporter}
|
||||
- **Environment**: {Affected environment}
|
||||
|
||||
### Description
|
||||
{Bug description}
|
||||
|
||||
### Steps to Reproduce
|
||||
1. {Step 1}
|
||||
2. {Step 2}
|
||||
3. {Step 3}
|
||||
|
||||
### Expected Behavior
|
||||
{What should happen}
|
||||
|
||||
### Actual Behavior
|
||||
{What actually happens}
|
||||
|
||||
### Screenshots/Logs
|
||||
{Reference to attachments or inline log snippets}
|
||||
|
||||
### Related Issues
|
||||
- **Duplicates**: {Similar bugs}
|
||||
- **Related Bugs**: {Potentially related issues}
|
||||
|
||||
### Customer Impact
|
||||
{Extracted from comments or description}
|
||||
|
||||
### Investigation Notes
|
||||
{Recent comments from developers}
|
||||
```
|
||||
|
||||
## Extraction Prompt Templates
|
||||
|
||||
### General Issue Extraction
|
||||
|
||||
```
|
||||
Extract and format the following information from this Jira issue:
|
||||
|
||||
- Issue Key and Type (Epic/Story/Bug/Task)
|
||||
- Summary and Description
|
||||
- Status and Priority
|
||||
- Assignee and Reporter
|
||||
- Epic Link (if applicable)
|
||||
- Story Points (if applicable)
|
||||
- Acceptance Criteria (from description or custom field)
|
||||
- Comments (last 3 most recent)
|
||||
- Linked Issues (blocks, is blocked by, relates to)
|
||||
- Labels and Components
|
||||
|
||||
Format as a clear, structured markdown summary for development context.
|
||||
```
|
||||
|
||||
### Epic with Children Extraction
|
||||
|
||||
```
|
||||
Extract and format this Epic with all child stories:
|
||||
|
||||
**Epic Details**:
|
||||
- Key, Name, Status
|
||||
- Description and Goal
|
||||
- Acceptance Criteria
|
||||
|
||||
**Child Stories**:
|
||||
- List all child issues with key, summary, status, story points
|
||||
- Calculate total story points
|
||||
- Show completion progress (Done/In Progress/To Do)
|
||||
|
||||
**Dependencies**:
|
||||
- Linked issues that affect this epic
|
||||
|
||||
Format as structured markdown with progress metrics.
|
||||
```
|
||||
|
||||
### Story for Development Extraction
|
||||
|
||||
```
|
||||
Extract and format this Story for implementation:
|
||||
|
||||
**Story Overview**:
|
||||
- Key, Title, Epic Link
|
||||
- Status, Priority, Assignee
|
||||
|
||||
**Requirements**:
|
||||
- User story (As a... I want... So that...)
|
||||
- Acceptance Criteria (as checklist)
|
||||
|
||||
**Technical Context**:
|
||||
- Technical notes from description
|
||||
- Implementation comments
|
||||
- Blocked by / Blocking issues
|
||||
|
||||
**Subtasks**:
|
||||
- List all subtasks with status
|
||||
|
||||
Format clearly for developer to start implementation.
|
||||
```
|
||||
|
||||
### Bug Investigation Extraction
|
||||
|
||||
```
|
||||
Extract and format this Bug for investigation:
|
||||
|
||||
**Bug Summary**:
|
||||
- Key, Title, Severity, Status
|
||||
|
||||
**Reproduction**:
|
||||
- Steps to reproduce
|
||||
- Expected vs Actual behavior
|
||||
|
||||
**Customer Impact**:
|
||||
- Who reported it
|
||||
- How many affected
|
||||
- Business impact
|
||||
|
||||
**Investigation**:
|
||||
- Recent comments from team
|
||||
- Related bugs or patterns
|
||||
|
||||
**Environment**:
|
||||
- Where it occurs
|
||||
- Version information
|
||||
|
||||
Format for support/developer to investigate.
|
||||
```
|
||||
|
||||
## Field Mapping
|
||||
|
||||
### Standard Jira Fields to Display Names
|
||||
|
||||
| Jira API Field | Display Name |
|
||||
|----------------|--------------|
|
||||
| `fields.issuetype.name` | Type |
|
||||
| `fields.status.name` | Status |
|
||||
| `fields.priority.name` | Priority |
|
||||
| `fields.assignee.displayName` | Assignee |
|
||||
| `fields.reporter.displayName` | Reporter |
|
||||
| `fields.summary` | Title/Summary |
|
||||
| `fields.description` | Description |
|
||||
| `fields.parent.key` | Parent Issue |
|
||||
| `fields.comment.comments` | Comments |
|
||||
| `fields.issuelinks` | Linked Issues |
|
||||
| `fields.labels` | Labels |
|
||||
| `fields.components` | Components |
|
||||
| `fields.fixVersions` | Fix Versions |
|
||||
| `fields.timetracking.originalEstimate` | Original Estimate |
|
||||
| `fields.timetracking.remainingEstimate` | Remaining Estimate |
|
||||
|
||||
### Custom Fields (Instance-Specific)
|
||||
|
||||
| Custom Field | Typical ID | Display Name |
|
||||
|--------------|------------|--------------|
|
||||
| Epic Link | `customfield_10014` | Epic |
|
||||
| Story Points | `customfield_10016` | Story Points |
|
||||
| Sprint | `customfield_10020` | Sprint |
|
||||
| Epic Name | `customfield_10011` | Epic Name |
|
||||
| Acceptance Criteria | `customfield_xxxxx` | Acceptance Criteria |
|
||||
|
||||
**Note**: Custom field IDs vary by Jira instance. Use AI extraction to find relevant fields generically.
|
||||
|
||||
## Acceptance Criteria Extraction
|
||||
|
||||
Acceptance Criteria can appear in multiple places:
|
||||
|
||||
### From Description
|
||||
|
||||
Look for markers in description text:
|
||||
- "Acceptance Criteria:"
|
||||
- "AC:"
|
||||
- "Success Criteria:"
|
||||
- Lists that follow these markers
|
||||
|
||||
### From Custom Field
|
||||
|
||||
Some instances have dedicated AC custom field:
|
||||
- `customfield_xxxxx` (varies by instance)
|
||||
- Usually contains structured list
|
||||
|
||||
### Extraction Strategy
|
||||
|
||||
```
|
||||
1. Check for dedicated AC custom field first
|
||||
2. If not found, scan description for AC markers
|
||||
3. Extract list items following markers
|
||||
4. Format as checklist:
|
||||
- [ ] Criterion 1
|
||||
- [ ] Criterion 2
|
||||
5. If no explicit AC found, note: "No explicit acceptance criteria defined"
|
||||
```
|
||||
|
||||
## Handling Missing Data
|
||||
|
||||
Not all issues have all fields. Handle gracefully:
|
||||
|
||||
```markdown
|
||||
### Field Display Rules
|
||||
|
||||
- **Missing Assignee**: Display "Unassigned"
|
||||
- **No Story Points**: Display "Not estimated"
|
||||
- **No Epic Link**: Omit Epic section entirely
|
||||
- **No Comments**: Display "No comments"
|
||||
- **No Linked Issues**: Display "No linked issues"
|
||||
- **No Labels**: Display "None"
|
||||
- **No Description**: Display "No description provided"
|
||||
- **No Acceptance Criteria**: Display "No explicit acceptance criteria defined"
|
||||
```
|
||||
|
||||
## Clickable Links
|
||||
|
||||
Always include clickable Jira links:
|
||||
|
||||
```markdown
|
||||
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/PLAT-123)
|
||||
|
||||
**Epic**: [[PLAT-789]](https://resolvesys.atlassian.net/browse/PLAT-789) Authentication System
|
||||
|
||||
**Blocked By**: [[PLAT-456]](https://resolvesys.atlassian.net/browse/PLAT-456) Database schema update
|
||||
```
|
||||
|
||||
## Session Caching
|
||||
|
||||
When an issue is fetched, cache it for the conversation session:
|
||||
|
||||
```markdown
|
||||
## Cached Issue Data
|
||||
|
||||
Store in memory for current conversation:
|
||||
- Issue key → Full issue data
|
||||
- Last fetched timestamp
|
||||
- TTL: End of conversation session
|
||||
|
||||
Reuse cached data when:
|
||||
- Same issue referenced again in conversation
|
||||
- Reduces API calls
|
||||
- Ensures consistency during session
|
||||
|
||||
Refetch when:
|
||||
- User explicitly requests refresh
|
||||
- Cached data is from previous session
|
||||
- User mentions issue status changed
|
||||
```
|
||||
|
||||
## Formatting Best Practices
|
||||
|
||||
### Markdown Elements
|
||||
|
||||
✅ **Use**:
|
||||
- Headers (`##`, `###`) for sections
|
||||
- Bullet lists for non-sequential items
|
||||
- Numbered lists for sequential items (steps)
|
||||
- Checkboxes (`- [ ]`) for acceptance criteria
|
||||
- Bold (`**text**`) for field names
|
||||
- Links (`[text](url)`) for Jira references
|
||||
- Code blocks (` ``` `) for logs or JSON
|
||||
|
||||
❌ **Avoid**:
|
||||
- Excessive nested lists (max 2 levels)
|
||||
- Tables for small data (use lists instead)
|
||||
- All-caps text
|
||||
- Emojis (except standard status icons: ✅ 🔄 📋 🔗)
|
||||
|
||||
### Readability
|
||||
|
||||
- Keep line length reasonable (~80-100 chars)
|
||||
- Use blank lines to separate sections
|
||||
- Indent nested content consistently
|
||||
- Format dates consistently (YYYY-MM-DD or relative "3 days ago")
|
||||
- Truncate very long descriptions (show first ~500 chars + "...")
|
||||
|
||||
### Context Awareness
|
||||
|
||||
Adjust verbosity based on use case:
|
||||
|
||||
**For Story Master (Epic Decomposition)**:
|
||||
- Emphasize epic goal and scope
|
||||
- Show all child stories
|
||||
- Highlight gaps or missing stories
|
||||
|
||||
**For Developer (Implementation)**:
|
||||
- Emphasize acceptance criteria
|
||||
- Show technical notes prominently
|
||||
- Include blocking issues
|
||||
|
||||
**For Support (Bug Investigation)**:
|
||||
- Emphasize reproduction steps
|
||||
- Show customer comments
|
||||
- Highlight related bugs
|
||||
|
||||
**For QA (Test Planning)**:
|
||||
- Emphasize acceptance criteria
|
||||
- Show expected behavior
|
||||
- List related test issues
|
||||
|
||||
## Examples
|
||||
|
||||
See [Examples](../../../shared/reference/examples.md#jira-workflows) for complete real-world extraction examples.
|
||||
Reference in New Issue
Block a user