Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't clean sub directories if Tech not supporting Multi Module #255

Merged
merged 3 commits into from
Jan 20, 2025
Merged
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
22 changes: 20 additions & 2 deletions utils/techutils/techutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"regexp"
"strconv"
"strings"

"golang.org/x/exp/maps"
Expand All @@ -21,6 +22,8 @@ import (
"github.com/jfrog/jfrog-client-go/utils/log"
)

const JfrogCleanTechSubModulesEnv = "JFROG_CLI_CLEAN_SUB_MODULES"

type Technology string

const (
Expand Down Expand Up @@ -582,11 +585,26 @@ func getTechInformationFromWorkingDir(tech Technology, workingDirectoryToIndicat
techWorkingDirs[wd] = descriptorsAtWd
}
}
// Don't allow working directory if sub directory already exists as key for the same technology
techWorkingDirs = cleanSubDirectories(techWorkingDirs)
if tech == Maven || tech == Gradle || tech == Nuget || tech == Dotnet || shouldCleanSubModulesInUnsupportedTechs() {
// Multi Module - Don't allow working directory if sub directory already exists as key for the same technology
techWorkingDirs = cleanSubDirectories(techWorkingDirs)
}
return
}

func shouldCleanSubModulesInUnsupportedTechs() bool {
// Turn on clean sub modules for tech that we do not support multi-module projects if requested
shouldCleanEnvValRaw := os.Getenv(JfrogCleanTechSubModulesEnv)
if shouldCleanEnvValRaw == "" {
return false
}
shouldClean, e := strconv.ParseBool(shouldCleanEnvValRaw)
if e != nil {
log.Warn(fmt.Sprintf("Failed to parse %s: %s", JfrogCleanTechSubModulesEnv, e.Error()))
}
return shouldClean
}

func isTechExcludedInWorkingDir(tech Technology, wd string, excludedTechAtWorkingDir map[string][]Technology) bool {
if excludedTechs, exist := excludedTechAtWorkingDir[wd]; exist {
for _, excludedTech := range excludedTechs {
Expand Down
56 changes: 48 additions & 8 deletions utils/techutils/techutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,42 @@ func createTempDirWithPyProjectToml(t *testing.T, tech Technology) (tmpDir strin
return
}

func TestCleanSubDirectoriesForTechUnsupportedMulti(t *testing.T) {
workingDirectoryToIndicators := map[string][]string{
"project-root": {filepath.Join("project-root", "package.json")},
filepath.Join("project-root", "directory"): {filepath.Join("project-root", "directory", "package.json")},
}

testCases := []struct {
name string
cleanSubDirectories bool
expected map[string][]string
}{
{
name: "cleanSubDirectories is true",
cleanSubDirectories: true,
expected: map[string][]string{"project-root": {filepath.Join("project-root", "package.json"), filepath.Join("project-root", "directory", "package.json")}},
},
{
name: "cleanSubDirectories is false",
expected: map[string][]string{
"project-root": {filepath.Join("project-root", "package.json")},
filepath.Join("project-root", "directory"): {filepath.Join("project-root", "directory", "package.json")},
},
},
}

for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
if test.cleanSubDirectories {
unsetEnv := clientTests.SetEnvWithCallbackAndAssert(t, JfrogCleanTechSubModulesEnv, "TRUE")
defer unsetEnv()
}
assertTechInformation(t, Npm, workingDirectoryToIndicators, map[string][]Technology{}, map[Technology][]string{}, false, test.expected)
})
}
}

func TestGetTechInformationFromWorkingDir(t *testing.T) {
projectDir, callback := createTempDirWithPyProjectToml(t, Pip)
defer callback()
Expand Down Expand Up @@ -636,18 +672,22 @@ func TestGetTechInformationFromWorkingDir(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
techInformation, err := getTechInformationFromWorkingDir(test.tech, workingDirectoryToIndicators, excludedTechAtWorkingDir, test.requestedDescriptors, test.techProvidedByUser)
assert.NoError(t, err)
expectedKeys := maps.Keys(test.expected)
actualKeys := maps.Keys(techInformation)
assert.ElementsMatch(t, expectedKeys, actualKeys, fmt.Sprintf("expected: %v, actual: %v", expectedKeys, actualKeys))
for key, value := range test.expected {
assert.ElementsMatch(t, value, techInformation[key], fmt.Sprintf("expected: %v, actual: %v", value, techInformation[key]))
}
assertTechInformation(t, test.tech, workingDirectoryToIndicators, excludedTechAtWorkingDir, test.requestedDescriptors, test.techProvidedByUser, test.expected)
})
}
}

func assertTechInformation(t *testing.T, tech Technology, workingDirectoryToIndicators map[string][]string, excludedTechAtWorkingDir map[string][]Technology, requestedDescriptors map[Technology][]string, techProvidedByUser bool, expected map[string][]string) {
techInformation, err := getTechInformationFromWorkingDir(tech, workingDirectoryToIndicators, excludedTechAtWorkingDir, requestedDescriptors, techProvidedByUser)
assert.NoError(t, err)
expectedKeys := maps.Keys(expected)
actualKeys := maps.Keys(techInformation)
assert.ElementsMatch(t, expectedKeys, actualKeys, fmt.Sprintf("expected: %v, actual: %v", expectedKeys, actualKeys))
for key, value := range expected {
assert.ElementsMatch(t, value, techInformation[key], fmt.Sprintf("expected: %v, actual: %v", value, techInformation[key]))
}
}

func TestTechnologyToLanguage(t *testing.T) {
tests := []struct {
name string
Expand Down
Loading