Skip to content

Commit d6813fb

Browse files
authored
Allow .yaml and .yml extension for azure-dev pipeline files (#4182)
* Test aks * Fix msg * Treat azure-dev.yaml as a valid default pipelines file * Fix tests * Update to use ciProviderType
1 parent b801642 commit d6813fb

File tree

3 files changed

+193
-150
lines changed

3 files changed

+193
-150
lines changed

cli/azd/pkg/pipeline/pipeline.go

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -160,26 +160,61 @@ func mergeProjectVariablesAndSecrets(
160160
}
161161

162162
const (
163-
gitHubDisplayName string = "GitHub"
164-
azdoDisplayName string = "Azure DevOps"
165-
envPersistedKey string = "AZD_PIPELINE_PROVIDER"
166-
defaultPipelineFileName string = "azure-dev.yml"
167-
gitHubDirectory string = ".github"
168-
azdoDirectory string = ".azdo"
163+
gitHubDisplayName string = "GitHub"
164+
gitHubCode = "github"
165+
gitHubRoot string = ".github"
166+
gitHubWorkflows string = "workflows"
167+
azdoDisplayName string = "Azure DevOps"
168+
azdoCode = "azdo"
169+
azdoRoot string = ".azdo"
170+
azdoPipelines string = "pipelines"
171+
envPersistedKey string = "AZD_PIPELINE_PROVIDER"
169172
)
170173

171174
var (
172-
gitHubWorkflowsDirectory string = filepath.Join(gitHubDirectory, "workflows")
173-
azdoPipelinesDirectory string = filepath.Join(azdoDirectory, "pipelines")
174-
gitHubYml string = filepath.Join(gitHubWorkflowsDirectory, defaultPipelineFileName)
175-
azdoYml string = filepath.Join(azdoPipelinesDirectory, defaultPipelineFileName)
175+
pipelineFileNames = []string{"azure-dev.yml", "azure-dev.yaml"}
176176
)
177177

178+
var (
179+
// Define a map to hold the directory and file names for each provider
180+
pipelineProviderFiles = map[ciProviderType]struct {
181+
RootDirectory string
182+
PipelineDirectory string
183+
Files []string
184+
DefaultFile string
185+
DisplayName string
186+
Code string
187+
}{
188+
ciProviderGitHubActions: {
189+
RootDirectory: gitHubRoot,
190+
PipelineDirectory: filepath.Join(gitHubRoot, gitHubWorkflows),
191+
Files: generateFilePaths(filepath.Join(gitHubRoot, gitHubWorkflows), pipelineFileNames),
192+
DefaultFile: pipelineFileNames[0],
193+
DisplayName: gitHubDisplayName,
194+
},
195+
ciProviderAzureDevOps: {
196+
RootDirectory: azdoRoot,
197+
PipelineDirectory: filepath.Join(azdoRoot, azdoPipelines),
198+
Files: generateFilePaths(filepath.Join(azdoRoot, azdoPipelines), pipelineFileNames),
199+
DefaultFile: pipelineFileNames[0],
200+
DisplayName: azdoDisplayName,
201+
},
202+
}
203+
)
204+
205+
func generateFilePaths(directory string, fileNames []string) []string {
206+
var paths []string
207+
for _, file := range fileNames {
208+
paths = append(paths, filepath.Join(directory, file))
209+
}
210+
return paths
211+
}
212+
178213
type ciProviderType string
179214

180215
const (
181-
ciProviderGitHubActions ciProviderType = "github"
182-
ciProviderAzureDevOps ciProviderType = "azdo"
216+
ciProviderGitHubActions ciProviderType = gitHubCode
217+
ciProviderAzureDevOps ciProviderType = azdoCode
183218
)
184219

185220
func toCiProviderType(provider string) (ciProviderType, error) {

cli/azd/pkg/pipeline/pipeline_manager.go

Lines changed: 41 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -822,71 +822,41 @@ func (pm *PipelineManager) savePipelineProviderToEnv(
822822
return nil
823823
}
824824

825+
// checkAndPromptForProviderFiles checks if the provider files are present and prompts the user to create them if not.
825826
func (pm *PipelineManager) checkAndPromptForProviderFiles(
826827
ctx context.Context, props projectProperties) error {
827828
log.Printf("Checking for provider files for: %s", props.CiProvider)
828829

829-
providerFileChecks := map[ciProviderType]struct {
830-
ymlPath string
831-
dirPath string
832-
dirDisplayName string
833-
providerDisplayName string
834-
}{
835-
ciProviderGitHubActions: {
836-
ymlPath: filepath.Join(props.RepoRoot, gitHubYml),
837-
dirPath: filepath.Join(props.RepoRoot, gitHubWorkflowsDirectory),
838-
dirDisplayName: gitHubWorkflowsDirectory,
839-
providerDisplayName: gitHubDisplayName,
840-
},
841-
ciProviderAzureDevOps: {
842-
ymlPath: filepath.Join(props.RepoRoot, azdoYml),
843-
dirPath: filepath.Join(props.RepoRoot, azdoPipelinesDirectory),
844-
dirDisplayName: azdoPipelinesDirectory,
845-
providerDisplayName: azdoDisplayName,
846-
},
847-
}
848-
849-
providerCheck, exists := providerFileChecks[props.CiProvider]
850-
if !exists {
851-
errMsg := fmt.Sprintf("%s is not a known pipeline provider", props.CiProvider)
852-
log.Println("Error:", errMsg)
853-
return fmt.Errorf(errMsg)
854-
}
855-
856-
log.Printf("YAML path: %s", providerCheck.ymlPath)
857-
log.Printf("Directory path: %s", providerCheck.dirPath)
858-
859-
if !osutil.FileExists(providerCheck.ymlPath) {
860-
log.Printf("%s YAML not found, prompting for creation", providerCheck.providerDisplayName)
830+
if !hasPipelineFile(props.CiProvider, props.RepoRoot) {
831+
log.Printf("%s YAML not found, prompting for creation", props.CiProvider)
861832
if err := pm.promptForCiFiles(ctx, props); err != nil {
862833
log.Println("Error prompting for CI files:", err)
863834
return err
864835
}
865836
log.Println("Prompt for CI files completed successfully.")
866837
}
867838

868-
log.Printf("Checking if directory %s is empty", providerCheck.dirPath)
869-
isEmpty, err := osutil.IsDirEmpty(providerCheck.dirPath, true)
839+
dirPath := pipelineProviderFiles[props.CiProvider].PipelineDirectory
840+
log.Printf("Checking if directory %s is empty", dirPath)
841+
isEmpty, err := osutil.IsDirEmpty(filepath.Join(props.RepoRoot, dirPath), true)
870842
if err != nil {
871843
log.Println("Error checking if directory is empty:", err)
872844
return fmt.Errorf("error checking if directory is empty: %w", err)
873845
}
874846

875847
if isEmpty {
848+
message := fmt.Sprintf(
849+
"%s provider selected, but %s is empty. Please add pipeline files.",
850+
pipelineProviderFiles[props.CiProvider].DisplayName, dirPath)
876851
if props.CiProvider == ciProviderAzureDevOps {
877-
message := fmt.Sprintf(
852+
message = fmt.Sprintf(
878853
"%s provider selected, but %s is empty. Please add pipeline files and try again.",
879-
providerCheck.providerDisplayName, providerCheck.dirDisplayName)
854+
pipelineProviderFiles[props.CiProvider].DisplayName, dirPath)
880855
log.Println("Error:", message)
881856
return fmt.Errorf(message)
882857
}
883-
if props.CiProvider == ciProviderGitHubActions {
884-
message := fmt.Sprintf(
885-
"%s provider selected, but %s is empty. Please add pipeline files.",
886-
providerCheck.providerDisplayName, providerCheck.dirDisplayName)
887-
log.Println("Info:", message)
888-
pm.console.Message(ctx, message)
889-
}
858+
log.Println("Info:", message)
859+
pm.console.Message(ctx, message)
890860
pm.console.Message(ctx, "")
891861
}
892862

@@ -896,29 +866,13 @@ func (pm *PipelineManager) checkAndPromptForProviderFiles(
896866

897867
// promptForCiFiles creates CI/CD files for the specified provider, confirming with the user before creation.
898868
func (pm *PipelineManager) promptForCiFiles(ctx context.Context, props projectProperties) error {
899-
paths := map[ciProviderType]struct {
900-
directory string
901-
yml string
902-
}{
903-
ciProviderGitHubActions: {
904-
filepath.Join(props.RepoRoot, gitHubWorkflowsDirectory), filepath.Join(props.RepoRoot, gitHubYml),
905-
},
906-
ciProviderAzureDevOps: {
907-
filepath.Join(props.RepoRoot, azdoPipelinesDirectory), filepath.Join(props.RepoRoot, azdoYml),
908-
},
909-
}
910-
911-
providerPaths, exists := paths[props.CiProvider]
912-
if !exists {
913-
errMsg := fmt.Sprintf("Unknown provider: %s", props.CiProvider)
914-
log.Println("Error:", errMsg)
915-
return fmt.Errorf(errMsg)
916-
}
869+
dirPath := filepath.Join(props.RepoRoot, pipelineProviderFiles[props.CiProvider].PipelineDirectory)
870+
defaultFile := filepath.Join(dirPath, pipelineProviderFiles[props.CiProvider].DefaultFile)
917871

918-
log.Printf("Directory path: %s", providerPaths.directory)
919-
log.Printf("YAML path: %s", providerPaths.yml)
872+
log.Printf("Directory path: %s", dirPath)
873+
log.Printf("Default YAML path: %s", defaultFile)
920874

921-
// Confirm with the user before adding the file
875+
// Confirm with the user before adding the default file
922876
pm.console.Message(ctx, "")
923877
pm.console.Message(ctx,
924878
fmt.Sprintf(
@@ -937,33 +891,32 @@ func (pm *PipelineManager) promptForCiFiles(ctx context.Context, props projectPr
937891
pm.console.Message(ctx, "")
938892

939893
if confirm {
940-
log.Printf("Confirmed creation of %s file at %s", filepath.Base(providerPaths.yml), providerPaths.directory)
894+
log.Printf("Confirmed creation of %s file at %s", filepath.Base(defaultFile), dirPath)
941895

942-
if !osutil.DirExists(providerPaths.directory) {
943-
log.Printf("Creating directory %s", providerPaths.directory)
944-
if err := os.MkdirAll(providerPaths.directory, os.ModePerm); err != nil {
945-
return fmt.Errorf("creating directory %s: %w", providerPaths.directory, err)
896+
if !osutil.DirExists(dirPath) {
897+
log.Printf("Creating directory %s", dirPath)
898+
if err := os.MkdirAll(dirPath, os.ModePerm); err != nil {
899+
return fmt.Errorf("creating directory %s: %w", dirPath, err)
946900
}
947901
}
948902

949-
if !osutil.FileExists(providerPaths.yml) {
950-
if err := generatePipelineDefinition(providerPaths.yml, props); err != nil {
903+
if !osutil.FileExists(defaultFile) {
904+
if err := generatePipelineDefinition(defaultFile, props); err != nil {
951905
return err
952906
}
953907
pm.console.Message(ctx,
954908
fmt.Sprintf(
955909
"The %s file has been created at %s. You can use it as-is or modify it to suit your needs.",
956-
output.WithHighLightFormat(filepath.Base(providerPaths.yml)),
957-
output.WithHighLightFormat(providerPaths.yml)),
910+
output.WithHighLightFormat(filepath.Base(defaultFile)),
911+
output.WithHighLightFormat(defaultFile)),
958912
)
959913
pm.console.Message(ctx, "")
960914
}
961915

962916
return nil
963917
}
964918

965-
log.Printf("User declined creation of %s file at %s", filepath.Base(providerPaths.yml), providerPaths.directory)
966-
919+
log.Printf("User declined creation of %s file at %s", filepath.Base(defaultFile), dirPath)
967920
return nil
968921
}
969922

@@ -998,12 +951,23 @@ func generatePipelineDefinition(path string, props projectProperties) error {
998951
return nil
999952
}
1000953

954+
// hasPipelineFile checks if any pipeline files exist for the given provider in the specified repository root.
955+
func hasPipelineFile(provider ciProviderType, repoRoot string) bool {
956+
for _, path := range pipelineProviderFiles[provider].Files {
957+
fullPath := filepath.Join(repoRoot, path)
958+
if osutil.FileExists(fullPath) {
959+
return true
960+
}
961+
}
962+
return false
963+
}
964+
1001965
func (pm *PipelineManager) determineProvider(ctx context.Context, repoRoot string) (ciProviderType, error) {
1002966
log.Printf("Checking for CI/CD YAML files in the repository root: %s", repoRoot)
1003967

1004968
// Check for existence of official YAML files in the repo root
1005-
hasGitHubYml := osutil.FileExists(filepath.Join(repoRoot, gitHubYml))
1006-
hasAzDevOpsYml := osutil.FileExists(filepath.Join(repoRoot, azdoYml))
969+
hasGitHubYml := hasPipelineFile(ciProviderGitHubActions, repoRoot)
970+
hasAzDevOpsYml := hasPipelineFile(ciProviderAzureDevOps, repoRoot)
1007971

1008972
log.Printf("GitHub Actions YAML exists: %v", hasGitHubYml)
1009973
log.Printf("Azure DevOps YAML exists: %v", hasAzDevOpsYml)

0 commit comments

Comments
 (0)