From 490f9ce65c48b4687cc35f90730c162cd69a7343 Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Mon, 23 Mar 2026 21:33:48 +0100 Subject: [PATCH 1/4] #233 The Pester test will be skipped when run accidentally ran on Windows PowerShell 5.1 ... this branch requires #235 for a working CI pipeline --- .../Scripts/Public/Invoke-IshRemoteMcpHandleRequest.Tests.ps1 | 2 +- .../Scripts/Public/Register-IshRemoteMcpInstructions.Tests.ps1 | 2 +- .../Scripts/Public/Register-IshRemoteMcpTool.Tests.ps1 | 2 +- .../Scripts/Public/Start-IshRemoteMcpServer.Tests.ps1 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Invoke-IshRemoteMcpHandleRequest.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Invoke-IshRemoteMcpHandleRequest.Tests.ps1 index b0d534c..f9585e8 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Invoke-IshRemoteMcpHandleRequest.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Invoke-IshRemoteMcpHandleRequest.Tests.ps1 @@ -12,7 +12,7 @@ BeforeAll { } -Describe "Invoke-IshRemoteMcpHandleRequest" { +Describe "Invoke-IshRemoteMcpHandleRequest" -Skip:($PSVersionTable.PSVersion.Major -lt 7){ Context "Method Initialize" { BeforeAll { Mock -ModuleName ISHRemote Write-IshRemoteLog { } diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpInstructions.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpInstructions.Tests.ps1 index 4656832..8be1140 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpInstructions.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpInstructions.Tests.ps1 @@ -4,7 +4,7 @@ BeforeAll { . (Join-Path (Split-Path -Parent $PSCommandPath) "\..\..\ISHRemote.PesterSetup.ps1") } -Describe "Register-IshRemoteMcpInstructions" { +Describe "Register-IshRemoteMcpInstructions" -Skip:($PSVersionTable.PSVersion.Major -lt 7) { Context "Function Output" { It "Should return valid JSON" { diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpTool.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpTool.Tests.ps1 index 56e66ea..a2bb8d4 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpTool.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Register-IshRemoteMcpTool.Tests.ps1 @@ -12,7 +12,7 @@ BeforeAll { } -Describe "Register-IshRemoteMcpTool" -Tags "Read" { +Describe "Register-IshRemoteMcpTool" -Tags "Read" -Skip:($PSVersionTable.PSVersion.Major -lt 7) { Context "Register-IshRemoteMcpTool (beware Get-Help is empty if Get-InstalledPSResource still shows ISHRemote installed)" { BeforeEach{ Mock -ModuleName ISHRemote Write-IshRemoteLog { } diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Start-IshRemoteMcpServer.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Start-IshRemoteMcpServer.Tests.ps1 index 471b3b1..d75d31e 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Start-IshRemoteMcpServer.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Scripts/Public/Start-IshRemoteMcpServer.Tests.ps1 @@ -11,7 +11,7 @@ BeforeAll { } } -Describe "Start-IshRemoteMcpServer" -Tags "Read" { +Describe "Start-IshRemoteMcpServer" -Tags "Read" -Skip:($PSVersionTable.PSVersion.Major -lt 7) { Context "Start-IshRemoteMcpServer with ActivateWhileLoop=false" { BeforeEach { Mock -ModuleName ISHRemote Write-IshRemoteLog { } From f32095731dee76304be468489b0f849f6d01e3eb Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Wed, 25 Mar 2026 10:06:32 +0100 Subject: [PATCH 2/4] #233 Trisoft.ISHRemote.dll-Help.xml should be present in ISHRemote and the currently 3 target frameworks to make PS1-based cmdlets tests works --- .github/workflows/continuous-integration.yml | 2 +- .../Trisoft.ISHRemote.csproj | 25 ++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 24ef1e1..33bb4c7 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -26,7 +26,7 @@ jobs: runs-on: windows-latest steps: - - name: PowerShell Update to latest stable (initially because 7.2.13/lts had issues, forced latest stable 7.3.6 or higher) + - name: PowerShell Update to latest stable (initially because 7.2.13/lts had issues, forcing latest stable) uses: bjompen/UpdatePWSHAction@v1.0.1 with: ReleaseVersion: 'Stable' diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Trisoft.ISHRemote.csproj b/Source/ISHRemote/Trisoft.ISHRemote/Trisoft.ISHRemote.csproj index f8c158e..026b40c 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Trisoft.ISHRemote.csproj +++ b/Source/ISHRemote/Trisoft.ISHRemote/Trisoft.ISHRemote.csproj @@ -124,20 +124,26 @@ net48\XmlDoc2CmdletDoc.dll net48\XmlDoc2CmdletDoc.dll - $(ProjectDir)bin/$(Configuration)/ISHRemote - - - + - - + + + + + + $(ProjectDir)bin/$(Configuration)/ISHRemote + $(ISHRemoteDir)/Trisoft.ISHRemote.dll-Help.xml + + @@ -148,6 +154,7 @@ $(ProjectDir)bin/$(Configuration)/ISHRemote $(ProjectDir)bin/$(Configuration)/net48/Trisoft.ISHRemote.dll $(ProjectDir)bin/$(Configuration)/net6.0/Trisoft.ISHRemote.dll + $(ProjectDir)bin/$(Configuration)/net10.0/Trisoft.ISHRemote.dll $(ISHRemoteDir)/$(ModuleName).psd1 $(ModuleName).psm1 $(ModuleName).Format.ps1xml @@ -158,7 +165,7 @@ - + $(ProjectDir)bin/$(Configuration) $(ProjectDir)bin/$(Configuration)/ISHRemote/$(TargetFramework) From 1015bcf32112739ab5fae97629700af82b26daa4 Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Wed, 25 Mar 2026 14:34:03 +0100 Subject: [PATCH 3/4] #233 Trisoft.ISHRemote.dll-Help.xml Github Actions race condition causes that sometimes net6.0 and or net10.0 are missing the help xml file. Extended TestPrerequisite.Tests.ps1 for basic package validation especially Trisoft.ISHRemote.dll-Help.xml existance --- .../TestPrerequisite.Tests.ps1 | 39 +++++++++++++++++++ .../Trisoft.ISHRemote.csproj | 22 ++++------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 index 3c90e18..987cd11 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/_TestEnvironment/TestPrerequisite.Tests.ps1 @@ -7,6 +7,45 @@ } Describe "Test-Prerequisite" -Tags "Read" { + Context "Package ISHRemote verification" { + It "Folder ISHRemote exists" { + Test-Path -Path $moduleFolder | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "ISHRemote.psm1") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "ISHRemote.psd1") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "ISHRemote.Format.ps1xml") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "Trisoft.ISHRemote.dll-Help.xml") | Should -Be $true + } + It "Folder ISHRemote/Scripts exists" { + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "Scripts") | Should -Be $true + } + It "Folder ISHRemote/Scripts/Public exists" { + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "Scripts/Public") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "Scripts/Public/Expand-ISHParameter.ps1") | Should -Be $true + } + It "Folder ISHRemote/Scripts/Private exists" { + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "Scripts/Private") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "Scripts/Private/Register-IshAuxParameterCompleter.ps1") | Should -Be $true + } + It "Folder ISHRemote/net48 exists" { + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net48") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net48/Trisoft.ISHRemote.dll") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net48/Trisoft.ISHRemote.xml") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net48/Trisoft.ISHRemote.dll-Help.xml") | Should -Be $true + } + It "Folder ISHRemote/net6.0 exists" { + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net6.0") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net6.0/Trisoft.ISHRemote.dll") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net6.0/Trisoft.ISHRemote.xml") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net6.0/Trisoft.ISHRemote.dll-Help.xml") | Should -Be $true + } + It "Folder ISHRemote/net10.0 exists" { + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net10.0") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net10.0/Trisoft.ISHRemote.dll") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net10.0/Trisoft.ISHRemote.xml") | Should -Be $true + Test-Path -Path (Join-Path -Path $moduleFolder -ChildPath "net10.0/Trisoft.ISHRemote.dll-Help.xml") | Should -Be $true + } + } + Context "ISHRemote.PesterSetup.Debug.ps1 minimal overwrites" { It "baseUrl" { $baseUrl | Should -Not -Be 'https://ish.example.com' diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Trisoft.ISHRemote.csproj b/Source/ISHRemote/Trisoft.ISHRemote/Trisoft.ISHRemote.csproj index 026b40c..d98465f 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Trisoft.ISHRemote.csproj +++ b/Source/ISHRemote/Trisoft.ISHRemote/Trisoft.ISHRemote.csproj @@ -125,25 +125,21 @@ net48\XmlDoc2CmdletDoc.dll $(ProjectDir)bin/$(Configuration)/ISHRemote + $(ProjectDir)bin/$(Configuration)/ISHRemote/net6.0 + $(ProjectDir)bin/$(Configuration)/ISHRemote/net10.0 + + - - - - - - $(ProjectDir)bin/$(Configuration)/ISHRemote - $(ISHRemoteDir)/Trisoft.ISHRemote.dll-Help.xml - - + + @@ -153,8 +149,6 @@ "%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe" $(ProjectDir)bin/$(Configuration)/ISHRemote $(ProjectDir)bin/$(Configuration)/net48/Trisoft.ISHRemote.dll - $(ProjectDir)bin/$(Configuration)/net6.0/Trisoft.ISHRemote.dll - $(ProjectDir)bin/$(Configuration)/net10.0/Trisoft.ISHRemote.dll $(ISHRemoteDir)/$(ModuleName).psd1 $(ModuleName).psm1 $(ModuleName).Format.ps1xml From aa3e19f03c685683ebc8810355c5736f52221cfd Mon Sep 17 00:00:00 2001 From: ddemeyer Date: Wed, 25 Mar 2026 16:24:43 +0100 Subject: [PATCH 4/4] #233 Get-IShDocumentObj augment by CoPilot roll back, merged into main branch coming from #229 because of PowerShell 7.6 not working. Should not be part of ISHRemote prerelease, hence roll back. --- .../Cmdlets/DocumentObj/GetIshDocumentObj.cs | 109 ++++-------------- 1 file changed, 20 insertions(+), 89 deletions(-) diff --git a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.cs b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.cs index dd0a217..6385967 100644 --- a/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.cs +++ b/Source/ISHRemote/Trisoft.ISHRemote/Cmdlets/DocumentObj/GetIshDocumentObj.cs @@ -19,9 +19,7 @@ using System.Linq; using System.Management.Automation; using System.ServiceModel; -using System.Threading; using Trisoft.ISHRemote.Exceptions; -using Trisoft.ISHRemote.ExtensionMethods; using Trisoft.ISHRemote.HelperClasses; using Trisoft.ISHRemote.Objects; using Trisoft.ISHRemote.Objects.Public; @@ -48,8 +46,8 @@ public sealed class GetIshDocumentObj : DocumentObjCmdlet /// /// The IshSession variable holds the authentication and contract information. This object can be initialized using the New-IshSession cmdlet. /// - [Parameter(Mandatory =false, ValueFromPipelineByPropertyName = false, ParameterSetName = "ParameterGroup")] - [Parameter(Mandatory =false, ValueFromPipelineByPropertyName = false, ParameterSetName = "IshObjectsGroup")] + [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = false, ParameterSetName = "ParameterGroup")] + [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = false, ParameterSetName = "IshObjectsGroup")] [ValidateNotNullOrEmpty] public IshSession IshSession { get; set; } @@ -81,7 +79,7 @@ public sealed class GetIshDocumentObj : DocumentObjCmdlet [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = false, ParameterSetName = "ParameterGroup")] [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = false, ParameterSetName = "IshObjectsGroup")] [ValidateNotNullOrEmpty] - public Enumerations.StatusFilter StatusFilter + public Enumerations.StatusFilter StatusFilter { get { return _statusFilter; } set { _statusFilter = value; } @@ -112,12 +110,6 @@ public SwitchParameter IncludeData [AllowEmptyCollection] public IshObject[] IshObject { get; set; } - /// - /// Switch parameter to use REST API (OpenAPI) instead of SOAP API for retrieval. This is experimental in Phase 1. - /// - [Parameter(Mandatory = false, ParameterSetName = "ParameterGroup")] - public SwitchParameter UseREST { get; set; } - @@ -156,7 +148,7 @@ protected override void ProcessRecord() { // 1. Validating the input WriteDebug("Validating"); - + List returnIshObjects = new List(); if (IshObject != null && IshObject.Length == 0) @@ -224,85 +216,24 @@ protected override void ProcessRecord() var statusFilter = EnumConverter.ToStatusFilter(StatusFilter); if (!_includeData) { - if (!UseREST) - { - //RetrieveMetadata via SOAP (default implementation) - WriteDebug($"[SOAP] Retrieving LogicalId.length[{LogicalId.Length}] StatusFilter[{statusFilter}] MetadataFilter.length[{metadataFilter.ToXml().Length}] RequestedMetadata.length[{requestedMetadata.ToXml().Length}] 0/{LogicalId.Length}"); - // Divides the list of language card ids in different lists that all have maximally MetadataBatchSize elements - List> dividedLogicalIdsList = DivideListInBatches(LogicalId.ToList(), IshSession.MetadataBatchSize); - int currentLogicalIdCount = 0; - foreach (List logicalIdBatch in dividedLogicalIdsList) - { - // Process language card ids in batches - string xmlIshObjects = IshSession.DocumentObj25.RetrieveMetadata( - logicalIdBatch.ToArray(), - statusFilter, - metadataFilter.ToXml(), - requestedMetadata.ToXml()); - IshObjects retrievedObjects = new IshObjects(ISHType, xmlIshObjects); - returnIshObjects.AddRange(retrievedObjects.Objects); - currentLogicalIdCount += logicalIdBatch.Count; - WriteDebug($"[SOAP] Retrieving LogicalId.length[{logicalIdBatch.Count}] StatusFilter[{statusFilter}] MetadataFilter.length[{metadataFilter.ToXml().Length}] RequestedMetadata.length[{requestedMetadata.ToXml().Length}] {currentLogicalIdCount}/{LogicalId.Length}"); - } - } - else + //RetrieveMetadata + WriteDebug($"Retrieving LogicalId.length[{LogicalId.Length}] StatusFilter[{statusFilter}] MetadataFilter.length[{metadataFilter.ToXml().Length}] RequestedMetadata.length[{requestedMetadata.ToXml().Length}] 0/{LogicalId.Length}"); + // Divides the list of language card ids in different lists that all have maximally MetadataBatchSize elements + List> dividedLogicalIdsList = DivideListInBatches(LogicalId.ToList(), IshSession.MetadataBatchSize); + int currentLogicalIdCount = 0; + foreach (List logicalIdBatch in dividedLogicalIdsList) { - //RetrieveMetadata via REST/OpenAPI (experimental Phase 1 implementation) - WriteDebug($"[REST] Retrieving LogicalId.length[{LogicalId.Length}] StatusFilter[{StatusFilter}] MetadataFilter fields[{metadataFilter.Fields().Length}] RequestedMetadata fields[{requestedMetadata.Fields().Length}]"); - - // Convert ISHRemote types to OpenAPI types - var openApiStatusFilter = StatusFilter.ToOpenApiISH30StatusFilter(); - var filterFields = metadataFilter.ToOpenApiISH30FilterFieldValues(); - var requestedFields = requestedMetadata.ToOpenApiISH30RequestedFields(); - - // Divide logical IDs into batches (same batch size as SOAP for consistency) - List> dividedLogicalIdsList = DivideListInBatches(LogicalId.ToList(), IshSession.MetadataBatchSize); - int currentLogicalIdCount = 0; - - foreach (List logicalIdBatch in dividedLogicalIdsList) - { - // Build the request object for this batch - var getDocumentObjectRequest = new OpenApiISH30.GetDocumentObjectListByLogicalId - { - LogicalIds = logicalIdBatch, - StatusFilter = openApiStatusFilter, - FilterFields = filterFields, - Fields = requestedFields, - SelectedProperties = OpenApiISH30.SelectedProperties.Id, - FieldGroup = requestedMetadata.Fields().Length > 0 ? OpenApiISH30.FieldGroup.None : OpenApiISH30.FieldGroup.Basic, - IncludeLinks = false, - IncludePartialItems = false - }; - - WriteDebug($"[REST] Calling GetDocumentObjectListByLogicalIdAsync for batch {currentLogicalIdCount}/{LogicalId.Length}"); - - // Make the async call synchronously (using GetAwaiter().GetResult() for PowerShell compatibility) - var documentObjects = IshSession.OpenApiISH30Client.GetDocumentObjectListByLogicalIdAsync( - getDocumentObjectRequest, - CancellationToken.None) - .GetAwaiter() - .GetResult(); - - WriteDebug($"[REST] Retrieved {documentObjects.Count} document objects from OpenAPI"); - - // TODO [Phase 2]: Convert OpenApiISH30.DocumentObject collection to IshObjects - // For Phase 1, we log that REST API was called successfully but cannot yet process results - WriteWarning($"[REST Phase 1] Successfully retrieved {documentObjects.Count} objects via REST API, but conversion to IshObjects not yet implemented. Falling back to SOAP for this batch."); - - // Fallback to SOAP for actual data retrieval in Phase 1 - string xmlIshObjects = IshSession.DocumentObj25.RetrieveMetadata( - logicalIdBatch.ToArray(), - statusFilter, - metadataFilter.ToXml(), - requestedMetadata.ToXml()); - IshObjects retrievedObjects = new IshObjects(ISHType, xmlIshObjects); - returnIshObjects.AddRange(retrievedObjects.Objects); - - currentLogicalIdCount += logicalIdBatch.Count; - WriteDebug($"[REST] Processed batch {currentLogicalIdCount}/{LogicalId.Length}"); - } + // Process language card ids in batches + string xmlIshObjects = IshSession.DocumentObj25.RetrieveMetadata( + logicalIdBatch.ToArray(), + statusFilter, + metadataFilter.ToXml(), + requestedMetadata.ToXml()); + IshObjects retrievedObjects = new IshObjects(ISHType, xmlIshObjects); + returnIshObjects.AddRange(retrievedObjects.Objects); + currentLogicalIdCount += logicalIdBatch.Count; + WriteDebug($"Retrieving LogicalId.length[{logicalIdBatch.Count}] StatusFilter[{statusFilter}] MetadataFilter.length[{metadataFilter.ToXml().Length}] RequestedMetadata.length[{requestedMetadata.ToXml().Length}] {currentLogicalIdCount}/{LogicalId.Length}"); } - } else {