Claude-skill-registry jira-status-updater
Automate JIRA ticket status transitions after pull requests are merged, ensuring proper workflow closure
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/jira-status-updater" ~/.claude/skills/majiayu000-claude-skill-registry-jira-status-updater && rm -rf "$T"
skills/data/jira-status-updater/SKILL.mdWhat I do
I provide automated JIRA ticket status transitions to ensure proper workflow completion after PR merges:
- Detect JIRA Ticket: Extract JIRA ticket key from PR title, commits, or branch name
- Query Available Transitions: Use Atlassian API to get valid status transitions for the ticket
- Identify Target Status: Find "Done" or "Closed" status transition
- Execute Status Transition: Update JIRA ticket status using transition API
- Add Merge Comment: Post final comment with PR merge details
- Handle Edge Cases: Gracefully handle missing transitions, permissions, already-done status
- Log Status: Provide clear feedback on transition success/failure
When to use me
Use this framework when:
- A PR has been successfully merged
- You need to update the linked JIRA ticket status
- You want to ensure JIRA tickets are properly closed after work completion
- You're building a workflow that includes PR merge handling
- You need automated JIRA workflow management
This is a framework skill - it provides JIRA status transition functionality that other skills use.
Core Workflow Steps
Step 1: Detect JIRA Ticket Reference
Purpose: Extract JIRA ticket key from PR or commit information
Detection Methods (in priority order):
| Source | Detection Pattern | Example | Command |
|---|---|---|---|
| PR Title | Regex for JIRA key | | Extract from |
| Commit Messages | Regex for JIRA key | | |
| Branch Name | Parse ticket key | | |
| PLAN.md | Search for references | | Read PLAN.md |
Detection Logic:
# Method 1: Extract from PR title (if available) if command -v gh &>/dev/null; then PR_TITLE=$(gh pr view --json title --jq '.title') JIRA_TICKET=$(echo "$PR_TITLE" | grep -oE '[A-Z]+-[0-9]+' | head -1) fi # Method 2: Extract from latest commit if [ -z "$JIRA_TICKET" ]; then JIRA_TICKET=$(git log --oneline -1 | grep -oE '[A-Z]+-[0-9]+' | head -1) fi # Method 3: Extract from branch name if [ -z "$JIRA_TICKET" ]; then BRANCH_NAME=$(git branch --show-current) JIRA_TICKET=$(echo "$BRANCH_NAME" | grep -oE '[A-Z]+-[0-9]+' | head -1) fi # Method 4: Extract from PLAN.md if [ -z "$JIRA_TICKET" ] && [ -f "PLAN.md" ]; then JIRA_TICKET=$(grep -oE '[A-Z]+-[0-9]+' PLAN.md | head -1) fi # Validate ticket format if [ -n "$JIRA_TICKET" ]; then echo "✅ Detected JIRA ticket: $JIRA_TICKET" else echo "⚠️ No JIRA ticket reference found" return 1 fi
Step 2: Get Available Transitions
Purpose: Query Atlassian API to get valid status transitions for the ticket
Tools Used:
atlassian_getTransitionsForJiraIssue
# Get cloud ID CLOUD_ID="${ATLASSIAN_CLOUD_ID:-<default-cloud-id>}" # Query available transitions TRANSITIONS=$(atlassian_getTransitionsForJiraIssue \ --cloudId "$CLOUD_ID" \ --issueIdOrKey "$JIRA_TICKET") # Parse transitions echo "Available transitions for $JIRA_TICKET:" echo "$TRANSITIONS" | jq -r '.transitions[] | "- \(.name) → \(.to.name)"'
Expected Output:
{ "transitions": [ { "id": "121", "name": "Done", "to": { "id": "101", "name": "Done", "statusCategory": { "id": "3", "key": "done", "colorName": "green" } } }, { "id": "131", "name": "In Review", "to": { "id": "103", "name": "In Review", "statusCategory": { "id": "4", "key": "inprogress", "colorName": "blue" } } } ] }
Step 3: Identify Target Status Transition
Purpose: Find the transition that leads to "Done" or "Closed" status
Target Status Priority:
- Done - Most common final status
- Closed - Alternative final status
- Custom status - Any status with category "done"
Detection Logic:
# Try to find "Done" transition TARGET_TRANSITION=$(echo "$TRANSITIONS" | \ jq -r '.transitions[] | select(.to.name == "Done") | {id: .id, name: .name}') # If no "Done", try "Closed" if [ -z "$TARGET_TRANSITION" ]; then TARGET_TRANSITION=$(echo "$TRANSITIONS" | \ jq -r '.transitions[] | select(.to.name == "Closed") | {id: .id, name: .name}') fi # If no specific status found, try any "done" category status if [ -z "$TARGET_TRANSITION" ]; then TARGET_TRANSITION=$(echo "$TRANSITIONS" | \ jq -r '.transitions[] | select(.to.statusCategory.key == "done") | {id: .id, name: .name} | first') fi # Extract transition ID and name TRANSITION_ID=$(echo "$TARGET_TRANSITION" | jq -r '.id') TRANSITION_NAME=$(echo "$TARGET_TRANSITION" | jq -r '.name') if [ -n "$TRANSITION_ID" ]; then echo "✅ Found target transition: $TRANSITION_NAME (ID: $TRANSITION_ID)" else echo "⚠️ No 'Done' or 'Closed' transition available for $JIRA_TICKET" return 1 fi
Alternative Status Handling: Some JIRA workflows use different final status names:
,Done
,Closed
,Complete
,FinishedResolved- Use statusCategory.key == "done" to find any done-category status
Step 4: Check Current Status
Purpose: Avoid unnecessary transitions if ticket is already in target status
Tools Used:
atlassian_getJiraIssue
# Get current ticket status TICKET_DETAILS=$(atlassian_getJiraIssue \ --cloudId "$CLOUD_ID" \ --issueIdOrKey "$JIRA_TICKET") CURRENT_STATUS=$(echo "$TICKET_DETAILS" | jq -r '.fields.status.name') echo "Current status: $CURRENT_STATUS" echo "Target status: $TRANSITION_NAME" # Check if already in target status if [ "$CURRENT_STATUS" = "$TRANSITION_NAME" ]; then echo "✅ Ticket already in target status: $TRANSITION_NAME" echo "No transition needed" return 0 fi # Check if status category is already "done" CURRENT_CATEGORY=$(echo "$TICKET_DETAILS" | jq -r '.fields.status.statusCategory.key') if [ "$CURRENT_CATEGORY" = "done" ]; then echo "✅ Ticket already in done category: $CURRENT_STATUS" echo "No transition needed" return 0 fi
Step 5: Execute Status Transition
Purpose: Update JIRA ticket status to target status
Tools Used:
atlassian_transitionJiraIssue
# Execute transition echo "Transitioning $JIRA_TICKET from $CURRENT_STATUS to $TRANSITION_NAME..." TRANSITION_RESULT=$(atlassian_transitionJiraIssue \ --cloudId "$CLOUD_ID" \ --issueIdOrKey "$JIRA_TICKET" \ --transition "{\"id\": \"$TRANSITION_ID\"}") # Check if transition was successful if [ $? -eq 0 ]; then echo "✅ Successfully transitioned $JIRA_TICKET to $TRANSITION_NAME" STATUS="success" else echo "❌ Failed to transition $JIRA_TICKET" STATUS="failed" fi
Error Handling:
# Check for common errors if echo "$TRANSITION_RESULT" | grep -q "permission"; then echo "❌ Permission denied: You don't have permission to transition this ticket" STATUS="permission_denied" elif echo "$TRANSITION_RESULT" | grep -q "transition does not exist"; then echo "❌ Invalid transition: The selected transition is not available" STATUS="invalid_transition" elif echo "$TRANSITION_RESULT" | grep -q "issue does not exist"; then echo "❌ Invalid ticket: $JIRA_TICKET does not exist" STATUS="invalid_ticket" fi
Step 6: Add Merge Comment to JIRA
Purpose: Document the PR merge with details for traceability
Tools Used:
atlassian_addCommentToJiraIssue
# Get PR details PR_NUMBER=$(gh pr view --json number --jq '.number') PR_URL=$(gh pr view --json url --jq '.url') PR_TITLE=$(gh pr view --json title --jq '.title') MERGED_BY=$(gh pr view --json mergedBy --jq '.mergedBy.login') MERGED_AT=$(gh pr view --json mergedAt --jq '.mergedAt') # Extract commit details COMMIT_HASH=$(git log -1 --pretty=%H) COMMIT_MSG=$(git log -1 --pretty=%s) COMMIT_AUTHOR=$(git log -1 --pretty=%an) COMMIT_DATE=$(git log -1 --date=iso8601 --pretty=%aI) # Create comment body COMMENT_BODY=$(cat <<EOF ## Pull Request Merged **PR**: #$PR_NUMBER - $PR_TITLE **URL**: $PR_URL **Merged By**: @$MERGED_BY **Merged At**: $MERGED_AT ### Status Update ✅ Ticket transitioned from **$CURRENT_STATUS** to **$TRANSITION_NAME** ### Merge Details - **Commit**: \`$COMMIT_HASH\` - **Author**: $COMMIT_AUTHOR - **Date**: $COMMIT_DATE - **Message**: $COMMIT_MSG ### Files Changed \`\`\` $(git diff --stat HEAD~1 HEAD) \`\`\` ### Work Completed The pull request has been successfully merged and the ticket has been closed. EOF ) # Add comment to JIRA ticket atlassian_addCommentToJiraIssue \ --cloudId "$CLOUD_ID" \ --issueIdOrKey "$JIRA_TICKET" \ --commentBody "$COMMENT_BODY" if [ $? -eq 0 ]; then echo "✅ Added merge comment to $JIRA_TICKET" else echo "⚠️ Failed to add comment to $JIRA_TICKET" fi
Step 7: Provide Summary
Purpose: Display clear summary of transition operation
echo "" echo "==========================================" echo "📊 JIRA Status Update Summary" echo "==========================================" echo "" if [ "$STATUS" = "success" ]; then echo "✅ Status Update: SUCCESS" echo "" echo "🎫 Ticket: $JIRA_TICKET" echo "🔄 Transition: $CURRENT_STATUS → $TRANSITION_NAME" echo "👤 Transitioned By: $COMMIT_AUTHOR" echo "📅 Date: $COMMIT_DATE" echo "" echo "🔗 JIRA Ticket: https://<company>.atlassian.net/browse/$JIRA_TICKET" echo "🔗 PR: $PR_URL" elif [ "$STATUS" = "permission_denied" ]; then echo "❌ Status Update: FAILED - Permission Denied" echo "" echo "⚠️ You don't have permission to transition this ticket" echo "🔗 JIRA Ticket: https://<company>.atlassian.net/browse/$JIRA_TICKET" echo "" echo "💡 Solution: Contact your JIRA administrator for permissions" elif [ "$STATUS" = "invalid_transition" ]; then echo "❌ Status Update: FAILED - Invalid Transition" echo "" echo "⚠️ The selected transition is not available for this ticket" echo "🔗 JIRA Ticket: https://<company>.atlassian.net/browse/$JIRA_TICKET" echo "" echo "💡 Solution: Check available transitions and try a different status" elif [ "$STATUS" = "invalid_ticket" ]; then echo "❌ Status Update: FAILED - Invalid Ticket" echo "" echo "⚠️ The JIRA ticket '$JIRA_TICKET' does not exist" echo "" echo "💡 Solution: Verify the ticket key is correct" fi echo "==========================================" echo ""
Integration with Other Skills
Skills That Should Use jira-status-updater
- pr-creation-workflow: Update JIRA status after PR merge
- git-pr-creator: Optionally update JIRA status after PR merge
- jira-git-workflow: Document the complete workflow including status updates
- nextjs-pr-workflow: Update JIRA status after Next.js PR merge
Integration Pattern
# In pr-creation-workflow or git-pr-creator # After successful PR merge: # Step 1: Check if JIRA integration is enabled if [ "$ENABLE_JIRA_STATUS_UPDATE" = "true" ]; then # Step 2: Call jira-status-updater jira-status-updater \ --ticket "$JIRA_TICKET" \ --cloudId "$CLOUD_ID" \ --target-status "Done" # Step 3: Check result if [ $? -eq 0 ]; then echo "✅ JIRA ticket status updated successfully" else echo "⚠️ JIRA ticket status update failed" fi fi
Best Practices
Transition Detection
- Dynamic Query: Always query available transitions, don't hardcode status names
- Status Category: Use
to find any done-category statusstatusCategory.key == "done" - Multiple Targets: Support "Done", "Closed", and other final status names
- Priority Order: Prefer "Done" → "Closed" → Any done-category status
Error Handling
- Current Status Check: Always check current status before transitioning
- Graceful Failure: Don't fail entire workflow if status update fails
- Clear Messages: Provide specific error messages for different failure modes
- User Guidance: Suggest next steps for common errors
Documentation
- Comment Addition: Always add a merge comment for traceability
- PR Details: Include PR number, URL, and merge details in comments
- Commit Info: Add commit hash, author, and date for audit trail
- Files Changed: Include file statistics in merge comments
Configuration
- Enable/Disable: Make JIRA status updates optional via configuration
- Default Status: Allow configuration of default target status
- Cloud ID: Support cloud ID configuration via environment variable
- Fallback Behavior: Continue workflow even if status update fails
Common Issues
No JIRA Ticket Reference Found
Issue: Cannot extract JIRA ticket key from PR or commits
Solution:
# Ask user to specify ticket read -p "Enter JIRA ticket key (e.g., IBIS-101): " JIRA_TICKET # Or skip status update read -p "Skip JIRA status update? (y/n): " SKIP_UPDATE if [ "$SKIP_UPDATE" = "y" ]; then echo "Skipping JIRA status update" fi
Transition Not Available
Issue: Target status transition not available for ticket
Solution:
# List available transitions echo "Available transitions:" echo "$TRANSITIONS" | jq -r '.transitions[] | "- \(.name)"' # Ask user to select read -p "Select transition (or skip): " USER_TRANSITION if [ -n "$USER_TRANSITION" ]; then TRANSITION_ID=$(echo "$TRANSITIONS" | jq -r ".transitions[] | select(.name == \"$USER_TRANSITION\") | .id") else echo "Skipping status update" fi
Permission Denied
Issue: User lacks permission to transition ticket status
Solution:
# Provide clear error message echo "❌ Permission denied: You don't have permission to transition this ticket" echo "" echo "🔗 JIRA Ticket: https://<company>.atlassian.net/browse/$JIRA_TICKET" echo "" echo "💡 Next steps:" echo " 1. Contact your JIRA administrator" echo " 2. Request transition permissions for this project" echo " 3. Manually update ticket status in JIRA"
Ticket Already Done
Issue: Ticket is already in target status
Solution:
# Skip transition but add comment if [ "$CURRENT_STATUS" = "$TRANSITION_NAME" ]; then echo "✅ Ticket already in target status: $TRANSITION_NAME" echo "Adding merge comment only..." # Add merge comment without transitioning fi
Cloud ID Not Configured
Issue: ATLASSIAN_CLOUD_ID environment variable not set
Solution:
# Try to auto-detect if [ -z "$ATLASSIAN_CLOUD_ID" ]; then echo "Detecting cloud ID..." CLOUD_ID=$(atlassian_getAccessibleAtlassianResources | jq -r '.[0].id') export ATLASSIAN_CLOUD_ID="$CLOUD_ID" echo "✅ Detected cloud ID: $ATLASSIAN_CLOUD_ID" fi # Or ask user if [ -z "$ATLASSIAN_CLOUD_ID" ]; then read -p "Enter Atlassian cloud ID: " CLOUD_ID export ATLASSIAN_CLOUD_ID="$CLOUD_ID" fi
Troubleshooting Checklist
Before updating JIRA status:
- JIRA ticket key is valid (e.g., IBIS-101)
- Atlassian cloud ID is configured
- Atlassian MCP tools are available
- User has permission to transition tickets
- Current status is not already target status
After updating JIRA status:
- Status transition was successful
- Merge comment was added to ticket
- Ticket URL is accessible
- Summary is displayed to user
Examples
Example 1: Successful Status Update
Scenario: PR for IBIS-101 is merged, ticket transitions from "In Progress" to "Done"
Output:
✅ Detected JIRA ticket: IBIS-101 Available transitions for IBIS-101: - In Review → In Review - Done → Done - Cancel → Cancelled Current status: In Progress Target status: Done Transitioning IBIS-101 from In Progress to Done... ✅ Successfully transitioned IBIS-101 to Done ✅ Added merge comment to IBIS-101 ========================================== 📊 JIRA Status Update Summary ========================================== ✅ Status Update: SUCCESS 🎫 Ticket: IBIS-101 🔄 Transition: In Progress → Done 👤 Transitioned By: John Doe 📅 Date: 2024-01-26T21:30:00+08:00 🔗 JIRA Ticket: https://company.atlassian.net/browse/IBIS-101 🔗 PR: https://github.com/org/repo/pull/42 ==========================================
Example 2: Ticket Already Done
Scenario: PR for IBIS-102 is merged, but ticket is already in "Done" status
Output:
✅ Detected JIRA ticket: IBIS-102 Current status: Done Target status: Done ✅ Ticket already in target status: Done No transition needed ✅ Added merge comment to IBIS-102 ========================================== 📊 JIRA Status Update Summary ========================================== ✅ Status Update: SUCCESS (No Transition Needed) 🎫 Ticket: IBIS-102 🔄 Transition: Done → Done (Skipped - Already Done) 👤 By: John Doe 📅 Date: 2024-01-26T21:30:00+08:00 🔗 JIRA Ticket: https://company.atlassian.net/browse/IBIS-102 🔗 PR: https://github.com/org/repo/pull/43 ==========================================
Example 3: Permission Denied
Scenario: User lacks permission to transition IBIS-103
Output:
✅ Detected JIRA ticket: IBIS-103 Available transitions for IBIS-103: - In Review → In Review Current status: In Progress Target status: Done ⚠️ No 'Done' or 'Closed' transition available for IBIS-103 ❌ Status Update: FAILED - Invalid Transition ⚠️ The selected transition is not available for this ticket 🔗 JIRA Ticket: https://company.atlassian.net/browse/IBIS-103 💡 Solution: Check available transitions and try a different status ==========================================
Related Skills
- JIRA Integration:
- Provides JIRA utilities and API toolsjira-git-integration
- Git Frameworks:
- PR creation framework (uses jira-status-updater)pr-creation-workflow
- PR creation with JIRA (uses jira-status-updater)git-pr-creator
- Adds progress comments to JIRAgit-issue-updater
- JIRA Workflows:
- Complete JIRA ticket creation and branching workflowjira-git-workflow