Compile-AppWithArtifact.ps1
function Compile-AppWithArtifact { param( [parameter(Mandatory=$true)] [string]$alcPath, [parameter(Mandatory=$true)] [string]$artifactUrl, [parameter(Mandatory=$true)] [string]$appProjectFolder, [parameter(Mandatory=$true)] [string]$appOutputFolder, [parameter(Mandatory=$true)] [string]$appSymbolsFolder, [switch]$AzureDevOps, [switch]$EnableCodeCop, [switch]$EnableAppSourceCop, [switch]$EnablePerTenantExtensionCop, [switch]$EnableUICop, [ValidateSet('none','error','warning')] [string] $FailOn = 'none', [string]$rulesetFile, [string]$assemblyProbingPaths, [scriptblock] $outputTo = { Param($line) Write-Host $line } ) $startTime = [DateTime]::Now $appJsonFile = Join-Path $appProjectFolder 'app.json' $appJsonObject = [System.IO.File]::ReadAllLines($appJsonFile) | ConvertFrom-Json if ("$appName" -eq "") { $appName = "$($appJsonObject.Publisher)_$($appJsonObject.Name)_$($appJsonObject.Version).app".Split([System.IO.Path]::GetInvalidFileNameChars()) -join '' } Write-Host "Using Symbols Folder: $appSymbolsFolder" if (!(Test-Path -Path $appSymbolsFolder -PathType Container)) { New-Item -Path $appSymbolsFolder -ItemType Directory | Out-Null } Write-Host 'Copying Microsoft apps from artifact folder' $ArtifactPaths = Download-Artifacts -artifactUrl $artifactUrl -includePlatform if ((-not (Test-Path (Join-Path $ArtifactPaths[0] 'Applications'))) -and (-not (Test-Path (Join-Path $ArtifactPaths[0] 'Applications.*')))) { $AppPath = $ArtifactPaths[1] } else { $AppPath = $ArtifactPaths[0] } (Join-Path $ArtifactPaths[1] "\ModernDev\program files\Microsoft Dynamics NAV\*\AL Development Environment\System.app"), (Join-Path $AppPath "\Applications.*\Microsoft_Application_*.app"), (Join-Path $AppPath "\Applications\Application\Source\Microsoft_Application.app"), (Join-Path $AppPath "\Applications.*\Microsoft_Base Application_*.app"), (Join-Path $AppPath "\Applications\BaseApp\Source\Microsoft_Base Application.app"), (Join-Path $AppPath "\Applications.*\Microsoft_System Application_*.app"), (Join-Path $AppPath "\Applications\System Application\source\Microsoft_System Application.app")| ForEach-Object { if ($_) { if (Test-Path $_) { if (-not (Test-Path (Join-Path $appSymbolsFolder (Split-Path $_ -Leaf)))) { Write-Host "Copying $([System.IO.Path]::GetFileName($_)) " Copy-Item -Path $_ -Destination $appSymbolsFolder -Force } } } } import-module (Get-BCModulePathFromArtifact -artifactPath ((Download-Artifacts -artifactUrl $artifactUrl -includePlatform)[1])) $MSAppsFiles = Get-ChildItem -Path $AppPath -Filter *.app -Recurse $MSApps = @() foreach($File in $MSAppsFiles) { $AppInfo = get-navappinfo -Path $File.FullName $AppJson = New-Object -TypeName PSObject $AppJson | Add-Member -MemberType NoteProperty -Name "id" -Value $AppInfo.id $AppJson | Add-Member -MemberType NoteProperty -Name "name" -Value $AppInfo.Name $AppJson | Add-Member -MemberType NoteProperty -Name "publisher" -Value $AppInfo.Publisher $AppJson | Add-Member -MemberType NoteProperty -Name "version" -Value $AppInfo.Version $AppJson | Add-Member -MemberType NoteProperty -Name "file" -Value $File.FullName $MSApps += $AppJson } $dependencies = @() if (([bool]($appJsonObject.PSobject.Properties.name -eq "application")) -and $appJsonObject.application) { $dependencies += @{"publisher" = "Microsoft"; "name" = "Application"; "version" = $appJsonObject.application } } if (([bool]($appJsonObject.PSobject.Properties.name -eq "platform")) -and $appJsonObject.platform) { $dependencies += @{"publisher" = "Microsoft"; "name" = "System"; "version" = $appJsonObject.platform } } if (([bool]($appJsonObject.PSobject.Properties.name -eq "test")) -and $appJsonObject.test) { $dependencies += @{"publisher" = "Microsoft"; "name" = "Test"; "version" = $appJsonObject.test } if (([bool]($customConfig.PSobject.Properties.name -eq "EnableSymbolLoadingAtServerStartup")) -and ($customConfig.EnableSymbolLoadingAtServerStartup -eq "true")) { throw "app.json should NOT have a test dependency when running hybrid development (EnableSymbolLoading)" } } if (([bool]($appJsonObject.PSobject.Properties.name -eq "dependencies")) -and $appJsonObject.dependencies) { $appJsonObject.dependencies | ForEach-Object { $dependencies += @{ "publisher" = $_.publisher; "name" = $_.name; "version" = $_.version } } } Write-Host "Looking for missing MS dependencies" foreach($dep in ($dependencies | Where-Object {$_.publisher -like 'Microsoft'})) { $MSAppFile = $MSApps | Where-Object {($_.name -eq $dep.name) -and ($_.publisher -eq $dep.publisher)} | Select-Object -First 1 if ($MSAppFile) { if (-not (Test-Path (Join-Path $appSymbolsFolder (Split-Path $MSAppFile -Leaf)))) { Write-Host "Copying $([System.IO.Path]::GetFileName($MSAppFile.file)) " Copy-Item -Path $MSAppFile.file -Destination $appSymbolsFolder -Force } } } $result = Invoke-Command -ScriptBlock { Param($binPath,$appProjectFolder, $appSymbolsFolder, $appOutputFile, $EnableCodeCop, $EnableAppSourceCop, $EnablePerTenantExtensionCop, $EnableUICop, $rulesetFile, $assemblyProbingPaths, $nowarn, $generateReportLayoutParam, $features, $preProcessorSymbols ) Push-Location set-location $binPath #Add-Type -AssemblyName System.IO.Compression.FileSystem #Add-Type -AssemblyName System.Text.Encoding # Import types needed to invoke the compiler #Add-Type -Path (Join-Path $alcPath System.Collections.Immutable.dll) #Add-Type -Path (Join-Path $alcPath Microsoft.Dynamics.Nav.CodeAnalysis.dll) $alcParameters = @("/project:""$($appProjectFolder.TrimEnd('/\'))""", "/packagecachepath:""$($appSymbolsFolder.TrimEnd('/\'))""", "/out:""$appOutputFile""") if ($EnableCodeCop) { $alcParameters += @("/analyzer:$(Join-Path $binPath 'Analyzers\Microsoft.Dynamics.Nav.CodeCop.dll')") } if ($EnableAppSourceCop) { $alcParameters += @("/analyzer:$(Join-Path $binPath 'Analyzers\Microsoft.Dynamics.Nav.AppSourceCop.dll')") } if ($EnablePerTenantExtensionCop) { $alcParameters += @("/analyzer:$(Join-Path $binPath 'Analyzers\Microsoft.Dynamics.Nav.PerTenantExtensionCop.dll')") } if ($EnableUICop) { $alcParameters += @("/analyzer:$(Join-Path $binPath 'Analyzers\Microsoft.Dynamics.Nav.UICop.dll')") } if ($rulesetFile) { $alcParameters += @("/ruleset:$rulesetfile") } if ($assemblyProbingPaths) { $alcParameters += @("/assemblyprobingpaths:$assemblyProbingPaths") } Write-Host ".\alc.exe $([string]::Join(' ', $alcParameters))" & .\alc.exe $alcParameters Pop-Location if ($lastexitcode -ne 0) { "App generation failed with exit code $lastexitcode" } } -ArgumentList $alcPath,$appProjectFolder, $appSymbolsFolder, (Join-Path $appOutputFolder $appName), $EnableCodeCop, $EnableAppSourceCop, $EnablePerTenantExtensionCop, $EnableUICop, $containerRulesetFile, $assemblyProbingPaths, $nowarn, $GenerateReportLayoutParam, $features, $preProcessorSymbols $devOpsResult = "" if ($result) { $devOpsResult = Convert-ALCOutputToAzureDevOps -FailOn $FailOn -AlcOutput $result -DoNotWriteToHost } if ($AzureDevOps) { $devOpsResult | % { $outputTo.Invoke($_) } } else { $result | % { $outputTo.Invoke($_) } if ($devOpsResult -like "*task.complete result=Failed*") { throw "App generation failed" } } $result | Where-Object { $_ -like "App generation failed*" } | % { throw $_ } $timespend = [Math]::Round([DateTime]::Now.Subtract($startTime).Totalseconds) $appFile = Join-Path $appOutputFolder $appName if (Test-Path -Path $appFile) { Write-Host "$appFile successfully created in $timespend seconds" if ($CopyAppToSymbolsFolder) { Copy-Item -Path $appFile -Destination $appSymbolsFolder -ErrorAction SilentlyContinue if (Test-Path -Path (Join-Path -Path $appSymbolsFolder -ChildPath $appName)) { Write-Host "${appName} copied to ${appSymbolsFolder}" } } } else { throw "App generation failed" } $appFile } |