Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
555d703
Remove frogbot-config.yml functionality - use only environment variables
eyalk007 Nov 3, 2025
8ef541e
Remove all config yml file support and references
eyalk007 Nov 20, 2025
59e943f
Merge remote-tracking branch 'upstream/v3_er' into remove-config-yaml
eyalk007 Nov 25, 2025
5fd7179
Remove deprecated schema and jfrog-pipelines templates
eyalk007 Nov 25, 2025
dc45007
Remove redundant config YAML tests
eyalk007 Nov 26, 2025
d9605e1
Fix scanpullrequest test: add missing RepoName field
eyalk007 Nov 26, 2025
d6c1262
Fix failing multi-dir and no-fail tests by setting env vars
eyalk007 Nov 26, 2025
cc83c2b
deleted GitEmailAuthorEnv
kerenr-jfrog Nov 26, 2025
6f082f6
Cr fixes
eyalk007 Nov 30, 2025
be82aaf
removed: JF_USE_CONFIG_PROFILE, JF_CONFIG_PROFILE, JF_AVOID_PREVIOUS_…
kerenr-jfrog Nov 30, 2025
f6fce1b
fixed tests
kerenr-jfrog Nov 30, 2025
b8459bc
fixed outputcontent_test.go
kerenr-jfrog Dec 1, 2025
93f5d9a
Fix aggregate-multi-project test expectations
eyalk007 Dec 1, 2025
61fc295
Fix aggregate-multi-project test branch name
eyalk007 Dec 1, 2025
29999e3
Fix scanpullrequest field access patterns to use nested Params structure
eyalk007 Dec 1, 2025
e487989
Complete field access pattern fixes for scanrepository.go
eyalk007 Dec 1, 2025
da2f644
Update expected test response for new vulnerability ordering
eyalk007 Dec 1, 2025
94bff22
fixed params_test.go
kerenr-jfrog Dec 1, 2025
f5aed9a
Merge branch 'remove-config-yaml' into remove-frogbot-general-env-vars
kerenr-jfrog Dec 1, 2025
4f12d6f
Remove obsolete aggregate-multi-project test and fix partial-results-…
eyalk007 Dec 1, 2025
3e5dce7
Fix critical test isolation issues in TestScanRepositoryCmd_Run
eyalk007 Dec 2, 2025
d5bc03a
Fix test isolation by adding environment variable cleanup
eyalk007 Dec 2, 2025
c31b33d
Merge branch 'remove-config-yaml' into remove-frogbot-general-env-vars
kerenr-jfrog Dec 2, 2025
cdff937
removed JF_PR_COMMENT_TITLE
kerenr-jfrog Dec 2, 2025
0f41317
fix params_test.go
kerenr-jfrog Dec 3, 2025
07547d1
Merge branch 'v3_er' into remove-frogbot-general-env-vars
kerenr-jfrog Dec 7, 2025
6083d9b
removed JF_FAIL & JF_INCLUDE_ALL_VULNERABILITIES
kerenr-jfrog Dec 8, 2025
668ad3a
Merge branch 'v3_er' into remove-frogbot-general-env-vars
kerenr-jfrog Dec 8, 2025
6394da6
fix pr comments - scanpullrequest_test.go, outputcontent_test.go and …
kerenr-jfrog Dec 8, 2025
69cfd44
fix scan pull request test
kerenr-jfrog Dec 8, 2025
30029d2
fix scan pull request multi dir test
kerenr-jfrog Dec 8, 2025
359d699
fix linter errors
kerenr-jfrog Dec 8, 2025
9dd400b
fixed tests
kerenr-jfrog Dec 9, 2025
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
15 changes: 8 additions & 7 deletions integrationutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ package main
import (
"context"
"fmt"
"os"
"strconv"
"strings"
"testing"
"time"

"github.com/go-git/go-git/v5"
githttp "github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/jfrog/frogbot/v2/scanpullrequest"
Expand All @@ -13,11 +19,6 @@ import (
"github.com/jfrog/froggit-go/vcsutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"strconv"
"strings"
"testing"
"time"
)

const (
Expand Down Expand Up @@ -171,8 +172,8 @@ func runScanPullRequestCmd(t *testing.T, client vcsclient.VcsClient, testDetails
defer unsetEnvs()

err = Exec(&scanpullrequest.ScanPullRequestCmd{}, utils.ScanPullRequest)
// Validate that issues were found and the relevant error returned
require.Errorf(t, err, scanpullrequest.SecurityIssueFoundErr)
// Validate that no error is returned
require.NoError(t, err)

validateResults(t, ctx, client, testDetails, prId)
}
Expand Down
39 changes: 11 additions & 28 deletions scanpullrequest/scanpullrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ import (

const (
SecurityIssueFoundErr = "issues were detected by Frogbot\n" +
"You can avoid marking the Frogbot scan as failed by setting the " + utils.FailOnSecurityIssuesEnv + " environment variable to false\n" +
"Note that even if " + utils.FailOnSecurityIssuesEnv + " is set to false, but a security violation with 'fail-pull-request' rule is found, Frogbot scan will fail as well"
"Security violation with 'fail-pull-request' rule is found"
noGitHubEnvErr = "frogbot did not scan this PR, because a GitHub Environment named 'frogbot' does not exist. Please refer to the Frogbot documentation for instructions on how to create the Environment"
noGitHubEnvReviewersErr = "frogbot did not scan this PR, because the existing GitHub Environment named 'frogbot' doesn't have reviewers selected. Please refer to the Frogbot documentation for instructions on how to create the Environment"
analyticsScanPrScanType = "PR"
Expand Down Expand Up @@ -81,7 +80,7 @@ func verifyGitHubFrogbotEnvironment(client vcsclient.VcsClient, repoConfig *util
return nil
}

// By default, includeAllVulnerabilities is set to false and the scan goes as follows:
// By default, the scan goes as follows:
// a. Audit the dependencies of the source and the target branches.
// b. Compare the vulnerabilities found in source and target branches, and show only the new vulnerabilities added by the pull request.
// Otherwise, only the source branch is scanned and all found vulnerabilities are being displayed.
Expand All @@ -104,25 +103,14 @@ func scanPullRequest(repo *utils.Repository, client vcsclient.VcsClient) (err er
return
}

// Fail the Frogbot task if a security issue is found and Frogbot isn't configured to avoid the failure.
if toFailTaskStatus(repo, issues) {
// Fail the Frogbot task if a security violation is found and fail pr rule applied.
if issues.IsFailPrRuleApplied() {
err = errors.New(SecurityIssueFoundErr)
return
}
return
}

func toFailTaskStatus(repo *utils.Repository, issues *issues.ScansIssuesCollection) bool {
failFlagSet := repo.Params.Scan.FailOnSecurityIssues != nil && *repo.Params.Scan.FailOnSecurityIssues
if failFlagSet {
// If the fail flag is set to true (JF_FAIL), we check if any security ISSUE exists (not just violations), and if so, we fail the build.
return issues.IssuesExists(repo.Params.Git.PullRequestSecretComments)
} else {
// When fail flag is set to false, we check for fail-pr rule in existing VIOLATIONS. If one exists, we fail the build as well.
return issues.IsFailPrRuleApplied()
}
}

func auditPullRequestAndReport(repoConfig *utils.Repository, client vcsclient.VcsClient) (issuesCollection *issues.ScansIssuesCollection, resultContext results.ResultContext, err error) {
// Prepare
scanDetails, err := createBaseScanDetails(repoConfig, client)
Expand Down Expand Up @@ -171,7 +159,6 @@ func createBaseScanDetails(repoConfig *utils.Repository, client vcsclient.VcsCli
SetFixableOnly(repoConfig.Params.Scan.FixableOnly).
SetConfigProfile(repoConfig.Params.Scan.ConfigProfile).
SetSkipAutoInstall(repoConfig.Params.Scan.SkipAutoInstall).
SetDisableJas(repoConfig.Params.Scan.DisableJas).
SetXscPRGitInfoContext(repoConfig.Params.Git.Project, client, repoConfig.Params.Git.PullRequestDetails).
SetDiffScan(!repoConfig.Params.JFrogPlatform.IncludeVulnerabilities).
SetAllowPartialResults(repoConfig.Params.Scan.AllowPartialResults)
Expand Down Expand Up @@ -212,15 +199,13 @@ func auditPullRequestCode(repoConfig *utils.Repository, scanDetails *utils.ScanD
// Reset scan details for each project
scanDetails.SetProject(&repoConfig.Params.Scan.Projects[i]).SetResultsToCompare(nil)
// Scan target branch of the project
if !repoConfig.Params.JFrogPlatform.IncludeVulnerabilities {
log.Debug("Scanning target branch code...")
if targetScanResults, e := auditPullRequestTargetCode(scanDetails, targetBranchWd); e != nil {
issuesCollection.AppendStatus(getResultScanStatues(targetScanResults))
err = errors.Join(err, fmt.Errorf("failed to audit target branch code for %v project. Error: %s", repoConfig.Params.Scan.Projects[i].WorkingDirs, e.Error()))
continue
} else {
scanDetails.SetResultsToCompare(targetScanResults)
}
log.Debug("Scanning target branch code...")
if targetScanResults, e := auditPullRequestTargetCode(scanDetails, targetBranchWd); e != nil {
issuesCollection.AppendStatus(getResultScanStatues(targetScanResults))
err = errors.Join(err, fmt.Errorf("failed to audit target branch code for %v project. Error: %s", repoConfig.Params.Scan.Projects[i].WorkingDirs, e.Error()))
continue
} else {
scanDetails.SetResultsToCompare(targetScanResults)
}
// Scan source branch of the project
log.Debug("Scanning source branch code...")
Expand Down Expand Up @@ -282,7 +267,6 @@ func filterOutFailedScansIfAllowPartialResultsEnabled(targetResults, sourceResul
return nil
}
if targetResults == nil {
// If IncludeAllVulnerabilities is applied, only sourceResults exists and we don't need to filter anything - we present results we have
return nil
}

Expand Down Expand Up @@ -403,7 +387,6 @@ func filterOutScaResultsIfScanFailed(targetResult, sourceResult *results.TargetR
// Sorts the Targets slice in both targetResults and sourceResults
// by the physical location (Target field) of each scan target in ascending order.
func sortTargetsByPhysicalLocation(targetResults, sourceResults *results.SecurityCommandResults) error {
// If !IncludeAllVulnerabilities we expect targetResults and sourceResults to be non-empty and to have the same amount of targets.
if len(targetResults.Targets) != len(sourceResults.Targets) {
return fmt.Errorf("amount of targets in target results is different than source results: %d vs %d", len(targetResults.Targets), len(sourceResults.Targets))
}
Expand Down
139 changes: 23 additions & 116 deletions scanpullrequest/scanpullrequest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,60 +220,49 @@ func TestScanResultsToIssuesCollection(t *testing.T) {

func TestScanPullRequest(t *testing.T) {
tests := []struct {
testName string
projectName string
failOnSecurityIssues bool
testName string
projectName string
}{
{
testName: "ScanPullRequest",
projectName: "test-proj",
failOnSecurityIssues: true,
testName: "ScanPullRequest",
projectName: "test-proj",
},
{
testName: "ScanPullRequestNoFail",
projectName: "test-proj",
failOnSecurityIssues: false,
testName: "ScanPullRequestNoFail",
projectName: "test-proj",
},
{
testName: "ScanPullRequestSubdir",
projectName: "test-proj-subdir",
failOnSecurityIssues: true,
testName: "ScanPullRequestSubdir",
projectName: "test-proj-subdir",
},
{
testName: "ScanPullRequestNoIssues",
projectName: "clean-test-proj",
failOnSecurityIssues: false,
testName: "ScanPullRequestNoIssues",
projectName: "clean-test-proj",
},
{
testName: "ScanPullRequestMultiWorkDir",
projectName: "multi-dir-test-proj",
failOnSecurityIssues: false,
testName: "ScanPullRequestMultiWorkDir",
projectName: "multi-dir-test-proj",
},
{
testName: "ScanPullRequestMultiWorkDirNoFail",
projectName: "multi-dir-test-proj",
failOnSecurityIssues: true,
testName: "ScanPullRequestMultiWorkDirNoFail",
projectName: "multi-dir-test-proj",
},
}
for _, test := range tests {
t.Run(test.testName, func(t *testing.T) {
testScanPullRequest(t, test.projectName, test.failOnSecurityIssues)
testScanPullRequest(t, test.projectName)
})
}
}

func testScanPullRequest(t *testing.T, projectName string, failOnSecurityIssues bool) {
config, client, cleanUp := preparePullRequestTest(t, projectName, failOnSecurityIssues)
func testScanPullRequest(t *testing.T, projectName string) {
config, client, cleanUp := preparePullRequestTest(t, projectName)
defer cleanUp()

// Run "frogbot scan pull request"
var scanPullRequest ScanPullRequestCmd
err := scanPullRequest.Run(config, client, utils.MockHasConnection())
if failOnSecurityIssues {
assert.EqualErrorf(t, err, SecurityIssueFoundErr, "Error should be: %v, got: %v", SecurityIssueFoundErr, err)
} else {
assert.NoError(t, err)
}
assert.NoError(t, err)

// Check env sanitize
err = utils.SanitizeEnv()
Expand Down Expand Up @@ -492,7 +481,7 @@ func TestAuditDiffInPullRequest(t *testing.T) {

for _, test := range tests {
t.Run(test.testName, func(t *testing.T) {
repoConfig, client, cleanUpTest := preparePullRequestTest(t, test.projectName, false)
repoConfig, client, cleanUpTest := preparePullRequestTest(t, test.projectName)
defer cleanUpTest()

issuesCollection, _, err := auditPullRequestAndReport(&repoConfig, client)
Expand All @@ -514,7 +503,7 @@ func TestToFailTaskStatus(t *testing.T) {
failureExpected bool
}{
{
name: "fail flag set to false and no violations with fail_pr",
name: "no violations with fail_pr",
setFailFlag: false,
issuesCollection: issues.ScansIssuesCollection{
LicensesViolations: []formats.LicenseViolationRow{{
Expand All @@ -541,74 +530,7 @@ func TestToFailTaskStatus(t *testing.T) {
failureExpected: false,
},
{
name: "fail flag set to true, sca vulnerability",
setFailFlag: true,
issuesCollection: issues.ScansIssuesCollection{
ScaVulnerabilities: []formats.VulnerabilityOrViolationRow{
{
ImpactedDependencyDetails: formats.ImpactedDependencyDetails{
ImpactedDependencyName: "impacted-name",
ImpactedDependencyVersion: "1.0.0",
SeverityDetails: formats.SeverityDetails{Severity: "High"},
Components: []formats.ComponentRow{
{
Name: "vuln-pack-name1",
Version: "1.0.0",
},
{
Name: "vuln-pack-name1",
Version: "1.2.3",
},
{
Name: "vuln-pack-name2",
Version: "1.2.3",
},
},
},
Cves: []formats.CveRow{{
Id: "CVE-2021-1234",
Applicability: &formats.Applicability{
Status: "Applicable",
ScannerDescription: "scanner",
Evidence: []formats.Evidence{
{Reason: "reason", Location: formats.Location{File: "file1", StartLine: 1, StartColumn: 2, EndLine: 3, EndColumn: 4, Snippet: "snippet1"}},
{Reason: "other reason", Location: formats.Location{File: "file2", StartLine: 5, StartColumn: 6, EndLine: 7, EndColumn: 8, Snippet: "snippet2"}},
},
},
}},
JfrogResearchInformation: &formats.JfrogResearchInformation{
Remediation: "remediation",
},
Summary: "summary",
Applicable: "Applicable",
IssueId: "Xray-Id",
},
{
ImpactedDependencyDetails: formats.ImpactedDependencyDetails{
ImpactedDependencyName: "impacted-name2",
ImpactedDependencyVersion: "1.0.0",
SeverityDetails: formats.SeverityDetails{Severity: "Low"},
Components: []formats.ComponentRow{
{
Name: "vuln-pack-name3",
Version: "1.0.0",
},
},
},
Cves: []formats.CveRow{{
Id: "CVE-1111-2222",
Applicability: &formats.Applicability{Status: "Not Applicable"},
}},
Summary: "other summary",
Applicable: "Not Applicable",
IssueId: "Xray-Id2",
},
},
},
failureExpected: true,
},
{
name: "fail flag is set to false, fail_pr in licenses violation",
name: "fail_pr in licenses violation",
setFailFlag: false,
issuesCollection: issues.ScansIssuesCollection{
LicensesViolations: []formats.LicenseViolationRow{{
Expand Down Expand Up @@ -638,19 +560,7 @@ func TestToFailTaskStatus(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
failFlag := test.setFailFlag
repo := &utils.Repository{
Params: utils.Params{
Scan: utils.Scan{
FailOnSecurityIssues: &failFlag,
},
Git: utils.Git{
PullRequestSecretComments: false,
},
},
}

assert.Equal(t, test.failureExpected, toFailTaskStatus(repo, &test.issuesCollection))
assert.Equal(t, test.failureExpected, test.issuesCollection.IsFailPrRuleApplied())
})
}
}
Expand Down Expand Up @@ -1138,14 +1048,11 @@ func TestFilterOutFailedScansIfAllowPartialResultsEnabled(t *testing.T) {
}
}

func preparePullRequestTest(t *testing.T, projectName string, failOnSecurityIssues bool) (utils.Repository, vcsclient.VcsClient, func()) {
func preparePullRequestTest(t *testing.T, projectName string) (utils.Repository, vcsclient.VcsClient, func()) {
params, restoreEnv := utils.VerifyEnv(t)

// Set test-specific environment variables
envVars := map[string]string{}
if !failOnSecurityIssues {
envVars[utils.FailOnSecurityIssuesEnv] = "false"
}

// Set working directories for multi-dir tests
if projectName == "multi-dir-test-proj" {
Expand Down
3 changes: 1 addition & 2 deletions scanrepository/scanrepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ func (cfp *ScanRepositoryCmd) setCommandPrerequisites(repository *utils.Reposito
SetFixableOnly(repository.Params.Scan.FixableOnly).
SetConfigProfile(repository.Params.Scan.ConfigProfile).
SetSkipAutoInstall(repository.Params.Scan.SkipAutoInstall).
SetAllowPartialResults(repository.Params.Scan.AllowPartialResults).
SetDisableJas(repository.Params.Scan.DisableJas)
SetAllowPartialResults(repository.Params.Scan.AllowPartialResults)

if cfp.scanDetails, err = cfp.scanDetails.SetMinSeverity(repository.Params.Scan.MinSeverity); err != nil {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
some content
```


---
<div align='center'>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
some content
```


---
<div align='center'>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@
some content
```


---
[🐸 JFrog Frogbot](https://jfrog.com/help/r/jfrog-security-user-guide/shift-left-on-security/frogbot)
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
some content
```


---
<div align='center'>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
some content
```


---
<div align='center'>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
some content
```


---
<div align='center'>

Expand Down
Loading
Loading