From 5ea3ddad70fe650467e861369a8f74d6e31aa351 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Thu, 8 Dec 2022 15:54:09 +0300 Subject: [PATCH 01/16] githubCreateIssue_fix --- cmd/githubCreateIssue.go | 70 +++++++++++++++++++---- cmd/githubCreateIssue_generated.go | 11 ++++ cmd/githubCreateIssue_test.go | 18 ++++-- resources/metadata/githubCreateIssue.yaml | 7 +++ 4 files changed, 89 insertions(+), 17 deletions(-) diff --git a/cmd/githubCreateIssue.go b/cmd/githubCreateIssue.go index d0aaafd0aa..1a8cc0e053 100644 --- a/cmd/githubCreateIssue.go +++ b/cmd/githubCreateIssue.go @@ -21,15 +21,47 @@ func githubCreateIssue(config githubCreateIssueOptions, telemetryData *telemetry func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomData) error { options := piperGithub.CreateIssueOptions{} - err := transformConfig(config, &options, ioutil.ReadFile) + chunks, err := getBody(config, ioutil.ReadFile) if err != nil { return err } + transformConfig(config, &options, chunks[0]) + err = piperGithub.CreateIssue(&options) + if err != nil { + return err + } + if len(chunks) > 0 { + for _, v := range chunks[1:] { + options.Body = []byte(v) + options.UpdateExisting = true + err = piperGithub.CreateIssue(&options) + if err != nil { + return err + } + + } + } + return nil +} - return piperGithub.CreateIssue(&options) +func getBody(config *githubCreateIssueOptions, readFile func(string) ([]byte, error)) ([]string, error) { + var bodyString []rune + if len(config.Body)+len(config.BodyFilePath) == 0 { + return nil, fmt.Errorf("either parameter `body` or parameter `bodyFilePath` is required") + } + if len(config.Body) == 0 { + issueContent, err := readFile(config.BodyFilePath) + if err != nil { + return nil, errors.Wrapf(err, "failed to read file '%v'", config.BodyFilePath) + } + bodyString = []rune(string(issueContent)) + } else { + bodyString = []rune(config.Body) + } + return getChunks(bodyString, config.ChunkSize), nil } -func transformConfig(config *githubCreateIssueOptions, options *piperGithub.CreateIssueOptions, readFile func(string) ([]byte, error)) error { +func transformConfig(config *githubCreateIssueOptions, options *piperGithub.CreateIssueOptions, body string) { options.Token = config.Token options.APIURL = config.APIURL options.Owner = config.Owner @@ -38,16 +70,30 @@ func transformConfig(config *githubCreateIssueOptions, options *piperGithub.Crea options.Body = []byte(config.Body) options.Assignees = config.Assignees options.UpdateExisting = config.UpdateExisting + options.Body = []byte(body) +} - if len(config.Body)+len(config.BodyFilePath) == 0 { - return fmt.Errorf("either parameter `body` or parameter `bodyFilePath` is required") - } - if len(config.Body) == 0 { - issueContent, err := readFile(config.BodyFilePath) - if err != nil { - return errors.Wrapf(err, "failed to read file '%v'", config.BodyFilePath) +func getChunks(value []rune, chunkSize int) []string { + chunks := []string{} + length := len(value) + for i := 0; i < length; { + to := length + if to > i+chunkSize { + to = i + chunkSize + } else { + chunks = append(chunks, string(value[i:to])) + break } - options.Body = issueContent + + for j := to - 1; j > i; j-- { + if value[j] == '\n' { + to = j + break + } + } + fmt.Printf("to %v i %v", to, i) + chunks = append(chunks, string(value[i:to])) + i = to } - return nil + return chunks } diff --git a/cmd/githubCreateIssue_generated.go b/cmd/githubCreateIssue_generated.go index 3f5a751727..5d27e77c7f 100644 --- a/cmd/githubCreateIssue_generated.go +++ b/cmd/githubCreateIssue_generated.go @@ -18,6 +18,7 @@ import ( type githubCreateIssueOptions struct { APIURL string `json:"apiUrl,omitempty"` Assignees []string `json:"assignees,omitempty"` + ChunkSize int `json:"chunkSize,omitempty"` Body string `json:"body,omitempty"` BodyFilePath string `json:"bodyFilePath,omitempty"` Owner string `json:"owner,omitempty"` @@ -125,6 +126,7 @@ You will be able to use this step for example for regular jobs to report into yo func addGithubCreateIssueFlags(cmd *cobra.Command, stepConfig *githubCreateIssueOptions) { cmd.Flags().StringVar(&stepConfig.APIURL, "apiUrl", `https://api.github.com`, "Set the GitHub API url.") cmd.Flags().StringSliceVar(&stepConfig.Assignees, "assignees", []string{``}, "Defines the assignees for the Issue.") + cmd.Flags().IntVar(&stepConfig.ChunkSize, "chunkSize", 0, "Defines size of the chunk. If content exceed chunk size it'll be sliced into chunks and stored in comments") cmd.Flags().StringVar(&stepConfig.Body, "body", os.Getenv("PIPER_body"), "Defines the content of the issue, e.g. using markdown syntax.") cmd.Flags().StringVar(&stepConfig.BodyFilePath, "bodyFilePath", os.Getenv("PIPER_bodyFilePath"), "Defines the path to a file containing the markdown content for the issue. This can be used instead of [`body`](#body)") cmd.Flags().StringVar(&stepConfig.Owner, "owner", os.Getenv("PIPER_owner"), "Name of the GitHub organization.") @@ -172,6 +174,15 @@ func githubCreateIssueMetadata() config.StepData { Aliases: []config.Alias{}, Default: []string{``}, }, + { + Name: "chunkSize", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "int", + Mandatory: false, + Aliases: []config.Alias{}, + Default: 0, + }, { Name: "body", ResourceRef: []config.ResourceReference{}, diff --git a/cmd/githubCreateIssue_test.go b/cmd/githubCreateIssue_test.go index b2d33bc024..99cd0d4b41 100644 --- a/cmd/githubCreateIssue_test.go +++ b/cmd/githubCreateIssue_test.go @@ -1,15 +1,22 @@ package cmd import ( + "fmt" "testing" +) - "github.com/SAP/jenkins-library/pkg/mock" - - "github.com/stretchr/testify/assert" +func TestGetChunk(t *testing.T) { + testString := []rune(`1AB +`) - piperGithub "github.com/SAP/jenkins-library/pkg/github" -) + chunkSize := 8 + chunks := getChunks(testString, chunkSize) + for k, v := range chunks { + t.Log(fmt.Sprintf("%v -- '%v'", k,v)) + } +} +/* func TestTransformConfig(t *testing.T) { t.Parallel() @@ -81,3 +88,4 @@ func TestTransformConfig(t *testing.T) { assert.EqualError(t, err, "either parameter `body` or parameter `bodyFilePath` is required") }) } +*/ diff --git a/resources/metadata/githubCreateIssue.yaml b/resources/metadata/githubCreateIssue.yaml index c07e56a169..deefda207f 100644 --- a/resources/metadata/githubCreateIssue.yaml +++ b/resources/metadata/githubCreateIssue.yaml @@ -33,6 +33,13 @@ spec: type: "[]string" default: [] mandatory: false + - name: chunkSize + description: Defines size of the chunk. If content exceed chunk size it'll be sliced into chunks and stored in comments + scope: + - PARAMETERS + - STAGES + - STEPS + type: int - name: body description: Defines the content of the issue, e.g. using markdown syntax. scope: From 59a62477d3aa241114eed0eb28359162724cb968 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Thu, 8 Dec 2022 20:51:12 +0300 Subject: [PATCH 02/16] simplification and test fix --- cmd/githubCreateIssue.go | 41 ++++++++++------------- cmd/githubCreateIssue_test.go | 63 +++++++++++++++++++++++++++-------- 2 files changed, 66 insertions(+), 38 deletions(-) diff --git a/cmd/githubCreateIssue.go b/cmd/githubCreateIssue.go index 1a8cc0e053..90195d064e 100644 --- a/cmd/githubCreateIssue.go +++ b/cmd/githubCreateIssue.go @@ -2,31 +2,34 @@ package cmd import ( "fmt" - "io/ioutil" "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/SAP/jenkins-library/pkg/telemetry" "github.com/pkg/errors" piperGithub "github.com/SAP/jenkins-library/pkg/github" ) +type githubCreateIssueUtils interface { +FileRead(string) ([]byte, error) +} func githubCreateIssue(config githubCreateIssueOptions, telemetryData *telemetry.CustomData) { - err := runGithubCreateIssue(&config, telemetryData) + fileUtils := &piperutils.Files{} + options := piperGithub.CreateIssueOptions{} + err := runGithubCreateIssue(&config, telemetryData, &options, fileUtils) if err != nil { log.Entry().WithError(err).Fatal("Failed to comment on issue") } } -func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomData) error { - - options := piperGithub.CreateIssueOptions{} - chunks, err := getBody(config, ioutil.ReadFile) +func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomData, options *piperGithub.CreateIssueOptions, utils githubCreateIssueUtils) error { + chunks, err := getBody(config, utils.FileRead) if err != nil { return err } - transformConfig(config, &options, chunks[0]) - err = piperGithub.CreateIssue(&options) + transformConfig(config, options, chunks[0]) + err = piperGithub.CreateIssue(options) if err != nil { return err } @@ -34,11 +37,10 @@ func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomD for _, v := range chunks[1:] { options.Body = []byte(v) options.UpdateExisting = true - err = piperGithub.CreateIssue(&options) + err = piperGithub.CreateIssue(options) if err != nil { return err } - } } return nil @@ -76,24 +78,15 @@ func transformConfig(config *githubCreateIssueOptions, options *piperGithub.Crea func getChunks(value []rune, chunkSize int) []string { chunks := []string{} length := len(value) - for i := 0; i < length; { + if length == 0 { + return []string{""} + } + for i := 0; i < length; i+=chunkSize { to := length if to > i+chunkSize { to = i + chunkSize - } else { - chunks = append(chunks, string(value[i:to])) - break - } - - for j := to - 1; j > i; j-- { - if value[j] == '\n' { - to = j - break - } - } - fmt.Printf("to %v i %v", to, i) + } chunks = append(chunks, string(value[i:to])) - i = to } return chunks } diff --git a/cmd/githubCreateIssue_test.go b/cmd/githubCreateIssue_test.go index 99cd0d4b41..485d59da04 100644 --- a/cmd/githubCreateIssue_test.go +++ b/cmd/githubCreateIssue_test.go @@ -1,22 +1,58 @@ package cmd import ( - "fmt" "testing" + + piperGithub "github.com/SAP/jenkins-library/pkg/github" + "github.com/SAP/jenkins-library/pkg/mock" + "github.com/stretchr/testify/assert" ) func TestGetChunk(t *testing.T) { - testString := []rune(`1AB -`) - - chunkSize := 8 - chunks := getChunks(testString, chunkSize) - for k, v := range chunks { - - t.Log(fmt.Sprintf("%v -- '%v'", k,v)) + tests := []struct { + name string + chunkSize int + largeString string + expectedChunks []string + }{ + { + name: "large string", + largeString: `The quick +brown fox jumps +over +the lazy dog +`, + chunkSize: 12, + expectedChunks: []string{"The quick\nbr", "own fox jump", "s\nover\nthe l", "azy dog\n"}, + }, + { + name: "small string", + largeString: `small`, + chunkSize: 12, + expectedChunks: []string{"small"}, + }, + { + name: "exact size", + largeString: `exact size12`, + chunkSize: 12, + expectedChunks: []string{"exact size12"}, + }, + { + name: "empty strict", + largeString: ``, + chunkSize: 12, + expectedChunks: []string{""}, + }, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + chunks := getChunks([]rune(test.largeString), test.chunkSize) + assert.ElementsMatch(t, test.expectedChunks, chunks) + }) } } -/* + func TestTransformConfig(t *testing.T) { t.Parallel() @@ -33,7 +69,7 @@ func TestTransformConfig(t *testing.T) { options := piperGithub.CreateIssueOptions{} // test - err := transformConfig(&config, &options, filesMock.FileRead) + err := runGithubCreateIssue(&config, nil, &options, &filesMock) // assert assert.NoError(t, err) @@ -61,7 +97,7 @@ func TestTransformConfig(t *testing.T) { options := piperGithub.CreateIssueOptions{} // test - err := transformConfig(&config, &options, filesMock.FileRead) + err := runGithubCreateIssue(&config, nil, &options, &filesMock) // assert assert.NoError(t, err) @@ -82,10 +118,9 @@ func TestTransformConfig(t *testing.T) { options := piperGithub.CreateIssueOptions{} // test - err := transformConfig(&config, &options, filesMock.FileRead) + err := runGithubCreateIssue(&config, nil, &options, &filesMock) // assert assert.EqualError(t, err, "either parameter `body` or parameter `bodyFilePath` is required") }) } -*/ From c80e5635130a137eb2407d2d117c46fc77209401 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Thu, 8 Dec 2022 23:39:03 +0300 Subject: [PATCH 03/16] yaml --- resources/metadata/githubCreateIssue.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/metadata/githubCreateIssue.yaml b/resources/metadata/githubCreateIssue.yaml index deefda207f..4d47dc240e 100644 --- a/resources/metadata/githubCreateIssue.yaml +++ b/resources/metadata/githubCreateIssue.yaml @@ -34,7 +34,7 @@ spec: default: [] mandatory: false - name: chunkSize - description: Defines size of the chunk. If content exceed chunk size it'll be sliced into chunks and stored in comments + description: Defines size of the chunk. If content exceed chunk size it'll be sliced into chunks and stored in comments scope: - PARAMETERS - STAGES From 40406ec64333d8be511dfe7a481bf966ccbc150d Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Thu, 8 Dec 2022 23:42:04 +0300 Subject: [PATCH 04/16] fmt --- cmd/githubCreateIssue_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/githubCreateIssue_test.go b/cmd/githubCreateIssue_test.go index 485d59da04..3fcd8ae565 100644 --- a/cmd/githubCreateIssue_test.go +++ b/cmd/githubCreateIssue_test.go @@ -26,20 +26,20 @@ the lazy dog expectedChunks: []string{"The quick\nbr", "own fox jump", "s\nover\nthe l", "azy dog\n"}, }, { - name: "small string", - largeString: `small`, + name: "small string", + largeString: `small`, chunkSize: 12, expectedChunks: []string{"small"}, }, { - name: "exact size", - largeString: `exact size12`, + name: "exact size", + largeString: `exact size12`, chunkSize: 12, expectedChunks: []string{"exact size12"}, }, { - name: "empty strict", - largeString: ``, + name: "empty strict", + largeString: ``, chunkSize: 12, expectedChunks: []string{""}, }, From 407ca414c2ee5b9f0214f0788dd6b8abf48a8840 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Thu, 8 Dec 2022 23:45:50 +0300 Subject: [PATCH 05/16] fmt --- cmd/githubCreateIssue.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/githubCreateIssue.go b/cmd/githubCreateIssue.go index 90195d064e..9e343c57cc 100644 --- a/cmd/githubCreateIssue.go +++ b/cmd/githubCreateIssue.go @@ -10,8 +10,9 @@ import ( piperGithub "github.com/SAP/jenkins-library/pkg/github" ) + type githubCreateIssueUtils interface { -FileRead(string) ([]byte, error) + FileRead(string) ([]byte, error) } func githubCreateIssue(config githubCreateIssueOptions, telemetryData *telemetry.CustomData) { @@ -81,11 +82,11 @@ func getChunks(value []rune, chunkSize int) []string { if length == 0 { return []string{""} } - for i := 0; i < length; i+=chunkSize { + for i := 0; i < length; i += chunkSize { to := length if to > i+chunkSize { to = i + chunkSize - } + } chunks = append(chunks, string(value[i:to])) } return chunks From 016c4eea39e698a836251154e41267def7e35bea Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Fri, 9 Dec 2022 19:44:23 +0300 Subject: [PATCH 06/16] fix --- cmd/githubCreateIssue.go | 8 ++++---- cmd/githubCreateIssue_test.go | 28 +++++++++++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/cmd/githubCreateIssue.go b/cmd/githubCreateIssue.go index 9e343c57cc..ee6d0aa900 100644 --- a/cmd/githubCreateIssue.go +++ b/cmd/githubCreateIssue.go @@ -18,19 +18,19 @@ type githubCreateIssueUtils interface { func githubCreateIssue(config githubCreateIssueOptions, telemetryData *telemetry.CustomData) { fileUtils := &piperutils.Files{} options := piperGithub.CreateIssueOptions{} - err := runGithubCreateIssue(&config, telemetryData, &options, fileUtils) + err := runGithubCreateIssue(&config, telemetryData, &options, fileUtils, piperGithub.CreateIssue) if err != nil { log.Entry().WithError(err).Fatal("Failed to comment on issue") } } -func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomData, options *piperGithub.CreateIssueOptions, utils githubCreateIssueUtils) error { +func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomData, options *piperGithub.CreateIssueOptions, utils githubCreateIssueUtils, createIssue func(*piperGithub.CreateIssueOptions) error) error { chunks, err := getBody(config, utils.FileRead) if err != nil { return err } transformConfig(config, options, chunks[0]) - err = piperGithub.CreateIssue(options) + err = createIssue(options) if err != nil { return err } @@ -38,7 +38,7 @@ func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomD for _, v := range chunks[1:] { options.Body = []byte(v) options.UpdateExisting = true - err = piperGithub.CreateIssue(options) + err = createIssue(options) if err != nil { return err } diff --git a/cmd/githubCreateIssue_test.go b/cmd/githubCreateIssue_test.go index 3fcd8ae565..ec2db82c81 100644 --- a/cmd/githubCreateIssue_test.go +++ b/cmd/githubCreateIssue_test.go @@ -65,11 +65,17 @@ func TestTransformConfig(t *testing.T) { Body: "This is my test body", Title: "This is my title", Assignees: []string{"userIdOne", "userIdTwo"}, + ChunkSize: 100, } options := piperGithub.CreateIssueOptions{} + resultChunks := []string{} + createIssue := func(options *piperGithub.CreateIssueOptions) error { + resultChunks = append(resultChunks, string(options.Body)) + return nil + } // test - err := runGithubCreateIssue(&config, nil, &options, &filesMock) + err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue) // assert assert.NoError(t, err) @@ -77,10 +83,10 @@ func TestTransformConfig(t *testing.T) { assert.Equal(t, config.APIURL, options.APIURL) assert.Equal(t, config.Owner, options.Owner) assert.Equal(t, config.Repository, options.Repository) - assert.Equal(t, []byte(config.Body), options.Body) assert.Equal(t, config.Title, options.Title) assert.Equal(t, config.Assignees, options.Assignees) assert.Equal(t, config.UpdateExisting, options.UpdateExisting) + assert.ElementsMatch(t, resultChunks, []string{string(config.Body)}) }) t.Run("Success bodyFilePath", func(t *testing.T) { @@ -95,9 +101,13 @@ func TestTransformConfig(t *testing.T) { Assignees: []string{"userIdOne", "userIdTwo"}, } options := piperGithub.CreateIssueOptions{} - + resultChunks := []string{} + createIssue := func(options *piperGithub.CreateIssueOptions) error { + resultChunks = append(resultChunks, string(options.Body)) + return nil + } // test - err := runGithubCreateIssue(&config, nil, &options, &filesMock) + err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue) // assert assert.NoError(t, err) @@ -105,10 +115,10 @@ func TestTransformConfig(t *testing.T) { assert.Equal(t, config.APIURL, options.APIURL) assert.Equal(t, config.Owner, options.Owner) assert.Equal(t, config.Repository, options.Repository) - assert.Equal(t, []byte("Test markdown"), options.Body) assert.Equal(t, config.Title, options.Title) assert.Equal(t, config.Assignees, options.Assignees) assert.Equal(t, config.UpdateExisting, options.UpdateExisting) + assert.ElementsMatch(t, resultChunks, []string{"Test markdown"}) }) t.Run("Error - missing issue body", func(t *testing.T) { @@ -116,9 +126,13 @@ func TestTransformConfig(t *testing.T) { filesMock := mock.FilesMock{} config := githubCreateIssueOptions{} options := piperGithub.CreateIssueOptions{} - + resultChunks := []string{} + createIssue := func(options *piperGithub.CreateIssueOptions) error { + resultChunks = append(resultChunks, string(options.Body)) + return nil + } // test - err := runGithubCreateIssue(&config, nil, &options, &filesMock) + err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue) // assert assert.EqualError(t, err, "either parameter `body` or parameter `bodyFilePath` is required") From 0515d66b4aeacf30077361412725e380e5f0ab1f Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Fri, 9 Dec 2022 21:03:02 +0300 Subject: [PATCH 07/16] fix tests --- cmd/githubCreateIssue.go | 2 +- cmd/githubCreateIssue_test.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/githubCreateIssue.go b/cmd/githubCreateIssue.go index ee6d0aa900..5f0ee5ea10 100644 --- a/cmd/githubCreateIssue.go +++ b/cmd/githubCreateIssue.go @@ -34,7 +34,7 @@ func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomD if err != nil { return err } - if len(chunks) > 0 { + if len(chunks) > 1 { for _, v := range chunks[1:] { options.Body = []byte(v) options.UpdateExisting = true diff --git a/cmd/githubCreateIssue_test.go b/cmd/githubCreateIssue_test.go index ec2db82c81..0d702ed5b2 100644 --- a/cmd/githubCreateIssue_test.go +++ b/cmd/githubCreateIssue_test.go @@ -99,6 +99,7 @@ func TestTransformConfig(t *testing.T) { BodyFilePath: "test.md", Title: "This is my title", Assignees: []string{"userIdOne", "userIdTwo"}, + ChunkSize: 100, } options := piperGithub.CreateIssueOptions{} resultChunks := []string{} @@ -124,7 +125,7 @@ func TestTransformConfig(t *testing.T) { t.Run("Error - missing issue body", func(t *testing.T) { // init filesMock := mock.FilesMock{} - config := githubCreateIssueOptions{} + config := githubCreateIssueOptions{ChunkSize: 100,} options := piperGithub.CreateIssueOptions{} resultChunks := []string{} createIssue := func(options *piperGithub.CreateIssueOptions) error { From 8554d4fc86724a2d05f9e10247cfa9cb33056755 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Fri, 9 Dec 2022 21:36:44 +0300 Subject: [PATCH 08/16] fix formatting --- cmd/githubCreateIssue_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/githubCreateIssue_test.go b/cmd/githubCreateIssue_test.go index 0d702ed5b2..ea5a434a91 100644 --- a/cmd/githubCreateIssue_test.go +++ b/cmd/githubCreateIssue_test.go @@ -65,14 +65,14 @@ func TestTransformConfig(t *testing.T) { Body: "This is my test body", Title: "This is my title", Assignees: []string{"userIdOne", "userIdTwo"}, - ChunkSize: 100, + ChunkSize: 100, } options := piperGithub.CreateIssueOptions{} resultChunks := []string{} createIssue := func(options *piperGithub.CreateIssueOptions) error { resultChunks = append(resultChunks, string(options.Body)) return nil - } + } // test err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue) @@ -99,14 +99,14 @@ func TestTransformConfig(t *testing.T) { BodyFilePath: "test.md", Title: "This is my title", Assignees: []string{"userIdOne", "userIdTwo"}, - ChunkSize: 100, + ChunkSize: 100, } options := piperGithub.CreateIssueOptions{} resultChunks := []string{} createIssue := func(options *piperGithub.CreateIssueOptions) error { resultChunks = append(resultChunks, string(options.Body)) return nil - } + } // test err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue) @@ -125,13 +125,13 @@ func TestTransformConfig(t *testing.T) { t.Run("Error - missing issue body", func(t *testing.T) { // init filesMock := mock.FilesMock{} - config := githubCreateIssueOptions{ChunkSize: 100,} + config := githubCreateIssueOptions{ChunkSize: 100} options := piperGithub.CreateIssueOptions{} resultChunks := []string{} createIssue := func(options *piperGithub.CreateIssueOptions) error { resultChunks = append(resultChunks, string(options.Body)) return nil - } + } // test err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue) From 77579e2f689be3f05d2bee525a72c99b7348369e Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Sat, 10 Dec 2022 09:38:42 +0300 Subject: [PATCH 09/16] add default --- cmd/githubCreateIssue_generated.go | 4 ++-- resources/metadata/githubCreateIssue.yaml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/githubCreateIssue_generated.go b/cmd/githubCreateIssue_generated.go index 5d27e77c7f..05036942d0 100644 --- a/cmd/githubCreateIssue_generated.go +++ b/cmd/githubCreateIssue_generated.go @@ -126,7 +126,7 @@ You will be able to use this step for example for regular jobs to report into yo func addGithubCreateIssueFlags(cmd *cobra.Command, stepConfig *githubCreateIssueOptions) { cmd.Flags().StringVar(&stepConfig.APIURL, "apiUrl", `https://api.github.com`, "Set the GitHub API url.") cmd.Flags().StringSliceVar(&stepConfig.Assignees, "assignees", []string{``}, "Defines the assignees for the Issue.") - cmd.Flags().IntVar(&stepConfig.ChunkSize, "chunkSize", 0, "Defines size of the chunk. If content exceed chunk size it'll be sliced into chunks and stored in comments") + cmd.Flags().IntVar(&stepConfig.ChunkSize, "chunkSize", 65500, "Defines size of the chunk. If content exceed chunk size it'll be sliced into chunks and stored in comments") cmd.Flags().StringVar(&stepConfig.Body, "body", os.Getenv("PIPER_body"), "Defines the content of the issue, e.g. using markdown syntax.") cmd.Flags().StringVar(&stepConfig.BodyFilePath, "bodyFilePath", os.Getenv("PIPER_bodyFilePath"), "Defines the path to a file containing the markdown content for the issue. This can be used instead of [`body`](#body)") cmd.Flags().StringVar(&stepConfig.Owner, "owner", os.Getenv("PIPER_owner"), "Name of the GitHub organization.") @@ -181,7 +181,7 @@ func githubCreateIssueMetadata() config.StepData { Type: "int", Mandatory: false, Aliases: []config.Alias{}, - Default: 0, + Default: 65500, }, { Name: "body", diff --git a/resources/metadata/githubCreateIssue.yaml b/resources/metadata/githubCreateIssue.yaml index 4d47dc240e..be6aa3f367 100644 --- a/resources/metadata/githubCreateIssue.yaml +++ b/resources/metadata/githubCreateIssue.yaml @@ -40,6 +40,7 @@ spec: - STAGES - STEPS type: int + default: 65500 - name: body description: Defines the content of the issue, e.g. using markdown syntax. scope: From 7ee65e4ae6998f934d851cf420dc874c4e770b95 Mon Sep 17 00:00:00 2001 From: raman-susla-epam <104915202+raman-susla-epam@users.noreply.github.com> Date: Wed, 14 Dec 2022 19:01:04 +0300 Subject: [PATCH 10/16] Update cmd/githubCreateIssue_test.go Co-authored-by: Jordi van Liempt <35920075+jliempt@users.noreply.github.com> --- cmd/githubCreateIssue_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/githubCreateIssue_test.go b/cmd/githubCreateIssue_test.go index ea5a434a91..7b63f24025 100644 --- a/cmd/githubCreateIssue_test.go +++ b/cmd/githubCreateIssue_test.go @@ -38,7 +38,7 @@ the lazy dog expectedChunks: []string{"exact size12"}, }, { - name: "empty strict", + name: "empty string", largeString: ``, chunkSize: 12, expectedChunks: []string{""}, From e7bc65861975fc9e8ccf9533d42e8399cdb29464 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Wed, 14 Dec 2022 21:51:01 +0300 Subject: [PATCH 11/16] fix issue recreation --- cmd/checkmarxExecuteScan.go | 3 ++- cmd/fortifyExecuteScan.go | 3 ++- cmd/githubCreateIssue.go | 8 +++++--- cmd/githubCreateIssue_test.go | 13 +++++++------ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/cmd/checkmarxExecuteScan.go b/cmd/checkmarxExecuteScan.go index a04ee23582..8c638622d1 100644 --- a/cmd/checkmarxExecuteScan.go +++ b/cmd/checkmarxExecuteScan.go @@ -77,7 +77,8 @@ func (c *checkmarxExecuteScanUtilsBundle) Open(name string) (*os.File, error) { } func (c *checkmarxExecuteScanUtilsBundle) CreateIssue(ghCreateIssueOptions *piperGithub.CreateIssueOptions) error { - return piperGithub.CreateIssue(ghCreateIssueOptions) + _, err := piperGithub.CreateIssue(ghCreateIssueOptions) + return err } func (c *checkmarxExecuteScanUtilsBundle) GetIssueService() *github.IssuesService { diff --git a/cmd/fortifyExecuteScan.go b/cmd/fortifyExecuteScan.go index f728682a65..fa7d871116 100644 --- a/cmd/fortifyExecuteScan.go +++ b/cmd/fortifyExecuteScan.go @@ -78,7 +78,8 @@ func (f *fortifyUtilsBundle) GetArtifact(buildTool, buildDescriptorFile string, } func (f *fortifyUtilsBundle) CreateIssue(ghCreateIssueOptions *piperGithub.CreateIssueOptions) error { - return piperGithub.CreateIssue(ghCreateIssueOptions) + _, err := piperGithub.CreateIssue(ghCreateIssueOptions) + return err } func (f *fortifyUtilsBundle) GetIssueService() *github.IssuesService { diff --git a/cmd/githubCreateIssue.go b/cmd/githubCreateIssue.go index 5f0ee5ea10..dfb9f930d8 100644 --- a/cmd/githubCreateIssue.go +++ b/cmd/githubCreateIssue.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" piperGithub "github.com/SAP/jenkins-library/pkg/github" + github "github.com/google/go-github/v45/github" ) type githubCreateIssueUtils interface { @@ -24,21 +25,22 @@ func githubCreateIssue(config githubCreateIssueOptions, telemetryData *telemetry } } -func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomData, options *piperGithub.CreateIssueOptions, utils githubCreateIssueUtils, createIssue func(*piperGithub.CreateIssueOptions) error) error { +func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomData, options *piperGithub.CreateIssueOptions, utils githubCreateIssueUtils, createIssue func(*piperGithub.CreateIssueOptions) (*github.Issue, error)) error { chunks, err := getBody(config, utils.FileRead) if err != nil { return err } transformConfig(config, options, chunks[0]) - err = createIssue(options) + issue, err := createIssue(options) if err != nil { return err } if len(chunks) > 1 { for _, v := range chunks[1:] { options.Body = []byte(v) + options.Issue = issue options.UpdateExisting = true - err = createIssue(options) + _, err = createIssue(options) if err != nil { return err } diff --git a/cmd/githubCreateIssue_test.go b/cmd/githubCreateIssue_test.go index ea5a434a91..6bea8014f1 100644 --- a/cmd/githubCreateIssue_test.go +++ b/cmd/githubCreateIssue_test.go @@ -3,6 +3,7 @@ package cmd import ( "testing" + github "github.com/google/go-github/v45/github" piperGithub "github.com/SAP/jenkins-library/pkg/github" "github.com/SAP/jenkins-library/pkg/mock" "github.com/stretchr/testify/assert" @@ -69,9 +70,9 @@ func TestTransformConfig(t *testing.T) { } options := piperGithub.CreateIssueOptions{} resultChunks := []string{} - createIssue := func(options *piperGithub.CreateIssueOptions) error { + createIssue := func(options *piperGithub.CreateIssueOptions) (*github.Issue, error) { resultChunks = append(resultChunks, string(options.Body)) - return nil + return nil, nil } // test @@ -103,9 +104,9 @@ func TestTransformConfig(t *testing.T) { } options := piperGithub.CreateIssueOptions{} resultChunks := []string{} - createIssue := func(options *piperGithub.CreateIssueOptions) error { + createIssue := func(options *piperGithub.CreateIssueOptions) (*github.Issue, error) { resultChunks = append(resultChunks, string(options.Body)) - return nil + return nil, nil } // test err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue) @@ -128,9 +129,9 @@ func TestTransformConfig(t *testing.T) { config := githubCreateIssueOptions{ChunkSize: 100} options := piperGithub.CreateIssueOptions{} resultChunks := []string{} - createIssue := func(options *piperGithub.CreateIssueOptions) error { + createIssue := func(options *piperGithub.CreateIssueOptions) (*github.Issue, error) { resultChunks = append(resultChunks, string(options.Body)) - return nil + return nil, nil } // test err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue) From aae3e81a4060e6f37a50d24051110dcf859900d3 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Wed, 14 Dec 2022 21:56:44 +0300 Subject: [PATCH 12/16] fix fmt --- cmd/githubCreateIssue_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/githubCreateIssue_test.go b/cmd/githubCreateIssue_test.go index 88e39c27b0..df86574ef8 100644 --- a/cmd/githubCreateIssue_test.go +++ b/cmd/githubCreateIssue_test.go @@ -3,9 +3,9 @@ package cmd import ( "testing" - github "github.com/google/go-github/v45/github" piperGithub "github.com/SAP/jenkins-library/pkg/github" "github.com/SAP/jenkins-library/pkg/mock" + github "github.com/google/go-github/v45/github" "github.com/stretchr/testify/assert" ) From 3f57b7ecd2363f4224cdefa5b406bfbf5f862953 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Wed, 14 Dec 2022 22:04:00 +0300 Subject: [PATCH 13/16] add missed change --- pkg/github/github.go | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/pkg/github/github.go b/pkg/github/github.go index c5977f9874..88894501a7 100644 --- a/pkg/github/github.go +++ b/pkg/github/github.go @@ -27,15 +27,16 @@ type githubCreateCommentService interface { // CreateIssueOptions to configure the creation type CreateIssueOptions struct { - APIURL string `json:"apiUrl,omitempty"` - Assignees []string `json:"assignees,omitempty"` - Body []byte `json:"body,omitempty"` - Owner string `json:"owner,omitempty"` - Repository string `json:"repository,omitempty"` - Title string `json:"title,omitempty"` - UpdateExisting bool `json:"updateExisting,omitempty"` - Token string `json:"token,omitempty"` - TrustedCerts []string `json:"trustedCerts,omitempty"` + APIURL string `json:"apiUrl,omitempty"` + Assignees []string `json:"assignees,omitempty"` + Body []byte `json:"body,omitempty"` + Owner string `json:"owner,omitempty"` + Repository string `json:"repository,omitempty"` + Title string `json:"title,omitempty"` + UpdateExisting bool `json:"updateExisting,omitempty"` + Token string `json:"token,omitempty"` + TrustedCerts []string `json:"trustedCerts,omitempty"` + Issue *github.Issue `json:"issue,omitempty"` } // NewClient creates a new GitHub client using an OAuth token for authentication @@ -74,15 +75,15 @@ func NewClient(token, apiURL, uploadURL string, trustedCerts []string) (context. return ctx, client, nil } -func CreateIssue(ghCreateIssueOptions *CreateIssueOptions) error { +func CreateIssue(ghCreateIssueOptions *CreateIssueOptions) (*github.Issue, error) { ctx, client, err := NewClient(ghCreateIssueOptions.Token, ghCreateIssueOptions.APIURL, "", ghCreateIssueOptions.TrustedCerts) if err != nil { - return errors.Wrap(err, "failed to get GitHub client") + return nil, errors.Wrap(err, "failed to get GitHub client") } return createIssueLocal(ctx, ghCreateIssueOptions, client.Issues, client.Search, client.Issues) } -func createIssueLocal(ctx context.Context, ghCreateIssueOptions *CreateIssueOptions, ghCreateIssueService githubCreateIssueService, ghSearchIssuesService githubSearchIssuesService, ghCreateCommentService githubCreateCommentService) error { +func createIssueLocal(ctx context.Context, ghCreateIssueOptions *CreateIssueOptions, ghCreateIssueService githubCreateIssueService, ghSearchIssuesService githubSearchIssuesService, ghCreateCommentService githubCreateCommentService) (*github.Issue, error) { issue := github.IssueRequest{ Title: &ghCreateIssueOptions.Title, } @@ -99,16 +100,17 @@ func createIssueLocal(ctx context.Context, ghCreateIssueOptions *CreateIssueOpti issue.Assignees = &[]string{} } - var existingIssue *github.Issue = nil + var existingIssue *github.Issue = ghCreateIssueOptions.Issue if ghCreateIssueOptions.UpdateExisting { + if existingIssue == nil { queryString := fmt.Sprintf("is:open is:issue repo:%v/%v in:title %v", ghCreateIssueOptions.Owner, ghCreateIssueOptions.Repository, ghCreateIssueOptions.Title) searchResult, resp, err := ghSearchIssuesService.Issues(ctx, queryString, nil) if err != nil { if resp != nil { log.Entry().Errorf("GitHub search issue returned response code %v", resp.Status) } - return errors.Wrap(err, "error occurred when looking for existing issue") + return nil, errors.Wrap(err, "error occurred when looking for existing issue") } else { for _, value := range searchResult.Issues { if value != nil && *value.Title == ghCreateIssueOptions.Title { @@ -116,6 +118,7 @@ func createIssueLocal(ctx context.Context, ghCreateIssueOptions *CreateIssueOpti } } } + } if existingIssue != nil { comment := &github.IssueComment{Body: issue.Body} @@ -124,7 +127,7 @@ func createIssueLocal(ctx context.Context, ghCreateIssueOptions *CreateIssueOpti if resp != nil { log.Entry().Errorf("GitHub create comment returned response code %v", resp.Status) } - return errors.Wrap(err, "error occurred when adding comment to existing issue") + return nil, errors.Wrap(err, "error occurred when adding comment to existing issue") } } } @@ -135,10 +138,11 @@ func createIssueLocal(ctx context.Context, ghCreateIssueOptions *CreateIssueOpti if resp != nil { log.Entry().Errorf("GitHub create issue returned response code %v", resp.Status) } - return errors.Wrap(err, "error occurred when creating issue") + return nil, errors.Wrap(err, "error occurred when creating issue") } log.Entry().Debugf("New issue created: %v", newIssue) + existingIssue = newIssue } - return nil + return existingIssue, nil } From e43daedb578af71a56849b47e5f51f7814515606 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Wed, 14 Dec 2022 22:13:40 +0300 Subject: [PATCH 14/16] fix fmt --- pkg/github/github.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/github/github.go b/pkg/github/github.go index 88894501a7..bc814f2780 100644 --- a/pkg/github/github.go +++ b/pkg/github/github.go @@ -104,21 +104,21 @@ func createIssueLocal(ctx context.Context, ghCreateIssueOptions *CreateIssueOpti if ghCreateIssueOptions.UpdateExisting { if existingIssue == nil { - queryString := fmt.Sprintf("is:open is:issue repo:%v/%v in:title %v", ghCreateIssueOptions.Owner, ghCreateIssueOptions.Repository, ghCreateIssueOptions.Title) - searchResult, resp, err := ghSearchIssuesService.Issues(ctx, queryString, nil) - if err != nil { - if resp != nil { - log.Entry().Errorf("GitHub search issue returned response code %v", resp.Status) - } - return nil, errors.Wrap(err, "error occurred when looking for existing issue") - } else { - for _, value := range searchResult.Issues { - if value != nil && *value.Title == ghCreateIssueOptions.Title { - existingIssue = value + queryString := fmt.Sprintf("is:open is:issue repo:%v/%v in:title %v", ghCreateIssueOptions.Owner, ghCreateIssueOptions.Repository, ghCreateIssueOptions.Title) + searchResult, resp, err := ghSearchIssuesService.Issues(ctx, queryString, nil) + if err != nil { + if resp != nil { + log.Entry().Errorf("GitHub search issue returned response code %v", resp.Status) + } + return nil, errors.Wrap(err, "error occurred when looking for existing issue") + } else { + for _, value := range searchResult.Issues { + if value != nil && *value.Title == ghCreateIssueOptions.Title { + existingIssue = value + } } } } - } if existingIssue != nil { comment := &github.IssueComment{Body: issue.Body} From 0fcf604c9402e397d2426fd40f774d42ac353f62 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Wed, 14 Dec 2022 23:03:12 +0300 Subject: [PATCH 15/16] add test for github pkg --- pkg/github/github.go | 3 ++- pkg/github/github_test.go | 42 +++++++++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/pkg/github/github.go b/pkg/github/github.go index bc814f2780..c70e048091 100644 --- a/pkg/github/github.go +++ b/pkg/github/github.go @@ -100,9 +100,10 @@ func createIssueLocal(ctx context.Context, ghCreateIssueOptions *CreateIssueOpti issue.Assignees = &[]string{} } - var existingIssue *github.Issue = ghCreateIssueOptions.Issue + var existingIssue *github.Issue = nil if ghCreateIssueOptions.UpdateExisting { + existingIssue = ghCreateIssueOptions.Issue if existingIssue == nil { queryString := fmt.Sprintf("is:open is:issue repo:%v/%v in:title %v", ghCreateIssueOptions.Owner, ghCreateIssueOptions.Repository, ghCreateIssueOptions.Title) searchResult, resp, err := ghSearchIssuesService.Issues(ctx, queryString, nil) diff --git a/pkg/github/github_test.go b/pkg/github/github_test.go index a9e388bcdd..e5e4874988 100644 --- a/pkg/github/github_test.go +++ b/pkg/github/github_test.go @@ -80,11 +80,13 @@ func (g *ghSearchIssuesMock) Issues(ctx context.Context, query string, opts *git type ghCreateCommentMock struct { issueComment *github.IssueComment + issueNumber int issueCommentError error } func (g *ghCreateCommentMock) CreateComment(ctx context.Context, owner string, repo string, number int, comment *github.IssueComment) (*github.IssueComment, *github.Response, error) { g.issueComment = comment + g.issueNumber = number ghRes := github.Response{Response: &http.Response{Status: "200"}} if g.issueCommentError != nil { ghRes.Status = "401" @@ -114,7 +116,7 @@ func TestRunGithubCreateIssue(t *testing.T) { } // test - err := createIssueLocal(ctx, &config, &ghCreateIssueService, &ghSearchIssuesMock, &ghCreateCommentMock) + _, err := createIssueLocal(ctx, &config, &ghCreateIssueService, &ghSearchIssuesMock, &ghCreateCommentMock) // assert assert.NoError(t, err) @@ -143,7 +145,7 @@ func TestRunGithubCreateIssue(t *testing.T) { } // test - err := createIssueLocal(ctx, &config, nil, &ghSearchIssuesMock, &ghCreateCommentMock) + _, err := createIssueLocal(ctx, &config, nil, &ghSearchIssuesMock, &ghCreateCommentMock) // assert assert.NoError(t, err) @@ -154,6 +156,38 @@ func TestRunGithubCreateIssue(t *testing.T) { assert.Equal(t, "This is my test body", ghCreateCommentMock.issueComment.GetBody()) }) + t.Run("Success update existing based on instance", func(t *testing.T) { + // init + ghSearchIssuesMock := ghSearchIssuesMock{ + issueID: 1, + } + ghCreateCommentMock := ghCreateCommentMock{} + var id int64 = 2 + var number int = 123 + config := CreateIssueOptions{ + Owner: "TEST", + Repository: "test", + Body: []byte("This is my test body"), + Title: "This is my title", + Assignees: []string{"userIdOne", "userIdTwo"}, + UpdateExisting: true, + Issue: &github.Issue{ + ID: &id, + Number: &number, + }, + } + + // test + _, err := createIssueLocal(ctx, &config, nil, &ghSearchIssuesMock, &ghCreateCommentMock) + + // assert + assert.NoError(t, err) + assert.Nil(t, ghSearchIssuesMock.issuesSearchResult) + assert.NotNil(t, ghCreateCommentMock.issueComment) + assert.Equal(t, ghCreateCommentMock.issueNumber, number) + assert.Equal(t, "This is my test body", ghCreateCommentMock.issueComment.GetBody()) + }) + t.Run("Empty body", func(t *testing.T) { // init ghCreateIssueService := ghCreateIssueMock{ @@ -173,7 +207,7 @@ func TestRunGithubCreateIssue(t *testing.T) { } // test - err := createIssueLocal(ctx, &config, &ghCreateIssueService, &ghSearchIssuesMock, &ghCreateCommentMock) + _, err := createIssueLocal(ctx, &config, &ghCreateIssueService, &ghSearchIssuesMock, &ghCreateCommentMock) // assert assert.NoError(t, err) @@ -194,7 +228,7 @@ func TestRunGithubCreateIssue(t *testing.T) { } // test - err := createIssueLocal(ctx, &config, &ghCreateIssueService, nil, nil) + _, err := createIssueLocal(ctx, &config, &ghCreateIssueService, nil, nil) // assert assert.EqualError(t, err, "error occurred when creating issue: error creating issue") From fa68d3e4d032bdc86b85f29b1f6ddd825161d701 Mon Sep 17 00:00:00 2001 From: Raman_Susla Date: Wed, 14 Dec 2022 23:07:12 +0300 Subject: [PATCH 16/16] fix fmt github test --- pkg/github/github_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/github/github_test.go b/pkg/github/github_test.go index e5e4874988..b61013e807 100644 --- a/pkg/github/github_test.go +++ b/pkg/github/github_test.go @@ -80,7 +80,7 @@ func (g *ghSearchIssuesMock) Issues(ctx context.Context, query string, opts *git type ghCreateCommentMock struct { issueComment *github.IssueComment - issueNumber int + issueNumber int issueCommentError error } @@ -172,7 +172,7 @@ func TestRunGithubCreateIssue(t *testing.T) { Assignees: []string{"userIdOne", "userIdTwo"}, UpdateExisting: true, Issue: &github.Issue{ - ID: &id, + ID: &id, Number: &number, }, }