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

feat: [CI-11708] - Extract multiple Issues #29

Merged
merged 12 commits into from
Nov 17, 2024
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ drone-jira
NOTES*
output.json
.vscode/
.idea/
13 changes: 8 additions & 5 deletions plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"net/http"
"net/http/httputil"
"strconv"
"strings"
"time"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -101,18 +102,20 @@ func Exec(ctx context.Context, args Args) error {
WithField("environment Type", environmentType).
WithField("environment ID", environmentID)

//check if PLUGIN_ISSUEKEYS is provided
// check if PLUGIN_ISSUEKEYS is provided
if len(args.IssueKeys) > 0 {
logger.Debugln("Provided issue keys are :", args.IssueKeys)
issues = args.IssueKeys
} else {
// fallback to extracting from commit if no issue keys are passed
var issue string = extractIssue(args)
if issue == "" {
issues = extractIssues(args)
if len(issues) == 0 {
logger.Debugln("cannot find issue number")
return errors.New("failed to extract issue number")
}
issues = []string{issue} // add the single issue here for consistency
}
logger = logger.WithField("issues", strings.Join(issues, ","))
logger.Debugln("successfully extracted all issues")

commitMessage := args.Commit.Message
if len(commitMessage) > 255 {
Expand Down Expand Up @@ -433,7 +436,7 @@ func getCloudID(instance, cloudID string) (string, error) {
return tenant.ID, nil
}
if cloudID == "" {
return "", fmt.Errorf("cloud id is empty. specify the cloud id or instance name")
return "", fmt.Errorf("Cloud id is empty. Specify the cloud id or instance name")
}
return cloudID, nil
}
Expand Down
40 changes: 30 additions & 10 deletions plugin/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ 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.Commit.Message,
args.PullRequest.Title,
args.Commit.Source,
args.Commit.Target,
args.Commit.Branch,
), -1)

return removeDuplicates(matches)
}

// helper function determines the pipeline state.
Expand Down Expand Up @@ -153,3 +155,21 @@ func toStateEnum(s string) string {
return "unknown"
}
}

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
}
93 changes: 72 additions & 21 deletions plugin/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,94 @@ package plugin

import "testing"

func TestExtractIssue(t *testing.T) {
// compareSlices checks if s2 is a subset of s1
func compareSlices(s1, s2 []string) bool {
// Special case: if both slices are empty, they're equal
if len(s1) == 0 && len(s2) == 0 {
return true
}

// If s2 is empty but s1 isn't, or s1 is shorter than s2, they can't match
if len(s2) == 0 || len(s1) < len(s2) {
return false
}

// For each possible starting position in s1
for i := 0; i <= len(s1)-len(s2); i++ {
allMatch := true
// Try to match all elements of s2 starting at position i
for j := 0; j < len(s2); j++ {
if s1[i+j] != s2[j] {
allMatch = false
break
}
}
if allMatch {
return true
}
}
return false
}

func TestExtractIssues(t *testing.T) {
tests := []struct {
name string
text string
want string
want []string
}{
{
name: "Single issue",
text: "TEST-1 this is a test",
want: "TEST-1",
want: []string{"TEST-1"},
},
{
text: "suffix [TEST-123]",
want: "TEST-123",
name: "Two issues in brackets",
text: "suffix [TEST-123] [TEST-234]",
want: []string{"TEST-123", "TEST-234"},
},
{
text: "[TEST-123] prefix",
want: "TEST-123",
name: "Two issues, one in prefix",
text: "[TEST-123] prefix [TEST-456]",
want: []string{"TEST-123", "TEST-456"},
},
{
text: "TEST-123 prefix",
want: "TEST-123",
name: "Multiple comma-separated issues",
text: "Multiple issues: TEST-123, TEST-234, TEST-456",
want: []string{"TEST-123", "TEST-234", "TEST-456"},
},
{
text: "feature/TEST-123",
want: "TEST-123",
name: "Mixed format issues",
text: "feature/TEST-123 [TEST-456] and [TEST-789]",
want: []string{"TEST-123", "TEST-456", "TEST-789"},
},
{
name: "Space-separated issues",
text: "TEST-123 TEST-456 TEST-789",
want: []string{"TEST-123", "TEST-456", "TEST-789"},
},
{
name: "No issues",
text: "no issue",
want: "",
want: []string{},
},
}
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)
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var args Args
args.Commit.Message = tt.text
args.Project = "TEST"

got := extractIssues(args)

if !compareSlices(got, tt.want) {
t.Logf("\n Test case '%s' FAILED", tt.name)
t.Errorf("\ngot: %v\nwant: %v", got, tt.want)
} else {
t.Logf("\n Test case '%s' PASSED", tt.name)
t.Logf("\ngot: %v\nwant: %v", got, tt.want)
}
})
}
}

Expand Down Expand Up @@ -89,7 +140,7 @@ func TestToEnvironmentId(t *testing.T) {
{
name: "Empty EnvironmentId",
args: Args{EnvironmentId: ""},
expectedOutput: "production", // Updated to match the default value of "production"
expectedOutput: "production", // Updated to match the default value of "production"
},
}

Expand Down Expand Up @@ -118,7 +169,7 @@ func TestToEnvironmentType(t *testing.T) {
{
name: "Empty EnvironmentType",
args: Args{EnvironmentType: ""},
expectedOutput: "production", // Updated to match the default value of "production"
expectedOutput: "production", // Updated to match the default value of "production"
},
}

Expand Down