Skip to content

Commit 55d80fa

Browse files
authored
Enable using local repository instead cloning a remote repo - ScanRepository (#767)
1 parent 9d5ed08 commit 55d80fa

File tree

9 files changed

+139
-62
lines changed

9 files changed

+139
-62
lines changed

azure_test.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,30 @@ func buildAzureReposClient(t *testing.T, azureToken string) vcsclient.VcsClient
2020
return azureClient
2121
}
2222

23-
func buildAzureReposIntegrationTestDetails(t *testing.T) *IntegrationTestDetails {
23+
func buildAzureReposIntegrationTestDetails(t *testing.T, useLocalRepo bool) *IntegrationTestDetails {
2424
integrationRepoToken := getIntegrationToken(t, azureIntegrationTokenEnv)
25-
testDetails := NewIntegrationTestDetails(integrationRepoToken, string(utils.AzureRepos), azureGitCloneUrl, "frogbot-test")
25+
testDetails := NewIntegrationTestDetails(integrationRepoToken, string(utils.AzureRepos), azureGitCloneUrl, "frogbot-test", useLocalRepo)
2626
testDetails.ApiEndpoint = azureApiEndpoint
2727
return testDetails
2828
}
2929

30-
func azureReposTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) {
31-
testDetails := buildAzureReposIntegrationTestDetails(t)
30+
func azureReposTestsInit(t *testing.T, useLocalRepo bool) (vcsclient.VcsClient, *IntegrationTestDetails) {
31+
testDetails := buildAzureReposIntegrationTestDetails(t, useLocalRepo)
3232
azureClient := buildAzureReposClient(t, testDetails.GitToken)
3333
return azureClient, testDetails
3434
}
3535

3636
func TestAzureRepos_ScanPullRequestIntegration(t *testing.T) {
37-
azureClient, testDetails := azureReposTestsInit(t)
37+
azureClient, testDetails := azureReposTestsInit(t, false)
3838
runScanPullRequestCmd(t, azureClient, testDetails)
3939
}
4040

4141
func TestAzureRepos_ScanRepositoryIntegration(t *testing.T) {
42-
azureClient, testDetails := azureReposTestsInit(t)
42+
azureClient, testDetails := azureReposTestsInit(t, false)
43+
runScanRepositoryCmd(t, azureClient, testDetails)
44+
}
45+
46+
func TestAzureRepos_ScanRepositoryWithLocalDirIntegration(t *testing.T) {
47+
azureClient, testDetails := azureReposTestsInit(t, true)
4348
runScanRepositoryCmd(t, azureClient, testDetails)
4449
}

bitbucket_server_test.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ func buildBitbucketServerClient(t *testing.T, bitbucketServerToken string) vcscl
2626
return bbClient
2727
}
2828

29-
func buildBitbucketServerIntegrationTestDetails(t *testing.T) *IntegrationTestDetails {
29+
func buildBitbucketServerIntegrationTestDetails(t *testing.T, useLocalRepo bool) *IntegrationTestDetails {
3030
integrationRepoToken := getIntegrationToken(t, bitbucketServerIntegrationTokenEnv)
31-
testDetails := NewIntegrationTestDetails(integrationRepoToken, string(utils.BitbucketServer), bitbucketServerGitCloneUrl, "FROG")
31+
testDetails := NewIntegrationTestDetails(integrationRepoToken, string(utils.BitbucketServer), bitbucketServerGitCloneUrl, "FROG", useLocalRepo)
3232
testDetails.ApiEndpoint = bitbucketServerApiEndpoint
3333
return testDetails
3434
}
@@ -53,19 +53,24 @@ func waitForConnection(t *testing.T) {
5353
require.NoError(t, retryExecutor.Execute())
5454
}
5555

56-
func bitbucketServerTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) {
57-
testDetails := buildBitbucketServerIntegrationTestDetails(t)
56+
func bitbucketServerTestsInit(t *testing.T, useLocalRepo bool) (vcsclient.VcsClient, *IntegrationTestDetails) {
57+
testDetails := buildBitbucketServerIntegrationTestDetails(t, useLocalRepo)
5858
bbClient := buildBitbucketServerClient(t, testDetails.GitToken)
5959
waitForConnection(t)
6060
return bbClient, testDetails
6161
}
6262

6363
func TestBitbucketServer_ScanPullRequestIntegration(t *testing.T) {
64-
bbClient, testDetails := bitbucketServerTestsInit(t)
64+
bbClient, testDetails := bitbucketServerTestsInit(t, false)
6565
runScanPullRequestCmd(t, bbClient, testDetails)
6666
}
6767

6868
func TestBitbucketServer_ScanRepositoryIntegration(t *testing.T) {
69-
bbClient, testDetails := bitbucketServerTestsInit(t)
69+
bbClient, testDetails := bitbucketServerTestsInit(t, false)
70+
runScanRepositoryCmd(t, bbClient, testDetails)
71+
}
72+
73+
func TestBitbucketServer_ScanRepositoryWithLocalDirIntegration(t *testing.T) {
74+
bbClient, testDetails := bitbucketServerTestsInit(t, true)
7075
runScanRepositoryCmd(t, bbClient, testDetails)
7176
}

github_test.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,28 @@ func buildGitHubClient(t *testing.T, githubToken string) vcsclient.VcsClient {
1919
return githubClient
2020
}
2121

22-
func buildGitHubIntegrationTestDetails(t *testing.T) *IntegrationTestDetails {
22+
func buildGitHubIntegrationTestDetails(t *testing.T, useLocalRepo bool) *IntegrationTestDetails {
2323
integrationRepoToken := getIntegrationToken(t, githubIntegrationTokenEnv)
24-
return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitHub), githubGitCloneUrl, "frogbot-test")
24+
return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitHub), githubGitCloneUrl, "frogbot-test", useLocalRepo)
2525
}
2626

27-
func githubTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) {
28-
testDetails := buildGitHubIntegrationTestDetails(t)
27+
func githubTestsInit(t *testing.T, useLocalRepo bool) (vcsclient.VcsClient, *IntegrationTestDetails) {
28+
testDetails := buildGitHubIntegrationTestDetails(t, useLocalRepo)
2929
githubClient := buildGitHubClient(t, testDetails.GitToken)
3030
return githubClient, testDetails
3131
}
3232

3333
func TestGitHub_ScanPullRequestIntegration(t *testing.T) {
34-
githubClient, testDetails := githubTestsInit(t)
34+
githubClient, testDetails := githubTestsInit(t, false)
3535
runScanPullRequestCmd(t, githubClient, testDetails)
3636
}
3737

3838
func TestGitHub_ScanRepositoryIntegration(t *testing.T) {
39-
githubClient, testDetails := githubTestsInit(t)
39+
githubClient, testDetails := githubTestsInit(t, false)
40+
runScanRepositoryCmd(t, githubClient, testDetails)
41+
}
42+
43+
func TestGitHub_ScanRepositoryWithLocalDirIntegration(t *testing.T) {
44+
githubClient, testDetails := githubTestsInit(t, true)
4045
runScanRepositoryCmd(t, githubClient, testDetails)
4146
}

gitlab_test.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,28 @@ func buildGitLabClient(t *testing.T, gitlabToken string) vcsclient.VcsClient {
1919
return azureClient
2020
}
2121

22-
func buildGitLabIntegrationTestDetails(t *testing.T) *IntegrationTestDetails {
22+
func buildGitLabIntegrationTestDetails(t *testing.T, useLocalRepo bool) *IntegrationTestDetails {
2323
integrationRepoToken := getIntegrationToken(t, gitlabIntegrationTokenEnv)
24-
return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitLab), gitlabGitCloneUrl, "frogbot-test2")
24+
return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitLab), gitlabGitCloneUrl, "frogbot-test2", useLocalRepo)
2525
}
2626

27-
func gitlabTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) {
28-
testDetails := buildGitLabIntegrationTestDetails(t)
27+
func gitlabTestsInit(t *testing.T, useLocalRepo bool) (vcsclient.VcsClient, *IntegrationTestDetails) {
28+
testDetails := buildGitLabIntegrationTestDetails(t, useLocalRepo)
2929
gitlabClient := buildGitLabClient(t, testDetails.GitToken)
3030
return gitlabClient, testDetails
3131
}
3232

3333
func TestGitLab_ScanPullRequestIntegration(t *testing.T) {
34-
gitlabClient, testDetails := gitlabTestsInit(t)
34+
gitlabClient, testDetails := gitlabTestsInit(t, false)
3535
runScanPullRequestCmd(t, gitlabClient, testDetails)
3636
}
3737

3838
func TestGitLab_ScanRepositoryIntegration(t *testing.T) {
39-
gitlabClient, testDetails := gitlabTestsInit(t)
39+
gitlabClient, testDetails := gitlabTestsInit(t, false)
40+
runScanRepositoryCmd(t, gitlabClient, testDetails)
41+
}
42+
43+
func TestGitLab_ScanRepositoryWithLocalDirIntegration(t *testing.T) {
44+
gitlabClient, testDetails := gitlabTestsInit(t, true)
4045
runScanRepositoryCmd(t, gitlabClient, testDetails)
4146
}

integrationutils.go

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package main
33
import (
44
"context"
55
"fmt"
6+
"github.com/go-git/go-git/v5"
7+
githttp "github.com/go-git/go-git/v5/plumbing/transport/http"
68
"github.com/jfrog/frogbot/v2/scanpullrequest"
79
"github.com/jfrog/frogbot/v2/scanrepository"
810
"github.com/jfrog/frogbot/v2/utils"
@@ -36,17 +38,19 @@ type IntegrationTestDetails struct {
3638
ApiEndpoint string
3739
PullRequestID string
3840
CustomBranchName string
41+
UseLocalRepo bool
3942
}
4043

41-
func NewIntegrationTestDetails(token, gitProvider, gitCloneUrl, repoOwner string) *IntegrationTestDetails {
44+
func NewIntegrationTestDetails(token, gitProvider, gitCloneUrl, repoOwner string, useLocalRepo bool) *IntegrationTestDetails {
4245
return &IntegrationTestDetails{
43-
GitProject: repoName,
44-
RepoOwner: repoOwner,
45-
RepoName: repoName,
46-
GitToken: token,
47-
GitUsername: "frogbot",
48-
GitProvider: gitProvider,
49-
GitCloneURL: gitCloneUrl,
46+
GitProject: repoName,
47+
RepoOwner: repoOwner,
48+
RepoName: repoName,
49+
GitToken: token,
50+
GitUsername: "frogbot",
51+
GitProvider: gitProvider,
52+
GitCloneURL: gitCloneUrl,
53+
UseLocalRepo: useLocalRepo,
5054
}
5155
}
5256

@@ -71,18 +75,23 @@ func setIntegrationTestEnvs(t *testing.T, testDetails *IntegrationTestDetails) f
7175
// Frogbot sanitizes all the environment variables that start with 'JF',
7276
// so we restore them at the end of the test to avoid collisions with other tests
7377
envRestoreFunc := getJfrogEnvRestoreFunc(t)
78+
useLocalRepo := "false"
79+
if testDetails.UseLocalRepo {
80+
useLocalRepo = "true"
81+
}
7482
unsetEnvs := utils.SetEnvsAndAssertWithCallback(t, map[string]string{
75-
utils.RequirementsFileEnv: "requirements.txt",
76-
utils.GitPullRequestIDEnv: testDetails.PullRequestID,
77-
utils.GitProvider: testDetails.GitProvider,
78-
utils.GitTokenEnv: testDetails.GitToken,
79-
utils.GitRepoEnv: testDetails.RepoName,
80-
utils.GitRepoOwnerEnv: testDetails.RepoOwner,
81-
utils.BranchNameTemplateEnv: testDetails.CustomBranchName,
82-
utils.GitApiEndpointEnv: testDetails.ApiEndpoint,
83-
utils.GitProjectEnv: testDetails.GitProject,
84-
utils.GitUsernameEnv: testDetails.GitUsername,
85-
utils.GitBaseBranchEnv: mainBranch,
83+
utils.RequirementsFileEnv: "requirements.txt",
84+
utils.GitPullRequestIDEnv: testDetails.PullRequestID,
85+
utils.GitProvider: testDetails.GitProvider,
86+
utils.GitTokenEnv: testDetails.GitToken,
87+
utils.GitRepoEnv: testDetails.RepoName,
88+
utils.GitRepoOwnerEnv: testDetails.RepoOwner,
89+
utils.BranchNameTemplateEnv: testDetails.CustomBranchName,
90+
utils.GitApiEndpointEnv: testDetails.ApiEndpoint,
91+
utils.GitProjectEnv: testDetails.GitProject,
92+
utils.GitUsernameEnv: testDetails.GitUsername,
93+
utils.GitBaseBranchEnv: mainBranch,
94+
utils.GitUseLocalRepositoryEnv: useLocalRepo,
8695
})
8796
return func() {
8897
envRestoreFunc()
@@ -173,11 +182,28 @@ func runScanPullRequestCmd(t *testing.T, client vcsclient.VcsClient, testDetails
173182
}
174183

175184
func runScanRepositoryCmd(t *testing.T, client vcsclient.VcsClient, testDetails *IntegrationTestDetails) {
176-
_, restoreFunc := utils.ChangeToTempDirWithCallback(t)
185+
testTempDir, restoreFunc := utils.ChangeToTempDirWithCallback(t)
177186
defer func() {
178187
assert.NoError(t, restoreFunc())
179188
}()
180189

190+
// When testing using local repository clone the repository before the test starts so we can work with it as if it existed locally
191+
if testDetails.UseLocalRepo {
192+
cloneOptions := &git.CloneOptions{
193+
URL: testDetails.GitCloneURL,
194+
Auth: &githttp.BasicAuth{
195+
Username: testDetails.GitUsername,
196+
Password: testDetails.GitToken,
197+
},
198+
RemoteName: "origin",
199+
ReferenceName: utils.GetFullBranchName("main"),
200+
SingleBranch: true,
201+
Depth: 1,
202+
Tags: git.NoTags,
203+
}
204+
_, err := git.PlainClone(testTempDir, false, cloneOptions)
205+
require.NoError(t, err)
206+
}
181207
timestamp := getTimestamp()
182208
// Add a timestamp to the fixing pull requests, to identify them later
183209
testDetails.CustomBranchName = "frogbot-{IMPACTED_PACKAGE}-{BRANCH_NAME_HASH}-" + timestamp

scanrepository/scanrepository.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
biutils "github.com/jfrog/build-info-go/utils"
8+
"os"
79
"path/filepath"
810
"regexp"
911
"strings"
@@ -80,17 +82,17 @@ func (cfp *ScanRepositoryCmd) scanAndFixBranch(repository *utils.Repository) (er
8082
cfp.analyticsService.UpdateAndSendXscAnalyticsGeneralEventFinalize(err)
8183
}()
8284

83-
clonedRepoDir, restoreBaseDir, err := cfp.cloneRepositoryAndCheckoutToBranch()
85+
repoDir, restoreBaseDir, err := cfp.cloneRepositoryOrUseLocalAndCheckoutToBranch()
8486
if err != nil {
8587
return
8688
}
87-
cfp.baseWd = clonedRepoDir
89+
cfp.baseWd = repoDir
8890
defer func() {
8991
// On dry run don't delete the folder as we want to validate results
9092
if cfp.dryRun {
9193
return
9294
}
93-
err = errors.Join(err, restoreBaseDir(), fileutils.RemoveTempDir(clonedRepoDir))
95+
err = errors.Join(err, restoreBaseDir(), fileutils.RemoveTempDir(repoDir))
9496
}()
9597

9698
// If MSI exists we always need to report events
@@ -476,7 +478,7 @@ func (cfp *ScanRepositoryCmd) preparePullRequestDetails(vulnerabilitiesDetails .
476478
return pullRequestTitle, prBody, extraComments, nil
477479
}
478480

479-
func (cfp *ScanRepositoryCmd) cloneRepositoryAndCheckoutToBranch() (tempWd string, restoreDir func() error, err error) {
481+
func (cfp *ScanRepositoryCmd) cloneRepositoryOrUseLocalAndCheckoutToBranch() (tempWd string, restoreDir func() error, err error) {
480482
if cfp.dryRun {
481483
tempWd = filepath.Join(cfp.dryRunRepoPath, cfp.scanDetails.RepoName)
482484
} else {
@@ -487,13 +489,29 @@ func (cfp *ScanRepositoryCmd) cloneRepositoryAndCheckoutToBranch() (tempWd strin
487489
}
488490
log.Debug("Created temp working directory:", tempWd)
489491

490-
// Clone the content of the repo to the new working directory
491-
if err = cfp.gitManager.Clone(tempWd, cfp.scanDetails.BaseBranch()); err != nil {
492-
return
492+
if cfp.scanDetails.UseLocalRepository {
493+
var curDir string
494+
if curDir, err = os.Getwd(); err != nil {
495+
return
496+
}
497+
if err = biutils.CopyDir(curDir, tempWd, true, nil); err != nil {
498+
return
499+
}
500+
// 'CD' into the temp working directory
501+
restoreDir, err = utils.Chdir(tempWd)
502+
if err != nil {
503+
return
504+
}
505+
// Set the current copied local dir as the local git repository we are working with
506+
err = cfp.gitManager.SetLocalRepository()
507+
} else {
508+
// Clone the content of the repo to the new working directory
509+
if err = cfp.gitManager.Clone(tempWd, cfp.scanDetails.BaseBranch()); err != nil {
510+
return
511+
}
512+
// 'CD' into the temp working directory
513+
restoreDir, err = utils.Chdir(tempWd)
493514
}
494-
495-
// 'CD' into the temp working directory
496-
restoreDir, err = utils.Chdir(tempWd)
497515
return
498516
}
499517

utils/consts.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ const (
3434
JfrogConfigProfileEnv = "JF_CONFIG_PROFILE"
3535

3636
// Git environment variables
37-
GitProvider = "JF_GIT_PROVIDER"
38-
GitRepoOwnerEnv = "JF_GIT_OWNER"
39-
GitRepoEnv = "JF_GIT_REPO"
40-
GitProjectEnv = "JF_GIT_PROJECT"
41-
GitUsernameEnv = "JF_GIT_USERNAME"
37+
GitProvider = "JF_GIT_PROVIDER"
38+
GitRepoOwnerEnv = "JF_GIT_OWNER"
39+
GitRepoEnv = "JF_GIT_REPO"
40+
GitProjectEnv = "JF_GIT_PROJECT"
41+
GitUsernameEnv = "JF_GIT_USERNAME"
42+
GitUseLocalRepositoryEnv = "JF_USE_LOCAL_REPOSITORY"
4243

4344
// Git naming template environment variables
4445
BranchNameTemplateEnv = "JF_BRANCH_NAME_TEMPLATE"

utils/git.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func (gm *GitManager) SetRemoteGitUrl(remoteHttpsGitUrl string) (*GitManager, er
9292
}
9393

9494
if gm.localGitRepository == nil {
95-
if _, err = gm.SetLocalRepository(); err != nil {
95+
if _, err = gm.SetLocalRepositoryAndRemoteName(); err != nil {
9696
return gm, err
9797
}
9898
}
@@ -115,14 +115,20 @@ func (gm *GitManager) SetRemoteGitUrl(remoteHttpsGitUrl string) (*GitManager, er
115115
return gm, nil
116116
}
117117

118-
func (gm *GitManager) SetLocalRepository() (*GitManager, error) {
118+
func (gm *GitManager) SetLocalRepositoryAndRemoteName() (*GitManager, error) {
119119
var err error
120120
// Re-initialize the repository and update remoteName
121121
gm.remoteName = vcsutils.RemoteName
122-
gm.localGitRepository, err = git.PlainOpen(".")
122+
err = gm.SetLocalRepository()
123123
return gm, err
124124
}
125125

126+
func (gm *GitManager) SetLocalRepository() error {
127+
var err error
128+
gm.localGitRepository, err = git.PlainOpen(".")
129+
return err
130+
}
131+
126132
func (gm *GitManager) SetGitParams(gitParams *Git) (*GitManager, error) {
127133
var err error
128134
if gm.customTemplates, err = loadCustomTemplates(gitParams.CommitMessageTemplate, gitParams.BranchNameTemplate, gitParams.PullRequestTitleTemplate); err != nil {

utils/params.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ type Git struct {
302302
AggregateFixes bool `yaml:"aggregateFixes,omitempty"`
303303
PullRequestDetails vcsclient.PullRequestInfo
304304
RepositoryCloneUrl string
305+
UseLocalRepository bool
305306
}
306307

307308
func (g *Git) setDefaultsIfNeeded(gitParamsFromEnv *Git, commandName string) (err error) {
@@ -373,6 +374,11 @@ func (g *Git) extractScanRepositoryEnvParams(gitParamsFromEnv *Git) (err error)
373374
return
374375
}
375376
}
377+
if !g.UseLocalRepository {
378+
if g.UseLocalRepository, err = getBoolEnv(GitUseLocalRepositoryEnv, false); err != nil {
379+
return
380+
}
381+
}
376382
return
377383
}
378384

0 commit comments

Comments
 (0)