Public/Update-UnifiedContacts.ps1
function Update-UnifiedContacts { [CmdletBinding()] Param( [Parameter (Mandatory = $true, HelpMessage = "The Url you can copy from your browser when you open the App Service. Format: https://portal.azure.com/#<domain>/resource/subscriptions/<subscriptionId>/resourceGroups/<ressourceGroupName>/providers/Microsoft.Web/sites/<appServiceName>/appServices")][string]$AppServiceAzureUrl, [Parameter (Mandatory = $false, HelpMessage = "Choose your release channel.")][string]$ReleaseChannel = $null ) $ErrorActionPreference = "Stop" #$Script:AppServiceAzureUrl = $AppServiceAzureUrl; $resourceGroup = (($AppServiceAzureUrl -Split "resourceGroups/")[1] -Split "/")[0] $subscriptionId = (($AppServiceAzureUrl -Split "subscriptions/")[1] -Split "/")[0] $appServiceName = (($AppServiceAzureUrl -Split "sites/")[1] -Split "/")[0] Write-Host "ResourceGroup: $resourceGroup`nSubscriptionId: $subscriptionId`nAppServiceName: $appServiceName" Import-Module Az.Resources try { Get-LatestModuleVersion try { $context = Get-AzContext } catch { #fall through } if ($null -eq $context) { [void] (Connect-AzAccount -Subscription $subscriptionId) } elseif ($context.Subscription.Id -ne $subscriptionId) { [void] (Set-AzContext -Subscription $subscriptionId) } az account set --subscription $subscriptionId | Out-Null $response = Invoke-WebRequest -Uri $Script:versionManifesUri -UseBasicParsing if ($response.StatusCode -lt 200 -or $response.StatusCode -ge 300) { throw "Could not accquire versionManifest" } Write-Progress -Activity "Update Unified Contacts" -Status "Get Web App Information" -PercentComplete 5 $versionManifest = $response.Content | ConvertFrom-Json $appService = Get-AzWebApp -ResourceGroupName $resourceGroup -Name $appServiceName if ($null -eq ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq $Script:AppServiceAzureUrlPropertyName })) { $settings = @{} foreach ($appsetting in $appService.SiteConfig.AppSettings) { $settings.add($appsetting.Name, $appsetting.Value) } $settings.add($Script:appServiceAzureUrlPropertyName, $AppServiceAzureUrl) Set-AzWebApp -ResourceGroupName $resourceGroup -Name $appServiceName -AppSettings $settings } $storageAccountName = ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq $Script:storageAccountPropertyName }).value $destContext = New-AzStorageContext -StorageAccountName $storageAccountName $me = Get-AzADUser -UserPrincipalName (az account show --query user.name --output tsv) Write-Progress -Activity "Update Unified Contacts" -Status "Check necessary permissions" -PercentComplete 15 $role = Get-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Blob Data Contributor" if ($null -eq $role) { New-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Blob Data Contributor" | Out-Null $roleReady = $null while ($null -eq $roleReady) { Start-Sleep -Seconds 10 $roleReady = Get-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Blob Data Contributor" } } Write-Progress -Activity "Update Unified Contacts" -Status "Get selected release channel" -PercentComplete 25 $selectedChannel = $versionManifest.channels | Where-Object { $_.name -eq $releaseChannel } if ($null -eq $releaseChannel -or $null -eq $selectedChannel ) { $title = "From which release channel do you want to update?" $prompt = "Enter your choice" $default = 0 $choicesRaw = @("&Stable", "&Preview", "&Nightly") $releaseChannelName = @() $choices = [System.Management.Automation.Host.ChoiceDescription[]] @() $choicesRaw | ForEach-Object { $choices += [System.Management.Automation.Host.ChoiceDescription]$_ $releaseChannelName += $_.TrimStart("&").ToLower() } $releaseChannel = $host.UI.PromptForChoice($title, $prompt, $choices, $default) $selectedChannel = $versionManifest.channels | Where-Object { $_.name -eq $releaseChannelName[$releaseChannel] } } Write-Progress -Activity "Update Unified Contacts" -Status "Update Infrastructure" -PercentComplete 40 Update-Infrastructure -SubscriptionId $subscriptionId -destContext $destContext -resourceGroupName $resourceGroup -storageAcccountName $storageAccountName -AppServiceName $appServiceName -selectedVersion $selectedChannel.latestVersion $currentVersion = ((Get-Version -AppService $appService).Content | ConvertFrom-Json).version if ($currentVersion -eq $selectedChannel.latestVersion) { Write-Host "The latest version is already deployed." -ForegroundColor Yellow return; } Write-Progress -Activity "Update Unified Contacts" -Status "Copy Binaries" -PercentComplete 65 Start-AzStorageBlobCopy -AbsoluteUri $selectedChannel.latestVersionRef -DestContainer "unified-contacts" -DestBlob "binaries.zip" -DestContext $destContext -Force | Out-Null $role = Get-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Table Data Contributor" if ($null -eq $role) { New-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Table Data Contributor" | Out-Null $roleReady = $null while ($null -eq $roleReady) { Start-Sleep -Seconds 10 #wait for roleassignment to be present in Entra Id $roleReady = Get-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Table Data Contributor" } } Write-Progress -Activity "Update Unified Contacts" -Status "Restart Web App" -PercentComplete 75 Restart-AzWebApp -ResourceGroupName $resourceGroup -Name $appServiceName | Out-Null Start-Sleep -Seconds 20 $timeout = (Get-Date).AddMinutes(5) $responseReady = $null $timeout = (Get-Date).AddMinutes(10) $restartedWebApp = $false while ((Get-Date) -lt $timeout) { Start-Sleep -Seconds 5 if ((Get-AzWebApp -Name $appServiceName -ResourceGroupName $resourceGroup).State -eq "Running") { # AppService has successfully restarted if we get a 2XX returned with the current version $responseReady = $null try { $responseReady = Get-Version -AppService $appService -ErrorAction 'SilentlyContinue' } catch [Microsoft.PowerShell.Commands.HttpResponseException] { $responseReady = $_.Exception.Response } catch { Write-Warning "No Http-Error was thrown: $_" } if ($null -ne $responseReady -and $responseReady.StatusCode -ge 200 -and $responseReady.StatusCode -le 299 -and $null -ne $responseReady.Content -and ($responseReady.Content | ConvertFrom-Json).version -eq $selectedChannel.latestVersion) { Write-Host "AppService successfully restarted" -ForegroundColor Green $restartedWebApp = $true break; } } } if ($restartedWebApp) { Write-Host "Go to https://$($appService.hostnames[0]) to upload the Manifest." -ForegroundColor Yellow Write-Host "Please refresh the Unified Contacts Admin Portal using Shift+F5 to refresh the cache." -ForegroundColor Yellow } else { Write-Error "Restarting of App Service failed. Please try to restart the App Service manually ($appServiceAzureUrl) or try to update Unified Contacts again." } } catch { Write-Error "Something went wrong please. Try again later. Error: $_" -ErrorAction 'Continue' } } |