Skip to content

Commit

Permalink
[GH-865]: Solved the bug: Jira issues cannot be created anymore with …
Browse files Browse the repository at this point in the history
…Jira Server/Datacenter 9.x (#881)
  • Loading branch information
Nityanand13 authored Jan 24, 2023
1 parent 4872b3b commit 94aee50
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 545 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.13

require (
github.com/andygrunwald/go-jira v1.10.0
github.com/blang/semver/v4 v4.0.0
github.com/dghubble/oauth1 v0.5.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gorilla/mux v1.8.0
Expand Down
2 changes: 1 addition & 1 deletion server/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ type IssueService interface {
AddAttachment(api plugin.API, issueKey, fileID string, maxSize utils.ByteSize) (mattermostName, jiraName, mime string, err error)
AddComment(issueKey string, comment *jira.Comment) (*jira.Comment, error)
DoTransition(issueKey, transitionID string) error
GetCreateMeta(*jira.GetQueryOptions) (*jira.CreateMetaInfo, error)
GetCreateMetaInfo(*jira.GetQueryOptions) (*jira.CreateMetaInfo, error)
GetTransitions(issueKey string) ([]jira.Transition, error)
UpdateAssignee(issueKey string, user *jira.User) error
UpdateComment(issueKey string, comment *jira.Comment) (*jira.Comment, error)
Expand Down
4 changes: 2 additions & 2 deletions server/client_cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ func newCloudClient(jiraClient *jira.Client) Client {
}
}

// GetCreateMeta returns the metadata needed to implement the UI and validation of
// GetCreateMetaInfo returns the metadata needed to implement the UI and validation of
// creating new Jira issues.
func (client jiraCloudClient) GetCreateMeta(options *jira.GetQueryOptions) (*jira.CreateMetaInfo, error) {
func (client jiraCloudClient) GetCreateMetaInfo(options *jira.GetQueryOptions) (*jira.CreateMetaInfo, error) {
cimd, resp, err := client.Jira.Issue.GetCreateMetaWithOptions(options)
if err != nil {
if resp == nil {
Expand Down
119 changes: 115 additions & 4 deletions server/client_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@
package main

import (
"fmt"
"net/http"

jira "github.com/andygrunwald/go-jira"
"github.com/blang/semver/v4"
"github.com/pkg/errors"
)

const (
APIEndpointGetServerInfo = "rest/api/2/serverInfo"
APIEndpointCreateIssueMeta = "rest/api/2/issue/createmeta/"
JiraVersionWithOldIssueAPIBreaking = "9.0.0"
)

type jiraServerClient struct {
JiraClient
}
Expand All @@ -22,10 +30,113 @@ func newServerClient(jiraClient *jira.Client) Client {
}
}

// GetCreateMeta returns the metadata needed to implement the UI and validation of
type ProjectIssueInfo struct {
Values []*jira.MetaIssueType `json:"values"`
}

type FieldInfo struct {
Values []map[string]interface{} `json:"values"`
}

type JiraServerVersionInfo struct {
Version string `json:"version"`
}

// GetIssueInfo returns the issues information based on project id.
func (client jiraServerClient) GetIssueInfo(projectID string) (*ProjectIssueInfo, *jira.Response, error) {
apiEndpoint := fmt.Sprintf("%s%s/issuetypes", APIEndpointCreateIssueMeta, projectID)
req, err := client.Jira.NewRequest(http.MethodGet, apiEndpoint, nil)
if err != nil {
return nil, nil, err
}

issues := ProjectIssueInfo{}
response, err := client.Jira.Do(req, &issues)
return &issues, response, err
}

func (client jiraServerClient) GetProjectInfoForPivotJiraVersion(options *jira.GetQueryOptions) (*jira.CreateMetaInfo, *jira.Response, error) {
var issueInfo *ProjectIssueInfo
var req *http.Request

projectList, resp, err := client.Jira.Project.ListWithOptions(options)
meta := new(jira.CreateMetaInfo)

if err != nil {
return nil, resp, errors.Wrap(err, "failed to list projects")
}

for _, proj := range *projectList {
meta.Expand = proj.Expand
issueInfo, resp, err = client.GetIssueInfo(proj.ID)
if err != nil {
break
}

for _, issueType := range issueInfo.Values {
apiEndpoint := fmt.Sprintf("%s%s/issuetypes/%s", APIEndpointCreateIssueMeta, proj.ID, issueType.Id)
req, err = client.Jira.NewRequest(http.MethodGet, apiEndpoint, nil)
if err != nil {
break
}

fieldInfo := FieldInfo{}
resp, err = client.Jira.Do(req, &fieldInfo)
if err != nil {
break
}

fieldMap := make(map[string]interface{})
for _, fieldValue := range fieldInfo.Values {
fieldMap[fmt.Sprintf("%v", fieldValue["fieldId"])] = fieldValue
}
issueType.Fields = fieldMap
}
project := &jira.MetaProject{
Expand: proj.Expand,
Self: proj.Self,
Id: proj.ID,
Key: proj.Key,
Name: proj.Name,
IssueTypes: issueInfo.Values,
}

meta.Projects = append(meta.Projects, project)
}
return meta, resp, err
}

func (client jiraServerClient) GetProjectInfo(currentVersion, pivotVersion semver.Version, options *jira.GetQueryOptions) (*jira.CreateMetaInfo, *jira.Response, error) {
if currentVersion.LT(pivotVersion) {
return client.Jira.Issue.GetCreateMetaWithOptions(options)
}
return client.GetProjectInfoForPivotJiraVersion(options)
}

// GetCreateMetaInfo returns the metadata needed to implement the UI and validation of
// creating new Jira issues.
func (client jiraServerClient) GetCreateMeta(options *jira.GetQueryOptions) (*jira.CreateMetaInfo, error) {
cimd, resp, err := client.Jira.Issue.GetCreateMetaWithOptions(options)
func (client jiraServerClient) GetCreateMetaInfo(options *jira.GetQueryOptions) (*jira.CreateMetaInfo, error) {
v := new(JiraServerVersionInfo)
req, err := client.Jira.NewRequest(http.MethodGet, APIEndpointGetServerInfo, nil)
if err != nil {
return nil, err
}

if _, err = client.Jira.Do(req, v); err != nil {
return nil, errors.Wrap(err, "failed to fetch Jira server version")
}

currentVersion, err := semver.Make(v.Version)
if err != nil {
return nil, errors.Wrap(err, "error while parsing version")
}

pivotVersion, err := semver.Make(JiraVersionWithOldIssueAPIBreaking)
if err != nil {
return nil, errors.Wrap(err, "error while parsing version")
}

info, resp, err := client.GetProjectInfo(currentVersion, pivotVersion, options)
if err != nil {
if resp == nil {
return nil, err
Expand All @@ -36,7 +147,7 @@ func (client jiraServerClient) GetCreateMeta(options *jira.GetQueryOptions) (*ji
}
return nil, RESTError{err, resp.StatusCode}
}
return cimd, nil
return info, nil
}

// SearchUsersAssignableToIssue finds all users that can be assigned to an issue.
Expand Down
2 changes: 1 addition & 1 deletion server/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestEndpointNameFromRequest(t *testing.T) {
{"UpdateComment", "https://hostname/2/issue/XYZ-1234/comment/XXX", "PUT", "api/jira/2/issue/comment/PUT"},
{"SearchIssues", "https://hostname/2/search", "GET", "api/jira/2/search/GET"},
{"DoTransition", "https://hostname/2/issue/XYZ-4321/transitions", "POST", "api/jira/2/issue/transitions/POST"},
{"GetCreateMeta", "https://hostname/2/issue/createmeta", "GET", "api/jira/2/issue/createmeta/GET"},
{"GetCreateMetaInfo", "https://hostname/2/issue/createmeta", "GET", "api/jira/2/issue/createmeta/GET"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion server/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ func (p *Plugin) GetCreateIssueMetadataForProjects(instanceID, mattermostUserID
return nil, err
}

return client.GetCreateMeta(&jira.GetQueryOptions{
return client.GetCreateMetaInfo(&jira.GetQueryOptions{
Expand: "projects.issuetypes.fields",
ProjectKeys: projectKeys,
})
Expand Down
Loading

0 comments on commit 94aee50

Please sign in to comment.