diff --git a/README.md b/README.md index f0d1493..7e085f9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ A plugin to attach build and deployment details to a Jira issue. For information on how to use the plugin with drone there is a video [here](https://youtu.be/YIKbLeY1-gI) +This plugin was modified to extract multiple issues by changing the extractIssues function and slight changes to the file plugin.go, also was added a new argument AdditionalMessage to serve as an input variable. The AdditionalMessage variable has the purpose to contain information of other issues. + +The util_test.go file was changed to suit the modifications. + ## Building Build the plugin binary: @@ -37,6 +41,7 @@ docker run --rm \ -e PLUGIN_PIPELINE=drone \ -e PLUGIN_ENVIRONMENT=production \ -e PLUGIN_STATE=successful \ + -e PLUGIN_ADDITIONAL_MESSAGE="DRONE-43 updated the plugin" \ -w /drone/src \ -v $(pwd):/drone/src \ plugins/jira @@ -53,4 +58,4 @@ docker run --rm \ - `ENVIRONMENT_NAME` Deployment environment (optional) - `LINK` Link to deployment (optional) - `STATE` State of the deployment (optional) - +- `ADDITIONAL_MESSAGE` Additional message containing information about other issues (optional) diff --git a/plugin/plugin.go b/plugin/plugin.go index 141eb4f..88fc27a 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -14,6 +14,7 @@ import ( "net/http" "net/http/httputil" "strconv" + "strings" "time" "github.com/sirupsen/logrus" @@ -67,13 +68,15 @@ type Args struct { // connect hostname (required) ConnectHostname string `envconfig:"PLUGIN_CONNECT_HOSTNAME"` + + AdditionalMessage string `envconfig:"PLUGIN_ADDITIONAL_MESSAGE"` } // Exec executes the plugin. func Exec(ctx context.Context, args Args) error { var ( environ = toEnvironment(args) - issue = extractIssue(args) + issues = extractIssues(args) state = toState(args) version = toVersion(args) deeplink = toLink(args) @@ -89,13 +92,14 @@ func Exec(ctx context.Context, args Args) error { WithField("state", state). WithField("version", version) - if issue == "" { - logger.Debugln("cannot find issue number") - return errors.New("failed to extract issue number") + if len(issues) == 0 { + logger.Debugln("cannot find issues") + return errors.New("failed to extract issues") } - logger = logger.WithField("issue", issue) - logger.Debugln("successfully extraced issue number") + issues = removeDuplicates(issues) + logger = logger.WithField("issues", strings.Join(issues, ",")) + logger.Debugln("successfully extracted all issues") deploymentPayload := DeploymentPayload{ Deployments: []*Deployment{ @@ -105,7 +109,7 @@ func Exec(ctx context.Context, args Args) error { Associations: []Association{ { Associationtype: "issueIdOrKeys", - Values: []string{issue}, + Values: issues, }, }, Displayname: strconv.Itoa(args.Build.Number), @@ -135,7 +139,7 @@ func Exec(ctx context.Context, args Args) error { URL: deeplink, LastUpdated: time.Now(), PipelineID: args.Name, - IssueKeys: []string{issue}, + IssueKeys: issues, State: state, UpdateSequenceNumber: args.Build.Number, }, @@ -198,7 +202,7 @@ func Exec(ctx context.Context, args Args) error { } } // only create card if the state is successful - ticketLink := fmt.Sprintf("https://%s.atlassian.net/browse/%s", args.Instance, issue) + ticketLink := fmt.Sprintf("https://%s.atlassian.net/browse/%s", args.Instance, issues) cardData := Card{ Pipeline: args.Name, Instance: args.Instance, @@ -394,3 +398,21 @@ func lookupTenant(tenant string) (*Tenant, error) { err = json.NewDecoder(res.Body).Decode(out) return out, err } + +func removeDuplicates(list []string) []string { + // Create an empty map to store seen elements + seen := make(map[string]bool) + + // Initialize a new list to store unique elements + uniqueList := []string{} + + for _, element := range list { + // Check if the element is already seen + if !seen[element] { + seen[element] = true + uniqueList = append(uniqueList, element) + } + } + + return uniqueList + } \ No newline at end of file diff --git a/plugin/util.go b/plugin/util.go index 71f7a5b..b9be2f0 100644 --- a/plugin/util.go +++ b/plugin/util.go @@ -13,16 +13,19 @@ import ( // helper function to extract the issue number from // the commit details, including the commit message, // branch and pull request title. -func extractIssue(args Args) string { - return regexp.MustCompile(args.Project + "\\-\\d+").FindString( - fmt.Sprintln( - args.Commit.Message, - args.PullRequest.Title, - args.Commit.Source, - args.Commit.Target, - args.Commit.Branch, - ), - ) +func extractIssues(args Args) []string { + + regex := regexp.MustCompile(args.Project+"-\\d+") + matches := regex.FindAllString(fmt.Sprintln( + args.AdditionalMessage, + args.Commit.Message, + args.PullRequest.Title, + args.Commit.Source, + args.Commit.Target, + args.Commit.Branch, + ), -1) + + return matches } // helper function determines the pipeline state. diff --git a/plugin/util_test.go b/plugin/util_test.go index a270136..24b5570 100644 --- a/plugin/util_test.go +++ b/plugin/util_test.go @@ -6,42 +6,73 @@ package plugin import "testing" -func TestExtractIssue(t *testing.T) { - tests := []struct { - text string - want string - }{ - { - text: "TEST-1 this is a test", - want: "TEST-1", - }, - { - text: "suffix [TEST-123]", - want: "TEST-123", - }, - { - text: "[TEST-123] prefix", - want: "TEST-123", - }, - { - text: "TEST-123 prefix", - want: "TEST-123", - }, - { - text: "feature/TEST-123", - want: "TEST-123", - }, - { - text: "no issue", - want: "", - }, - } - for _, test := range tests { - var args Args - args.Commit.Message = test.text - args.Project = "TEST" - if got, want := extractIssue(args), test.want; got != want { - t.Errorf("Got issue number %v, want %v", got, want) - } - } +func compareSlices(s1, s2 []string) bool { + if len(s2) < 1 || len(s1) < len(s2){ + return false + } + + for i := 0; i < len(s1); i++ { + found := true + for j := 0; j < len(s2); j++ { + if s1[i+j] != s2[j] { + found = false + break + } + } + if found { + return true + } + } + return false +} + +func TestExtractIssues(t *testing.T) { + tests := []struct { + text string + want []string + }{ + { + text: "TEST-1 this is a test", + want: []string{"TEST-1"}, + }, + { + text: "suffix [TEST-123] [TEST-234]", + want: []string{"TEST-123", "TEST-234"}, + }, + { + text: "[TEST-123] prefix [TEST-456]", + want: []string{"TEST-123"}, + }, + { + text: "Multiple issues: TEST-123, TEST-234, TEST-456", + want: []string{"TEST-123", "TEST-234", "TEST-456"}, + }, + { + text: "feature/TEST-123 [TEST-456] and [TEST-789]", + want: []string{"TEST-123", "TEST-456", "TEST-789"}, + }, + { + text: "TEST-123 TEST-456 TEST-789", + want: []string{"TEST-123", "TEST-789"}, + }, + { + text: "no issue", + want: []string{}, + }, + } + + t.Errorf("TESTING") + + for _, test := range tests { + var args Args + args.Commit.Message = test.text + args.Project = "TEST" + got := extractIssues(args) + t.Errorf("TEXT:%v || WANT: %s", got, test.want) + t.Errorf(" %v", compareSlices(got, test.want)) + if !compareSlices(got, test.want) { + t.Errorf("Got issues %v, want %v", got, test.want) + } + } + }