Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions schema/frogbot-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
"description": "The name of the git repository to scan.",
"examples": ["repo-name"]
},
"lfsCheckout": {
"type": "boolean",
"title": "lfsCheckout",
"description": "Use `git lfs pull` after cloning the repository.",
"default": false
},
"branches": {
"type": "array",
"title": "Repository Branches",
Expand Down
22 changes: 22 additions & 0 deletions utils/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"net/http"
"os/exec"

"regexp"
"strings"
Expand Down Expand Up @@ -241,6 +242,27 @@ func (gm *GitManager) Clone(destinationPath, branchName string) error {
}
gm.localGitRepository = repo
log.Debug(fmt.Sprintf("Project cloned from %s to %s", credentialsFreeRemoteGitUrl, destinationPath))

if gm.git != nil && gm.git.LfsCheckout {
if err := gm.lfsCheckout(destinationPath); err != nil {
return fmt.Errorf("git lfs pull failed with error: %s", err.Error())
}
}

return nil
}

// lfsCheckout performs git lfs pull to fetch LFS objects after cloning
func (gm *GitManager) lfsCheckout(workingDir string) error {
log.Debug("Running git lfs pull...")
// Use exec.Command to run git lfs pull since go-git doesn't support LFS natively
cmd := exec.Command("git", "lfs", "pull")
cmd.Dir = workingDir
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to run git lfs pull: %s, output: %s", err.Error(), string(output))
}
log.Debug("Git LFS pull completed successfully")
return nil
}

Expand Down
75 changes: 75 additions & 0 deletions utils/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,78 @@ func TestRemoveCredentialsFromUrlIfNeeded(t *testing.T) {
})
}
}

func TestGitManager_Clone_WithLfsCheckout(t *testing.T) {
testCases := []struct {
name string
lfsCheckout bool
description string
expectLfsPull bool
}{
{
name: "Clone without LFS checkout",
lfsCheckout: false,
description: "LFS checkout disabled, should not attempt git lfs pull",
expectLfsPull: false,
},
{
name: "Clone with LFS checkout enabled",
lfsCheckout: true,
description: "LFS checkout enabled, should attempt git lfs pull",
expectLfsPull: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
tmpDir, err := fileutils.CreateTempDir()
assert.NoError(t, err)
defer func() {
assert.NoError(t, fileutils.RemoveTempDir(tmpDir))
}()

// Create a git manager in dry run mode
gitManager := NewGitManager().SetDryRun(true, tmpDir)
gitManager.SetGitParams(&Git{
LfsCheckout: tc.lfsCheckout,
})

// Since we're in dry run mode, Clone will not actually attempt to run git lfs pull
// The test verifies that the SetGitParams correctly sets the LfsCheckout flag
assert.NotNil(t, gitManager.git)
assert.Equal(t, tc.lfsCheckout, gitManager.git.LfsCheckout)
})
}
}

func TestGitManager_SetGitParams_LfsCheckout(t *testing.T) {
testCases := []struct {
name string
lfsCheckout bool
}{
{
name: "LFS checkout disabled",
lfsCheckout: false,
},
{
name: "LFS checkout enabled",
lfsCheckout: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
gitManager := NewGitManager()
gitParams := &Git{
LfsCheckout: tc.lfsCheckout,
EmailAuthor: "[email protected]",
}

resultManager, err := gitManager.SetGitParams(gitParams)
assert.NoError(t, err)
assert.NotNil(t, resultManager.git)
assert.Equal(t, tc.lfsCheckout, resultManager.git.LfsCheckout)
assert.Equal(t, "[email protected]", resultManager.git.EmailAuthor)
})
}
}
1 change: 1 addition & 0 deletions utils/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ type Git struct {
UseMostCommonAncestorAsTarget *bool `yaml:"useMostCommonAncestorAsTarget,omitempty"`
RepoOwner string
RepoName string `yaml:"repoName,omitempty"`
LfsCheckout bool `yaml:"lfsCheckout"`
Branches []string `yaml:"branches,omitempty"`
BranchNameTemplate string `yaml:"branchNameTemplate,omitempty"`
CommitMessageTemplate string `yaml:"commitMessageTemplate,omitempty"`
Expand Down
93 changes: 93 additions & 0 deletions utils/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -820,3 +820,96 @@ func createMockVcsClient(t *testing.T, repoOwner, repoName string) *testdata.Moc
}, nil)
return mockVcsClient
}

func TestGitParams_LfsCheckout(t *testing.T) {
testCases := []struct {
name string
lfsCheckout bool
expectedLfsCheckout bool
}{
{
name: "LFS checkout enabled",
lfsCheckout: true,
expectedLfsCheckout: true,
},
{
name: "LFS checkout disabled",
lfsCheckout: false,
expectedLfsCheckout: false,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
gitParams := &Git{
LfsCheckout: tc.lfsCheckout,
}

assert.Equal(t, tc.expectedLfsCheckout, gitParams.LfsCheckout)
})
}
}

func TestBuildRepoAggregator_LfsCheckout(t *testing.T) {
SetEnvAndAssert(t, map[string]string{
JFrogUrlEnv: "http://127.0.0.1:8081",
JFrogTokenEnv: "token",
GitProvider: string(GitHub),
GitRepoOwnerEnv: "jfrog",
GitRepoEnv: "frogbot",
GitTokenEnv: "123456789",
GitBaseBranchEnv: "main",
})
defer func() {
assert.NoError(t, SanitizeEnv())
}()

server, err := extractJFrogCredentialsFromEnvs()
assert.NoError(t, err)
gitParams, err := extractGitParamsFromEnvs(ScanRepository)
assert.NoError(t, err)

// Test with LfsCheckout = true in config file
configWithLfs := []byte(`
- params:
git:
repoName: test-repo
lfsCheckout: true
branches:
- main
`)

configAggregator, err := BuildRepoAggregator("xrayVersion", "xscVersion", nil, configWithLfs, gitParams, server, ScanRepository)
assert.NoError(t, err)
assert.Len(t, configAggregator, 1)
assert.True(t, configAggregator[0].LfsCheckout, "LfsCheckout should be true when set in config")

// Test with LfsCheckout = false in config file
configWithoutLfs := []byte(`
- params:
git:
repoName: test-repo
lfsCheckout: false
branches:
- main
`)

configAggregator, err = BuildRepoAggregator("xrayVersion", "xscVersion", nil, configWithoutLfs, gitParams, server, ScanRepository)
assert.NoError(t, err)
assert.Len(t, configAggregator, 1)
assert.False(t, configAggregator[0].LfsCheckout, "LfsCheckout should be false when set to false in config")

// Test with no LfsCheckout field in config (should default to false)
configDefault := []byte(`
- params:
git:
repoName: test-repo
branches:
- main
`)

configAggregator, err = BuildRepoAggregator("xrayVersion", "xscVersion", nil, configDefault, gitParams, server, ScanRepository)
assert.NoError(t, err)
assert.Len(t, configAggregator, 1)
assert.False(t, configAggregator[0].LfsCheckout, "LfsCheckout should default to false when not specified")
}