commit d1e017f3a5e32144c02d8ce26763abec03576014 Author: Zhongwei Li Date: Sat Nov 29 18:09:17 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..205c8a2 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "jira-ticket", + "description": "Generate Jira tickets from discussions, PRs, issues, or files", + "version": "1.0.0", + "author": { + "name": "Claude Code Plugins", + "email": "plugins@claude.com" + }, + "commands": [ + "./commands" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8071ba2 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# jira-ticket + +Generate Jira tickets from discussions, PRs, issues, or files diff --git a/commands/jira-ticket.md b/commands/jira-ticket.md new file mode 100644 index 0000000..6a08ed8 --- /dev/null +++ b/commands/jira-ticket.md @@ -0,0 +1,233 @@ +--- +description: Generate Jira tickets from discussions, PRs, issues, or files +argument-hint: [reference] +--- + +# Generate Jira Ticket + +Create a high-level Jira issue from a discussion, PR, issue, file, or conversation. + +**Arguments**: `$ARGUMENTS` (required) +- Can be: GitHub URL, PR number, issue number, file path, commit hash/range, or "conversation" + +--- + +## Phase 1: Context Discovery & Gathering + +**Goal**: Identify what the argument references and gather relevant context + +**Actions**: +1. Create a todo list with all phases: + - Phase 1: Context Discovery & Gathering + - Phase 2: Generate Jira Issue + - Phase 3: Validation & Preview + - Phase 4: Save to File + +2. Mark Phase 1 as in_progress + +3. Analyze `$ARGUMENTS` to determine the type: + - **If empty or not provided**: Error - ask user to provide a reference + - **If GitHub URL (starts with https://github.com/ or http://github.com/)**: Parse and use gh + - For PR URLs (e.g., `https://github.com/owner/repo/pull/123`): + - Extract owner, repo, and PR number + - Use `gh pr view -R owner/repo` + - For issue URLs (e.g., `https://github.com/owner/repo/issues/456`): + - Extract owner, repo, and issue number + - Use `gh issue view -R owner/repo` + - **If numeric (e.g., "123")**: Check if it's a PR or issue number in current repo + - Try `gh pr view $ARGUMENTS` first + - If that fails, try `gh issue view $ARGUMENTS` + - **If starts with # (e.g., "#123")**: Treat as issue number in current repo + - Use `gh issue view ${ARGUMENTS#\#}` + - **If starts with PR# or pr# (e.g., "PR#123")**: Treat as PR number in current repo + - Extract number and use `gh pr view ` + - **If file path exists**: Read the file contents + - Use Read tool to read the file + - **If git commit hash or range (e.g., "abc123" or "abc123..def456")**: Get commit messages + - Use `git log --format="%h %s%n%b" $ARGUMENTS` + - **If "conversation" or "chat"**: Use current conversation context + - Inform user you'll use the current conversation as context + - **Otherwise**: Treat as a search term or ask user to clarify + +4. Gather the context based on the identified type: + - For PRs: Extract title, description, and relevant comments + - For issues: Extract title, description, and discussion + - For files: Read and summarize the content + - For commits: Collect commit messages and changes summary + - For conversation: Use recent messages in this chat + +5. Present a brief summary of gathered context to confirm with user: + ``` + **Context Gathered**: + Type: [PR/Issue/File/Commits/Conversation] + Source: [specific reference] + Summary: [1-2 sentence summary] + + Proceeding to generate Jira issue... + ``` + +6. Mark Phase 1 as completed, Phase 2 as in_progress + +**Error Handling**: +- If argument is missing → ask user to provide a reference +- If PR/issue not found → ask user to verify the number +- If file doesn't exist → ask user to check the path +- If git command fails → ask if we're in a git repository + +--- + +## Phase 2: Generate Jira Issue + +**Goal**: Create a high-level Jira issue following the template + +**Actions**: +1. Using the gathered context, generate a Jira issue that: + - Follows the Jira template structure (provided below) + - Extracts **high-level context only** - NO implementation details or design steps + - Anonymizes any customer names → replace with "customer" + - Adds links where possible (PR links, issue links, commit links, file URLs) + - Uses Jira markdown formatting + - Is copy-paste ready for Jira input box + +2. Generate a recommended title (one line, descriptive, under 100 characters) + +3. Use this Jira template structure: + +```jira-markup +h1. Story (Required) + +As a trying to I want + +__ + +h2. *Background (Required)* + +__ + +h2. *Out of scope* + +__ + +h2. *Approach (Required)* + +__ + +h2. *Dependencies* + +__ + +h2. *Acceptance Criteria (Mandatory)* + +__ +__ +``` + +4. **IMPORTANT Guidelines**: + - Do NOT add implementation details - keep it high-level for engineers to figure out + - Do NOT add low-level design steps + - DO add links to relevant resources (PRs, issues, docs, commits) + - DO use clear, testable Acceptance Criteria (Given/When/Then or numbered checklist) + - DO keep customer references anonymous as "customer" + - DO format everything in Jira markdown (h1., h2., *, _, etc.) + +5. Mark Phase 2 as completed, Phase 3 as in_progress + +--- + +## Phase 3: Validation & Preview + +**Goal**: Validate the generated issue and get user approval + +**Actions**: +1. Validate that all required fields are filled: + - Story section has content + - Background section has content + - Approach section has content + - Acceptance Criteria has content + +2. Present the generated Jira issue to the user: + ``` + **Recommended Title**: + [Generated title] + + **Jira Issue Body**: + [Show the full generated Jira issue in a code block] + ``` + +3. **Ask user**: "Does this Jira issue look good? Should I save it to a file?" + +4. **WAIT FOR USER RESPONSE** + +5. If user wants changes: + - Ask what needs to be modified + - Regenerate the issue + - Return to step 2 + +6. If user approves: + - Mark Phase 3 as completed, Phase 4 as in_progress + - Proceed to Phase 4 + +7. If user rejects: + - Exit gracefully + - Mark all remaining phases as completed + +**Error Handling**: +- If any required field is missing → warn user and ask if they want to proceed anyway + +--- + +## Phase 4: Save to File + +**Goal**: Save the Jira issue to a file with a smart filename + +**Actions**: +1. Generate a filename slug from the title: + - Convert title to lowercase + - Replace spaces with hyphens + - Remove special characters + - Limit to 50 characters + - Add `.md` extension + - Example: "Add user authentication flow" → "add-user-authentication-flow.md" + +2. Ask user for save location using AskUserQuestion tool: + - Option 1: Save to `/tmp/jira-[slug].md` + - Option 2: Save to current directory `./jira-[slug].md` + - Show both full paths in the options + +3. Save the file to the chosen location: + - Write the Jira issue content to the file + - Include a comment at the top with metadata: + ``` + + + + ``` + +4. Report success to user: + ``` + ✓ Jira issue saved successfully! + + **File**: [full path to saved file] + **Title**: [recommended title] + + **Next Steps**: + 1. Review the file: `cat [path]` + 2. Copy to clipboard: `cat [path] | pbcopy` (macOS) or `cat [path] | xclip -selection clipboard` (Linux) + 3. Paste into Jira and use the recommended title above + ``` + +5. Mark Phase 4 as completed + +**Error Handling**: +- If file write fails → report error and suggest alternative location +- If directory doesn't exist → create it or ask user for alternative + +--- + +## Final Notes + +- The plugin uses TodoWrite to track progress through all phases +- Each phase has clear boundaries and completion markers +- User approval is required before saving +- Smart context gathering handles multiple input types +- Output is Jira-ready markdown with proper formatting diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..d4e3d1f --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,45 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:chmouel/claude-code-plugins:plugins/jira-ticket", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "de601c8d4d4d97323e11673625e6065436c65d07", + "treeHash": "3bf4fbe4ddd17eb1e5c27dab2018ab147450ce091ee699e15512962798f713d2", + "generatedAt": "2025-11-28T10:15:02.635544Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "jira-ticket", + "description": "Generate Jira tickets from discussions, PRs, issues, or files", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "0e3eb71feefbe1e162d81fa9ab684271556c35d4f10403c9b598a5a20e7c04b8" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "e50f0c548e220a3359edae7e9b66b0fc1710142f9e044c27b91438b923328f15" + }, + { + "path": "commands/jira-ticket.md", + "sha256": "3d35165be0351ad2ed7c89277d310c252d7dac00e75c1acbb36dcaf2397e77cf" + } + ], + "dirSha256": "3bf4fbe4ddd17eb1e5c27dab2018ab147450ce091ee699e15512962798f713d2" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file