Skip to content

Commit b55c703

Browse files
Jordanh1996claude
andcommitted
Gate the violation link on the minimum Xray version (XRAY-155957)
The violation permalink endpoint shipped in Xray 3.150.4 / 3.151.0 (XRAY-147005). Without a gate, Frogbot would print a link that 404s on older Xray versions. GetViolationUiLinkBaseUrl returns an empty string below the minimum, which the renderer already treats as "no link". The endpoint was also backported to 3.143.31, but a single minimum cannot cover that line without wrongly admitting 3.144-3.150.3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent e205505 commit b55c703

4 files changed

Lines changed: 38 additions & 19 deletions

File tree

scanpullrequest/scanpullrequest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func (pr *ScanPullRequestCmd) Run(repository utils.Repository, client vcsclient.
5757
return
5858
}
5959
if pullRequestIssues.IsFailPrRuleApplied() {
60-
issues.LogFailingPolicyRulesForPr(pullRequestIssues.Violations, utils.GetPlatformUrl(&repository.Server))
60+
issues.LogFailingPolicyRulesForPr(pullRequestIssues.Violations, utils.GetViolationUiLinkBaseUrl(&repository.Server, repository.Params.JFrogPlatform.XrayVersion))
6161
err = errors.New(SecurityIssueFoundErr)
6262
return
6363
}

scanrepository/scanrepository.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func (sr *ScanRepositoryCmd) scanAndFixBranch(repository *utils.Repository) (tot
160160
defer func() {
161161
// Always check policy even if an error occurred during the scan
162162
if policyErr := policy.CheckPolicyFailBuildError(scanResults); policyErr != nil {
163-
issues.LogFailingPolicyRulesForBuild(scanResults.Violations, utils.GetPlatformUrl(&repository.Server))
163+
issues.LogFailingPolicyRulesForBuild(scanResults.Violations, utils.GetViolationUiLinkBaseUrl(&repository.Server, repository.Params.JFrogPlatform.XrayVersion))
164164
err = errors.Join(err, policyErr)
165165
}
166166
}()

utils/getconfiguration.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ import (
2323
"github.com/jfrog/jfrog-client-go/utils/log"
2424
)
2525

26-
const configProfileV3MinXrayVersion = "3.117.0" // TODO switch to real the Xray version when available
26+
const (
27+
configProfileV3MinXrayVersion = "3.117.0" // TODO switch to real the Xray version when available
28+
violationUiLinkMinXrayVersion = "3.150.4"
29+
)
2730

2831
type FrogbotDetails struct {
2932
XrayVersion string
@@ -223,8 +226,14 @@ func extractJFrogCredentialsFromEnvs() (*coreconfig.ServerDetails, error) {
223226
return &server, nil
224227
}
225228

226-
// GetPlatformUrl returns the JFrog platform base URL, deriving it from the Xray URL when only the service URLs are configured.
227-
func GetPlatformUrl(server *coreconfig.ServerDetails) string {
229+
// GetViolationUiLinkBaseUrl returns the platform base URL used to build violation UI links, deriving it from the
230+
// Xray URL when only the service URLs are configured. It returns an empty string on Xray versions that predate the
231+
// violation permalink endpoint, so that no unresolvable link is printed. The endpoint was also released in 3.143.31,
232+
// but a single minimum cannot cover that line without wrongly admitting the 3.144-3.150.3 versions that lack it.
233+
func GetViolationUiLinkBaseUrl(server *coreconfig.ServerDetails, xrayVersion string) string {
234+
if err := clientutils.ValidateMinimumVersion(clientutils.Xray, xrayVersion, violationUiLinkMinXrayVersion); err != nil {
235+
return ""
236+
}
228237
if server.Url != "" {
229238
return strings.TrimSuffix(server.Url, "/")
230239
}

utils/getconfiguration_test.go

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -444,31 +444,41 @@ func createMockVcsClient(t *testing.T, repoOwner, repoName string, withError boo
444444
return mockVcsClient
445445
}
446446

447-
func TestGetPlatformUrl(t *testing.T) {
447+
func TestGetViolationUiLinkBaseUrl(t *testing.T) {
448448
testCases := []struct {
449-
name string
450-
server config.ServerDetails
451-
expected string
449+
name string
450+
server config.ServerDetails
451+
xrayVersion string
452+
expected string
452453
}{
453454
{
454-
name: "Platform url set",
455-
server: config.ServerDetails{Url: "https://acme.jfrog.io/"},
456-
expected: "https://acme.jfrog.io",
455+
name: "Platform url set",
456+
server: config.ServerDetails{Url: "https://acme.jfrog.io/"},
457+
xrayVersion: violationUiLinkMinXrayVersion,
458+
expected: "https://acme.jfrog.io",
457459
},
458460
{
459-
name: "Derived from xray url",
460-
server: config.ServerDetails{XrayUrl: "https://acme.jfrog.io/xray/"},
461-
expected: "https://acme.jfrog.io",
461+
name: "Derived from xray url",
462+
server: config.ServerDetails{XrayUrl: "https://acme.jfrog.io/xray/"},
463+
xrayVersion: "3.151.0",
464+
expected: "https://acme.jfrog.io",
462465
},
463466
{
464-
name: "No urls configured",
465-
server: config.ServerDetails{},
466-
expected: "",
467+
name: "No urls configured",
468+
server: config.ServerDetails{},
469+
xrayVersion: "3.151.0",
470+
expected: "",
471+
},
472+
{
473+
name: "Xray version below the permalink endpoint",
474+
server: config.ServerDetails{Url: "https://acme.jfrog.io/"},
475+
xrayVersion: "3.150.2",
476+
expected: "",
467477
},
468478
}
469479
for _, tc := range testCases {
470480
t.Run(tc.name, func(t *testing.T) {
471-
assert.Equal(t, tc.expected, GetPlatformUrl(&tc.server))
481+
assert.Equal(t, tc.expected, GetViolationUiLinkBaseUrl(&tc.server, tc.xrayVersion))
472482
})
473483
}
474484
}

0 commit comments

Comments
 (0)