Skip to content

Commit

Permalink
Fix issues caused by vsix changes + publish timeout on publishing apps (
Browse files Browse the repository at this point in the history
#3258)

When using Publish-PerTenantExtensionApps with a set of apps, which
takes a very long time to publish, the AccessToken might expire and lead
to failure. AccessToken is now refreshed when needed.
Issue #3254 vsix no longer includes dotnet framework 4.8 compatible dlls
for version 24
Avoid using CDN when downloading from bcinsider as this frequently
changes and subsequently fails

---------

Co-authored-by: freddydk <freddydk@users.noreply.github.com>
  • Loading branch information
freddydk and freddydk authored Dec 1, 2023
1 parent 9cf2f23 commit 97af5cf
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 56 deletions.
53 changes: 34 additions & 19 deletions AppHandling/Compile-AppInNavContainer.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -502,28 +502,43 @@ try {
try {
# Import types needed to invoke the compiler
$alcPath = 'C:\build\vsix\extension\bin'
Add-Type -Path (Join-Path $alcPath Newtonsoft.Json.dll)
Add-Type -Path (Join-Path $alcPath System.Collections.Immutable.dll)
Add-Type -Path (Join-Path $alcPath System.IO.Packaging.dll)
Add-Type -Path (Join-Path $alcPath Microsoft.Dynamics.Nav.CodeAnalysis.dll)

$packageStream = [System.IO.File]::OpenRead($symbolsFile)
$package = [Microsoft.Dynamics.Nav.CodeAnalysis.Packaging.NavAppPackageReader]::Create($PackageStream, $true)
$manifest = $package.ReadNavAppManifest()

if ($manifest.application) {
@{ "publisher" = "Microsoft"; "name" = "Application"; "appId" = ''; "version" = $manifest.Application }
$alToolExe = Join-Path $alcPath 'win32\altool.exe'
$alToolExists = Test-Path -Path $alToolExe -PathType Leaf
if ($alToolExists) {
$manifest = & "$alToolExe" GetPackageManifest "$symbolsFile" | ConvertFrom-Json
if ($manifest.PSObject.Properties.Name -eq 'application' -and $manifest.application) {
@{ "publisher" = "Microsoft"; "name" = "Application"; "appId" = ''; "version" = $manifest.Application }
}
if ($manifest.PSObject.Properties.Name -eq 'dependencies') {
foreach ($dependency in $manifest.dependencies) {
@{ "publisher" = $dependency.Publisher; "name" = $dependency.name; "appId" = $dependency.id; "Version" = $dependency.Version }
}
}
}

foreach ($dependency in $manifest.dependencies) {
$appId = ''
if ($dependency.psobject.Properties.name -eq 'appid') {
$appId = $dependency.appid
else {
Add-Type -Path (Join-Path $alcPath Newtonsoft.Json.dll)
Add-Type -Path (Join-Path $alcPath System.Collections.Immutable.dll)
Add-Type -Path (Join-Path $alcPath System.IO.Packaging.dll)
Add-Type -Path (Join-Path $alcPath Microsoft.Dynamics.Nav.CodeAnalysis.dll)

$packageStream = [System.IO.File]::OpenRead($symbolsFile)
$package = [Microsoft.Dynamics.Nav.CodeAnalysis.Packaging.NavAppPackageReader]::Create($PackageStream, $true)
$manifest = $package.ReadNavAppManifest()

if ($manifest.application) {
@{ "publisher" = "Microsoft"; "name" = "Application"; "appId" = ''; "version" = $manifest.Application }
}
elseif ($dependency.psobject.Properties.name -eq 'id') {
$appId = $dependency.id

foreach ($dependency in $manifest.dependencies) {
$appId = ''
if ($dependency.psobject.Properties.name -eq 'appid') {
$appId = $dependency.appid
}
elseif ($dependency.psobject.Properties.name -eq 'id') {
$appId = $dependency.id
}
@{ "publisher" = $dependency.Publisher; "name" = $dependency.name; "appId" = $appId; "Version" = $dependency.Version }
}
@{ "publisher" = $dependency.Publisher; "name" = $dependency.name; "appId" = $appId; "Version" = $dependency.Version }
}
}
catch [System.Reflection.ReflectionTypeLoadException] {
Expand Down
3 changes: 2 additions & 1 deletion Common/Download-File.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ try {
Invoke-WebRequest -UseBasicParsing -Uri $sourceUrl -OutFile $destinationFile
}
else {
if ($bcContainerHelperConfig.DoNotUseCdnForArtifacts) {
if ($bcContainerHelperConfig.DoNotUseCdnForArtifacts -or $sourceUrl -like 'https://bcinsider.azureedge.net/*') {
# Do not use CDN when configured or bcinsider
$sourceUrl = ReplaceCDN -sourceUrl $sourceUrl
}
try {
Expand Down
2 changes: 0 additions & 2 deletions CompilerFolderHandling/Compile-AppWithBcCompilerFolder.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,8 @@ try {
throw "CompilerFolder doesn't exist"
}

$vsixPath = Join-Path $compilerFolder 'compiler'
$dllsPath = Join-Path $compilerFolder 'dlls'
$symbolsPath = Join-Path $compilerFolder 'symbols'
$binPath = Join-Path $vsixPath 'extension/bin'

$appJsonFile = Join-Path $appProjectFolder 'app.json'
$appJsonObject = [System.IO.File]::ReadAllLines($appJsonFile) | ConvertFrom-Json
Expand Down
6 changes: 6 additions & 0 deletions CompilerFolderHandling/New-BcCompilerFolder.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ try {
}

if ($isLinux) {
$alToolExePath = Join-Path $containerCompilerPath 'extension/bin/linux/altool'
if (Test-Path $alToolExePath) {
# Set execute permissions on altool
Write-Host "Setting execute permissions on altool"
& /usr/bin/env sudo pwsh -command "& chmod +x $alToolExePath"
}
$alcExePath = Join-Path $containerCompilerPath 'extension/bin/linux/alc'
if (Test-Path $alcExePath) {
# Set execute permissions on alc
Expand Down
58 changes: 38 additions & 20 deletions HelperFunctions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1118,13 +1118,16 @@ function GetAppInfo {
$binPath = Join-Path $compilerFolder 'compiler/extension/bin'
if ($isLinux) {
$alcPath = Join-Path $binPath 'linux'
$alToolExe = Join-Path $alcPath 'altool'
}
else {
$alcPath = Join-Path $binPath 'win32'
$alToolExe = Join-Path $alcPath 'altool.exe'
}
if (-not (Test-Path $alcPath)) {
$alcPath = $binPath
}
$alToolExists = Test-Path -Path $alToolExe -PathType Leaf
$alcDllPath = $alcPath
if (!$isLinux -and !$isPsCore) {
$alcDllPath = $binPath
Expand All @@ -1142,27 +1145,42 @@ function GetAppInfo {
Write-Host " (cached)"
}
else {
if (!$assembliesAdded) {
Add-Type -AssemblyName System.IO.Compression.FileSystem
Add-Type -AssemblyName System.Text.Encoding
LoadDLL -Path (Join-Path $alcDllPath Newtonsoft.Json.dll)
LoadDLL -Path (Join-Path $alcDllPath System.Collections.Immutable.dll)
LoadDLL -Path (Join-Path $alcDllPath System.IO.Packaging.dll)
LoadDLL -Path (Join-Path $alcDllPath Microsoft.Dynamics.Nav.CodeAnalysis.dll)
$assembliesAdded = $true
if ($alToolExists) {
$manifest = CmdDo -Command $alToolExe -arguments @('GetPackageManifest', """$path""") -returnValue -silent | ConvertFrom-Json
$appInfo = @{
"appId" = $manifest.id
"publisher" = $manifest.publisher
"name" = $manifest.name
"version" = $manifest.version
"application" = "$(if($manifest.PSObject.Properties.Name -eq 'application'){$manifest.application})"
"platform" = "$(if($manifest.PSObject.Properties.Name -eq 'platform'){$manifest.Platform})"
"propagateDependencies" = ($manifest.PSObject.Properties.Name -eq 'PropagateDependencies') -and $manifest.PropagateDependencies
"dependencies" = @(if($manifest.PSObject.Properties.Name -eq 'dependencies'){$manifest.dependencies | ForEach-Object { @{ "id" = $_.id; "name" = $_.name; "publisher" = $_.publisher; "version" = $_.version }}})
}
}
$packageStream = [System.IO.File]::OpenRead($path)
$package = [Microsoft.Dynamics.Nav.CodeAnalysis.Packaging.NavAppPackageReader]::Create($PackageStream, $true)
$manifest = $package.ReadNavAppManifest()
$appInfo = @{
"appId" = $manifest.AppId
"publisher" = $manifest.AppPublisher
"name" = $manifest.AppName
"version" = "$($manifest.AppVersion)"
"dependencies" = @($manifest.Dependencies | ForEach-Object { @{ "id" = $_.AppId; "name" = $_.Name; "publisher" = $_.Publisher; "version" = "$($_.Version)" } })
"application" = "$($manifest.Application)"
"platform" = "$($manifest.Platform)"
"propagateDependencies" = $manifest.PropagateDependencies
else {
if (!$assembliesAdded) {
Add-Type -AssemblyName System.IO.Compression.FileSystem
Add-Type -AssemblyName System.Text.Encoding
LoadDLL -Path (Join-Path $alcDllPath Newtonsoft.Json.dll)
LoadDLL -Path (Join-Path $alcDllPath System.Collections.Immutable.dll)
LoadDLL -Path (Join-Path $alcDllPath System.IO.Packaging.dll)
LoadDLL -Path (Join-Path $alcDllPath Microsoft.Dynamics.Nav.CodeAnalysis.dll)
$assembliesAdded = $true
}
$packageStream = [System.IO.File]::OpenRead($path)
$package = [Microsoft.Dynamics.Nav.CodeAnalysis.Packaging.NavAppPackageReader]::Create($PackageStream, $true)
$manifest = $package.ReadNavAppManifest()
$appInfo = @{
"appId" = $manifest.AppId
"publisher" = $manifest.AppPublisher
"name" = $manifest.AppName
"version" = "$($manifest.AppVersion)"
"dependencies" = @($manifest.Dependencies | ForEach-Object { @{ "id" = $_.AppId; "name" = $_.Name; "publisher" = $_.Publisher; "version" = "$($_.Version)" } })
"application" = "$($manifest.Application)"
"platform" = "$($manifest.Platform)"
"propagateDependencies" = $manifest.PropagateDependencies
}
}
Write-Host " (succeeded)"
if ($appInfoCache) {
Expand Down
3 changes: 3 additions & 0 deletions ReleaseNotes.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
6.0.2
When using Publish-PerTenantExtensionApps with a set of apps, which takes a very long time to publish, the AccessToken might expire and lead to failure. AccessToken is now refreshed when needed.
Issue #3254 vsix no longer includes dotnet framework 4.8 compatible dlls for version 24
Avoid using CDN when downloading from bcinsider as this frequently changes and subsequently fails

6.0.1
New-AadAppsForBC doesn't work with the newer versions of Microsoft.Graph module (where the type of the accesstoken parameter has changed)
Expand Down
29 changes: 15 additions & 14 deletions Saas/Publish-PerTenantExtensionApps.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ function Publish-PerTenantExtensionApps {
$telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @()
try {

function GetAuthHeaders {
$bcAuthContext = Renew-BcAuthContext -bcAuthContext $bcAuthContext
return @{ "Authorization" = "Bearer $($bcAuthContext.AccessToken)" }
}

$newLine = @{}
if (!$useNewLine) {
$newLine = @{ "NoNewLine" = $true }
Expand All @@ -70,18 +75,14 @@ try {
throw "Authentication failed"
}
}
else {
$bcAuthContext = Renew-BcAuthContext -bcAuthContext $bcAuthContext
}

$appFolder = Join-Path ([System.IO.Path]::GetTempPath()) ([guid]::NewGuid().ToString())
try {
$appFiles = CopyAppFilesToFolder -appFiles $appFiles -folder $appFolder
$automationApiUrl = "$($bcContainerHelperConfig.apiBaseUrl.TrimEnd('/'))/v2.0/$environment/api/microsoft/automation/v2.0"

$authHeaders = @{ "Authorization" = "Bearer $($bcauthcontext.AccessToken)" }
Write-Host "$automationApiUrl/companies"
$companies = Invoke-RestMethod -Headers $authHeaders -Method Get -Uri "$automationApiUrl/companies" -UseBasicParsing
$companies = Invoke-RestMethod -Headers (GetAuthHeaders) -Method Get -Uri "$automationApiUrl/companies" -UseBasicParsing
$company = $companies.value | Where-Object { ($companyName -eq "") -or ($_.name -eq $companyName) } | Select-Object -First 1
if (!($company)) {
throw "No company $companyName"
Expand All @@ -90,7 +91,7 @@ try {
Write-Host "Company '$companyName' has id $companyId"

Write-Host "$automationApiUrl/companies($companyId)/extensions"
$getExtensions = Invoke-WebRequest -Headers $authHeaders -Method Get -Uri "$automationApiUrl/companies($companyId)/extensions" -UseBasicParsing
$getExtensions = Invoke-WebRequest -Headers (GetAuthHeaders) -Method Get -Uri "$automationApiUrl/companies($companyId)/extensions" -UseBasicParsing
$extensions = (ConvertFrom-Json $getExtensions.Content).value | Sort-Object -Property DisplayName

if(!$hideInstalledExtensionsOutput) {
Expand Down Expand Up @@ -147,20 +148,20 @@ try {
Write-Host @newLine "publishing and installing"
}
if (!$existingApp) {
$extensionUpload = (Invoke-RestMethod -Method Get -Uri "$automationApiUrl/companies($companyId)/extensionUpload" -Headers $authHeaders).value
$extensionUpload = (Invoke-RestMethod -Method Get -Uri "$automationApiUrl/companies($companyId)/extensionUpload" -Headers (GetAuthHeaders)).value
Write-Host @newLine "."
if ($extensionUpload -and $extensionUpload.systemId) {
$extensionUpload = Invoke-RestMethod `
-Method Patch `
-Uri "$automationApiUrl/companies($companyId)/extensionUpload($($extensionUpload.systemId))" `
-Headers ($authHeaders + $ifMatchHeader + $jsonHeader) `
-Headers ((GetAuthHeaders) + $ifMatchHeader + $jsonHeader) `
-Body ($body | ConvertTo-Json -Compress)
}
else {
$ExtensionUpload = Invoke-RestMethod `
-Method Post `
-Uri "$automationApiUrl/companies($companyId)/extensionUpload" `
-Headers ($authHeaders + $jsonHeader) `
-Headers ((GetAuthHeaders) + $jsonHeader) `
-Body ($body | ConvertTo-Json -Compress)
}
Write-Host @newLine "."
Expand All @@ -171,22 +172,22 @@ try {
Invoke-RestMethod `
-Method Patch `
-Uri $extensionUpload.'extensionContent@odata.mediaEditLink' `
-Headers ($authHeaders + $ifMatchHeader + $streamHeader) `
-Headers ((GetAuthHeaders) + $ifMatchHeader + $streamHeader) `
-Body $fileBody | Out-Null
Write-Host @newLine "."
Invoke-RestMethod `
-Method Post `
-Uri "$automationApiUrl/companies($companyId)/extensionUpload($($extensionUpload.systemId))/Microsoft.NAV.upload" `
-Headers ($authHeaders + $ifMatchHeader) | Out-Null
-Headers ((GetAuthHeaders) + $ifMatchHeader) | Out-Null
Write-Host @newLine "."
$completed = $false
$errCount = 0
$sleepSeconds = 5
$sleepSeconds = 30
while (!$completed)
{
Start-Sleep -Seconds $sleepSeconds
try {
$extensionDeploymentStatusResponse = Invoke-WebRequest -Headers $authHeaders -Method Get -Uri "$automationApiUrl/companies($companyId)/extensionDeploymentStatus" -UseBasicParsing
$extensionDeploymentStatusResponse = Invoke-WebRequest -Headers (GetAuthHeaders) -Method Get -Uri "$automationApiUrl/companies($companyId)/extensionDeploymentStatus" -UseBasicParsing
$extensionDeploymentStatuses = (ConvertFrom-Json $extensionDeploymentStatusResponse.Content).value

$completed = $true
Expand Down Expand Up @@ -231,7 +232,7 @@ try {
throw
}
finally {
$getExtensions = Invoke-WebRequest -Headers $authHeaders -Method Get -Uri "$automationApiUrl/companies($companyId)/extensions" -UseBasicParsing
$getExtensions = Invoke-WebRequest -Headers (GetAuthHeaders) -Method Get -Uri "$automationApiUrl/companies($companyId)/extensions" -UseBasicParsing
$extensions = (ConvertFrom-Json $getExtensions.Content).value | Sort-Object -Property DisplayName

if (!$hideInstalledExtensionsOutput) {
Expand Down

0 comments on commit 97af5cf

Please sign in to comment.