Skip to content

Commit

Permalink
githubCreateIssue_fix (SAP#4151)
Browse files Browse the repository at this point in the history
* extend githubCreateIssue to handle long body

Co-authored-by: Jordi van Liempt <[email protected]>
  • Loading branch information
2 people authored and maxatsap committed Jul 23, 2024
1 parent 46c07e8 commit 54cb5e1
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 59 deletions.
3 changes: 2 additions & 1 deletion cmd/checkmarxExecuteScan.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion cmd/fortifyExecuteScan.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
74 changes: 58 additions & 16 deletions cmd/githubCreateIssue.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,71 @@ 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"
github "github.com/google/go-github/v45/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, piperGithub.CreateIssue)
if err != nil {
log.Entry().WithError(err).Fatal("Failed to comment on issue")
}
}

func runGithubCreateIssue(config *githubCreateIssueOptions, _ *telemetry.CustomData) error {

options := piperGithub.CreateIssueOptions{}
err := transformConfig(config, &options, ioutil.ReadFile)
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])
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)
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
Expand All @@ -38,16 +75,21 @@ 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")
func getChunks(value []rune, chunkSize int) []string {
chunks := []string{}
length := len(value)
if length == 0 {
return []string{""}
}
if len(config.Body) == 0 {
issueContent, err := readFile(config.BodyFilePath)
if err != nil {
return errors.Wrapf(err, "failed to read file '%v'", config.BodyFilePath)
for i := 0; i < length; i += chunkSize {
to := length
if to > i+chunkSize {
to = i + chunkSize
}
options.Body = issueContent
chunks = append(chunks, string(value[i:to]))
}
return nil
return chunks
}
11 changes: 11 additions & 0 deletions cmd/githubCreateIssue_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 70 additions & 11 deletions cmd/githubCreateIssue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,57 @@ package cmd
import (
"testing"

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"

piperGithub "github.com/SAP/jenkins-library/pkg/github"
)

func TestGetChunk(t *testing.T) {
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 string",
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()

Expand All @@ -22,22 +66,28 @@ 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) (*github.Issue, error) {
resultChunks = append(resultChunks, string(options.Body))
return nil, nil
}

// test
err := transformConfig(&config, &options, filesMock.FileRead)
err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue)

// assert
assert.NoError(t, err)
assert.Equal(t, config.Token, options.Token)
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) {
Expand All @@ -50,32 +100,41 @@ func TestTransformConfig(t *testing.T) {
BodyFilePath: "test.md",
Title: "This is my title",
Assignees: []string{"userIdOne", "userIdTwo"},
ChunkSize: 100,
}
options := piperGithub.CreateIssueOptions{}

resultChunks := []string{}
createIssue := func(options *piperGithub.CreateIssueOptions) (*github.Issue, error) {
resultChunks = append(resultChunks, string(options.Body))
return nil, nil
}
// test
err := transformConfig(&config, &options, filesMock.FileRead)
err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue)

// assert
assert.NoError(t, err)
assert.Equal(t, config.Token, options.Token)
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) {
// init
filesMock := mock.FilesMock{}
config := githubCreateIssueOptions{}
config := githubCreateIssueOptions{ChunkSize: 100}
options := piperGithub.CreateIssueOptions{}

resultChunks := []string{}
createIssue := func(options *piperGithub.CreateIssueOptions) (*github.Issue, error) {
resultChunks = append(resultChunks, string(options.Body))
return nil, nil
}
// test
err := transformConfig(&config, &options, filesMock.FileRead)
err := runGithubCreateIssue(&config, nil, &options, &filesMock, createIssue)

// assert
assert.EqualError(t, err, "either parameter `body` or parameter `bodyFilePath` is required")
Expand Down
Loading

0 comments on commit 54cb5e1

Please sign in to comment.