Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating Jira issues with attachments fails #386

Open
NuLL3rr0r opened this issue Jul 14, 2021 · 6 comments
Open

Creating Jira issues with attachments fails #386

NuLL3rr0r opened this issue Jul 14, 2021 · 6 comments
Labels
needs triage Ticket that needs triage (a proper look for classification)

Comments

@NuLL3rr0r
Copy link

NuLL3rr0r commented Jul 14, 2021

Describe the bug

Attachments are not working and result in the following response from Jira:

 {"errorMessages":[],"errors":{"attachment":"string expected at index 0"}}

To Reproduce

Example code which fails:

func ReportIssue(client *jira.Client, project Project, summary string, description string) error {
	jww.INFO.Printf("Reporting an issue for '%s' project on Jira...\n", project.Name)

	// Acquire the id/keys through /rest/api/latest/field
	// NOTE: For custom fields with specific data types (string/number), the value must be passed directly
	// NOTE: Syntax for multicheckboxes (an array) => []map[string]string{{"value": "Something"}}
	// NOTE: Syntax for customfieldtype:select => map[string]string{"value": "NA"}
	customFields := tcontainer.NewMarshalMap()
	// Revision reported
	customFields["customfield_10700"] = "39018"
	// Reproducibilty
	customFields["customfield_10922"] = map[string]string{"value": "50% - Random"}
	// Severity
	customFields["customfield_10919"] = map[string]string{"value": "P1 - Critical"}

	logFile, err := ioutil.ReadFile("D:\\hello.txt")
	if err != nil {
		jww.FATAL.Println(err)
	}

	mtype := mimetype.Detect(logFile)

	i := jira.Issue{
		Fields: &jira.IssueFields{
			Type: jira.IssueType{
				Name: "Bug",
			},
			Project: jira.Project{
				Key: project.Name,
			},
			Priority: &jira.Priority{
				Name: "Medium",
			},
			Components: []*jira.Component{
				&jira.Component{
					Name: "QA",
				},
			},
			Description: description,
			Summary:     summary,
			FixVersions: []*jira.FixVersion{
				&jira.FixVersion{
					Name: "Gameplay Prototype",
				},
			},
			Attachments: []*jira.Attachment{
				&jira.Attachment{
					Filename: "helloworld.txt",
					Size:     len(logFile),
					MimeType: mtype.String(),
					Content:  string(logFile[:]),
				},
			},
			Unknowns: customFields,
		},
	}

	issue, resp, err := client.Issue.Create(&i)
	if err != nil {
		jww.FATAL.Println(err)
		body, err := ioutil.ReadAll(resp.Body)
		if err == nil {
			jww.FATAL.Println(string(body))
		} else {
			jww.FATAL.Println("Failed to decode the Jira's response!")
		}
		return errors.New("Failed to create the Jira issue!")
	}

	jww.INFO.Printf("The Jira issue '%s': %+v has been created!\n", issue.Key, issue.Self)

	return nil
}

Expected behavior

The attachments should work when creating an issue.

Your Environment

Include as many relevant details about the environment you experienced the problem in

  • go-jira version (v1.8.0):
  • Go version (1.16):
  • Jira version: Hosted from atlassian.net
  • Jira type (cloud or on-premise): cloud
  • Involved Jira plugins:
  • Operating System and version: Windows 10

Additional context

Our Jira instance requires the following (some are custom fields and attachments) when we create an issue:

{"errorMessages":["Please fill in the Component, priority, reproducibility, severity, type, description, Fix version, and revision reported. Also add your log/video or images as an attachment"],"errors":{}}
@github-actions
Copy link

Hi! Thank you for taking the time to create your first issue! Really cool to see you here for the first time. Please give us a bit of time to review it.

@NuLL3rr0r
Copy link
Author

It would also be nice if there were any attachment examples in the examples dir.

@ctreminiom
Copy link
Contributor

It seems you cannot add attachments while you're creating the issue, the issue must be created before.

I've created a little example about how to attach a file on an issue: https://docs.go-atlassian.io/jira-software-cloud/issues/attachments#add-attachment

@NuLL3rr0r
Copy link
Author

Thank you very much! Indeed creating issues with attachments in one go won't work. I found the relevant info after creating this issue: "Creating an issue required posting JSON payload. Adding an attachment required posting a MultiPartMime. Both the same time is not possible at the moment."

I changed my code like this:

func ReportIssue(client *jira.Client, project Project, revision string,
	logFile string, screenShotFile string,
	summary string, description string) error {
	jww.INFO.Printf("Reporting an issue for '%s' project on Jira...\n", project.Name)

	// Acquire the id/keys through /rest/api/latest/field
	// NOTE: For custom fields with specific data types (string/number), the value must be passed directly
	// NOTE: Syntax for multicheckboxes (an array) => []map[string]string{{"value": "Something"}}
	// NOTE: Syntax for customfieldtype:select => map[string]string{"value": "NA"}
	customFields := tcontainer.NewMarshalMap()
	// Revision reported
	customFields["customfield_10700"] = revision

	i := jira.Issue{
		Fields: &jira.IssueFields{
			Type: jira.IssueType{
				Name: "Bug",
			},
			Project: jira.Project{
				Key: project.Name,
			},
			Priority: &jira.Priority{
				Name: "Medium",
			},
			Components: []*jira.Component{
				&jira.Component{
					Name: "QA",
				},
			},
			Description: description,
			Summary:     summary,
			Unknowns:    customFields,
		},
	}

	issue, resp, err := client.Issue.Create(&i)
	if err != nil {
		jww.ERROR.Println(err)
		body, err := ioutil.ReadAll(resp.Body)
		if err == nil {
			jww.ERROR.Println(string(body))
		} else {
			jww.ERROR.Println("Failed to decode the Jira's response!")
		}
		return errors.New("Failed to create the Jira issue!")
	}

	jww.INFO.Printf("The Jira issue '%s': '%+v' has been created!\n", issue.Key, issue.Self)

	/// NOTE:
	// Creating an issue required posting JSON payload.
	// Adding an attachment required posting a MultiPartMime.
	// Both the same time is not possible at the moment.
	// Source:
	// https://community.atlassian.com/t5/Jira-questions/Jira-REST-API-Attach-file-at-the-same-time-as-creating-an-issue/qaq-p/1295704

	/// NOTE:
	// It only accepts one attachment at once.
	// Source:
	// https://docs.go-atlassian.io/jira-software-cloud/issues/attachments#add-attachment

	jww.INFO.Printf("Adding the log file '%s' as an attachment to issue '%s'...\n", logFile, issue.Key)
	err = addIssueAttachment(client, project, issue.Key, logFile)
	if err != nil {
		jww.ERROR.Println(err)
		return errors.New("Failed to attach the log file to the newly created Jira issue!")
	}

	jww.INFO.Printf("Adding the screenshot file '%s' as an attachment to issue '%s'...\n", screenShotFile, issue.Key)
	err = addIssueAttachment(client, project, issue.Key, screenShotFile)
	if err != nil {
		jww.ERROR.Println(err)
		return errors.New("Failed to attach the log file to the newly created Jira issue!")
	}

	jww.INFO.Printf("All files have been attached to the Jira issue '%s' successfully!\n", issue.Key)

	return nil
}

func addIssueAttachment(client *jira.Client, project Project, issue string, filePath string) error {
	jww.INFO.Printf("Attaching '%s' to issue '%s' on '%s' Jira project...\n", filePath, issue, project.Name)

	absPath, err := filepath.Abs(filePath)
	if err != nil {
		jww.ERROR.Println(err)
		return errors.New(fmt.Sprintf("Failed to attach '%s' to issue '%s' on '%s' Jira project!", filePath, issue, project.Name))
	}
	jww.INFO.Printf("The abosulte path for '%s' is '%s'.\n", filePath, absPath)
	fileName := filepath.Base(absPath)

	reader, err := os.Open(absPath)
	if err != nil {
		jww.ERROR.Println(err)
		return errors.New(fmt.Sprintf("Failed to attach '%s' to issue '%s' on '%s' Jira project!", absPath, issue, project.Name))
	}

	attachments, resp, err := client.Issue.PostAttachment(issue, reader, fileName)
	if err != nil {
		jww.ERROR.Println(err)
		body, err := ioutil.ReadAll(resp.Body)
		if err == nil {
			jww.ERROR.Println(string(body))
		} else {
			jww.ERROR.Println("Failed to decode the Jira's response!")
		}
		return errors.New(fmt.Sprintf("Failed to attach '%s' to issue '%s' on '%s' Jira project!", absPath, issue, project.Name))
	}

	for _, attachment := range *attachments {
		jww.INFO.Printf("The attachment '%s' with ID '%s' has been attached to issue '%s' on '%s' Jira project successfully", attachment.Filename, attachment.ID, issue, project.Name)
	}

	return nil
}

Still good to have a working example inside the examples folder, though.

@andygrunwald andygrunwald added the needs triage Ticket that needs triage (a proper look for classification) label Aug 20, 2022
@andygrunwald
Copy link
Owner

Hey,

I am very sorry that this issue has been open for a long time with no final solution. We work on this project in our spare time, and sometimes, other priorities take over. This is the typical open source dilemma.

However, there is news: We are kicking off v2 of this library 🚀

To provide visibility, we created the Road to v2 Milestone and calling for your feedback in #489

The development will take some time; however, I hope you can benefit from the changes.
If you seek priority development for your issue + you like to sponsor it, please contact me.

What does this mean for my issue?

We will work on this issue indirectly.
This means that during the development phase, we aim to tackle it.
Maybe in a different way like it is currently handled.
Please understand that this will take a while because we are running this in our spare time.

Final words

Thanks for using this library.
If there is anything else you would like to tell us, let us know!

@NuLL3rr0r
Copy link
Author

Thank you very much for the information. It was a one-time project I worked on at the previous company I was working for. Nonetheless, the project went well and your library was a substantial part of that project. I will look into it again in the future if I come across a project dealing with Jira.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs triage Ticket that needs triage (a proper look for classification)
Projects
None yet
Development

No branches or pull requests

3 participants