From 3f1e8fe1ab1c5d8cb9703be8037babdf1c62c8a6 Mon Sep 17 00:00:00 2001 From: Alex Pavel Date: Wed, 10 Jul 2024 22:11:54 +0000 Subject: [PATCH] server: fix assignee race condition Fixes a bug with handling jira's auto-assign functionality that conflicts with the plugin's assignee cloning. --- cmd/jira-lifecycle-plugin/server.go | 24 +++++++++++++++--------- cmd/jira-lifecycle-plugin/server_test.go | 10 ++++++++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/cmd/jira-lifecycle-plugin/server.go b/cmd/jira-lifecycle-plugin/server.go index 06e9983..57b7095 100644 --- a/cmd/jira-lifecycle-plugin/server.go +++ b/cmd/jira-lifecycle-plugin/server.go @@ -1894,22 +1894,28 @@ func createCherryPickBug(jc jiraclient.Client, bug *jira.Issue, branch string, o return clone.Key, fmt.Sprintf("Detected clone of %s with correct target version. Will retitle the PR to link to the clone.", oldLink), nil } } + // clone the bug in order to not lose fields during backports, which reuse *bug + bugCopy := *bug + copyFields := *bug.Fields + bugCopy.Fields = ©Fields // TODO: these fields can cause the clone to fail if not manually removed. It may be better to // perform some recursion when cloning issues, as these only error when everything else is correct... - delete(bug.Fields.Unknowns, "environment") - delete(bug.Fields.Unknowns, "customfield_12318341") + delete(bugCopy.Fields.Unknowns, "environment") + delete(bugCopy.Fields.Unknowns, "customfield_12318341") // This is the sprint field; sprints are handled by a custom plugin, and the data given to us via // GetIssue is invalid for setting the field ourselves - sprintField := bug.Fields.Unknowns[helpers.SprintField] - delete(bug.Fields.Unknowns, helpers.SprintField) - releaseNoteType := bug.Fields.Unknowns[helpers.ReleaseNoteTypeField] - releaseNoteText := bug.Fields.Unknowns[helpers.ReleaseNoteTextField] + sprintField := bugCopy.Fields.Unknowns[helpers.SprintField] + delete(bugCopy.Fields.Unknowns, helpers.SprintField) + releaseNoteType := bugCopy.Fields.Unknowns[helpers.ReleaseNoteTypeField] + releaseNoteText := bugCopy.Fields.Unknowns[helpers.ReleaseNoteTextField] if len(options.IgnoreCloneLabels) != 0 { - labelsSet := sets.New[string](bug.Fields.Labels...) + labelsSet := sets.New[string](bugCopy.Fields.Labels...) labelsSet.Delete(options.IgnoreCloneLabels...) - bug.Fields.Labels = labelsSet.UnsortedList() + bugCopy.Fields.Labels = labelsSet.UnsortedList() } - clone, err := jc.CloneIssue(bug) + // unset assignee so we can more easily check when jira's internal auto-assign completes + bugCopy.Fields.Assignee = nil + clone, err := jc.CloneIssue(&bugCopy) if err != nil { log.WithError(err).Debugf("Failed to clone bug %+v", bug) return "", "", errors.New(formatError("cloning bug for cherrypick", jc.JiraURL(), bug.Key, err)) diff --git a/cmd/jira-lifecycle-plugin/server_test.go b/cmd/jira-lifecycle-plugin/server_test.go index b99e45a..b33b04e 100644 --- a/cmd/jira-lifecycle-plugin/server_test.go +++ b/cmd/jira-lifecycle-plugin/server_test.go @@ -47,7 +47,13 @@ func (f *fakeJiraClient) CloneIssue(issue *jira.Issue) (*jira.Issue, error) { newFields := *issue.Fields newIssue.Fields = &newFields newIssue.Fields.IssueLinks = nil - return jiraclient.CloneIssue(f, &newIssue) + clonedIssue, err := jiraclient.CloneIssue(f, &newIssue) + if err != nil { + return clonedIssue, err + } + // simulate auto-assignee plugin for jira + clonedIssue.Fields.Assignee = &jira.User{Name: "defaultAssignee"} + return clonedIssue, err } func TestHandle(t *testing.T) { @@ -2213,7 +2219,7 @@ In response to [this](https://github.com/org/repo/pull/1): Instructions for interacting with me using PR comments are available [here](https://prow.ci.openshift.org/command-help?repo=org%2Frepo). If you have questions or suggestions related to my behavior, please file an issue against the [openshift-eng/jira-lifecycle-plugin](https://github.com/openshift-eng/jira-lifecycle-plugin/issues/new) repository. `, expectedIssues: []*jira.Issue{{ID: "3", Key: "OCPBUGS-125", Fields: &jira.IssueFields{ - Assignee: &jira.User{Name: "testUser"}, + Assignee: &jira.User{Name: "defaultAssignee"}, Description: "This is a clone of issue OCPBUGS-123. The following is the description of the original issue: \n---\n", Status: &jira.Status{Name: "CLOSED"}, Comments: &jira.Comments{Comments: []*jira.Comment{{