Skip to content
Open
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
24 changes: 24 additions & 0 deletions artifactory/commands/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,36 @@ func (sc *SetupCommand) SetProjectKey(projectKey string) *SetupCommand {
return sc
}

// validateRepoExistsFn is overridable so tests can stub out the network call.
var validateRepoExistsFn = validateRepoExists

// validateRepoExists checks that the repository explicitly requested via --repo exists in Artifactory,
// so that a bad repo name fails fast with a clear error instead of surfacing later as a confusing
// package-manager-specific failure.
func validateRepoExists(sc *SetupCommand) error {
serviceDetails, err := sc.serverDetails.CreateArtAuthConfig()
if err != nil {
return err
}
return utils.ValidateRepoExists(sc.repoName, serviceDetails)
}

// Run executes the configuration method corresponding to the package manager specified for the command.
func (sc *SetupCommand) Run() (err error) {
if !IsSupportedPackageManager(sc.packageManager) {
return errorutils.CheckErrorf("unsupported package manager: %s", sc.packageManager)
}

// Validate the explicitly provided repository up front. This runs inside Run() (rather than in the
// CLI layer before Run() is invoked) so that every return path from here on is covered by the single
// usage-report call site in commands.Exec/ExecWithPackageManager - no separate reporting is needed
// for this failure.
if sc.repoName != "" {
if err = validateRepoExistsFn(sc); err != nil {
return err
}
}

// If the repository name is not provided, and the package manager is not Docker or Podman, prompt the user to select a repository.
// Docker and Podman do not require a repository name as they authenticate directly with the platform and require the repository name as part of the image name.
if sc.repoName == "" && sc.packageManager != project.Docker && sc.packageManager != project.Podman {
Expand Down
28 changes: 28 additions & 0 deletions artifactory/commands/setup/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-core/v2/utils/ioutils"
"github.com/jfrog/jfrog-client-go/auth"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -29,6 +30,18 @@ const (
goProxyEnv = "GOPROXY"
)

// TestMain stubs out validateRepoExistsFn for every test in this package, since
// createTestSetupCommand points serverDetails at a fake host (acme.jfrog.io)
// that can't answer a real repo-existence check. Tests that specifically want
// to exercise validateRepoExists restore the real function for their own scope.
func TestMain(m *testing.M) {
realValidateRepoExistsFn := validateRepoExistsFn
validateRepoExistsFn = func(*SetupCommand) error { return nil }
code := m.Run()
validateRepoExistsFn = realValidateRepoExistsFn
os.Exit(code)
}

// testCredential returns a fake JWT-like string for testing. NOT a real credential.
func testCredential() string {
// Construct fake JWT parts separately to avoid secret detection
Expand Down Expand Up @@ -67,6 +80,21 @@ func createTestSetupCommand(packageManager project.ProjectType) *SetupCommand {
return cmd
}

// TestSetupCommand_RepoValidationFailure verifies that Run() returns the repo-validation
// error immediately, before attempting any package-manager-specific configuration.
func TestSetupCommand_RepoValidationFailure(t *testing.T) {
realValidateRepoExistsFn := validateRepoExistsFn
defer func() { validateRepoExistsFn = realValidateRepoExistsFn }()

expectedErr := errorutils.CheckErrorf("the repository 'test-repo' does not exist")
validateRepoExistsFn = func(*SetupCommand) error { return expectedErr }

cmd := createTestSetupCommand(project.Npm)
err := cmd.Run()
require.Error(t, err)
assert.Equal(t, expectedErr, err)
}

func TestSetupCommand_NotSupported(t *testing.T) {
notSupportedLoginCmd := createTestSetupCommand(project.Cocoapods)
err := notSupportedLoginCmd.Run()
Expand Down
Loading