diff --git a/.github/workflows/event.yml b/.github/workflows/event.yml index 601aa66568c..6479128b97f 100644 --- a/.github/workflows/event.yml +++ b/.github/workflows/event.yml @@ -12,7 +12,7 @@ on: # entirely of github actions won't trigger this action. workflow_run: types: [completed] - workflows: ["cli-ci", "templates-ci", "vscode-ci"] + workflows: ["cli-ci"] permissions: {} diff --git a/.github/workflows/go-test-for-sjad-branch.yml b/.github/workflows/go-test-for-sjad-branch.yml index bad4b06e15e..c44aefe5b36 100644 --- a/.github/workflows/go-test-for-sjad-branch.yml +++ b/.github/workflows/go-test-for-sjad-branch.yml @@ -18,6 +18,14 @@ jobs: with: go-version: 1.23.1 + - name: Cache Maven repository + uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Cache Go modules uses: actions/cache@v4 with: @@ -31,4 +39,4 @@ jobs: - name: Run tests run: | cd ./cli/azd - go test $(go list ./... | grep -v github.com/azure/azure-dev/cli/azd/test/functional) -cover \ No newline at end of file + go test $(go list ./... | grep -v github.com/azure/azure-dev/cli/azd/test/functional) -cover -v diff --git a/cli/azd/internal/appdetect/pom.go b/cli/azd/internal/appdetect/pom.go index 65acc0ae68f..8745c7e50b6 100644 --- a/cli/azd/internal/appdetect/pom.go +++ b/cli/azd/internal/appdetect/pom.go @@ -214,8 +214,7 @@ func makePathFitCurrentOs(filePath string) string { func absorbInformationFromParentInRemoteMavenRepository(pom *pom) { p := pom.Parent - parent, err := getSimulatedEffectivePomFromRemoteMavenRepository( - p.GroupId, p.ArtifactId, p.Version) + parent, err := getSimulatedEffectivePomFromMavenRepository(p.GroupId, p.ArtifactId, p.Version) if err != nil { slog.InfoContext(context.TODO(), "Skip absorb parent from remote maven repository.", "ArtifactId", pom.ArtifactId, "err", err) @@ -269,7 +268,7 @@ func absorbImportedBomInDependencyManagement(pom *pom) { if dep.Scope != "import" { continue } - toBeAbsorbedPom, err := getSimulatedEffectivePomFromRemoteMavenRepository( + toBeAbsorbedPom, err := getSimulatedEffectivePomFromMavenRepository( dep.GroupId, dep.ArtifactId, dep.Version) if err != nil { slog.InfoContext(context.TODO(), "Skip absorb imported bom from remote maven repository.", @@ -294,12 +293,52 @@ func absorbDependencyManagement(pom *pom, dependencyManagementMap map[string]str } } +func getSimulatedEffectivePomFromMavenRepository(groupId string, artifactId string, version string) (pom, error) { + result, err := getSimulatedEffectivePomFromLocalMavenRepository(groupId, artifactId, version) + if err == nil { + return result, nil + } + return getSimulatedEffectivePomFromRemoteMavenRepository(groupId, artifactId, version) +} + +func getSimulatedEffectivePomFromLocalMavenRepository(groupId string, artifactId string, version string) (pom, error) { + pomPath, err := getPathInLocalMavenRepository(groupId, artifactId, version) + if err != nil { + return pom{}, err + } + return createSimulatedEffectivePom(pomPath) +} + func getSimulatedEffectivePomFromRemoteMavenRepository(groupId string, artifactId string, version string) (pom, error) { requestUrl := getRemoteMavenRepositoryUrl(groupId, artifactId, version) bytes, err := internal.Download(requestUrl) if err != nil { return pom{}, err } + savePomFileToLocalMavenRepository(groupId, artifactId, version, bytes) + return createSimulatedEffectivePomByPomFileBytes(bytes) +} + +func savePomFileToLocalMavenRepository(groupId string, artifactId string, version string, bytes []byte) { + pomPath, err := getPathInLocalMavenRepository(groupId, artifactId, version) + if err != nil { + slog.DebugContext(context.TODO(), "Failed to get pomPath.", + "groupId", groupId, "artifactId", artifactId, "version", version, "err", err) + return + } + dir := filepath.Dir(pomPath) + if err := os.MkdirAll(dir, 0755); err != nil { + slog.DebugContext(context.TODO(), "Failed to create pomPath.", + "groupId", groupId, "artifactId", artifactId, "version", version, "err", err) + return + } + err = os.WriteFile(pomPath, bytes, 0600) + if err != nil { + slog.DebugContext(context.TODO(), "Failed to write file.", "pomPath", pomPath, "err", err) + } +} + +func createSimulatedEffectivePomByPomFileBytes(bytes []byte) (pom, error) { var result pom if err := xml.Unmarshal(bytes, &result); err != nil { return pom{}, fmt.Errorf("parsing xml: %w", err) @@ -313,8 +352,22 @@ func getSimulatedEffectivePomFromRemoteMavenRepository(groupId string, artifactI return result, nil } +func getPathInLocalMavenRepository(groupId string, artifactId string, version string) (string, error) { + homeDir, err := os.UserHomeDir() + if err != nil { + return "", err + } + relativePath := makePathFitCurrentOs(relativePathInMavenRepository(groupId, artifactId, version)) + return filepath.Join(homeDir, ".m2", "repository", relativePath), nil +} + func getRemoteMavenRepositoryUrl(groupId string, artifactId string, version string) string { - return fmt.Sprintf("https://repo.maven.apache.org/maven2/%s/%s/%s/%s-%s.pom", + return fmt.Sprintf("https://repo.maven.apache.org/maven2/%s", + relativePathInMavenRepository(groupId, artifactId, version)) +} + +func relativePathInMavenRepository(groupId string, artifactId string, version string) string { + return fmt.Sprintf("%s/%s/%s/%s-%s.pom", strings.ReplaceAll(groupId, ".", "/"), artifactId, version, artifactId, version) } diff --git a/cli/azd/internal/appdetect/pom_test.go b/cli/azd/internal/appdetect/pom_test.go index 70f79d9c288..ebcafd2a9e9 100644 --- a/cli/azd/internal/appdetect/pom_test.go +++ b/cli/azd/internal/appdetect/pom_test.go @@ -2,7 +2,9 @@ package appdetect import ( "context" + "log/slog" "os" + os_exec "os/exec" "path/filepath" "reflect" "strings" @@ -13,6 +15,12 @@ import ( ) func TestCreateEffectivePom(t *testing.T) { + path, err := os_exec.LookPath("java") + if err != nil { + t.Skip("Skip TestCreateEffectivePom because java command doesn't exist.") + } else { + slog.Info("Java command found.", "path", path) + } tests := []struct { name string testPoms []testPom diff --git a/cli/azd/internal/download_util.go b/cli/azd/internal/download_util.go index c1a1d5da4bf..753e873b543 100644 --- a/cli/azd/internal/download_util.go +++ b/cli/azd/internal/download_util.go @@ -1,9 +1,10 @@ package internal import ( + "context" "fmt" "io" - "log" + "log/slog" "net/http" "net/url" "time" @@ -23,6 +24,7 @@ func Download(requestUrl string) ([]byte, error) { Proxy: http.ProxyFromEnvironment, }, } + slog.DebugContext(context.TODO(), "Downloading file.", "requestUrl", requestUrl, "err", err) resp, err := client.Get(requestUrl) if err != nil { return nil, err @@ -30,7 +32,7 @@ func Download(requestUrl string) ([]byte, error) { defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { - log.Println("failed to close http response body") + slog.DebugContext(context.TODO(), "Failed to close http body.", "requestUrl", requestUrl, "err", err) } }(resp.Body) return io.ReadAll(resp.Body)