Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
JFrog Pipelines Step committed May 26, 2023
2 parents 68159dc + aa1fdf7 commit e263a73
Show file tree
Hide file tree
Showing 28 changed files with 853 additions and 340 deletions.
180 changes: 112 additions & 68 deletions commands/createfixpullrequests.go

Large diffs are not rendered by default.

130 changes: 14 additions & 116 deletions commands/createfixpullrequests_test.go
Original file line number Diff line number Diff line change
@@ -1,72 +1,18 @@
package commands

import (
testdatautils "github.com/jfrog/build-info-go/build/testdata"
"github.com/jfrog/frogbot/commands/utils/packagehandlers"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/stretchr/testify/assert"
"os"
"path/filepath"
"regexp"
"strings"
"testing"

"github.com/jfrog/frogbot/commands/utils"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-client-go/xray/services"
)

type FixPackagesTestFunc func(test packageFixTest) CreateFixPullRequestsCmd

type packageFixTest struct {
technology coreutils.Technology
impactedPackaged string
fixVersion string
packageDescriptor string
testPath string
shouldNotFix bool
fixPackageVersionCmd FixPackagesTestFunc
}

var packageFixTests = []packageFixTest{
{technology: coreutils.Npm, impactedPackaged: "minimatch", fixVersion: "3.0.2", packageDescriptor: "package.json", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Go, impactedPackaged: "github.com/google/uuid", fixVersion: "1.3.0", packageDescriptor: "go.mod", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Go, impactedPackaged: "github.com/golang/go", fixVersion: "1.20.3", packageDescriptor: "go.mod", fixPackageVersionCmd: getGenericFixPackageVersionFunc(), shouldNotFix: true},
{technology: coreutils.Yarn, impactedPackaged: "minimist", fixVersion: "1.2.6", packageDescriptor: "package.json", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Pipenv, impactedPackaged: "pyjwt", fixVersion: "2.4.0", packageDescriptor: "Pipfile", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Pipenv, impactedPackaged: "Pyjwt", fixVersion: "2.4.0", packageDescriptor: "Pipfile", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Poetry, impactedPackaged: "pyjwt", fixVersion: "2.4.0", packageDescriptor: "pyproject.toml", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Poetry, impactedPackaged: "Pyjwt", fixVersion: "2.4.0", packageDescriptor: "pyproject.toml", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Pip, impactedPackaged: "pyjwt", fixVersion: "2.4.0", packageDescriptor: "requirements.txt", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Pip, impactedPackaged: "PyJwt", fixVersion: "2.4.0", packageDescriptor: "requirements.txt", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Pip, impactedPackaged: "pyjwt", fixVersion: "2.4.0", packageDescriptor: "setup.py", fixPackageVersionCmd: getGenericFixPackageVersionFunc()},
{technology: coreutils.Pip, impactedPackaged: "pip", fixVersion: "23.1", packageDescriptor: "setup.py", fixPackageVersionCmd: getGenericFixPackageVersionFunc(), shouldNotFix: true},
{technology: coreutils.Pip, impactedPackaged: "wheel", fixVersion: "2.3.0", packageDescriptor: "setup.py", fixPackageVersionCmd: getGenericFixPackageVersionFunc(), shouldNotFix: true},
{technology: coreutils.Pip, impactedPackaged: "setuptools", fixVersion: "66.6.6", packageDescriptor: "setup.py", fixPackageVersionCmd: getGenericFixPackageVersionFunc(), shouldNotFix: true},
}

var requirementsFile = "oslo.config>=1.12.1,<1.13\noslo.utils<5.0,>=4.0.0\nparamiko==2.7.2\npasslib<=1.7.4\nprance>=0.9.0\nprompt-toolkit~=1.0.15\npyinotify>0.9.6\nPyJWT>1.7.1\nurllib3 > 1.1.9, < 1.5.*"

type pipPackageRegexTest struct {
packageName string
expectedRequirement string
}

var pipPackagesRegexTests = []pipPackageRegexTest{
{"oslo.config", "oslo.config>=1.12.1,<1.13"},
{"oslo.utils", "oslo.utils<5.0,>=4.0.0"},
{"paramiko", "paramiko==2.7.2"},
{"passlib", "passlib<=1.7.4"},
{"PassLib", "passlib<=1.7.4"},
{"prance", "prance>=0.9.0"},
{"prompt-toolkit", "prompt-toolkit~=1.0.15"},
{"pyinotify", "pyinotify>0.9.6"},
{"pyjwt", "pyjwt>1.7.1"},
{"PyJWT", "pyjwt>1.7.1"},
{"urllib3", "urllib3 > 1.1.9, < 1.5.*"},
}

var testPackagesData = []struct {
packageType coreutils.Technology
commandName string
Expand Down Expand Up @@ -107,60 +53,6 @@ var testPackagesData = []struct {
},
}

func getGenericFixPackageVersionFunc() FixPackagesTestFunc {
return func(test packageFixTest) CreateFixPullRequestsCmd {
return CreateFixPullRequestsCmd{
details: &utils.ScanDetails{
Project: &utils.Project{
PipRequirementsFile: test.packageDescriptor,
WorkingDirs: []string{test.testPath},
},
},
}
}
}

func TestGenericFixPackageVersion(t *testing.T) {
currentDir, testdataDir := getTestDataDir(t)
defer func() {
assert.NoError(t, os.Chdir(currentDir))
}()

for _, test := range packageFixTests {
func() {
// Create a temp technology project
projectPath := filepath.Join(testdataDir, test.technology.ToString())
tmpProjectPath, cleanup := testdatautils.CreateTestProject(t, projectPath)
defer cleanup()
test.testPath = tmpProjectPath
assert.NoError(t, os.Chdir(tmpProjectPath))

t.Run(test.technology.ToString(), func(t *testing.T) {
cfg := test.fixPackageVersionCmd(test)
// Fix impacted package for each technology
fixVersionInfo := utils.NewFixVersionInfo(test.fixVersion, test.technology, true)
assert.NoError(t, cfg.updatePackageToFixedVersion(test.impactedPackaged, fixVersionInfo))
file, err := os.ReadFile(test.packageDescriptor)
assert.NoError(t, err)
if test.shouldNotFix {
assert.NotContains(t, string(file), test.fixVersion)
} else {
assert.Contains(t, string(file), test.fixVersion)
// Verify that case-sensitive packages in python are lowered
assert.Contains(t, string(file), strings.ToLower(test.impactedPackaged))
}
})
}()
}
}
func getTestDataDir(t *testing.T) (string, string) {
currentDir, err := os.Getwd()
assert.NoError(t, err)
testdataDir, err := filepath.Abs("testdata/projects")
assert.NoError(t, err)
return currentDir, testdataDir
}

// / 1.0 --> 1.0 ≤ x
// / (,1.0] --> x ≤ 1.0
// / (,1.0) --> x < 1.0
Expand Down Expand Up @@ -211,14 +103,6 @@ func TestGenerateFixBranchName(t *testing.T) {
}
}

func TestPipPackageRegex(t *testing.T) {
for _, pack := range pipPackagesRegexTests {
re := regexp.MustCompile(packagehandlers.PythonPackageRegexPrefix + "(" + pack.packageName + "|" + strings.ToLower(pack.packageName) + ")" + packagehandlers.PythonPackageRegexSuffix)
found := re.FindString(requirementsFile)
assert.Equal(t, pack.expectedRequirement, strings.ToLower(found))
}
}

func TestPackageTypeFromScan(t *testing.T) {
environmentVars, restoreEnv := verifyEnv(t)
defer restoreEnv()
Expand Down Expand Up @@ -285,6 +169,20 @@ func TestGetMinimalFixVersion(t *testing.T) {
}
}

// Verifies unsupported packages return specific error
// Other logic is implemented inside each package-handler.
func TestUpdatePackageToFixedVersion(t *testing.T) {
var testScan CreateFixPullRequestsCmd
for tech, buildToolsDependencies := range utils.BuildToolsDependenciesMap {
for _, impactedDependency := range buildToolsDependencies {
fixDetails := &utils.FixDetails{FixVersion: "3.3.3", PackageType: tech, ImpactedDependency: impactedDependency, DirectDependency: true}
err := testScan.updatePackageToFixedVersion(fixDetails)
assert.Error(t, err, "Expected error to occur")
assert.IsType(t, &utils.ErrUnsupportedFix{}, err, "Expected unsupported fix error")
}
}
}

func verifyTechnologyNaming(t *testing.T, scanResponse []services.ScanResponse, expectedType coreutils.Technology) {
for _, resp := range scanResponse {
for _, vulnerability := range resp.Vulnerabilities {
Expand Down
18 changes: 10 additions & 8 deletions commands/scanandfixrepos.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@ type ScanAndFixRepositories struct {
func (saf *ScanAndFixRepositories) Run(configAggregator utils.FrogbotConfigAggregator, client vcsclient.VcsClient) error {
var errList strings.Builder
for repoNum := range configAggregator {
err := saf.scanAndFixSingleRepository(&configAggregator[repoNum], client)
if err != nil {
if err := saf.scanAndFixSingleRepository(&configAggregator[repoNum], client); err != nil {
errList.WriteString(fmt.Sprintf("repository %s returned the following error: \n%s\n", configAggregator[repoNum].RepoName, err.Error()))
}
}

if errList.String() != "" {
return errors.New(errList.String())
}
Expand All @@ -45,13 +43,17 @@ func (saf *ScanAndFixRepositories) scanAndFixSingleRepository(repoConfig *utils.
continue
}
if err = saf.downloadAndRunScanAndFix(repoConfig, branch, client); err != nil {
// Scan failed, mark commit status failed with error info
e := saf.setCommitBuildStatus(client, repoConfig, vcsclient.Fail, checkedCommit, fmt.Sprintf("Frogbot error: %s", err))
if e != nil {
return errors.New(err.Error() + "\n" + e.Error())
if _, isCustomError := err.(*utils.ErrUnsupportedFix); isCustomError {
log.Debug(err.Error())
} else {
// Scan failed, mark commit status failed with error info
if e := saf.setCommitBuildStatus(client, repoConfig, vcsclient.Fail, checkedCommit, fmt.Sprintf("Frogbot error: %s", err)); e != nil {
return errors.Join(e, err)
}
return err
}
return err
}
// Mark successful run
if err = saf.setCommitBuildStatus(client, repoConfig, vcsclient.Pass, checkedCommit, utils.CommitStatusDescription); err != nil {
return err
}
Expand Down
22 changes: 22 additions & 0 deletions commands/testdata/indirect-projects/go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module goproject

go 1.19

require github.com/gin-gonic/gin v1.7.3

require (
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.13.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/go-playground/validator/v10 v10.4.1 // indirect
github.com/golang/protobuf v1.3.3 // indirect
github.com/json-iterator/go v1.1.9 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect
gopkg.in/yaml.v2 v2.2.8 // indirect
)
10 changes: 10 additions & 0 deletions commands/testdata/indirect-projects/go/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

import (
"github.com/gin-gonic/gin"
)

func main() {
print("test")
_ = gin.Default()
}
67 changes: 67 additions & 0 deletions commands/testdata/indirect-projects/maven/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jfrog.test</groupId>
<artifactId>multi</artifactId>
<version>3.7-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Simple Multi Modules Build</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
1 change: 1 addition & 0 deletions commands/testdata/indirect-projects/pip/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requests==2.21.0
9 changes: 9 additions & 0 deletions commands/testdata/indirect-projects/pip/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from setuptools import setup, find_packages

setup(
name="pip-example",
version="1.2.3",
install_requires=[
"requests==2.21.0"
],
)
12 changes: 12 additions & 0 deletions commands/testdata/indirect-projects/pipenv/Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"

[packages]
requests = "==2.21.0"

[dev-packages]

[requires]
python_version = "*"
59 changes: 59 additions & 0 deletions commands/testdata/indirect-projects/pipenv/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e263a73

Please sign in to comment.