From ef99ddf7f37ec68ac971af590bdbe4bc11705130 Mon Sep 17 00:00:00 2001 From: Florian Hopfner Date: Sun, 17 Nov 2024 15:54:36 +0100 Subject: [PATCH 1/9] add Publish-D365WebResources function --- d365fo.tools/d365fo.tools.psd1 | 5 +- .../functions/publish-d365webresources.ps1 | 99 +++++++++++++++++++ 2 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 d365fo.tools/functions/publish-d365webresources.ps1 diff --git a/d365fo.tools/d365fo.tools.psd1 b/d365fo.tools/d365fo.tools.psd1 index 7acdeb3e..a743e81e 100644 --- a/d365fo.tools/d365fo.tools.psd1 +++ b/d365fo.tools/d365fo.tools.psd1 @@ -65,8 +65,6 @@ 'Clear-D365TempDbTables', 'ConvertTo-D365Dacpac', - 'Publish-D365SsrsReport', - 'Disable-D365MaintenanceMode' 'Disable-D365SqlChangeTracking', 'Disable-D365User', @@ -261,6 +259,9 @@ 'New-D365ModuleToRemove', 'New-D365TopologyFile', + 'Publish-D365WebResources', + 'Publish-D365SsrsReport', + 'Register-D365AzureStorageConfig', 'Remove-D365LcsAssetFile', diff --git a/d365fo.tools/functions/publish-d365webresources.ps1 b/d365fo.tools/functions/publish-d365webresources.ps1 new file mode 100644 index 00000000..cbb836bb --- /dev/null +++ b/d365fo.tools/functions/publish-d365webresources.ps1 @@ -0,0 +1,99 @@ +function Publish-D365WebResources { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $false)] + [PsfDirectory] $PackageDirectory = $Script:PackageDirectory, + + [Parameter(Mandatory = $false)] + [PsfDirectory] $AosServiceWebRootPath = $Script:AOSPath + ) + + Invoke-TimeSignal -Start + + Write-PSFMessage -Level Verbose -Message "Initializing web resources deplyoment." + + $webResourceTypes = @("Images", "Scripts", "Styles", "Html") + + Write-PSFMessage -Level Debug -Message "Creating web resource directories." + $resourcesDirectory = Join-Path $AosServiceWebRootPath "Resources" + Test-PathExists -Path $resourcesDirectory -Type Container -Create | Out-Null + + $webResourceTypes | ForEach-Object { + $resourceTypeDirectory = Join-Path $resourcesDirectory $_ + Test-PathExists -Path $resourceTypeDirectory -Type Container -Create | Out-Null + } + + Write-PSFMessage -Level Debug -Message "Importing required assemblies." + [System.Collections.ArrayList] $Files2Process = New-Object -TypeName "System.Collections.ArrayList" + $binDir = Join-Path $AosServiceWebRootPath "bin" + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.AX.Metadata.Core.dll)) + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.AX.Metadata.dll)) + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.AX.Metadata.Storage.dll)) + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.Performance.Instrumentation.dll)) + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.ApplicationPlatform.XppServices.Instrumentation.dll)) + Import-AssemblyFileIntoMemory -Path $($Files2Process.ToArray()) + + Write-PSFMessage -Level Debug -Message "Initializing metadata runtime provider." + $runtimeProviderConfiguration = New-Object Microsoft.Dynamics.AX.Metadata.Storage.Runtime.RuntimeProviderConfiguration -ArgumentList $PackageDirectory + $metadataProviderFactoryViaRuntime = New-Object Microsoft.Dynamics.AX.Metadata.Storage.MetadataProviderFactory + $metadataProviderViaRuntime = $metadataProviderFactoryViaRuntime.CreateRuntimeProvider($runtimeProviderConfiguration) + + Write-PSFMessage -Level Verbose -Message "Starting web resources deployment" + $resources = $metadataProviderViaRuntime.Resources.GetPrimaryKeys() + foreach ($resourceItem in $resources) { + $resourceName = [System.String]$resourceItem + Write-PSFMessage -Level Debug -Message "Processing resource '$resourceName'." + $resourceHeader = New-Object -TypeName Microsoft.Dynamics.AX.Metadata.MetaModel.MetaReadHeader + $resource = $metadataProviderViaRuntime.Resources.Read($resourceName, [ref]$resourceHeader) + $resourceTimestamp = $metadataProviderViaRuntime.Resources.GetContentTimestampUtc($resource, $resourceHeader) + $resourceType = $resource.TypeOfResource + + $isAWebResource = $webResourceTypes -contains $resourceType + if (-not $isAWebResource) { + Write-PSFMessage -Level Debug -Message "Resource '$resourceName' is not a web resource. Skipping." + continue + } + + Write-PSFMessage -Level Debug -Message "Checking web resource '$resourceName' of type '$resourceType' for deployment." + $resourcePath = Join-Path $resourcesDirectory $resourceType + $resourceFilePath = Join-Path $resourcePath $resource.FileName + + $copyFile = $false + if (-not (Test-PathExists -Path $resourceFilePath -Type Leaf)) { + Write-PSFMessage -Level Debug -Message "Web resource '$resourceName' does not exist. Will be deployed." + $copyFile = $true + } + else { + $existingFileTimestamp = (Get-ItemProperty $resourceFilePath).LastWriteTimeUtc + if ($existingFileTimestamp -ne $resourceTimestamp) { + Write-PSFMessage -Level Debug -Message "Web resource '$resourceName' is outdated (resource time stamp: $resouceTimestamp, existing file time stamp: $existingFileTimestamp). Will be deployed." + $copyFile = $true + } + } + + if (-not $copyFile) { + Write-PSFMessage -Level Debug -Message "Web resource '$resourceName' is up to date." + continue + } + + Write-PSFMessage -Level Debug -Message "Deploying web resource '$resourceName' to '$resourceFilePath'." + $sourceStream = $metadataProviderViaRuntime.Resources.GetContent($resource, $resourceHeader) + if ($sourceStream) { + $argumentList = @( + $resourceFilePath, + [System.IO.FileMode]::Create, + [System.IO.FileAccess]::Write + ) + $targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $argumentList + $sourceStream.CopyTo($targetStream) + + $sourceStream.Close() + $targetStream.Close() + Write-PSFMessage -Level Debug -Message "Web resource '$resourceName' deployed successfully." + } + } + Write-PSFMessage -Level Host -Message "Web resources deployment completed." + + Invoke-TimeSignal -End + +} \ No newline at end of file From 2df29ddeffe46402a7ad6ab06270cae77df0512c Mon Sep 17 00:00:00 2001 From: Florian Hopfner Date: Sun, 17 Nov 2024 16:00:45 +0100 Subject: [PATCH 2/9] suppress warning if resource file does not exist yet --- d365fo.tools/functions/publish-d365webresources.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/d365fo.tools/functions/publish-d365webresources.ps1 b/d365fo.tools/functions/publish-d365webresources.ps1 index cbb836bb..c969b97a 100644 --- a/d365fo.tools/functions/publish-d365webresources.ps1 +++ b/d365fo.tools/functions/publish-d365webresources.ps1 @@ -59,7 +59,7 @@ function Publish-D365WebResources { $resourceFilePath = Join-Path $resourcePath $resource.FileName $copyFile = $false - if (-not (Test-PathExists -Path $resourceFilePath -Type Leaf)) { + if (-not (Test-PathExists -Path $resourceFilePath -Type Leaf -WarningAction SilentlyContinue -ErrorAction SilentlyContinue)) { Write-PSFMessage -Level Debug -Message "Web resource '$resourceName' does not exist. Will be deployed." $copyFile = $true } From 116b3134e77b7ee09a168d20dcc6ae66cfff4bbc Mon Sep 17 00:00:00 2001 From: Florian Hopfner Date: Sun, 17 Nov 2024 17:41:06 +0100 Subject: [PATCH 3/9] refactor resource publishing into internal function --- .../functions/publish-d365webresources.ps1 | 81 +-------- .../functions/publish-d365foresources.ps1 | 165 ++++++++++++++++++ 2 files changed, 172 insertions(+), 74 deletions(-) create mode 100644 d365fo.tools/internal/functions/publish-d365foresources.ps1 diff --git a/d365fo.tools/functions/publish-d365webresources.ps1 b/d365fo.tools/functions/publish-d365webresources.ps1 index c969b97a..47169b2d 100644 --- a/d365fo.tools/functions/publish-d365webresources.ps1 +++ b/d365fo.tools/functions/publish-d365webresources.ps1 @@ -14,86 +14,19 @@ function Publish-D365WebResources { $webResourceTypes = @("Images", "Scripts", "Styles", "Html") - Write-PSFMessage -Level Debug -Message "Creating web resource directories." + Write-PSFMessage -Level Debug -Message "Creating web resources directory." $resourcesDirectory = Join-Path $AosServiceWebRootPath "Resources" Test-PathExists -Path $resourcesDirectory -Type Container -Create | Out-Null - $webResourceTypes | ForEach-Object { - $resourceTypeDirectory = Join-Path $resourcesDirectory $_ - Test-PathExists -Path $resourceTypeDirectory -Type Container -Create | Out-Null + $params = @{ + ResourceTypes = $webResourceTypes + PublishingDirectory = $resourcesDirectory + PackageDirectory = $PackageDirectory + AosServiceWebRootPath = $AosServiceWebRootPath } + Publish-D365FOResources @params - Write-PSFMessage -Level Debug -Message "Importing required assemblies." - [System.Collections.ArrayList] $Files2Process = New-Object -TypeName "System.Collections.ArrayList" - $binDir = Join-Path $AosServiceWebRootPath "bin" - $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.AX.Metadata.Core.dll)) - $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.AX.Metadata.dll)) - $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.AX.Metadata.Storage.dll)) - $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.Performance.Instrumentation.dll)) - $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.ApplicationPlatform.XppServices.Instrumentation.dll)) - Import-AssemblyFileIntoMemory -Path $($Files2Process.ToArray()) - - Write-PSFMessage -Level Debug -Message "Initializing metadata runtime provider." - $runtimeProviderConfiguration = New-Object Microsoft.Dynamics.AX.Metadata.Storage.Runtime.RuntimeProviderConfiguration -ArgumentList $PackageDirectory - $metadataProviderFactoryViaRuntime = New-Object Microsoft.Dynamics.AX.Metadata.Storage.MetadataProviderFactory - $metadataProviderViaRuntime = $metadataProviderFactoryViaRuntime.CreateRuntimeProvider($runtimeProviderConfiguration) - - Write-PSFMessage -Level Verbose -Message "Starting web resources deployment" - $resources = $metadataProviderViaRuntime.Resources.GetPrimaryKeys() - foreach ($resourceItem in $resources) { - $resourceName = [System.String]$resourceItem - Write-PSFMessage -Level Debug -Message "Processing resource '$resourceName'." - $resourceHeader = New-Object -TypeName Microsoft.Dynamics.AX.Metadata.MetaModel.MetaReadHeader - $resource = $metadataProviderViaRuntime.Resources.Read($resourceName, [ref]$resourceHeader) - $resourceTimestamp = $metadataProviderViaRuntime.Resources.GetContentTimestampUtc($resource, $resourceHeader) - $resourceType = $resource.TypeOfResource - - $isAWebResource = $webResourceTypes -contains $resourceType - if (-not $isAWebResource) { - Write-PSFMessage -Level Debug -Message "Resource '$resourceName' is not a web resource. Skipping." - continue - } - - Write-PSFMessage -Level Debug -Message "Checking web resource '$resourceName' of type '$resourceType' for deployment." - $resourcePath = Join-Path $resourcesDirectory $resourceType - $resourceFilePath = Join-Path $resourcePath $resource.FileName - - $copyFile = $false - if (-not (Test-PathExists -Path $resourceFilePath -Type Leaf -WarningAction SilentlyContinue -ErrorAction SilentlyContinue)) { - Write-PSFMessage -Level Debug -Message "Web resource '$resourceName' does not exist. Will be deployed." - $copyFile = $true - } - else { - $existingFileTimestamp = (Get-ItemProperty $resourceFilePath).LastWriteTimeUtc - if ($existingFileTimestamp -ne $resourceTimestamp) { - Write-PSFMessage -Level Debug -Message "Web resource '$resourceName' is outdated (resource time stamp: $resouceTimestamp, existing file time stamp: $existingFileTimestamp). Will be deployed." - $copyFile = $true - } - } - - if (-not $copyFile) { - Write-PSFMessage -Level Debug -Message "Web resource '$resourceName' is up to date." - continue - } - - Write-PSFMessage -Level Debug -Message "Deploying web resource '$resourceName' to '$resourceFilePath'." - $sourceStream = $metadataProviderViaRuntime.Resources.GetContent($resource, $resourceHeader) - if ($sourceStream) { - $argumentList = @( - $resourceFilePath, - [System.IO.FileMode]::Create, - [System.IO.FileAccess]::Write - ) - $targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $argumentList - $sourceStream.CopyTo($targetStream) - - $sourceStream.Close() - $targetStream.Close() - Write-PSFMessage -Level Debug -Message "Web resource '$resourceName' deployed successfully." - } - } Write-PSFMessage -Level Host -Message "Web resources deployment completed." Invoke-TimeSignal -End - } \ No newline at end of file diff --git a/d365fo.tools/internal/functions/publish-d365foresources.ps1 b/d365fo.tools/internal/functions/publish-d365foresources.ps1 new file mode 100644 index 00000000..b9f33533 --- /dev/null +++ b/d365fo.tools/internal/functions/publish-d365foresources.ps1 @@ -0,0 +1,165 @@ +function Publish-D365FOResources { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string[]] $ResourceTypes, + + [Parameter(Mandatory = $true)] + [PsfDirectory] $PublishingDirectory, + + [Parameter(Mandatory = $false)] + [PsfDirectory] $PackageDirectory = $Script:PackageDirectory, + + [Parameter(Mandatory = $false)] + [PsfDirectory] $AosServiceWebRootPath = $Script:AOSPath + ) + + Invoke-TimeSignal -Start + + Write-PSFMessage -Level Verbose -Message "Initializing resources publishing." + + $resourcesDirectory = $PublishingDirectory + foreach ($resourceType in $ResourceTypes) { + $resourceTypeDirectory = Join-Path $resourcesDirectory $resourceType + Test-PathExists -Path $resourceTypeDirectory -Type Container -Create | Out-Null + } + + Import-Assemblies -AosServiceWebRootPath $AosServiceWebRootPath + # For unknown reasons, the provider cannot be initialized in a separate function. + # If this is done, $metadataProviderViaRuntime.Resources is null. + Write-PSFMessage -Level Debug -Message "Initializing metadata runtime provider." + $runtimeProviderConfiguration = New-Object Microsoft.Dynamics.AX.Metadata.Storage.Runtime.RuntimeProviderConfiguration -ArgumentList $PackageDirectory + $metadataProviderFactoryViaRuntime = New-Object Microsoft.Dynamics.AX.Metadata.Storage.MetadataProviderFactory + $metadataProviderViaRuntime = $metadataProviderFactoryViaRuntime.CreateRuntimeProvider($runtimeProviderConfiguration) + + Write-PSFMessage -Level Verbose -Message "Starting resources publishing" + $resources = $metadataProviderViaRuntime.Resources.GetPrimaryKeys() + foreach ($resourceItem in $resources) { + $params = @{ + ResourceItem = $resourceItem + MetadataProviderViaRuntime = $metadataProviderViaRuntime + ResourceTypes = $ResourceTypes + ResourcesDirectory = $resourcesDirectory + } + Publish-Resource @params + } + Write-PSFMessage -Level Host -Message "Resources publishing completed." + + Invoke-TimeSignal -End +} + +function Import-Assemblies { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [PsfDirectory] $AosServiceWebRootPath + ) + + Write-PSFMessage -Level Debug -Message "Importing required assemblies." + [System.Collections.ArrayList] $Files2Process = New-Object -TypeName "System.Collections.ArrayList" + $binDir = Join-Path $AosServiceWebRootPath "bin" + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.AX.Metadata.Core.dll)) + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.AX.Metadata.dll)) + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.AX.Metadata.Storage.dll)) + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.Performance.Instrumentation.dll)) + $null = $Files2Process.Add((Join-Path $binDir Microsoft.Dynamics.ApplicationPlatform.XppServices.Instrumentation.dll)) + Import-AssemblyFileIntoMemory -Path $($Files2Process.ToArray()) +} + +function Publish-Resource { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [object] $ResourceItem, + + [Parameter(Mandatory = $true)] + [object] $MetadataProviderViaRuntime, + + [Parameter(Mandatory = $true)] + [string[]] $ResourceTypes, + + [Parameter(Mandatory = $true)] + [string] $ResourcesDirectory + ) + + $resourceName = [System.String]$ResourceItem + Write-PSFMessage -Level Debug -Message "Processing resource '$resourceName'." + $resourceHeader = New-Object -TypeName Microsoft.Dynamics.AX.Metadata.MetaModel.MetaReadHeader + $resource = $MetadataProviderViaRuntime.Resources.Read($resourceName, [ref]$resourceHeader) + $resourceTimestamp = $MetadataProviderViaRuntime.Resources.GetContentTimestampUtc($resource, $resourceHeader) + $resourceType = $resource.TypeOfResource + + $resourcePath = Join-Path $ResourcesDirectory $resourceType + $resourceFilePath = Join-Path $resourcePath $resource.FileName + + Write-PSFMessage -Level Debug -Message "Checking resource '$resourceName' of type '$resourceType' for publishing." + $resourceData = @{ + ResourceType = $resourceType + ResourceName = $resourceName + ResourceTimestamp = $resourceTimestamp + } + $params = @{ + ResourceData = $resourceData + AllowedResourceTypes = $ResourceTypes + ResourceFilePath = $resourceFilePath + } + $shouldPublishResource = Test-PublishResource @params + if (-not $shouldPublishResource) { + Write-PSFMessage -Level Debug -Message "Resource '$resourceName' is not being published." + continue + } + + Write-PSFMessage -Level Debug -Message "Publishing resource '$resourceName' to '$resourceFilePath'." + $sourceStream = $MetadataProviderViaRuntime.Resources.GetContent($resource, $resourceHeader) + if ($sourceStream) { + $argumentList = @( + $resourceFilePath, + [System.IO.FileMode]::Create, + [System.IO.FileAccess]::Write + ) + $targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $argumentList + $sourceStream.CopyTo($targetStream) + + $sourceStream.Close() + $targetStream.Close() + Write-PSFMessage -Level Debug -Message "Resource '$resourceName' published successfully." + } +} + +function Test-PublishResource { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [hashtable] $ResourceData, + + [Parameter(Mandatory = $true)] + [string[]] $AllowedResourceTypes, + + [Parameter(Mandatory = $true)] + [string] $ResourceFilePath + ) + + $resourceType = $ResourceData.ResourceType + $resourceName = $ResourceData.ResourceName + $resourceTimestamp = $ResourceData.ResourceTimestamp + + $isAResourceTypeToPublish = $AllowedResourceTypes -contains $resourceType + if (-not $isAResourceTypeToPublish) { + Write-PSFMessage -Level Debug -Message "Resource '$resourceName' of type '$resourceType' is not a resource type to publish. Skipping." + return $false + } + + if (-not (Test-PathExists -Path $ResourceFilePath -Type Leaf -WarningAction SilentlyContinue -ErrorAction SilentlyContinue)) { + Write-PSFMessage -Level Debug -Message "Resource '$resourceName' does not exist. Will be published." + return $true + } + + $existingFileTimestamp = (Get-ItemProperty $resourceFilePath).LastWriteTimeUtc + if ($existingFileTimestamp -ne $ResourceTimestamp) { + Write-PSFMessage -Level Debug -Message "Resource '$ResourceName' is outdated (resource time stamp: $ResouceTimestamp, existing file time stamp: $existingFileTimestamp). Will be published." + return $true + } + + Write-PSFMessage -Level Debug -Message "Resource '$ResourceName' is up to date." + return $false +} \ No newline at end of file From 7631e8c945d0bbed603b54f3f6be15ccc8f31c80 Mon Sep 17 00:00:00 2001 From: Florian Hopfner Date: Sun, 17 Nov 2024 17:58:57 +0100 Subject: [PATCH 4/9] add documentation --- .../functions/publish-d365webresources.ps1 | 21 +++++++++++++++ .../functions/publish-d365foresources.ps1 | 27 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/d365fo.tools/functions/publish-d365webresources.ps1 b/d365fo.tools/functions/publish-d365webresources.ps1 index 47169b2d..33fa7ea4 100644 --- a/d365fo.tools/functions/publish-d365webresources.ps1 +++ b/d365fo.tools/functions/publish-d365webresources.ps1 @@ -1,3 +1,24 @@ +<# + .SYNOPSIS + Deploy web resources + + .DESCRIPTION + Deploys the Dynamics 365 for Finance and Operations web resources to the AOS service web root path. + + .PARAMETER PackageDirectory + Path to the package directory containing the web resources. + + .PARAMETER AosServiceWebRootPath + Path to the AOS service web root path. + + .EXAMPLE + PS C:\> Publish-D365WebResources + + This will deploy the web resources to the AOS service web root path. + + .NOTES + Author: Florian Hopfner (@FH-Inway) +#> function Publish-D365WebResources { [CmdletBinding()] param ( diff --git a/d365fo.tools/internal/functions/publish-d365foresources.ps1 b/d365fo.tools/internal/functions/publish-d365foresources.ps1 index b9f33533..ba57f54e 100644 --- a/d365fo.tools/internal/functions/publish-d365foresources.ps1 +++ b/d365fo.tools/internal/functions/publish-d365foresources.ps1 @@ -1,3 +1,30 @@ +<# + .SYNOPSIS + Publish resources + + .DESCRIPTION + Publishes Dynamics 365 for Finance and Operations resources to the publishing directory. + + .PARAMETER ResourceTypes + The types of resources to publish. + + .PARAMETER PublishingDirectory + The directory to publish the resources to. Each resource type will be published to a subdirectory. + + .PARAMETER PackageDirectory + The directory containing the resources. + + .PARAMETER AosServiceWebRootPath + The path to the AOS service web root containing the metadata assemblies to access the resources. + + .EXAMPLE + PS C:\> Publish-D365FOResources -ResourceTypes Images,Scripts,Styles,Html -PublishingDirectory C:\temp\resources + + This will publish the resources of the types Images, Scripts, Styles, and Html to the directory C:\temp\resources. + + .NOTES + Author: Florian Hopfner (@FH-Inway) +#> function Publish-D365FOResources { [CmdletBinding()] param ( From ad952c0cf1d0f631d1714a7eb28ab2f0716b2c75 Mon Sep 17 00:00:00 2001 From: FH-Inway <33372796+FH-Inway@users.noreply.github.com> Date: Sun, 17 Nov 2024 17:02:07 +0000 Subject: [PATCH 5/9] =?UTF-8?q?=F0=9F=A4=96=20Fix=20best=20practice=20devi?= =?UTF-8?q?ations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request was automatically created by the d365fo.tools-Generate-Text action' --- d365fo.tools/bin/d365fo.tools-index.json | 29 ++++++++ .../functions/publish-d365webresources.ps1 | 13 ++-- .../functions/publish-d365foresources.ps1 | 17 +++-- .../Publish-D365WebResources.Tests.ps1 | 49 ++++++++++++ docs/Publish-D365WebResources.md | 74 +++++++++++++++++++ 5 files changed, 168 insertions(+), 14 deletions(-) create mode 100644 d365fo.tools/tests/functions/Publish-D365WebResources.Tests.ps1 create mode 100644 docs/Publish-D365WebResources.md diff --git a/d365fo.tools/bin/d365fo.tools-index.json b/d365fo.tools/bin/d365fo.tools-index.json index d89e5add..29f6f6db 100644 --- a/d365fo.tools/bin/d365fo.tools-index.json +++ b/d365fo.tools/bin/d365fo.tools-index.json @@ -9952,6 +9952,35 @@ "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003ePublish-D365SsrsReport -Module ApplicationSuite -ReportName TaxVatRegister.Report\nThis will deploy the report which is named \"TaxVatRegister.Report\".\r\nThe cmdlet will look for the report inside the ApplicationSuite module.\r\nThe cmdlet will be using the default 127.0.0.1 while deploying the report.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003ePublish-D365SsrsReport -Module ApplicationSuite -ReportName *\nThis will deploy the all reports from the ApplicationSuite module.\r\nThe cmdlet will be using the default 127.0.0.1 while deploying the report.", "Syntax": "Publish-D365SsrsReport [[-Module] \u003cString[]\u003e] [[-ReportName] \u003cString[]\u003e] [[-LogFile] \u003cString\u003e] [[-PackageDirectory] \u003cString\u003e] [[-ToolsBasePath] \u003cString\u003e] [[-ReportServerIp] \u003cString[]\u003e] [\u003cCommonParameters\u003e]" }, + { + "CommandName": "Publish-D365WebResources", + "Description": "Deploys the Dynamics 365 for Finance and Operations web resources to the AOS service web root path.", + "Params": [ + [ + "PackageDirectory", + "Path to the package directory containing the web resources.", + "", + false, + "false", + "$Script:PackageDirectory" + ], + [ + "AosServiceWebRootPath", + "Path to the AOS service web root path.", + "", + false, + "false", + "$Script:AOSPath" + ] + ], + "Alias": "", + "Author": "Florian Hopfner (@FH-Inway)", + "Synopsis": "Deploy web resources", + "Name": "Publish-D365WebResources", + "Links": null, + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003ePublish-D365WebResources\nThis will deploy the web resources to the AOS service web root path.", + "Syntax": "Publish-D365WebResources [[-PackageDirectory] \u003cPathDirectoryParameter\u003e] [[-AosServiceWebRootPath] \u003cPathDirectoryParameter\u003e] [\u003cCommonParameters\u003e]" + }, { "CommandName": "Register-D365AzureStorageConfig", "Description": "Register all Azure Storage Configurations", diff --git a/d365fo.tools/functions/publish-d365webresources.ps1 b/d365fo.tools/functions/publish-d365webresources.ps1 index 33fa7ea4..242807b8 100644 --- a/d365fo.tools/functions/publish-d365webresources.ps1 +++ b/d365fo.tools/functions/publish-d365webresources.ps1 @@ -1,21 +1,22 @@ + <# .SYNOPSIS Deploy web resources - + .DESCRIPTION Deploys the Dynamics 365 for Finance and Operations web resources to the AOS service web root path. - + .PARAMETER PackageDirectory Path to the package directory containing the web resources. - + .PARAMETER AosServiceWebRootPath Path to the AOS service web root path. - + .EXAMPLE PS C:\> Publish-D365WebResources - + This will deploy the web resources to the AOS service web root path. - + .NOTES Author: Florian Hopfner (@FH-Inway) #> diff --git a/d365fo.tools/internal/functions/publish-d365foresources.ps1 b/d365fo.tools/internal/functions/publish-d365foresources.ps1 index ba57f54e..4205a5b6 100644 --- a/d365fo.tools/internal/functions/publish-d365foresources.ps1 +++ b/d365fo.tools/internal/functions/publish-d365foresources.ps1 @@ -1,27 +1,28 @@ + <# .SYNOPSIS Publish resources - + .DESCRIPTION Publishes Dynamics 365 for Finance and Operations resources to the publishing directory. - + .PARAMETER ResourceTypes The types of resources to publish. - + .PARAMETER PublishingDirectory The directory to publish the resources to. Each resource type will be published to a subdirectory. - + .PARAMETER PackageDirectory The directory containing the resources. - + .PARAMETER AosServiceWebRootPath The path to the AOS service web root containing the metadata assemblies to access the resources. - + .EXAMPLE PS C:\> Publish-D365FOResources -ResourceTypes Images,Scripts,Styles,Html -PublishingDirectory C:\temp\resources - + This will publish the resources of the types Images, Scripts, Styles, and Html to the directory C:\temp\resources. - + .NOTES Author: Florian Hopfner (@FH-Inway) #> diff --git a/d365fo.tools/tests/functions/Publish-D365WebResources.Tests.ps1 b/d365fo.tools/tests/functions/Publish-D365WebResources.Tests.ps1 new file mode 100644 index 00000000..af90e579 --- /dev/null +++ b/d365fo.tools/tests/functions/Publish-D365WebResources.Tests.ps1 @@ -0,0 +1,49 @@ +Describe "Publish-D365WebResources Unit Tests" -Tag "Unit" { + BeforeAll { + # Place here all things needed to prepare for the tests + } + AfterAll { + # Here is where all the cleanup tasks go + } + + Describe "Ensuring unchanged command signature" { + It "should have the expected parameter sets" { + (Get-Command Publish-D365WebResources).ParameterSets.Name | Should -Be '__AllParameterSets' + } + + It 'Should have the expected parameter PackageDirectory' { + $parameter = (Get-Command Publish-D365WebResources).Parameters['PackageDirectory'] + $parameter.Name | Should -Be 'PackageDirectory' + $parameter.ParameterType.ToString() | Should -Be PSFramework.Parameter.PathDirectoryParameter + $parameter.IsDynamic | Should -Be $False + $parameter.ParameterSets.Keys | Should -Be '__AllParameterSets' + $parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets' + $parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 0 + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False + } + It 'Should have the expected parameter AosServiceWebRootPath' { + $parameter = (Get-Command Publish-D365WebResources).Parameters['AosServiceWebRootPath'] + $parameter.Name | Should -Be 'AosServiceWebRootPath' + $parameter.ParameterType.ToString() | Should -Be PSFramework.Parameter.PathDirectoryParameter + $parameter.IsDynamic | Should -Be $False + $parameter.ParameterSets.Keys | Should -Be '__AllParameterSets' + $parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets' + $parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 1 + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False + } + } + + Describe "Testing parameterset __AllParameterSets" { + <# + __AllParameterSets - + __AllParameterSets -PackageDirectory -AosServiceWebRootPath + #> + } + +} \ No newline at end of file diff --git a/docs/Publish-D365WebResources.md b/docs/Publish-D365WebResources.md new file mode 100644 index 00000000..7ade8e5b --- /dev/null +++ b/docs/Publish-D365WebResources.md @@ -0,0 +1,74 @@ +--- +external help file: d365fo.tools-help.xml +Module Name: d365fo.tools +online version: +schema: 2.0.0 +--- + +# Publish-D365WebResources + +## SYNOPSIS +Deploy web resources + +## SYNTAX + +``` +Publish-D365WebResources [[-PackageDirectory] ] + [[-AosServiceWebRootPath] ] [] +``` + +## DESCRIPTION +Deploys the Dynamics 365 for Finance and Operations web resources to the AOS service web root path. + +## EXAMPLES + +### EXAMPLE 1 +``` +Publish-D365WebResources +``` + +This will deploy the web resources to the AOS service web root path. + +## PARAMETERS + +### -PackageDirectory +Path to the package directory containing the web resources. + +```yaml +Type: PathDirectoryParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: $Script:PackageDirectory +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AosServiceWebRootPath +Path to the AOS service web root path. + +```yaml +Type: PathDirectoryParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: $Script:AOSPath +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +Author: Florian Hopfner (@FH-Inway) + +## RELATED LINKS From 249db6af386c5f9cebb0f623819e569f846ef908 Mon Sep 17 00:00:00 2001 From: Florian Hopfner Date: Sun, 17 Nov 2024 18:18:46 +0100 Subject: [PATCH 6/9] remove trailing spaces --- d365fo.tools/internal/functions/publish-d365foresources.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/d365fo.tools/internal/functions/publish-d365foresources.ps1 b/d365fo.tools/internal/functions/publish-d365foresources.ps1 index 4205a5b6..90b4db6c 100644 --- a/d365fo.tools/internal/functions/publish-d365foresources.ps1 +++ b/d365fo.tools/internal/functions/publish-d365foresources.ps1 @@ -1,4 +1,4 @@ - + <# .SYNOPSIS Publish resources @@ -172,9 +172,9 @@ function Test-PublishResource { $resourceTimestamp = $ResourceData.ResourceTimestamp $isAResourceTypeToPublish = $AllowedResourceTypes -contains $resourceType - if (-not $isAResourceTypeToPublish) { + if (-not $isAResourceTypeToPublish) { Write-PSFMessage -Level Debug -Message "Resource '$resourceName' of type '$resourceType' is not a resource type to publish. Skipping." - return $false + return $false } if (-not (Test-PathExists -Path $ResourceFilePath -Type Leaf -WarningAction SilentlyContinue -ErrorAction SilentlyContinue)) { From 26a3acd8496cfb138a9b3e53d27f54f65a885948 Mon Sep 17 00:00:00 2001 From: Florian Hopfner Date: Sun, 17 Nov 2024 18:19:46 +0100 Subject: [PATCH 7/9] relax restrictions on publishing directory to enable unit tests where the example directory does not exist --- d365fo.tools/internal/functions/publish-d365foresources.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/d365fo.tools/internal/functions/publish-d365foresources.ps1 b/d365fo.tools/internal/functions/publish-d365foresources.ps1 index 90b4db6c..8dcd0e39 100644 --- a/d365fo.tools/internal/functions/publish-d365foresources.ps1 +++ b/d365fo.tools/internal/functions/publish-d365foresources.ps1 @@ -1,4 +1,4 @@ - + <# .SYNOPSIS Publish resources @@ -33,7 +33,7 @@ function Publish-D365FOResources { [string[]] $ResourceTypes, [Parameter(Mandatory = $true)] - [PsfDirectory] $PublishingDirectory, + [string] $PublishingDirectory, [Parameter(Mandatory = $false)] [PsfDirectory] $PackageDirectory = $Script:PackageDirectory, From b2fc0bcdf5d91368ef83a27c07da8b547ce1ed9b Mon Sep 17 00:00:00 2001 From: Florian Hopfner Date: Sun, 17 Nov 2024 18:23:29 +0100 Subject: [PATCH 8/9] suppress warnings because of plural nouns --- d365fo.tools/functions/publish-d365webresources.ps1 | 1 + d365fo.tools/internal/functions/publish-d365foresources.ps1 | 2 ++ 2 files changed, 3 insertions(+) diff --git a/d365fo.tools/functions/publish-d365webresources.ps1 b/d365fo.tools/functions/publish-d365webresources.ps1 index 242807b8..ca8fcc14 100644 --- a/d365fo.tools/functions/publish-d365webresources.ps1 +++ b/d365fo.tools/functions/publish-d365webresources.ps1 @@ -21,6 +21,7 @@ Author: Florian Hopfner (@FH-Inway) #> function Publish-D365WebResources { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', 'Publish-D365WebResources')] [CmdletBinding()] param ( [Parameter(Mandatory = $false)] diff --git a/d365fo.tools/internal/functions/publish-d365foresources.ps1 b/d365fo.tools/internal/functions/publish-d365foresources.ps1 index 8dcd0e39..c69ac72b 100644 --- a/d365fo.tools/internal/functions/publish-d365foresources.ps1 +++ b/d365fo.tools/internal/functions/publish-d365foresources.ps1 @@ -27,6 +27,7 @@ Author: Florian Hopfner (@FH-Inway) #> function Publish-D365FOResources { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', 'Publish-D365FOResources')] [CmdletBinding()] param ( [Parameter(Mandatory = $true)] @@ -77,6 +78,7 @@ function Publish-D365FOResources { } function Import-Assemblies { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', 'Import-Assemblies')] [CmdletBinding()] param ( [Parameter(Mandatory = $true)] From b1521b2a726b087155b2c9cb8297756abb2065b6 Mon Sep 17 00:00:00 2001 From: Florian Hopfner Date: Sun, 17 Nov 2024 18:25:43 +0100 Subject: [PATCH 9/9] add return type --- d365fo.tools/internal/functions/publish-d365foresources.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/d365fo.tools/internal/functions/publish-d365foresources.ps1 b/d365fo.tools/internal/functions/publish-d365foresources.ps1 index c69ac72b..cd3a1761 100644 --- a/d365fo.tools/internal/functions/publish-d365foresources.ps1 +++ b/d365fo.tools/internal/functions/publish-d365foresources.ps1 @@ -158,6 +158,7 @@ function Publish-Resource { function Test-PublishResource { [CmdletBinding()] + [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [hashtable] $ResourceData,