lib/actions/releases/RepublishReleaseAction/RepublishReleaseAction.Tests.ps1
|
BeforeAll { . "$PSScriptRoot/../../../StateModel.ps1" . "$PSScriptRoot/../../../Logging.ps1" . "$PSScriptRoot/../../../GitHubApi.ps1" . "$PSScriptRoot/../../base/RemediationAction.ps1" . "$PSScriptRoot/../../base/ReleaseRemediationAction.ps1" . "$PSScriptRoot/RepublishReleaseAction.ps1" } Describe "RepublishReleaseAction" { BeforeEach { $script:state = [RepositoryState]::new() $script:state.RepoOwner = "test-owner" $script:state.RepoName = "test-repo" $script:state.ApiUrl = "https://api.github.com" $script:state.ServerUrl = "https://github.com" $script:state.Token = "test-token" } Context "Constructor" { It "Should create action with correct priority" { $action = [RepublishReleaseAction]::new("v1.0.0") $action.TagName | Should -Be "v1.0.0" $action.Priority | Should -Be 45 $action.Description | Should -Be "Republish release for immutability" } } Context "GetManualCommands" { It "Should generate manual commands without latest flag by default" { # Add an immutable release so the settings URL is not shown $immutableRelease = [PSCustomObject]@{ tag_name = "v2.0.0" id = 456 draft = $false prerelease = $false html_url = "https://github.com/test-owner/test-repo/releases/tag/v2.0.0" target_commitish = "def456" immutable = $true } $script:state.Releases = @([ReleaseInfo]::new($immutableRelease)) $action = [RepublishReleaseAction]::new("v1.0.0") $commands = $action.GetManualCommands($script:state) $commands.Count | Should -Be 2 $commands[0] | Should -Match "gh release edit v1.0.0" $commands[0] | Should -Match "--repo test-owner/test-repo" $commands[0] | Should -Match "--draft=true" $commands[1] | Should -Match "gh release edit v1.0.0" $commands[1] | Should -Match "--repo test-owner/test-repo" $commands[1] | Should -Match "--draft=false" $commands[1] | Should -Not -Match "--latest" } It "Should include --latest when MakeLatest is true" { # Add an immutable release so the settings URL is not shown $immutableRelease = [PSCustomObject]@{ tag_name = "v2.0.0" id = 456 draft = $false prerelease = $false html_url = "https://github.com/test-owner/test-repo/releases/tag/v2.0.0" target_commitish = "def456" immutable = $true } $script:state.Releases = @([ReleaseInfo]::new($immutableRelease)) $action = [RepublishReleaseAction]::new("v1.0.0") $action.MakeLatest = $true $commands = $action.GetManualCommands($script:state) $commands[1] | Should -Match "gh release edit v1.0.0" $commands[1] | Should -Match "--repo test-owner/test-repo" $commands[1] | Should -Match "--draft=false --latest" } It "Should include --latest=false when MakeLatest is false" { # Add an immutable release so the settings URL is not shown $immutableRelease = [PSCustomObject]@{ tag_name = "v2.0.0" id = 456 draft = $false prerelease = $false html_url = "https://github.com/test-owner/test-repo/releases/tag/v2.0.0" target_commitish = "def456" immutable = $true } $script:state.Releases = @([ReleaseInfo]::new($immutableRelease)) $action = [RepublishReleaseAction]::new("v1.0.0") $action.MakeLatest = $false $commands = $action.GetManualCommands($script:state) $commands[1] | Should -Match "gh release edit v1.0.0" $commands[1] | Should -Match "--repo test-owner/test-repo" $commands[1] | Should -Match "--draft=false --latest=false" } It "Should return empty array when issue is unfixable" { $action = [RepublishReleaseAction]::new("v1.0.0") $issue = [ValidationIssue]::new("non_immutable_release", "error", "Release not immutable") $issue.Version = "v1.0.0" $issue.Status = "unfixable" $script:state.Issues = @($issue) $commands = $action.GetManualCommands($script:state) $commands.Count | Should -Be 0 } It "Should return settings URL comment AND remediation commands when no immutable releases exist" { # When no immutable releases exist, show both the settings URL comment AND the gh release edit commands $action = [RepublishReleaseAction]::new("v1.0.0") $issue = [ValidationIssue]::new("non_immutable_release", "error", "Release v1.0.0 was republished but is still mutable. Enable 'Release immutability' in repository settings") $issue.Version = "v1.0.0" $issue.Status = "manual_fix_required" $script:state.Issues = @($issue) $script:state.Releases = @() # No immutable releases exist $commands = $action.GetManualCommands($script:state) $commands.Count | Should -Be 3 $commands[0] | Should -Match "^# Enable 'Release immutability'" $commands[0] | Should -Match "settings#releases-settings" $commands[1] | Should -Match "gh release edit v1.0.0" $commands[1] | Should -Match "--draft=true" $commands[2] | Should -Match "gh release edit v1.0.0" $commands[2] | Should -Match "--draft=false" } It "Should return settings URL comment AND remediation commands when auto-fix is false" { # Show settings URL AND remediation commands when no immutable releases exist # This ensures users see the comment even in non-autofix mode $action = [RepublishReleaseAction]::new("v1.0.0") $issue = [ValidationIssue]::new("non_immutable_release", "error", "Release v1.0.0 is published but not immutable") $issue.Version = "v1.0.0" $issue.Status = "pending" # Not yet processed $script:state.Issues = @($issue) $script:state.Releases = @() # No immutable releases exist $commands = $action.GetManualCommands($script:state) $commands.Count | Should -Be 3 $commands[0] | Should -Match "^# Enable 'Release immutability'" $commands[0] | Should -Match "settings#releases-settings" $commands[1] | Should -Match "gh release edit v1.0.0" $commands[1] | Should -Match "--draft=true" $commands[2] | Should -Match "gh release edit v1.0.0" $commands[2] | Should -Match "--draft=false" } It "Should return gh release edit commands when repo already has immutable releases" { # If the repo already has immutable releases, the feature is enabled - no need for settings URL $action = [RepublishReleaseAction]::new("v1.0.0") $issue = [ValidationIssue]::new("non_immutable_release", "error", "Release v1.0.0 was republished but is still mutable. Enable 'Release immutability' in repository settings") $issue.Version = "v1.0.0" $issue.Status = "manual_fix_required" $script:state.Issues = @($issue) # Add an immutable release to the state - feature is already enabled $immutableRelease = [PSCustomObject]@{ tag_name = "v2.0.0" id = 456 draft = $false prerelease = $false html_url = "https://github.com/test-owner/test-repo/releases/tag/v2.0.0" target_commitish = "def456" immutable = $true } $script:state.Releases = @([ReleaseInfo]::new($immutableRelease)) $commands = $action.GetManualCommands($script:state) # Should return gh release edit commands since feature is already enabled $commands.Count | Should -Be 2 $commands[0] | Should -Match "gh release edit v1.0.0" $commands[0] | Should -Match "--draft=true" $commands[1] | Should -Match "gh release edit v1.0.0" $commands[1] | Should -Match "--draft=false" } It "Should return gh release edit commands when repo has immutable releases even in manual_fix_required state" { # When auto-fix: false, Invoke-AutoFix marks ALL pending issues as # manual_fix_required before GetManualCommands is called. # If the repo has immutable releases, show gh release edit commands. $action = [RepublishReleaseAction]::new("v1.0.0") $issue = [ValidationIssue]::new("non_immutable_release", "error", "Release v1.0.0 is published but not immutable (repository 'Release immutability' setting may not be enabled)") $issue.Version = "v1.0.0" $issue.Status = "manual_fix_required" # Set by Invoke-AutoFix when auto-fix: false $script:state.Issues = @($issue) # Add an immutable release - feature is already enabled $immutableRelease = [PSCustomObject]@{ tag_name = "v2.0.0" id = 456 draft = $false prerelease = $false html_url = "https://github.com/test-owner/test-repo/releases/tag/v2.0.0" target_commitish = "def456" immutable = $true } $script:state.Releases = @([ReleaseInfo]::new($immutableRelease)) $commands = $action.GetManualCommands($script:state) # Should return gh release edit commands, NOT the settings URL $commands.Count | Should -Be 2 $commands[0] | Should -Match "gh release edit v1.0.0" $commands[0] | Should -Match "--draft=true" $commands[1] | Should -Match "gh release edit v1.0.0" $commands[1] | Should -Match "--draft=false" } It "Should not show settings URL when another immutability fix already succeeded" { # If auto-fix succeeded for one release (status=fixed), the feature is enabled # So we shouldn't show the settings URL for subsequent failed fixes $action = [RepublishReleaseAction]::new("v1.0.7") # v1.0.8 was successfully fixed (status=fixed) $fixedIssue = [ValidationIssue]::new("non_immutable_release", "error", "Release v1.0.8 was fixed") $fixedIssue.Version = "v1.0.8" $fixedIssue.Status = "fixed" # v1.0.7 failed to fix $failedIssue = [ValidationIssue]::new("non_immutable_release", "error", "Release v1.0.7 failed") $failedIssue.Version = "v1.0.7" $failedIssue.Status = "failed" $script:state.Issues = @($fixedIssue, $failedIssue) $script:state.Releases = @() # No immutable releases in original state $commands = $action.GetManualCommands($script:state) # Should NOT show settings URL since another fix succeeded (feature is enabled) $commands.Count | Should -Be 2 $commands[0] | Should -Match "gh release edit v1.0.7" $commands[0] | Should -Match "--draft=true" $commands[1] | Should -Match "gh release edit v1.0.7" $commands[1] | Should -Match "--draft=false" } } Context "Execute" { BeforeEach { Mock Republish-GitHubRelease { return @{ Success = $true } } Mock Test-ReleaseImmutability { return $true } } It "Should republish and verify immutability" { $action = [RepublishReleaseAction]::new("v1.0.0") $result = $action.Execute($script:state) $result | Should -Be $true Should -Invoke Republish-GitHubRelease -Times 1 Should -Invoke Test-ReleaseImmutability -Times 1 } It "Should mark as manual_fix_required when republish succeeds but still mutable" { Mock Test-ReleaseImmutability { return $false } $action = [RepublishReleaseAction]::new("v1.0.0") $issue = [ValidationIssue]::new("non_immutable_release", "error", "Release not immutable") $issue.Version = "v1.0.0" $issue.Status = "pending" $script:state.Issues = @($issue) $result = $action.Execute($script:state) $result | Should -Be $false $issue.Status | Should -Be "manual_fix_required" $issue.Message | Should -Match "Enable 'Release immutability'" } It "Should mark as unfixable on 422 error" { Mock Republish-GitHubRelease { return @{ Success = $false; Unfixable = $true } } $action = [RepublishReleaseAction]::new("v1.0.0") $issue = [ValidationIssue]::new("non_immutable_release", "error", "Release not immutable") $issue.Version = "v1.0.0" $issue.Status = "pending" $script:state.Issues = @($issue) $result = $action.Execute($script:state) $result | Should -Be $false $issue.Status | Should -Be "unfixable" } } } |