From c5ddd8c88a4bd3a0509e8f168daddfb19604563b Mon Sep 17 00:00:00 2001 From: Andrew Pearce Date: Sat, 20 Dec 2025 22:45:52 -0800 Subject: [PATCH 1/3] Pin GitHub Actions to full-length commit SHAs --- .github/workflows/ci.yml | 2 +- .github/workflows/docs.yml | 14 +++++++------- .github/workflows/publish.yml | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9755977..3d7b774 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -324,7 +324,7 @@ jobs: - name: Download previous module artifact (if not rebuilt) if: steps.upload-new.outputs.artifact-id == '' - uses: dawidd6/action-download-artifact@v6 + uses: dawidd6/action-download-artifact@bf251b5aa9c2f7eeb574a96ee720e24f801b7c11 with: name: Convert-Module-Universal path: Artifacts/ diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7b9a617..913538e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,11 +30,11 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 - name: Download module artifact from CI if: ${{ github.event_name == 'workflow_run' }} - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e with: name: Convert-Module-Universal path: Artifacts/ @@ -51,10 +51,10 @@ jobs: ./build.ps1 -PowerShell -Build - name: Setup Pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b - name: Cache PowerShell modules - uses: actions/cache@v4 + uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 with: path: ~/.local/share/powershell/Modules key: ${{ runner.os }}-psmodules-${{ hashFiles('install_modules.ps1') }} @@ -68,7 +68,7 @@ jobs: run: ./.build/Invoke-DocumentationGeneration.ps1 -Force - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 with: python-version: '3.11' cache: 'pip' @@ -80,7 +80,7 @@ jobs: run: mkdocs build --strict - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa with: path: site/ @@ -95,4 +95,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b9ead82..8bce2ba 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -27,13 +27,13 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: sparse-checkout: .build/Invoke-PublishModule.ps1 sparse-checkout-cone-mode: false - name: Download module artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e with: name: ${{ env.MODULE_NAME }}-Module-Universal path: Artifacts/ From 215c88df31d47dfc310138031aafa38af2b2925c Mon Sep 17 00:00:00 2001 From: Andrew Pearce Date: Wed, 28 Jan 2026 23:26:02 -0800 Subject: [PATCH 2/3] refactor: consolidate redundant -MemoryStream parameter into -Stream (#17) --- .../ConvertFrom-MemoryStreamToString.ps1 | 27 +----- src/Convert/Public/ConvertTo-String.ps1 | 18 +--- ...ConvertFrom-MemoryStreamToString.Tests.ps1 | 95 +++++++++++++++++++ src/Tests/Unit/ConvertTo-String.Tests.ps1 | 88 +++++++++++++++++ 4 files changed, 189 insertions(+), 39 deletions(-) diff --git a/src/Convert/Public/ConvertFrom-MemoryStreamToString.ps1 b/src/Convert/Public/ConvertFrom-MemoryStreamToString.ps1 index 69b49ce..f0937ee 100644 --- a/src/Convert/Public/ConvertFrom-MemoryStreamToString.ps1 +++ b/src/Convert/Public/ConvertFrom-MemoryStreamToString.ps1 @@ -5,11 +5,8 @@ .DESCRIPTION Converts MemoryStream to a string. - .PARAMETER MemoryStream - A System.IO.MemoryStream object for conversion. - .PARAMETER Stream - A System.IO.Stream object for conversion. + A System.IO.Stream object for conversion. Accepts any stream type including MemoryStream, FileStream, etc. .EXAMPLE $string = 'A string' @@ -84,16 +81,9 @@ function ConvertFrom-MemoryStreamToString { Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, - ParameterSetName = 'MemoryStream')] - [ValidateNotNullOrEmpty()] - [System.IO.MemoryStream[]] - $MemoryStream, - - [Parameter( - Mandatory = $true, - ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Stream')] [ValidateNotNullOrEmpty()] + [Alias('MemoryStream')] [System.IO.Stream[]] $Stream ) @@ -103,18 +93,9 @@ function ConvertFrom-MemoryStreamToString { } process { - switch ($PSCmdlet.ParameterSetName) { - 'MemoryStream' { - $inputObject = $MemoryStream - } - 'Stream' { - $inputObject = $Stream - } - } - - foreach ($object in $inputObject) { + foreach ($object in $Stream) { try { - if ($PSCmdlet.ParameterSetName -eq 'MemoryStream') { + if ($object.CanSeek) { $object.Position = 0 } $reader = [System.IO.StreamReader]::new($object) diff --git a/src/Convert/Public/ConvertTo-String.ps1 b/src/Convert/Public/ConvertTo-String.ps1 index 2718f6d..92d1a31 100644 --- a/src/Convert/Public/ConvertTo-String.ps1 +++ b/src/Convert/Public/ConvertTo-String.ps1 @@ -8,11 +8,8 @@ .PARAMETER Base64EncodedString A Base64 Encoded String - .PARAMETER MemoryStream - A MemoryStream object for conversion. - .PARAMETER Stream - A System.IO.Stream object for conversion. + A System.IO.Stream object for conversion. Accepts any stream type including MemoryStream, FileStream, etc. .PARAMETER Encoding The encoding to use for conversion. @@ -105,16 +102,9 @@ function ConvertTo-String { Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, - ParameterSetName = 'MemoryStream')] - [ValidateNotNullOrEmpty()] - [System.IO.MemoryStream[]] - $MemoryStream, - - [Parameter( - Mandatory = $true, - ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Stream')] [ValidateNotNullOrEmpty()] + [Alias('MemoryStream')] [System.IO.Stream[]] $Stream, @@ -158,10 +148,6 @@ function ConvertTo-String { } } - 'MemoryStream' { - $MemoryStream | ConvertFrom-MemoryStreamToString -ErrorAction $userErrorActionPreference - } - 'Stream' { $Stream | ConvertFrom-MemoryStreamToString -ErrorAction $userErrorActionPreference } diff --git a/src/Tests/Unit/ConvertFrom-MemoryStreamToString.Tests.ps1 b/src/Tests/Unit/ConvertFrom-MemoryStreamToString.Tests.ps1 index d02379c..ba1151f 100644 --- a/src/Tests/Unit/ConvertFrom-MemoryStreamToString.Tests.ps1 +++ b/src/Tests/Unit/ConvertFrom-MemoryStreamToString.Tests.ps1 @@ -2,6 +2,101 @@ $function = $MyInvocation.MyCommand.Name.Split('.')[0] Describe -Name $function -Fixture { + Context -Name 'Stream input (non-MemoryStream)' -Fixture { + It -Name 'Converts FileStream using -Stream parameter' -Test { + $string = 'ThisIsMyString' + $tempFile = [System.IO.Path]::GetTempFileName() + $fileStream = $null + try { + [System.IO.File]::WriteAllText($tempFile, $string) + $fileStream = [System.IO.File]::OpenRead($tempFile) + + $assertion = ConvertFrom-MemoryStreamToString -Stream $fileStream + + $assertion | Should -BeExactly $string + } finally { + if ($fileStream) { $fileStream.Dispose() } + if (Test-Path $tempFile) { Remove-Item $tempFile -Force } + } + } + + It -Name 'Converts FileStream from Pipeline' -Test { + $string = 'ThisIsMyString' + $tempFile = [System.IO.Path]::GetTempFileName() + $fileStream = $null + try { + [System.IO.File]::WriteAllText($tempFile, $string) + $fileStream = [System.IO.File]::OpenRead($tempFile) + + $assertion = $fileStream | ConvertFrom-MemoryStreamToString + + $assertion | Should -BeExactly $string + } finally { + if ($fileStream) { $fileStream.Dispose() } + if (Test-Path $tempFile) { Remove-Item $tempFile -Force } + } + } + + It -Name 'Converts BufferedStream to string' -Test { + $string = 'ThisIsMyString' + $memStream = [System.IO.MemoryStream]::new() + $writer = [System.IO.StreamWriter]::new($memStream) + $writer.Write($string) + $writer.Flush() + + $bufferedStream = [System.IO.BufferedStream]::new($memStream) + + $assertion = ConvertFrom-MemoryStreamToString -Stream $bufferedStream + + $assertion | Should -BeExactly $string + + $bufferedStream.Dispose() + $writer.Dispose() + $memStream.Dispose() + } + + It -Name 'Converts array of FileStreams from Pipeline' -Test { + $string = 'ThisIsMyString' + $tempFile1 = [System.IO.Path]::GetTempFileName() + $tempFile2 = [System.IO.Path]::GetTempFileName() + $stream1 = $null + $stream2 = $null + try { + [System.IO.File]::WriteAllText($tempFile1, $string) + [System.IO.File]::WriteAllText($tempFile2, $string) + + $stream1 = [System.IO.File]::OpenRead($tempFile1) + $stream2 = [System.IO.File]::OpenRead($tempFile2) + + $assertion = @($stream1, $stream2) | ConvertFrom-MemoryStreamToString + + $assertion | Should -HaveCount 2 + } finally { + if ($stream1) { $stream1.Dispose() } + if ($stream2) { $stream2.Dispose() } + if (Test-Path $tempFile1) { Remove-Item $tempFile1 -Force } + if (Test-Path $tempFile2) { Remove-Item $tempFile2 -Force } + } + } + } + + Context -Name 'Alias' -Fixture { + It -Name 'ConvertFrom-StreamToString alias works' -Test { + $string = 'ThisIsMyString' + $stream = [System.IO.MemoryStream]::new() + $writer = [System.IO.StreamWriter]::new($stream) + $writer.Write($string) + $writer.Flush() + + $assertion = ConvertFrom-StreamToString -Stream $stream + + $assertion | Should -BeExactly $string + + $stream.Dispose() + $writer.Dispose() + } + } + Context -Name 'Input/Output' -Fixture { It -Name "Converts a MemoryStream to a string" -Test { $string = 'ThisIsMyString' diff --git a/src/Tests/Unit/ConvertTo-String.Tests.ps1 b/src/Tests/Unit/ConvertTo-String.Tests.ps1 index 098132e..5265645 100644 --- a/src/Tests/Unit/ConvertTo-String.Tests.ps1 +++ b/src/Tests/Unit/ConvertTo-String.Tests.ps1 @@ -59,6 +59,94 @@ Describe -Name $function -Fixture { } } + Context -Name 'Stream input' -Fixture { + It -Name 'Converts MemoryStream using -Stream parameter' -Test { + $stream = [System.IO.MemoryStream]::new() + $writer = [System.IO.StreamWriter]::new($stream) + $writer.Write($String) + $writer.Flush() + + $assertion = ConvertTo-String -Stream $stream + + $assertion | Should -BeExactly $String + + $writer.Dispose() + $stream.Dispose() + } + + It -Name 'Converts FileStream to string' -Test { + $tempFile = [System.IO.Path]::GetTempFileName() + $fileStream = $null + try { + [System.IO.File]::WriteAllText($tempFile, $String) + $fileStream = [System.IO.File]::OpenRead($tempFile) + + $assertion = ConvertTo-String -Stream $fileStream + + $assertion | Should -BeExactly $String + } finally { + if ($fileStream) { $fileStream.Dispose() } + if (Test-Path $tempFile) { Remove-Item $tempFile -Force } + } + } + + It -Name 'Converts FileStream from Pipeline' -Test { + $tempFile = [System.IO.Path]::GetTempFileName() + $fileStream = $null + try { + [System.IO.File]::WriteAllText($tempFile, $String) + $fileStream = [System.IO.File]::OpenRead($tempFile) + + $assertion = $fileStream | ConvertTo-String + + $assertion | Should -BeExactly $String + } finally { + if ($fileStream) { $fileStream.Dispose() } + if (Test-Path $tempFile) { Remove-Item $tempFile -Force } + } + } + + It -Name 'Converts BufferedStream to string' -Test { + $memStream = [System.IO.MemoryStream]::new() + $writer = [System.IO.StreamWriter]::new($memStream) + $writer.Write($String) + $writer.Flush() + + $bufferedStream = [System.IO.BufferedStream]::new($memStream) + + $assertion = ConvertTo-String -Stream $bufferedStream + + $assertion | Should -BeExactly $String + + $bufferedStream.Dispose() + $writer.Dispose() + $memStream.Dispose() + } + + It -Name 'Converts array of FileStreams from Pipeline' -Test { + $tempFile1 = [System.IO.Path]::GetTempFileName() + $tempFile2 = [System.IO.Path]::GetTempFileName() + $stream1 = $null + $stream2 = $null + try { + [System.IO.File]::WriteAllText($tempFile1, $String) + [System.IO.File]::WriteAllText($tempFile2, $String) + + $stream1 = [System.IO.File]::OpenRead($tempFile1) + $stream2 = [System.IO.File]::OpenRead($tempFile2) + + $assertion = @($stream1, $stream2) | ConvertTo-String + + $assertion | Should -HaveCount 2 + } finally { + if ($stream1) { $stream1.Dispose() } + if ($stream2) { $stream2.Dispose() } + if (Test-Path $tempFile1) { Remove-Item $tempFile1 -Force } + if (Test-Path $tempFile2) { Remove-Item $tempFile2 -Force } + } + } + } + Context -Name 'MemoryStream input' -Fixture { It -Name 'Converts to base64 correctly' -Test { $stream = [System.IO.MemoryStream]::new() From 257fed9c28bbc960371c86d22873af714468382c Mon Sep 17 00:00:00 2001 From: Andrew Pearce Date: Wed, 28 Jan 2026 23:29:54 -0800 Subject: [PATCH 3/3] chore: bump version to 2.0.2-alpha --- src/Convert/Convert.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Convert/Convert.psd1 b/src/Convert/Convert.psd1 index b6a20e5..8ef0825 100644 --- a/src/Convert/Convert.psd1 +++ b/src/Convert/Convert.psd1 @@ -12,7 +12,7 @@ RootModule = 'Convert.psm1' # Version number of this module. - ModuleVersion = '2.0.1' + ModuleVersion = '2.0.2' # Supported PSEditions CompatiblePSEditions = @(