Skip to content

Commit 58015ba

Browse files
Updates to support telemetry and better prompts (#115)
# Pull Request ## Issue #114 ## Description This PR makes no significant functional changes other than improving the prompts users see for IaC, bootstrao and starter. The primary update is to pull the bootstrap and starter from named artefacts. By doing this we can get some usage telemetry from the GitHub API. Note that changes have been made to the starter and bootstrap repos for Terraform to accommodate this, but all those changes are backwards compatible and already released. They are ready to go with these changes now. ## Testing - E2E tests have be run for this branch here: https://github.com/Azure/accelerator-bootstrap-modules/actions/runs/9414281487 - Manual testing of Terraform and Bicep happy paths has been completed for prompt testing. ## License By submitting this pull request, I confirm that my contribution is made under the terms of the projects associated license.
1 parent cc905c8 commit 58015ba

File tree

8 files changed

+147
-82
lines changed

8 files changed

+147
-82
lines changed

src/ALZ/Private/Config-Helpers/Request-SpecialInput.ps1

Lines changed: 59 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function Request-SpecialInput {
55
[string] $type,
66

77
[Parameter(Mandatory = $false)]
8-
[string] $starterPath,
8+
[PSCustomObject] $starterConfig,
99

1010
[Parameter(Mandatory = $false)]
1111
[PSCustomObject] $bootstrapModules,
@@ -17,83 +17,79 @@ function Request-SpecialInput {
1717
if ($PSCmdlet.ShouldProcess("ALZ-Terraform module configuration", "modify")) {
1818

1919
$result = ""
20-
21-
if($null -ne $userInputOverrides) {
22-
$userInputOverride = $userInputOverrides.PSObject.Properties | Where-Object { $_.Name -eq $type }
23-
if($null -ne $userInputOverride) {
24-
$result = $userInputOverride.Value
25-
return $result
26-
}
20+
$options = @()
21+
$aliasOptions = @()
22+
$typeDescription = ""
23+
24+
if($type -eq "iac") {
25+
$options += @{ key = "bicep"; name = "Bicep"; description = "Bicep" }
26+
$options += @{ key = "terraform"; name = "Terraform"; description = "Terraform" }
27+
$typeDescription = "Infrastructure as Code (IaC) language"
2728
}
2829

29-
$gotValidInput = $false
30-
31-
while(!$gotValidInput) {
32-
if($type -eq "starter") {
33-
34-
$starterFolders = Get-ChildItem -Path $starterPath -Directory
35-
Write-InformationColored "Please select the starter module you would like to use, you can enter one of the following keys:" -ForegroundColor Yellow -InformationAction Continue
36-
37-
$starterOptions = @()
38-
foreach($starterFolder in $starterFolders) {
39-
if($starterFolder.Name -eq $starterPipelineFolder) {
40-
continue
30+
if($type -eq "bootstrap") {
31+
if($bootstrapModules.PsObject.Properties.Name.Count -eq 0) {
32+
$options += @{ key = "azuredevops"; name = "Azure DevOps"; description = "Azure DevOps" }
33+
$options += @{ key = "github"; name = "GitHub"; description = "GitHub" }
34+
$aliasOptions += @{ key = "alz_azuredevops"; name = "Azure DevOps"; description = "Azure DevOps" }
35+
$aliasOptions += @{ key = "alz_github"; name = "GitHub"; description = "GitHub" }
36+
} else {
37+
foreach ($bootstrapModule in $bootstrapModules.PsObject.Properties) {
38+
$options += @{ key = $bootstrapModule.Name; name = $bootstrapModule.Value.short_name; description = $bootstrapModule.Value.description }
39+
foreach($alias in $bootstrapModule.Value.aliases) {
40+
$aliasOptions += @{ key = $alias; name = $bootstrapModule.Value.short_name; description = $bootstrapModule.Value.description }
4141
}
42+
}
43+
}
44+
$typeDescription = "bootstrap module"
45+
}
4246

43-
Write-InformationColored "- $($starterFolder.Name)" -ForegroundColor Yellow -InformationAction Continue
44-
$starterOptions += $starterFolder.Name
47+
if($type -eq "starter") {
48+
foreach($starter in $starterConfig.starter_modules.PsObject.Properties) {
49+
if($starter.Name -eq $starterPipelineFolder) {
50+
continue
4551
}
4652

47-
Write-InformationColored ": " -ForegroundColor Yellow -NoNewline -InformationAction Continue
48-
$result = Read-Host
53+
$options += @{ key = $starter.Name; name = $starter.Value.short_name; description = $starter.Value.description }
54+
}
55+
$typeDescription = "starter module"
56+
}
4957

50-
if($result -notin $starterOptions) {
51-
Write-InformationColored "The starter '$result' that you have selected does not exist. Please try again with a valid starter..." -ForegroundColor Red -InformationAction Continue
52-
} else {
53-
$gotValidInput = $true
58+
if($null -ne $userInputOverrides) {
59+
$userInputOverride = $userInputOverrides.PSObject.Properties | Where-Object { $_.Name -eq $type }
60+
if($null -ne $userInputOverride) {
61+
$result = $userInputOverride.Value
62+
if($options.key -notcontains $result -and $aliasOptions.key -notcontains $result) {
63+
Write-InformationColored "The $typeDescription '$result' that you have selected does not exist. Please try again with a valid $typeDescription..." -ForegroundColor Red -InformationAction Continue
64+
throw "The $typeDescription '$result' that you have selected does not exist. Please try again with a valid $typeDescription..."
5465
}
66+
return $result
5567
}
68+
}
5669

57-
if($type -eq "iac") {
58-
Write-InformationColored "Please select the IAC you would like to use, you can enter one of 'bicep or 'terraform': " -ForegroundColor Yellow -NoNewline -InformationAction Continue
59-
$result = Read-Host
60-
61-
$validIac = @("bicep", "terraform")
62-
if($result -notin $validIac) {
63-
Write-InformationColored "The IAC '$result' that you have selected does not exist. Please try again with a valid IAC..." -ForegroundColor Red -InformationAction Continue
70+
# Add the options to the choices array
71+
$choices = @()
72+
$usedLetters = @()
73+
foreach($option in $options) {
74+
$letterIndex = 0
6475

65-
} else {
66-
$gotValidInput = $true
67-
}
76+
Write-Verbose "Checking for used letters in '$($option.name)'. Used letters: $usedLetters"
77+
while($usedLetters -contains $option.name[$letterIndex].ToString().ToLower()) {
78+
$letterIndex++
6879
}
6980

70-
if($type -eq "bootstrap") {
71-
Write-InformationColored "Please select the bootstrap module you would like to use, you can enter one of the following keys:" -ForegroundColor Yellow -InformationAction Continue
72-
73-
$bootstrapOptions = @()
74-
if($bootstrapModules.PsObject.Properties.Name.Count -eq 0) {
75-
$bootstrapOptions += "azuredevops"
76-
Write-InformationColored "- azuredevops" -ForegroundColor Yellow -InformationAction Continue
77-
$bootstrapOptions += "github"
78-
Write-InformationColored "- github" -ForegroundColor Yellow -InformationAction Continue
79-
} else {
80-
foreach ($bootstrapModule in $bootstrapModules.PsObject.Properties) {
81-
Write-InformationColored "- $($bootstrapModule.Name) ($($bootstrapModule.Value.description))" -ForegroundColor Yellow -InformationAction Continue
82-
$bootstrapOptions += $bootstrapModule.Name
83-
}
84-
}
81+
$usedLetters += $option.name[$letterIndex].ToString().ToLower()
82+
$option.name = $option.name.Insert($letterIndex, "&")
83+
$choices += New-Object System.Management.Automation.Host.ChoiceDescription $option.name, $option.description
84+
}
8585

86-
Write-InformationColored ": " -ForegroundColor Yellow -NoNewline -InformationAction Continue
87-
$result = Read-Host
86+
$message = "Please select the $typeDescription you would like to use."
87+
$title = "Choose $typeDescription"
88+
$resultIndex = $host.ui.PromptForChoice($title, $message, $choices, 0)
89+
$result = $options[$resultIndex].key
8890

89-
if($result -notin $bootstrapOptions) {
90-
Write-InformationColored "The starter '$result' that you have selected does not exist. Please try again with a valid starter..." -ForegroundColor Red -InformationAction Continue
91-
} else {
92-
$gotValidInput = $true
93-
}
94-
}
95-
}
91+
Write-InformationColored "You selected '$result'. Continuing with deployment..." -ForegroundColor Green -InformationAction Continue
9692

9793
return $result
9894
}
99-
}
95+
}

src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ function Get-BootstrapAndStarterConfig {
2020
$starterModuleSourceFolder = ""
2121
$starterReleaseTag = ""
2222
$starterPipelineFolder = ""
23+
$starterReleaseArtifactName = ""
24+
$starterConfigFilePath = ""
2325

2426
$bootstrapDetails = $null
2527
$validationConfig = $null
@@ -61,8 +63,10 @@ function Get-BootstrapAndStarterConfig {
6163
}
6264

6365
$starterModuleUrl = $starterModuleDetails.Value.$iac.url
64-
$starterModuleSourceFolder = $starterModuleDetails.Value.$iac.module_path
65-
$starterPipelineFolder = $starterModuleDetails.Value.$iac.pipeline_folder
66+
$starterModuleSourceFolder = $starterModuleDetails.Value.$iac.release_artifact_root_path
67+
$starterPipelineFolder = $starterModuleDetails.Value.$iac.release_artifact_ci_cd_path
68+
$starterReleaseArtifactName = $starterModuleDetails.Value.$iac.release_artifact_name
69+
$starterConfigFilePath = $starterModuleDetails.Value.$iac.release_artifact_config_file
6670
}
6771

6872
# Get the bootstrap interface user input config
@@ -71,14 +75,16 @@ function Get-BootstrapAndStarterConfig {
7175
$inputConfig = Get-ALZConfig -configFilePath $inputConfigFilePath
7276

7377
return @{
74-
bootstrapDetails = $bootstrapDetails
75-
hasStarterModule = $hasStarterModule
76-
starterModuleUrl = $starterModuleUrl
77-
starterModuleSourceFolder = $starterModuleSourceFolder
78-
starterReleaseTag = $starterReleaseTag
79-
starterPipelineFolder = $starterPipelineFolder
80-
validationConfig = $validationConfig
81-
inputConfig = $inputConfig
78+
bootstrapDetails = $bootstrapDetails
79+
hasStarterModule = $hasStarterModule
80+
starterModuleUrl = $starterModuleUrl
81+
starterModuleSourceFolder = $starterModuleSourceFolder
82+
starterReleaseTag = $starterReleaseTag
83+
starterPipelineFolder = $starterPipelineFolder
84+
starterReleaseArtifactName = $starterReleaseArtifactName
85+
starterConfigFilePath = $starterConfigFilePath
86+
validationConfig = $validationConfig
87+
inputConfig = $inputConfig
8288
}
8389
}
8490
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
function Get-StarterConfig {
3+
[CmdletBinding(SupportsShouldProcess = $true)]
4+
param(
5+
[Parameter(Mandatory = $false)]
6+
[string]$starterPath,
7+
[Parameter(Mandatory = $false)]
8+
[string]$starterConfigPath
9+
)
10+
11+
if ($PSCmdlet.ShouldProcess("Get Configuration for Bootstrap and Starter", "modify")) {
12+
# Get the bootstap configuration
13+
$starterConfigFullPath = Join-Path $starterPath $starterConfigPath
14+
Write-Verbose "Starter config path $starterConfigFullPath"
15+
$starterConfig = Get-ALZConfig -configFilePath $starterConfigFullPath
16+
17+
return $starterConfig
18+
}
19+
}

src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ function New-Bootstrap {
2525
[Parameter(Mandatory = $false)]
2626
[string] $starterTargetPath,
2727

28+
[Parameter(Mandatory = $false)]
29+
[PSCustomObject] $starterConfig = $null,
30+
2831
[Parameter(Mandatory = $false)]
2932
[string] $bootstrapRelease,
3033

@@ -83,8 +86,11 @@ function New-Bootstrap {
8386
$pipelineModulePath = ""
8487

8588
if($hasStarter) {
86-
$starter = Request-SpecialInput -type "starter" -starterPath $starterPath -userInputOverrides $userInputOverrides
87-
$starterModulePath = Resolve-Path (Join-Path -Path $starterPath -ChildPath $starter)
89+
$starter = Request-SpecialInput -type "starter" -starterConfig $starterConfig -userInputOverrides $userInputOverrides
90+
91+
Write-Verbose "Selected Starter: $starter"
92+
93+
$starterModulePath = Resolve-Path (Join-Path -Path $starterPath -ChildPath $starterConfig.starter_modules.$starter.location)
8894
$pipelineModulePath = Resolve-Path (Join-Path -Path $starterPath -ChildPath $starterPipelineFolder)
8995

9096
Write-Verbose "Starter Module Path: $starterModulePath"

src/ALZ/Private/Deploy-Accelerator-Helpers/New-FolderStructure.ps1

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ function New-FolderStructure {
1010
[Parameter(Mandatory = $false)]
1111
[string] $release = "latest",
1212

13+
[Parameter(Mandatory = $false)]
14+
[string] $releaseArtifactName = "",
15+
1316
[Parameter(Mandatory = $true)]
1417
[string] $targetFolder,
1518

@@ -43,7 +46,7 @@ function New-FolderStructure {
4346
}
4447

4548
} else {
46-
$releaseTag = Get-GithubRelease -githubRepoUrl $url -targetDirectory $targetDirectory -moduleSourceFolder $sourceFolder -moduleTargetFolder $targetFolder -release $release
49+
$releaseTag = Get-GithubRelease -githubRepoUrl $url -targetDirectory $targetDirectory -moduleSourceFolder $sourceFolder -moduleTargetFolder $targetFolder -release $release -releaseArtifactName $releaseArtifactName
4750
$path = Join-Path $targetDirectory $targetFolder $releaseTag
4851
}
4952

src/ALZ/Private/Deploy-Accelerator-Helpers/New-ModuleSetup.ps1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ function New-ModuleSetup {
1313
[Parameter(Mandatory = $false)]
1414
[string]$release,
1515
[Parameter(Mandatory = $false)]
16+
[string]$releaseArtifactName = "",
17+
[Parameter(Mandatory = $false)]
1618
[string]$moduleOverrideFolderPath,
1719
[Parameter(Mandatory = $false)]
1820
[bool]$skipInternetChecks
@@ -28,6 +30,7 @@ function New-ModuleSetup {
2830
-targetDirectory $targetDirectory `
2931
-url $url `
3032
-release $release `
33+
-releaseArtifactName $releaseArtifactName `
3134
-targetFolder $targetFolder `
3235
-sourceFolder $sourceFolder `
3336
-overrideSourceDirectoryPath $moduleOverrideFolderPath

src/ALZ/Private/Shared/Get-GithubRelease.ps1

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ function Get-GithubRelease {
4242
$moduleSourceFolder = ".",
4343

4444
[Parameter(Mandatory = $true, HelpMessage = "The target directory location of the modules.")]
45-
$moduleTargetFolder
45+
$moduleTargetFolder,
46+
47+
[Parameter(Mandatory = $false, HelpMessage = "The name of the release artifact in the target release. Defaults to standard release zip.")]
48+
$releaseArtifactName = ""
4649
)
4750

4851
$parentDirectory = $targetDirectory
@@ -110,7 +113,17 @@ function Get-GithubRelease {
110113
Write-Verbose "===> Pulling and extracting release $releaseTag into $targetVersionPath"
111114
New-Item -ItemType Directory -Path "$targetVersionPath/tmp" | Out-String | Write-Verbose
112115
$targetPathForZip = "$targetVersionPath/tmp/$releaseTag.zip"
113-
Invoke-WebRequest -Uri "https://github.com/$repoOrgPlusRepo/archive/refs/tags/$releaseTag.zip" -OutFile $targetPathForZip -RetryIntervalSec 3 -MaximumRetryCount 100 | Out-String | Write-Verbose
116+
117+
# Get the artifact url
118+
if($releaseArtifactName -ne "") {
119+
$releaseArtifactUrl = $releaseData.assets | Where-Object { $_.name -eq $releaseArtifactName } | Select-Object -ExpandProperty browser_download_url
120+
} else {
121+
$releaseArtifactUrl = $releaseData.zipball_url
122+
}
123+
124+
Write-Verbose "===> Downloading the release artifact $releaseArtifactUrl from the GitHub repository $repoOrgPlusRepo"
125+
126+
Invoke-WebRequest -Uri $releaseArtifactUrl -OutFile $targetPathForZip -RetryIntervalSec 3 -MaximumRetryCount 100 | Out-String | Write-Verbose
114127

115128
if(!(Test-Path $targetPathForZip)) {
116129
Write-InformationColored "Failed to download the release $releaseTag from the GitHub repository $repoOrgPlusRepo" -ForegroundColor Red -InformationAction Continue
@@ -120,11 +133,15 @@ function Get-GithubRelease {
120133
$targetPathForExtractedZip = "$targetVersionPath/tmp/extracted"
121134

122135
Expand-Archive -Path $targetPathForZip -DestinationPath $targetPathForExtractedZip | Out-String | Write-Verbose
123-
$extractedSubFolder = Get-ChildItem -Path $targetPathForExtractedZip -Directory
124136

125-
Write-Verbose "===> Copying all extracted contents into $targetVersionPath."
137+
$extractedSubFolder = $targetPathForExtractedZip
138+
if($releaseArtifactName -eq "") {
139+
$extractedSubFolder = (Get-ChildItem -Path $targetPathForExtractedZip -Directory).FullName
140+
}
141+
142+
Write-Verbose "===> Copying all extracted contents into $targetVersionPath from $($extractedSubFolder)/$moduleSourceFolder/*."
126143

127-
Copy-Item -Path "$($extractedSubFolder.FullName)/$moduleSourceFolder/*" -Destination "$targetVersionPath" -Recurse -Force | Out-String | Write-Verbose
144+
Copy-Item -Path "$($extractedSubFolder)/$moduleSourceFolder/*" -Destination "$targetVersionPath" -Recurse -Force | Out-String | Write-Verbose
128145

129146
Remove-Item -Path "$targetVersionPath/tmp" -Force -Recurse
130147
Write-InformationColored "The directory for $targetVersionPath has been created and populated." -ForegroundColor Green -InformationAction Continue

0 commit comments

Comments
 (0)