diff --git a/artifactory/commands/transfer/settings.go b/artifactory/commands/transfer/settings.go
index b034412de..3a4959000 100644
--- a/artifactory/commands/transfer/settings.go
+++ b/artifactory/commands/transfer/settings.go
@@ -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)
diff --git a/artifactory/commands/transferconfig/transferconfig.go b/artifactory/commands/transferconfig/transferconfig.go
index 42af06f40..d71577b8f 100644
--- a/artifactory/commands/transferconfig/transferconfig.go
+++ b/artifactory/commands/transferconfig/transferconfig.go
@@ -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
diff --git a/artifactory/commands/transferfiles/utils.go b/artifactory/commands/transferfiles/utils.go
index 4db4c0587..1aa353fb4 100644
--- a/artifactory/commands/transferfiles/utils.go
+++ b/artifactory/commands/transferfiles/utils.go
@@ -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
}
diff --git a/artifactory/commands/utils/templateutils.go b/artifactory/commands/utils/templateutils.go
index f88f5854c..3e291167b 100644
--- a/artifactory/commands/utils/templateutils.go
+++ b/artifactory/commands/utils/templateutils.go
@@ -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
}
diff --git a/artifactory/commands/utils/transfer.go b/artifactory/commands/utils/transfer.go
index ae9117b25..5d2083feb 100644
--- a/artifactory/commands/utils/transfer.go
+++ b/artifactory/commands/utils/transfer.go
@@ -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
@@ -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)
}
}
diff --git a/artifactory/utils/commandsummary/evidence_url.go b/artifactory/utils/commandsummary/evidence_url.go
new file mode 100644
index 000000000..50ca88bca
--- /dev/null
+++ b/artifactory/utils/commandsummary/evidence_url.go
@@ -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)
+}
diff --git a/artifactory/utils/commandsummary/evidence_url_test.go b/artifactory/utils/commandsummary/evidence_url_test.go
new file mode 100644
index 000000000..352096985
--- /dev/null
+++ b/artifactory/utils/commandsummary/evidence_url_test.go
@@ -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")
+ }
+ }
+ })
+ }
+}
diff --git a/artifactory/utils/commandsummary/evidencesummary.go b/artifactory/utils/commandsummary/evidencesummary.go
new file mode 100644
index 000000000..5e87d5cf7
--- /dev/null
+++ b/artifactory/utils/commandsummary/evidencesummary.go
@@ -0,0 +1,151 @@
+package commandsummary
+
+import (
+ "fmt"
+ "github.com/jfrog/jfrog-client-go/utils/log"
+ "strings"
+ "time"
+)
+
+const evidenceHeaderSize = 3
+
+type EvidenceSummaryData struct {
+ Subject string `json:"subject"`
+ SubjectSha256 string `json:"subjectSha256"`
+ PredicateType string `json:"predicateType"`
+ PredicateSlug string `json:"predicateSlug"`
+ Verified bool `json:"verified"`
+ DisplayName string `json:"displayName,omitempty"`
+ SubjectType SubjectType `json:"subjectType"`
+ BuildName string `json:"buildName"`
+ BuildNumber string `json:"buildNumber"`
+ BuildTimestamp string `json:"buildTimestamp"`
+ ReleaseBundleName string `json:"releaseBundleName"`
+ ReleaseBundleVersion string `json:"releaseBundleVersion"`
+ RepoKey string `json:"repoKey"`
+ CreatedAt time.Time `json:"createdAt"`
+}
+
+type SubjectType string
+
+const (
+ SubjectTypeArtifact SubjectType = "artifact"
+ SubjectTypeBuild SubjectType = "build"
+ SubjectTypePackage SubjectType = "package"
+ SubjectTypeReleaseBundle SubjectType = "release-bundle"
+)
+
+type EvidenceSummary struct {
+ CommandSummary
+}
+
+func NewEvidenceSummary() (*CommandSummary, error) {
+ return New(&EvidenceSummary{}, "evidence")
+}
+
+func (es *EvidenceSummary) GetSummaryTitle() string {
+ return "🔎 Evidence"
+}
+
+func (es *EvidenceSummary) GenerateMarkdownFromFiles(dataFilePaths []string) (finalMarkdown string, err error) {
+ log.Debug("Generating evidence summary markdown.")
+ var evidenceData []EvidenceSummaryData
+ for _, filePath := range dataFilePaths {
+ var evidence EvidenceSummaryData
+ if err = UnmarshalFromFilePath(filePath, &evidence); err != nil {
+ log.Warn("Failed to unmarshal evidence data from file %s: %v", filePath, err)
+ return
+ }
+ evidenceData = append(evidenceData, evidence)
+ }
+
+ if len(evidenceData) == 0 {
+ return
+ }
+
+ tableMarkdown := es.generateEvidenceTable(evidenceData)
+ return WrapCollapsableMarkdown(es.GetSummaryTitle(), tableMarkdown, evidenceHeaderSize), nil
+}
+
+func (es *EvidenceSummary) generateEvidenceTable(evidenceData []EvidenceSummaryData) string {
+ var tableBuilder strings.Builder
+ tableBuilder.WriteString(es.getTableHeader())
+
+ for _, evidence := range evidenceData {
+ es.appendEvidenceRow(&tableBuilder, evidence)
+ }
+
+ tableBuilder.WriteString(" \n")
+ return tableBuilder.String()
+}
+
+func (es *EvidenceSummary) getTableHeader() string {
+ return "
| Evidence Subject | Evidence Type | Verification Status |
\n"
+}
+
+func (es *EvidenceSummary) appendEvidenceRow(tableBuilder *strings.Builder, evidence EvidenceSummaryData) {
+ subject := es.formatSubjectWithLink(evidence)
+ evidenceType := es.formatEvidenceType(evidence)
+ verificationStatus := es.formatVerificationStatus(evidence.Verified)
+
+ tableBuilder.WriteString(fmt.Sprintf("| %s | %s | %s |
\n", subject, evidenceType, verificationStatus))
+}
+
+func (es *EvidenceSummary) formatSubjectWithLink(evidence EvidenceSummaryData) string {
+ if evidence.Subject == "" {
+ return "evidence"
+ }
+
+ evidenceUrl, err := GenerateEvidenceUrlByType(evidence, evidenceSection)
+ if err != nil {
+ log.Warn("Failed to generate evidence URL: %v", err)
+ evidenceUrl = ""
+ }
+
+ displayName := evidence.DisplayName
+ if displayName == "" {
+ displayName = evidence.Subject
+ }
+
+ var viewLink string
+ subjectType := es.formatSubjectType(evidence.SubjectType)
+ if evidenceUrl != "" {
+ viewLink = fmt.Sprintf(`%s %s`, subjectType, evidenceUrl, displayName)
+ } else {
+ viewLink = fmt.Sprintf("%s %s", subjectType, displayName)
+ }
+
+ return viewLink
+}
+
+func (es *EvidenceSummary) formatVerificationStatus(verified bool) string {
+ if verified {
+ return fmt.Sprintf("%s Verified", "✅")
+ }
+ return fmt.Sprintf("%s Not Verified", "❌")
+}
+
+func (es *EvidenceSummary) formatEvidenceType(evidence EvidenceSummaryData) string {
+ if evidence.PredicateSlug == "" {
+ if evidence.PredicateType == "" {
+ return "⚠️ Unknown"
+ }
+ return evidence.PredicateType
+ }
+ return evidence.PredicateSlug
+}
+
+func (es *EvidenceSummary) formatSubjectType(subjectType SubjectType) string {
+ switch subjectType {
+ case SubjectTypePackage:
+ return "📦️"
+ case SubjectTypeBuild:
+ return "🛠️️"
+ case SubjectTypeReleaseBundle:
+ return "🧩"
+ case SubjectTypeArtifact:
+ return "📄"
+ default:
+ return ""
+ }
+}
diff --git a/artifactory/utils/commandsummary/evidencesummary_test.go b/artifactory/utils/commandsummary/evidencesummary_test.go
new file mode 100644
index 000000000..e69356b8f
--- /dev/null
+++ b/artifactory/utils/commandsummary/evidencesummary_test.go
@@ -0,0 +1,191 @@
+package commandsummary
+
+import (
+ "os"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+)
+
+const (
+ evidenceTable = "evidence.md"
+)
+
+func prepareEvidenceTest(t *testing.T) (*EvidenceSummary, func()) {
+ originalWorkflow := os.Getenv(workflowEnvKey)
+ err := os.Setenv(workflowEnvKey, "JFrog CLI Core Tests")
+ if err != nil {
+ assert.Fail(t, "Failed to set environment variable", err)
+ }
+
+ StaticMarkdownConfig.setPlatformUrl(testPlatformUrl)
+ StaticMarkdownConfig.setPlatformMajorVersion(7)
+ StaticMarkdownConfig.setExtendedSummary(false)
+
+ cleanup := func() {
+ StaticMarkdownConfig.setExtendedSummary(false)
+ StaticMarkdownConfig.setPlatformMajorVersion(0)
+ StaticMarkdownConfig.setPlatformUrl("")
+
+ if originalWorkflow != "" {
+ err = os.Setenv(workflowEnvKey, originalWorkflow)
+ if err != nil {
+ assert.Fail(t, "Failed to set workflow environment variable", err)
+ }
+ } else {
+ os.Unsetenv(workflowEnvKey)
+ }
+ }
+
+ evidenceSummary := &EvidenceSummary{}
+ return evidenceSummary, cleanup
+}
+
+func TestEvidenceTable(t *testing.T) {
+ evidenceSummary, cleanUp := prepareEvidenceTest(t)
+ defer func() {
+ cleanUp()
+ }()
+
+ createdTime := time.Date(2024, 12, 1, 10, 0, 0, 0, time.UTC)
+
+ var evidenceData = []EvidenceSummaryData{
+ {
+ Subject: "cli-sigstore-test/commons-1.0.0.txt",
+ SubjectSha256: "",
+ PredicateType: "in-toto",
+ PredicateSlug: "in-toto",
+ Verified: true,
+ DisplayName: "cli-sigstore-test/commons-1.0.0.txt",
+ SubjectType: SubjectTypeArtifact,
+ RepoKey: "cli-sigstore-test/commons-1.0.0.txt",
+ CreatedAt: createdTime,
+ },
+ }
+
+ t.Run("Extended Summary", func(t *testing.T) {
+ StaticMarkdownConfig.setExtendedSummary(true)
+ res := evidenceSummary.generateEvidenceTable(evidenceData)
+ testMarkdownOutput(t, getTestDataFile(t, evidenceTable), res)
+ })
+
+ t.Run("Basic Summary", func(t *testing.T) {
+ StaticMarkdownConfig.setExtendedSummary(false)
+ res := evidenceSummary.generateEvidenceTable(evidenceData)
+ testMarkdownOutput(t, getTestDataFile(t, evidenceTable), res)
+ })
+}
+
+func TestFormatSubjectType(t *testing.T) {
+ evidenceSummary := &EvidenceSummary{}
+
+ tests := []struct {
+ name string
+ subjectType SubjectType
+ expectedIcon string
+ }{
+ {
+ name: "Artifact",
+ subjectType: SubjectTypeArtifact,
+ expectedIcon: "📄",
+ },
+ {
+ name: "Package",
+ subjectType: SubjectTypePackage,
+ expectedIcon: "📦️",
+ },
+ {
+ name: "Build",
+ subjectType: SubjectTypeBuild,
+ expectedIcon: "🛠️️",
+ },
+ {
+ name: "Release Bundle",
+ subjectType: SubjectTypeReleaseBundle,
+ expectedIcon: "🧩",
+ },
+ {
+ name: "Unknown",
+ subjectType: SubjectType("unknown"),
+ expectedIcon: "",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := evidenceSummary.formatSubjectType(tt.subjectType)
+ assert.Equal(t, tt.expectedIcon, result)
+ })
+ }
+}
+
+func TestFormatVerificationStatus(t *testing.T) {
+ evidenceSummary := &EvidenceSummary{}
+
+ tests := []struct {
+ name string
+ verified bool
+ expected string
+ }{
+ {
+ name: "Verified",
+ verified: true,
+ expected: "✅ Verified",
+ },
+ {
+ name: "Not Verified",
+ verified: false,
+ expected: "❌ Not Verified",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := evidenceSummary.formatVerificationStatus(tt.verified)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestFormatEvidenceType(t *testing.T) {
+ evidenceSummary := &EvidenceSummary{}
+
+ tests := []struct {
+ name string
+ evidence EvidenceSummaryData
+ expectedType string
+ }{
+ {
+ name: "With PredicateSlug",
+ evidence: EvidenceSummaryData{
+ PredicateSlug: "in-toto",
+ PredicateType: "in-toto",
+ },
+ expectedType: "in-toto",
+ },
+ {
+ name: "Without PredicateSlug but with PredicateType",
+ evidence: EvidenceSummaryData{
+ PredicateSlug: "",
+ PredicateType: "https://slsa.dev/provenance/v0.2",
+ },
+ expectedType: "https://slsa.dev/provenance/v0.2",
+ },
+ {
+ name: "Without PredicateSlug and PredicateType",
+ evidence: EvidenceSummaryData{
+ PredicateSlug: "",
+ PredicateType: "",
+ },
+ expectedType: "⚠️ Unknown",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := evidenceSummary.formatEvidenceType(tt.evidence)
+ assert.Equal(t, tt.expectedType, result)
+ })
+ }
+}
diff --git a/artifactory/utils/commandsummary/utils.go b/artifactory/utils/commandsummary/utils.go
index 75b9541e9..a83457c0f 100644
--- a/artifactory/utils/commandsummary/utils.go
+++ b/artifactory/utils/commandsummary/utils.go
@@ -47,6 +47,7 @@ const (
artifactsSection summarySection = "artifacts"
packagesSection summarySection = "packages"
buildInfoSection summarySection = "buildInfo"
+ evidenceSection summarySection = "evidence"
)
const (
diff --git a/artifactory/utils/container/buildinfo.go b/artifactory/utils/container/buildinfo.go
index 5d2a6c446..74b69fe67 100644
--- a/artifactory/utils/container/buildinfo.go
+++ b/artifactory/utils/container/buildinfo.go
@@ -71,7 +71,7 @@ func newBuildInfoBuilder(image *Image, repository, buildName, buildNumber, proje
repoDetails := &services.RepositoryDetails{}
err = serviceManager.GetRepository(repository, &repoDetails)
if err != nil {
- return nil, errorutils.CheckErrorf("failed to get details for repository '" + repository + "'. Error:\n" + err.Error())
+ return nil, errorutils.CheckErrorf("failed to get details for repository '%s'. Error:\n%s", repository, err.Error())
}
builder.repositoryDetails.isRemote = repoDetails.GetRepoType() == "remote"
@@ -324,11 +324,11 @@ func GetImageTagWithDigest(filePath string) (*Image, string, error) {
// Try read Kaniko/oc file.
splittedData := strings.Split(string(data), `@`)
if len(splittedData) != 2 {
- return nil, "", errorutils.CheckErrorf(`unexpected file format "` + filePath + `". The file should include one line in the following format: image-tag@sha256`)
+ return nil, "", errorutils.CheckErrorf(`unexpected file format "%s". The file should include one line in the following format: image-tag@sha256`, filePath)
}
tag, sha256 := splittedData[0], strings.Trim(splittedData[1], "\n")
if tag == "" || sha256 == "" {
- err = errorutils.CheckErrorf(`missing image-tag/sha256 in file: "` + filePath + `"`)
+ err = errorutils.CheckErrorf(`missing image-tag/sha256 in file: "%s"`, filePath)
if err != nil {
return nil, "", err
}
@@ -609,7 +609,7 @@ func getDependenciesFromManifestConfig(candidateLayers map[string]*utils.ResultI
dependencies = append(dependencies, getManifestDependency(manifestSearchResults))
imageDetails, found := candidateLayers[digestToLayer(imageSha2)]
if !found {
- return nil, errorutils.CheckErrorf("failed to collect build-info. Image '" + imageSha2 + "' was not found in Artifactory")
+ return nil, errorutils.CheckErrorf("failed to collect build-info. Image '%s' was not found in Artifactory", imageSha2)
}
return append(dependencies, imageDetails.ToDependency()), nil
diff --git a/artifactory/utils/container/containermanager.go b/artifactory/utils/container/containermanager.go
index 464da9589..a9ec54405 100644
--- a/artifactory/utils/container/containermanager.go
+++ b/artifactory/utils/container/containermanager.go
@@ -84,7 +84,7 @@ func (containerManager *containerManager) OsCompatibility(image *Image) (string,
content = strings.Trim(content, "\n")
firstSeparator := strings.Index(content, ",")
if firstSeparator == -1 {
- return "", "", errorutils.CheckErrorf("couldn't find OS and architecture of image:" + image.name)
+ return "", "", errorutils.CheckErrorf("couldn't find OS and architecture of image: %s", image.name)
}
return content[:firstSeparator], content[firstSeparator+1:], err
}
diff --git a/artifactory/utils/container/image.go b/artifactory/utils/container/image.go
index 81f3d5e3d..7738f9113 100644
--- a/artifactory/utils/container/image.go
+++ b/artifactory/utils/container/image.go
@@ -1,6 +1,7 @@
package container
import (
+ "errors"
"net/http"
"path"
"strconv"
@@ -154,15 +155,15 @@ func (image *Image) GetRemoteRepo(serviceManager artifactory.ArtifactoryServices
return "", err
}
if resp.StatusCode == http.StatusForbidden {
- return "", errorutils.CheckErrorf(getStatusForbiddenErrorMessage())
+ return "", errors.New(getStatusForbiddenErrorMessage())
}
if resp.StatusCode != http.StatusOK {
- return "", errorutils.CheckErrorf("error while getting docker repository name. Artifactory response: " + resp.Status)
+ return "", errorutils.CheckErrorf("error while getting docker repository name. Artifactory response: %s", resp.Status)
}
if dockerRepo := resp.Header["X-Artifactory-Docker-Registry"]; len(dockerRepo) != 0 {
return dockerRepo[0], nil
}
- return "", errorutils.CheckErrorf("couldn't find 'X-Artifactory-Docker-Registry' header docker repository in artifactory")
+ return "", errors.New("couldn't find 'X-Artifactory-Docker-Registry' header docker repository in artifactory")
}
// Returns the name of the repository containing the image in Artifactory.
diff --git a/artifactory/utils/container/localagent.go b/artifactory/utils/container/localagent.go
index 57c4ef573..7d44734a1 100644
--- a/artifactory/utils/container/localagent.go
+++ b/artifactory/utils/container/localagent.go
@@ -192,5 +192,5 @@ func handleForeignLayer(layerMediaType, layerFileName string) error {
log.Info(fmt.Sprintf("Foreign layer: %s is missing in Artifactory and therefore will not be added to the build-info.", layerFileName))
return nil
}
- return errorutils.CheckErrorf("Could not find layer: " + layerFileName + " in Artifactory")
+ return errorutils.CheckErrorf("Could not find layer: %s in Artifactory", layerFileName)
}
diff --git a/artifactory/utils/container/remoteagent.go b/artifactory/utils/container/remoteagent.go
index af2ff59e9..3bb6dbf22 100644
--- a/artifactory/utils/container/remoteagent.go
+++ b/artifactory/utils/container/remoteagent.go
@@ -65,7 +65,7 @@ func (rabib *RemoteAgentBuildInfoBuilder) handleManifest(resultMap map[string]*u
log.Debug("Found manifest.json. Proceeding to create build-info.")
return resultMap, manifest, nil
}
- return nil, nil, errorutils.CheckErrorf(`couldn't find image "` + rabib.buildInfoBuilder.image.name + `" manifest in Artifactory`)
+ return nil, nil, errorutils.CheckErrorf(`couldn't find image "%s" manifest in Artifactory`, rabib.buildInfoBuilder.image.name)
}
func (rabib *RemoteAgentBuildInfoBuilder) handleFatManifestImage(results map[string]*utils.ResultItem) (map[string][]*utils.ResultItem, *utils.ResultItem, *FatManifest, error) {
@@ -79,7 +79,7 @@ func (rabib *RemoteAgentBuildInfoBuilder) handleFatManifestImage(results map[str
multiPlatformImages, err := performMultiPlatformImageSearch(fatManifestRootPath, rabib.buildInfoBuilder.serviceManager)
return multiPlatformImages, fatManifestResult, fatManifest, err
}
- return nil, nil, nil, errorutils.CheckErrorf(`couldn't find image "` + rabib.buildInfoBuilder.image.name + `" fat manifest in Artifactory`)
+ return nil, nil, nil, errorutils.CheckErrorf(`couldn't find image "%s" fat manifest in Artifactory`, rabib.buildInfoBuilder.image.name)
}
// Search image manifest or fat-manifest of and image.
diff --git a/artifactory/utils/repositoryutils.go b/artifactory/utils/repositoryutils.go
index e73c2a913..37b8e68e5 100644
--- a/artifactory/utils/repositoryutils.go
+++ b/artifactory/utils/repositoryutils.go
@@ -1,15 +1,16 @@
package utils
import (
+ "os"
+ "path"
+ "strings"
+
"github.com/jfrog/gofrog/datastructures"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-core/v2/utils/ioutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"golang.org/x/exp/slices"
- "os"
- "path"
- "strings"
"github.com/jfrog/jfrog-client-go/artifactory"
"github.com/jfrog/jfrog-client-go/artifactory/services"
@@ -77,7 +78,7 @@ func IsRemoteRepo(repoName string, serviceManager artifactory.ArtifactoryService
repoDetails := &services.RepositoryDetails{}
err := serviceManager.GetRepository(repoName, &repoDetails)
if err != nil {
- return false, errorutils.CheckErrorf("failed to get details for repository '" + repoName + "'. Error:\n" + err.Error())
+ return false, errorutils.CheckErrorf("failed to get details for repository '%s'. Error:\n%s", repoName, err.Error())
}
return repoDetails.GetRepoType() == "remote", nil
}
diff --git a/artifactory/utils/testdata/command_summaries/basic/evidence.md b/artifactory/utils/testdata/command_summaries/basic/evidence.md
new file mode 100644
index 000000000..b12858ec1
--- /dev/null
+++ b/artifactory/utils/testdata/command_summaries/basic/evidence.md
@@ -0,0 +1,3 @@
+
diff --git a/artifactory/utils/testdata/command_summaries/extended/evidence.md b/artifactory/utils/testdata/command_summaries/extended/evidence.md
new file mode 100644
index 000000000..b12858ec1
--- /dev/null
+++ b/artifactory/utils/testdata/command_summaries/extended/evidence.md
@@ -0,0 +1,3 @@
+
diff --git a/artifactory/utils/utils.go b/artifactory/utils/utils.go
index 485cac992..3fe79261f 100644
--- a/artifactory/utils/utils.go
+++ b/artifactory/utils/utils.go
@@ -22,6 +22,7 @@ import (
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-client-go/access"
"github.com/jfrog/jfrog-client-go/artifactory"
+ artifactoryServices "github.com/jfrog/jfrog-client-go/artifactory/services"
"github.com/jfrog/jfrog-client-go/auth"
clientConfig "github.com/jfrog/jfrog-client-go/config"
"github.com/jfrog/jfrog-client-go/distribution"
@@ -86,10 +87,10 @@ func GetEncryptedPasswordFromArtifactory(artifactoryAuth auth.ServiceDetails, in
if resp.StatusCode == http.StatusConflict {
message := "\nYour Artifactory server is not configured to encrypt passwords.\n" +
"You may use \"art config --enc-password=false\""
- return "", errorutils.CheckErrorf(message)
+ return "", errors.New(message)
}
- return "", errorutils.CheckErrorf("Artifactory response: " + resp.Status + "\n" + clientUtils.IndentJson(body))
+ return "", errorutils.CheckErrorf("Artifactory response: %s\n%s", resp.Status, clientUtils.IndentJson(body))
}
func CreateServiceManager(serverDetails *config.ServerDetails, httpRetries, httpRetryWaitMilliSecs int, isDryRun bool) (artifactory.ArtifactoryServicesManager, error) {
@@ -341,7 +342,24 @@ func ValidateRepoExists(repoKey string, serviceDetails auth.ServiceDetails) erro
}
if !exists {
- return errorutils.CheckErrorf("The repository '" + repoKey + "' does not exist.")
+ return errorutils.CheckErrorf("The repository '%s' does not exist.", repoKey)
+ }
+ return nil
+}
+
+// ValidateRepoType checks if the repository exists and is of the expected package type (e.g., "vscode", "jetbrains").
+func ValidateRepoType(repoKey string, serviceDetails auth.ServiceDetails, expectedType string) error {
+ servicesManager, err := createServiceManager(serviceDetails)
+ if err != nil {
+ return err
+ }
+ repoDetails := &artifactoryServices.RepositoryDetails{}
+ err = servicesManager.GetRepository(repoKey, repoDetails)
+ if err != nil {
+ return fmt.Errorf("failed to fetch repository details for %q: %w", repoKey, err)
+ }
+ if !strings.EqualFold(repoDetails.PackageType, expectedType) {
+ return fmt.Errorf("repository '%s' is of type '%s', but expected type is '%s'", repoKey, repoDetails.PackageType, expectedType)
}
return nil
}
diff --git a/artifactory/utils/yarn/versionVerify.go b/artifactory/utils/yarn/versionVerify.go
index acebfc922..897ecf5ab 100644
--- a/artifactory/utils/yarn/versionVerify.go
+++ b/artifactory/utils/yarn/versionVerify.go
@@ -1,10 +1,11 @@
package yarn
import (
+ "strings"
+
gofrogcmd "github.com/jfrog/gofrog/io"
"github.com/jfrog/gofrog/version"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
- "strings"
)
const unsupportedYarnVersion = "4.0.0"
@@ -22,8 +23,7 @@ func IsInstalledYarnVersionSupported(executablePath string) error {
func IsVersionSupported(versionStr string) error {
yarnVersion := version.NewVersion(versionStr)
if yarnVersion.Compare(unsupportedYarnVersion) <= 0 {
- return errorutils.CheckErrorf("Yarn version 4 is not supported. The current version is: " + versionStr +
- ". Please downgrade to a compatible version to continue")
+ return errorutils.CheckErrorf("Yarn version 4 is not supported. The current version is: %s. Please downgrade to a compatible version to continue", versionStr)
}
return nil
}
diff --git a/common/build/buildinfoproperties.go b/common/build/buildinfoproperties.go
index ea2a6aa1d..cfac03d27 100644
--- a/common/build/buildinfoproperties.go
+++ b/common/build/buildinfoproperties.go
@@ -184,7 +184,7 @@ func GetServerDetails(vConfig *viper.Viper) (*config.ServerDetails, error) {
func CreateBuildInfoProps(buildArtifactsDetailsFile string, config *viper.Viper, projectType project.ProjectType) (map[string]string, error) {
if config.GetString("type") != projectType.String() {
- return nil, errorutils.CheckErrorf("Incompatible build config, expected: " + projectType.String() + " got: " + config.GetString("type"))
+ return nil, errorutils.CheckErrorf("Incompatible build config, expected: %s, got: %s", projectType.String(), config.GetString("type"))
}
if err := setServerDetailsToConfig(ResolverPrefix, config); err != nil {
return nil, err
@@ -300,7 +300,7 @@ func setServerDetailsToConfig(contextPrefix string, vConfig *viper.Viper) error
return err
}
if artDetails.GetArtifactoryUrl() == "" {
- return errorutils.CheckErrorf("Server ID " + serverId + ": URL is required.")
+ return errorutils.CheckErrorf("Server ID %s URL is required.", serverId)
}
vConfig.Set(contextPrefix+Url, artDetails.GetArtifactoryUrl())
diff --git a/common/commands/config.go b/common/commands/config.go
index ca3c9da85..b34ae8d80 100644
--- a/common/commands/config.go
+++ b/common/commands/config.go
@@ -3,7 +3,6 @@ package commands
import (
"errors"
"fmt"
- generic "github.com/jfrog/jfrog-cli-core/v2/general/token"
"net/url"
"os"
"reflect"
@@ -11,6 +10,8 @@ import (
"strings"
"sync"
+ generic "github.com/jfrog/jfrog-cli-core/v2/general/token"
+
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
@@ -134,7 +135,7 @@ func (cc *ConfigCommand) Run() (err error) {
case Clear:
err = cc.clear()
default:
- err = fmt.Errorf("Not supported config command type: " + string(cc.cmdType))
+ err = fmt.Errorf("Not supported config command type: %s", string(cc.cmdType))
}
return
}
diff --git a/common/commands/configfile.go b/common/commands/configfile.go
index a9f45b2a5..db06a59ba 100644
--- a/common/commands/configfile.go
+++ b/common/commands/configfile.go
@@ -1,6 +1,7 @@
package commands
import (
+ "errors"
"fmt"
"os"
"path/filepath"
@@ -580,7 +581,7 @@ func validateRepositoryConfig(repository *project.Repository, errorPrefix string
snapshotRepo := repository.SnapshotRepo
if repository.ServerId != "" && repository.Repo == "" && releaseRepo == "" && snapshotRepo == "" {
- return errorutils.CheckErrorf(errorPrefix + setRepositoryError)
+ return errors.New(errorPrefix + setRepositoryError)
}
// Server-id flag was not provided.
if repository.ServerId == "" {
@@ -601,7 +602,7 @@ func validateRepositoryConfig(repository *project.Repository, errorPrefix string
if serverId == "" {
// Repositories flags were provided.
if repository.Repo != "" || releaseRepo != "" || snapshotRepo != "" {
- return errorutils.CheckErrorf(errorPrefix + setServerIdError)
+ return errors.New(errorPrefix + setServerIdError)
}
} else if repository.Repo != "" || releaseRepo != "" || snapshotRepo != "" {
// Server-id flag wasn't provided and repositories flags were provided - the default configured global server will be chosen.
@@ -610,7 +611,7 @@ func validateRepositoryConfig(repository *project.Repository, errorPrefix string
}
// Release/snapshot repositories should be entangled to each other.
if (releaseRepo == "" && snapshotRepo != "") || (releaseRepo != "" && snapshotRepo == "") {
- return errorutils.CheckErrorf(errorPrefix + setSnapshotAndReleaseError)
+ return errors.New(errorPrefix + setSnapshotAndReleaseError)
}
return nil
}
@@ -632,7 +633,7 @@ func readArtifactoryServer(useArtifactoryQuestion string) (string, error) {
return "", err
}
if len(serversIds) == 0 {
- return "", errorutils.CheckErrorf("No Artifactory servers configured. Use the 'jfrog c add' command to set the Artifactory server details.")
+ return "", errors.New("No Artifactory servers configured. Use the 'jfrog c add' command to set the Artifactory server details.")
}
// Ask whether to use artifactory
diff --git a/common/format/output.go b/common/format/output.go
index a1ae5a6a5..01ded4abe 100644
--- a/common/format/output.go
+++ b/common/format/output.go
@@ -36,7 +36,7 @@ func GetOutputFormat(formatFlagVal string) (format OutputFormat, err error) {
case string(CycloneDx):
format = CycloneDx
default:
- err = errorutils.CheckErrorf("only the following output formats are supported: " + coreutils.ListToText(OutputFormats))
+ err = errorutils.CheckErrorf("only the following output formats are supported: %s", coreutils.ListToText(OutputFormats))
}
}
return
diff --git a/common/project/projectconfig.go b/common/project/projectconfig.go
index a4ef3d93e..d00f9cd3b 100644
--- a/common/project/projectconfig.go
+++ b/common/project/projectconfig.go
@@ -219,7 +219,7 @@ func GetResolutionOnlyConfiguration(projectType ProjectType) (*RepositoryConfig,
return nil, err
}
if !exists {
- return nil, errorutils.CheckErrorf(projectType.String() + " Project configuration does not exist.")
+ return nil, errorutils.CheckErrorf("%s Project configuration does not exist.", projectType.String())
}
return ReadResolutionOnlyConfiguration(confFilePath)
}
diff --git a/go.mod b/go.mod
index 25bf141af..489e93072 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module github.com/jfrog/jfrog-cli-core/v2
-go 1.23.7
+go 1.24.4
require github.com/c-bata/go-prompt v0.2.5 // Should not be updated to 0.2.6 due to a bug (https://github.com/jfrog/jfrog-cli-core/pull/372)
@@ -13,9 +13,9 @@ require (
github.com/google/uuid v1.6.0
github.com/gookit/color v1.5.4
github.com/jedib0t/go-pretty/v6 v6.6.5
- github.com/jfrog/build-info-go v1.10.14
+ github.com/jfrog/build-info-go v1.10.15
github.com/jfrog/gofrog v1.7.6
- github.com/jfrog/jfrog-client-go v1.54.3
+ github.com/jfrog/jfrog-client-go v1.54.4
github.com/magiconair/properties v1.8.9
github.com/manifoldco/promptui v0.9.0
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
diff --git a/go.sum b/go.sum
index b40159050..315b9d1b4 100644
--- a/go.sum
+++ b/go.sum
@@ -109,12 +109,12 @@ github.com/jedib0t/go-pretty/v6 v6.6.5 h1:9PgMJOVBedpgYLI56jQRJYqngxYAAzfEUua+3N
github.com/jedib0t/go-pretty/v6 v6.6.5/go.mod h1:Uq/HrbhuFty5WSVNfjpQQe47x16RwVGXIveNGEyGtHs=
github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI=
github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw=
-github.com/jfrog/build-info-go v1.10.14 h1:PWnw+rBwiQTHZ5q+84+E8MHFjtAQkB3+Oc2sKwBSSGE=
-github.com/jfrog/build-info-go v1.10.14/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE=
+github.com/jfrog/build-info-go v1.10.15 h1:y6E87iIBTofNy4mus6Ngv6AtVwg/bN/Rz+oaI3kpN4M=
+github.com/jfrog/build-info-go v1.10.15/go.mod h1:+8u1CEGrr8XY5a5U6farFW3EKYk0ge0BMGZE3BAZBcE=
github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s=
github.com/jfrog/gofrog v1.7.6/go.mod h1:ntr1txqNOZtHplmaNd7rS4f8jpA5Apx8em70oYEe7+4=
-github.com/jfrog/jfrog-client-go v1.54.3 h1:tIhhDhM7rDMT1lzgeQy4nr6H2ihlqnumhiFybIWlLz0=
-github.com/jfrog/jfrog-client-go v1.54.3/go.mod h1:1v0eih4thdPA4clBo9TuvAMT25sGDr1IQJ81DXQ/lBY=
+github.com/jfrog/jfrog-client-go v1.54.4 h1:W5J2WAidEPghlvWl7FbrJUeRyVbNzC6GnihNACVaeEM=
+github.com/jfrog/jfrog-client-go v1.54.4/go.mod h1:+pSVE7Co+ytwhOhmz84/Lpe5fSeTaWJXsP1qt+WVfw0=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
diff --git a/missioncontrol/commands/jpdadd.go b/missioncontrol/commands/jpdadd.go
index 977d068d2..01b71ceba 100644
--- a/missioncontrol/commands/jpdadd.go
+++ b/missioncontrol/commands/jpdadd.go
@@ -23,7 +23,7 @@ func JpdAdd(flags *JpdAddFlags) error {
return err
}
if resp.StatusCode != http.StatusCreated {
- return errorutils.CheckErrorf(resp.Status + ". " + utils.ReadMissionControlHttpMessage(body))
+ return errorutils.CheckErrorf("%s. %s", resp.Status, utils.ReadMissionControlHttpMessage(body))
}
log.Debug("Mission Control response: " + resp.Status)
diff --git a/missioncontrol/commands/jpddelete.go b/missioncontrol/commands/jpddelete.go
index 52692a21e..418844481 100644
--- a/missioncontrol/commands/jpddelete.go
+++ b/missioncontrol/commands/jpddelete.go
@@ -1,12 +1,13 @@
package commands
import (
+ "net/http"
+
"github.com/jfrog/jfrog-cli-core/v2/missioncontrol/utils"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-client-go/http/httpclient"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/log"
- "net/http"
)
func JpdDelete(jpdId string, serverDetails *config.ServerDetails) error {
@@ -21,7 +22,7 @@ func JpdDelete(jpdId string, serverDetails *config.ServerDetails) error {
return err
}
if resp.StatusCode != http.StatusNoContent {
- return errorutils.CheckErrorf(resp.Status + ". " + utils.ReadMissionControlHttpMessage(body))
+ return errorutils.CheckErrorf("%s. %s", resp.Status, utils.ReadMissionControlHttpMessage(body))
}
log.Debug("Mission Control response: " + resp.Status)
return nil
diff --git a/missioncontrol/commands/licenseacquire.go b/missioncontrol/commands/licenseacquire.go
index 56f659fb9..cce82c9a1 100644
--- a/missioncontrol/commands/licenseacquire.go
+++ b/missioncontrol/commands/licenseacquire.go
@@ -19,7 +19,7 @@ func LicenseAcquire(bucketId string, name string, serverDetails *config.ServerDe
}
requestContent, err := json.Marshal(postContent)
if err != nil {
- return errorutils.CheckErrorf("Failed to marshal json: " + err.Error())
+ return errorutils.CheckErrorf("Failed to marshal json: %s", err.Error())
}
missionControlUrl := serverDetails.MissionControlUrl + "api/v1/buckets/" + bucketId + "/acquire"
httpClientDetails := utils.GetMissionControlHttpClientDetails(serverDetails)
diff --git a/missioncontrol/commands/licensedeploy.go b/missioncontrol/commands/licensedeploy.go
index b3f86dea1..0b311102a 100644
--- a/missioncontrol/commands/licensedeploy.go
+++ b/missioncontrol/commands/licensedeploy.go
@@ -20,7 +20,7 @@ func LicenseDeploy(bucketId, jpdId string, flags *LicenseDeployFlags) error {
}
requestContent, err := json.Marshal(postContent)
if err != nil {
- return errorutils.CheckErrorf("Failed to marshal json: " + err.Error())
+ return errorutils.CheckErrorf("Failed to marshal json: %s", err.Error())
}
missionControlUrl := flags.ServerDetails.MissionControlUrl + "api/v1/buckets/" + bucketId + "/deploy"
httpClientDetails := utils.GetMissionControlHttpClientDetails(flags.ServerDetails)
diff --git a/missioncontrol/commands/licenserelease.go b/missioncontrol/commands/licenserelease.go
index a6854ba59..ec53abb06 100644
--- a/missioncontrol/commands/licenserelease.go
+++ b/missioncontrol/commands/licenserelease.go
@@ -17,7 +17,7 @@ func LicenseRelease(bucketId, jpdId string, mcDetails *config.ServerDetails) err
Name: jpdId}
requestContent, err := json.Marshal(postContent)
if err != nil {
- return errorutils.CheckErrorf("Failed to marshal json: " + err.Error())
+ return errorutils.CheckErrorf("Failed to marshal json: %s", err.Error())
}
missionControlUrl := mcDetails.MissionControlUrl + "api/v1/buckets/" + bucketId + "/release"
httpClientDetails := utils.GetMissionControlHttpClientDetails(mcDetails)
diff --git a/utils/config/config.go b/utils/config/config.go
index d059c5d54..92dfe9fda 100644
--- a/utils/config/config.go
+++ b/utils/config/config.go
@@ -851,7 +851,7 @@ func (serverDetails *ServerDetails) GetAuthenticationCredentials() (string, stri
} else if serverDetails.ArtifactoryUrl != "" {
errMissingCredsMsg += serverDetails.ArtifactoryUrl
}
- return "", "", errorutils.CheckErrorf(errMissingCredsMsg)
+ return "", "", errors.New(errMissingCredsMsg)
}
func (missionControlDetails *MissionControlDetails) GetAccessToken() string {
diff --git a/utils/config/encryption.go b/utils/config/encryption.go
index 2c78afb7d..a9b8731d7 100644
--- a/utils/config/encryption.go
+++ b/utils/config/encryption.go
@@ -5,12 +5,13 @@ import (
"crypto/cipher"
"crypto/rand"
"encoding/base64"
- ioutils "github.com/jfrog/gofrog/io"
"io"
"os"
"strconv"
"syscall"
+ ioutils "github.com/jfrog/gofrog/io"
+
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
@@ -147,7 +148,7 @@ func encrypt(secret string, key string) (string, error) {
return "", nil
}
if len(key) != 32 {
- return "", errorutils.CheckErrorf(encryptErrorPrefix + "Wrong length for master key. Key should have a length of exactly: " + strconv.Itoa(masterKeyLength) + " bytes")
+ return "", errorutils.CheckErrorf("%s Wrong length for master key. Key should have a length of exactly: %s bytes", encryptErrorPrefix, strconv.Itoa(masterKeyLength))
}
c, err := aes.NewCipher([]byte(key))
if err != nil {
diff --git a/utils/config/tokenrefresh.go b/utils/config/tokenrefresh.go
index e4362e2ea..5422db235 100644
--- a/utils/config/tokenrefresh.go
+++ b/utils/config/tokenrefresh.go
@@ -2,11 +2,12 @@ package config
import (
"errors"
+ "sync"
+ "time"
+
"github.com/jfrog/jfrog-client-go/access"
accessservices "github.com/jfrog/jfrog-client-go/access/services"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
- "sync"
- "time"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-core/v2/utils/lock"
@@ -113,7 +114,7 @@ func tokenRefreshHandler(currentAccessToken string, tokenType TokenType) (newAcc
newAccessToken, err = refreshAccessTokenAndWriteToConfig(serverConfiguration, currentAccessToken)
return
}
- err = errorutils.CheckErrorf("unsupported refreshable token type: " + string(tokenType))
+ err = errorutils.CheckErrorf("unsupported refreshable token type: %s", string(tokenType))
return
}
@@ -151,7 +152,7 @@ func refreshAccessTokenAndWriteToConfig(serverConfiguration *ServerDetails, curr
// Try refreshing tokens
newToken, err := refreshExpiredAccessToken(serverConfiguration, currentAccessToken, serverConfiguration.RefreshToken)
if err != nil {
- return "", errorutils.CheckErrorf("Refresh access token failed: " + err.Error())
+ return "", errorutils.CheckErrorf("Refresh access token failed: %s", err.Error())
}
err = writeNewTokens(serverConfiguration, tokenRefreshServerId, newToken.AccessToken, newToken.RefreshToken, AccessToken)
return newToken.AccessToken, err
diff --git a/utils/ioutils/ioutils.go b/utils/ioutils/ioutils.go
index c410c4d25..76f4c3f2a 100644
--- a/utils/ioutils/ioutils.go
+++ b/utils/ioutils/ioutils.go
@@ -4,16 +4,17 @@ import (
"bufio"
"errors"
"fmt"
- "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
- "github.com/jfrog/jfrog-client-go/utils/errorutils"
- "github.com/jfrog/jfrog-client-go/utils/io/fileutils"
- "github.com/jfrog/jfrog-client-go/utils/log"
- "golang.org/x/term"
"io"
"os"
"path/filepath"
"strings"
"syscall"
+
+ "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
+ "github.com/jfrog/jfrog-client-go/utils/errorutils"
+ "github.com/jfrog/jfrog-client-go/utils/io/fileutils"
+ "github.com/jfrog/jfrog-client-go/utils/log"
+ "golang.org/x/term"
)
// disallowUsingSavedPassword - Prevent changing username or url without changing the password.
@@ -145,7 +146,7 @@ func createRestoreFileFunc(filePath, backupFileName string) func() error {
}
return errorutils.CheckError(err)
}
- return errorutils.CheckErrorf(createRestoreErrorPrefix(filePath, backupPath) + err.Error())
+ return errors.New(createRestoreErrorPrefix(filePath, backupPath) + err.Error())
}
if err := fileutils.MoveFile(backupPath, filePath); err != nil {
diff --git a/utils/reposnapshot/snapshotmanager.go b/utils/reposnapshot/snapshotmanager.go
index 2e92c2868..99ccd4174 100644
--- a/utils/reposnapshot/snapshotmanager.go
+++ b/utils/reposnapshot/snapshotmanager.go
@@ -92,7 +92,7 @@ func (sm *RepoSnapshotManager) CalculateTransferredFilesAndSize() (totalFilesCou
// Returns the node corresponding to the directory in the provided relative path. Path should be provided without the repository name.
func (sm *RepoSnapshotManager) LookUpNode(relativePath string) (requestedNode *Node, err error) {
if relativePath == "" {
- return nil, errorutils.CheckErrorf(getLookUpNodeError(relativePath) + "- unexpected empty path provided to look up")
+ return nil, errorutils.CheckErrorf("%s- unexpected empty path provided to look up", getLookUpNodeError(relativePath))
}
relativePath = strings.TrimSuffix(relativePath, "/")
if relativePath == "." {
@@ -107,7 +107,7 @@ func (sm *RepoSnapshotManager) LookUpNode(relativePath string) (requestedNode *N
return nil, err
}
if requestedNode == nil {
- return nil, errorutils.CheckErrorf(getLookUpNodeError(relativePath))
+ return nil, errors.New(getLookUpNodeError(relativePath))
}
return
}