Skip to content
Closed
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
2 changes: 1 addition & 1 deletion artifactory/commands/transfer/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (tst *TransferSettingsCommand) Run() error {
ioutils.ScanFromConsole("Set the maximum number of working threads", &threadsNumberInput, currThreadsNumber)
threadsNumber, err := strconv.Atoi(threadsNumberInput)
if err != nil || threadsNumber < 1 || threadsNumber > MaxThreadsLimit {
return errorutils.CheckErrorf("the value must be a number between 1 and " + strconv.Itoa(MaxThreadsLimit))
return errorutils.CheckErrorf("the value must be a number between 1 and %s", strconv.Itoa(MaxThreadsLimit))
}
conf := &utils.TransferSettings{ThreadsNumber: threadsNumber}
err = utils.SaveTransferSettings(conf)
Expand Down
2 changes: 1 addition & 1 deletion artifactory/commands/transferconfig/transferconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ func (tcc *TransferConfigCommand) verifyConfigImportPlugin() error {

// Unexpected status received: 403 if the user is not admin, 500+ if there is a server error
messageFormat := fmt.Sprintf("Target server response: %s.\n%s", resp.Status, body)
return errorutils.CheckErrorf(messageFormat)
return errors.New(messageFormat)
}

// Creates the Pre-checks runner for the config import command
Expand Down
2 changes: 1 addition & 1 deletion artifactory/commands/transferfiles/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ func uploadChunkWhenPossibleHandler(pcWrapper *producerConsumerWrapper, phaseBas
shouldStop := uploadChunkWhenPossible(pcWrapper, phaseBase, chunk, uploadTokensChan, errorsChannelMng)
if shouldStop {
// The specific error that triggered the stop is already in the errors channel
return errorutils.CheckErrorf(logMsgPrefix + "stopped")
return errorutils.CheckErrorf("%sstopped", logMsgPrefix)
}
return nil
}
Expand Down
4 changes: 2 additions & 2 deletions artifactory/commands/utils/templateutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ func ConvertTemplateToMaps(templateUserCommand TemplateUserCommand) (interface{}

func ValidateMapEntry(key string, value interface{}, writersMap map[string]ioutils.AnswerWriter) error {
if _, ok := writersMap[key]; !ok {
return errorutils.CheckErrorf("template syntax error: unknown key: \"" + key + "\".")
return errorutils.CheckErrorf("template syntax error: unknown key: \"%s\".", key)
}
if _, ok := value.(string); !ok {
return errorutils.CheckErrorf("template syntax error: the value for the key: \"" + key + "\" is not a string type.")
return errorutils.CheckErrorf("template syntax error: the value for the key: \"%s\" is not a string type.", key)
}
return nil
}
Expand Down
8 changes: 5 additions & 3 deletions artifactory/commands/utils/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package utils

import (
"encoding/json"
"errors"
"fmt"
"net/http"
"time"

"github.com/gocarina/gocsv"
ioutils "github.com/jfrog/gofrog/io"
logutils "github.com/jfrog/jfrog-cli-core/v2/utils/log"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io/httputils"
"net/http"
"time"
)

type ServerType string
Expand Down Expand Up @@ -40,7 +42,7 @@ func GetTransferPluginVersion(client *jfroghttpclient.JfrogHttpClient, url, plug
return "", errorutils.CheckErrorf("%sIt looks like the %s plugin is not installed on the %s server.", messageFormat, pluginName, serverType)
} else {
// 403 if the user is not admin, 500+ if there is a server error
return "", errorutils.CheckErrorf(messageFormat)
return "", errors.New(messageFormat)
}
}

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

import (
"fmt"
"net/url"
)

const (
releaseBundleEvidenceFormat = "%sui/artifactory/lifecycle?range=Any+Time&bundleName=%s&repositoryKey=%s&releaseBundleVersion=%s&activeVersionTab=Evidence+Graph"
buildEvidenceFormat = "%sui/builds/%s/%s/%s/Evidence/%s?buildRepo=%s"
artifactEvidenceFormat = "%sui/repos/tree/Evidence/%s?clearFilter=true"
)

func GenerateEvidenceUrlByType(data EvidenceSummaryData, section summarySection) (string, error) {
switch data.SubjectType {
// Currently, it is not possible to generate a link to the evidence tab for packages in the Artifactory UI.
// The link will point to the lead artifact of the package instead.
// This logic will be updated once UI support is available
case SubjectTypePackage, SubjectTypeArtifact:
return generateArtifactEvidenceUrl(data.Subject, section)
case SubjectTypeReleaseBundle:
return generateReleaseBundleEvidenceUrl(data, section)
case SubjectTypeBuild:
return generateBuildEvidenceUrl(data, section)
default:
return generateArtifactEvidenceUrl(data.Subject, section)
}
}

func generateArtifactEvidenceUrl(pathInRt string, section summarySection) (string, error) {
urlStr := fmt.Sprintf(artifactEvidenceFormat, StaticMarkdownConfig.GetPlatformUrl(), pathInRt)
return addGitHubTrackingToUrl(urlStr, section)
}

func generateReleaseBundleEvidenceUrl(data EvidenceSummaryData, section summarySection) (string, error) {
if data.ReleaseBundleName == "" || data.ReleaseBundleVersion == "" {
return generateArtifactEvidenceUrl(data.Subject, section)
}

urlStr := fmt.Sprintf(releaseBundleEvidenceFormat,
StaticMarkdownConfig.GetPlatformUrl(),
data.ReleaseBundleName,
data.RepoKey,
data.ReleaseBundleVersion)

return addGitHubTrackingToUrl(urlStr, section)
}

func generateBuildEvidenceUrl(data EvidenceSummaryData, section summarySection) (string, error) {
if data.BuildName == "" || data.BuildNumber == "" || data.BuildTimestamp == "" {
return generateArtifactEvidenceUrl(data.Subject, section)
}

urlStr := fmt.Sprintf(buildEvidenceFormat,
StaticMarkdownConfig.GetPlatformUrl(),
url.QueryEscape(data.BuildName),
data.BuildNumber,
data.BuildTimestamp,
url.QueryEscape(data.BuildName),
data.RepoKey)

return addGitHubTrackingToUrl(urlStr, section)
}
141 changes: 141 additions & 0 deletions artifactory/utils/commandsummary/evidence_url_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package commandsummary

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGenerateEvidenceUrlByType(t *testing.T) {
// Set up test environment
originalWorkflow := os.Getenv(workflowEnvKey)
err := os.Setenv(workflowEnvKey, "JFrog CLI Core Tests")
if err != nil {
assert.FailNow(t, "Failed to set environment variable", err)
}
defer func() {
if originalWorkflow != "" {
err = os.Setenv(workflowEnvKey, originalWorkflow)
if err != nil {
assert.Fail(t, "Failed to restore workflow environment variable", err)
return
}
} else {
os.Unsetenv(workflowEnvKey)
}
}()

// Configure static markdown config for tests
StaticMarkdownConfig.setPlatformUrl("https://myplatform.com/")
StaticMarkdownConfig.setPlatformMajorVersion(7)

tests := []struct {
name string
data EvidenceSummaryData
expectedURL string
expectError bool
}{
{
name: "Package evidence URL",
data: EvidenceSummaryData{
Subject: "repo/path/package.jar",
SubjectType: SubjectTypePackage,
},
expectedURL: "https://myplatform.com/ui/repos/tree/Evidence/repo/path/package.jar?clearFilter=true&gh_job_id=JFrog+CLI+Core+Tests&gh_section=evidence&m=3&s=1",
},
{
name: "Artifact evidence URL",
data: EvidenceSummaryData{
Subject: "repo/path/artifact.txt",
SubjectType: SubjectTypeArtifact,
},
expectedURL: "https://myplatform.com/ui/repos/tree/Evidence/repo/path/artifact.txt?clearFilter=true&gh_job_id=JFrog+CLI+Core+Tests&gh_section=evidence&m=3&s=1",
},
{
name: "Release bundle evidence URL",
data: EvidenceSummaryData{
Subject: "release-bundles-v2/my-bundle/1.0.0/release-bundle.json.evd",
SubjectType: SubjectTypeReleaseBundle,
ReleaseBundleName: "my-bundle",
ReleaseBundleVersion: "1.0.0",
RepoKey: "release-bundles-v2",
},
expectedURL: "", // Will be checked with custom assertion
},
{
name: "Build evidence URL",
data: EvidenceSummaryData{
Subject: "artifactory-build-info/my-build/123/1234567890.json",
SubjectType: SubjectTypeBuild,
BuildName: "my-build",
BuildNumber: "123",
BuildTimestamp: "1234567890",
RepoKey: "artifactory-build-info",
},
expectedURL: "https://myplatform.com/ui/builds/my-build/123/1234567890/Evidence/my-build?buildRepo=artifactory-build-info&gh_job_id=JFrog+CLI+Core+Tests&gh_section=evidence&m=3&s=1",
},
{
name: "Build with special characters in name",
data: EvidenceSummaryData{
Subject: "artifactory-build-info/my build with spaces/123/1234567890.json",
SubjectType: SubjectTypeBuild,
BuildName: "my build with spaces",
BuildNumber: "123",
BuildTimestamp: "1234567890",
RepoKey: "artifactory-build-info",
},
expectedURL: "https://myplatform.com/ui/builds/my+build+with+spaces/123/1234567890/Evidence/my+build+with+spaces?buildRepo=artifactory-build-info&gh_job_id=JFrog+CLI+Core+Tests&gh_section=evidence&m=3&s=1",
},
{
name: "Invalid release bundle falls back to artifact URL",
data: EvidenceSummaryData{
Subject: "invalid/path",
SubjectType: SubjectTypeReleaseBundle,
},
expectedURL: "https://myplatform.com/ui/repos/tree/Evidence/invalid/path?clearFilter=true&gh_job_id=JFrog+CLI+Core+Tests&gh_section=evidence&m=3&s=1",
},
{
name: "Invalid build falls back to artifact URL",
data: EvidenceSummaryData{
Subject: "invalid/build/path",
SubjectType: SubjectTypeBuild,
},
expectedURL: "https://myplatform.com/ui/repos/tree/Evidence/invalid/build/path?clearFilter=true&gh_job_id=JFrog+CLI+Core+Tests&gh_section=evidence&m=3&s=1",
},
{
name: "Default type uses artifact URL",
data: EvidenceSummaryData{
Subject: "some/path/file.txt",
SubjectType: "", // Empty type should default to artifact
},
expectedURL: "https://myplatform.com/ui/repos/tree/Evidence/some/path/file.txt?clearFilter=true&gh_job_id=JFrog+CLI+Core+Tests&gh_section=evidence&m=3&s=1",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
url, err := GenerateEvidenceUrlByType(tt.data, evidenceSection)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
if tt.expectedURL != "" {
assert.Equal(t, tt.expectedURL, url)
} else if tt.name == "Release bundle evidence URL" {
// Special handling for release bundle URL due to parameter ordering
assert.Contains(t, url, "https://myplatform.com/ui/artifactory/lifecycle?")
assert.Contains(t, url, "bundleName=my-bundle")
assert.Contains(t, url, "repositoryKey=release-bundles-v2")
assert.Contains(t, url, "releaseBundleVersion=1.0.0")
assert.Contains(t, url, "activeVersionTab=Evidence+Graph")
assert.Contains(t, url, "gh_job_id=JFrog+CLI+Core+Tests")
assert.Contains(t, url, "gh_section=evidence")
assert.Contains(t, url, "m=3")
assert.Contains(t, url, "s=1")
assert.Contains(t, url, "range=Any+Time")
}
}
})
}
}
Loading
Loading