diff --git a/commands/commands.go b/commands/commands.go index 4c51524c2..46e217fa2 100644 --- a/commands/commands.go +++ b/commands/commands.go @@ -17,10 +17,10 @@ type FrogbotCommand interface { Run(config utils.RepoAggregator, client vcsclient.VcsClient) error } -func Exec(command FrogbotCommand, name string) (err error) { +func Exec(command FrogbotCommand, commandName string) (err error) { // Get frogbotUtils that contains the config, server, and VCS client log.Info("Frogbot version:", utils.FrogbotVersion) - frogbotUtils, err := utils.GetFrogbotDetails() + frogbotUtils, err := utils.GetFrogbotDetails(commandName) if err != nil { return err } @@ -47,17 +47,17 @@ func Exec(command FrogbotCommand, name string) (err error) { // Send a usage report usageReportSent := make(chan error) - go utils.ReportUsage(name, frogbotUtils.ServerDetails, usageReportSent) + go utils.ReportUsage(commandName, frogbotUtils.ServerDetails, usageReportSent) // Invoke the command interface - log.Info(fmt.Sprintf("Running Frogbot %q command", name)) - err = command.Run(frogbotUtils.Repositories, frogbotUtils.Client) + log.Info(fmt.Sprintf("Running Frogbot %q command", commandName)) + err = command.Run(frogbotUtils.Repositories, frogbotUtils.GitClient) // Wait for a signal, letting us know that the usage reporting is done. <-usageReportSent if err == nil { - log.Info(fmt.Sprintf("Frogbot %q command finished successfully", name)) + log.Info(fmt.Sprintf("Frogbot %q command finished successfully", commandName)) } return err } @@ -65,7 +65,7 @@ func Exec(command FrogbotCommand, name string) (err error) { func GetCommands() []*clitool.Command { return []*clitool.Command{ { - Name: "scan-pull-request", + Name: utils.ScanPullRequest, Aliases: []string{"spr"}, Usage: "Scans a pull request with JFrog Xray for security vulnerabilities.", Action: func(ctx *clitool.Context) error { @@ -74,7 +74,7 @@ func GetCommands() []*clitool.Command { Flags: []clitool.Flag{}, }, { - Name: "create-fix-pull-requests", + Name: utils.CreateFixPullRequests, Aliases: []string{"cfpr"}, Usage: "Scan the current branch and create pull requests with fixes if needed", Action: func(ctx *clitool.Context) error { @@ -83,7 +83,7 @@ func GetCommands() []*clitool.Command { Flags: []clitool.Flag{}, }, { - Name: "scan-pull-requests", + Name: utils.ScanPullRequests, Aliases: []string{"sprs"}, Usage: "Scans all the open pull requests within a single or multiple repositories with JFrog Xray for security vulnerabilities", Action: func(ctx *clitool.Context) error { @@ -92,7 +92,7 @@ func GetCommands() []*clitool.Command { Flags: []clitool.Flag{}, }, { - Name: "scan-and-fix-repos", + Name: utils.ScanAndFixRepos, Aliases: []string{"safr"}, Usage: "Scan single or multiple repositories and create pull requests with fixes if any security vulnerabilities are found", Action: func(ctx *clitool.Context) error { diff --git a/commands/createfixpullrequests.go b/commands/createfixpullrequests.go index 07b5f0d6f..2dcdeb31c 100644 --- a/commands/createfixpullrequests.go +++ b/commands/createfixpullrequests.go @@ -43,26 +43,29 @@ type CreateFixPullRequestsCmd struct { handlers map[coreutils.Technology]packagehandlers.PackageHandler } -func (cfp *CreateFixPullRequestsCmd) Run(repoAggregator utils.RepoAggregator, client vcsclient.VcsClient) error { - if err := utils.ValidateSingleRepoConfiguration(&repoAggregator); err != nil { +func (cfp *CreateFixPullRequestsCmd) Run(repoAggregator utils.RepoAggregator, client vcsclient.VcsClient) (err error) { + if err = utils.ValidateSingleRepoConfiguration(&repoAggregator); err != nil { return err } repository := repoAggregator[0] for _, branch := range repository.Branches { - err := cfp.scanAndFixRepository(&repository, branch, client) - if err != nil { - return err + if err = cfp.scanAndFixRepository(&repository, branch, client); err != nil { + return } } - return nil + return } func (cfp *CreateFixPullRequestsCmd) scanAndFixRepository(repository *utils.Repository, branch string, client vcsclient.VcsClient) (err error) { - cfp.baseWd, err = os.Getwd() - if err != nil { + if cfp.baseWd, err = os.Getwd(); err != nil { + return + } + if err = cfp.setCommandPrerequisites(repository, branch, client); err != nil { return } - cfp.setCommandPrerequisites(repository, branch, client) + if err = cfp.gitManager.Checkout(branch); err != nil { + return fmt.Errorf("failed to checkout to %s branch before scanning. The following error has been received:\n%s", branch, err.Error()) + } for i := range repository.Projects { cfp.details.Project = &repository.Projects[i] cfp.projectTech = "" @@ -73,7 +76,7 @@ func (cfp *CreateFixPullRequestsCmd) scanAndFixRepository(repository *utils.Repo return } -func (cfp *CreateFixPullRequestsCmd) setCommandPrerequisites(repository *utils.Repository, branch string, client vcsclient.VcsClient) { +func (cfp *CreateFixPullRequestsCmd) setCommandPrerequisites(repository *utils.Repository, branch string, client vcsclient.VcsClient) (err error) { cfp.details = utils.NewScanDetails(client, &repository.Server, &repository.Git). SetXrayGraphScanParams(repository.Watches, repository.JFrogProjectKey). SetFailOnInstallationErrors(*repository.FailOnSecurityIssues). @@ -82,12 +85,14 @@ func (cfp *CreateFixPullRequestsCmd) setCommandPrerequisites(repository *utils.R SetMinSeverity(repository.MinSeverity) cfp.aggregateFixes = repository.Git.AggregateFixes cfp.OutputWriter = utils.GetCompatibleOutputWriter(repository.GitProvider) + cfp.gitManager, err = utils.NewGitManager(cfp.dryRun, cfp.dryRunRepoPath, ".", "origin", cfp.details.Token, cfp.details.Username, cfp.details.Git) + return } func (cfp *CreateFixPullRequestsCmd) scanAndFixProject(repository *utils.Repository) error { var fixNeeded bool // A map that contains the full project paths as a keys - // The value is a map of vulnerable package names -> the details of the vulnerable packages.x + // The value is a map of vulnerable package names -> the details of the vulnerable packages. // That means we have a map of all the vulnerabilities that were found in a specific folder, along with their full details. vulnerabilitiesByPathMap := make(map[string]map[string]*utils.VulnerabilityDetails) projectFullPathWorkingDirs := getFullPathWorkingDirs(cfp.details.Project.WorkingDirs, cfp.baseWd) @@ -147,12 +152,6 @@ func (cfp *CreateFixPullRequestsCmd) getVulnerabilitiesMap(scanResults *xrayutil } func (cfp *CreateFixPullRequestsCmd) fixVulnerablePackages(vulnerabilitiesByWdMap map[string]map[string]*utils.VulnerabilityDetails) (err error) { - if cfp.gitManager == nil { - cfp.gitManager, err = utils.NewGitManager(cfp.dryRun, cfp.dryRunRepoPath, ".", "origin", cfp.details.Token, cfp.details.Username, cfp.details.Git) - if err != nil { - return - } - } clonedRepoDir, restoreBaseDir, err := cfp.cloneRepository() if err != nil { return @@ -186,12 +185,12 @@ func (cfp *CreateFixPullRequestsCmd) fixProjectVulnerabilities(fullProjectPath s // 'CD' into the relevant working directory if projectWorkingDir != "" { - restoreDir, err := utils.Chdir(projectWorkingDir) - if err != nil { - return err + var restoreDirFunc func() error + if restoreDirFunc, err = utils.Chdir(projectWorkingDir); err != nil { + return } defer func() { - err = errors.Join(err, restoreDir()) + err = errors.Join(err, restoreDirFunc()) }() } @@ -203,7 +202,7 @@ func (cfp *CreateFixPullRequestsCmd) fixProjectVulnerabilities(fullProjectPath s // After fixing the current vulnerability, checkout to the base branch to start fixing the next vulnerability log.Debug("Running git checkout to base branch:", cfp.details.Branch()) - if e := cfp.gitManager.CheckoutLocalBranch(cfp.details.Branch()); e != nil { + if e := cfp.gitManager.Checkout(cfp.details.Branch()); e != nil { err = errors.Join(err, cfp.handleUpdatePackageErrors(e)) return } @@ -545,7 +544,7 @@ func (cfp *CreateFixPullRequestsCmd) aggregateFixAndOpenPullRequest(vulnerabilit } } log.Info("-----------------------------------------------------------------") - if e := cfp.gitManager.CheckoutLocalBranch(cfp.details.Branch()); e != nil { + if e := cfp.gitManager.Checkout(cfp.details.Branch()); e != nil { err = errors.Join(err, e) } return diff --git a/commands/createfixpullrequests_test.go b/commands/createfixpullrequests_test.go index 26b5f2f8d..a370aa011 100644 --- a/commands/createfixpullrequests_test.go +++ b/commands/createfixpullrequests_test.go @@ -91,7 +91,7 @@ func TestCreateFixPullRequestsCmd_Run(t *testing.T) { repoName: "aggregate-multi-dir", testDir: "createfixpullrequests/aggregate-multi-dir", expectedBranches: []string{"frogbot-update-npm-dependencies"}, - expectedDiff: []string{"diff --git a/npm1/package.json b/npm1/package.json\nindex ae09978..286211d 100644\n--- a/npm1/package.json\n+++ b/npm1/package.json\n@@ -9,8 +9,8 @@\n \"author\": \"\",\n \"license\": \"ISC\",\n \"dependencies\": {\n- \"uuid\": \"^9.0.0\",\n- \"minimatch\":\"3.0.2\",\n- \"mpath\": \"0.7.0\"\n+ \"minimatch\": \"^3.0.5\",\n+ \"mpath\": \"^0.8.4\",\n+ \"uuid\": \"^9.0.0\"\n }\n-}\n\\ No newline at end of file\n+}\ndiff --git a/npm2/package.json b/npm2/package.json\nindex be180a6..14b5c7a 100644\n--- a/npm2/package.json\n+++ b/npm2/package.json\n@@ -1,5 +1,5 @@\n {\n \"dependencies\": {\n- \"minimist\": \"^1.2.5\"\n+ \"minimist\": \"^1.2.6\"\n }\n }\n"}, + expectedDiff: []string{"diff --git a/npm1/package.json b/npm1/package.json\nindex ae09978..286211d 100644\n--- a/npm1/package.json\n+++ b/npm1/package.json\n@@ -9,8 +9,8 @@\n \"author\": \"\",\n \"license\": \"ISC\",\n \"dependencies\": {\n- \"uuid\": \"^9.0.0\",\n- \"minimatch\":\"3.0.2\",\n- \"mpath\": \"0.7.0\"\n+ \"minimatch\": \"^3.0.5\",\n+ \"mpath\": \"^0.8.4\",\n+ \"uuid\": \"^9.0.0\"\n }\n-}\n\\ No newline at end of file\n+}\ndiff --git a/npm2/package.json b/npm2/package.json\nindex ff94a18..14b5c7a 100644\n--- a/npm2/package.json\n+++ b/npm2/package.json\n@@ -1,5 +1,5 @@\n {\n \"dependencies\": {\n- \"minimist\": \"1.2.5\"\n+ \"minimist\": \"^1.2.6\"\n }\n }\n"}, packageDescriptorPaths: []string{"npm1/package.json", "npm2/package.json"}, aggregateFixes: true, configPath: "testdata/createfixpullrequests/aggregate-multi-dir/.frogbot/frogbot-config.yml", @@ -143,7 +143,7 @@ func TestCreateFixPullRequestsCmd_Run(t *testing.T) { var port string server := httptest.NewServer(createHttpHandler(t, &port, test.repoName)) port = server.URL[strings.LastIndex(server.URL, ":")+1:] - gitTestParams := utils.GitClientInfo{ + gitTestParams := utils.Git{ GitProvider: vcsutils.GitHub, VcsInfo: vcsclient.VcsInfo{ Token: "123456", @@ -243,7 +243,7 @@ pr body server.Close() }() port = server.URL[strings.LastIndex(server.URL, ":")+1:] - gitTestParams := &utils.GitClientInfo{ + gitTestParams := &utils.Git{ GitProvider: vcsutils.GitHub, VcsInfo: vcsclient.VcsInfo{ Token: "123456", diff --git a/commands/scanandfixrepos_test.go b/commands/scanandfixrepos_test.go index 1c7768e7e..1454cba3e 100644 --- a/commands/scanandfixrepos_test.go +++ b/commands/scanandfixrepos_test.go @@ -37,7 +37,7 @@ func TestScanAndFixRepos(t *testing.T) { defer server.Close() port = server.URL[strings.LastIndex(server.URL, ":")+1:] - gitTestParams := utils.GitClientInfo{ + gitTestParams := utils.Git{ GitProvider: vcsutils.GitHub, RepoOwner: "jfrog", VcsInfo: vcsclient.VcsInfo{ diff --git a/commands/scanpullrequest_test.go b/commands/scanpullrequest_test.go index 924a73bb7..210ab1728 100644 --- a/commands/scanpullrequest_test.go +++ b/commands/scanpullrequest_test.go @@ -598,8 +598,8 @@ func TestVerifyGitHubFrogbotEnvironmentNoReviewers(t *testing.T) { func TestVerifyGitHubFrogbotEnvironmentOnPrem(t *testing.T) { repoConfig := &utils.Repository{ - Params: utils.Params{Git: utils.Git{GitClientInfo: utils.GitClientInfo{ - VcsInfo: vcsclient.VcsInfo{APIEndpoint: "https://acme.vcs.io"}}}, + Params: utils.Params{Git: utils.Git{ + VcsInfo: vcsclient.VcsInfo{APIEndpoint: "https://acme.vcs.io"}}, }, } @@ -609,7 +609,7 @@ func TestVerifyGitHubFrogbotEnvironmentOnPrem(t *testing.T) { } func prepareConfigAndClient(t *testing.T, configPath string, server *httptest.Server, serverParams coreconfig.ServerDetails) (utils.RepoAggregator, vcsclient.VcsClient) { - gitTestParams := &utils.GitClientInfo{ + gitTestParams := &utils.Git{ GitProvider: vcsutils.GitHub, RepoOwner: "jfrog", VcsInfo: vcsclient.VcsInfo{ @@ -839,7 +839,8 @@ func TestDeletePreviousPullRequestMessages(t *testing.T) { repository := &utils.Repository{ Params: utils.Params{ Git: utils.Git{ - GitClientInfo: utils.GitClientInfo{RepoName: "repo", RepoOwner: "owner"}, + RepoName: "repo", + RepoOwner: "owner", PullRequestID: 17, }, }, diff --git a/commands/scanpullrequests_test.go b/commands/scanpullrequests_test.go index 57f07c4bc..fbeca8510 100644 --- a/commands/scanpullrequests_test.go +++ b/commands/scanpullrequests_test.go @@ -20,11 +20,9 @@ var gitParams = &utils.Repository{ OutputWriter: &utils.SimplifiedOutput{}, Params: utils.Params{ Git: utils.Git{ - GitClientInfo: utils.GitClientInfo{ - RepoOwner: "repo-owner", - Branches: []string{"master"}, - RepoName: "repo-name", - }, + RepoOwner: "repo-owner", + Branches: []string{"master"}, + RepoName: "repo-name", }, }, } diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/COMMIT_EDITMSG b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/COMMIT_EDITMSG index b2c0d99a7..b1b716105 100644 --- a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/COMMIT_EDITMSG +++ b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/COMMIT_EDITMSG @@ -1 +1 @@ -fix tests +init diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/index b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/index index 6c359bb82..cf9043747 100644 Binary files a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/index and b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/index differ diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/logs/HEAD b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/logs/HEAD index d4a6b8be3..8f31b400b 100644 --- a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/logs/HEAD +++ b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/logs/HEAD @@ -1 +1 @@ -0000000000000000000000000000000000000000 20cfb0cbabf22f1c12d626eec6e6dd834f4e43d1 Omer Zidkoni 1689852711 +0300 commit (initial): fix tests +0000000000000000000000000000000000000000 59fbea5efff5cfe6a005f33aaadbf21d58dc4af8 Omer Zidkoni 1691578013 +0300 commit (initial): init diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/logs/refs/heads/main b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/logs/refs/heads/main index d4a6b8be3..8f31b400b 100644 --- a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/logs/refs/heads/main +++ b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/logs/refs/heads/main @@ -1 +1 @@ -0000000000000000000000000000000000000000 20cfb0cbabf22f1c12d626eec6e6dd834f4e43d1 Omer Zidkoni 1689852711 +0300 commit (initial): fix tests +0000000000000000000000000000000000000000 59fbea5efff5cfe6a005f33aaadbf21d58dc4af8 Omer Zidkoni 1691578013 +0300 commit (initial): init diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/11/a23eda8941289a57af01af4929e3a6fd024dd7 b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/11/a23eda8941289a57af01af4929e3a6fd024dd7 new file mode 100644 index 000000000..b548a0653 Binary files /dev/null and b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/11/a23eda8941289a57af01af4929e3a6fd024dd7 differ diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/20/cfb0cbabf22f1c12d626eec6e6dd834f4e43d1 b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/20/cfb0cbabf22f1c12d626eec6e6dd834f4e43d1 deleted file mode 100644 index ef0858726..000000000 --- a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/20/cfb0cbabf22f1c12d626eec6e6dd834f4e43d1 +++ /dev/null @@ -1,2 +0,0 @@ -x��K -1 @]�� �4�tD��{w��Z�:���+�|/IkU��ig��y��.T��5P)���c��sF��ل�ޥåq�k�OyU8ʠ��Q��I� p^�er���5Î����Ҕ��M7� �7� \ No newline at end of file diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/b1/d50a083f2239a3ff3b3ed2d1bbaea16d17c1ee b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/3e/4432f7bbfd21f68525f7b9bf738931e91c37b9 similarity index 62% rename from commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/b1/d50a083f2239a3ff3b3ed2d1bbaea16d17c1ee rename to commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/3e/4432f7bbfd21f68525f7b9bf738931e91c37b9 index fef22e8a2..0641f5f1a 100644 Binary files a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/b1/d50a083f2239a3ff3b3ed2d1bbaea16d17c1ee and b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/3e/4432f7bbfd21f68525f7b9bf738931e91c37b9 differ diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/59/fbea5efff5cfe6a005f33aaadbf21d58dc4af8 b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/59/fbea5efff5cfe6a005f33aaadbf21d58dc4af8 new file mode 100644 index 000000000..ba487150c --- /dev/null +++ b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/59/fbea5efff5cfe6a005f33aaadbf21d58dc4af8 @@ -0,0 +1,2 @@ +x��A� E]s�ٛ�)��x��� EC'!����+�|?y�'n��ٞF�(O��b,��2{k�P�ő�9`"a���wX[�p�ۇ� + �n���yIܮ� h��Hp֤��U��H����u��d5 \ No newline at end of file diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/61/a70d8baf4dd63a6b1b01f87791cb73425caf55 b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/61/a70d8baf4dd63a6b1b01f87791cb73425caf55 deleted file mode 100644 index af1a19277..000000000 Binary files a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/61/a70d8baf4dd63a6b1b01f87791cb73425caf55 and /dev/null differ diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/be/180a62cd192cb4ef53647c6d907074d428d724 b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/be/180a62cd192cb4ef53647c6d907074d428d724 deleted file mode 100644 index d83aed2c8..000000000 Binary files a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/be/180a62cd192cb4ef53647c6d907074d428d724 and /dev/null differ diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/ff/94a18e368955fa7b7dfd66774838a64dc15efc b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/ff/94a18e368955fa7b7dfd66774838a64dc15efc new file mode 100644 index 000000000..71f0b428c Binary files /dev/null and b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/objects/ff/94a18e368955fa7b7dfd66774838a64dc15efc differ diff --git a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/refs/heads/main b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/refs/heads/main index 9e336a928..ed344f18a 100644 --- a/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/refs/heads/main +++ b/commands/testdata/createfixpullrequests/aggregate-multi-dir/git/refs/heads/main @@ -1 +1 @@ -20cfb0cbabf22f1c12d626eec6e6dd834f4e43d1 +59fbea5efff5cfe6a005f33aaadbf21d58dc4af8 diff --git a/commands/utils/git.go b/commands/utils/git.go index 7b3a0ec66..fc941d2b3 100644 --- a/commands/utils/git.go +++ b/commands/utils/git.go @@ -80,13 +80,12 @@ func NewGitManager(dryRun bool, clonedRepoPath, projectPath, remoteName, token, return &GitManager{repository: repository, dryRunRepoPath: clonedRepoPath, remoteName: remoteName, auth: basicAuth, dryRun: dryRun, customTemplates: templates, git: g}, nil } -func (gm *GitManager) CheckoutLocalBranch(branchName string) error { - err := gm.createBranchAndCheckout(branchName, false) - if err != nil { - err = fmt.Errorf("'git checkout %s' failed with error: %s", branchName, err.Error()) +func (gm *GitManager) Checkout(branchName string) error { + log.Debug("Running git checkout to branch:", branchName) + if err := gm.createBranchAndCheckout(branchName, false); err != nil { + return fmt.Errorf("'git checkout %s' failed with error: %s", branchName, err.Error()) } - log.Debug("Running git checkout to local branch:", branchName) - return err + return nil } func (gm *GitManager) Clone(destinationPath, branchName string) error { @@ -164,6 +163,14 @@ func (gm *GitManager) createBranchAndCheckout(branchName string, create bool) er return worktree.Checkout(checkoutConfig) } +func getCurrentBranch(repository *git.Repository) (string, error) { + head, err := repository.Head() + if err != nil { + return "", err + } + return head.Name().Short(), nil +} + func (gm *GitManager) AddAllAndCommit(commitMessage string) error { log.Debug("Running git add all and commit...") err := gm.addAll() @@ -388,28 +395,6 @@ func (gm *GitManager) generateHTTPSCloneUrl() (url string, err error) { } } -func (gm *GitManager) CheckoutRemoteBranch(branchName string) error { - var checkoutConfig *git.CheckoutOptions - if gm.dryRun { - // On dry runs we mimic remote as local branches. - checkoutConfig = &git.CheckoutOptions{ - Branch: plumbing.NewBranchReferenceName(branchName), - Force: true, - } - } else { - checkoutConfig = &git.CheckoutOptions{ - Branch: plumbing.NewRemoteReferenceName(gm.remoteName, branchName), - Force: true, - } - } - log.Debug("Running git checkout to remote branch:", branchName) - worktree, err := gm.repository.Worktree() - if err != nil { - return err - } - return worktree.Checkout(checkoutConfig) -} - func toBasicAuth(token, username string) *githttp.BasicAuth { // The username can be anything except for an empty string if username == "" { @@ -429,6 +414,14 @@ func getFullBranchName(branchName string) plumbing.ReferenceName { return plumbing.NewBranchReferenceName(plumbing.ReferenceName(branchName).Short()) } +func GetBranchFromDotGit() (string, error) { + currentRepo, err := git.PlainOpen(".") + if err != nil { + return "", errors.New("unable to retrieve the branch to scan, as the .git folder was not found in the current working directory. The error that was received: " + err.Error()) + } + return getCurrentBranch(currentRepo) +} + func loadCustomTemplates(commitMessageTemplate, branchNameTemplate, pullRequestTitleTemplate string) (CustomTemplates, error) { template := CustomTemplates{ commitMessageTemplate: commitMessageTemplate, diff --git a/commands/utils/git_test.go b/commands/utils/git_test.go index fc0ac6e0d..9d6897ce5 100644 --- a/commands/utils/git_test.go +++ b/commands/utils/git_test.go @@ -1,10 +1,14 @@ package utils import ( + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" "github.com/jfrog/froggit-go/vcsclient" "github.com/jfrog/froggit-go/vcsutils" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/stretchr/testify/assert" + "os" "testing" ) @@ -232,7 +236,7 @@ func TestConvertSSHtoHTTPS(t *testing.T) { } for _, test := range testsCases { t.Run(test.vcsProvider.String(), func(t *testing.T) { - gm := GitManager{git: &Git{GitClientInfo: GitClientInfo{GitProvider: test.vcsProvider, RepoName: test.repoName, RepoOwner: test.repoOwner, VcsInfo: vcsclient.VcsInfo{Project: test.projectName, APIEndpoint: test.apiEndpoint}}}} + gm := GitManager{git: &Git{GitProvider: test.vcsProvider, RepoName: test.repoName, RepoOwner: test.repoOwner, VcsInfo: vcsclient.VcsInfo{Project: test.projectName, APIEndpoint: test.apiEndpoint}}} remoteUrl, err := gm.generateHTTPSCloneUrl() if remoteUrl == "" { assert.Equal(t, err.Error(), "unsupported version control provider: Bitbucket Cloud") @@ -243,3 +247,60 @@ func TestConvertSSHtoHTTPS(t *testing.T) { }) } } + +func TestGitManager_Checkout(t *testing.T) { + tmpDir, err := fileutils.CreateTempDir() + assert.NoError(t, err) + defer func() { + assert.NoError(t, fileutils.RemoveTempDir(tmpDir)) + }() + var restoreWd func() error + restoreWd, err = Chdir(tmpDir) + assert.NoError(t, err) + defer func() { + assert.NoError(t, restoreWd()) + }() + gitManager := createFakeDotGit(t, tmpDir) + // Get the current branch that is set as HEAD + headRef, err := gitManager.repository.Head() + assert.NoError(t, err) + assert.Equal(t, headRef.Name().Short(), "master") + // Create 'dev' branch and checkout + err = gitManager.CreateBranchAndCheckout("dev") + assert.NoError(t, err) + var currBranch string + currBranch, err = getCurrentBranch(gitManager.repository) + assert.NoError(t, err) + assert.Equal(t, "dev", currBranch) + // Checkout back to 'master' + assert.NoError(t, gitManager.Checkout("master")) + currBranch, err = getCurrentBranch(gitManager.repository) + assert.NoError(t, err) + assert.Equal(t, "master", currBranch) +} + +func createFakeDotGit(t *testing.T, testPath string) *GitManager { + // Initialize a new in-memory repository + repo, err := git.PlainInit(testPath, false) + assert.NoError(t, err) + // Create a new file and add it to the worktree + filename := "README.md" + content := []byte("# My New Repository\n\nThis is a sample repository created using go-git.") + err = os.WriteFile(filename, content, 0644) + assert.NoError(t, err) + worktree, err := repo.Worktree() + assert.NoError(t, err) + _, err = worktree.Add(filename) + assert.NoError(t, err) + // Commit the changes to the new main branch + _, err = worktree.Commit("Initial commit", &git.CommitOptions{ + Author: &object.Signature{ + Name: "Your Name", + Email: "your@email.com", + }, + }) + assert.NoError(t, err) + manager, err := NewGitManager(true, testPath, testPath, "origin", "", "", &Git{}) + assert.NoError(t, err) + return manager +} diff --git a/commands/utils/params.go b/commands/utils/params.go index 31240a69a..8c65da9b8 100644 --- a/commands/utils/params.go +++ b/commands/utils/params.go @@ -37,12 +37,17 @@ var ( type FrogbotDetails struct { Repositories RepoAggregator ServerDetails *coreconfig.ServerDetails - Client vcsclient.VcsClient + GitClient vcsclient.VcsClient ReleasesRepo string } type RepoAggregator []Repository +// NewRepoAggregator returns an initialized RepoAggregator with an empty repository +func NewRepoAggregator() RepoAggregator { + return RepoAggregator{{Params: Params{Scan: Scan{Projects: []Project{{}}}}}} +} + type Repository struct { Params `yaml:"params,omitempty"` OutputWriter @@ -55,8 +60,8 @@ type Params struct { JFrogPlatform `yaml:"jfrogPlatform,omitempty"` } -func (p *Params) setDefaultsIfNeeded(gitClientInfo *GitClientInfo) error { - if err := p.Git.setDefaultsIfNeeded(gitClientInfo); err != nil { +func (p *Params) setDefaultsIfNeeded(gitParamsFromEnv *Git) error { + if err := p.Git.setDefaultsIfNeeded(gitParamsFromEnv); err != nil { return err } if err := p.JFrogPlatform.setDefaultsIfNeeded(); err != nil { @@ -180,36 +185,38 @@ func (jp *JFrogPlatform) setDefaultsIfNeeded() (err error) { return } -type GitClientInfo struct { +type Git struct { GitProvider vcsutils.VcsProvider vcsclient.VcsInfo - RepoName string `yaml:"repoName,omitempty"` - Branches []string `yaml:"branches,omitempty"` - RepoOwner string -} - -type Git struct { - GitClientInfo `yaml:",inline"` - BranchNameTemplate string `yaml:"branchNameTemplate,omitempty"` - CommitMessageTemplate string `yaml:"commitMessageTemplate,omitempty"` - PullRequestTitleTemplate string `yaml:"pullRequestTitleTemplate,omitempty"` - EmailAuthor string `yaml:"emailAuthor,omitempty"` - AggregateFixes bool `yaml:"aggregateFixes,omitempty"` + RepoOwner string + RepoName string `yaml:"repoName,omitempty"` + Branches []string `yaml:"branches,omitempty"` + BranchNameTemplate string `yaml:"branchNameTemplate,omitempty"` + CommitMessageTemplate string `yaml:"commitMessageTemplate,omitempty"` + PullRequestTitleTemplate string `yaml:"pullRequestTitleTemplate,omitempty"` + EmailAuthor string `yaml:"emailAuthor,omitempty"` + AggregateFixes bool `yaml:"aggregateFixes,omitempty"` PullRequestID int } -func (g *Git) setDefaultsIfNeeded(gitClientInfo *GitClientInfo) (err error) { - g.RepoOwner = gitClientInfo.RepoOwner - g.GitProvider = gitClientInfo.GitProvider - g.VcsInfo = gitClientInfo.VcsInfo +func (g *Git) setDefaultsIfNeeded(gitParamsFromEnv *Git) (err error) { + g.RepoOwner = gitParamsFromEnv.RepoOwner + g.GitProvider = gitParamsFromEnv.GitProvider + g.VcsInfo = gitParamsFromEnv.VcsInfo if g.RepoName == "" { - if gitClientInfo.RepoName == "" { + if gitParamsFromEnv.RepoName == "" { return fmt.Errorf("repository name is missing. please set the repository name in your %s file or as the %s environment variable", FrogbotConfigFile, GitRepoEnv) } - g.RepoName = gitClientInfo.RepoName + g.RepoName = gitParamsFromEnv.RepoName } - if len(g.Branches) == 0 { - g.Branches = append(g.Branches, gitClientInfo.Branches...) + if len(g.Branches) == 0 && len(gitParamsFromEnv.Branches) == 0 { + var branch string + if branch, err = GetBranchFromDotGit(); err != nil { + return + } + g.Branches = append(g.Branches, branch) + } else if len(g.Branches) == 0 { + g.Branches = append(g.Branches, gitParamsFromEnv.Branches...) } if g.BranchNameTemplate == "" { branchTemplate := getTrimmedEnv(BranchNameTemplateEnv) @@ -236,8 +243,8 @@ func (g *Git) setDefaultsIfNeeded(gitClientInfo *GitClientInfo) (err error) { } if g.PullRequestID == UndefinedPrID { if idStr := getTrimmedEnv(GitPullRequestIDEnv); idStr != "" { - idNum, err := strconv.Atoi(idStr) - if err != nil { + var idNum int + if idNum, err = strconv.Atoi(idStr); err != nil { return fmt.Errorf("failed parsing pull request ID as a number. ID as string : %s", idStr) } g.PullRequestID = idNum @@ -253,13 +260,13 @@ func validateHashPlaceHolder(template string) error { return nil } -func GetFrogbotDetails() (frogbotUtils *FrogbotDetails, err error) { +func GetFrogbotDetails(commandName string) (frogbotDetails *FrogbotDetails, err error) { // Get server and git details jfrogServer, err := extractJFrogCredentialsFromEnvs() if err != nil { return } - gitClientInfo, err := extractGitInfoFromEnvs() + gitParamsFromEnv, err := extractGitInfoFromEnvs() if err != nil { return } @@ -270,56 +277,50 @@ func GetFrogbotDetails() (frogbotUtils *FrogbotDetails, err error) { // Build a version control client for REST API requests client, err := vcsclient. - NewClientBuilder(gitClientInfo.GitProvider). - ApiEndpoint(gitClientInfo.APIEndpoint). - Token(gitClientInfo.Token). - Project(gitClientInfo.Project). + NewClientBuilder(gitParamsFromEnv.GitProvider). + ApiEndpoint(gitParamsFromEnv.APIEndpoint). + Token(gitParamsFromEnv.Token). + Project(gitParamsFromEnv.Project). Logger(log.GetLogger()). - Username(gitClientInfo.Username). + Username(gitParamsFromEnv.Username). Build() if err != nil { return nil, err } - configAggregator, err := getConfigAggregator(client, gitClientInfo, jfrogServer) + configAggregator, err := getConfigAggregator(client, gitParamsFromEnv, jfrogServer, commandName) if err != nil { return nil, err } - return &FrogbotDetails{Repositories: configAggregator, Client: client, ServerDetails: jfrogServer, ReleasesRepo: os.Getenv(jfrogReleasesRepoEnv)}, err + return &FrogbotDetails{Repositories: configAggregator, GitClient: client, ServerDetails: jfrogServer, ReleasesRepo: os.Getenv(jfrogReleasesRepoEnv)}, err } // getConfigAggregator returns a RepoAggregator based on frogbot-config.yml and environment variables. -func getConfigAggregator(gitClient vcsclient.VcsClient, gitClientInfo *GitClientInfo, jfrogServer *coreconfig.ServerDetails) (RepoAggregator, error) { - configFileContent, err := getConfigFileContent(gitClient, gitClientInfo) +func getConfigAggregator(gitClient vcsclient.VcsClient, gitParamsFromEnv *Git, jfrogServer *coreconfig.ServerDetails, commandName string) (RepoAggregator, error) { + configFileContent, err := getConfigFileContent(gitClient, gitParamsFromEnv, commandName) // Don't return error in case of a missing frogbot-config.yml file // If an error occurs due to a missing file, attempt to generate an environment variable-based configuration aggregator as an alternative. var errMissingConfig *ErrMissingConfig if !errors.As(err, &errMissingConfig) && len(configFileContent) == 0 { return nil, err } - return BuildRepoAggregator(configFileContent, gitClientInfo, jfrogServer) + return BuildRepoAggregator(configFileContent, gitParamsFromEnv, jfrogServer) } // The getConfigFileContent function retrieves the frogbot-config.yml file content. // If the JF_GIT_REPO and JF_GIT_OWNER environment variables are set, this function will attempt to retrieve the frogbot-config.yml file from the target repository based on these variables. // If these variables aren't set, this function will attempt to retrieve the frogbot-config.yml file from the current working directory. -func getConfigFileContent(gitClient vcsclient.VcsClient, gitClientInfo *GitClientInfo) (configFileContent []byte, err error) { - configFileContent, err = readConfigFromTarget(gitClient, gitClientInfo) - var errMissingConfig *ErrMissingConfig - missingConfigErr := errors.As(err, &errMissingConfig) - if err != nil && !missingConfigErr { - return nil, err - } - // Read the config from the current working dir - if len(configFileContent) == 0 { +func getConfigFileContent(gitClient vcsclient.VcsClient, gitParamsFromEnv *Git, commandName string) (configFileContent []byte, err error) { + if commandName == ScanAndFixRepos || commandName == CreateFixPullRequests { configFileContent, err = ReadConfigFromFileSystem(osFrogbotConfigPath) + return } - return + return readConfigFromTarget(gitClient, gitParamsFromEnv) } -// BuildRepoAggregator receive a frogbot-config.yml file content along with the GitClientInfo and ServerDetails parameters. +// BuildRepoAggregator receives the content of a frogbot-config.yml file, along with the Git (built from environment variables) and ServerDetails parameters. // Returns a RepoAggregator instance with all the defaults and necessary fields. -func BuildRepoAggregator(configFileContent []byte, gitClientInfo *GitClientInfo, server *coreconfig.ServerDetails) (resultAggregator RepoAggregator, err error) { +func BuildRepoAggregator(configFileContent []byte, gitParamsFromEnv *Git, server *coreconfig.ServerDetails) (resultAggregator RepoAggregator, err error) { var cleanAggregator RepoAggregator // Unmarshal the frogbot-config.yml file if exists if cleanAggregator, err = unmarshalFrogbotConfigYaml(configFileContent); err != nil { @@ -327,8 +328,8 @@ func BuildRepoAggregator(configFileContent []byte, gitClientInfo *GitClientInfo, } for _, repository := range cleanAggregator { repository.Server = *server - repository.OutputWriter = GetCompatibleOutputWriter(gitClientInfo.GitProvider) - if err = repository.Params.setDefaultsIfNeeded(gitClientInfo); err != nil { + repository.OutputWriter = GetCompatibleOutputWriter(gitParamsFromEnv.GitProvider) + if err = repository.Params.setDefaultsIfNeeded(gitParamsFromEnv); err != nil { return } resultAggregator = append(resultAggregator, repository) @@ -341,7 +342,8 @@ func BuildRepoAggregator(configFileContent []byte, gitClientInfo *GitClientInfo, // If there is no config file, the function returns a RepoAggregator with an empty repository. func unmarshalFrogbotConfigYaml(yamlContent []byte) (result RepoAggregator, err error) { if len(yamlContent) == 0 { - return RepoAggregator{{Params: Params{Scan: Scan{Projects: []Project{{}}}}}}, nil + result = NewRepoAggregator() + return } err = yaml.Unmarshal(yamlContent, &result) return @@ -377,10 +379,10 @@ func extractJFrogCredentialsFromEnvs() (*coreconfig.ServerDetails, error) { return &server, nil } -func extractGitInfoFromEnvs() (*GitClientInfo, error) { +func extractGitInfoFromEnvs() (*Git, error) { e := &ErrMissingEnv{} var err error - clientInfo := &GitClientInfo{} + gitEnvParams := &Git{} // Branch & Repo names are mandatory variables. // Must be set in the frogbot-config.yml or as an environment variables. // Validation performed later @@ -389,44 +391,46 @@ func extractGitInfoFromEnvs() (*GitClientInfo, error) { if err = readParamFromEnv(GitBaseBranchEnv, &branch); err != nil && !e.IsMissingEnvErr(err) { return nil, err } - clientInfo.Branches = []string{branch} + if branch != "" { + gitEnvParams.Branches = []string{branch} + } // Set the repository name - if err = readParamFromEnv(GitRepoEnv, &clientInfo.RepoName); err != nil && !e.IsMissingEnvErr(err) { + if err = readParamFromEnv(GitRepoEnv, &gitEnvParams.RepoName); err != nil && !e.IsMissingEnvErr(err) { return nil, err } // Non-mandatory Git Api Endpoint, if not set, default values will be used. - if err = readParamFromEnv(GitApiEndpointEnv, &clientInfo.APIEndpoint); err != nil && !e.IsMissingEnvErr(err) { + if err = readParamFromEnv(GitApiEndpointEnv, &gitEnvParams.APIEndpoint); err != nil && !e.IsMissingEnvErr(err) { return nil, err } - if err = verifyValidApiEndpoint(clientInfo.APIEndpoint); err != nil { + if err = verifyValidApiEndpoint(gitEnvParams.APIEndpoint); err != nil { return nil, err } // Set the Git provider - if clientInfo.GitProvider, err = extractVcsProviderFromEnv(); err != nil { + if gitEnvParams.GitProvider, err = extractVcsProviderFromEnv(); err != nil { return nil, err } // Set the git repository owner name (organization) - if err = readParamFromEnv(GitRepoOwnerEnv, &clientInfo.RepoOwner); err != nil { + if err = readParamFromEnv(GitRepoOwnerEnv, &gitEnvParams.RepoOwner); err != nil { return nil, err } // Set the access token to the git provider - if err = readParamFromEnv(GitTokenEnv, &clientInfo.Token); err != nil { + if err = readParamFromEnv(GitTokenEnv, &gitEnvParams.Token); err != nil { return nil, err } // Set Bitbucket Server username // Mandatory only for Bitbucket Server, this authentication detail is required for performing git operations. - if err = readParamFromEnv(GitUsernameEnv, &clientInfo.Username); err != nil && !e.IsMissingEnvErr(err) { + if err = readParamFromEnv(GitUsernameEnv, &gitEnvParams.Username); err != nil && !e.IsMissingEnvErr(err) { return nil, err } // Set Azure Repos Project name // Mandatory for Azure Repos only - if err = readParamFromEnv(GitProjectEnv, &clientInfo.Project); err != nil && clientInfo.GitProvider == vcsutils.AzureRepos { + if err = readParamFromEnv(GitProjectEnv, &gitEnvParams.Project); err != nil && gitEnvParams.GitProvider == vcsutils.AzureRepos { return nil, err } - return clientInfo, nil + return gitEnvParams, nil } func verifyValidApiEndpoint(apiEndpoint string) error { @@ -535,22 +539,26 @@ func getBoolEnv(envKey string, defaultValue bool) (bool, error) { } // readConfigFromTarget reads the .frogbot/frogbot-config.yml from the target repository -func readConfigFromTarget(client vcsclient.VcsClient, clientInfo *GitClientInfo) (configContent []byte, err error) { - if clientInfo.RepoName != "" && clientInfo.RepoOwner != "" { - log.Debug("Downloading", FrogbotConfigFile, "from target", clientInfo.RepoOwner, "/", clientInfo.RepoName) +func readConfigFromTarget(client vcsclient.VcsClient, gitParamsFromEnv *Git) (configContent []byte, err error) { + repoName := gitParamsFromEnv.RepoName + repoOwner := gitParamsFromEnv.RepoOwner + branches := gitParamsFromEnv.Branches + if repoName != "" && repoOwner != "" { + log.Debug("Downloading", FrogbotConfigFile, "from target", repoOwner, "/", repoName) var branch string - if len(clientInfo.Branches) == 0 { + if len(branches) == 0 { log.Debug(GitBaseBranchEnv, "is missing. Assuming that the", FrogbotConfigFile, "file exists on default branch") } else { - branch = clientInfo.Branches[0] + // We encounter this scenario when the JF_GIT_BASE_BRANCH is defined. In this situation, we have only one branch. + branch = branches[0] log.Debug("the", FrogbotConfigFile, "will be downloaded from the", branch, "branch") } gitFrogbotConfigPath := fmt.Sprintf("%s/%s", frogbotConfigDir, FrogbotConfigFile) var statusCode int - configContent, statusCode, err = client.DownloadFileFromRepo(context.Background(), clientInfo.RepoOwner, clientInfo.RepoName, branch, gitFrogbotConfigPath) + configContent, statusCode, err = client.DownloadFileFromRepo(context.Background(), repoOwner, repoName, branch, gitFrogbotConfigPath) if statusCode == http.StatusNotFound { - log.Debug(fmt.Sprintf("the %s file wasn't recognized in the %s repository owned by %s", gitFrogbotConfigPath, clientInfo.RepoName, clientInfo.RepoOwner)) + log.Debug(fmt.Sprintf("the %s file wasn't recognized in the %s repository owned by %s", gitFrogbotConfigPath, repoName, repoOwner)) // If .frogbot/frogbot-config.yml isn't found, we'll try to run Frogbot using environment variables return nil, &ErrMissingConfig{errFrogbotConfigNotFound.Error()} } diff --git a/commands/utils/params_test.go b/commands/utils/params_test.go index effd132e2..5a8ec278b 100644 --- a/commands/utils/params_test.go +++ b/commands/utils/params_test.go @@ -314,7 +314,7 @@ func TestGenerateConfigAggregatorFromEnv(t *testing.T) { assert.NoError(t, SanitizeEnv()) }() - gitClientInfo := GitClientInfo{ + gitParams := Git{ GitProvider: vcsutils.GitHub, VcsInfo: vcsclient.VcsInfo{ APIEndpoint: "https://github.com", @@ -330,7 +330,7 @@ func TestGenerateConfigAggregatorFromEnv(t *testing.T) { User: "admin", Password: "password", } - repoAggregator, err := BuildRepoAggregator(nil, &gitClientInfo, &server) + repoAggregator, err := BuildRepoAggregator(nil, &gitParams, &server) assert.NoError(t, err) repo := repoAggregator[0] assert.Equal(t, "repoName", repo.RepoName) @@ -338,12 +338,12 @@ func TestGenerateConfigAggregatorFromEnv(t *testing.T) { assert.Equal(t, false, *repo.FailOnSecurityIssues) assert.Equal(t, "Medium", repo.MinSeverity) assert.Equal(t, true, repo.FixableOnly) - assert.Equal(t, gitClientInfo.RepoOwner, repo.RepoOwner) - assert.Equal(t, gitClientInfo.Token, repo.Token) - assert.Equal(t, gitClientInfo.APIEndpoint, repo.APIEndpoint) - assert.ElementsMatch(t, gitClientInfo.Branches, repo.Branches) + assert.Equal(t, gitParams.RepoOwner, repo.RepoOwner) + assert.Equal(t, gitParams.Token, repo.Token) + assert.Equal(t, gitParams.APIEndpoint, repo.APIEndpoint) + assert.ElementsMatch(t, gitParams.Branches, repo.Branches) assert.Equal(t, repo.PullRequestID, repo.PullRequestID) - assert.Equal(t, gitClientInfo.GitProvider, repo.GitProvider) + assert.Equal(t, gitParams.GitProvider, repo.GitProvider) assert.Equal(t, repo.BranchNameTemplate, repo.BranchNameTemplate) assert.Equal(t, repo.CommitMessageTemplate, repo.CommitMessageTemplate) assert.Equal(t, repo.PullRequestTitleTemplate, repo.PullRequestTitleTemplate) @@ -463,7 +463,7 @@ func TestBuildMergedRepoAggregator(t *testing.T) { testFilePath := filepath.Join("..", "testdata", "config", "frogbot-config-test-params-merge.yml") fileContent, err := os.ReadFile(testFilePath) assert.NoError(t, err) - gitClientInfo := &GitClientInfo{ + gitParams := &Git{ GitProvider: vcsutils.GitHub, VcsInfo: vcsclient.VcsInfo{ APIEndpoint: "endpoint.com", @@ -479,7 +479,7 @@ func TestBuildMergedRepoAggregator(t *testing.T) { User: "admin", Password: "password", } - repoAggregator, err := BuildRepoAggregator(fileContent, gitClientInfo, &server) + repoAggregator, err := BuildRepoAggregator(fileContent, gitParams, &server) assert.NoError(t, err) repo := repoAggregator[0] diff --git a/commands/utils/utils.go b/commands/utils/utils.go index e75b2e5b0..2cee2c3d5 100644 --- a/commands/utils/utils.go +++ b/commands/utils/utils.go @@ -26,8 +26,12 @@ import ( ) const ( - RootDir = "." - branchNameRegex = `[~^:?\\\[\]@{}*]` + ScanPullRequest = "scan-pull-request" + ScanPullRequests = "scan-pull-requests" + CreateFixPullRequests = "create-fix-pull-requests" + ScanAndFixRepos = "scan-and-fix-repos" + RootDir = "." + branchNameRegex = `[~^:?\\\[\]@{}*]` // Branch validation error messages branchInvalidChars = "branch name cannot contain the following chars ~, ^, :, ?, *, [, ], @, {, }"