Skip to content

Commit

Permalink
Applying auto-install modifications on a new 'fix' branch + restricti…
Browse files Browse the repository at this point in the history
…ng Frogbot's auto-install feature for Yarn (#565)
  • Loading branch information
eranturgeman authored Nov 19, 2023
1 parent 82d8753 commit c82f292
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 11 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ require (
gopkg.in/warnings.v0 v0.1.2 // indirect
)

replace github.com/jfrog/jfrog-cli-core/v2 => github.com/omerzi/jfrog-cli-core/v2 v2.15.3-0.20231119103345-2409fe7982be
replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20231119153717-1e3374cc5eb2

// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev
replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20231119150101-5cfbe8fca39e

// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go dev
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -874,14 +874,16 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jedib0t/go-pretty/v6 v6.4.8 h1:HiNzyMSEpsBaduKhmK+CwcpulEeBrTmxutz4oX/oWkg=
github.com/jedib0t/go-pretty/v6 v6.4.8/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
github.com/jfrog/build-info-go v1.9.15 h1:DN7DKZq6H5FlHfL3Lu8fo4t2INgczRgT09dJiZjJ1oo=
github.com/jfrog/build-info-go v1.9.15/go.mod h1:XVFk2rCYhIdc7+hIGE8TC3le5PPM+xYHU22udoE2b7Q=
github.com/jfrog/build-info-go v1.8.9-0.20231119150101-5cfbe8fca39e h1:yhy4z08QtckwUfVs0W931wjYUif/Gfv46QazrgHqQrE=
github.com/jfrog/build-info-go v1.8.9-0.20231119150101-5cfbe8fca39e/go.mod h1:XVFk2rCYhIdc7+hIGE8TC3le5PPM+xYHU22udoE2b7Q=
github.com/jfrog/froggit-go v1.14.2 h1:55x1anQtaiARlSBMVT59aFU6Mmx90tpcvvAuuPsZm9c=
github.com/jfrog/froggit-go v1.14.2/go.mod h1:0jRAaZZusaFFnITosmx6CA60SKryuoaCasJyUrP/c1s=
github.com/jfrog/gofrog v1.3.1 h1:QqAwQXCVReT724uga1AYqG/ZyrNQ6f+iTxmzkb+YFQk=
github.com/jfrog/gofrog v1.3.1/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0=
github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY=
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20231119153717-1e3374cc5eb2 h1:H7LO39Pn7TPT3tBDXv0oTQcAOIgX7yLBwDkwIYgj2y4=
github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20231119153717-1e3374cc5eb2/go.mod h1:+jzmxaxiiJgzascARg5Ioi4o3pfFfewk8rE5Pbo8u9Q=
github.com/jfrog/jfrog-client-go v1.34.5 h1:NYZrOHvT5D5BwwHdArIz5WnbP+DPbADjV/SPdN33bfQ=
github.com/jfrog/jfrog-client-go v1.34.5/go.mod h1:0PVhP6xGvBBaUzOU9LKf5OYkke/gY2IFILHA++iabFM=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
Expand Down Expand Up @@ -959,8 +961,6 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/omerzi/jfrog-cli-core/v2 v2.15.3-0.20231119103345-2409fe7982be h1:990HYOLME3D5NvUM0r3ig4nGxHW/nxE4x5hNzplgfxc=
github.com/omerzi/jfrog-cli-core/v2 v2.15.3-0.20231119103345-2409fe7982be/go.mod h1:Le0qPGC9aQ09O+foL+vOG6lJP+fy1C/5yfxL7XzjYpg=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U=
github.com/owenrumney/go-sarif/v2 v2.3.0 h1:wP5yEpI53zr0v5cBmagXzLbHZp9Oylyo3AJDpfLBITs=
Expand Down
40 changes: 36 additions & 4 deletions scanrepository/scanrepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,25 @@ func (cfp *ScanRepositoryCmd) fixSinglePackageAndCreatePR(vulnDetails *utils.Vul
log.Info(fmt.Sprintf("A pull request updating the dependency '%s' to version '%s' already exists. Skipping...", vulnDetails.ImpactedDependencyName, vulnDetails.SuggestedFixedVersion))
return
}
if err = cfp.gitManager.CreateBranchAndCheckout(fixBranchName); err != nil {
return fmt.Errorf("failed while creating new branch: \n%s", err.Error())

workTreeIsClean, err := cfp.gitManager.IsClean()
if !workTreeIsClean {
var removeTempDirCallback func() error
err, removeTempDirCallback = cfp.gitManager.CreateBranchAndCheckoutWithCopyingFilesDiff(fixBranchName)
defer func() {
err = errors.Join(err, removeTempDirCallback())
}()
if err != nil {
err = fmt.Errorf("failed while creating branch %s: %s", fixBranchName, err.Error())
return
}
} else {
if err = cfp.gitManager.CreateBranchAndCheckout(fixBranchName); err != nil {
err = fmt.Errorf("failed while creating branch %s: %s", fixBranchName, err.Error())
return
}
}

if err = cfp.updatePackageToFixedVersion(vulnDetails); err != nil {
return
}
Expand Down Expand Up @@ -515,9 +531,25 @@ func (cfp *ScanRepositoryCmd) getOpenPullRequestBySourceBranch(branchName string
func (cfp *ScanRepositoryCmd) aggregateFixAndOpenPullRequest(vulnerabilitiesMap map[string]map[string]*utils.VulnerabilityDetails, aggregatedFixBranchName string, existingPullRequestInfo *vcsclient.PullRequestInfo) (err error) {
log.Info("-----------------------------------------------------------------")
log.Info("Starting aggregated dependencies fix")
if err = cfp.gitManager.CreateBranchAndCheckout(aggregatedFixBranchName); err != nil {
return

workTreeIsClean, err := cfp.gitManager.IsClean()
if !workTreeIsClean {
var removeTempDirCallback func() error
err, removeTempDirCallback = cfp.gitManager.CreateBranchAndCheckoutWithCopyingFilesDiff(aggregatedFixBranchName)
defer func() {
err = errors.Join(err, removeTempDirCallback())
}()
if err != nil {
err = fmt.Errorf("failed while creating branch %s: %s", aggregatedFixBranchName, err.Error())
return
}
} else {
if err = cfp.gitManager.CreateBranchAndCheckout(aggregatedFixBranchName); err != nil {
err = fmt.Errorf("failed while creating branch %s: %s", aggregatedFixBranchName, err.Error())
return
}
}

// Fix all packages in the same branch if expected error accrued, log and continue.
var fixedVulnerabilities []*utils.VulnerabilityDetails
for fullPath, vulnerabilities := range vulnerabilitiesMap {
Expand Down
24 changes: 24 additions & 0 deletions utils/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,30 @@ func (gm *GitManager) createBranchAndCheckout(branchName string, create bool) er
return worktree.Checkout(checkoutConfig)
}

// Initiates a new branch and switches to it.
// To carry over modifications from the current branch to the new one, we copy all FILES from the current working directory to a temporary directory.
// Before switching to the new branch, we transfer the missing files from the temporary directory to the working directory associated with the new branch.
// Note: Only FILES are copied, avoiding directory and configurations overrides (such as .git configurations).
func (gm *GitManager) CreateBranchAndCheckoutWithCopyingFilesDiff(branchName string) (error, func() error) {
tempDirPath, err := CopyCurrentDirFilesToTempDir()
if err != nil {
return err, func() error { return nil }
}

removeDirCallback := func() error {
return fileutils.RemoveTempDir(tempDirPath)
}

if err = gm.CreateBranchAndCheckout(branchName); err != nil {
return err, removeDirCallback
}

// Copying all the files from the existing working directory to the new branch
// avoids the need for reinstalling the project in case it was previously installed.
err = CopyMissingFilesToCurrentWorkingDir(tempDirPath)
return err, removeDirCallback
}

func getCurrentBranch(repository *git.Repository) (string, error) {
head, err := repository.Head()
if err != nil {
Expand Down
32 changes: 32 additions & 0 deletions utils/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import (
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing/object"
bitests "github.com/jfrog/build-info-go/tests"
"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/jfrog/jfrog-client-go/utils/tests"
"github.com/stretchr/testify/assert"
"os"
"path/filepath"
"testing"
)

Expand Down Expand Up @@ -348,3 +350,33 @@ func TestGetAggregatedPullRequestTitle(t *testing.T) {
})
}
}

func TestCreateBranchAndCheckoutWithCopyingFilesDiff(t *testing.T) {
curWd, err := os.Getwd()
assert.NoError(t, err)
tempDirPath, createTempDirCallback := bitests.CreateTempDirWithCallbackAndAssert(t)
assert.NoError(t, os.Chdir(tempDirPath))
defer func() {
assert.NoError(t, os.Chdir(curWd))
}()

gitManager := createFakeDotGit(t, tempDirPath)
// Generating a new file that will result in an unclean working tree.
newFile, err := os.Create("new-file.txt")
assert.NoError(t, err)

var removeDirCallback func() error
err, removeDirCallback = gitManager.CreateBranchAndCheckoutWithCopyingFilesDiff("new-branch")
assert.NoError(t, err)
defer func() {
assert.NoError(t, newFile.Close())
assert.NoError(t, removeDirCallback())
createTempDirCallback()
}()

// Confirm that the new files exist in the new branch
var fileExists bool
fileExists, err = fileutils.IsFileExists(filepath.Join(tempDirPath, newFile.Name()), false)
assert.NoError(t, err)
assert.True(t, fileExists)
}
2 changes: 1 addition & 1 deletion utils/scandetails.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func (sc *ScanDetails) RunInstallAndAudit(workDirs ...string) (auditResults *xra

func (sc *ScanDetails) runInstallIfNeeded(workDir string) (err error) {
// A temporary barrier until all the 'install' logic is relocated from frogbot, at which point this code will become obsolete
if sc.InstallCommandName == "npm" {
if sc.InstallCommandName == "npm" || sc.InstallCommandName == "yarn" {
return nil
}

Expand Down
50 changes: 50 additions & 0 deletions utils/scanrepository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package utils

import (
"fmt"
biutils "github.com/jfrog/build-info-go/utils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"os"
"path/filepath"
)

// Generates a temporary directory and duplicates the current working directory files into it. Provides the complete path for the temporary directory.
func CopyCurrentDirFilesToTempDir() (tempDirPath string, err error) {
var wd string
tempDirPath, err = fileutils.CreateTempDir()
if err != nil {
err = fmt.Errorf("couldn't create a temp dir: %s", err.Error())
return
}

wd, err = os.Getwd()
if err != nil {
return
}
// If modifications have been made in the current working directory since it was cloned, we retain a duplicate of its files before initiating a new branch from the initially cloned directory.
err = biutils.CopyDir(wd, tempDirPath, false, nil)
return
}

// Duplicates all files from sourceDirPath into the present working directory, omitting any files that already exist.
func CopyMissingFilesToCurrentWorkingDir(sourceDirPath string) (err error) {
var wd string
wd, err = os.Getwd()
if err != nil {
return
}

var alreadyExistingFiles []string
alreadyExistingFiles, err = fileutils.ListFiles(wd, false)
if err != nil {
err = fmt.Errorf("couldn't get a list of files in current working directory '%s': %s", wd, err.Error())
return
}
// We need only the filename, not its complete path, to omit it from the duplication process
for idx, fileFullPath := range alreadyExistingFiles {
alreadyExistingFiles[idx] = filepath.Base(fileFullPath)
}

err = biutils.CopyDir(sourceDirPath, wd, false, alreadyExistingFiles)
return
}

0 comments on commit c82f292

Please sign in to comment.