mirror of
https://github.com/Threnklyn/jira.git
synced 2026-05-18 20:23:28 +02:00
6a27e28c61
this commit deprecates the searching ability by username and instructs user to provide email or display names in commands. the username parameter has been deprecated completely from v2 and v3 api Signed-off-by: ldelossa <ldelossa@redhat.com>
649 lines
18 KiB
Go
649 lines
18 KiB
Go
package jira
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/coryb/oreo"
|
|
|
|
"github.com/go-jira/jira/jiradata"
|
|
)
|
|
|
|
type IssueQueryProvider interface {
|
|
ProvideIssueQueryString() string
|
|
}
|
|
|
|
type IssueOptions struct {
|
|
Fields []string `json:"fields,omitempty" yaml:"fields,omitempty"`
|
|
Expand []string `json:"expand,omitempty" yaml:"expand,omitempty"`
|
|
Properties []string `json:"properties,omitempty" yaml:"properties,omitempty"`
|
|
FieldsByKeys bool `json:"fieldsByKeys,omitempty" yaml:"fieldsByKeys,omitempty"`
|
|
UpdateHistory bool `json:"updateHistory,omitempty" yaml:"updateHistory,omitempty"`
|
|
}
|
|
|
|
func (o *IssueOptions) ProvideIssueQueryString() string {
|
|
params := []string{}
|
|
if len(o.Fields) > 0 {
|
|
params = append(params, "fields="+strings.Join(o.Fields, ","))
|
|
}
|
|
if len(o.Expand) > 0 {
|
|
params = append(params, "expand="+strings.Join(o.Expand, ","))
|
|
}
|
|
if len(o.Properties) > 0 {
|
|
params = append(params, "properties="+strings.Join(o.Properties, ","))
|
|
}
|
|
if o.FieldsByKeys {
|
|
params = append(params, "fieldsByKeys=true")
|
|
}
|
|
if o.UpdateHistory {
|
|
params = append(params, "updateHistory=true")
|
|
}
|
|
if len(params) > 0 {
|
|
return "?" + strings.Join(params, "&")
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getIssue
|
|
func (j *Jira) GetIssue(issue string, iqg IssueQueryProvider) (*jiradata.Issue, error) {
|
|
return GetIssue(j.UA, j.Endpoint, issue, iqg)
|
|
}
|
|
|
|
func GetIssue(ua HttpClient, endpoint string, issue string, iqg IssueQueryProvider) (*jiradata.Issue, error) {
|
|
query := ""
|
|
if iqg != nil {
|
|
query = iqg.ProvideIssueQueryString()
|
|
}
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue)
|
|
uri += query
|
|
resp, err := ua.GetJSON(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 200 {
|
|
results := &jiradata.Issue{}
|
|
return results, json.NewDecoder(resp.Body).Decode(results)
|
|
}
|
|
return nil, responseError(resp)
|
|
}
|
|
|
|
func (j *Jira) GetIssueWorklog(issue string) (*jiradata.Worklogs, error) {
|
|
return GetIssueWorklog(j.UA, j.Endpoint, issue)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/worklog-getIssueWorklog
|
|
func GetIssueWorklog(ua HttpClient, endpoint string, issue string) (*jiradata.Worklogs, error) {
|
|
startAt := 0
|
|
total := 1
|
|
maxResults := 100
|
|
worklogs := jiradata.Worklogs{}
|
|
for startAt < total {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "worklog")
|
|
uri += fmt.Sprintf("?startAt=%d&maxResults=%d", startAt, maxResults)
|
|
resp, err := ua.GetJSON(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 200 {
|
|
results := &jiradata.WorklogWithPagination{}
|
|
err := json.NewDecoder(resp.Body).Decode(results)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
startAt = startAt + maxResults
|
|
total = results.Total
|
|
worklogs = append(worklogs, results.Worklogs...)
|
|
} else {
|
|
return nil, responseError(resp)
|
|
}
|
|
}
|
|
return &worklogs, nil
|
|
}
|
|
|
|
func (j *Jira) GetIssueComment(issue string) (*jiradata.Comments, error) {
|
|
return GetIssueComment(j.UA, j.Endpoint, issue)
|
|
}
|
|
|
|
// https://docs.atlassian.com/software/jira/docs/api/REST/7.12.0/#api/2/issue-getComments
|
|
func GetIssueComment(ua HttpClient, endpoint string, issue string) (*jiradata.Comments, error) {
|
|
startAt := 0
|
|
total := 1
|
|
maxResults := 100
|
|
comments := jiradata.Comments{}
|
|
for startAt < total {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "comment")
|
|
uri += fmt.Sprintf("?startAt=%d&maxResults=%d", startAt, maxResults)
|
|
resp, err := ua.GetJSON(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 200 {
|
|
results := &jiradata.CommentsWithPagination{}
|
|
err := json.NewDecoder(resp.Body).Decode(results)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
startAt = startAt + maxResults
|
|
total = results.Total
|
|
comments = append(comments, results.Comments...)
|
|
} else {
|
|
return nil, responseError(resp)
|
|
}
|
|
}
|
|
return &comments, nil
|
|
}
|
|
|
|
type WorklogProvider interface {
|
|
ProvideWorklog() *jiradata.Worklog
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/worklog-addWorklog
|
|
func (j *Jira) AddIssueWorklog(issue string, wp WorklogProvider) (*jiradata.Worklog, error) {
|
|
return AddIssueWorklog(j.UA, j.Endpoint, issue, wp)
|
|
}
|
|
|
|
func AddIssueWorklog(ua HttpClient, endpoint string, issue string, wp WorklogProvider) (*jiradata.Worklog, error) {
|
|
req := wp.ProvideWorklog()
|
|
encoded, err := json.Marshal(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "worklog")
|
|
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 201 {
|
|
results := &jiradata.Worklog{}
|
|
return results, json.NewDecoder(resp.Body).Decode(results)
|
|
}
|
|
return nil, responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getEditIssueMeta
|
|
func (j *Jira) GetIssueEditMeta(issue string) (*jiradata.EditMeta, error) {
|
|
return GetIssueEditMeta(j.UA, j.Endpoint, issue)
|
|
}
|
|
|
|
func GetIssueEditMeta(ua HttpClient, endpoint string, issue string) (*jiradata.EditMeta, error) {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "editmeta")
|
|
resp, err := ua.GetJSON(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 200 {
|
|
results := &jiradata.EditMeta{}
|
|
return results, json.NewDecoder(resp.Body).Decode(results)
|
|
}
|
|
return nil, responseError(resp)
|
|
}
|
|
|
|
type IssueUpdateProvider interface {
|
|
ProvideIssueUpdate() *jiradata.IssueUpdate
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-editIssue
|
|
func (j *Jira) EditIssue(issue string, iup IssueUpdateProvider) error {
|
|
return EditIssue(j.UA, j.Endpoint, issue, iup)
|
|
}
|
|
|
|
func EditIssue(ua HttpClient, endpoint string, issue string, iup IssueUpdateProvider) error {
|
|
req := iup.ProvideIssueUpdate()
|
|
encoded, err := json.Marshal(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue)
|
|
resp, err := ua.Put(uri, "application/json", bytes.NewBuffer(encoded))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 204 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-createIssue
|
|
func (j *Jira) CreateIssue(iup IssueUpdateProvider) (*jiradata.IssueCreateResponse, error) {
|
|
return CreateIssue(j.UA, j.Endpoint, iup)
|
|
}
|
|
|
|
func CreateIssue(ua HttpClient, endpoint string, iup IssueUpdateProvider) (*jiradata.IssueCreateResponse, error) {
|
|
req := iup.ProvideIssueUpdate()
|
|
encoded, err := json.Marshal(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
uri := URLJoin(endpoint, "rest/api/2/issue")
|
|
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 201 {
|
|
results := &jiradata.IssueCreateResponse{}
|
|
return results, json.NewDecoder(resp.Body).Decode(results)
|
|
}
|
|
return nil, responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getCreateIssueMeta
|
|
func (j *Jira) GetIssueCreateMetaProject(projectKey string) (*jiradata.CreateMetaProject, error) {
|
|
return GetIssueCreateMetaProject(j.UA, j.Endpoint, projectKey)
|
|
}
|
|
|
|
func GetIssueCreateMetaProject(ua HttpClient, endpoint string, projectKey string) (*jiradata.CreateMetaProject, error) {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue/createmeta")
|
|
uri += fmt.Sprintf("?projectKeys=%s&expand=projects.issuetypes.fields", projectKey)
|
|
resp, err := ua.GetJSON(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 200 {
|
|
results := &jiradata.CreateMeta{}
|
|
err = json.NewDecoder(resp.Body).Decode(results)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, project := range results.Projects {
|
|
if project.Key == projectKey {
|
|
return project, nil
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("project %s not found", projectKey)
|
|
}
|
|
return nil, responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getCreateIssueMeta
|
|
func (j *Jira) GetIssueCreateMetaIssueType(projectKey, issueTypeName string) (*jiradata.IssueType, error) {
|
|
return GetIssueCreateMetaIssueType(j.UA, j.Endpoint, projectKey, issueTypeName)
|
|
}
|
|
|
|
func GetIssueCreateMetaIssueType(ua HttpClient, endpoint string, projectKey, issueTypeName string) (*jiradata.IssueType, error) {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue/createmeta")
|
|
uri += fmt.Sprintf("?projectKeys=%s&issuetypeNames=%s&expand=projects.issuetypes.fields", projectKey, url.QueryEscape(issueTypeName))
|
|
resp, err := ua.GetJSON(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, responseError(resp)
|
|
}
|
|
results := &jiradata.CreateMeta{}
|
|
if err := json.NewDecoder(resp.Body).Decode(results); err != nil {
|
|
return nil, err
|
|
}
|
|
for _, project := range results.Projects {
|
|
if project.Key != projectKey {
|
|
continue
|
|
}
|
|
for _, issueType := range project.IssueTypes {
|
|
if issueType.Name == issueTypeName {
|
|
return issueType, nil
|
|
}
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("project %s and IssueType %s not found", projectKey, issueTypeName)
|
|
}
|
|
|
|
type LinkIssueProvider interface {
|
|
ProvideLinkIssueRequest() *jiradata.LinkIssueRequest
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issueLink-linkIssues
|
|
func (j *Jira) LinkIssues(lip LinkIssueProvider) error {
|
|
return LinkIssues(j.UA, j.Endpoint, lip)
|
|
}
|
|
|
|
func LinkIssues(ua HttpClient, endpoint string, lip LinkIssueProvider) error {
|
|
req := lip.ProvideLinkIssueRequest()
|
|
encoded, err := json.Marshal(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
uri := URLJoin(endpoint, "rest/api/2/issueLink")
|
|
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 201 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getTransitions
|
|
func (j *Jira) GetIssueTransitions(issue string) (*jiradata.TransitionsMeta, error) {
|
|
return GetIssueTransitions(j.UA, j.Endpoint, issue)
|
|
}
|
|
|
|
func GetIssueTransitions(ua HttpClient, endpoint string, issue string) (*jiradata.TransitionsMeta, error) {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "transitions")
|
|
uri += "?expand=transitions.fields"
|
|
resp, err := ua.GetJSON(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 200 {
|
|
results := &jiradata.TransitionsMeta{}
|
|
return results, json.NewDecoder(resp.Body).Decode(results)
|
|
}
|
|
return nil, responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-doTransition
|
|
func (j *Jira) TransitionIssue(issue string, iup IssueUpdateProvider) error {
|
|
return TransitionIssue(j.UA, j.Endpoint, issue, iup)
|
|
}
|
|
|
|
func TransitionIssue(ua HttpClient, endpoint string, issue string, iup IssueUpdateProvider) error {
|
|
req := iup.ProvideIssueUpdate()
|
|
encoded, err := json.Marshal(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "transitions")
|
|
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 204 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issueLinkType-getIssueLinkTypes
|
|
func (j *Jira) GetIssueLinkTypes() (*jiradata.IssueLinkTypes, error) {
|
|
return GetIssueLinkTypes(j.UA, j.Endpoint)
|
|
}
|
|
|
|
func GetIssueLinkTypes(ua HttpClient, endpoint string) (*jiradata.IssueLinkTypes, error) {
|
|
uri := URLJoin(endpoint, "rest/api/2/issueLinkType")
|
|
resp, err := ua.GetJSON(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 200 {
|
|
results := struct {
|
|
IssueLinkTypes jiradata.IssueLinkTypes
|
|
}{
|
|
IssueLinkTypes: jiradata.IssueLinkTypes{},
|
|
}
|
|
return &results.IssueLinkTypes, json.NewDecoder(resp.Body).Decode(&results)
|
|
}
|
|
return nil, responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-addVote
|
|
func (j *Jira) IssueAddVote(issue string) error {
|
|
return IssueAddVote(j.UA, j.Endpoint, issue)
|
|
}
|
|
|
|
func IssueAddVote(ua HttpClient, endpoint string, issue string) error {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "votes")
|
|
resp, err := ua.Post(uri, "application/json", strings.NewReader("{}"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 204 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-removeVote
|
|
func (j *Jira) IssueRemoveVote(issue string) error {
|
|
return IssueRemoveVote(j.UA, j.Endpoint, issue)
|
|
}
|
|
|
|
func IssueRemoveVote(ua HttpClient, endpoint string, issue string) error {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "votes")
|
|
resp, err := ua.Delete(uri)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 204 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
type RankRequestProvider interface {
|
|
ProvideRankRequest() *jiradata.RankRequest
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/issue-rankIssues
|
|
func (j *Jira) RankIssues(rrp RankRequestProvider) error {
|
|
return RankIssues(j.UA, j.Endpoint, rrp)
|
|
}
|
|
|
|
func RankIssues(ua HttpClient, endpoint string, rrp RankRequestProvider) error {
|
|
req := rrp.ProvideRankRequest()
|
|
encoded, err := json.Marshal(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
uri := URLJoin(endpoint, "rest/agile/1.0/issue/rank")
|
|
resp, err := ua.Put(uri, "application/json", bytes.NewBuffer(encoded))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 204 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-addWatcher
|
|
func (j *Jira) IssueAddWatcher(issue, user string) error {
|
|
return IssueAddWatcher(j.UA, j.Endpoint, issue, user)
|
|
}
|
|
|
|
func IssueAddWatcher(ua HttpClient, endpoint string, issue, user string) error {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "watchers")
|
|
resp, err := ua.Post(uri, "application/json", strings.NewReader(fmt.Sprintf("%q", user)))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 204 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-addWatcher
|
|
func (j *Jira) IssueRemoveWatcher(issue, user string) error {
|
|
return IssueRemoveWatcher(j.UA, j.Endpoint, issue, user)
|
|
}
|
|
|
|
func IssueRemoveWatcher(ua HttpClient, endpoint string, issue, user string) error {
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "watchers")
|
|
uri += fmt.Sprintf("?accountId=%s", user)
|
|
resp, err := ua.Delete(uri)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 204 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
type CommentProvider interface {
|
|
ProvideComment() *jiradata.Comment
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/comment-addComment
|
|
func (j *Jira) IssueAddComment(issue string, cp CommentProvider) (*jiradata.Comment, error) {
|
|
return IssueAddComment(j.UA, j.Endpoint, issue, cp)
|
|
}
|
|
|
|
func IssueAddComment(ua HttpClient, endpoint string, issue string, cp CommentProvider) (*jiradata.Comment, error) {
|
|
req := cp.ProvideComment()
|
|
encoded, err := json.Marshal(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "comment")
|
|
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 201 {
|
|
results := jiradata.Comment{}
|
|
return &results, json.NewDecoder(resp.Body).Decode(&results)
|
|
}
|
|
return nil, responseError(resp)
|
|
}
|
|
|
|
type UserProvider interface {
|
|
ProvideUser() *jiradata.User
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-assign
|
|
func (j *Jira) IssueAssign(issue, name string) error {
|
|
return IssueAssign(j.UA, j.Endpoint, issue, name)
|
|
}
|
|
|
|
func IssueAssign(ua HttpClient, endpoint string, issue, name string) error {
|
|
// this is special, not using the jiradata.User structure
|
|
// because we need to be able to send `null` as the name param
|
|
// when we want to un-assign the issue
|
|
req := struct {
|
|
Name *string `json:"name"`
|
|
}{&name}
|
|
if name == "" {
|
|
req.Name = nil
|
|
}
|
|
|
|
encoded, err := json.Marshal(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "assignee")
|
|
resp, err := ua.Put(uri, "application/json", bytes.NewBuffer(encoded))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 204 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
func IssueAssignAccountID(ua HttpClient, endpoint string, issue, acctId string) error {
|
|
// this is special, not using the jiradata.User structure
|
|
// because we need to be able to send `null` as the name param
|
|
// when we want to un-assign the issue
|
|
req := struct {
|
|
AccountID *string `json:"accountId"`
|
|
}{&acctId}
|
|
if acctId == "" {
|
|
req.AccountID = nil
|
|
}
|
|
|
|
encoded, err := json.Marshal(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
uri := URLJoin(endpoint, "rest/api/2/issue", issue, "assignee")
|
|
resp, err := ua.Put(uri, "application/json", bytes.NewBuffer(encoded))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 204 {
|
|
return nil
|
|
}
|
|
return responseError(resp)
|
|
}
|
|
|
|
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/attachments-addAttachment
|
|
func (j *Jira) IssueAttachFile(issue, filename string, contents io.Reader) (*jiradata.ListOfAttachment, error) {
|
|
return IssueAttachFile(j.UA, j.Endpoint, issue, filename, contents)
|
|
}
|
|
|
|
func IssueAttachFile(ua HttpClient, endpoint string, issue, filename string, contents io.Reader) (*jiradata.ListOfAttachment, error) {
|
|
var buf bytes.Buffer
|
|
w := multipart.NewWriter(&buf)
|
|
formFile, err := w.CreateFormFile("file", filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_, err = io.Copy(formFile, contents)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
uri, err := url.Parse(URLJoin(endpoint, "rest/api/2/issue", issue, "attachments"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req := oreo.RequestBuilder(uri).WithMethod("POST").WithHeader(
|
|
"X-Atlassian-Token", "no-check",
|
|
).WithHeader(
|
|
"Accept", "application/json",
|
|
).WithContentType(w.FormDataContentType()).WithBody(&buf).Build()
|
|
w.Close()
|
|
|
|
resp, err := ua.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == 200 {
|
|
results := jiradata.ListOfAttachment{}
|
|
return &results, json.NewDecoder(resp.Body).Decode(&results)
|
|
}
|
|
return nil, responseError(resp)
|
|
}
|