Skip to content

Commit 3dac034

Browse files
committed
Setup Command - configure Gradle
1 parent 134977b commit 3dac034

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

artifactory/commands/gradle/gradle.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package gradle
22

33
import (
4+
_ "embed"
45
"fmt"
56
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic"
67
commandsutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils"
@@ -15,9 +16,15 @@ import (
1516
"github.com/jfrog/jfrog-client-go/utils/errorutils"
1617
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
1718
"github.com/spf13/viper"
19+
"os"
1820
"path/filepath"
21+
"strings"
22+
"text/template"
1923
)
2024

25+
//go:embed resources/init.gradle
26+
var gradleInitScript string
27+
2128
const (
2229
usePlugin = "useplugin"
2330
useWrapper = "usewrapper"
@@ -231,6 +238,80 @@ func (gc *GradleCommand) setResult(result *commandsutils.Result) *GradleCommand
231238
return gc
232239
}
233240

241+
type InitScriptAuthConfig struct {
242+
ArtifactoryURL string
243+
ArtifactoryRepositoryKey string
244+
ArtifactoryUsername string
245+
ArtifactoryAccessToken string
246+
}
247+
248+
// GenerateInitScript generates a Gradle init script with the provided authentication configuration.
249+
func GenerateInitScript(config InitScriptAuthConfig) (string, error) {
250+
tmpl, err := template.New("gradleTemplate").Parse(gradleInitScript)
251+
if err != nil {
252+
return "", fmt.Errorf("failed to parse Gradle init script template: %s", err)
253+
}
254+
255+
var result strings.Builder
256+
err = tmpl.Execute(&result, config)
257+
if err != nil {
258+
return "", fmt.Errorf("failed to execute Gradle init script template: %s", err)
259+
}
260+
261+
return result.String(), nil
262+
}
263+
264+
// WriteInitScriptWithBackup write the Gradle init script to the Gradle user home directory.
265+
// If init scripts already exists, they will be backed up.
266+
// Allows the user to interactively decide whether to overwrite existing init scripts.
267+
func WriteInitScriptWithBackup(initScript string, interactUser bool) error {
268+
gradleHome := os.Getenv("GRADLE_USER_HOME")
269+
if gradleHome == "" {
270+
homeDir, err := os.UserHomeDir()
271+
if err != nil {
272+
return fmt.Errorf("failed to get user home directory: %w", err)
273+
}
274+
gradleHome = filepath.Join(homeDir, ".gradle")
275+
}
276+
initScripts, err := getExistingGradleInitScripts(gradleHome)
277+
if err != nil {
278+
return err
279+
}
280+
if len(initScripts) > 0 && interactUser {
281+
toContinue := coreutils.AskYesNo("Existing Gradle init scripts have been found. Do you want to overwrite them?", false)
282+
if !toContinue {
283+
return nil
284+
}
285+
}
286+
if err = backupExistingGradleInitScripts(initScripts); err != nil {
287+
return err
288+
}
289+
initScriptPath := filepath.Join(gradleHome, "init.gradle")
290+
if err = os.WriteFile(initScriptPath, []byte(initScript), 0644); err != nil {
291+
return fmt.Errorf("failed to write Gradle init script to %s: %w", initScriptPath, err)
292+
}
293+
return nil
294+
}
295+
296+
func getExistingGradleInitScripts(gradleHome string) ([]string, error) {
297+
gradleInitScripts, err := filepath.Glob(filepath.Join(gradleHome, "init.gradle*"))
298+
if err != nil {
299+
return nil, fmt.Errorf("failed while searching for Gradle init scripts: %w", err)
300+
}
301+
return gradleInitScripts, nil
302+
}
303+
304+
// backupExistingGradleInitScripts backup existing Gradle init scripts in the Gradle user home directory.
305+
func backupExistingGradleInitScripts(gradleInitScripts []string) error {
306+
for _, script := range gradleInitScripts {
307+
backupPath := script + ".bak"
308+
if err := os.Rename(script, backupPath); err != nil {
309+
return fmt.Errorf("failed to backup Gradle init script %s: %w", script, err)
310+
}
311+
}
312+
return nil
313+
}
314+
234315
func runGradle(vConfig *viper.Viper, tasks []string, deployableArtifactsFile string, configuration *build.BuildConfiguration, threads int, disableDeploy bool) error {
235316
buildInfoService := build.CreateBuildInfoService()
236317
buildName, err := configuration.GetBuildName()
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package gradle
2+
3+
import (
4+
"github.com/stretchr/testify/require"
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestGenerateInitScript(t *testing.T) {
13+
config := InitScriptAuthConfig{
14+
ArtifactoryURL: "http://example.com/artifactory",
15+
ArtifactoryRepositoryKey: "example-repo",
16+
ArtifactoryUsername: "user",
17+
ArtifactoryAccessToken: "token",
18+
}
19+
script, err := GenerateInitScript(config)
20+
assert.NoError(t, err)
21+
assert.Contains(t, script, "http://example.com/artifactory")
22+
assert.Contains(t, script, "example-repo")
23+
assert.Contains(t, script, "user")
24+
assert.Contains(t, script, "token")
25+
}
26+
27+
func TestWriteInitScriptWithBackup(t *testing.T) {
28+
tests := []struct {
29+
name string
30+
existingScript bool
31+
expectedBackup bool
32+
}{
33+
{name: "No existing init.gradle", existingScript: false, expectedBackup: false},
34+
{name: "Existing init.gradle", existingScript: true, expectedBackup: true},
35+
}
36+
37+
for _, tt := range tests {
38+
t.Run(tt.name, func(t *testing.T) {
39+
// Set up a temporary directory to act as the Gradle user home
40+
tempDir := t.TempDir()
41+
require.NoError(t, os.Setenv("GRADLE_USER_HOME", tempDir))
42+
defer func() {
43+
assert.NoError(t, os.Unsetenv("GRADLE_USER_HOME"))
44+
}()
45+
46+
// Create a dummy init script
47+
initScript := "init script content"
48+
49+
if tt.existingScript {
50+
existingScriptPath := filepath.Join(tempDir, "init.gradle")
51+
require.NoError(t, os.WriteFile(existingScriptPath, []byte("existing content"), 0644))
52+
}
53+
54+
// Call the function
55+
err := WriteInitScriptWithBackup(initScript, false)
56+
assert.NoError(t, err)
57+
58+
// Verify the init script was written to the correct location
59+
initScriptPath := filepath.Join(tempDir, "init.gradle")
60+
content, err := os.ReadFile(initScriptPath)
61+
assert.NoError(t, err)
62+
assert.Equal(t, initScript, string(content))
63+
64+
// Verify backup if there was an existing script
65+
if tt.expectedBackup {
66+
backupScriptPath := initScriptPath + ".bak"
67+
backupContent, err := os.ReadFile(backupScriptPath)
68+
assert.NoError(t, err)
69+
assert.Equal(t, "existing content", string(backupContent))
70+
}
71+
})
72+
}
73+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
def artifactoryUrl = '{{ .ArtifactoryURL }}'
2+
def artifactoryRepoKey = '{{ .ArtifactoryRepositoryKey }}'
3+
def artifactoryUsername = '{{ .ArtifactoryUsername }}'
4+
def artifactoryAccessToken = '{{ .ArtifactoryAccessToken }}'
5+
6+
gradle.settingsEvaluated { settings ->
7+
settings.pluginManagement {
8+
repositories {
9+
maven {
10+
url "${artifactoryUrl}/${artifactoryRepoKey}"
11+
credentials {
12+
username = artifactoryUsername
13+
password = artifactoryAccessToken
14+
}
15+
}
16+
gradlePluginPortal() // Fallback to Gradle Plugin Portal
17+
}
18+
}
19+
}
20+
21+
allprojects { project ->
22+
project.repositories {
23+
maven {
24+
url "${artifactoryUrl}/${artifactoryRepoKey}"
25+
credentials {
26+
username = artifactoryUsername
27+
password = artifactoryAccessToken
28+
}
29+
}
30+
}
31+
}

artifactory/commands/setup/setup.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package setup
22

33
import (
4+
_ "embed"
45
"fmt"
56
bidotnet "github.com/jfrog/build-info-go/build/utils/dotnet"
67
biutils "github.com/jfrog/build-info-go/utils"
78
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/dotnet"
89
gocommands "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/golang"
10+
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/gradle"
911
pythoncommands "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/python"
1012
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/repository"
1113
commandsutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils"
@@ -17,12 +19,14 @@ import (
1719
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
1820
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
1921
"github.com/jfrog/jfrog-client-go/artifactory/services"
22+
"github.com/jfrog/jfrog-client-go/auth"
2023
"github.com/jfrog/jfrog-client-go/utils/errorutils"
2124
"github.com/jfrog/jfrog-client-go/utils/log"
2225
"golang.org/x/exp/maps"
2326
"net/url"
2427
"os"
2528
"slices"
29+
"strings"
2630
)
2731

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

4852
project.Go: repository.Go,
53+
54+
project.Gradle: repository.Gradle,
4955
}
5056

5157
// SetupCommand configures registries and authentication for various package manager (npm, Yarn, Pip, Pipenv, Poetry, Go)
@@ -147,6 +153,8 @@ func (sc *SetupCommand) Run() (err error) {
147153
err = sc.configureDotnetNuget()
148154
case project.Docker, project.Podman:
149155
err = sc.configureContainer()
156+
case project.Gradle:
157+
err = sc.configureGradle()
150158
default:
151159
err = errorutils.CheckErrorf("unsupported package manager: %s", sc.packageManager)
152160
}
@@ -349,3 +357,25 @@ func (sc *SetupCommand) configureContainer() error {
349357
containerManagerType,
350358
)
351359
}
360+
361+
// configureGradle configures Gradle to use the specified Artifactory repository.
362+
func (sc *SetupCommand) configureGradle() error {
363+
password := sc.serverDetails.GetPassword()
364+
username := sc.serverDetails.GetUser()
365+
if sc.serverDetails.GetAccessToken() != "" {
366+
password = sc.serverDetails.GetAccessToken()
367+
username = auth.ExtractUsernameFromAccessToken(password)
368+
}
369+
initScriptAuthConfig := gradle.InitScriptAuthConfig{
370+
ArtifactoryURL: strings.TrimSuffix(sc.serverDetails.GetArtifactoryUrl(), "/"),
371+
ArtifactoryRepositoryKey: sc.repoName,
372+
ArtifactoryAccessToken: password,
373+
ArtifactoryUsername: username,
374+
}
375+
initScript, err := gradle.GenerateInitScript(initScriptAuthConfig)
376+
if err != nil {
377+
return err
378+
}
379+
380+
return gradle.WriteInitScriptWithBackup(initScript, true)
381+
}

0 commit comments

Comments
 (0)