You've already forked sap-jenkins-library
							
							
				mirror of
				https://github.com/SAP/jenkins-library.git
				synced 2025-10-30 23:57:50 +02:00 
			
		
		
		
	feat(githubCreateIssue): allow content via file (#2557)
This commit is contained in:
		| @@ -2,6 +2,8 @@ package cmd | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/log" | ||||
| 	"github.com/SAP/jenkins-library/pkg/telemetry" | ||||
| @@ -20,22 +22,37 @@ func githubCreateIssue(config githubCreateIssueOptions, telemetryData *telemetry | ||||
| 	if err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("Failed to get GitHub client") | ||||
| 	} | ||||
| 	err = runGithubCreateIssue(ctx, &config, telemetryData, client.Issues) | ||||
| 	err = runGithubCreateIssue(ctx, &config, telemetryData, client.Issues, ioutil.ReadFile) | ||||
| 	if err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("Failed to comment on issue") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func runGithubCreateIssue(ctx context.Context, config *githubCreateIssueOptions, _ *telemetry.CustomData, ghCreateIssueService githubCreateIssueService) error { | ||||
| func runGithubCreateIssue(ctx context.Context, config *githubCreateIssueOptions, _ *telemetry.CustomData, ghCreateIssueService githubCreateIssueService, readFile func(string) ([]byte, error)) error { | ||||
|  | ||||
| 	if len(config.Body)+len(config.BodyFilePath) == 0 { | ||||
| 		return fmt.Errorf("either parameter `body` or parameter `bodyFilePath` is required") | ||||
| 	} | ||||
|  | ||||
| 	issue := github.IssueRequest{ | ||||
| 		Body:  &config.Body, | ||||
| 		Title: &config.Title, | ||||
| 	} | ||||
|  | ||||
| 	if len(config.Body) > 0 { | ||||
| 		issue.Body = &config.Body | ||||
| 	} else { | ||||
| 		issueContent, err := readFile(config.BodyFilePath) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrapf(err, "failed to read file '%v'", config.BodyFilePath) | ||||
| 		} | ||||
| 		body := string(issueContent) | ||||
| 		issue.Body = &body | ||||
| 	} | ||||
|  | ||||
| 	newIssue, resp, err := ghCreateIssueService.Create(ctx, config.Owner, config.Repository, &issue) | ||||
| 	if err != nil { | ||||
| 		log.Entry().Errorf("GitHub response code %v", resp.Status) | ||||
| 		return errors.Wrap(err, "Error occurred when creating issue") | ||||
| 		return errors.Wrap(err, "error occurred when creating issue") | ||||
| 	} | ||||
| 	log.Entry().Debugf("New issue created: %v", newIssue) | ||||
|  | ||||
|   | ||||
| @@ -14,12 +14,13 @@ import ( | ||||
| ) | ||||
|  | ||||
| type githubCreateIssueOptions struct { | ||||
| 	APIURL     string `json:"apiUrl,omitempty"` | ||||
| 	Body       string `json:"body,omitempty"` | ||||
| 	Owner      string `json:"owner,omitempty"` | ||||
| 	Repository string `json:"repository,omitempty"` | ||||
| 	Title      string `json:"title,omitempty"` | ||||
| 	Token      string `json:"token,omitempty"` | ||||
| 	APIURL       string `json:"apiUrl,omitempty"` | ||||
| 	Body         string `json:"body,omitempty"` | ||||
| 	BodyFilePath string `json:"bodyFilePath,omitempty"` | ||||
| 	Owner        string `json:"owner,omitempty"` | ||||
| 	Repository   string `json:"repository,omitempty"` | ||||
| 	Title        string `json:"title,omitempty"` | ||||
| 	Token        string `json:"token,omitempty"` | ||||
| } | ||||
|  | ||||
| // GithubCreateIssueCommand Create a new GitHub issue. | ||||
| @@ -84,13 +85,13 @@ 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().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.") | ||||
| 	cmd.Flags().StringVar(&stepConfig.Repository, "repository", os.Getenv("PIPER_repository"), "Name of the GitHub repository.") | ||||
| 	cmd.Flags().StringVar(&stepConfig.Title, "title", os.Getenv("PIPER_title"), "Defines the title for the Issue.") | ||||
| 	cmd.Flags().StringVar(&stepConfig.Token, "token", os.Getenv("PIPER_token"), "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line.") | ||||
|  | ||||
| 	cmd.MarkFlagRequired("apiUrl") | ||||
| 	cmd.MarkFlagRequired("body") | ||||
| 	cmd.MarkFlagRequired("owner") | ||||
| 	cmd.MarkFlagRequired("repository") | ||||
| 	cmd.MarkFlagRequired("title") | ||||
| @@ -121,7 +122,15 @@ func githubCreateIssueMetadata() config.StepData { | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   true, | ||||
| 						Mandatory:   false, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "bodyFilePath", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   false, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
|   | ||||
| @@ -6,6 +6,8 @@ import ( | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/mock" | ||||
|  | ||||
| 	"github.com/google/go-github/v32/github" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
| @@ -40,6 +42,7 @@ func TestRunGithubCreateIssue(t *testing.T) { | ||||
|  | ||||
| 	t.Run("Success", func(t *testing.T) { | ||||
| 		// init | ||||
| 		filesMock := mock.FilesMock{} | ||||
| 		ghCreateIssueService := ghCreateIssueMock{ | ||||
| 			issueID: 1, | ||||
| 		} | ||||
| @@ -51,7 +54,7 @@ func TestRunGithubCreateIssue(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		// test | ||||
| 		err := runGithubCreateIssue(ctx, &config, nil, &ghCreateIssueService) | ||||
| 		err := runGithubCreateIssue(ctx, &config, nil, &ghCreateIssueService, filesMock.FileRead) | ||||
|  | ||||
| 		// assert | ||||
| 		assert.NoError(t, err) | ||||
| @@ -61,17 +64,73 @@ func TestRunGithubCreateIssue(t *testing.T) { | ||||
| 		assert.Equal(t, config.Title, ghCreateIssueService.issue.GetTitle()) | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Success - body from file", func(t *testing.T) { | ||||
| 		// init | ||||
| 		filesMock := mock.FilesMock{} | ||||
| 		filesMock.AddFile("test.md", []byte("Test markdown")) | ||||
| 		ghCreateIssueService := ghCreateIssueMock{ | ||||
| 			issueID: 1, | ||||
| 		} | ||||
| 		config := githubCreateIssueOptions{ | ||||
| 			Owner:        "TEST", | ||||
| 			Repository:   "test", | ||||
| 			BodyFilePath: "test.md", | ||||
| 			Title:        "This is my title", | ||||
| 		} | ||||
|  | ||||
| 		// test | ||||
| 		err := runGithubCreateIssue(ctx, &config, nil, &ghCreateIssueService, filesMock.FileRead) | ||||
|  | ||||
| 		// assert | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.Equal(t, config.Owner, ghCreateIssueService.owner) | ||||
| 		assert.Equal(t, config.Repository, ghCreateIssueService.repo) | ||||
| 		assert.Equal(t, "Test markdown", ghCreateIssueService.issue.GetBody()) | ||||
| 		assert.Equal(t, config.Title, ghCreateIssueService.issue.GetTitle()) | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Error", func(t *testing.T) { | ||||
| 		// init | ||||
| 		filesMock := mock.FilesMock{} | ||||
| 		ghCreateIssueService := ghCreateIssueMock{ | ||||
| 			issueError: fmt.Errorf("error creating issue"), | ||||
| 		} | ||||
| 		config := githubCreateIssueOptions{ | ||||
| 			Body: "test content", | ||||
| 		} | ||||
|  | ||||
| 		// test | ||||
| 		err := runGithubCreateIssue(ctx, &config, nil, &ghCreateIssueService, filesMock.FileRead) | ||||
|  | ||||
| 		// assert | ||||
| 		assert.EqualError(t, err, "error occurred when creating issue: error creating issue") | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Error - missing issue body", func(t *testing.T) { | ||||
| 		// init | ||||
| 		filesMock := mock.FilesMock{} | ||||
| 		ghCreateIssueService := ghCreateIssueMock{} | ||||
| 		config := githubCreateIssueOptions{} | ||||
|  | ||||
| 		// test | ||||
| 		err := runGithubCreateIssue(ctx, &config, nil, &ghCreateIssueService) | ||||
| 		err := runGithubCreateIssue(ctx, &config, nil, &ghCreateIssueService, filesMock.FileRead) | ||||
|  | ||||
| 		// assert | ||||
| 		assert.EqualError(t, err, "Error occurred when creating issue: error creating issue") | ||||
| 		assert.EqualError(t, err, "either parameter `body` or parameter `bodyFilePath` is required") | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Error - missing body file", func(t *testing.T) { | ||||
| 		// init | ||||
| 		filesMock := mock.FilesMock{} | ||||
| 		ghCreateIssueService := ghCreateIssueMock{} | ||||
| 		config := githubCreateIssueOptions{ | ||||
| 			BodyFilePath: "test.md", | ||||
| 		} | ||||
|  | ||||
| 		// test | ||||
| 		err := runGithubCreateIssue(ctx, &config, nil, &ghCreateIssueService, filesMock.FileRead) | ||||
|  | ||||
| 		// assert | ||||
| 		assert.Contains(t, fmt.Sprint(err), "failed to read file 'test.md'") | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -31,7 +31,13 @@ spec: | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         type: string | ||||
|         mandatory: true | ||||
|       - name: bodyFilePath | ||||
|         description: Defines the path to a file containing the markdown content for the issue. This can be used instead of [`body`](#body) | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         type: string | ||||
|       - name: owner | ||||
|         aliases: | ||||
|           - name: githubOrg | ||||
|   | ||||
		Reference in New Issue
	
	Block a user