Detailed implementation guide for generating bug fix release notes from Jira and GitHub PRs
Inherits all available tools
Additional assets for this skill
This skill inherits all available tools. When active, it can use any tool Claude has access to.
This skill provides detailed step-by-step implementation guidance for the /jira:create-release-note command, which automatically generates bug fix release notes by analyzing Jira bug tickets and their linked GitHub pull requests.
This skill is automatically invoked by the /jira:create-release-note command and should not be called directly by users.
gh) installed and authenticatedObjective: Retrieve the bug ticket and validate it's appropriate for release note generation.
Actions:
Fetch the bug using MCP:
mcp__atlassian__jira_get_issue(
issue_key=<issue-key>,
fields="summary,description,issuetype,status,issuelinks,customfield_12320850,customfield_12317313,comment"
)
Parse the response:
issuetype.name - verify it's "Bug"description - full bug description textissuelinks - array of linked issuescustomfield_12320850 - current Release Note Type (if already set)customfield_12317313 - current Release Note Text (if already set)comment.comments - array of comment objectsValidate issue type:
issuetype.name != "Bug", show warning:
Warning: {issue-key} is not a Bug (it's a {issuetype.name}).
Release notes are typically for bugs. Continue anyway? (yes/no)
Check if release note already exists:
customfield_12317313 is not empty, show warning:
This bug already has a release note:
---
{existing release note}
---
Do you want to regenerate it? (yes/no)
Objective: Extract the required Cause and Consequence sections from the bug description.
Bug Description Format:
Jira bug descriptions often follow this structure:
Description of problem:
{code:none}
<problem description>
{code}
Cause:
{code:none}
<root cause>
{code}
Consequence:
{code:none}
<impact>
{code}
Version-Release number of selected component (if applicable):
...
How reproducible:
...
Steps to Reproduce:
...
Actual results:
...
Expected results:
...
Parsing Strategy:
Look for "Cause:" section:
{code:none}, {code}, etc.Look for "Consequence:" section:
Alternative patterns:
Handle missing sections:
Bug description is missing the "Cause" section.
Would you like to:
1. Provide the Cause interactively
2. Update the bug description in Jira first
3. Cancel
Bug description is missing the "Consequence" section.
Would you like to:
1. Provide the Consequence interactively
2. Update the bug description in Jira first
3. Cancel
Interactive input (if user chooses option 1):
Example Parsing:
Input:
Description of problem:
{code:none}
The control plane operator crashes when CloudProviderConfig.Subnet is not specified
{code}
Cause:
{code:none}
hostedcontrolplane controller crashes when hcp.Spec.Platform.AWS.CloudProviderConfig.Subnet.ID is undefined
{code}
Consequence:
{code:none}
control-plane-operator enters a crash loop
{code}
Output:
Cause: "hostedcontrolplane controller crashes when hcp.Spec.Platform.AWS.CloudProviderConfig.Subnet.ID is undefined"
Consequence: "control-plane-operator enters a crash loop"
Objective: Find all GitHub PR URLs associated with this bug.
Sources to check (in priority order):
Remote Links (Primary source - web links in Jira):
remotelinks, or issuelinks with outward GitHub PR linkshttps://github\.com/[\w-]+/[\w-]+/pull/\d+gh issue view {JIRA-KEY} - Jira keys are NOT GitHub issue numbersBug Description:
description field for GitHub PR URLshttps://github\.com/([\w-]+)/([\w-]+)/pull/(\d+)Bug Comments:
comment.comments arraybody field for GitHub PR URLsSearch by bug number (Fallback if no PR URLs found):
for repo in "openshift/hypershift" "openshift/cluster-api-provider-aws" "openshift/origin"; do
gh pr list --repo "$repo" --search "{issue-key} in:title,body" --state all --limit 10 --json number,url,title
done
Found PRs mentioning {issue-key}:
1. openshift/hypershift#4567 - Fix panic when CloudProviderConfig.Subnet is undefined
2. openshift/hypershift#4568 - Add tests for Subnet validation
Which PRs should be included in the release note? (enter numbers separated by commas, or 'all')
gh issue view {JIRA-KEY} - this will failURL Parsing:
For each found URL https://github.com/openshift/hypershift/pull/4567:
org: "openshift"repo: "hypershift"pr_number: "4567"{"url": "...", "repo": "openshift/hypershift", "number": "4567"}Deduplication:
Validation:
No GitHub PRs found linked to {issue-key}.
Please link at least one PR to generate release notes.
How to link PRs in Jira:
1. Edit the bug in Jira
2. Add a web link to the GitHub PR URL
3. Or mention the PR URL in a comment
4. Then run this command again
Exit without updating the ticket.Example:
Found PRs:
[
{
"url": "https://github.com/openshift/hypershift/pull/4567",
"repo": "openshift/hypershift",
"number": "4567"
},
{
"url": "https://github.com/openshift/hypershift/pull/4568",
"repo": "openshift/hypershift",
"number": "4568"
}
]
Objective: Extract Fix, Result, and Workaround information from each linked PR.
For each PR in the list:
Command:
gh pr view {number} --json body,title,commits,url,state --repo {repo}
Error handling:
if ! gh pr view {number} --json body,title,commits,url,state --repo {repo} 2>/dev/null; then
echo "Warning: Unable to access PR {url}"
echo "Verify the PR exists and you have permissions."
# Skip this PR, continue with next
fi
Expected output (JSON):
{
"body": "This PR fixes the panic when CloudProviderConfig.Subnet is not specified...",
"title": "Fix panic when CloudProviderConfig.Subnet is not specified",
"commits": [
{
"messageHeadline": "Add nil check for Subnet field",
"messageBody": "This prevents the controller from crashing..."
}
],
"url": "https://github.com/openshift/hypershift/pull/4567",
"state": "MERGED"
}
Parse and store:
title: PR title (short summary)body: Full PR descriptioncommits: Array of commit objects with messagesstate: PR state (MERGED, OPEN, CLOSED)Command:
gh pr diff {number} --repo {repo}
Purpose: Understand what code was actually changed
Analysis strategy:
+)if err != nil)if x == nil)Example diff analysis:
+if hcp.Spec.Platform.AWS.CloudProviderConfig.Subnet == nil {
+ return fmt.Errorf("Subnet configuration is required")
+}
Summary: "Added nil check for CloudProviderConfig.Subnet field"
Command:
gh pr view {number} --json comments --repo {repo}
Expected output (JSON):
{
"comments": [
{
"author": {"login": "reviewer1"},
"body": "This looks good. The nil check will prevent the crash."
},
{
"author": {"login": "author"},
"body": "Yes, and I also added a more descriptive error message."
}
]
}
Analysis strategy:
Combine all sources (title, body, commits, diff, comments) to extract:
Fix (what was changed):
Example Fix:
Added nil check for CloudProviderConfig.Subnet before accessing Subnet.ID field to prevent nil pointer dereference
Result (outcome after the fix):
Example Result:
The control-plane-operator no longer crashes when CloudProviderConfig.Subnet is not specified
Workaround (temporary solution before fix):
Example Workaround (if found):
Users can manually specify a Subnet value in the HostedCluster spec to avoid the crash
Objective: If multiple PRs are linked, synthesize them into a single coherent release note.
Scenarios:
Example:
Strategy: Combine all fixes into a narrative
Fix: Added nil check for CloudProviderConfig.Subnet field (PR #123), improved error messaging for missing configuration (PR #456), and added validation tests to prevent regression (PR #789)
Example:
Strategy: Mention the fix once, note the backports
Fix: Added nil check for CloudProviderConfig.Subnet field (backported to 4.20 and 4.19)
Example:
Strategy: Analyze the code diffs to determine what actually happened, or ask user:
Found multiple PRs with different fix descriptions:
- PR #123: "Fixed by adding validation"
- PR #456: "Fixed by removing the field access"
Which description is more accurate, or should I combine them?
Objective: Create the final release note text following the standard template.
Template:
Cause: {cause from Jira}
Consequence: {consequence from Jira}
Fix: {synthesized from PRs}
Result: {synthesized from PRs}
Workaround: {synthesized from PRs - optional}
Formatting rules:
Example output:
Cause: hostedcontrolplane controller crashes when hcp.Spec.Platform.AWS.CloudProviderConfig.Subnet.ID is undefined
Consequence: control-plane-operator enters a crash loop
Fix: Added nil check for CloudProviderConfig.Subnet before accessing Subnet.ID field
Result: The control-plane-operator no longer crashes when CloudProviderConfig.Subnet is not specified
Objective: Scan the release note text for sensitive data before submission.
Patterns to detect:
API Tokens and Keys:
(sk|pk)_[a-zA-Z0-9]{20,}ghp_[a-zA-Z0-9]{36}gho_[a-zA-Z0-9]{36}github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}AWS Credentials:
AKIA[0-9A-Z]{16}aws_access_key_id\s*=\s*[A-Z0-9]+aws_secret_access_key\s*=\s*[A-Za-z0-9/+=]+Passwords in URLs:
https?://[^:]+:[^@]+@https://user:password@example.comJWT Tokens:
eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+SSH Private Keys:
-----BEGIN (RSA|OPENSSH|DSA|EC|PGP) PRIVATE KEY-----Kubernetes Secrets:
[a-zA-Z0-9+/]{40,}==? (base64 encoded secrets)Validation logic:
sensitive_patterns = {
"API Token": r"(sk|pk)_[a-zA-Z0-9]{20,}",
"GitHub Token": r"gh[po]_[a-zA-Z0-9]{36}",
"AWS Access Key": r"AKIA[0-9A-Z]{16}",
"URL with credentials": r"https?://[^:]+:[^@]+@",
"JWT Token": r"eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+",
"Private Key": r"-----BEGIN .* PRIVATE KEY-----"
}
for name, pattern in sensitive_patterns.items():
if re.search(pattern, release_note_text):
print(f"Security validation failed!")
print(f"Detected what appears to be {name} in the release note text.")
print(f"Please review the source PRs and remove any credentials.")
exit(1)
If validation fails:
Security validation failed!
Detected what appears to be an API token in the release note text.
This may have come from:
- PR description
- Commit messages
- Code changes (diff)
- PR comments
Please review the source PRs and remove any credentials before proceeding.
Use placeholder values instead:
- YOUR_API_KEY
- <redacted>
- ********
Aborting release note creation.
Objective: Determine the appropriate Release Note Type for this bug.
Available types (from Jira dropdown):
Auto-detection strategy:
For OCPBUGS: Default suggestion is "Bug Fix" (most common)
Check for CVE references:
Check for deprecation:
Check for new features:
Check for known issues:
User interaction:
Use the AskUserQuestion tool:
questions = [{
"question": "What type of release note is this?",
"header": "Type",
"multiSelect": false,
"options": [
{
"label": "Bug Fix",
"description": "Fix for a defect (most common)"
},
{
"label": "Known Issue",
"description": "Documents a known problem without a fix"
},
{
"label": "Enhancement",
"description": "New feature or improvement"
},
{
"label": "CVE",
"description": "Security vulnerability fix"
}
]
}]
Store selection for use in the next step.
Objective: Write the release note to the Jira ticket.
MCP tool call:
mcp__atlassian__jira_update_issue(
issue_key=<issue-key>,
fields={
"customfield_12320850": {"value": "<selected_type>"},
"customfield_12317313": "<formatted_release_note_text>"
}
)
Field details:
customfield_12320850: Release Note Type (must be exact match from dropdown)customfield_12317313: Release Note Text (plain text)Error handling:
Permission denied:
Failed to update {issue-key}.
Error: You do not have permission to edit Release Note fields
Please contact your Jira administrator or manually add the release note.
Generated release note (for manual entry):
---
{release_note_text}
---
Invalid field value:
Failed to update Release Note Type field.
Error: Value "{selected_type}" is not valid
Please select a different type or manually update in Jira.
Field not found:
Failed to update {issue-key}.
Error: Field customfield_12320850 not found
This may indicate a different Jira instance or configuration.
Please manually add the release note.
Success response:
{
"success": true,
"issue": {
"key": "OCPBUGS-38358",
"fields": {
"customfield_12320850": {"value": "Bug Fix"},
"customfield_12317313": "Cause: ... Consequence: ... Fix: ... Result: ..."
}
}
}
Objective: Show the user what was created and provide next steps.
Output format:
✓ Release Note Created for {issue-key}
Type: {Release Note Type}
Text:
---
{Release Note Text with proper formatting}
---
Updated: https://issues.redhat.com/browse/{issue-key}
Next steps:
- Review the release note in Jira
- Edit manually if any adjustments are needed
- The release note will be included in the next release
Example:
✓ Release Note Created for OCPBUGS-38358
Type: Bug Fix
Text:
---
Cause: hostedcontrolplane controller crashes when hcp.Spec.Platform.AWS.CloudProviderConfig.Subnet.ID is undefined
Consequence: control-plane-operator enters a crash loop
Fix: Added nil check for CloudProviderConfig.Subnet before accessing Subnet.ID field
Result: The control-plane-operator no longer crashes when CloudProviderConfig.Subnet is not specified
---
Updated: https://issues.redhat.com/browse/OCPBUGS-38358
Next steps:
- Review the release note in Jira
- Edit manually if any adjustments are needed
- The release note will be included in the next release
Problem: Some PRs can't be accessed or analyzed
Recovery:
Analyzed 2 of 3 linked PRs:
✓ PR #123
✓ PR #456
✗ PR #789 (access denied)
Problem: Missing Cause or Consequence sections
Recovery:
Problem: PRs don't clearly explain the fix
Recovery:
The linked PR doesn't clearly describe the fix.
Based on code analysis, it appears to:
{best guess from diff}
Is this correct? If not, please describe the fix:
Problem: Multiple PRs describe different fixes
Recovery: