mirror of https://gitlab.com/gitlab-org/cli.git
feat: add incident note command
This commit is contained in:
parent
1f8464b403
commit
3c6c7b097e
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
incidentCloseCmd "gitlab.com/gitlab-org/cli/commands/incident/close"
|
incidentCloseCmd "gitlab.com/gitlab-org/cli/commands/incident/close"
|
||||||
incidentListCmd "gitlab.com/gitlab-org/cli/commands/incident/list"
|
incidentListCmd "gitlab.com/gitlab-org/cli/commands/incident/list"
|
||||||
|
incidentNoteCmd "gitlab.com/gitlab-org/cli/commands/incident/note"
|
||||||
incidentReopenCmd "gitlab.com/gitlab-org/cli/commands/incident/reopen"
|
incidentReopenCmd "gitlab.com/gitlab-org/cli/commands/incident/reopen"
|
||||||
incidentSubscribeCmd "gitlab.com/gitlab-org/cli/commands/incident/subscribe"
|
incidentSubscribeCmd "gitlab.com/gitlab-org/cli/commands/incident/subscribe"
|
||||||
incidentUnsubscribeCmd "gitlab.com/gitlab-org/cli/commands/incident/unsubscribe"
|
incidentUnsubscribeCmd "gitlab.com/gitlab-org/cli/commands/incident/unsubscribe"
|
||||||
|
@ -34,6 +35,7 @@ func NewCmdIncident(f *cmdutils.Factory) *cobra.Command {
|
||||||
cmdutils.EnableRepoOverride(incidentCmd, f)
|
cmdutils.EnableRepoOverride(incidentCmd, f)
|
||||||
|
|
||||||
incidentCmd.AddCommand(incidentListCmd.NewCmdList(f, nil))
|
incidentCmd.AddCommand(incidentListCmd.NewCmdList(f, nil))
|
||||||
|
incidentCmd.AddCommand(incidentNoteCmd.NewCmdNote(f))
|
||||||
incidentCmd.AddCommand(incidentViewCmd.NewCmdView(f))
|
incidentCmd.AddCommand(incidentViewCmd.NewCmdView(f))
|
||||||
incidentCmd.AddCommand(incidentCloseCmd.NewCmdClose(f))
|
incidentCmd.AddCommand(incidentCloseCmd.NewCmdClose(f))
|
||||||
incidentCmd.AddCommand(incidentReopenCmd.NewCmdReopen(f))
|
incidentCmd.AddCommand(incidentReopenCmd.NewCmdReopen(f))
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package note
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/issuable"
|
||||||
|
|
||||||
|
issuableNoteCmd "gitlab.com/gitlab-org/cli/commands/issuable/note"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewCmdNote(f *cmdutils.Factory) *cobra.Command {
|
||||||
|
return issuableNoteCmd.NewCmdNote(f, issuable.TypeIncident)
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package note
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/issuable"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/issue/issueutils"
|
||||||
|
|
||||||
|
"gitlab.com/gitlab-org/cli/api"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/utils"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
gitlab "github.com/xanzy/go-gitlab"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewCmdNote(f *cmdutils.Factory, issueType issuable.IssueType) *cobra.Command {
|
||||||
|
issueNoteCreateCmd := &cobra.Command{
|
||||||
|
Use: fmt.Sprintf("note <%s-id>", issueType),
|
||||||
|
Aliases: []string{"comment"},
|
||||||
|
Short: fmt.Sprintf("Comment on an %s in GitLab", issueType),
|
||||||
|
Long: ``,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
out := f.IO.StdOut
|
||||||
|
|
||||||
|
apiClient, err := f.HttpClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
issue, repo, err := issueutils.IssueFromArg(apiClient, f.BaseRepo, args[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
valid, msg := issuable.ValidateIncidentCmd(issueType, "comment", issue)
|
||||||
|
if !valid {
|
||||||
|
fmt.Fprintln(f.IO.StdOut, msg)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
body, _ := cmd.Flags().GetString("message")
|
||||||
|
|
||||||
|
if strings.TrimSpace(body) == "" {
|
||||||
|
body = utils.Editor(utils.EditorOptions{
|
||||||
|
Label: "Note Message:",
|
||||||
|
Help: "Enter the note message. ",
|
||||||
|
FileName: "ISSUE_NOTE_EDITMSG",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.TrimSpace(body) == "" {
|
||||||
|
return errors.New("aborted... Note is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
noteInfo, err := api.CreateIssueNote(apiClient, repo.FullName(), issue.IID, &gitlab.CreateIssueNoteOptions{
|
||||||
|
Body: &body,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(out, "%s#note_%d\n", issue.WebURL, noteInfo.ID)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
issueNoteCreateCmd.Flags().StringP("message", "m", "", "Comment/Note message")
|
||||||
|
|
||||||
|
return issueNoteCreateCmd
|
||||||
|
}
|
|
@ -0,0 +1,236 @@
|
||||||
|
package note
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/alecthomas/assert"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdtest"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/issuable"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/git"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/httpmock"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/prompt"
|
||||||
|
"gitlab.com/gitlab-org/cli/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runCommand(rt http.RoundTripper, isTTY bool, cli string, issueType issuable.IssueType) (*test.CmdOut, error) {
|
||||||
|
ios, _, stdout, stderr := cmdtest.InitIOStreams(isTTY, "")
|
||||||
|
factory := cmdtest.InitFactory(ios, rt)
|
||||||
|
factory.Branch = git.CurrentBranch
|
||||||
|
|
||||||
|
// TODO: shouldn't be there but the stub doesn't work without it
|
||||||
|
_, _ = factory.HttpClient()
|
||||||
|
|
||||||
|
cmd := NewCmdNote(factory, issueType)
|
||||||
|
|
||||||
|
return cmdtest.ExecuteCommand(cmd, cli, stdout, stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_NewCmdNote(t *testing.T) {
|
||||||
|
fakeHTTP := httpmock.New()
|
||||||
|
defer fakeHTTP.Verify(t)
|
||||||
|
|
||||||
|
commands := []struct {
|
||||||
|
name string
|
||||||
|
issueType issuable.IssueType
|
||||||
|
}{
|
||||||
|
{"issue", issuable.TypeIssue},
|
||||||
|
{"incident", issuable.TypeIncident},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cc := range commands {
|
||||||
|
t.Run("--message flag specified", func(t *testing.T) {
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodPost, "/projects/OWNER/REPO/issues/1/notes",
|
||||||
|
httpmock.NewStringResponse(http.StatusCreated, `
|
||||||
|
{
|
||||||
|
"id": 301,
|
||||||
|
"created_at": "2013-10-02T08:57:14Z",
|
||||||
|
"updated_at": "2013-10-02T08:57:14Z",
|
||||||
|
"system": false,
|
||||||
|
"noteable_id": 1,
|
||||||
|
"noteable_type": "MergeRequest",
|
||||||
|
"noteable_iid": 1
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/1",
|
||||||
|
httpmock.NewStringResponse(http.StatusOK, fmt.Sprintf(`
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"iid": 1,
|
||||||
|
"issue_type": "%s",
|
||||||
|
"web_url": "https://gitlab.com/OWNER/REPO/issues/1"
|
||||||
|
}
|
||||||
|
`, cc.issueType)))
|
||||||
|
|
||||||
|
// glab issue note 1 --message "Here is my note"
|
||||||
|
// glab incident note 1 --message "Here is my note"
|
||||||
|
output, err := runCommand(fakeHTTP, true, `1 --message "Here is my note"`, cc.issueType)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, output.Stderr(), "")
|
||||||
|
assert.Equal(t, output.String(), "https://gitlab.com/OWNER/REPO/issues/1#note_301\n")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("issue not found", func(t *testing.T) {
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/122",
|
||||||
|
httpmock.NewStringResponse(http.StatusNotFound, `
|
||||||
|
{
|
||||||
|
"message" : "issue not found"
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
|
||||||
|
// glab issue note 1 --message "Here is my note"
|
||||||
|
// glab incident note 1 --message "Here is my note"
|
||||||
|
_, err := runCommand(fakeHTTP, true, `122`, cc.issueType)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Equal(t, "GET https://gitlab.com/api/v4/projects/OWNER/REPO/issues/122: 404 {message: issue not found}", err.Error())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_NewCmdNote_error(t *testing.T) {
|
||||||
|
fakeHTTP := httpmock.New()
|
||||||
|
defer fakeHTTP.Verify(t)
|
||||||
|
|
||||||
|
commands := []struct {
|
||||||
|
name string
|
||||||
|
issueType issuable.IssueType
|
||||||
|
}{
|
||||||
|
{"issue", issuable.TypeIssue},
|
||||||
|
{"incident", issuable.TypeIncident},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cc := range commands {
|
||||||
|
t.Run("note could not be created", func(t *testing.T) {
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodPost, "/projects/OWNER/REPO/issues/1/notes",
|
||||||
|
httpmock.NewStringResponse(http.StatusUnauthorized, `
|
||||||
|
{
|
||||||
|
"message" : "Unauthorized"
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/1",
|
||||||
|
httpmock.NewStringResponse(http.StatusOK, fmt.Sprintf(`
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"iid": 1,
|
||||||
|
"issue_type": "%s",
|
||||||
|
"web_url": "https://gitlab.com/OWNER/REPO/issues/1"
|
||||||
|
}
|
||||||
|
`, cc.issueType)))
|
||||||
|
|
||||||
|
// glab issue note 1 --message "Here is my note"
|
||||||
|
// glab incident note 1 --message "Here is my note"
|
||||||
|
_, err := runCommand(fakeHTTP, true, `1 -m "Some message"`, cc.issueType)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Equal(t, "POST https://gitlab.com/api/v4/projects/OWNER/REPO/issues/1/notes: 401 {message: Unauthorized}", err.Error())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("using incident note command with issue ID", func(t *testing.T) {
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/1",
|
||||||
|
httpmock.NewStringResponse(http.StatusOK, `
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"iid": 1,
|
||||||
|
"issue_type": "issue",
|
||||||
|
"web_url": "https://gitlab.com/OWNER/REPO/issues/1"
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
|
||||||
|
output, err := runCommand(fakeHTTP, true, `1 -m "Some message"`, issuable.TypeIncident)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "Incident not found, but an issue with the provided ID exists. Run `glab issue comment <id>` to comment.\n", output.String())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_IssuableNoteCreate_prompt(t *testing.T) {
|
||||||
|
fakeHTTP := httpmock.New()
|
||||||
|
defer fakeHTTP.Verify(t)
|
||||||
|
|
||||||
|
commands := []struct {
|
||||||
|
name string
|
||||||
|
issueType issuable.IssueType
|
||||||
|
}{
|
||||||
|
{"issue", issuable.TypeIssue},
|
||||||
|
{"incident", issuable.TypeIncident},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cc := range commands {
|
||||||
|
t.Run("message provided", func(t *testing.T) {
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodPost, "/projects/OWNER/REPO/issues/1/notes",
|
||||||
|
httpmock.NewStringResponse(http.StatusCreated, `
|
||||||
|
{
|
||||||
|
"id": 301,
|
||||||
|
"created_at": "2013-10-02T08:57:14Z",
|
||||||
|
"updated_at": "2013-10-02T08:57:14Z",
|
||||||
|
"system": false,
|
||||||
|
"noteable_id": 1,
|
||||||
|
"noteable_type": "MergeRequest",
|
||||||
|
"noteable_iid": 1
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/1",
|
||||||
|
httpmock.NewStringResponse(http.StatusOK, fmt.Sprintf(`
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"iid": 1,
|
||||||
|
"issue_type": "%s",
|
||||||
|
"web_url": "https://gitlab.com/OWNER/REPO/issues/1"
|
||||||
|
}
|
||||||
|
`, cc.issueType)))
|
||||||
|
as, teardown := prompt.InitAskStubber()
|
||||||
|
defer teardown()
|
||||||
|
as.StubOne("some note message")
|
||||||
|
|
||||||
|
// glab issue note 1
|
||||||
|
// glab incident note 1
|
||||||
|
output, err := runCommand(fakeHTTP, true, `1`, cc.issueType)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, output.Stderr(), "")
|
||||||
|
assert.Equal(t, output.String(), "https://gitlab.com/OWNER/REPO/issues/1#note_301\n")
|
||||||
|
})
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
message string
|
||||||
|
}{
|
||||||
|
{"message is empty", ""},
|
||||||
|
{"message contains only spaces", " "},
|
||||||
|
{"message contains only line breaks", "\n\n"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/1",
|
||||||
|
httpmock.NewStringResponse(http.StatusOK, fmt.Sprintf(`
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"iid": 1,
|
||||||
|
"issue_type": "%s",
|
||||||
|
"web_url": "https://gitlab.com/OWNER/REPO/issues/1"
|
||||||
|
}
|
||||||
|
`, cc.issueType)))
|
||||||
|
|
||||||
|
as, teardown := prompt.InitAskStubber()
|
||||||
|
defer teardown()
|
||||||
|
as.StubOne(tt.message)
|
||||||
|
|
||||||
|
_, err := runCommand(fakeHTTP, true, `1`, cc.issueType)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, "aborted... Note is empty", err.Error())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,66 +1,13 @@
|
||||||
package note
|
package note
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"gitlab.com/gitlab-org/cli/commands/issue/issueutils"
|
|
||||||
|
|
||||||
"gitlab.com/gitlab-org/cli/api"
|
|
||||||
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
|
||||||
"gitlab.com/gitlab-org/cli/pkg/utils"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
gitlab "github.com/xanzy/go-gitlab"
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/issuable"
|
||||||
|
|
||||||
|
issuableNoteCmd "gitlab.com/gitlab-org/cli/commands/issuable/note"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewCmdNote(f *cmdutils.Factory) *cobra.Command {
|
func NewCmdNote(f *cmdutils.Factory) *cobra.Command {
|
||||||
issueNoteCreateCmd := &cobra.Command{
|
return issuableNoteCmd.NewCmdNote(f, issuable.TypeIssue)
|
||||||
Use: "note <issue-id>",
|
|
||||||
Aliases: []string{"comment"},
|
|
||||||
Short: "Add a comment or note to an issue on GitLab",
|
|
||||||
Long: ``,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
var err error
|
|
||||||
out := f.IO.StdOut
|
|
||||||
|
|
||||||
apiClient, err := f.HttpClient()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
issue, repo, err := issueutils.IssueFromArg(apiClient, f.BaseRepo, args[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
body, _ := cmd.Flags().GetString("message")
|
|
||||||
|
|
||||||
if body == "" {
|
|
||||||
body = utils.Editor(utils.EditorOptions{
|
|
||||||
Label: "Note Message:",
|
|
||||||
Help: "Enter the note message. ",
|
|
||||||
FileName: "ISSUE_NOTE_EDITMSG",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if body == "" {
|
|
||||||
return errors.New("aborted... Note is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
noteInfo, err := api.CreateIssueNote(apiClient, repo.FullName(), issue.IID, &gitlab.CreateIssueNoteOptions{
|
|
||||||
Body: &body,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(out, "%s#note_%d\n", issue.WebURL, noteInfo.ID)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
issueNoteCreateCmd.Flags().StringP("message", "m", "", "Comment/Note message")
|
|
||||||
|
|
||||||
return issueNoteCreateCmd
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,170 +0,0 @@
|
||||||
package note
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/alecthomas/assert"
|
|
||||||
"gitlab.com/gitlab-org/cli/commands/cmdtest"
|
|
||||||
"gitlab.com/gitlab-org/cli/pkg/git"
|
|
||||||
"gitlab.com/gitlab-org/cli/pkg/httpmock"
|
|
||||||
"gitlab.com/gitlab-org/cli/pkg/prompt"
|
|
||||||
"gitlab.com/gitlab-org/cli/test"
|
|
||||||
)
|
|
||||||
|
|
||||||
func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) {
|
|
||||||
ios, _, stdout, stderr := cmdtest.InitIOStreams(isTTY, "")
|
|
||||||
factory := cmdtest.InitFactory(ios, rt)
|
|
||||||
factory.Branch = git.CurrentBranch
|
|
||||||
|
|
||||||
// TODO: shouldn't be there but the stub doesn't work without it
|
|
||||||
_, _ = factory.HttpClient()
|
|
||||||
|
|
||||||
cmd := NewCmdNote(factory)
|
|
||||||
|
|
||||||
return cmdtest.ExecuteCommand(cmd, cli, stdout, stderr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_NewCmdNote(t *testing.T) {
|
|
||||||
fakeHTTP := httpmock.New()
|
|
||||||
defer fakeHTTP.Verify(t)
|
|
||||||
|
|
||||||
t.Run("--message flag specified", func(t *testing.T) {
|
|
||||||
fakeHTTP.RegisterResponder(http.MethodPost, "/projects/OWNER/REPO/issues/1/notes",
|
|
||||||
httpmock.NewStringResponse(http.StatusCreated, `
|
|
||||||
{
|
|
||||||
"id": 301,
|
|
||||||
"created_at": "2013-10-02T08:57:14Z",
|
|
||||||
"updated_at": "2013-10-02T08:57:14Z",
|
|
||||||
"system": false,
|
|
||||||
"noteable_id": 1,
|
|
||||||
"noteable_type": "MergeRequest",
|
|
||||||
"noteable_iid": 1
|
|
||||||
}
|
|
||||||
`))
|
|
||||||
|
|
||||||
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/1",
|
|
||||||
httpmock.NewStringResponse(http.StatusOK, `
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"iid": 1,
|
|
||||||
"web_url": "https://gitlab.com/OWNER/REPO/issues/1"
|
|
||||||
}
|
|
||||||
`))
|
|
||||||
|
|
||||||
// glab mr note 1 --message "Here is my note"
|
|
||||||
output, err := runCommand(fakeHTTP, true, `1 --message "Here is my note"`)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
assert.Equal(t, output.Stderr(), "")
|
|
||||||
assert.Equal(t, output.String(), "https://gitlab.com/OWNER/REPO/issues/1#note_301\n")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("issue not found", func(t *testing.T) {
|
|
||||||
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/122",
|
|
||||||
httpmock.NewStringResponse(http.StatusNotFound, `
|
|
||||||
{
|
|
||||||
"message" : "issue not found"
|
|
||||||
}
|
|
||||||
`))
|
|
||||||
|
|
||||||
// glab mr note 1 --message "Here is my note"
|
|
||||||
_, err := runCommand(fakeHTTP, true, `122`)
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
assert.Equal(t, "GET https://gitlab.com/api/v4/projects/OWNER/REPO/issues/122: 404 {message: issue not found}", err.Error())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_NewCmdNote_error(t *testing.T) {
|
|
||||||
fakeHTTP := httpmock.New()
|
|
||||||
defer fakeHTTP.Verify(t)
|
|
||||||
|
|
||||||
t.Run("note could not be created", func(t *testing.T) {
|
|
||||||
fakeHTTP.RegisterResponder(http.MethodPost, "/projects/OWNER/REPO/issues/1/notes",
|
|
||||||
httpmock.NewStringResponse(http.StatusUnauthorized, `
|
|
||||||
{
|
|
||||||
"message" : "Unauthorized"
|
|
||||||
}
|
|
||||||
`))
|
|
||||||
|
|
||||||
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/1",
|
|
||||||
httpmock.NewStringResponse(http.StatusOK, `
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"iid": 1,
|
|
||||||
"web_url": "https://gitlab.com/OWNER/REPO/issues/1"
|
|
||||||
}
|
|
||||||
`))
|
|
||||||
|
|
||||||
// glab mr note 1 --message "Here is my note"
|
|
||||||
_, err := runCommand(fakeHTTP, true, `1 -m "Some message"`)
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
assert.Equal(t, "POST https://gitlab.com/api/v4/projects/OWNER/REPO/issues/1/notes: 401 {message: Unauthorized}", err.Error())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_mrNoteCreate_prompt(t *testing.T) {
|
|
||||||
fakeHTTP := httpmock.New()
|
|
||||||
defer fakeHTTP.Verify(t)
|
|
||||||
|
|
||||||
t.Run("message provided", func(t *testing.T) {
|
|
||||||
fakeHTTP.RegisterResponder(http.MethodPost, "/projects/OWNER/REPO/issues/1/notes",
|
|
||||||
httpmock.NewStringResponse(http.StatusCreated, `
|
|
||||||
{
|
|
||||||
"id": 301,
|
|
||||||
"created_at": "2013-10-02T08:57:14Z",
|
|
||||||
"updated_at": "2013-10-02T08:57:14Z",
|
|
||||||
"system": false,
|
|
||||||
"noteable_id": 1,
|
|
||||||
"noteable_type": "MergeRequest",
|
|
||||||
"noteable_iid": 1
|
|
||||||
}
|
|
||||||
`))
|
|
||||||
|
|
||||||
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/1",
|
|
||||||
httpmock.NewStringResponse(http.StatusOK, `
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"iid": 1,
|
|
||||||
"web_url": "https://gitlab.com/OWNER/REPO/issues/1"
|
|
||||||
}
|
|
||||||
`))
|
|
||||||
as, teardown := prompt.InitAskStubber()
|
|
||||||
defer teardown()
|
|
||||||
as.StubOne("some note message")
|
|
||||||
|
|
||||||
// glab mr note 1
|
|
||||||
output, err := runCommand(fakeHTTP, true, `1`)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
assert.Equal(t, output.Stderr(), "")
|
|
||||||
assert.Equal(t, output.String(), "https://gitlab.com/OWNER/REPO/issues/1#note_301\n")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("message is empty", func(t *testing.T) {
|
|
||||||
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/issues/1",
|
|
||||||
httpmock.NewStringResponse(http.StatusOK, `
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"iid": 1,
|
|
||||||
"web_url": "https://gitlab.com/OWNER/REPO/issues/1"
|
|
||||||
}
|
|
||||||
`))
|
|
||||||
|
|
||||||
as, teardown := prompt.InitAskStubber()
|
|
||||||
defer teardown()
|
|
||||||
as.StubOne("")
|
|
||||||
|
|
||||||
// glab mr note 1
|
|
||||||
_, err := runCommand(fakeHTTP, true, `1`)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("expected error")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
assert.Equal(t, "aborted... Note is empty", err.Error())
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -36,6 +36,7 @@ glab incident list
|
||||||
|
|
||||||
- [close](close.md)
|
- [close](close.md)
|
||||||
- [list](list.md)
|
- [list](list.md)
|
||||||
|
- [note](note.md)
|
||||||
- [reopen](reopen.md)
|
- [reopen](reopen.md)
|
||||||
- [subscribe](subscribe.md)
|
- [subscribe](subscribe.md)
|
||||||
- [unsubscribe](unsubscribe.md)
|
- [unsubscribe](unsubscribe.md)
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
stage: Create
|
||||||
|
group: Code Review
|
||||||
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This documentation is auto generated by a script.
|
||||||
|
Please do not edit this file directly. Run `make gen-docs` instead.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# `glab incident note`
|
||||||
|
|
||||||
|
Comment on an incident in GitLab
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
glab incident note <incident-id> [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
comment
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
-m, --message string Comment/Note message
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options inherited from parent commands
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
--help Show help for command
|
||||||
|
-R, --repo OWNER/REPO Select another repository using the OWNER/REPO or `GROUP/NAMESPACE/REPO` format or full URL or git URL
|
||||||
|
```
|
|
@ -11,7 +11,7 @@ Please do not edit this file directly. Run `make gen-docs` instead.
|
||||||
|
|
||||||
# `glab issue note`
|
# `glab issue note`
|
||||||
|
|
||||||
Add a comment or note to an issue on GitLab
|
Comment on an issue in GitLab
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
glab issue note <issue-id> [flags]
|
glab issue note <issue-id> [flags]
|
||||||
|
|
Loading…
Reference in New Issue