diff --git a/pkg/cmd/issue/edit/edit.go b/pkg/cmd/issue/edit/edit.go index 0361fead3..44358ebdc 100644 --- a/pkg/cmd/issue/edit/edit.go +++ b/pkg/cmd/issue/edit/edit.go @@ -173,21 +173,13 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman if flags.Changed("type") { opts.Editable.IssueType.Edited = true } - if flags.Changed("set-parent") || opts.RemoveParent { - opts.Editable.Parent.Edited = true - if opts.RemoveParent { - opts.Editable.Parent.Value = "" - } else { - opts.Editable.Parent.Value = opts.SetParent - } - } - // Sub-issue and relationship flags are outside the Editable pattern - // but still need to prevent interactive mode. - hasRelationshipFlags := len(opts.AddSubIssues) > 0 || len(opts.RemoveSubIssues) > 0 || + hasRelationshipFlags := flags.Changed("set-parent") || opts.RemoveParent || + len(opts.AddSubIssues) > 0 || len(opts.RemoveSubIssues) > 0 || len(opts.AddBlockedBy) > 0 || len(opts.RemoveBlockedBy) > 0 || len(opts.AddBlocking) > 0 || len(opts.RemoveBlocking) > 0 + // Drop into interactive mode only if the user passed no edit flags at all. if !opts.Editable.Dirty() && !hasRelationshipFlags { opts.Interactive = true } @@ -250,7 +242,6 @@ func editRun(opts *EditOptions) error { // Prompt the user which fields they'd like to edit. editable := opts.Editable editable.IssueType.Allowed = true - editable.Parent.Allowed = true if opts.Interactive { err = opts.FieldsToEditSurvey(opts.Prompter, &editable) if err != nil { @@ -297,7 +288,7 @@ func editRun(opts *EditOptions) error { if editable.IssueType.Edited { lookupFields = append(lookupFields, "issueType") } - if editable.Parent.Edited || opts.RemoveParent { + if opts.SetParent != "" || opts.RemoveParent { lookupFields = append(lookupFields, "parent") } @@ -371,9 +362,6 @@ func editRun(opts *EditOptions) error { if issue.IssueType != nil { editable.IssueType.Default = issue.IssueType.Name } - if issue.Parent != nil { - editable.Parent.Default = fmt.Sprintf("#%d", issue.Parent.Number) - } // Allow interactive prompts for one issue; failed earlier if multiple issues specified. if opts.Interactive { @@ -400,7 +388,7 @@ func editRun(opts *EditOptions) error { return } - mutations, err := deferredUpdateIssueOptions(apiClient, baseRepo, issue, opts, &editable, issueTypeID) + mutations, err := deferredUpdateIssueOptions(apiClient, baseRepo, issue, opts, issueTypeID) if err != nil { failedIssueChan <- fmt.Sprintf("failed to update %s: %s", issue.URL, err) return @@ -465,7 +453,7 @@ func lookupIssueTypeID(editable *prShared.Editable) (string, error) { return id, nil } -func deferredUpdateIssueOptions(client *api.Client, baseRepo ghrepo.Interface, issue *api.Issue, editOpts *EditOptions, editable *prShared.Editable, issueTypeID string) (api.DeferredUpdateIssueOptions, error) { +func deferredUpdateIssueOptions(client *api.Client, baseRepo ghrepo.Interface, issue *api.Issue, editOpts *EditOptions, issueTypeID string) (api.DeferredUpdateIssueOptions, error) { updateOpts := api.DeferredUpdateIssueOptions{ IssueID: issue.ID, Hostname: baseRepo.RepoHost(), @@ -473,18 +461,16 @@ func deferredUpdateIssueOptions(client *api.Client, baseRepo ghrepo.Interface, i ReplaceExistingParent: true, } - if editable.Parent.Edited { - if editable.Parent.Value == "" { - if issue.Parent != nil { - updateOpts.RemoveParentID = issue.Parent.ID - } - } else { - parentID, err := issueShared.ResolveIssueRef(client, baseRepo, editable.Parent.Value) - if err != nil { - return updateOpts, fmt.Errorf("resolving --set-parent reference %q: %w", editable.Parent.Value, err) - } - updateOpts.ParentID = parentID + if editOpts.RemoveParent { + if issue.Parent != nil { + updateOpts.RemoveParentID = issue.Parent.ID } + } else if editOpts.SetParent != "" { + parentID, err := issueShared.ResolveIssueRef(client, baseRepo, editOpts.SetParent) + if err != nil { + return updateOpts, fmt.Errorf("resolving --set-parent reference %q: %w", editOpts.SetParent, err) + } + updateOpts.ParentID = parentID } for _, ref := range editOpts.AddSubIssues { diff --git a/pkg/cmd/issue/edit/edit_test.go b/pkg/cmd/issue/edit/edit_test.go index 094a6bdda..086244047 100644 --- a/pkg/cmd/issue/edit/edit_test.go +++ b/pkg/cmd/issue/edit/edit_test.go @@ -303,12 +303,6 @@ func TestNewCmdEdit(t *testing.T) { output: EditOptions{ IssueNumbers: []int{23}, SetParent: "100", - Editable: prShared.Editable{ - Parent: prShared.EditableString{ - Value: "100", - Edited: true, - }, - }, }, }, { @@ -317,12 +311,6 @@ func TestNewCmdEdit(t *testing.T) { output: EditOptions{ IssueNumbers: []int{23}, RemoveParent: true, - Editable: prShared.Editable{ - Parent: prShared.EditableString{ - Value: "", - Edited: true, - }, - }, }, }, { @@ -913,60 +901,13 @@ func Test_editRun(t *testing.T) { }, stdout: "https://github.com/OWNER/REPO/issue/123\n", }, - { - name: "interactive edit parent prompt", - input: &EditOptions{ - Detector: &fd.EnabledDetectorMock{}, - IssueNumbers: []int{123}, - Interactive: true, - FieldsToEditSurvey: func(_ prShared.EditPrompter, eo *prShared.Editable) error { - // Verify the survey is allowed to offer Parent as an option for issue edit. - assert.True(t, eo.Parent.Allowed) - eo.Parent.Edited = true - return nil - }, - EditFieldsSurvey: func(_ prShared.EditPrompter, eo *prShared.Editable, _ string) error { - eo.Parent.Value = "100" - return nil - }, - FetchOptions: func(_ *api.Client, _ ghrepo.Interface, _ *prShared.Editable, _ gh.ProjectsV1Support) error { - return nil - }, - DetermineEditor: func() (string, error) { return "vim", nil }, - }, - httpStubs: func(t *testing.T, reg *httpmock.Registry) { - mockIssueGet(t, reg) - reg.Register( - httpmock.GraphQL(`query IssueNodeID\b`), - httpmock.StringResponse(` - { "data": { "repository": { "issue": { "id": "PARENT_100_ID" } } } } - `), - ) - reg.Register( - httpmock.GraphQL(`mutation AddSubIssue\b`), - httpmock.GraphQLMutation(` - { "data": { "addSubIssue": { "issue": { "id": "PARENT_100_ID" } } } }`, - func(inputs map[string]interface{}) { - assert.Equal(t, "PARENT_100_ID", inputs["issueId"]) - assert.Equal(t, "123", inputs["subIssueId"]) - assert.Equal(t, true, inputs["replaceParent"]) - }), - ) - }, - stdout: "https://github.com/OWNER/REPO/issue/123\n", - }, { name: "edit set parent", input: &EditOptions{ Detector: &fd.EnabledDetectorMock{}, IssueNumbers: []int{123}, Interactive: false, - Editable: prShared.Editable{ - Parent: prShared.EditableString{ - Value: "100", - Edited: true, - }, - }, + SetParent: "100", FetchOptions: func(_ *api.Client, _ ghrepo.Interface, _ *prShared.Editable, _ gh.ProjectsV1Support) error { return nil }, @@ -999,12 +940,6 @@ func Test_editRun(t *testing.T) { IssueNumbers: []int{123}, Interactive: false, RemoveParent: true, - Editable: prShared.Editable{ - Parent: prShared.EditableString{ - Value: "", - Edited: true, - }, - }, FetchOptions: func(_ *api.Client, _ ghrepo.Interface, _ *prShared.Editable, _ gh.ProjectsV1Support) error { return nil }, @@ -1500,15 +1435,8 @@ func Test_editRun_crossHostRelationshipRefs(t *testing.T) { input *EditOptions }{ { - name: "set parent", - input: &EditOptions{ - Editable: prShared.Editable{ - Parent: prShared.EditableString{ - Value: crossHostURL, - Edited: true, - }, - }, - }, + name: "set parent", + input: &EditOptions{SetParent: crossHostURL}, }, { name: "add sub-issue", diff --git a/pkg/cmd/pr/shared/editable.go b/pkg/cmd/pr/shared/editable.go index 2b6bbe15c..84fb8748c 100644 --- a/pkg/cmd/pr/shared/editable.go +++ b/pkg/cmd/pr/shared/editable.go @@ -23,7 +23,6 @@ type Editable struct { Milestone EditableString IssueType EditableString IssueTypeNameToID map[string]string - Parent EditableString Metadata api.RepoMetadataResult // TODO ApiActorsSupported @@ -80,8 +79,7 @@ func (e Editable) Dirty() bool { e.Labels.Edited || e.Projects.Edited || e.Milestone.Edited || - e.IssueType.Edited || - e.Parent.Edited + e.IssueType.Edited } func (e Editable) TitleValue() *string { @@ -298,7 +296,6 @@ func (e *Editable) Clone() Editable { Milestone: e.Milestone.clone(), IssueType: e.IssueType.clone(), IssueTypeNameToID: e.IssueTypeNameToID, - Parent: e.Parent.clone(), ApiActorsSupported: e.ApiActorsSupported, // Shallow copy since no mutation. Metadata: e.Metadata, @@ -463,12 +460,6 @@ func EditFieldsSurvey(p EditPrompter, editable *Editable, editorCommand string) editable.IssueType.Value = editable.IssueType.Options[selected] } } - if editable.Parent.Edited { - editable.Parent.Value, err = p.Input("Parent (issue number or URL, leave empty to remove)", editable.Parent.Default) - if err != nil { - return err - } - } confirm, err := p.Confirm("Submit?", true) if err != nil { return err @@ -498,9 +489,6 @@ func FieldsToEditSurvey(p EditPrompter, editable *Editable) error { if editable.IssueType.Allowed { opts = append(opts, "Type") } - if editable.Parent.Allowed { - opts = append(opts, "Parent") - } opts = append(opts, "Projects", "Milestone") results, err := multiSelectSurvey(p, "What would you like to edit?", []string{}, opts) if err != nil { @@ -525,9 +513,6 @@ func FieldsToEditSurvey(p EditPrompter, editable *Editable) error { if contains(results, "Type") { editable.IssueType.Edited = true } - if contains(results, "Parent") { - editable.Parent.Edited = true - } if contains(results, "Projects") { editable.Projects.Edited = true } diff --git a/pkg/cmd/pr/shared/survey_test.go b/pkg/cmd/pr/shared/survey_test.go index 5b84548a2..efe9785b0 100644 --- a/pkg/cmd/pr/shared/survey_test.go +++ b/pkg/cmd/pr/shared/survey_test.go @@ -262,10 +262,10 @@ func TestTitleSurvey(t *testing.T) { } func TestFieldsToEditSurvey_IssueOnlyFields(t *testing.T) { - t.Run("without Allowed flags omits Type and Parent", func(t *testing.T) { + t.Run("without Allowed flag omits Type", func(t *testing.T) { pm := prompter.NewMockPrompter(t) pm.RegisterMultiSelect("What would you like to edit?", []string{}, - // Type and Parent should NOT appear here + // Type should NOT appear here []string{"Title", "Body", "Assignees", "Labels", "Projects", "Milestone"}, func(_ string, _, _ []string) ([]int, error) { return []int{0}, nil @@ -277,21 +277,19 @@ func TestFieldsToEditSurvey_IssueOnlyFields(t *testing.T) { assert.True(t, editable.Title.Edited) }) - t.Run("with Allowed flags includes Type and Parent", func(t *testing.T) { + t.Run("with Allowed flag includes Type", func(t *testing.T) { pm := prompter.NewMockPrompter(t) pm.RegisterMultiSelect("What would you like to edit?", []string{}, - // Type and Parent should appear between Labels and Projects - []string{"Title", "Body", "Assignees", "Labels", "Type", "Parent", "Projects", "Milestone"}, + // Type should appear between Labels and Projects + []string{"Title", "Body", "Assignees", "Labels", "Type", "Projects", "Milestone"}, func(_ string, _, _ []string) ([]int, error) { - return []int{4, 5}, nil // select Type and Parent + return []int{4}, nil // select Type }) editable := &Editable{} editable.IssueType.Allowed = true - editable.Parent.Allowed = true err := FieldsToEditSurvey(pm, editable) require.NoError(t, err) assert.True(t, editable.IssueType.Edited) - assert.True(t, editable.Parent.Edited) }) }