Repository: lindell/multi-gitter
Pull request #28 (2020-11-23 07:01:47)

feat!: added output option to differentiate log and other output
this change does also include the renaming of some options to keep
concistency


Patch:
diff --git a/cmd/print.go b/cmd/print.go
index 84b33b6..f71af9b 100755
--- a/cmd/print.go
+++ b/cmd/print.go
@@ -33,10 +33,10 @@ func PrintCmd() *cobra.Command {
 	}
 
 	cmd.Flags().IntP("concurrent", "C", 1, "The maximum number of concurrent runs")
-	cmd.Flags().StringP("output", "O", "-", `The file that the output of the script should be outputted to. "-" means stdout`)
 	cmd.Flags().StringP("error-output", "E", "-", `The file that the output of the script should be outputted to. "-" means stderr`)
 	cmd.Flags().AddFlagSet(platformFlags())
 	cmd.Flags().AddFlagSet(logFlags(""))
+	cmd.Flags().AddFlagSet(outputFlag())
 
 	return cmd
 }
diff --git a/cmd/root.go b/cmd/root.go
index 11e61f3..7bb14fd 100755
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -45,12 +45,13 @@ func platformFlags() *flag.FlagSet {
 	flags.StringP("gh-base-url", "g", "", "Base URL of the (v3) GitHub API, needs to be changed if GitHub enterprise is used.")
 	flags.StringP("token", "T", "", "The GitHub/GitLab personal access token. Can also be set using the GITHUB_TOKEN/GITLAB_TOKEN environment variable.")
 
-	flags.StringSliceP("org", "o", nil, "The name of a GitHub organization. All repositories in that organization will be used.")
+	flags.StringSliceP("org", "O", nil, "The name of a GitHub organization. All repositories in that organization will be used.")
 	flags.StringSliceP("group", "G", nil, "The name of a GitLab organization. All repositories in that group will be used.")
-	flags.StringSliceP("user", "u", nil, "The name of a user. All repositories owned by that user will be used.")
+	flags.StringSliceP("user", "U", nil, "The name of a user. All repositories owned by that user will be used.")
 	flags.StringSliceP("repo", "R", nil, "The name, including owner of a GitHub repository in the format \"ownerName/repoName\"")
-	flags.StringSliceP("project", "p", nil, "The name, including owner of a GitLab project in the format \"ownerName/repoName\"")
-	flags.StringP("platform", "P", "github", "The platform that is used. Available values: github, gitlab")
+	flags.StringSliceP("project", "P", nil, "The name, including owner of a GitLab project in the format \"ownerName/repoName\"")
+
+	flags.StringP("platform", "p", "github", "The platform that is used. Available values: github, gitlab")
 
 	return flags
 }
@@ -104,6 +105,14 @@ func logFlagInit(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
+func outputFlag() *flag.FlagSet {
+	flags := flag.NewFlagSet("output", flag.ExitOnError)
+
+	flags.StringP("output", "o", "-", `The file that the output of the script should be outputted to. "-" means stdout`)
+
+	return flags
+}
+
 // OverrideVersionController can be set to force a specific version controller to be used
 // This is used to override the version controller with a mock, to be used during testing
 var OverrideVersionController multigitter.VersionController = nil
diff --git a/cmd/run.go b/cmd/run.go
index b314e8d..b1ef19c 100755
--- a/cmd/run.go
+++ b/cmd/run.go
@@ -46,6 +46,7 @@ func RunCmd() *cobra.Command {
 	cmd.Flags().StringP("author-email", "", "", "If set, this fields will be used as the email of the committer")
 	cmd.Flags().AddFlagSet(platformFlags())
 	cmd.Flags().AddFlagSet(logFlags("-"))
+	cmd.Flags().AddFlagSet(outputFlag())
 
 	return cmd
 }
@@ -63,6 +64,7 @@ func run(cmd *cobra.Command, args []string) error {
 	dryRun, _ := flag.GetBool("dry-run")
 	authorName, _ := flag.GetString("author-name")
 	authorEmail, _ := flag.GetString("author-email")
+	strOutput, _ := flag.GetString("output")
 
 	token, err := getToken(flag)
 	if err != nil {
@@ -75,6 +77,11 @@ func run(cmd *cobra.Command, args []string) error {
 		return errors.New("concurrent runs can't be less than one")
 	}
 
+	output, err := fileOutput(strOutput, os.Stdout)
+	if err != nil {
+		return err
+	}
+
 	// Set commit message based on pr title and body or the reverse
 	if commitMessage == "" && prTitle == "" {
 		return errors.New("pull request title or commit message must be set")
@@ -144,6 +151,8 @@ func run(cmd *cobra.Command, args []string) error {
 		FeatureBranch: branchName,
 		Token:         token,
 
+		Output: output,
+
 		VersionController: vc,
 
 		CommitMessage:    commitMessage,
diff --git a/cmd/status.go b/cmd/status.go
index f6ef97c..93063d1 100644
--- a/cmd/status.go
+++ b/cmd/status.go
@@ -2,6 +2,7 @@ package cmd
 
 import (
 	"context"
+	"os"
 
 	"github.com/lindell/multi-gitter/internal/multigitter"
 	"github.com/spf13/cobra"
@@ -21,6 +22,7 @@ func StatusCmd() *cobra.Command {
 	cmd.Flags().StringP("branch", "B", "multi-gitter-branch", "The name of the branch where changes are committed.")
 	cmd.Flags().AddFlagSet(platformFlags())
 	cmd.Flags().AddFlagSet(logFlags("-"))
+	cmd.Flags().AddFlagSet(outputFlag())
 
 	return cmd
 }
@@ -29,15 +31,23 @@ func status(cmd *cobra.Command, args []string) error {
 	flag := cmd.Flags()
 
 	branchName, _ := flag.GetString("branch")
+	strOutput, _ := flag.GetString("output")
 
 	vc, err := getVersionController(flag)
 	if err != nil {
 		return err
 	}
 
+	output, err := fileOutput(strOutput, os.Stdout)
+	if err != nil {
+		return err
+	}
+
 	statuser := multigitter.Statuser{
 		VersionController: vc,
 
+		Output: output,
+
 		FeatureBranch: branchName,
 	}
 
diff --git a/internal/multigitter/run.go b/internal/multigitter/run.go
index c3b8db9..481eaae 100755
--- a/internal/multigitter/run.go
+++ b/internal/multigitter/run.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"io"
 	"io/ioutil"
 	"math/rand"
 	"os"
@@ -36,6 +37,8 @@ type Runner struct {
 	FeatureBranch string
 	Token         string
 
+	Output io.Writer
+
 	CommitMessage    string
 	PullRequestTitle string
 	PullRequestBody  string
@@ -59,7 +62,7 @@ func (r Runner) Run(ctx context.Context) error {
 	rc := repocounter.NewCounter()
 	defer func() {
 		if info := rc.Info(); info != "" {
-			fmt.Fprint(log.StandardLogger().Out, info)
+			fmt.Fprint(r.Output, info)
 		}
 	}()
 
diff --git a/internal/multigitter/status.go b/internal/multigitter/status.go
index df9744b..94940d0 100644
--- a/internal/multigitter/status.go
+++ b/internal/multigitter/status.go
@@ -3,14 +3,15 @@ package multigitter
 import (
 	"context"
 	"fmt"
-
-	log "github.com/sirupsen/logrus"
+	"io"
 )
 
 // Statuser checks the statuses of pull requests
 type Statuser struct {
 	VersionController VersionController
 
+	Output io.Writer
+
 	FeatureBranch string
 }
 
@@ -22,7 +23,7 @@ func (s Statuser) Statuses(ctx context.Context) error {
 	}
 
 	for _, pr := range prs {
-		fmt.Fprintf(log.StandardLogger().Out, "%s: %s\n", pr.String(), pr.Status())
+		fmt.Fprintf(s.Output, "%s: %s\n", pr.String(), pr.Status())
 	}
 
 	return nil


Test patch:
diff --git a/tests/story_test.go b/tests/story_test.go
index 8f2f390..c0b2aec 100644
--- a/tests/story_test.go
+++ b/tests/story_test.go
@@ -23,6 +23,7 @@ func TestStory(t *testing.T) {
 	cmd.OverrideVersionController = vcMock
 
 	tmpDir, err := ioutil.TempDir(os.TempDir(), "multi-git-test-run-")
+	defer os.RemoveAll(tmpDir)
 	assert.NoError(t, err)
 
 	workingDir, err := os.Getwd()
@@ -35,11 +36,11 @@ func TestStory(t *testing.T) {
 	vcMock.AddRepository(changeRepo2)
 	vcMock.AddRepository(noChangeRepo)
 
-	runLogFile := path.Join(tmpDir, "run-log.txt")
+	runOutFile := path.Join(tmpDir, "run-log.txt")
 
 	command := cmd.RootCmd()
 	command.SetArgs([]string{"run",
-		"--log-file", runLogFile,
+		"--output", runOutFile,
 		"--author-name", "Test Author",
 		"--author-email", "test@example.com",
 		"-B", "custom-branch-name",
@@ -61,32 +62,32 @@ func TestStory(t *testing.T) {
 	assert.Equal(t, []byte("i like bananas"), data)
 
 	// Verify that the output was correct
-	runLogData, err := ioutil.ReadFile(runLogFile)
+	runOutData, err := ioutil.ReadFile(runOutFile)
 	require.NoError(t, err)
-	assert.Contains(t, string(runLogData), `
-No data was changed:
+	assert.Equal(t, string(runOutData), `No data was changed:
   should-not-change
 Repositories with a successful run:
   should-change
-  should-change-2`)
+  should-change-2
+`)
 
 	//
 	// Status
 	//
-	statusLogFile := path.Join(tmpDir, "status-log.txt")
+	statusOutFile := path.Join(tmpDir, "status-log.txt")
 
 	command = cmd.RootCmd()
 	command.SetArgs([]string{"status",
-		"--log-file", statusLogFile,
+		"--output", statusOutFile,
 		"-B", "custom-branch-name",
 	})
 	err = command.Execute()
 	assert.NoError(t, err)
 
 	// Verify that the output was correct
-	statusLogData, err := ioutil.ReadFile(statusLogFile)
+	statusOutData, err := ioutil.ReadFile(statusOutFile)
 	require.NoError(t, err)
-	assert.Equal(t, "should-change/XX: Pending\nshould-change-2/XX: Pending\n", string(statusLogData))
+	assert.Equal(t, "should-change/XX: Pending\nshould-change-2/XX: Pending\n", string(statusOutData))
 
 	// One of the created PRs is set to succeeded
 	vcMock.SetPRStatus("should-change", "custom-branch-name", domain.PullRequestStatusSuccess)
@@ -113,20 +114,20 @@ Repositories with a successful run:
 	//
 	// After Merge Status
 	//
-	afterMergeStatusLogFile := path.Join(tmpDir, "after-merge-status-log.txt")
+	afterMergeStatusOutFile := path.Join(tmpDir, "after-merge-status-log.txt")
 
 	command = cmd.RootCmd()
 	command.SetArgs([]string{"status",
-		"--log-file", afterMergeStatusLogFile,
+		"--output", afterMergeStatusOutFile,
 		"-B", "custom-branch-name",
 	})
 	err = command.Execute()
 	assert.NoError(t, err)
 
 	// Verify that the output was correct
-	afterMergeStatusLogData, err := ioutil.ReadFile(afterMergeStatusLogFile)
+	afterMergeStatusOutData, err := ioutil.ReadFile(afterMergeStatusOutFile)
 	require.NoError(t, err)
-	assert.Equal(t, "should-change/XX: Merged\nshould-change-2/XX: Pending\n", string(afterMergeStatusLogData))
+	assert.Equal(t, "should-change/XX: Merged\nshould-change-2/XX: Pending\n", string(afterMergeStatusOutData))
 
 	//
 	// Close
@@ -150,18 +151,18 @@ Repositories with a successful run:
 	//
 	// After Close Status
 	//
-	afterCloseStatusLogFile := path.Join(tmpDir, "after-close-status-log.txt")
+	afterCloseStatusOutFile := path.Join(tmpDir, "after-close-status-log.txt")
 
 	command = cmd.RootCmd()
 	command.SetArgs([]string{"status",
-		"--log-file", afterCloseStatusLogFile,
+		"--output", afterCloseStatusOutFile,
 		"-B", "custom-branch-name",
 	})
 	err = command.Execute()
 	assert.NoError(t, err)
 
 	// Verify that the output was correct
-	afterCloseStatusLogData, err := ioutil.ReadFile(afterCloseStatusLogFile)
+	afterCloseStatusOutData, err := ioutil.ReadFile(afterCloseStatusOutFile)
 	require.NoError(t, err)
-	assert.Equal(t, "should-change/XX: Merged\nshould-change-2/XX: Closed\n", string(afterCloseStatusLogData))
+	assert.Equal(t, "should-change/XX: Merged\nshould-change-2/XX: Closed\n", string(afterCloseStatusOutData))
 }