From 2dcd7e3a2201aba2d7e81beb77ff8ab3081f366f Mon Sep 17 00:00:00 2001 From: Sebastien Le Digabel Date: Mon, 19 Jun 2023 10:56:07 +0100 Subject: [PATCH] Optional repo file (#75) * Optional repo file Fixes #74 Adds a new flag for all commands `--repos=`, which gives the ability to select a different file from the default `repos.txt` one. * Fixing defaultOptions naming * Renaming test * Fix typo on CampaignOptions * Updates following PR - Changed error text to include filename last Signed-off-by: Sebastien Le Digabel * Adding repofile to update_pr * Rebasing after #67 The `pr-status` command was added after and needed the extra danse to include the new repo file option. Also renamed the `pr_status` package into `prstatus` as gofumpt told me packages should not include underscores. https://go.dev/blog/package-names * Changed the campaign start message with the repo filename .. addressing the PR comment. Also renamed the update_prs package name for the same reason as the pr_status one. * Fixing the parsing for foreach Adding a manual parsing of the foreach parameters and extra testing. Also added some details in the Readme * Rephrasing comment in foreach * Removing extraneous comment --------- Signed-off-by: Sebastien Le Digabel Co-authored-by: Cat from Catalyst Co-authored-by: Richard North --- README.md | 11 +++ cmd/clone/clone.go | 12 ++- cmd/commit/commit.go | 21 ++++-- cmd/create_prs/create_prs.go | 15 ++-- cmd/foreach/foreach.go | 39 +++++++++- cmd/foreach/foreach_test.go | 67 ++++++++++++++++- .../pr_status.go => prstatus/prstatus.go} | 25 +++++-- .../prstatus_test.go} | 6 +- cmd/root.go | 8 +- .../update_prs.go => updateprs/updateprs.go} | 13 +++- .../updateprs_test.go} | 5 +- internal/campaign/campaign.go | 32 +++++--- internal/campaign/campaign_test.go | 75 ++++++++++++++++--- internal/testsupport/testsupport.go | 14 +++- 14 files changed, 279 insertions(+), 64 deletions(-) rename cmd/{pr_status/pr_status.go => prstatus/prstatus.go} (92%) rename cmd/{pr_status/pr_status_test.go => prstatus/prstatus_test.go} (99%) rename cmd/{update_prs/update_prs.go => updateprs/updateprs.go} (92%) rename cmd/{update_prs/update_prs_test.go => updateprs/updateprs_test.go} (99%) diff --git a/README.md b/README.md index fd00d48..fabf73c 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,17 @@ e.g. $ gh-search --repos-with-matches YOUR_GITHUB_CODE_SEARCH_QUERY > repos.txt ``` +### Working on multiple repo files + +Occasionally you may need to work on different repo files. For instance the repos can be divided in sub categories and the same change don't apply to them the same way. +The default repo file is called `repos.txt` but you can override this with the `--repos` flag. + +```console +turbolift foreach --repos repoFile1.txt sed 's/pattern1/replacement1/g' +turbolift foreach --repos repoFile2.txt sed 's/pattern2/replacement2/g' +``` + + ### Running a mass `clone` ```turbolift clone``` diff --git a/cmd/clone/clone.go b/cmd/clone/clone.go index af61fd5..f439029 100644 --- a/cmd/clone/clone.go +++ b/cmd/clone/clone.go @@ -33,7 +33,10 @@ var ( g git.Git = git.NewRealGit() ) -var nofork bool +var ( + nofork bool + repoFile string +) func NewCloneCmd() *cobra.Command { cmd := &cobra.Command{ @@ -43,6 +46,7 @@ func NewCloneCmd() *cobra.Command { } cmd.Flags().BoolVar(&nofork, "no-fork", false, "Will not fork, just clone and create a branch.") + cmd.Flags().StringVar(&repoFile, "repos", "repos.txt", "A file containing a list of repositories to clone.") return cmd } @@ -50,8 +54,10 @@ func NewCloneCmd() *cobra.Command { func run(c *cobra.Command, _ []string) { logger := logging.NewLogger(c) - readCampaignActivity := logger.StartActivity("Reading campaign data") - dir, err := campaign.OpenCampaign() + readCampaignActivity := logger.StartActivity("Reading campaign data (%s)", repoFile) + options := campaign.NewCampaignOptions() + options.RepoFilename = repoFile + dir, err := campaign.OpenCampaign(options) if err != nil { readCampaignActivity.EndWithFailure(err) return diff --git a/cmd/commit/commit.go b/cmd/commit/commit.go index d08fc5a..858d5e7 100644 --- a/cmd/commit/commit.go +++ b/cmd/commit/commit.go @@ -16,18 +16,23 @@ package commit import ( + "os" + "path" + + "github.com/spf13/cobra" + "github.com/skyscanner/turbolift/internal/campaign" "github.com/skyscanner/turbolift/internal/colors" "github.com/skyscanner/turbolift/internal/git" "github.com/skyscanner/turbolift/internal/logging" - "github.com/spf13/cobra" - "os" - "path" ) var g git.Git = git.NewRealGit() -var message string +var ( + message string + repoFile string +) func NewCommitCmd() *cobra.Command { cmd := &cobra.Command{ @@ -37,6 +42,8 @@ func NewCommitCmd() *cobra.Command { } cmd.Flags().StringVarP(&message, "message", "m", "", "Commit message to apply") + cmd.Flags().StringVar(&repoFile, "repos", "repos.txt", "A file containing a list of repositories to clone.") + err := cmd.MarkFlagRequired("message") if err != nil { panic(err) @@ -48,8 +55,10 @@ func NewCommitCmd() *cobra.Command { func run(c *cobra.Command, _ []string) { logger := logging.NewLogger(c) - readCampaignActivity := logger.StartActivity("Reading campaign data") - dir, err := campaign.OpenCampaign() + readCampaignActivity := logger.StartActivity("Reading campaign data (%s)", repoFile) + options := campaign.NewCampaignOptions() + options.RepoFilename = repoFile + dir, err := campaign.OpenCampaign(options) if err != nil { readCampaignActivity.EndWithFailure(err) return diff --git a/cmd/create_prs/create_prs.go b/cmd/create_prs/create_prs.go index b5d30a4..e7e7dc4 100644 --- a/cmd/create_prs/create_prs.go +++ b/cmd/create_prs/create_prs.go @@ -20,12 +20,13 @@ import ( "path" "time" + "github.com/spf13/cobra" + "github.com/skyscanner/turbolift/internal/campaign" "github.com/skyscanner/turbolift/internal/colors" "github.com/skyscanner/turbolift/internal/git" "github.com/skyscanner/turbolift/internal/github" "github.com/skyscanner/turbolift/internal/logging" - "github.com/spf13/cobra" ) var ( @@ -34,8 +35,9 @@ var ( ) var ( - sleep time.Duration - isDraft bool + isDraft bool + repoFile string + sleep time.Duration ) func NewCreatePRsCmd() *cobra.Command { @@ -47,6 +49,7 @@ func NewCreatePRsCmd() *cobra.Command { cmd.Flags().DurationVar(&sleep, "sleep", 0, "Fixed sleep in between PR creations (to spread load on CI infrastructure)") cmd.Flags().BoolVar(&isDraft, "draft", false, "Creates the Pull Request as Draft PR") + cmd.Flags().StringVar(&repoFile, "repos", "repos.txt", "A file containing a list of repositories to clone.") return cmd } @@ -54,8 +57,10 @@ func NewCreatePRsCmd() *cobra.Command { func run(c *cobra.Command, _ []string) { logger := logging.NewLogger(c) - readCampaignActivity := logger.StartActivity("Reading campaign data") - dir, err := campaign.OpenCampaign() + readCampaignActivity := logger.StartActivity("Reading campaign data (%s)", repoFile) + options := campaign.NewCampaignOptions() + options.RepoFilename = repoFile + dir, err := campaign.OpenCampaign(options) if err != nil { readCampaignActivity.EndWithFailure(err) return diff --git a/cmd/foreach/foreach.go b/cmd/foreach/foreach.go index 66234e7..4ed6574 100644 --- a/cmd/foreach/foreach.go +++ b/cmd/foreach/foreach.go @@ -20,15 +20,35 @@ import ( "path" "strings" + "github.com/spf13/cobra" + "github.com/skyscanner/turbolift/internal/campaign" "github.com/skyscanner/turbolift/internal/colors" "github.com/skyscanner/turbolift/internal/executor" "github.com/skyscanner/turbolift/internal/logging" - "github.com/spf13/cobra" ) var exec executor.Executor = executor.NewRealExecutor() +var repoFile string = "repos.txt" + +func parseForeachArgs(args []string) (strippedArgs []string) { +MAIN: + for i := 0; i < len(args); i++ { + switch args[i] { + case "--repos": + repoFile = args[i+1] + i = i + 1 + default: + // we've parsed everything that could be parsed; this is now the command + strippedArgs = args[i:] + break MAIN + } + } + + return +} + func NewForeachCmd() *cobra.Command { cmd := &cobra.Command{ Use: "foreach SHELL_COMMAND", @@ -38,14 +58,27 @@ func NewForeachCmd() *cobra.Command { DisableFlagParsing: true, } + // this flag will not be parsed (DisabledFlagParsing is on) but is here for the help context and auto complete + cmd.Flags().StringVar(&repoFile, "repos", "repos.txt", "A file containing a list of repositories to clone.") + return cmd } func run(c *cobra.Command, args []string) { logger := logging.NewLogger(c) - readCampaignActivity := logger.StartActivity("Reading campaign data") - dir, err := campaign.OpenCampaign() + /* + Parsing is disabled for this command to make sure it doesn't capture flags from the subsequent command. + E.g.: turbolift foreach ls -l <- here, the -l would be captured by foreach, not by ls + Because of this, we need a manual parsing of the arguments. + Assumption is the foreach arguments will be parsed before the command and its arguments. + */ + args = parseForeachArgs(args) + + readCampaignActivity := logger.StartActivity("Reading campaign data (%s)", repoFile) + options := campaign.NewCampaignOptions() + options.RepoFilename = repoFile + dir, err := campaign.OpenCampaign(options) if err != nil { readCampaignActivity.EndWithFailure(err) return diff --git a/cmd/foreach/foreach_test.go b/cmd/foreach/foreach_test.go index de2cdec..b57cf79 100644 --- a/cmd/foreach/foreach_test.go +++ b/cmd/foreach/foreach_test.go @@ -17,13 +17,73 @@ package foreach import ( "bytes" - "github.com/skyscanner/turbolift/internal/executor" - "github.com/skyscanner/turbolift/internal/testsupport" - "github.com/stretchr/testify/assert" "os" "testing" + + "github.com/stretchr/testify/assert" + + "github.com/skyscanner/turbolift/internal/executor" + "github.com/skyscanner/turbolift/internal/testsupport" ) +func TestParseForEachArgs(t *testing.T) { + testCases := []struct { + Name string + Args []string + ExpectedCommand []string + ExpectedRepoFileName string + }{ + { + Name: "simple command", + Args: []string{"ls", "-l"}, + ExpectedCommand: []string{"ls", "-l"}, + ExpectedRepoFileName: "repos.txt", + }, + { + Name: "advanced command", + Args: []string{"sed", "-e", "'s/foo/bar/'", "-e", "'s/bar/baz/'"}, + ExpectedCommand: []string{"sed", "-e", "'s/foo/bar/'", "-e", "'s/bar/baz/'"}, + ExpectedRepoFileName: "repos.txt", + }, + { + Name: "simple command with repo flag", + Args: []string{"--repos", "test.txt", "ls", "-l"}, + ExpectedCommand: []string{"ls", "-l"}, + ExpectedRepoFileName: "test.txt", + }, + { + Name: "advanced command with repos flag", + Args: []string{"--repos", "test2.txt", "sed", "-e", "'s/foo/bar/'", "-e", "'s/bar/baz/'"}, + ExpectedCommand: []string{"sed", "-e", "'s/foo/bar/'", "-e", "'s/bar/baz/'"}, + ExpectedRepoFileName: "test2.txt", + }, + { + Name: "repos flag should only be caught when at the beginning", + Args: []string{"ls", "-l", "--repos", "random.txt"}, + ExpectedCommand: []string{"ls", "-l", "--repos", "random.txt"}, + ExpectedRepoFileName: "repos.txt", + }, + { + Name: "random flag is not caught", + Args: []string{"--random", "arg", "ls", "-l"}, + ExpectedCommand: []string{"--random", "arg", "ls", "-l"}, + ExpectedRepoFileName: "repos.txt", + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + actual := parseForeachArgs(tc.Args) + t.Log(actual) + assert.EqualValues(t, tc.ExpectedCommand, actual) + assert.Equal(t, repoFile, tc.ExpectedRepoFileName) + + // Cleanup to default repo file name + repoFile = "repos.txt" + }) + } +} + func TestItRejectsEmptyArgs(t *testing.T) { fakeExecutor := executor.NewAlwaysSucceedsFakeExecutor() exec = fakeExecutor @@ -102,7 +162,6 @@ func runCommand(args ...string) (string, error) { cmd.SetOut(outBuffer) cmd.SetArgs(args) err := cmd.Execute() - if err != nil { return outBuffer.String(), err } diff --git a/cmd/pr_status/pr_status.go b/cmd/prstatus/prstatus.go similarity index 92% rename from cmd/pr_status/pr_status.go rename to cmd/prstatus/prstatus.go index d92d918..8580e54 100644 --- a/cmd/pr_status/pr_status.go +++ b/cmd/prstatus/prstatus.go @@ -13,19 +13,21 @@ * */ -package pr_status +package prstatus import ( "fmt" + "os" + "path" + "strings" + "github.com/fatih/color" "github.com/rodaine/table" + "github.com/spf13/cobra" + "github.com/skyscanner/turbolift/internal/campaign" "github.com/skyscanner/turbolift/internal/github" "github.com/skyscanner/turbolift/internal/logging" - "github.com/spf13/cobra" - "os" - "path" - "strings" ) var reactionsOrder = []string{ @@ -52,7 +54,10 @@ var reactionsMapping = map[string]string{ var gh github.GitHub = github.NewRealGitHub() -var list bool +var ( + list bool + repoFile string +) func NewPrStatusCmd() *cobra.Command { cmd := &cobra.Command{ @@ -61,6 +66,7 @@ func NewPrStatusCmd() *cobra.Command { Run: run, } cmd.Flags().BoolVar(&list, "list", false, "Displays a listing by PR") + cmd.Flags().StringVar(&repoFile, "repos", "repos.txt", "A file containing a list of repositories to clone.") return cmd } @@ -68,8 +74,11 @@ func NewPrStatusCmd() *cobra.Command { func run(c *cobra.Command, _ []string) { logger := logging.NewLogger(c) - readCampaignActivity := logger.StartActivity("Reading campaign data") - dir, err := campaign.OpenCampaign() + readCampaignActivity := logger.StartActivity("Reading campaign data (%s)", repoFile) + + options := campaign.NewCampaignOptions() + options.RepoFilename = repoFile + dir, err := campaign.OpenCampaign(options) if err != nil { readCampaignActivity.EndWithFailure(err) return diff --git a/cmd/pr_status/pr_status_test.go b/cmd/prstatus/prstatus_test.go similarity index 99% rename from cmd/pr_status/pr_status_test.go rename to cmd/prstatus/prstatus_test.go index 7026fed..4e974cc 100644 --- a/cmd/pr_status/pr_status_test.go +++ b/cmd/prstatus/prstatus_test.go @@ -13,7 +13,7 @@ * */ -package pr_status +package prstatus import ( "bytes" @@ -22,9 +22,10 @@ import ( "os" "testing" + "github.com/stretchr/testify/assert" + "github.com/skyscanner/turbolift/internal/github" "github.com/skyscanner/turbolift/internal/testsupport" - "github.com/stretchr/testify/assert" ) func init() { @@ -109,7 +110,6 @@ func runCommand(showList bool) (string, error) { outBuffer := bytes.NewBufferString("") cmd.SetOut(outBuffer) err := cmd.Execute() - if err != nil { return outBuffer.String(), err } diff --git a/cmd/root.go b/cmd/root.go index 0df73cc..e4dbd4a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -19,16 +19,16 @@ import ( "fmt" "log" + "github.com/spf13/cobra" + cloneCmd "github.com/skyscanner/turbolift/cmd/clone" commitCmd "github.com/skyscanner/turbolift/cmd/commit" createPrsCmd "github.com/skyscanner/turbolift/cmd/create_prs" "github.com/skyscanner/turbolift/cmd/flags" foreachCmd "github.com/skyscanner/turbolift/cmd/foreach" initCmd "github.com/skyscanner/turbolift/cmd/init" - updatePrsCmd "github.com/skyscanner/turbolift/cmd/update_prs" - "github.com/spf13/cobra" - - prStatusCmd "github.com/skyscanner/turbolift/cmd/pr_status" + prStatusCmd "github.com/skyscanner/turbolift/cmd/prstatus" + updatePrsCmd "github.com/skyscanner/turbolift/cmd/updateprs" ) var ( diff --git a/cmd/update_prs/update_prs.go b/cmd/updateprs/updateprs.go similarity index 92% rename from cmd/update_prs/update_prs.go rename to cmd/updateprs/updateprs.go index ca6dddb..4162bc1 100644 --- a/cmd/update_prs/update_prs.go +++ b/cmd/updateprs/updateprs.go @@ -13,19 +13,20 @@ * */ -package update_prs +package updateprs import ( "errors" "fmt" "os" + "github.com/spf13/cobra" + "github.com/skyscanner/turbolift/internal/campaign" "github.com/skyscanner/turbolift/internal/colors" "github.com/skyscanner/turbolift/internal/github" "github.com/skyscanner/turbolift/internal/logging" "github.com/skyscanner/turbolift/internal/prompt" - "github.com/spf13/cobra" ) var ( @@ -36,6 +37,7 @@ var ( var ( closeFlag bool yesFlag bool + repoFile string ) func NewUpdatePRsCmd() *cobra.Command { @@ -47,6 +49,7 @@ func NewUpdatePRsCmd() *cobra.Command { cmd.Flags().BoolVar(&closeFlag, "close", false, "Close all generated PRs") cmd.Flags().BoolVar(&yesFlag, "yes", false, "Skips the confirmation prompt") + cmd.Flags().StringVar(&repoFile, "repos", "repos.txt", "A file containing a list of repositories to clone.") return cmd } @@ -88,8 +91,10 @@ func run(c *cobra.Command, args []string) { func runClose(c *cobra.Command, _ []string) { logger := logging.NewLogger(c) - readCampaignActivity := logger.StartActivity("Reading campaign data") - dir, err := campaign.OpenCampaign() + readCampaignActivity := logger.StartActivity("Reading campaign data (%s)", repoFile) + options := campaign.NewCampaignOptions() + options.RepoFilename = repoFile + dir, err := campaign.OpenCampaign(options) if err != nil { readCampaignActivity.EndWithFailure(err) return diff --git a/cmd/update_prs/update_prs_test.go b/cmd/updateprs/updateprs_test.go similarity index 99% rename from cmd/update_prs/update_prs_test.go rename to cmd/updateprs/updateprs_test.go index 9559f55..0fa4bbc 100644 --- a/cmd/update_prs/update_prs_test.go +++ b/cmd/updateprs/updateprs_test.go @@ -1,14 +1,15 @@ -package update_prs +package updateprs import ( "bytes" "path/filepath" "testing" + "github.com/stretchr/testify/assert" + "github.com/skyscanner/turbolift/internal/github" "github.com/skyscanner/turbolift/internal/prompt" "github.com/skyscanner/turbolift/internal/testsupport" - "github.com/stretchr/testify/assert" ) func TestItLogsClosePrErrorsButContinuesToTryAll(t *testing.T) { diff --git a/internal/campaign/campaign.go b/internal/campaign/campaign.go index 0e18300..a15e626 100644 --- a/internal/campaign/campaign.go +++ b/internal/campaign/campaign.go @@ -43,11 +43,19 @@ func (r Repo) FullRepoPath() string { return path.Join("work", r.OrgName, r.RepoName) // i.e. work/org/repo } -func OpenCampaign() (*Campaign, error) { +type CampaignOptions struct { + RepoFilename string +} + +func NewCampaignOptions() *CampaignOptions { + return &CampaignOptions{RepoFilename: "repos.txt"} +} + +func OpenCampaign(options *CampaignOptions) (*Campaign, error) { dir, _ := os.Getwd() dirBasename := filepath.Base(dir) - repos, err := readReposTxtFile() + repos, err := readReposTxtFile(options.RepoFilename) if err != nil { return nil, err } @@ -65,10 +73,13 @@ func OpenCampaign() (*Campaign, error) { }, nil } -func readReposTxtFile() ([]Repo, error) { - file, err := os.Open("repos.txt") +func readReposTxtFile(filename string) ([]Repo, error) { + if filename == "" { + return nil, errors.New("no repos filename to open") + } + file, err := os.Open(filename) if err != nil { - return nil, errors.New("unable to open repos.txt file") + return nil, fmt.Errorf("unable to open repo file: %s", filename) } defer func() { closeErr := file.Close() @@ -92,28 +103,29 @@ func readReposTxtFile() ([]Repo, error) { numParts := len(splitLine) var repo Repo - if numParts == 2 { + switch numParts { + case 2: repo = Repo{ OrgName: splitLine[0], RepoName: splitLine[1], FullRepoName: line, } - } else if numParts == 3 { + case 3: repo = Repo{ Host: splitLine[0], OrgName: splitLine[1], RepoName: splitLine[2], FullRepoName: line, } - } else { - return nil, fmt.Errorf("unable to parse entry in repos.txt file: %s", line) + default: + return nil, fmt.Errorf("unable to parse entry in %s file: %s", filename, line) } repos = append(repos, repo) } } if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("unable to open repos.txt file: %w", err) + return nil, fmt.Errorf("unable to open %s file: %w", filename, err) } return repos, nil diff --git a/internal/campaign/campaign_test.go b/internal/campaign/campaign_test.go index 2256c94..894dbc2 100644 --- a/internal/campaign/campaign_test.go +++ b/internal/campaign/campaign_test.go @@ -16,15 +16,18 @@ package campaign import ( - "github.com/skyscanner/turbolift/internal/testsupport" - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" + + "github.com/skyscanner/turbolift/internal/testsupport" ) func TestItReadsSimpleRepoNamesFromReposFile(t *testing.T) { testsupport.PrepareTempCampaign(false, "org/repo1", "org/repo2") - campaign, err := OpenCampaign() + defaultOptions := NewCampaignOptions() + campaign, err := OpenCampaign(defaultOptions) assert.NoError(t, err) assert.Equal(t, testsupport.Pwd(), campaign.Name) @@ -49,7 +52,8 @@ func TestItReadsSimpleRepoNamesFromReposFile(t *testing.T) { func TestItReadsRepoNamesWithOtherHostsFromReposFile(t *testing.T) { testsupport.PrepareTempCampaign(false, "org/repo1", "mygitserver.com/org/repo2") - campaign, err := OpenCampaign() + defaultOptions := NewCampaignOptions() + campaign, err := OpenCampaign(defaultOptions) assert.NoError(t, err) assert.Equal(t, testsupport.Pwd(), campaign.Name) @@ -74,7 +78,8 @@ func TestItReadsRepoNamesWithOtherHostsFromReposFile(t *testing.T) { func TestItIgnoresCommentedLines(t *testing.T) { testsupport.PrepareTempCampaign(false, "org/repo1", "#org/repo2") - campaign, err := OpenCampaign() + defaultOptions := NewCampaignOptions() + campaign, err := OpenCampaign(defaultOptions) assert.NoError(t, err) assert.Equal(t, testsupport.Pwd(), campaign.Name) @@ -93,7 +98,8 @@ func TestItIgnoresCommentedLines(t *testing.T) { func TestItIgnoresEmptyLines(t *testing.T) { testsupport.PrepareTempCampaign(false, "org/repo1", "") - campaign, err := OpenCampaign() + defaultOptions := NewCampaignOptions() + campaign, err := OpenCampaign(defaultOptions) assert.NoError(t, err) assert.Equal(t, testsupport.Pwd(), campaign.Name) @@ -112,7 +118,8 @@ func TestItIgnoresEmptyLines(t *testing.T) { func TestItIgnoresEmptyAndCommentedLines(t *testing.T) { testsupport.PrepareTempCampaign(false, "#Comment", "org/repo1", "") - campaign, err := OpenCampaign() + defaultOptions := NewCampaignOptions() + campaign, err := OpenCampaign(defaultOptions) assert.NoError(t, err) assert.Equal(t, testsupport.Pwd(), campaign.Name) @@ -131,7 +138,8 @@ func TestItIgnoresEmptyAndCommentedLines(t *testing.T) { func TestItIgnoresDuplicatedLines(t *testing.T) { testsupport.PrepareTempCampaign(false, "org/repo1", "org/repo1") - campaign, err := OpenCampaign() + defaultOptions := NewCampaignOptions() + campaign, err := OpenCampaign(defaultOptions) assert.NoError(t, err) assert.Equal(t, []Repo{ @@ -147,7 +155,8 @@ func TestItIgnoresDuplicatedLines(t *testing.T) { func TestItIgnoresDuplicatedNonSequentialLines(t *testing.T) { testsupport.PrepareTempCampaign(false, "org/repo1", "org/repo2", "org/repo1") - campaign, err := OpenCampaign() + defaultOptions := NewCampaignOptions() + campaign, err := OpenCampaign(defaultOptions) assert.NoError(t, err) assert.Equal(t, []Repo{ @@ -165,3 +174,51 @@ func TestItIgnoresDuplicatedNonSequentialLines(t *testing.T) { }, }, campaign.Repos) } + +func TestItShouldAcceptADifferentRepoFileSuccess(t *testing.T) { + testsupport.PrepareTempCampaign(false) + + testsupport.CreateAnotherRepoFile("newrepos.txt", "org/repo1", "org/repo2", "org/repo3") + options := NewCampaignOptions() + options.RepoFilename = "newrepos.txt" + campaign, err := OpenCampaign(options) + assert.NoError(t, err) + + assert.Equal(t, []Repo{ + { + Host: "", + OrgName: "org", + RepoName: "repo1", + FullRepoName: "org/repo1", + }, + { + Host: "", + OrgName: "org", + RepoName: "repo2", + FullRepoName: "org/repo2", + }, + { + Host: "", + OrgName: "org", + RepoName: "repo3", + FullRepoName: "org/repo3", + }, + }, campaign.Repos) +} + +func TestItShouldAcceptADifferentRepoFileNotExist(t *testing.T) { + testsupport.PrepareTempCampaign(false) + + options := NewCampaignOptions() + options.RepoFilename = "newrepos.txt" + _, err := OpenCampaign(options) + assert.Error(t, err) +} + +func TestItShouldErrorWhenRepoFileIsEmpty(t *testing.T) { + testsupport.PrepareTempCampaign(false) + + options := &CampaignOptions{} + _, err := OpenCampaign(options) + assert.Error(t, err) +} diff --git a/internal/testsupport/testsupport.go b/internal/testsupport/testsupport.go index 81ceccd..267aa11 100644 --- a/internal/testsupport/testsupport.go +++ b/internal/testsupport/testsupport.go @@ -41,7 +41,7 @@ func PrepareTempCampaign(createDirs bool, repos ...string) string { tempDir := CreateAndEnterTempDirectory() delimitedList := strings.Join(repos, "\n") - err := ioutil.WriteFile("repos.txt", []byte(delimitedList), os.ModePerm|0644) + err := ioutil.WriteFile("repos.txt", []byte(delimitedList), os.ModePerm|0o644) if err != nil { panic(err) } @@ -49,7 +49,7 @@ func PrepareTempCampaign(createDirs bool, repos ...string) string { if createDirs { for _, name := range repos { dirToCreate := path.Join("work", name) - err := os.MkdirAll(dirToCreate, os.ModeDir|0755) + err := os.MkdirAll(dirToCreate, os.ModeDir|0o755) if err != nil { panic(err) } @@ -57,10 +57,18 @@ func PrepareTempCampaign(createDirs bool, repos ...string) string { } dummyPrDescription := "# PR title\nPR body" - err = ioutil.WriteFile("README.md", []byte(dummyPrDescription), os.ModePerm|0644) + err = ioutil.WriteFile("README.md", []byte(dummyPrDescription), os.ModePerm|0o644) if err != nil { panic(err) } return tempDir } + +func CreateAnotherRepoFile(filename string, repos ...string) { + delimitedList := strings.Join(repos, "\n") + err := ioutil.WriteFile(filename, []byte(delimitedList), os.ModePerm|0o644) + if err != nil { + panic(err) + } +}