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
56 changes: 56 additions & 0 deletions artifactory/commands/gradle/gradle.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gradle

import (
_ "embed"
"fmt"
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic"
commandsutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils"
Expand All @@ -15,12 +16,21 @@ import (
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/spf13/viper"
"os"
"path/filepath"
"strings"
"text/template"
)

//go:embed resources/jfrog.init.gradle
var gradleInitScript string

const (
usePlugin = "useplugin"
useWrapper = "usewrapper"

UserHomeEnv = "GRADLE_USER_HOME"
InitScriptName = "jfrog.init.gradle"
)

type GradleCommand struct {
Expand Down Expand Up @@ -231,6 +241,52 @@ func (gc *GradleCommand) setResult(result *commandsutils.Result) *GradleCommand
return gc
}

type InitScriptAuthConfig struct {
ArtifactoryURL string
ArtifactoryRepositoryKey string
ArtifactoryUsername string
ArtifactoryAccessToken string
}

// GenerateInitScript generates a Gradle init script with the provided authentication configuration.
func GenerateInitScript(config InitScriptAuthConfig) (string, error) {
tmpl, err := template.New("gradleTemplate").Parse(gradleInitScript)
if err != nil {
return "", fmt.Errorf("failed to parse Gradle init script template: %s", err)
}

var result strings.Builder
err = tmpl.Execute(&result, config)
if err != nil {
return "", fmt.Errorf("failed to execute Gradle init script template: %s", err)
}

return result.String(), nil
}

// WriteInitScript writes the Gradle init script to the Gradle user home `init.d` directory,
// which stores initialization scripts.
func WriteInitScript(initScript string) error {
gradleHome := os.Getenv(UserHomeEnv)
if gradleHome == "" {
homeDir, err := os.UserHomeDir()
if err != nil {
return fmt.Errorf("failed to get user home directory: %w", err)
}
gradleHome = filepath.Join(homeDir, ".gradle")
}

initScriptsDir := filepath.Join(gradleHome, "init.d")
if err := os.MkdirAll(initScriptsDir, 0755); err != nil {
return fmt.Errorf("failed to create Gradle init.d directory: %w", err)
}
jfrogInitScriptPath := filepath.Join(initScriptsDir, InitScriptName)
if err := os.WriteFile(jfrogInitScriptPath, []byte(initScript), 0644); err != nil {
return fmt.Errorf("failed to write Gradle init script to %s: %w", jfrogInitScriptPath, err)
}
return nil
}

func runGradle(vConfig *viper.Viper, tasks []string, deployableArtifactsFile string, configuration *build.BuildConfiguration, threads int, disableDeploy bool) error {
buildInfoService := build.CreateBuildInfoService()
buildName, err := configuration.GetBuildName()
Expand Down
41 changes: 41 additions & 0 deletions artifactory/commands/gradle/gradle_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package gradle

import (
"os"
"path/filepath"
"testing"

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

func TestGenerateInitScript(t *testing.T) {
config := InitScriptAuthConfig{
ArtifactoryURL: "http://example.com/artifactory",
ArtifactoryRepositoryKey: "example-repo",
ArtifactoryUsername: "user",
ArtifactoryAccessToken: "token",
}
script, err := GenerateInitScript(config)
assert.NoError(t, err)
assert.Contains(t, script, "http://example.com/artifactory")
assert.Contains(t, script, "example-repo")
assert.Contains(t, script, "user")
assert.Contains(t, script, "token")
}

func TestWriteInitScript(t *testing.T) {
// Set up a temporary directory for testing
tempDir := t.TempDir()
t.Setenv(UserHomeEnv, tempDir)

initScript := "test init script content"

err := WriteInitScript(initScript)
assert.NoError(t, err)

// Verify the init script was written to the correct location
expectedPath := filepath.Join(tempDir, "init.d", InitScriptName)
content, err := os.ReadFile(expectedPath)
assert.NoError(t, err)
assert.Equal(t, initScript, string(content))
}
31 changes: 31 additions & 0 deletions artifactory/commands/gradle/resources/jfrog.init.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
def artifactoryUrl = '{{ .ArtifactoryURL }}'
def artifactoryRepoKey = '{{ .ArtifactoryRepositoryKey }}'
def artifactoryUsername = '{{ .ArtifactoryUsername }}'
def artifactoryAccessToken = '{{ .ArtifactoryAccessToken }}'

gradle.settingsEvaluated { settings ->
settings.pluginManagement {
repositories {
maven {
url "${artifactoryUrl}/${artifactoryRepoKey}"
credentials {
username = artifactoryUsername
password = artifactoryAccessToken
}
}
gradlePluginPortal() // Fallback to Gradle Plugin Portal
}
}
}

allprojects { project ->
project.repositories {
maven {
url "${artifactoryUrl}/${artifactoryRepoKey}"
credentials {
username = artifactoryUsername
password = artifactoryAccessToken
}
}
}
}
30 changes: 30 additions & 0 deletions artifactory/commands/setup/setup.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package setup

import (
_ "embed"
"fmt"
bidotnet "github.com/jfrog/build-info-go/build/utils/dotnet"
biutils "github.com/jfrog/build-info-go/utils"
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/dotnet"
gocommands "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/golang"
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/gradle"
pythoncommands "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/python"
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/repository"
commandsutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils"
Expand All @@ -17,12 +19,14 @@ import (
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-client-go/artifactory/services"
"github.com/jfrog/jfrog-client-go/auth"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"golang.org/x/exp/maps"
"net/url"
"os"
"slices"
"strings"
)

// packageManagerToRepositoryPackageType maps project types to corresponding Artifactory repository package types.
Expand All @@ -46,6 +50,8 @@ var packageManagerToRepositoryPackageType = map[project.ProjectType]string{
project.Podman: repository.Docker,

project.Go: repository.Go,

project.Gradle: repository.Gradle,
}

// SetupCommand configures registries and authentication for various package manager (npm, Yarn, Pip, Pipenv, Poetry, Go)
Expand Down Expand Up @@ -147,6 +153,8 @@ func (sc *SetupCommand) Run() (err error) {
err = sc.configureDotnetNuget()
case project.Docker, project.Podman:
err = sc.configureContainer()
case project.Gradle:
err = sc.configureGradle()
default:
err = errorutils.CheckErrorf("unsupported package manager: %s", sc.packageManager)
}
Expand Down Expand Up @@ -349,3 +357,25 @@ func (sc *SetupCommand) configureContainer() error {
containerManagerType,
)
}

// configureGradle configures Gradle to use the specified Artifactory repository.
func (sc *SetupCommand) configureGradle() error {
password := sc.serverDetails.GetPassword()
username := sc.serverDetails.GetUser()
if sc.serverDetails.GetAccessToken() != "" {
password = sc.serverDetails.GetAccessToken()
username = auth.ExtractUsernameFromAccessToken(password)
}
initScriptAuthConfig := gradle.InitScriptAuthConfig{
ArtifactoryURL: strings.TrimSuffix(sc.serverDetails.GetArtifactoryUrl(), "/"),
ArtifactoryRepositoryKey: sc.repoName,
ArtifactoryAccessToken: password,
ArtifactoryUsername: username,
}
initScript, err := gradle.GenerateInitScript(initScriptAuthConfig)
if err != nil {
return err
}

return gradle.WriteInitScript(initScript)
}
36 changes: 36 additions & 0 deletions artifactory/commands/setup/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package setup
import (
"fmt"
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/dotnet"
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/gradle"
cmdutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils"
"github.com/jfrog/jfrog-cli-core/v2/common/project"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
Expand Down Expand Up @@ -321,6 +322,41 @@ func TestSetupCommand_Go(t *testing.T) {
}
}

func TestSetupCommand_Gradle(t *testing.T) {
testGradleUserHome := t.TempDir()
t.Setenv(gradle.UserHomeEnv, testGradleUserHome)
gradleLoginCmd := createTestSetupCommand(project.Gradle)

expectedInitScriptPath := filepath.Join(testGradleUserHome, "init.d", gradle.InitScriptName)
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
// Set up server details for the current test case's authentication type.
gradleLoginCmd.serverDetails.SetUser(testCase.user)
gradleLoginCmd.serverDetails.SetPassword(testCase.password)
gradleLoginCmd.serverDetails.SetAccessToken(testCase.accessToken)

// Run the login command and ensure no errors occur.
require.NoError(t, gradleLoginCmd.Run())

// Get the content of the gradle init script.
contentBytes, err := os.ReadFile(expectedInitScriptPath)
require.NoError(t, err)
content := string(contentBytes)

assert.Contains(t, content, "artifactoryUrl = 'https://acme.jfrog.io/artifactory'")
if testCase.accessToken != "" {
// Validate token-based authentication.
assert.Contains(t, content, fmt.Sprintf("def artifactoryUsername = '%s'", auth.ExtractUsernameFromAccessToken(testCase.accessToken)))
assert.Contains(t, content, fmt.Sprintf("def artifactoryAccessToken = '%s'", testCase.accessToken))
} else {
// Validate basic authentication with user and password.
assert.Contains(t, content, fmt.Sprintf("def artifactoryUsername = '%s'", testCase.user))
assert.Contains(t, content, fmt.Sprintf("def artifactoryAccessToken = '%s'", testCase.password))
}
})
}
}

func TestBuildToolLoginCommand_configureNuget(t *testing.T) {
testBuildToolLoginCommandConfigureDotnetNuget(t, project.Nuget)
}
Expand Down
Loading