diff --git a/cli/azd/pkg/pipeline/pipeline.go b/cli/azd/pkg/pipeline/pipeline.go index 9af4b013ca3..ada30f88d3f 100644 --- a/cli/azd/pkg/pipeline/pipeline.go +++ b/cli/azd/pkg/pipeline/pipeline.go @@ -167,6 +167,7 @@ const ( azdoDisplayName string = "Azure DevOps" azdoCode = "azdo" azdoRoot string = ".azdo" + azdoRootAlt string = ".azuredevops" azdoPipelines string = "pipelines" envPersistedKey string = "AZD_PIPELINE_PROVIDER" ) @@ -176,36 +177,38 @@ var ( ) var ( - // Define a map to hold the directory and file names for each provider pipelineProviderFiles = map[ciProviderType]struct { - RootDirectory string - PipelineDirectory string - Files []string - DefaultFile string - DisplayName string - Code string + RootDirectories []string + PipelineDirectories []string + Files []string + DefaultFile string + DisplayName string + Code string }{ ciProviderGitHubActions: { - RootDirectory: gitHubRoot, - PipelineDirectory: filepath.Join(gitHubRoot, gitHubWorkflows), - Files: generateFilePaths(filepath.Join(gitHubRoot, gitHubWorkflows), pipelineFileNames), - DefaultFile: pipelineFileNames[0], - DisplayName: gitHubDisplayName, + RootDirectories: []string{gitHubRoot}, + PipelineDirectories: []string{filepath.Join(gitHubRoot, gitHubWorkflows)}, + Files: generateFilePaths([]string{filepath.Join(gitHubRoot, gitHubWorkflows)}, pipelineFileNames), + DefaultFile: pipelineFileNames[0], + DisplayName: gitHubDisplayName, }, ciProviderAzureDevOps: { - RootDirectory: azdoRoot, - PipelineDirectory: filepath.Join(azdoRoot, azdoPipelines), - Files: generateFilePaths(filepath.Join(azdoRoot, azdoPipelines), pipelineFileNames), - DefaultFile: pipelineFileNames[0], - DisplayName: azdoDisplayName, + RootDirectories: []string{azdoRoot, azdoRootAlt}, + PipelineDirectories: []string{filepath.Join(azdoRoot, azdoPipelines), filepath.Join(azdoRootAlt, azdoPipelines)}, + Files: generateFilePaths([]string{filepath.Join(azdoRoot, azdoPipelines), + filepath.Join(azdoRootAlt, azdoPipelines)}, pipelineFileNames), + DefaultFile: pipelineFileNames[0], + DisplayName: azdoDisplayName, }, } ) -func generateFilePaths(directory string, fileNames []string) []string { +func generateFilePaths(directories []string, fileNames []string) []string { var paths []string - for _, file := range fileNames { - paths = append(paths, filepath.Join(directory, file)) + for _, dir := range directories { + for _, file := range fileNames { + paths = append(paths, filepath.Join(dir, file)) + } } return paths } diff --git a/cli/azd/pkg/pipeline/pipeline_manager.go b/cli/azd/pkg/pipeline/pipeline_manager.go index b9cdde848af..f11e29ccc49 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager.go +++ b/cli/azd/pkg/pipeline/pipeline_manager.go @@ -823,8 +823,7 @@ func (pm *PipelineManager) savePipelineProviderToEnv( } // checkAndPromptForProviderFiles checks if the provider files are present and prompts the user to create them if not. -func (pm *PipelineManager) checkAndPromptForProviderFiles( - ctx context.Context, props projectProperties) error { +func (pm *PipelineManager) checkAndPromptForProviderFiles(ctx context.Context, props projectProperties) error { log.Printf("Checking for provider files for: %s", props.CiProvider) if !hasPipelineFile(props.CiProvider, props.RepoRoot) { @@ -836,41 +835,65 @@ func (pm *PipelineManager) checkAndPromptForProviderFiles( log.Println("Prompt for CI files completed successfully.") } - dirPath := pipelineProviderFiles[props.CiProvider].PipelineDirectory - log.Printf("Checking if directory %s is empty", dirPath) - isEmpty, err := osutil.IsDirEmpty(filepath.Join(props.RepoRoot, dirPath), true) - if err != nil { - log.Println("Error checking if directory is empty:", err) - return fmt.Errorf("error checking if directory is empty: %w", err) - } - - if isEmpty { - message := fmt.Sprintf( - "%s provider selected, but %s is empty. Please add pipeline files.", - pipelineProviderFiles[props.CiProvider].DisplayName, dirPath) - if props.CiProvider == ciProviderAzureDevOps { - message = fmt.Sprintf( - "%s provider selected, but %s is empty. Please add pipeline files and try again.", - pipelineProviderFiles[props.CiProvider].DisplayName, dirPath) - log.Println("Error:", message) - return fmt.Errorf(message) + var dirPaths []string + for _, dir := range pipelineProviderFiles[props.CiProvider].PipelineDirectories { + dirPaths = append(dirPaths, filepath.Join(props.RepoRoot, dir)) + } + + for _, dirPath := range dirPaths { + log.Printf("Checking if directory %s is empty", dirPath) + isEmpty, err := osutil.IsDirEmpty(dirPath, true) + if err != nil { + log.Println("Error checking if directory is empty:", err) + return fmt.Errorf("error checking if directory is empty: %w", err) + } + if !isEmpty { + log.Printf("Provider files are present in directory: %s", dirPath) + return nil } - log.Println("Info:", message) - pm.console.Message(ctx, message) - pm.console.Message(ctx, "") } - log.Printf("Provider files are present for: %s", props.CiProvider) + message := fmt.Sprintf( + "%s provider selected, but no pipeline files were found in any expected directories:\n%s\n"+ + "Please add pipeline files.", + pipelineProviderFiles[props.CiProvider].DisplayName, + strings.Join(pipelineProviderFiles[props.CiProvider].PipelineDirectories, "\n")) + + if props.CiProvider == ciProviderAzureDevOps { + message = fmt.Sprintf( + "%s provider selected, but no pipeline files were found in any expected directories:\n%s\n"+ + "Please add pipeline files and try again.", + pipelineProviderFiles[props.CiProvider].DisplayName, + strings.Join(pipelineProviderFiles[props.CiProvider].PipelineDirectories, "\n")) + log.Println("Error:", message) + return fmt.Errorf(message) + } + + log.Println("Info:", message) + pm.console.Message(ctx, message) + pm.console.Message(ctx, "") + + log.Printf("Provider files are not present for: %s", props.CiProvider) return nil } // promptForCiFiles creates CI/CD files for the specified provider, confirming with the user before creation. func (pm *PipelineManager) promptForCiFiles(ctx context.Context, props projectProperties) error { - dirPath := filepath.Join(props.RepoRoot, pipelineProviderFiles[props.CiProvider].PipelineDirectory) - defaultFile := filepath.Join(dirPath, pipelineProviderFiles[props.CiProvider].DefaultFile) + var dirPaths []string + for _, dir := range pipelineProviderFiles[props.CiProvider].PipelineDirectories { + dirPaths = append(dirPaths, filepath.Join(props.RepoRoot, dir)) + } - log.Printf("Directory path: %s", dirPath) - log.Printf("Default YAML path: %s", defaultFile) + var defaultFilePath string + for _, dirPath := range dirPaths { + defaultFilePath = filepath.Join(dirPath, pipelineProviderFiles[props.CiProvider].DefaultFile) + if osutil.DirExists(dirPath) || osutil.FileExists(defaultFilePath) { + break + } + } + + log.Printf("Directory paths: %v", dirPaths) + log.Printf("Default YAML path: %s", defaultFilePath) // Confirm with the user before adding the default file pm.console.Message(ctx, "") @@ -891,32 +914,47 @@ func (pm *PipelineManager) promptForCiFiles(ctx context.Context, props projectPr pm.console.Message(ctx, "") if confirm { - log.Printf("Confirmed creation of %s file at %s", filepath.Base(defaultFile), dirPath) + log.Printf("Confirmed creation of %s file at %s", filepath.Base(defaultFilePath), dirPaths) + + created := false + for _, dirPath := range dirPaths { + if !osutil.DirExists(dirPath) { + log.Printf("Creating directory %s", dirPath) + if err := os.MkdirAll(dirPath, os.ModePerm); err != nil { + return fmt.Errorf("creating directory %s: %w", dirPath, err) + } + created = true + } - if !osutil.DirExists(dirPath) { - log.Printf("Creating directory %s", dirPath) - if err := os.MkdirAll(dirPath, os.ModePerm); err != nil { - return fmt.Errorf("creating directory %s: %w", dirPath, err) + if !osutil.FileExists(filepath.Join(dirPath, pipelineProviderFiles[props.CiProvider].DefaultFile)) { + if err := generatePipelineDefinition(filepath.Join(dirPath, + pipelineProviderFiles[props.CiProvider].DefaultFile), props); err != nil { + return err + } + pm.console.Message(ctx, + fmt.Sprintf( + "The %s file has been created at %s. You can use it as-is or modify it to suit your needs.", + output.WithHighLightFormat(filepath.Base(defaultFilePath)), + output.WithHighLightFormat(filepath.Join(dirPath, + pipelineProviderFiles[props.CiProvider].DefaultFile))), + ) + pm.console.Message(ctx, "") + created = true } - } - if !osutil.FileExists(defaultFile) { - if err := generatePipelineDefinition(defaultFile, props); err != nil { - return err + if created { + break } - pm.console.Message(ctx, - fmt.Sprintf( - "The %s file has been created at %s. You can use it as-is or modify it to suit your needs.", - output.WithHighLightFormat(filepath.Base(defaultFile)), - output.WithHighLightFormat(defaultFile)), - ) - pm.console.Message(ctx, "") + } + + if !created { + log.Printf("User declined creation of %s file at %s", filepath.Base(defaultFilePath), dirPaths) } return nil } - log.Printf("User declined creation of %s file at %s", filepath.Base(defaultFile), dirPath) + log.Printf("User declined creation of %s file at %s", filepath.Base(defaultFilePath), dirPaths) return nil } diff --git a/cli/azd/pkg/pipeline/pipeline_manager_test.go b/cli/azd/pkg/pipeline/pipeline_manager_test.go index 04c9fbe2dcb..118544dd871 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager_test.go +++ b/cli/azd/pkg/pipeline/pipeline_manager_test.go @@ -70,6 +70,7 @@ func Test_PipelineManager_Initialize(t *testing.T) { deleteYamlFiles(t, tempDir) }) + t.Run("no files - github selected - empty workflows dir", func(t *testing.T) { mockContext = resetContext(tempDir, ctx) @@ -81,9 +82,14 @@ func Test_PipelineManager_Initialize(t *testing.T) { // No error for GitHub, just a message to the console assert.NoError(t, err) assert.Contains(t, - mockContext.Console.Output(), fmt.Sprintf("%s provider selected, but %s is empty. Please add pipeline files.", - gitHubDisplayName, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory)) + mockContext.Console.Output(), + fmt.Sprintf( + "%s provider selected, but no pipeline files were found in any expected directories:\n%s\n"+ + "Please add pipeline files.", + gitHubDisplayName, + strings.Join(pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectories, "\n"))) }) + t.Run("no files - azdo selected - empty pipelines dir", func(t *testing.T) { mockContext = resetContext(tempDir, ctx) @@ -94,11 +100,13 @@ func Test_PipelineManager_Initialize(t *testing.T) { manager, err := createPipelineManager(mockContext, azdContext, nil, nil) assert.Nil(t, manager) assert.EqualError(t, err, fmt.Sprintf( - "%s provider selected, but %s is empty. Please add pipeline files and try again.", - azdoDisplayName, pipelineProviderFiles[ciProviderAzureDevOps].PipelineDirectory)) + "%s provider selected, but no pipeline files were found in any expected directories:\n%s\n"+ + "Please add pipeline files and try again.", + azdoDisplayName, + strings.Join(pipelineProviderFiles[ciProviderAzureDevOps].PipelineDirectories, "\n"))) }) - t.Run("no files - azdo selected", func(t *testing.T) { + t.Run("no files - azdo selected", func(t *testing.T) { mockContext = resetContext(tempDir, ctx) deleteYamlFiles(t, tempDir) @@ -119,6 +127,7 @@ func Test_PipelineManager_Initialize(t *testing.T) { assert.FileExists(t, azdoYmlPath) deleteYamlFiles(t, tempDir) }) + t.Run("from persisted data azdo error", func(t *testing.T) { // User selects Azure DevOps, but the required directory is missing mockContext = resetContext(tempDir, ctx) @@ -132,9 +141,13 @@ func Test_PipelineManager_Initialize(t *testing.T) { manager, err := createPipelineManager(mockContext, azdContext, env, nil) assert.Nil(t, manager) assert.EqualError(t, err, fmt.Sprintf( - "%s provider selected, but %s is empty. Please add pipeline files and try again.", - azdoDisplayName, pipelineProviderFiles[ciProviderAzureDevOps].PipelineDirectory)) + "%s provider selected, but no pipeline files were found in any expected directories:\n%s\n"+ + "Please add pipeline files and try again.", + azdoDisplayName, + strings.Join(pipelineProviderFiles[ciProviderAzureDevOps].PipelineDirectories, "\n")), + ) }) + t.Run("from persisted data azdo", func(t *testing.T) { // User has azdo persisted in env and they have the files mockContext = resetContext(tempDir, ctx) @@ -164,9 +177,15 @@ func Test_PipelineManager_Initialize(t *testing.T) { // No error for GitHub, just a message to the console assert.NoError(t, err) assert.Contains(t, - mockContext.Console.Output(), fmt.Sprintf("%s provider selected, but %s is empty. Please add pipeline files.", - gitHubDisplayName, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory)) + mockContext.Console.Output(), + fmt.Sprintf( + "%s provider selected, but no pipeline files were found in any expected directories:\n%s\n"+ + "Please add pipeline files.", + gitHubDisplayName, + strings.Join(pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectories, "\n")), + ) }) + t.Run("from persisted data github", func(t *testing.T) { // User has azdo persisted in env and they have the files mockContext = resetContext(tempDir, ctx) @@ -346,6 +365,25 @@ func Test_PipelineManager_Initialize(t *testing.T) { deleteYamlFiles(t, tempDir) }) + t.Run("has azure-dev.yaml in .azuredevops folder", func(t *testing.T) { + mockContext = resetContext(tempDir, ctx) + + // Create the azure-dev.yml file in the .azuredevops folder using createYamlFiles + createYamlFiles(t, tempDir, ciProviderAzureDevOps, 2) + + // Initialize the PipelineManager + manager, err := createPipelineManager(mockContext, azdContext, nil, nil) + assert.NotNil(t, manager) + assert.NoError(t, err) + + // Execute the initialize method, which should trigger the provider selection prompt + err = manager.initialize(ctx, "") + + verifyProvider(t, manager, ciProviderAzureDevOps, err) + + deleteYamlFiles(t, tempDir) + }) + t.Run("both files - user selects azdo", func(t *testing.T) { mockContext = resetContext(tempDir, ctx) @@ -453,7 +491,7 @@ func Test_PipelineManager_Initialize(t *testing.T) { func Test_promptForCiFiles(t *testing.T) { t.Run("no files - github selected - no app host - fed Cred", func(t *testing.T) { tempDir := t.TempDir() - path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory) + path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectories[0]) err := os.MkdirAll(path, osutil.PermissionDirectory) assert.NoError(t, err) expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].Files[0]) @@ -475,7 +513,7 @@ func Test_promptForCiFiles(t *testing.T) { }) t.Run("no files - github selected - App host - fed Cred", func(t *testing.T) { tempDir := t.TempDir() - path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory) + path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectories[0]) err := os.MkdirAll(path, osutil.PermissionDirectory) assert.NoError(t, err) expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].Files[0]) @@ -497,10 +535,10 @@ func Test_promptForCiFiles(t *testing.T) { }) t.Run("no files - azdo selected - App host - fed Cred", func(t *testing.T) { tempDir := t.TempDir() - path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory) + path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderAzureDevOps].PipelineDirectories[0]) err := os.MkdirAll(path, osutil.PermissionDirectory) assert.NoError(t, err) - expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].Files[0]) + expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderAzureDevOps].Files[0]) err = generatePipelineDefinition(expectedPath, projectProperties{ CiProvider: ciProviderAzureDevOps, InfraProvider: infraProviderBicep, @@ -519,7 +557,7 @@ func Test_promptForCiFiles(t *testing.T) { }) t.Run("no files - github selected - no app host - client cred", func(t *testing.T) { tempDir := t.TempDir() - path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory) + path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectories[0]) err := os.MkdirAll(path, osutil.PermissionDirectory) assert.NoError(t, err) expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].Files[0]) @@ -541,7 +579,7 @@ func Test_promptForCiFiles(t *testing.T) { }) t.Run("no files - github selected - branch name", func(t *testing.T) { tempDir := t.TempDir() - path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory) + path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectories[0]) err := os.MkdirAll(path, osutil.PermissionDirectory) assert.NoError(t, err) expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].Files[0]) @@ -563,10 +601,10 @@ func Test_promptForCiFiles(t *testing.T) { }) t.Run("no files - azdo selected - no app host - fed Cred", func(t *testing.T) { tempDir := t.TempDir() - path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory) + path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderAzureDevOps].PipelineDirectories[0]) err := os.MkdirAll(path, osutil.PermissionDirectory) assert.NoError(t, err) - expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].Files[0]) + expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderAzureDevOps].Files[0]) err = generatePipelineDefinition(expectedPath, projectProperties{ CiProvider: ciProviderAzureDevOps, InfraProvider: infraProviderBicep, @@ -585,10 +623,10 @@ func Test_promptForCiFiles(t *testing.T) { }) t.Run("no files - azdo selected - no app host - client cred", func(t *testing.T) { tempDir := t.TempDir() - path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory) + path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderAzureDevOps].PipelineDirectories[0]) err := os.MkdirAll(path, osutil.PermissionDirectory) assert.NoError(t, err) - expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].Files[0]) + expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderAzureDevOps].Files[0]) err = generatePipelineDefinition(expectedPath, projectProperties{ CiProvider: ciProviderAzureDevOps, InfraProvider: infraProviderBicep, @@ -607,10 +645,10 @@ func Test_promptForCiFiles(t *testing.T) { }) t.Run("no files - azdo selected - branch name", func(t *testing.T) { tempDir := t.TempDir() - path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].PipelineDirectory) + path := filepath.Join(tempDir, pipelineProviderFiles[ciProviderAzureDevOps].PipelineDirectories[0]) err := os.MkdirAll(path, osutil.PermissionDirectory) assert.NoError(t, err) - expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].Files[0]) + expectedPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderAzureDevOps].Files[0]) err = generatePipelineDefinition(expectedPath, projectProperties{ CiProvider: ciProviderAzureDevOps, InfraProvider: infraProviderBicep, @@ -629,6 +667,54 @@ func Test_promptForCiFiles(t *testing.T) { }) } +func Test_promptForCiFiles_azureDevOpsDirectory(t *testing.T) { + t.Run("no files - azdo selected - azuredevops dir - fed Cred", func(t *testing.T) { + tempDir := t.TempDir() + path := filepath.Join(tempDir, ".azuredevops") + err := os.MkdirAll(path, osutil.PermissionDirectory) + assert.NoError(t, err) + expectedPath := filepath.Join(tempDir, ".azuredevops/azure-dev.yml") + err = generatePipelineDefinition(expectedPath, projectProperties{ + CiProvider: ciProviderAzureDevOps, + InfraProvider: infraProviderBicep, + RepoRoot: tempDir, + HasAppHost: false, + BranchName: "main", + AuthType: AuthTypeFederated, + }) + assert.NoError(t, err) + // should've created the pipeline + assert.FileExists(t, expectedPath) + // open the file and check the content + content, err := os.ReadFile(expectedPath) + assert.NoError(t, err) + snapshot.SnapshotT(t, normalizeEOL(content)) + }) + + t.Run("no files - azdo selected - azuredevops dir - client cred", func(t *testing.T) { + tempDir := t.TempDir() + path := filepath.Join(tempDir, ".azuredevops") + err := os.MkdirAll(path, osutil.PermissionDirectory) + assert.NoError(t, err) + expectedPath := filepath.Join(tempDir, ".azuredevops/azure-dev.yml") + err = generatePipelineDefinition(expectedPath, projectProperties{ + CiProvider: ciProviderAzureDevOps, + InfraProvider: infraProviderBicep, + RepoRoot: tempDir, + HasAppHost: false, + BranchName: "main", + AuthType: AuthTypeClientCredentials, + }) + assert.NoError(t, err) + // should've created the pipeline + assert.FileExists(t, expectedPath) + // open the file and check the content + content, err := os.ReadFile(expectedPath) + assert.NoError(t, err) + snapshot.SnapshotT(t, normalizeEOL(content)) + }) +} + func createPipelineManager( mockContext *mocks.MockContext, azdContext *azdcontext.AzdContext, @@ -799,16 +885,20 @@ func createYamlFiles(t *testing.T, tempDir string, createOptionsAndFileIndex ... // Helper function to create pipeline files func createPipelineFiles(t *testing.T, baseDir string, provider ciProviderType, fileIndex int) { - dir := filepath.Join(baseDir, pipelineProviderFiles[provider].PipelineDirectory) - err := os.MkdirAll(dir, osutil.PermissionDirectory) - assert.NoError(t, err) - files := pipelineProviderFiles[provider].Files if fileIndex < 0 || fileIndex >= len(files) { fileIndex = 0 // Default to 0 if index is out of bounds } + // Get the full path by joining the baseDir with the relative file path filePath := filepath.Join(baseDir, files[fileIndex]) + + // Ensure the directory exists + dir := filepath.Dir(filePath) + err := os.MkdirAll(dir, osutil.PermissionDirectory) + assert.NoError(t, err) + + // Create the file file, err := os.Create(filePath) assert.NoError(t, err) err = file.Close() @@ -843,9 +933,11 @@ func deleteYamlFiles(t *testing.T, tempDir string, deleteOptions ...ciProviderTy // Helper function to delete pipeline files and directories func deletePipelineFiles(t *testing.T, baseDir string, provider ciProviderType) { - dir := filepath.Join(baseDir, pipelineProviderFiles[provider].RootDirectory) - err := os.RemoveAll(dir) - assert.NoError(t, err) + for _, file := range pipelineProviderFiles[provider].Files { + fullPath := filepath.Join(baseDir, file) + err := os.RemoveAll(fullPath) + assert.NoError(t, err) + } } func simulateUserInteraction(mockContext *mocks.MockContext, providerLabel ciProviderType, createConfirmation bool) { diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_client_cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_client_cred.snap new file mode 100644 index 00000000000..02e7ca228bd --- /dev/null +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_client_cred.snap @@ -0,0 +1,56 @@ +# Run when commits are pushed to main +trigger: + - main + +pool: + vmImage: ubuntu-latest + +steps: + # setup-azd@0 needs to be manually installed in your organization + # if you can't install it, you can use the below bash script to install azd + # and remove this step + - task: setup-azd@0 + displayName: Install azd + + # If you can't install above task in your organization, you can comment it and uncomment below task to install azd + # - task: Bash@3 + # displayName: Install azd + # inputs: + # targetType: 'inline' + # script: | + # curl -fsSL https://aka.ms/install-azd.sh | bash + + # azd delegate auth to az to use service connection with AzureCLI@2 + - pwsh: | + azd config set auth.useAzCliAuth "true" + displayName: Configure AZD to Use AZ CLI Authentication. + - task: AzureCLI@2 + displayName: Provision Infrastructure + inputs: + azureSubscription: azconnection + scriptType: bash + scriptLocation: inlineScript + keepAzSessionActive: true + inlineScript: | + azd provision --no-prompt + env: + AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) + AZURE_ENV_NAME: $(AZURE_ENV_NAME) + AZURE_LOCATION: $(AZURE_LOCATION) + AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) + + - task: AzureCLI@2 + displayName: Deploy Application + inputs: + azureSubscription: azconnection + scriptType: bash + scriptLocation: inlineScript + keepAzSessionActive: true + inlineScript: | + azd deploy --no-prompt + env: + AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) + AZURE_ENV_NAME: $(AZURE_ENV_NAME) + AZURE_LOCATION: $(AZURE_LOCATION) + + diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_fed_Cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_fed_Cred.snap new file mode 100644 index 00000000000..02e7ca228bd --- /dev/null +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_fed_Cred.snap @@ -0,0 +1,56 @@ +# Run when commits are pushed to main +trigger: + - main + +pool: + vmImage: ubuntu-latest + +steps: + # setup-azd@0 needs to be manually installed in your organization + # if you can't install it, you can use the below bash script to install azd + # and remove this step + - task: setup-azd@0 + displayName: Install azd + + # If you can't install above task in your organization, you can comment it and uncomment below task to install azd + # - task: Bash@3 + # displayName: Install azd + # inputs: + # targetType: 'inline' + # script: | + # curl -fsSL https://aka.ms/install-azd.sh | bash + + # azd delegate auth to az to use service connection with AzureCLI@2 + - pwsh: | + azd config set auth.useAzCliAuth "true" + displayName: Configure AZD to Use AZ CLI Authentication. + - task: AzureCLI@2 + displayName: Provision Infrastructure + inputs: + azureSubscription: azconnection + scriptType: bash + scriptLocation: inlineScript + keepAzSessionActive: true + inlineScript: | + azd provision --no-prompt + env: + AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) + AZURE_ENV_NAME: $(AZURE_ENV_NAME) + AZURE_LOCATION: $(AZURE_LOCATION) + AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) + + - task: AzureCLI@2 + displayName: Deploy Application + inputs: + azureSubscription: azconnection + scriptType: bash + scriptLocation: inlineScript + keepAzSessionActive: true + inlineScript: | + azd deploy --no-prompt + env: + AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) + AZURE_ENV_NAME: $(AZURE_ENV_NAME) + AZURE_LOCATION: $(AZURE_LOCATION) + +