Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cli/azd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ Install Go extension https://marketplace.visualstudio.com/items?itemName=golang.
## Contribute

See [CONTRIBUTING.md](./CONTRIBUTING.md) for information on contributing.

Trivial change to trigger CI build.
92 changes: 64 additions & 28 deletions eng/common/TestResources/New-TestResources.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ param (

$wellKnownTMETenants = @('70a036f6-8e4d-4615-bad6-149c02e7720d')

# People keep passing this legacy parameter. Throw an error to save them future keystrokes
if ($NewTestResourcesRemainingArguments -like '*UserAuth*') {
throw "The -UserAuth parameter is deprecated and is now the default behavior"
}

if (!$ServicePrincipalAuth) {
# Clear secrets if not using Service Principal auth. This prevents secrets
# from being passed to pre- and post-scripts.
Expand Down Expand Up @@ -174,7 +179,7 @@ try {
}
Write-Verbose "Overriding test resources search directory to '$root'"
}

$templateFiles = @()

"$ResourceType-resources.json", "$ResourceType-resources.bicep" | ForEach-Object {
Expand All @@ -198,7 +203,7 @@ try {

# returns empty string if $ServiceDirectory is not set
$serviceName = GetServiceLeafDirectoryName $ServiceDirectory

# in ci, random names are used
# in non-ci, without BaseName, ResourceGroupName or ServiceDirectory, all invocations will
# generate the same resource group name and base name for a given user
Expand Down Expand Up @@ -267,13 +272,13 @@ try {
if ($context.Tenant.Name -like '*TME*') {
if ($currentSubscriptionId -ne '4d042dc6-fe17-4698-a23f-ec6a8d1e98f4') {
Log "Attempting to select subscription 'Azure SDK Test Resources - TME (4d042dc6-fe17-4698-a23f-ec6a8d1e98f4)'"
$null = Select-AzSubscription -Subscription '4d042dc6-fe17-4698-a23f-ec6a8d1e98f4' -ErrorAction Ignore
$null = Select-AzSubscription -Subscription '4d042dc6-fe17-4698-a23f-ec6a8d1e98f4' -ErrorAction Ignore -WarningAction Ignore
# Update the context.
$context = Get-AzContext
}
} elseif ($currentSubcriptionId -ne 'faa080af-c1d8-40ad-9cce-e1a450ca5b57') {
Log "Attempting to select subscription 'Azure SDK Developer Playground (faa080af-c1d8-40ad-9cce-e1a450ca5b57)'"
$null = Select-AzSubscription -Subscription 'faa080af-c1d8-40ad-9cce-e1a450ca5b57' -ErrorAction Ignore
$null = Select-AzSubscription -Subscription 'faa080af-c1d8-40ad-9cce-e1a450ca5b57' -ErrorAction Ignore -WarningAction Ignore
# Update the context.
$context = Get-AzContext
}
Expand Down Expand Up @@ -305,7 +310,7 @@ try {
}
}

# This needs to happen after we set the TenantId but before we use the ResourceGroupName
# This needs to happen after we set the TenantId but before we use the ResourceGroupName
if ($wellKnownTMETenants.Contains($TenantId)) {
# Add a prefix to the resource group name to avoid flagging the usages of local auth
# See details at https://eng.ms/docs/products/onecert-certificates-key-vault-and-dsms/key-vault-dsms/certandsecretmngmt/credfreefaqs#how-can-i-disable-s360-reporting-when-testing-customer-facing-3p-features-that-depend-on-use-of-unsafe-local-auth
Expand Down Expand Up @@ -353,15 +358,19 @@ try {
# Make sure the provisioner OID is set so we can pass it through to the deployment.
if (!$ProvisionerApplicationId -and !$ProvisionerApplicationOid) {
if ($context.Account.Type -eq 'User') {
# Support corp tenant and TME tenant user id lookups
$user = Get-AzADUser -Mail $context.Account.Id
if ($null -eq $user -or !$user.Id) {
$user = Get-AzADUser -UserPrincipalName $context.Account.Id
# Calls to graph API in corp tenant get blocked by conditional access policy now
# but not in TME. For corp tenant we get the user's id from the login context
# but for TME it is different so we have to source it from graph
$userAccountId = if ($wellKnownTMETenants.Contains($TenantId)) {
(Get-AzADUser -SignedIn).Id
} else {
# HomeAccountId format is '<object id>.<tenant id>'
(Get-AzContext).Account.ExtendedProperties.HomeAccountId.Split('.')[0]
}
if ($null -eq $user -or !$user.Id) {
if ($null -eq $userAccountId) {
throw "Failed to find entra object ID for the current user"
}
$ProvisionerApplicationOid = $user.Id
$ProvisionerApplicationOid = $userAccountId
} elseif ($context.Account.Type -eq 'ServicePrincipal') {
$sp = Get-AzADServicePrincipal -ApplicationId $context.Account.Id
$ProvisionerApplicationOid = $sp.Id
Expand Down Expand Up @@ -428,20 +437,25 @@ try {

if (!$CI -and !$ServicePrincipalAuth) {
if ($TestApplicationId) {
Write-Warning "The specified TestApplicationId '$TestApplicationId' will be ignored when -ServicePrincipalAutth is not set."
Write-Warning "The specified TestApplicationId '$TestApplicationId' will be ignored when -ServicePrincipalAuth is not set."
}

# Support corp tenant and TME tenant user id lookups
$userAccount = (Get-AzADUser -Mail (Get-AzContext).Account.Id)
if ($null -eq $userAccount -or !$userAccount.Id) {
$userAccount = (Get-AzADUser -UserPrincipalName (Get-AzContext).Account)
$userAccountName = (Get-AzContext).Account.Id
# HomeAccountId format is '<object id>.<tenant id>'
# Calls to graph API in corp tenant get blocked by conditional access policy now
# but not in TME. For corp tenant we get the user's id from the login context
# but for TME it is different so we have to source it from graph
$userAccountId = if ($wellKnownTMETenants.Contains($TenantId)) {
(Get-AzADUser -SignedIn).Id
} else {
# HomeAccountId format is '<object id>.<tenant id>'
(Get-AzContext).Account.ExtendedProperties.HomeAccountId.Split('.')[0]
}
if ($null -eq $userAccount -or !$userAccount.Id) {
if ($null -eq $userAccountId) {
throw "Failed to find entra object ID for the current user"
}
$TestApplicationOid = $userAccount.Id
$TestApplicationOid = $userAccountId
$TestApplicationId = $testApplicationOid
$userAccountName = $userAccount.UserPrincipalName
Log "User authentication with user '$userAccountName' ('$TestApplicationId') will be used."
}
# If user has specified -ServicePrincipalAuth
Expand Down Expand Up @@ -613,22 +627,44 @@ try {
}
Log $msg

$deployment = Retry {
New-AzResourceGroupDeployment `
# Run a first pass outside of Retry to fail fast for
# template validation errors that won't be fixed with retries.
# Only run Test-AzResourceGroupDeployment after error because it can
# take a while for large templates even during success cases.
try {
$deployment = New-AzResourceGroupDeployment `
-Name $BaseName `
-ResourceGroupName $resourceGroup.ResourceGroupName `
-TemplateFile $templateFile.jsonFilePath `
-TemplateParameterObject $templateFileParameters `
-Force:$Force
} catch {
# Throw if we hit a template validation error, otherwise proceed
if ($_.Exception.Message -like '*InvalidTemplateDeployment*') {
$validation = Test-AzResourceGroupDeployment `
-ResourceGroupName $resourceGroup.ResourceGroupName `
-TemplateFile $templateFile.jsonFilePath `
-TemplateParameterObject $templateFileParameters

HandleTemplateDeploymentError $validation
throw
}
}

if (!$deployment -or $deployment.ProvisioningState -ne 'Succeeded') {
Write-Warning "Initial deployment attempt failed, retrying..."
$deployment = Retry -Attempts 4 -Action {
New-AzResourceGroupDeployment `
-Name $BaseName `
-ResourceGroupName $resourceGroup.ResourceGroupName `
-TemplateFile $templateFile.jsonFilePath `
-TemplateParameterObject $templateFileParameters `
-Force:$Force
}
}

if ($deployment.ProvisioningState -ne 'Succeeded') {
Write-Host "Deployment '$($deployment.DeploymentName)' has state '$($deployment.ProvisioningState)' with CorrelationId '$($deployment.CorrelationId)'. Exiting..."
Write-Host @'
#####################################################
# For help debugging live test provisioning issues, #
# see http://aka.ms/azsdk/engsys/live-test-help #
#####################################################
'@
HandleDeploymentFailure $deployment
exit 1
}

Expand Down
77 changes: 54 additions & 23 deletions eng/common/TestResources/TestResources-Helpers.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,6 @@ function LintBicepFile([string] $path) {
}

# Work around lack of config file override: https://github.com/Azure/bicep/issues/5013
$output = bicep lint $path 2>&1

if ($useBicepCli) {
$output = bicep lint $path 2>&1
} else {
Expand Down Expand Up @@ -264,9 +262,10 @@ function SetDeploymentOutputs(
) {
$deploymentEnvironmentVariables = $environmentVariables.Clone()
$deploymentOutputs = BuildDeploymentOutputs $serviceName $azContext $deployment $deploymentEnvironmentVariables
$isBicep = $templateFile.originalFilePath -and $templateFile.originalFilePath.EndsWith(".bicep")

if ($OutFile) {
if ($IsWindows -and $Language -eq 'dotnet') {
# Azure SDK for .NET on Windows uses DPAPI-encrypted, JSON-encoded environment variables.
if ($OutFile -and $IsWindows -and $Language -eq 'dotnet') {
$outputFile = "$($templateFile.originalFilePath).env"

$environmentText = $deploymentOutputs | ConvertTo-Json;
Expand All @@ -276,29 +275,29 @@ function SetDeploymentOutputs(
Set-Content $outputFile -Value $protectedBytes -AsByteStream -Force

Write-Host "Test environment settings`n$environmentText`nstored into encrypted $outputFile"
}
# Any Bicep template in a repo that has opted into .env files.
elseif ($OutFile -and $isBicep) {
$bicepTemplateFile = $templateFile.originalFilePath

# Make sure the file would not write secrets to .env file.
if (!(LintBicepFile $bicepTemplateFile)) {
Write-Error "$bicepTemplateFile may write secrets. No file written."
}
elseif ($templateFile.originalFilePath -and $templateFile.originalFilePath.EndsWith(".bicep")) {
$bicepTemplateFile = $templateFile.originalFilePath
$outputFile = $bicepTemplateFile | Split-Path | Join-Path -ChildPath '.env'

# Make sure the file would not write secrets to .env file.
if (!(LintBicepFile $bicepTemplateFile)) {
Write-Error "$bicepTemplateFile may write secrets. No file written."
# Make sure the file would be ignored.
git check-ignore -- "$outputFile" > $null
if ($?) {
$environmentText = foreach ($kv in $deploymentOutputs.GetEnumerator()) {
"$($kv.Key)=`"$($kv.Value)`""
}
$outputFile = $bicepTemplateFile | Split-Path | Join-Path -ChildPath '.env'

# Make sure the file would be ignored.
git check-ignore -- "$outputFile" > $null
if ($?) {
$environmentText = foreach ($kv in $deploymentOutputs.GetEnumerator()) {
"$($kv.Key)=`"$($kv.Value)`""
}

Set-Content $outputFile -Value $environmentText -Force
Write-Host "Test environment settings`n$environmentText`nstored in $outputFile"
}
else {
Write-Error "$outputFile is not ignored by .gitignore. No file written."
}
Set-Content $outputFile -Value $environmentText -Force
Write-Host "Test environment settings`n$environmentText`nstored in $outputFile"
}
else {
Write-Error "$outputFile is not ignored by .gitignore. No file written."
}
}
else {
Expand Down Expand Up @@ -349,3 +348,35 @@ function SetDeploymentOutputs(

return $deploymentEnvironmentVariables, $deploymentOutputs
}

function HandleTemplateDeploymentError($templateValidationResult) {
Write-Warning "Deployment template validation failed"

if (!$templateValidationResult.Details.Message) {
Write-Warning "Could not parse template validation error"
return
}

# Retrieve one or more messages then decode the strings for readability (remove quote escapes, fix link readability, etc.)
$parsedMessage = ($templateValidationResult.Details.Message -join "$([System.Environment]::NewLine)$([System.Environment]::NewLine)")
$parsedMessage = [System.Net.WebUtility]::UrlDecode($parsedMessage)

Write-Warning "#####################################################"
Write-Warning "######### TEMPLATE VALIDATION ERROR DETAILS #########"
Write-Warning "#####################################################"
Write-Host $parsedMessage
Write-Warning "#####################################################"
}

function HandleDeploymentFailure($deployment) {
Write-Host "Deployment '$($deployment.DeploymentName)' has state '$($deployment.ProvisioningState)' with CorrelationId '$($deployment.CorrelationId)'. Exiting..."
Write-Host @'
#####################################################
# For help debugging live test provisioning issues, #
# see http://aka.ms/azsdk/engsys/live-test-help #
#####################################################
'@
$queryTime = (Get-Date).AddMinutes(-10).ToString("o")
Write-Host "To check the activity log with the below command after waiting 2 minutes for propagation:"
Write-Host "(Get-AzActivityLog -CorrelationId '$($deployment.CorrelationId)' -StartTime '$queryTime').Properties.Content.statusMessage"
}
7 changes: 5 additions & 2 deletions eng/common/TestResources/deploy-test-resources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ parameters:
ServiceDirectory: ''
TestResourcesDirectory: ''
ArmTemplateParameters: '@{}'
AdditionalParameters: '@{}'
DeleteAfterHours: 8
Location: ''
EnvVars: {}
Expand Down Expand Up @@ -103,7 +104,8 @@ steps:
-Location '${{ parameters.Location }}' `
-DeleteAfterHours '${{ parameters.DeleteAfterHours }}' `
@subscriptionConfiguration `
-AdditionalParameters ${{ parameters.ArmTemplateParameters }} `
-ArmTemplateParameters ${{ parameters.ArmTemplateParameters }} `
-AdditionalParameters ${{ parameters.AdditionalParameters }} `
-AllowIpRanges ('$(azsdk-corp-net-ip-ranges)' -split ',') `
-SelfContainedPostScript $postScriptPath `
-CI `
Expand Down Expand Up @@ -148,7 +150,8 @@ steps:
-Location '${{ parameters.Location }}' `
-DeleteAfterHours '${{ parameters.DeleteAfterHours }}' `
@subscriptionConfiguration `
-AdditionalParameters ${{ parameters.ArmTemplateParameters }} `
-ArmTemplateParameters ${{ parameters.ArmTemplateParameters }} `
-AdditionalParameters ${{ parameters.AdditionalParameters }} `
-AllowIpRanges ('$(azsdk-corp-net-ip-ranges)' -split ',') `
-CI `
-ServicePrincipalAuth `
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
description: 'This prompt is designed to check the release readiness of a SDK package.'
---
## Goal
Check the release readiness of an SDK package by collecting the required information from the user and executing the readiness check.

## Instructions
1. **Collect Required Information**:
- Prompt the user for the exact package name
- Prompt the user to select the programming language from the following options (case sensitive):
- Python
- Java
- JavaScript
- .NET
- Go

2. **Execute Readiness Check**:
- Use the `azsdk_release_sdk` tool with the provided package name, selected language, and set checkReady to true.
- Do not check for existing pull requests to run this step.
- Do not ask the user to create a release plan to run this step.

3. **Present Results**:
- If the package is ready for release, highlight and provide the link to the release pipeline
- If the package is not ready, display the specific issues that need to be resolved

4. **Follow-up Actions**:
- Provide clear next steps based on the readiness status
- If issues are found, offer guidance on how to resolve them

## Expected User Interaction Flow
1. Ask: "What is the exact name of the package you want to check for release readiness?"
2. Ask: "Please select the programming language for this package: Python, Java, JavaScript, .NET, or Go"
3. Execute the readiness check using the provided information
4. Display results and next steps
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
description: 'Run the package validation checks for the SDK package.'
---
## Goal
Run the validation checks for the SDK package by collecting the required information from the user and executing the `azsdk_package_run_check` tool.

## Instructions
1. **Collect Required Information**:
- Prompt the user for the absolute package path to the package directory for the SDK package they want to check.
- Prompt the user to specify values for each of the parameters required by the azsdk_package_run_check tool. Present the user with options to pick from for the allowed values specified by the parameter schema.

2. **Execute Check**:
- Use the `azsdk_package_run_check` tool with the package path and check type.

3. **Present Results**:
- If the package has passed all validation checks, highlight and finish
- If the package is not ready, display the specific check types that need to be fixed for each language.

## Expected User Interaction Flow
1. Ask: "What is the exact path of the package you want to check for validation?"
2. Ask: "Please specify the check type you want to run (e.g., 'all', 'linting', 'format', etc.)"
3. Execute the check using the provided information
4. Display results and next steps
Loading
Loading