Skip to content

Commit 53b32f3

Browse files
Reproduce terminal provenance, raw metadata and module ref compatibility gaps
Publication spies accept malformed terminal markers and projected API arrays; stable PR provenance is absent, empty verified arrays fail, and valid module names can form invalid Git refs. All experiments are isolated. (cherry picked from commit 3faf9fb)
1 parent c665a9b commit 53b32f3

3 files changed

Lines changed: 124 additions & 1 deletion

File tree

‎.github/actions/Publish-PSModule/tests/Publish-PSModule.Preflight.Tests.ps1‎

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ BeforeAll {
1313
throw 'Cannot acquire the process environment lock for action tests.'
1414
}
1515
Import-Module -Name 'PSModule' -Force
16+
Import-Module -Name ([IO.Path]::Combine($PSScriptRoot, '..', 'src', 'Publish-PSModule.Helpers.psm1')) -Force
1617
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'Publish-PSModule.TestFixture.psm1') -Force
1718

1819
$script:publishScriptPath = [IO.Path]::GetFullPath(
@@ -178,6 +179,43 @@ Describe 'Publish-PSModule source-bound preflight' {
178179
$failure.Exception.Message | Should -Match '503|API|read|lookup'
179180
}
180181

182+
It 'rejects a malformed <Resource> response before publication' -ForEach @(
183+
@{ Resource = 'repository array' }
184+
@{ Resource = 'commit array' }
185+
@{ Resource = 'string write permission' }
186+
) {
187+
if ($Resource -ceq 'commit array') {
188+
$endpoint = "repos/PSModule/TestModule/git/commits/$env:GITHUB_SHA"
189+
$script:state.ApiResponses[$endpoint] = @([pscustomobject]@{ sha = $env:GITHUB_SHA })
190+
} else {
191+
$metadata = [pscustomobject]@{
192+
full_name = 'PSModule/TestModule'; permissions = [pscustomobject]@{ push = $true }
193+
}
194+
if ($Resource -ceq 'string write permission') {
195+
$metadata.permissions.push = 'true'
196+
$script:state.ApiResponses['repos/PSModule/TestModule'] = $metadata
197+
} else {
198+
$script:state.ApiResponses['repos/PSModule/TestModule'] = @($metadata)
199+
}
200+
}
201+
202+
$failure = $null
203+
try { & $script:publishScriptPath 1>$null 6>$null } catch { $failure = $_ }
204+
205+
$script:state.GalleryWrites | Should -Be 0
206+
$script:state.GitHubWrites | Should -Be 0
207+
$failure.Exception.Message | Should -Match 'metadata|access|source'
208+
}
209+
210+
It 'retains a verified empty tag enumeration instead of treating it as an unknown JSON response' {
211+
$script:state.ApiResponses['repos/PSModule/TestModule/git/matching-refs/tags/'] = @()
212+
213+
$response = Invoke-PSModulePublicationApi -Endpoint 'repos/PSModule/TestModule/git/matching-refs/tags/'
214+
215+
$response.Value -is [array] | Should -BeTrue
216+
$response.Value.Count | Should -Be 0
217+
}
218+
181219
It 'rejects a Gallery-only package with no source and artifact proof' {
182220
$script:state.Package = [pscustomobject]@{ Name = 'TestModule'; Version = '1.2.4' }
183221

@@ -475,6 +513,75 @@ Describe 'Publish-PSModule source-bound preflight' {
475513
$script:state.GitHubWrites | Should -Be 0
476514
}
477515

516+
It 'rejects a terminal ownership marker with <Shape> before publication' -ForEach @(
517+
@{ Shape = 'indentation' }
518+
@{ Shape = 'inline placement' }
519+
@{ Shape = 'missing delimiter spacing' }
520+
) {
521+
Set-PSModuleFixtureClaim -State $script:state -Claim $script:state.ExpectedClaim
522+
$owner = [pscustomobject]@{
523+
Repository = 'Other/TestModule'; PullRequest = 99; CommitSha = $env:GITHUB_SHA
524+
} | ConvertTo-Json -Compress
525+
$encoded = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($owner))
526+
$footer = "<!-- PSModule.PrereleaseOwner:v1:$encoded -->"
527+
if ($Shape -ceq 'indentation') {
528+
$body = "Notes.`n $footer"
529+
} elseif ($Shape -ceq 'inline placement') {
530+
$body = "Notes. $footer"
531+
} else {
532+
$body = $footer.Replace('<!-- ', '<!--')
533+
}
534+
$script:state.Release = [pscustomobject]@{
535+
tag_name = 'v1.2.4'; html_url = 'https://github.com/PSModule/TestModule/releases/tag/v1.2.4'
536+
prerelease = $false; draft = $false; body = $body; assets = @()
537+
}
538+
539+
$failure = $null
540+
try { & $script:publishScriptPath 1>$null 6>$null } catch { $failure = $_ }
541+
542+
$script:state.GalleryWrites | Should -Be 0
543+
$script:state.GitHubWrites | Should -Be 0
544+
$failure.Exception.Message | Should -Match 'footer'
545+
}
546+
547+
It 'rejects a stable PR release with no producing-context footer rather than inferring ownership from its tag' {
548+
$script:state.ExpectedClaim.PullRequest = 42
549+
$env:PSMODULE_PUBLISH_PSMODULE_INPUT_PullRequest = '{"Number":42}'
550+
Set-PSModuleFixtureClaim -State $script:state -Claim $script:state.ExpectedClaim
551+
$script:state.Release = [pscustomobject]@{
552+
tag_name = 'v1.2.4'; html_url = 'https://github.com/PSModule/TestModule/releases/tag/v1.2.4'
553+
prerelease = $false; draft = $false; body = 'Unknown stable publication context.'; assets = @()
554+
}
555+
556+
$failure = $null
557+
try { & $script:publishScriptPath 1>$null 6>$null } catch { $failure = $_ }
558+
559+
$script:state.GalleryWrites | Should -Be 0
560+
$script:state.GitHubWrites | Should -Be 0
561+
$failure.Exception.Message | Should -Match 'footer'
562+
}
563+
564+
It 'retains complete stable PR notes and footer across an exact missing-upload retry' {
565+
$script:state.ExpectedClaim.PullRequest = 42
566+
$env:PSMODULE_RELEASE_PSMODULE_INPUT_PullRequest = '{"Number":42,"Title":"Stable release","Body":"Complete authored stable notes."}'
567+
$env:PSMODULE_RELEASE_PSMODULE_INPUT_UsePRBodyAsReleaseNotes = 'true'
568+
$env:PSMODULE_RELEASE_PSMODULE_INPUT_UsePRTitleAsNotesHeading = 'true'
569+
570+
{ & $script:releaseScriptPath 1>$null 6>$null } | Should -Not -Throw
571+
572+
$script:state.Release.body | Should -Match 'Complete authored stable notes\.'
573+
(Get-PSModulePrereleaseOwnership -Body $script:state.Release.body).PullRequest | Should -Be 42
574+
$originalNotes = $script:state.Release.body
575+
$script:state.Release.assets = @()
576+
$script:state.GitHubWrites = 0
577+
$script:state.GitHubCreationUpload = 0
578+
579+
{ & $script:releaseScriptPath 1>$null 6>$null } | Should -Not -Throw
580+
581+
$script:state.GitHubCreationUpload | Should -Be 1
582+
$script:state.Release.body | Should -BeExactly $originalNotes
583+
}
584+
478585
It 'rejects a disappeared previously claimed tag rather than recreating it' {
479586
Set-PSModuleFixtureClaim -State $script:state -Claim $script:state.ExpectedClaim
480587
$script:state.OnTagRead = {

‎.github/actions/Publish-PSModule/tests/Publish-PSModule.TestFixture.psm1‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ function New-PSModulePublicationFixture {
205205
RawPackage = ''
206206
ModulePath = $Path
207207
ApiError = ''
208+
ApiResponses = @{}
208209
TagReads = 0
209210
OnTagRead = $null
210211
OnTagCreate = $null
@@ -300,7 +301,9 @@ function New-PSModulePublicationFixture {
300301
$endpoint = $Arguments[1]
301302
$status = 200
302303
$value = $null
303-
if ($Arguments -contains 'POST') {
304+
if ($state.ApiResponses.ContainsKey($endpoint)) {
305+
$value = $state.ApiResponses[$endpoint]
306+
} elseif ($Arguments -contains 'POST') {
304307
$state.GitHubWrites++
305308
$fields = @{}
306309
for ($index = 0; $index -lt $Arguments.Count - 1; $index++) {

‎.github/actions/Release-PSModule/tests/Release-PSModule.Ownership.Tests.ps1‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ Describe 'Source-bound publication proof' {
5050
Get-PSModulePublicationClaim -Message 'Legacy tag message.' | Should -BeNullOrEmpty
5151
}
5252

53+
It 'reserves a valid Git coordinate for module <Name>' -ForEach @(
54+
@{ Name = 'TestModule.lock' }
55+
@{ Name = 'Test..Module' }
56+
@{ Name = 'Microsoft.PowerShell.Management' }
57+
) {
58+
$coordinate = Get-PSModulePublicationVersionTag -ModuleName $Name -GalleryVersion '1.2.4'
59+
$gitPath = (Get-Command -Name git -CommandType Application | Select-Object -First 1).Source
60+
61+
& $gitPath check-ref-format "refs/tags/$coordinate"
62+
63+
$LASTEXITCODE | Should -Be 0
64+
}
65+
5366
It 'ignores a completed authored ownership marker followed by ordinary notes' {
5467
$owner = @{ Repository = 'PSModule/TestModule'; PullRequest = 42; CommitSha = 'original-source' } |
5568
ConvertTo-Json -Compress

0 commit comments

Comments
 (0)