Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

A helpful guide to export issues only with public comments

This workaround is intended to support Jira Service Management (JSM) projects that require exporting issues with only public comments, excluding internal ones. Currently, there are limitations in JQL's ability to differentiate between public and internal comments. Since JSM is primarily designed for customer interaction, sharing internal comments with customers is not a good ideia sometimes. We recognize the importance of this capability and have a related feature in our development backlog to enhance this functionality:

Please be aware that this workaround requires scripting development. If you have any additional questions about implementing the Jira REST API with custom scripts, feel free to share your concerns in our Developer Community.

Workaround steps

To implement this idea, I utilized Python, due to the fact that Python is known for its readability and simplicity, which makes it accessible for both beginners and experienced developers. Also, this language can be particularly useful when writing scripts to interact with APIs.

1. Use this Jira REST API to get a list of all issues in a project. You can do this by querying the endpoint, for example:

GET /rest/api/3/search?jql=project={projectKey}&fields=id,key

This will return a list of issue IDs and keys which you can then iterate over.

2. For each issue ID or key retrieved, make a call to the Request Comments API , for example:

GET /rest/servicedeskapi/request/{issueIdOrKey}/comment

This will return all comments associated with that particular issue.

3. Within the response, check each comment's "visibility" field or equivalent to determine if it's an external comment. External comments typically do not have any restrictions on visibility. So we need to do it by the comment properties below:

"public": true or false

4. Store the external comments in a suitable format (e.g., CSV, JSON) for import into an external platform. For this idea I used CSV format.

With this in mind, we can use a Python script to automate the process, iterate over the issues, and filter and return all external comments from tickets with a request type in a JSM project:

 Please note that this will only apply to issues with an assigned request type. For any issues without a request type, the script will ignored it.

import requests
import csv
from requests.auth import HTTPBasicAuth

# Configure your Jira credentials and project details
JIRA_URL = "https://yourcompany.atlassian.net"  # Replace with your Jira instance URL
PROJECT_KEY = "KEY"  # Replace with your specific project key
AUTH = HTTPBasicAuth("your_email@example.com", "your_api_token")  # Replace with your Jira email and API token

def get_issues_from_project():
    # Construct the API URL for searching issues within the specified project
    url = f"{JIRA_URL}/rest/api/3/search"
    
    # Set the parameters for the JQL query to filter issues by project and specify fields to retrieve
    params = {"jql": f"project={PROJECT_KEY}", "fields": "id,key"}
    
    # Send a GET request to the Jira API to retrieve issues
    response = requests.get(url, auth=AUTH, params=params)
    
    # Raise an exception if the response contains an HTTP error status
    response.raise_for_status()
    
    # Extract and return the list of issues from the JSON response
    return response.json().get('issues', [])

def get_comments_for_issue(issue_key):
    # Construct the API URL to fetch comments for a specific issue
    url = f"{JIRA_URL}/rest/servicedeskapi/request/{issue_key}/comment"
    try:
        # Send a GET request to the Jira API to fetch comments for the specified issue
        response = requests.get(url, auth=AUTH)
        
        # Raise an exception if the response contains an HTTP error status
        response.raise_for_status()
        
        # Extract and return the list of comments from the JSON response
        return response.json().get('values', [])
    except requests.exceptions.HTTPError as e:
        # Check if the error is a 404 Not Found error
        if e.response.status_code == 404:
            # Print a warning message and skip processing this issue if it doesn't exist or lacks a request type
            print(f"Warning: Issue {issue_key} does not have a request type or does not exist. Skipping.")
            return []  # Return an empty list if the issue is not found
        else:
            # Re-raise the exception for any other HTTP errors
            raise

def filter_external_comments(comments):
    # Initialize a list to store external comments
    external_comments = []
    
    # Iterate over each comment
    for comment in comments:
        # Check if the comment is public (external)
        if comment.get('public', False):
            # Add the external comment to the list
            external_comments.append(comment)
    
    # Return the list of external comments
    return external_comments

def export_to_csv(comments, filename='external_comments.csv'):
    # Define the CSV file headers based on the comment fields you want to include
    headers = ['issueKey', 'commentId', 'author', 'body', 'created']
    
    # Open a new CSV file for writing
    with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
        # Create a CSV dictionary writer object
        writer = csv.DictWriter(csvfile, fieldnames=headers)
        
        # Write the header row to the CSV file
        writer.writeheader()
        
        # Iterate over each comment
        for comment in comments:
            # Write the comment data to the CSV file
            writer.writerow({
                'issueKey': comment.get('issueKey'),
                'commentId': comment.get('id'),
                'author': comment.get('author', {}).get('displayName', 'Unknown'),
                'body': comment.get('body', ''),  # Assume body is a simple string
                'created': comment.get('created', '')  # Use the created date as a string
            })

def main():
    # Fetch all issues from the specified project
    issues = get_issues_from_project()
    
    # Initialize a list to store all external comments
    all_external_comments = []

    # Iterate over each issue
    for issue in issues:
        # Get the issue key (identifier)
        issue_key = issue['key']
        
        # Fetch comments for the current issue
        comments = get_comments_for_issue(issue_key)
        
        # Filter out only external comments
        external_comments = filter_external_comments(comments)
        
        # Add the issue key to each external comment for context
        for comment in external_comments:
            comment['issueKey'] = issue_key
            
        # Add the external comments to the list of all external comments
        all_external_comments.extend(external_comments)

    # Export all external comments to a CSV file
    export_to_csv(all_external_comments)

if __name__ == "__main__":
    main()
You can also find the script above in my personal GitHub repository here. It also includes other useful scripts, including one for exporting issues along with internal comments.

This workaround will work as demonstrated in the screen recording below. In this example, I retrieve all issues from the AFJ project:

2 comments

Ashok Shembde
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 23, 2024

Hi @Bruno Altenhofen ,

Thank you for sharing this detailed workaround! It's great to see how you've tackled the limitation of JQL in differentiating between public and internal comments in Jira Service Management (JSM).

Like Bruno Altenhofen likes this
Bruno Altenhofen
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
October 24, 2024

Thanks @Ashok Shembde ! :D

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events