From f62f7adaf3e6ff5fab07e22dfe6226c43d2be11c Mon Sep 17 00:00:00 2001 From: Wei Lim Date: Mon, 12 Jan 2026 15:23:07 -0800 Subject: [PATCH 1/2] fix graphsdk test taking 3 minutes --- cli/azd/test/mocks/mockgraphsdk/mocks.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/azd/test/mocks/mockgraphsdk/mocks.go b/cli/azd/test/mocks/mockgraphsdk/mocks.go index bbfd1f24583..2f4c34d40aa 100644 --- a/cli/azd/test/mocks/mockgraphsdk/mocks.go +++ b/cli/azd/test/mocks/mockgraphsdk/mocks.go @@ -19,7 +19,11 @@ import ( func CreateGraphClient(mockContext *mocks.MockContext) (*graphsdk.GraphClient, error) { clientOptions := &azcore.ClientOptions{ Transport: mockContext.HttpClient, - Retry: policy.RetryOptions{RetryDelay: -1}, + Retry: policy.RetryOptions{ + MaxRetries: -1, + MaxRetryDelay: -1, + RetryDelay: -1, + }, } return graphsdk.NewGraphClient(mockContext.Credentials, clientOptions) } From 8e9c00de8c438f44b1ffe0218ef9b4172168cb9b Mon Sep 17 00:00:00 2001 From: Wei Lim Date: Tue, 13 Jan 2026 11:06:21 -0800 Subject: [PATCH 2/2] Update appdetect tests --- cli/azd/internal/appdetect/appdetect_test.go | 8 +- cli/azd/internal/appdetect/java_test.go | 454 ------------------ .../java-multimodules/application/pom.xml | 42 +- .../java-multimodules/library/pom.xml | 20 +- .../{module1 => module}/pom.xml | 4 +- .../java-multimodules/module2/pom.xml | 32 -- .../module2/submodule1/pom.xml | 28 -- .../java-multimodules/notmodule/pom.xml | 17 - .../testdata/java-multimodules/pom.xml | 3 +- eng/scripts/Set-CliBuildVariables.ps1 | 2 +- 10 files changed, 15 insertions(+), 595 deletions(-) delete mode 100644 cli/azd/internal/appdetect/java_test.go rename cli/azd/internal/appdetect/testdata/java-multimodules/{module1 => module}/pom.xml (93%) delete mode 100644 cli/azd/internal/appdetect/testdata/java-multimodules/module2/pom.xml delete mode 100644 cli/azd/internal/appdetect/testdata/java-multimodules/module2/submodule1/pom.xml diff --git a/cli/azd/internal/appdetect/appdetect_test.go b/cli/azd/internal/appdetect/appdetect_test.go index 2182293a5ba..16faa53eda0 100644 --- a/cli/azd/internal/appdetect/appdetect_test.go +++ b/cli/azd/internal/appdetect/appdetect_test.go @@ -62,16 +62,10 @@ func TestDetect(t *testing.T) { }, { Language: Java, - Path: "java-multimodules/module1", + Path: "java-multimodules/module", RootPath: filepath.Join(dir, "java-multimodules"), DetectionRule: "Inferred by presence of: pom.xml", }, - { - Language: Java, - Path: "java-multimodules/module2/submodule1", - RootPath: filepath.Join(dir, "java-multimodules"), // point to the root, not direct parent - DetectionRule: "Inferred by presence of: pom.xml", - }, { Language: Java, Path: "java-multimodules/notmodule", diff --git a/cli/azd/internal/appdetect/java_test.go b/cli/azd/internal/appdetect/java_test.go deleted file mode 100644 index c448a2bcfa4..00000000000 --- a/cli/azd/internal/appdetect/java_test.go +++ /dev/null @@ -1,454 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package appdetect - -import ( - "context" - "fmt" - "log/slog" - "os" - osexec "os/exec" - "path/filepath" - "strings" - "testing" - "time" - - "github.com/azure/azure-dev/cli/azd/pkg/exec" - "github.com/azure/azure-dev/cli/azd/pkg/tools/maven" - "github.com/sethvargo/go-retry" -) - -func TestToMavenProject(t *testing.T) { - // Skip in short mode since this test requires network access to Maven Central - if testing.Short() { - t.Skip("Skipping Maven network-dependent test in short mode") - } - - path, err := osexec.LookPath("java") - if err != nil { - t.Skip("Skip readMavenProject because java command doesn't exist.") - } else { - slog.Info("Java command found.", "path", path) - } - path, err = osexec.LookPath("mvn") - if err != nil { - t.Skip("Skip readMavenProject because mvn command doesn't exist.") - } else { - slog.Info("Java command found.", "path", path) - } - tests := []struct { - name string - testPoms []testPom - expected []dependency - }{ - { - name: "Test with two dependencies", - testPoms: []testPom{ - { - pomFilePath: "pom.xml", - pomContentString: ` - - 4.0.0 - com.example - example-project - 1.0.0 - - - org.springframework - spring-core - 5.3.8 - compile - - - junit - junit - 4.13.2 - test - - - - `, - }, - }, - expected: []dependency{ - { - GroupId: "org.springframework", - ArtifactId: "spring-core", - Version: "5.3.8", - Scope: "compile", - }, - { - GroupId: "junit", - ArtifactId: "junit", - Version: "4.13.2", - Scope: "test", - }, - }, - }, - { - name: "Test with no dependencies", - testPoms: []testPom{ - { - pomFilePath: "pom.xml", - pomContentString: ` - - 4.0.0 - com.example - example-project - 1.0.0 - - - - `, - }, - }, - expected: []dependency{}, - }, - { - name: "Test with one dependency which version is decided by dependencyManagement", - testPoms: []testPom{ - { - pomFilePath: "pom.xml", - pomContentString: ` - - 4.0.0 - com.example - example-project - 1.0.0 - - - org.slf4j - slf4j-api - - - - - - org.springframework.boot - spring-boot-dependencies - 3.0.0 - pom - import - - - - - `, - }, - }, - expected: []dependency{ - { - GroupId: "org.slf4j", - ArtifactId: "slf4j-api", - Version: "2.0.4", - Scope: "compile", - }, - }, - }, - { - name: "Test with one dependency which version is decided by parent", - testPoms: []testPom{ - { - pomFilePath: "pom.xml", - pomContentString: ` - - - org.springframework.boot - spring-boot-starter-parent - 3.0.0 - - - 4.0.0 - com.example - example-project - 1.0.0 - - - org.slf4j - slf4j-api - - - - `, - }, - }, - expected: []dependency{ - { - GroupId: "org.slf4j", - ArtifactId: "slf4j-api", - Version: "2.0.4", - Scope: "compile", - }, - }, - }, - { - name: "Test pom with multi modules: root pom build first when run help:effective-pom", - testPoms: []testPom{ - { - pomFilePath: "pom.xml", - pomContentString: ` - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.7 - - org.springframework - gs-multi-module - 0.1.0 - pom - - library - application - - - `, - }, - { - pomFilePath: filepath.Join("application", "pom.xml"), - pomContentString: ` - - 4.0.0 - - org.springframework - gs-multi-module - 0.1.0 - - com.example - application - 0.0.1-SNAPSHOT - application - Demo project for Spring Boot - - - org.slf4j - slf4j-api - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - `, - }, - { - pomFilePath: filepath.Join("library", "pom.xml"), - pomContentString: ` - - 4.0.0 - - org.springframework - gs-multi-module - 0.1.0 - - com.example - library - 0.0.1-SNAPSHOT - library - Demo project for Spring Boot - - - org.springframework.boot - spring-boot - - - org.springframework.boot - spring-boot-starter-test - test - - - - `, - }, - }, - expected: []dependency{}, - }, - { - name: "Test pom with multi modules: root pom build last when run help:effective-pom", - testPoms: []testPom{ - { - pomFilePath: "pom.xml", - pomContentString: ` - - 4.0.0 - org.springframework - gs-multi-module - 0.1.0 - pom - - library - application - - - `, - }, - { - pomFilePath: filepath.Join("application", "pom.xml"), - pomContentString: ` - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.3.0 - - - com.example - application - 0.0.1-SNAPSHOT - application - Demo project for Spring Boot - - - org.slf4j - slf4j-api - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - `, - }, - { - pomFilePath: filepath.Join("library", "pom.xml"), - pomContentString: ` - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.2 - - - com.example - library - 0.0.1-SNAPSHOT - library - Demo project for Spring Boot - - - org.springframework.boot - spring-boot - - - org.springframework.boot - spring-boot-starter-test - test - - - - `, - }, - }, - expected: []dependency{}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - workingDir, err := prepareTestPomFiles(tt.testPoms) - if err != nil { - t.Fatalf("%v", err) - } - testPom := tt.testPoms[0] - pomFilePath := filepath.Join(workingDir, testPom.pomFilePath) - - // Use a timeout context to prevent hanging on network issues - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - - // Use retry logic for Maven operations due to potential network issues - mavenProject, err := readMavenProjectWithRetry(ctx, maven.NewCli(exec.NewCommandRunner(nil)), - pomFilePath) - if err != nil { - t.Fatalf("readMavenProject failed: %v", err) - } - - if len(mavenProject.Dependencies) != len(tt.expected) { - t.Fatalf("Expected: %d\nActual: %d", len(tt.expected), len(mavenProject.Dependencies)) - } - - for i, dep := range mavenProject.Dependencies { - if dep != tt.expected[i] { - t.Errorf("\nExpected: %s\nActual: %s", tt.expected[i], dep) - } - } - }) - } -} - -// readMavenProjectWithRetry wraps readMavenProject with retry logic to handle network issues -func readMavenProjectWithRetry(ctx context.Context, mvnCli *maven.Cli, filePath string) (*mavenProject, error) { - var mavenProject *mavenProject - var lastErr error - - err := retry.Do( - ctx, - retry.WithMaxRetries(3, retry.NewExponential(1*time.Second)), - func(ctx context.Context) error { - result, err := readMavenProject(ctx, mvnCli, filePath) - if err != nil { - // Check if error is likely network-related - errStr := strings.ToLower(err.Error()) - if strings.Contains(errStr, "connection") || - strings.Contains(errStr, "timeout") || - strings.Contains(errStr, "network") || - strings.Contains(errStr, "unknown host") || - strings.Contains(errStr, "could not resolve") || - strings.Contains(errStr, "transfer failed") { - lastErr = err - return retry.RetryableError(err) - } - // For non-network errors (parsing, etc.), fail immediately - return err - } - mavenProject = result - return nil - }, - ) - - if err != nil && lastErr != nil { - // If we retried but still failed, include context about retries - return nil, fmt.Errorf("maven operation failed after retries due to network issues: %w", lastErr) - } - - return mavenProject, err -} - -type testPom struct { - pomFilePath string - pomContentString string -} - -func prepareTestPomFiles(testPoms []testPom) (string, error) { - tempDir, err := os.MkdirTemp("", "prepareTestPomFiles") - if err != nil { - return "", err - } - for _, testPom := range testPoms { - pomPath := filepath.Join(tempDir, testPom.pomFilePath) - err := os.MkdirAll(filepath.Dir(pomPath), 0755) - if err != nil { - return "", err - } - err = os.WriteFile(pomPath, []byte(testPom.pomContentString), 0600) - if err != nil { - return "", err - } - } - return tempDir, nil -} diff --git a/cli/azd/internal/appdetect/testdata/java-multimodules/application/pom.xml b/cli/azd/internal/appdetect/testdata/java-multimodules/application/pom.xml index 62df3be885d..6f5f7dd70c0 100644 --- a/cli/azd/internal/appdetect/testdata/java-multimodules/application/pom.xml +++ b/cli/azd/internal/appdetect/testdata/java-multimodules/application/pom.xml @@ -3,57 +3,27 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.springframework.boot - spring-boot-starter-parent - 3.5.6 - + org.springframework + java-multimodules + 0.1.0 + .. com.example application 0.0.1-SNAPSHOT - application - Demo project for Spring Boot - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-web - - - com.example - library - ${project.version} - - - - org.springframework.boot - spring-boot-starter-test - test - - com.mysql mysql-connector-j + 8.0.33 org.postgresql postgresql - test + 42.6.0 - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/cli/azd/internal/appdetect/testdata/java-multimodules/library/pom.xml b/cli/azd/internal/appdetect/testdata/java-multimodules/library/pom.xml index e969a23417a..4633ca304ee 100644 --- a/cli/azd/internal/appdetect/testdata/java-multimodules/library/pom.xml +++ b/cli/azd/internal/appdetect/testdata/java-multimodules/library/pom.xml @@ -3,27 +3,15 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.springframework.boot - spring-boot-starter-parent - 3.5.6 - + org.springframework + java-multimodules + 0.1.0 + .. com.example library 0.0.1-SNAPSHOT - library - Demo project for Spring Boot - - org.springframework.boot - spring-boot - - - - org.springframework.boot - spring-boot-starter-test - test - diff --git a/cli/azd/internal/appdetect/testdata/java-multimodules/module1/pom.xml b/cli/azd/internal/appdetect/testdata/java-multimodules/module/pom.xml similarity index 93% rename from cli/azd/internal/appdetect/testdata/java-multimodules/module1/pom.xml rename to cli/azd/internal/appdetect/testdata/java-multimodules/module/pom.xml index 64400716997..abb54dc5ae3 100644 --- a/cli/azd/internal/appdetect/testdata/java-multimodules/module1/pom.xml +++ b/cli/azd/internal/appdetect/testdata/java-multimodules/module/pom.xml @@ -9,9 +9,9 @@ com.example - module1 + module 0.0.1-SNAPSHOT - module1 + module Demo project for Spring Boot diff --git a/cli/azd/internal/appdetect/testdata/java-multimodules/module2/pom.xml b/cli/azd/internal/appdetect/testdata/java-multimodules/module2/pom.xml deleted file mode 100644 index 3d06ae0d829..00000000000 --- a/cli/azd/internal/appdetect/testdata/java-multimodules/module2/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.5.6 - - - - com.example - module2 - 0.0.1-SNAPSHOT - module2 - Demo project for Spring Boot - pom - - - submodule1 - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/cli/azd/internal/appdetect/testdata/java-multimodules/module2/submodule1/pom.xml b/cli/azd/internal/appdetect/testdata/java-multimodules/module2/submodule1/pom.xml deleted file mode 100644 index 88a9349047b..00000000000 --- a/cli/azd/internal/appdetect/testdata/java-multimodules/module2/submodule1/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.5.6 - - - - com.example - submodule1 - 0.0.1-SNAPSHOT - submodule1 - Demo project for Spring Boot - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - \ No newline at end of file diff --git a/cli/azd/internal/appdetect/testdata/java-multimodules/notmodule/pom.xml b/cli/azd/internal/appdetect/testdata/java-multimodules/notmodule/pom.xml index 9ef2a6f0ba7..3fdaf812d38 100644 --- a/cli/azd/internal/appdetect/testdata/java-multimodules/notmodule/pom.xml +++ b/cli/azd/internal/appdetect/testdata/java-multimodules/notmodule/pom.xml @@ -3,26 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.4.5 - - com.example notmodule 0.0.1-SNAPSHOT - notmodule - Demo project for Spring Boot - - - - - org.springframework.boot - spring-boot-maven-plugin - - - \ No newline at end of file diff --git a/cli/azd/internal/appdetect/testdata/java-multimodules/pom.xml b/cli/azd/internal/appdetect/testdata/java-multimodules/pom.xml index e0cff252eff..a84c82e8bbe 100644 --- a/cli/azd/internal/appdetect/testdata/java-multimodules/pom.xml +++ b/cli/azd/internal/appdetect/testdata/java-multimodules/pom.xml @@ -11,8 +11,7 @@ library application - module1 - module2 + module diff --git a/eng/scripts/Set-CliBuildVariables.ps1 b/eng/scripts/Set-CliBuildVariables.ps1 index 5959de05a4f..463946d2ddc 100644 --- a/eng/scripts/Set-CliBuildVariables.ps1 +++ b/eng/scripts/Set-CliBuildVariables.ps1 @@ -26,7 +26,7 @@ # AZURE_RECORD_MODE is used for running tests in a specific recording mode. if (-not $env:AZURE_RECORD_MODE) { - $recordMode = "live" + $recordMode = "playback" if ($BuildReason -eq "PullRequest") { $recordMode = "playback"