diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index 3df83f7..04409d8 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -17,8 +17,8 @@ permissions: pull-requests: read jobs: - ActionTest-PatchBump: - name: Action-Test - [Patch bump] + Action-Test: + name: Action-Test runs-on: ubuntu-latest steps: - name: Checkout repo @@ -26,624 +26,29 @@ jobs: with: persist-credentials: false - - name: Create fake PR event - shell: pwsh - run: | - $event = @{ - pull_request = @{ - head = @{ ref = 'feat/test-patch' } - labels = @( - @{ name = 'patch' } - ) - } - } | ConvertTo-Json -Depth 5 - $event | Set-Content -Path "$env:RUNNER_TEMP/event.json" - "GITHUB_EVENT_PATH=$env:RUNNER_TEMP/event.json" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Resolve-PSModuleVersion - id: resolve - uses: ./ - env: - GH_TOKEN: ${{ github.token }} - with: - Settings: | - { - "Publish": { - "Module": { - "ReleaseType": "Release", - "AutoPatching": false, - "VersionPrefix": "v", - "MajorLabels": "major", - "MinorLabels": "minor", - "PatchLabels": "patch", - "IgnoreLabels": "" - } - } - } - EventJson: '{"pull_request":{"head":{"ref":"feat/test-patch"},"labels":[{"name":"patch"}]}}' - - - name: Verify - Patch bump - shell: pwsh - env: - GH_TOKEN: ${{ github.token }} - RESOLVE_CREATE_RELEASE: ${{ steps.resolve.outputs.CreateRelease }} - RESOLVE_VERSION: ${{ steps.resolve.outputs.Version }} - RESOLVE_RELEASE_TYPE: ${{ steps.resolve.outputs.ReleaseType }} - RESOLVE_FULL_VERSION: ${{ steps.resolve.outputs.FullVersion }} - run: | - $PSStyle.OutputRendering = 'Ansi' - - $releases = (gh release list --json 'tagName,isLatest') | ConvertFrom-Json - $latestTag = ($releases | Where-Object { $_.isLatest }).tagName - if ([string]::IsNullOrEmpty($latestTag)) { $parts = @(0, 0, 0) } - else { $parts = ($latestTag -replace '^v', '').Split('.') | ForEach-Object { [int]$_ } } - $expectedVersion = "$($parts[0]).$($parts[1]).$($parts[2] + 1)" - $expectedFullVersion = "v$expectedVersion" - - Write-Host '--- Input ---' - Write-Host "EventJson: {`"pull_request`":{`"head`":{`"ref`":`"feat/test-patch`"},`"labels`":[{`"name`":`"patch`"}]}}" - Write-Host "Settings: ReleaseType=Release, AutoPatching=false, PatchLabels=patch" - Write-Host '' - - @( - [PSCustomObject]@{ Output = 'CreateRelease'; Expected = 'true'; Actual = $env:RESOLVE_CREATE_RELEASE; Passed = $env:RESOLVE_CREATE_RELEASE -eq 'true' } - [PSCustomObject]@{ Output = 'ReleaseType'; Expected = 'Release'; Actual = $env:RESOLVE_RELEASE_TYPE; Passed = $env:RESOLVE_RELEASE_TYPE -eq 'Release' } - [PSCustomObject]@{ Output = 'Version'; Expected = $expectedVersion; Actual = $env:RESOLVE_VERSION; Passed = $env:RESOLVE_VERSION -eq $expectedVersion } - [PSCustomObject]@{ Output = 'FullVersion'; Expected = $expectedFullVersion; Actual = $env:RESOLVE_FULL_VERSION; Passed = $env:RESOLVE_FULL_VERSION -eq $expectedFullVersion } - ) | Format-Table -AutoSize | Out-String -Width 200 - - $failed = $false - if ($env:RESOLVE_CREATE_RELEASE -ne 'true') { - Write-Error "CreateRelease: expected 'true', got '$env:RESOLVE_CREATE_RELEASE'" - $failed = $true - } - if ($env:RESOLVE_VERSION -ne $expectedVersion) { - Write-Error "Version: expected '$expectedVersion', got '$env:RESOLVE_VERSION'" - $failed = $true - } - if ($env:RESOLVE_RELEASE_TYPE -ne 'Release') { - Write-Error "ReleaseType: expected 'Release', got '$env:RESOLVE_RELEASE_TYPE'" - $failed = $true - } - if ($env:RESOLVE_FULL_VERSION -ne $expectedFullVersion) { - Write-Error "FullVersion: expected '$expectedFullVersion', got '$env:RESOLVE_FULL_VERSION'" - $failed = $true - } - if ($failed) { exit 1 } - - ActionTest-MinorBump: - name: Action-Test - [Minor bump] - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - - name: Create fake PR event - shell: pwsh - run: | - $event = @{ - pull_request = @{ - head = @{ ref = 'feat/test-minor' } - labels = @( - @{ name = 'minor' } - ) - } - } | ConvertTo-Json -Depth 5 - $event | Set-Content -Path "$env:RUNNER_TEMP/event.json" - "GITHUB_EVENT_PATH=$env:RUNNER_TEMP/event.json" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Resolve-PSModuleVersion - id: resolve - uses: ./ - env: - GH_TOKEN: ${{ github.token }} - with: - Settings: | - { - "Publish": { - "Module": { - "ReleaseType": "Release", - "AutoPatching": false, - "VersionPrefix": "v", - "MajorLabels": "major", - "MinorLabels": "minor", - "PatchLabels": "patch", - "IgnoreLabels": "" - } - } - } - EventJson: '{"pull_request":{"head":{"ref":"feat/test-minor"},"labels":[{"name":"minor"}]}}' - - - name: Verify - Minor bump - shell: pwsh - env: - GH_TOKEN: ${{ github.token }} - RESOLVE_CREATE_RELEASE: ${{ steps.resolve.outputs.CreateRelease }} - RESOLVE_VERSION: ${{ steps.resolve.outputs.Version }} - RESOLVE_RELEASE_TYPE: ${{ steps.resolve.outputs.ReleaseType }} - RESOLVE_FULL_VERSION: ${{ steps.resolve.outputs.FullVersion }} - run: | - $PSStyle.OutputRendering = 'Ansi' - - $releases = (gh release list --json 'tagName,isLatest') | ConvertFrom-Json - $latestTag = ($releases | Where-Object { $_.isLatest }).tagName - if ([string]::IsNullOrEmpty($latestTag)) { $parts = @(0, 0, 0) } - else { $parts = ($latestTag -replace '^v', '').Split('.') | ForEach-Object { [int]$_ } } - $expectedVersion = "$($parts[0]).$($parts[1] + 1).0" - $expectedFullVersion = "v$expectedVersion" - - Write-Host '--- Input ---' - Write-Host "EventJson: {`"pull_request`":{`"head`":{`"ref`":`"feat/test-minor`"},`"labels`":[{`"name`":`"minor`"}]}}" - Write-Host "Settings: ReleaseType=Release, AutoPatching=false, MinorLabels=minor" - Write-Host '' - - @( - [PSCustomObject]@{ Output = 'CreateRelease'; Expected = 'true'; Actual = $env:RESOLVE_CREATE_RELEASE; Passed = $env:RESOLVE_CREATE_RELEASE -eq 'true' } - [PSCustomObject]@{ Output = 'ReleaseType'; Expected = 'Release'; Actual = $env:RESOLVE_RELEASE_TYPE; Passed = $env:RESOLVE_RELEASE_TYPE -eq 'Release' } - [PSCustomObject]@{ Output = 'Version'; Expected = $expectedVersion; Actual = $env:RESOLVE_VERSION; Passed = $env:RESOLVE_VERSION -eq $expectedVersion } - [PSCustomObject]@{ Output = 'FullVersion'; Expected = $expectedFullVersion; Actual = $env:RESOLVE_FULL_VERSION; Passed = $env:RESOLVE_FULL_VERSION -eq $expectedFullVersion } - ) | Format-Table -AutoSize | Out-String -Width 200 - - $failed = $false - if ($env:RESOLVE_CREATE_RELEASE -ne 'true') { - Write-Error "CreateRelease: expected 'true', got '$env:RESOLVE_CREATE_RELEASE'" - $failed = $true - } - if ($env:RESOLVE_VERSION -ne $expectedVersion) { - Write-Error "Version: expected '$expectedVersion', got '$env:RESOLVE_VERSION'" - $failed = $true - } - if ($env:RESOLVE_RELEASE_TYPE -ne 'Release') { - Write-Error "ReleaseType: expected 'Release', got '$env:RESOLVE_RELEASE_TYPE'" - $failed = $true - } - if ($env:RESOLVE_FULL_VERSION -ne $expectedFullVersion) { - Write-Error "FullVersion: expected '$expectedFullVersion', got '$env:RESOLVE_FULL_VERSION'" - $failed = $true - } - if ($failed) { exit 1 } - - ActionTest-MajorBump: - name: Action-Test - [Major bump] - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - - name: Create fake PR event - shell: pwsh - run: | - $event = @{ - pull_request = @{ - head = @{ ref = 'feat/test-major' } - labels = @( - @{ name = 'major' } - ) - } - } | ConvertTo-Json -Depth 5 - $event | Set-Content -Path "$env:RUNNER_TEMP/event.json" - "GITHUB_EVENT_PATH=$env:RUNNER_TEMP/event.json" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Resolve-PSModuleVersion - id: resolve - uses: ./ - env: - GH_TOKEN: ${{ github.token }} - with: - Settings: | - { - "Publish": { - "Module": { - "ReleaseType": "Release", - "AutoPatching": false, - "VersionPrefix": "v", - "MajorLabels": "major", - "MinorLabels": "minor", - "PatchLabels": "patch", - "IgnoreLabels": "" - } - } - } - EventJson: '{"pull_request":{"head":{"ref":"feat/test-major"},"labels":[{"name":"major"}]}}' - - - name: Verify - Major bump - shell: pwsh - env: - GH_TOKEN: ${{ github.token }} - RESOLVE_CREATE_RELEASE: ${{ steps.resolve.outputs.CreateRelease }} - RESOLVE_VERSION: ${{ steps.resolve.outputs.Version }} - RESOLVE_RELEASE_TYPE: ${{ steps.resolve.outputs.ReleaseType }} - RESOLVE_FULL_VERSION: ${{ steps.resolve.outputs.FullVersion }} - run: | - $PSStyle.OutputRendering = 'Ansi' - - $releases = (gh release list --json 'tagName,isLatest') | ConvertFrom-Json - $latestTag = ($releases | Where-Object { $_.isLatest }).tagName - if ([string]::IsNullOrEmpty($latestTag)) { $parts = @(0, 0, 0) } - else { $parts = ($latestTag -replace '^v', '').Split('.') | ForEach-Object { [int]$_ } } - $expectedVersion = "$($parts[0] + 1).0.0" - $expectedFullVersion = "v$expectedVersion" - - Write-Host '--- Input ---' - Write-Host "EventJson: {`"pull_request`":{`"head`":{`"ref`":`"feat/test-major`"},`"labels`":[{`"name`":`"major`"}]}}" - Write-Host "Settings: ReleaseType=Release, AutoPatching=false, MajorLabels=major" - Write-Host '' - - @( - [PSCustomObject]@{ Output = 'CreateRelease'; Expected = 'true'; Actual = $env:RESOLVE_CREATE_RELEASE; Passed = $env:RESOLVE_CREATE_RELEASE -eq 'true' } - [PSCustomObject]@{ Output = 'ReleaseType'; Expected = 'Release'; Actual = $env:RESOLVE_RELEASE_TYPE; Passed = $env:RESOLVE_RELEASE_TYPE -eq 'Release' } - [PSCustomObject]@{ Output = 'Version'; Expected = $expectedVersion; Actual = $env:RESOLVE_VERSION; Passed = $env:RESOLVE_VERSION -eq $expectedVersion } - [PSCustomObject]@{ Output = 'FullVersion'; Expected = $expectedFullVersion; Actual = $env:RESOLVE_FULL_VERSION; Passed = $env:RESOLVE_FULL_VERSION -eq $expectedFullVersion } - ) | Format-Table -AutoSize | Out-String -Width 200 - - $failed = $false - if ($env:RESOLVE_CREATE_RELEASE -ne 'true') { - Write-Error "CreateRelease: expected 'true', got '$env:RESOLVE_CREATE_RELEASE'" - $failed = $true - } - if ($env:RESOLVE_VERSION -ne $expectedVersion) { - Write-Error "Version: expected '$expectedVersion', got '$env:RESOLVE_VERSION'" - $failed = $true - } - if ($env:RESOLVE_RELEASE_TYPE -ne 'Release') { - Write-Error "ReleaseType: expected 'Release', got '$env:RESOLVE_RELEASE_TYPE'" - $failed = $true - } - if ($env:RESOLVE_FULL_VERSION -ne $expectedFullVersion) { - Write-Error "FullVersion: expected '$expectedFullVersion', got '$env:RESOLVE_FULL_VERSION'" - $failed = $true - } - if ($failed) { exit 1 } - - ActionTest-AutoPatch: - name: Action-Test - [Auto-patch] - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - - name: Create fake PR event - shell: pwsh - run: | - $event = @{ - pull_request = @{ - head = @{ ref = 'feat/test-autopatch' } - labels = @() - } - } | ConvertTo-Json -Depth 5 - $event | Set-Content -Path "$env:RUNNER_TEMP/event.json" - "GITHUB_EVENT_PATH=$env:RUNNER_TEMP/event.json" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Resolve-PSModuleVersion - id: resolve - uses: ./ - env: - GH_TOKEN: ${{ github.token }} - with: - Settings: | - { - "Publish": { - "Module": { - "ReleaseType": "Release", - "AutoPatching": true, - "VersionPrefix": "v", - "MajorLabels": "major", - "MinorLabels": "minor", - "PatchLabels": "patch", - "IgnoreLabels": "" - } - } - } - EventJson: '{"pull_request":{"head":{"ref":"feat/test-autopatch"},"labels":[]}}' - - - name: Verify - Auto-patch - shell: pwsh - env: - GH_TOKEN: ${{ github.token }} - RESOLVE_CREATE_RELEASE: ${{ steps.resolve.outputs.CreateRelease }} - RESOLVE_VERSION: ${{ steps.resolve.outputs.Version }} - RESOLVE_RELEASE_TYPE: ${{ steps.resolve.outputs.ReleaseType }} - RESOLVE_FULL_VERSION: ${{ steps.resolve.outputs.FullVersion }} - run: | - $PSStyle.OutputRendering = 'Ansi' - - $releases = (gh release list --json 'tagName,isLatest') | ConvertFrom-Json - $latestTag = ($releases | Where-Object { $_.isLatest }).tagName - if ([string]::IsNullOrEmpty($latestTag)) { $parts = @(0, 0, 0) } - else { $parts = ($latestTag -replace '^v', '').Split('.') | ForEach-Object { [int]$_ } } - $expectedVersion = "$($parts[0]).$($parts[1]).$($parts[2] + 1)" - $expectedFullVersion = "v$expectedVersion" - - Write-Host '--- Input ---' - Write-Host "EventJson: {`"pull_request`":{`"head`":{`"ref`":`"feat/test-autopatch`"},`"labels`":[]}}" - Write-Host "Settings: ReleaseType=Release, AutoPatching=true, PatchLabels=patch" - Write-Host '' - - @( - [PSCustomObject]@{ Output = 'CreateRelease'; Expected = 'true'; Actual = $env:RESOLVE_CREATE_RELEASE; Passed = $env:RESOLVE_CREATE_RELEASE -eq 'true' } - [PSCustomObject]@{ Output = 'ReleaseType'; Expected = 'Release'; Actual = $env:RESOLVE_RELEASE_TYPE; Passed = $env:RESOLVE_RELEASE_TYPE -eq 'Release' } - [PSCustomObject]@{ Output = 'Version'; Expected = $expectedVersion; Actual = $env:RESOLVE_VERSION; Passed = $env:RESOLVE_VERSION -eq $expectedVersion } - [PSCustomObject]@{ Output = 'FullVersion'; Expected = $expectedFullVersion; Actual = $env:RESOLVE_FULL_VERSION; Passed = $env:RESOLVE_FULL_VERSION -eq $expectedFullVersion } - ) | Format-Table -AutoSize | Out-String -Width 200 - - $failed = $false - if ($env:RESOLVE_CREATE_RELEASE -ne 'true') { - Write-Error "CreateRelease: expected 'true', got '$env:RESOLVE_CREATE_RELEASE'" - $failed = $true - } - if ($env:RESOLVE_VERSION -ne $expectedVersion) { - Write-Error "Version: expected '$expectedVersion', got '$env:RESOLVE_VERSION'" - $failed = $true - } - if ($env:RESOLVE_RELEASE_TYPE -ne 'Release') { - Write-Error "ReleaseType: expected 'Release', got '$env:RESOLVE_RELEASE_TYPE'" - $failed = $true - } - if ($env:RESOLVE_FULL_VERSION -ne $expectedFullVersion) { - Write-Error "FullVersion: expected '$expectedFullVersion', got '$env:RESOLVE_FULL_VERSION'" - $failed = $true - } - if ($failed) { exit 1 } - - ActionTest-IgnoreLabel: - name: Action-Test - [Ignore label] - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - - name: Create fake PR event - shell: pwsh - run: | - $event = @{ - pull_request = @{ - head = @{ ref = 'feat/test-ignore' } - labels = @( - @{ name = 'patch' } - @{ name = 'skip-release' } - ) - } - } | ConvertTo-Json -Depth 5 - $event | Set-Content -Path "$env:RUNNER_TEMP/fake-event.json" - "GITHUB_EVENT_PATH=$env:RUNNER_TEMP/fake-event.json" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Resolve-PSModuleVersion - id: resolve - uses: ./ - env: - GH_TOKEN: ${{ github.token }} - with: - Settings: | - { - "Publish": { - "Module": { - "ReleaseType": "Release", - "AutoPatching": false, - "VersionPrefix": "v", - "MajorLabels": "major", - "MinorLabels": "minor", - "PatchLabels": "patch", - "IgnoreLabels": "skip-release" - } - } - } - EventPath: ${{ runner.temp }}/fake-event.json - EventJson: '{"pull_request":{"head":{"ref":"feat/test-ignore"},"labels":[{"name":"patch"},{"name":"skip-release"}]}}' - - - name: Verify - Ignore label - shell: pwsh - env: - RESOLVE_CREATE_RELEASE: ${{ steps.resolve.outputs.CreateRelease }} - RESOLVE_RELEASE_TYPE: ${{ steps.resolve.outputs.ReleaseType }} - run: | - $PSStyle.OutputRendering = 'Ansi' - - Write-Host '--- Input ---' - Write-Host "EventJson: {`"pull_request`":{`"head`":{`"ref`":`"feat/test-ignore`"},`"labels`":[{`"name`":`"patch`"},{`"name`":`"skip-release`"}]}}" - Write-Host "Settings: ReleaseType=Release, AutoPatching=false, IgnoreLabels=skip-release" - Write-Host '' - - @( - [PSCustomObject]@{ Output = 'CreateRelease'; Expected = 'false'; Actual = $env:RESOLVE_CREATE_RELEASE; Passed = $env:RESOLVE_CREATE_RELEASE -eq 'false' } - [PSCustomObject]@{ Output = 'ReleaseType'; Expected = 'None'; Actual = $env:RESOLVE_RELEASE_TYPE; Passed = $env:RESOLVE_RELEASE_TYPE -eq 'None' } - ) | Format-Table -AutoSize | Out-String -Width 200 - - $failed = $false - if ($env:RESOLVE_CREATE_RELEASE -ne 'false') { - Write-Error "CreateRelease: expected 'false', got '$env:RESOLVE_CREATE_RELEASE'" - $failed = $true - } - if ($env:RESOLVE_RELEASE_TYPE -ne 'None') { - Write-Error "ReleaseType: expected 'None', got '$env:RESOLVE_RELEASE_TYPE'" - $failed = $true - } - if ($failed) { exit 1 } - - ActionTest-None: - name: Action-Test - [None release type] - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - - name: Create fake PR event - shell: pwsh - run: | - $event = @{ - pull_request = @{ - head = @{ ref = 'feat/test-none' } - labels = @( - @{ name = 'patch' } - ) - } - } | ConvertTo-Json -Depth 5 - $event | Set-Content -Path "$env:RUNNER_TEMP/event.json" - "GITHUB_EVENT_PATH=$env:RUNNER_TEMP/event.json" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Resolve-PSModuleVersion - id: resolve - uses: ./ + - name: Run Pester tests + id: pester + uses: PSModule/Invoke-Pester@266d1cf2532f572470b7c4463fa1072f2bfe4455 # v4.2.5 with: - Settings: | - { - "Publish": { - "Module": { - "ReleaseType": "None", - "AutoPatching": false, - "VersionPrefix": "v", - "MajorLabels": "major", - "MinorLabels": "minor", - "PatchLabels": "patch", - "IgnoreLabels": "" - } - } - } - EventJson: '{"pull_request":{"head":{"ref":"feat/test-none"},"labels":[{"name":"patch"}]}}' + Path: ./tests + Run_Path: ./scripts + Output_Verbosity: Detailed + TestResult_TestSuiteName: Resolve-PSModuleVersion - - name: Verify - None release type + - name: Check test outcome shell: pwsh + if: always() env: - RESOLVE_CREATE_RELEASE: ${{ steps.resolve.outputs.CreateRelease }} - RESOLVE_VERSION: ${{ steps.resolve.outputs.Version }} - RESOLVE_RELEASE_TYPE: ${{ steps.resolve.outputs.ReleaseType }} + OUTCOME: ${{ steps.pester.outcome }} + PASSED: ${{ steps.pester.outputs.PassedCount }} + FAILED: ${{ steps.pester.outputs.FailedCount }} + TOTAL: ${{ steps.pester.outputs.TotalCount }} run: | - $PSStyle.OutputRendering = 'Ansi' - - Write-Host '--- Input ---' - Write-Host "EventJson: {`"pull_request`":{`"head`":{`"ref`":`"feat/test-none`"},`"labels`":[{`"name`":`"patch`"}]}}" - Write-Host "Settings: ReleaseType=None, AutoPatching=false" - Write-Host '' - - @( - [PSCustomObject]@{ Output = 'CreateRelease'; Expected = 'false'; Actual = $env:RESOLVE_CREATE_RELEASE; Passed = $env:RESOLVE_CREATE_RELEASE -eq 'false' } - [PSCustomObject]@{ Output = 'ReleaseType'; Expected = 'None'; Actual = $env:RESOLVE_RELEASE_TYPE; Passed = $env:RESOLVE_RELEASE_TYPE -eq 'None' } - [PSCustomObject]@{ Output = 'Version'; Expected = '(empty)'; Actual = $env:RESOLVE_VERSION; Passed = [string]::IsNullOrEmpty($env:RESOLVE_VERSION) } - ) | Format-Table -AutoSize | Out-String -Width 200 - - $failed = $false - if ($env:RESOLVE_CREATE_RELEASE -ne 'false') { - Write-Error "CreateRelease: expected 'false', got '$env:RESOLVE_CREATE_RELEASE'" - $failed = $true - } - if (-not [string]::IsNullOrEmpty($env:RESOLVE_VERSION)) { - Write-Error "Version: expected empty, got '$env:RESOLVE_VERSION'" - $failed = $true - } - if ($env:RESOLVE_RELEASE_TYPE -ne 'None') { - Write-Error "ReleaseType: expected 'None', got '$env:RESOLVE_RELEASE_TYPE'" - $failed = $true - } - if ($failed) { exit 1 } - - ActionTest-Prerelease: - name: Action-Test - [Prerelease] - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - - name: Create fake PR event - shell: pwsh - run: | - $event = @{ - pull_request = @{ - head = @{ ref = 'feat/add-prerelease-support' } - labels = @( - @{ name = 'minor' } - ) - } - } | ConvertTo-Json -Depth 5 - $event | Set-Content -Path "$env:RUNNER_TEMP/event.json" - "GITHUB_EVENT_PATH=$env:RUNNER_TEMP/event.json" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Resolve-PSModuleVersion - id: resolve - uses: ./ - env: - GH_TOKEN: ${{ github.token }} - with: - Settings: | - { - "Publish": { - "Module": { - "ReleaseType": "Prerelease", - "AutoPatching": false, - "IncrementalPrerelease": true, - "DatePrereleaseFormat": "", - "VersionPrefix": "v", - "MajorLabels": "major", - "MinorLabels": "minor", - "PatchLabels": "patch", - "IgnoreLabels": "" - } - } - } - EventJson: '{"pull_request":{"head":{"ref":"feat/add-prerelease-support"},"labels":[{"name":"minor"}]}}' - - - name: Verify - Prerelease - shell: pwsh - env: - GH_TOKEN: ${{ github.token }} - RESOLVE_CREATE_RELEASE: ${{ steps.resolve.outputs.CreateRelease }} - RESOLVE_VERSION: ${{ steps.resolve.outputs.Version }} - RESOLVE_PRERELEASE: ${{ steps.resolve.outputs.Prerelease }} - RESOLVE_RELEASE_TYPE: ${{ steps.resolve.outputs.ReleaseType }} - RESOLVE_FULL_VERSION: ${{ steps.resolve.outputs.FullVersion }} - run: | - $PSStyle.OutputRendering = 'Ansi' - - $releases = (gh release list --json 'tagName,isLatest') | ConvertFrom-Json - $latestTag = ($releases | Where-Object { $_.isLatest }).tagName - if ([string]::IsNullOrEmpty($latestTag)) { $parts = @(0, 0, 0) } - else { $parts = ($latestTag -replace '^v', '').Split('.') | ForEach-Object { [int]$_ } } - $expectedVersion = "$($parts[0]).$($parts[1] + 1).0" - $expectedPrerelease = 'feataddprereleasesupport001' - $expectedFullVersion = "v$expectedVersion-$expectedPrerelease" - - Write-Host '--- Input ---' - Write-Host "EventJson: {`"pull_request`":{`"head`":{`"ref`":`"feat/add-prerelease-support`"},`"labels`":[{`"name`":`"minor`"}]}}" - Write-Host "Settings: ReleaseType=Prerelease, AutoPatching=false, IncrementalPrerelease=true, MinorLabels=minor" - Write-Host '' - - @( - [PSCustomObject]@{ Output = 'CreateRelease'; Expected = 'true'; Actual = $env:RESOLVE_CREATE_RELEASE; Passed = $env:RESOLVE_CREATE_RELEASE -eq 'true' } - [PSCustomObject]@{ Output = 'ReleaseType'; Expected = 'Prerelease'; Actual = $env:RESOLVE_RELEASE_TYPE; Passed = $env:RESOLVE_RELEASE_TYPE -eq 'Prerelease' } - [PSCustomObject]@{ Output = 'Version'; Expected = $expectedVersion; Actual = $env:RESOLVE_VERSION; Passed = $env:RESOLVE_VERSION -eq $expectedVersion } - [PSCustomObject]@{ Output = 'Prerelease'; Expected = $expectedPrerelease; Actual = $env:RESOLVE_PRERELEASE; Passed = $env:RESOLVE_PRERELEASE -eq $expectedPrerelease } - [PSCustomObject]@{ Output = 'FullVersion'; Expected = $expectedFullVersion; Actual = $env:RESOLVE_FULL_VERSION; Passed = $env:RESOLVE_FULL_VERSION -eq $expectedFullVersion } - ) | Format-Table -AutoSize | Out-String -Width 200 - - $failed = $false - if ($env:RESOLVE_CREATE_RELEASE -ne 'true') { - Write-Error "CreateRelease: expected 'true', got '$env:RESOLVE_CREATE_RELEASE'" - $failed = $true - } - if ($env:RESOLVE_RELEASE_TYPE -ne 'Prerelease') { - Write-Error "ReleaseType: expected 'Prerelease', got '$env:RESOLVE_RELEASE_TYPE'" - $failed = $true - } - if ($env:RESOLVE_VERSION -ne $expectedVersion) { - Write-Error "Version: expected '$expectedVersion', got '$env:RESOLVE_VERSION'" - $failed = $true - } - if ($env:RESOLVE_PRERELEASE -ne $expectedPrerelease) { - Write-Error "Prerelease: expected '$expectedPrerelease', got '$env:RESOLVE_PRERELEASE'" - $failed = $true - } - if ($env:RESOLVE_FULL_VERSION -ne $expectedFullVersion) { - Write-Error "FullVersion: expected '$expectedFullVersion', got '$env:RESOLVE_FULL_VERSION'" - $failed = $true + Write-Host "Outcome: [$env:OUTCOME]" + Write-Host "Passed: [$env:PASSED]" + Write-Host "Failed: [$env:FAILED]" + Write-Host "Total: [$env:TOTAL]" + if ($env:OUTCOME -ne 'success') { + Write-Error 'Pester tests did not pass.' + exit 1 } - if ($failed) { exit 1 } diff --git a/action.yml b/action.yml index c2843ea..6d5c6bf 100644 --- a/action.yml +++ b/action.yml @@ -66,6 +66,7 @@ runs: shell: pwsh working-directory: ${{ inputs.WorkingDirectory }} env: + GH_TOKEN: ${{ github.token }} PSMODULE_RESOLVE_PSMODULEVERSION_INPUT_Settings: ${{ inputs.Settings }} PSMODULE_RESOLVE_PSMODULEVERSION_INPUT_Name: ${{ inputs.Name }} PSMODULE_RESOLVE_PSMODULEVERSION_INPUT_EventJson: ${{ inputs.EventJson }} diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index cb3eb8a..5a70e97 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -1,13 +1,13 @@ function Split-CommaSeparatedList { <# - .SYNOPSIS - Splits a comma-separated string into a trimmed, non-empty array. + .SYNOPSIS + Splits a comma-separated string into a trimmed, non-empty array. - .EXAMPLE - Split-CommaSeparatedList -Value 'Major, Minor, Patch' + .EXAMPLE + Split-CommaSeparatedList -Value 'Major, Minor, Patch' - Returns @('Major', 'Minor', 'Patch'). -#> + Returns @('Major', 'Minor', 'Patch'). + #> [CmdletBinding()] [OutputType([string[]])] param( @@ -21,19 +21,19 @@ function Read-ActionInput { <# - .SYNOPSIS - Reads and validates action inputs from environment variables. + .SYNOPSIS + Reads and validates action inputs from environment variables. - .DESCRIPTION - Reads the module name and settings JSON from GitHub Actions environment variables. - Falls back to the repository name when the module name input is not provided. + .DESCRIPTION + Reads the module name and settings JSON from GitHub Actions environment variables. + Falls back to the repository name when the module name input is not provided. - .OUTPUTS - PSCustomObject with Name and SettingsJson properties. + .OUTPUTS + PSCustomObject with Name and SettingsJson properties. - .EXAMPLE - $actionInput = Read-ActionInput -#> + .EXAMPLE + $actionInput = Read-ActionInput + #> [CmdletBinding()] [OutputType([PSCustomObject])] param() @@ -62,19 +62,19 @@ function Read-ActionInput { function Get-PublishConfiguration { <# - .SYNOPSIS - Parses the settings JSON into a publish configuration object. + .SYNOPSIS + Parses the settings JSON into a publish configuration object. - .DESCRIPTION - Extracts publish module settings including auto-patching flags, version prefix, - release type, and label classification arrays. + .DESCRIPTION + Extracts publish module settings including auto-patching flags, version prefix, + release type, and label classification arrays. - .OUTPUTS - PSCustomObject with publish configuration properties. + .OUTPUTS + PSCustomObject with publish configuration properties. - .EXAMPLE - $config = Get-PublishConfiguration -SettingsJson $actionInput.SettingsJson -#> + .EXAMPLE + $config = Get-PublishConfiguration -SettingsJson $actionInput.SettingsJson + #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'Parameter is used inside LogGroup script block.')] [CmdletBinding()] @@ -122,19 +122,19 @@ function Get-PublishConfiguration { function Get-GitHubPullRequest { <# - .SYNOPSIS - Reads and validates the GitHub pull request from the event payload. + .SYNOPSIS + Reads and validates the GitHub pull request from the event payload. - .DESCRIPTION - Loads the GitHub event from the input override or from the event path file, - then validates and extracts pull request data. + .DESCRIPTION + Loads the GitHub event from the input override or from the event path file, + then validates and extracts pull request data. - .OUTPUTS - PSCustomObject with HeadRef and Labels properties. + .OUTPUTS + PSCustomObject with HeadRef and Labels properties. - .EXAMPLE - $pullRequest = Get-GitHubPullRequest -#> + .EXAMPLE + $pullRequest = Get-GitHubPullRequest + #> [CmdletBinding()] [OutputType([PSCustomObject])] param() @@ -171,20 +171,20 @@ function Get-GitHubPullRequest { function Resolve-ReleaseDecision { <# - .SYNOPSIS - Determines whether to publish a release and what kind of version bump to apply. + .SYNOPSIS + Determines whether to publish a release and what kind of version bump to apply. - .DESCRIPTION - Evaluates the PR labels against the configured label categories and release type - to produce a complete release decision. + .DESCRIPTION + Evaluates the PR labels against the configured label categories and release type + to produce a complete release decision. - .OUTPUTS - PSCustomObject with ShouldPublish, CreateRelease, CreatePrerelease, MajorRelease, - MinorRelease, PatchRelease, HasVersionBump, and PrereleaseName properties. + .OUTPUTS + PSCustomObject with ShouldPublish, CreateRelease, CreatePrerelease, MajorRelease, + MinorRelease, PatchRelease, HasVersionBump, and PrereleaseName properties. - .EXAMPLE - $decision = Resolve-ReleaseDecision -Configuration $config -PullRequest $pullRequest -#> + .EXAMPLE + $decision = Resolve-ReleaseDecision -Configuration $config -PullRequest $pullRequest + #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'Parameter is used inside LogGroup script block.')] [CmdletBinding()] @@ -222,10 +222,14 @@ function Resolve-ReleaseDecision { $shouldPublish = $false } + # Defaults: always produce a prerelease patch version. $majorRelease = $false $minorRelease = $false - $patchRelease = $false - $hasVersionBump = $false + $patchRelease = $true + $hasVersionBump = $true + if (-not $shouldPublish) { + $createPrerelease = $true + } if ($shouldPublish) { $majorRelease = ($labels | Where-Object { $Configuration.MajorLabels -contains $_ }).Count -gt 0 @@ -238,6 +242,9 @@ function Resolve-ReleaseDecision { if (-not $hasVersionBump) { Write-Host 'No version bump label found and AutoPatching is disabled. No release will be created.' $shouldPublish = $false + $createPrerelease = $true + $patchRelease = $true + $hasVersionBump = $true } } @@ -268,15 +275,15 @@ function Resolve-ReleaseDecision { function Get-GitHubRelease { <# - .SYNOPSIS - Retrieves all releases from the current GitHub repository. + .SYNOPSIS + Retrieves all releases from the current GitHub repository. - .OUTPUTS - Array of release objects. + .OUTPUTS + Array of release objects. - .EXAMPLE - $releases = Get-GitHubReleases -#> + .EXAMPLE + $releases = Get-GitHubRelease + #> [CmdletBinding()] [OutputType([array])] param() @@ -300,15 +307,15 @@ function Get-GitHubRelease { function Get-LatestGitHubVersion { <# - .SYNOPSIS - Extracts the latest stable version from a GitHub releases list. + .SYNOPSIS + Extracts the latest stable version from a GitHub releases list. - .OUTPUTS - PSSemVer representing the latest GitHub release version. + .OUTPUTS + PSSemVer representing the latest GitHub release version. - .EXAMPLE - $ghVersion = Get-LatestGitHubVersion -Releases $releases -#> + .EXAMPLE + $ghVersion = Get-LatestGitHubVersion -Releases $releases + #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'Parameter is used inside LogGroup script block.')] [CmdletBinding()] @@ -337,19 +344,19 @@ function Get-LatestGitHubVersion { function Get-LatestPSGalleryVersion { <# - .SYNOPSIS - Finds the latest stable version of a module in the PowerShell Gallery. + .SYNOPSIS + Finds the latest stable version of a module in the PowerShell Gallery. - .DESCRIPTION - Queries the PowerShell Gallery for the latest published version of the module. - Retries up to five times with a ten-second delay between attempts. + .DESCRIPTION + Queries the PowerShell Gallery for the latest published version of the module. + Retries up to five times with a ten-second delay between attempts. - .OUTPUTS - PSSemVer representing the latest PSGallery version. + .OUTPUTS + PSSemVer representing the latest PSGallery version. - .EXAMPLE - $psGalleryVersion = Get-LatestPSGalleryVersion -ModuleName 'MyModule' -#> + .EXAMPLE + $psGalleryVersion = Get-LatestPSGalleryVersion -ModuleName 'MyModule' + #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'Parameter is used inside LogGroup script block.')] [CmdletBinding()] @@ -395,15 +402,15 @@ function Get-LatestPSGalleryVersion { function Get-LatestPublishedVersion { <# - .SYNOPSIS - Returns the highest version between GitHub and the PowerShell Gallery. + .SYNOPSIS + Returns the highest version between GitHub and the PowerShell Gallery. - .OUTPUTS - PSSemVer representing the highest known published version. + .OUTPUTS + PSSemVer representing the highest known published version. - .EXAMPLE - $latestVersion = Get-LatestPublishedVersion -GitHubVersion $ghVersion -PSGalleryVersion $psGalleryVersion -#> + .EXAMPLE + $latestVersion = Get-LatestPublishedVersion -GitHubVersion $ghVersion -PSGalleryVersion $psGalleryVersion + #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'Parameter is used inside LogGroup script block.')] [CmdletBinding()] @@ -429,20 +436,20 @@ function Get-LatestPublishedVersion { function Get-NextPrereleaseNumber { <# - .SYNOPSIS - Calculates the next incremental prerelease number across GitHub and PSGallery. + .SYNOPSIS + Calculates the next incremental prerelease number across GitHub and PSGallery. - .DESCRIPTION - Queries both GitHub releases and the PowerShell Gallery for existing prereleases - matching the base version and prerelease name, then returns the next number - zero-padded to three digits. + .DESCRIPTION + Queries both GitHub releases and the PowerShell Gallery for existing prereleases + matching the base version and prerelease name, then returns the next number + zero-padded to three digits. - .OUTPUTS - String. A zero-padded three-digit number (e.g. '001'). + .OUTPUTS + String. A zero-padded three-digit number (e.g. '001'). - .EXAMPLE - $number = Get-NextPrereleaseNumber -ModuleName 'MyModule' -BaseVersion '1.2.3' -PrereleaseName 'mybranch' -Releases $releases -#> + .EXAMPLE + $number = Get-NextPrereleaseNumber -ModuleName 'MyModule' -BaseVersion '1.2.3' -PrereleaseName 'mybranch' -Releases $releases + #> [CmdletBinding()] [OutputType([string])] param( @@ -502,20 +509,20 @@ function Get-NextPrereleaseNumber { function Get-NextModuleVersion { <# - .SYNOPSIS - Calculates the next module version based on the release decision. + .SYNOPSIS + Calculates the next module version based on the release decision. - .DESCRIPTION - Increments the current version according to the version bump type (major, minor, or patch), - then optionally appends a prerelease suffix with support for date-based and incremental numbering. + .DESCRIPTION + Increments the current version according to the version bump type (major, minor, or patch), + then optionally appends a prerelease suffix with support for date-based and incremental numbering. - .OUTPUTS - PSSemVer representing the resolved next version. + .OUTPUTS + PSSemVer representing the resolved next version. - .EXAMPLE - $newVersion = Get-NextModuleVersion -LatestVersion $latestVersion -Decision $decision ` - -Configuration $config -ModuleName 'MyModule' -Releases $releases -#> + .EXAMPLE + $newVersion = Get-NextModuleVersion -LatestVersion $latestVersion -Decision $decision ` + -Configuration $config -ModuleName 'MyModule' -Releases $releases + #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'Parameter is used inside LogGroup script block.')] [CmdletBinding()] @@ -569,7 +576,7 @@ function Get-NextModuleVersion { $newVersion.Prerelease += "$(Get-Date -Format $Configuration.DatePrereleaseFormat)" } - if ($Configuration.IncrementalPrerelease) { + if ($Configuration.IncrementalPrerelease -or -not $Decision.ShouldPublish) { $baseVersionString = "$($newVersion.Major).$($newVersion.Minor).$($newVersion.Patch)" $params = @{ ModuleName = $ModuleName @@ -588,12 +595,12 @@ function Get-NextModuleVersion { function Write-ActionOutput { <# - .SYNOPSIS - Emits the resolved version and release type as GitHub Actions step outputs. + .SYNOPSIS + Emits the resolved version and release type as GitHub Actions step outputs. - .EXAMPLE - Write-ActionOutput -Decision $decision -NewVersion $newVersion -#> + .EXAMPLE + Write-ActionOutput -Decision $decision -NewVersion $newVersion + #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'Parameter is used inside LogGroup script block.')] [CmdletBinding()] @@ -602,21 +609,15 @@ function Write-ActionOutput { [Parameter(Mandatory)] [PSCustomObject] $Decision, - # The resolved next version, or $null when no release will be created. - [Parameter()] + # The resolved next version. + [Parameter(Mandatory)] [object] $NewVersion ) LogGroup 'Emit outputs' { - $versionString = '' - $prereleaseString = '' - $fullVersionString = '' - - if ($NewVersion) { - $versionString = "$($NewVersion.Major).$($NewVersion.Minor).$($NewVersion.Patch)" - $prereleaseString = [string]$NewVersion.Prerelease - $fullVersionString = $NewVersion.ToString() - } + $versionString = "$($NewVersion.Major).$($NewVersion.Minor).$($NewVersion.Patch)" + $prereleaseString = [string]$NewVersion.Prerelease + $fullVersionString = $NewVersion.ToString() $resolvedReleaseType = if ($Decision.ShouldPublish) { if ($Decision.CreateRelease) { 'Release' } else { 'Prerelease' } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 73f6d36..b22dd6a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -11,22 +11,18 @@ $config = Get-PublishConfiguration -SettingsJson $actionInput.SettingsJson $pullRequest = Get-GitHubPullRequest $decision = Resolve-ReleaseDecision -Configuration $config -PullRequest $pullRequest -$newVersion = $null +$releases = Get-GitHubRelease +$ghVersion = Get-LatestGitHubVersion -Releases $releases +$psGalleryVersion = Get-LatestPSGalleryVersion -ModuleName $actionInput.Name +$latestVersion = Get-LatestPublishedVersion -GitHubVersion $ghVersion -PSGalleryVersion $psGalleryVersion -if ($decision.ShouldPublish) { - $releases = Get-GitHubRelease - $ghVersion = Get-LatestGitHubVersion -Releases $releases - $psGalleryVersion = Get-LatestPSGalleryVersion -ModuleName $actionInput.Name - $latestVersion = Get-LatestPublishedVersion -GitHubVersion $ghVersion -PSGalleryVersion $psGalleryVersion - - $params = @{ - LatestVersion = $latestVersion - Decision = $decision - Configuration = $config - ModuleName = $actionInput.Name - Releases = $releases - } - $newVersion = Get-NextModuleVersion @params +$params = @{ + LatestVersion = $latestVersion + Decision = $decision + Configuration = $config + ModuleName = $actionInput.Name + Releases = $releases } +$newVersion = Get-NextModuleVersion @params Write-ActionOutput -Decision $decision -NewVersion $newVersion diff --git a/tests/Helpers.Tests.Data.psd1 b/tests/Helpers.Tests.Data.psd1 new file mode 100644 index 0000000..0e1e2d5 --- /dev/null +++ b/tests/Helpers.Tests.Data.psd1 @@ -0,0 +1,446 @@ +@{ + ReleaseDecision = @( + @{ + Name = 'Patch label with Release type' + ReleaseType = 'Release' + AutoPatching = $false + HeadRef = 'feat/test-patch' + Labels = @('patch') + Expected = @{ + ShouldPublish = $true + CreateRelease = $true + CreatePrerelease = $false + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'feattestpatch' + } + } + @{ + Name = 'Minor label with Release type' + ReleaseType = 'Release' + AutoPatching = $false + HeadRef = 'feat/test-minor' + Labels = @('minor') + Expected = @{ + ShouldPublish = $true + CreateRelease = $true + CreatePrerelease = $false + MajorRelease = $false + MinorRelease = $true + PatchRelease = $false + HasVersionBump = $true + PrereleaseName = 'feattestminor' + } + } + @{ + Name = 'Major label with Release type' + ReleaseType = 'Release' + AutoPatching = $false + HeadRef = 'feat/test-major' + Labels = @('major') + Expected = @{ + ShouldPublish = $true + CreateRelease = $true + CreatePrerelease = $false + MajorRelease = $true + MinorRelease = $false + PatchRelease = $false + HasVersionBump = $true + PrereleaseName = 'feattestmajor' + } + } + @{ + Name = 'AutoPatching with no label' + ReleaseType = 'Release' + AutoPatching = $true + HeadRef = 'feat/test-autopatch' + Labels = @() + Expected = @{ + ShouldPublish = $true + CreateRelease = $true + CreatePrerelease = $false + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'feattestautopatch' + } + } + @{ + Name = 'Ignore label suppresses release' + ReleaseType = 'Release' + AutoPatching = $false + HeadRef = 'feat/test-ignore' + Labels = @('patch', 'skip-release') + Expected = @{ + ShouldPublish = $false + CreateRelease = $true + CreatePrerelease = $true + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'feattestignore' + } + } + @{ + Name = 'ReleaseType None produces prerelease' + ReleaseType = 'None' + AutoPatching = $false + HeadRef = 'feat/test-none' + Labels = @('patch') + Expected = @{ + ShouldPublish = $false + CreateRelease = $false + CreatePrerelease = $true + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'feattestnone' + } + } + @{ + Name = 'ReleaseType Prerelease with minor label' + ReleaseType = 'Prerelease' + AutoPatching = $false + HeadRef = 'feat/add-prerelease-support' + Labels = @('minor') + Expected = @{ + ShouldPublish = $true + CreateRelease = $false + CreatePrerelease = $true + MajorRelease = $false + MinorRelease = $true + PatchRelease = $false + HasVersionBump = $true + PrereleaseName = 'feataddprereleasesupport' + } + } + @{ + Name = 'No bump label and no AutoPatching falls back to prerelease' + ReleaseType = 'Release' + AutoPatching = $false + HeadRef = 'feat/no-label' + Labels = @() + Expected = @{ + ShouldPublish = $false + CreateRelease = $true + CreatePrerelease = $true + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'featnolabel' + } + } + ) + + NextModuleVersion = @( + @{ + Name = 'Patch bump - Release' + LatestVersion = '1.0.1' + VersionPrefix = 'v' + IncrementalPrerelease = $false + DatePrereleaseFormat = '' + ExpectedVersion = '1.0.2' + ExpectedPrerelease = '' + ExpectedPrefix = 'v' + Decision = @{ + ShouldPublish = $true + CreateRelease = $true + CreatePrerelease = $false + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'feattestpatch' + } + } + @{ + Name = 'Minor bump - Release' + LatestVersion = '1.0.1' + VersionPrefix = 'v' + IncrementalPrerelease = $false + DatePrereleaseFormat = '' + ExpectedVersion = '1.1.0' + ExpectedPrerelease = '' + ExpectedPrefix = 'v' + Decision = @{ + ShouldPublish = $true + CreateRelease = $true + CreatePrerelease = $false + MajorRelease = $false + MinorRelease = $true + PatchRelease = $false + HasVersionBump = $true + PrereleaseName = 'feattestminor' + } + } + @{ + Name = 'Major bump - Release' + LatestVersion = '1.2.3' + VersionPrefix = 'v' + IncrementalPrerelease = $false + DatePrereleaseFormat = '' + ExpectedVersion = '2.0.0' + ExpectedPrerelease = '' + ExpectedPrefix = 'v' + Decision = @{ + ShouldPublish = $true + CreateRelease = $true + CreatePrerelease = $false + MajorRelease = $true + MinorRelease = $false + PatchRelease = $false + HasVersionBump = $true + PrereleaseName = 'feattestmajor' + } + } + @{ + Name = 'ReleaseType None - prerelease with incremental counter' + LatestVersion = '1.0.1' + VersionPrefix = 'v' + IncrementalPrerelease = $false + DatePrereleaseFormat = '' + ExpectedVersion = '1.0.2' + ExpectedPrerelease = 'feattestnone001' + ExpectedPrefix = 'v' + Decision = @{ + ShouldPublish = $false + CreateRelease = $false + CreatePrerelease = $true + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'feattestnone' + } + } + @{ + Name = 'Prerelease type with IncrementalPrerelease' + LatestVersion = '1.0.1' + VersionPrefix = 'v' + IncrementalPrerelease = $true + DatePrereleaseFormat = '' + ExpectedVersion = '1.1.0' + ExpectedPrerelease = 'feataddprereleasesupport001' + ExpectedPrefix = 'v' + Decision = @{ + ShouldPublish = $true + CreateRelease = $false + CreatePrerelease = $true + MajorRelease = $false + MinorRelease = $true + PatchRelease = $false + HasVersionBump = $true + PrereleaseName = 'feataddprereleasesupport' + } + } + @{ + Name = 'Ignore label falls back to prerelease with counter' + LatestVersion = '1.0.1' + VersionPrefix = 'v' + IncrementalPrerelease = $false + DatePrereleaseFormat = '' + ExpectedVersion = '1.0.2' + ExpectedPrerelease = 'feattestignore001' + ExpectedPrefix = 'v' + Decision = @{ + ShouldPublish = $false + CreateRelease = $true + CreatePrerelease = $true + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'feattestignore' + } + } + @{ + Name = 'No version prefix' + LatestVersion = '2.0.0' + VersionPrefix = '' + IncrementalPrerelease = $false + DatePrereleaseFormat = '' + ExpectedVersion = '2.0.1' + ExpectedPrerelease = '' + ExpectedPrefix = '' + Decision = @{ + ShouldPublish = $true + CreateRelease = $true + CreatePrerelease = $false + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'main' + } + } + @{ + Name = 'AutoPatch - Release with no label' + LatestVersion = '1.0.1' + VersionPrefix = 'v' + IncrementalPrerelease = $false + DatePrereleaseFormat = '' + ExpectedVersion = '1.0.2' + ExpectedPrerelease = '' + ExpectedPrefix = 'v' + Decision = @{ + ShouldPublish = $true + CreateRelease = $true + CreatePrerelease = $false + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'feattestautopatch' + } + } + @{ + Name = 'Prerelease without IncrementalPrerelease but ShouldPublish true' + LatestVersion = '1.0.0' + VersionPrefix = 'v' + IncrementalPrerelease = $false + DatePrereleaseFormat = '' + ExpectedVersion = '1.0.1' + ExpectedPrerelease = 'dev' + ExpectedPrefix = 'v' + Decision = @{ + ShouldPublish = $true + CreateRelease = $false + CreatePrerelease = $true + MajorRelease = $false + MinorRelease = $false + PatchRelease = $true + HasVersionBump = $true + PrereleaseName = 'dev' + } + } + ) + + EndToEnd = @( + @{ + Name = 'Patch bump produces release version' + LatestVersion = '1.0.1' + ReleaseType = 'Release' + AutoPatching = $false + IncrementalPrerelease = $false + VersionPrefix = 'v' + HeadRef = 'feat/test-patch' + Labels = @('patch') + ExpectedShouldPublish = $true + ExpectedReleaseType = 'Release' + ExpectedVersion = '1.0.2' + ExpectedPrerelease = '' + ExpectedFullVersion = 'v1.0.2' + } + @{ + Name = 'Minor bump produces release version' + LatestVersion = '1.0.1' + ReleaseType = 'Release' + AutoPatching = $false + IncrementalPrerelease = $false + VersionPrefix = 'v' + HeadRef = 'feat/test-minor' + Labels = @('minor') + ExpectedShouldPublish = $true + ExpectedReleaseType = 'Release' + ExpectedVersion = '1.1.0' + ExpectedPrerelease = '' + ExpectedFullVersion = 'v1.1.0' + } + @{ + Name = 'Major bump produces release version' + LatestVersion = '1.0.1' + ReleaseType = 'Release' + AutoPatching = $false + IncrementalPrerelease = $false + VersionPrefix = 'v' + HeadRef = 'feat/test-major' + Labels = @('major') + ExpectedShouldPublish = $true + ExpectedReleaseType = 'Release' + ExpectedVersion = '2.0.0' + ExpectedPrerelease = '' + ExpectedFullVersion = 'v2.0.0' + } + @{ + Name = 'Auto-patch with no label produces release version' + LatestVersion = '1.0.1' + ReleaseType = 'Release' + AutoPatching = $true + IncrementalPrerelease = $false + VersionPrefix = 'v' + HeadRef = 'feat/test-autopatch' + Labels = @() + ExpectedShouldPublish = $true + ExpectedReleaseType = 'Release' + ExpectedVersion = '1.0.2' + ExpectedPrerelease = '' + ExpectedFullVersion = 'v1.0.2' + } + @{ + Name = 'Ignore label suppresses release, produces prerelease' + LatestVersion = '1.0.1' + ReleaseType = 'Release' + AutoPatching = $false + IncrementalPrerelease = $false + VersionPrefix = 'v' + HeadRef = 'feat/test-ignore' + Labels = @('patch', 'skip-release') + ExpectedShouldPublish = $false + ExpectedReleaseType = 'None' + ExpectedVersion = '1.0.2' + ExpectedPrerelease = 'feattestignore001' + ExpectedFullVersion = 'v1.0.2-feattestignore001' + } + @{ + Name = 'ReleaseType None produces prerelease with counter' + LatestVersion = '1.0.1' + ReleaseType = 'None' + AutoPatching = $false + IncrementalPrerelease = $false + VersionPrefix = 'v' + HeadRef = 'feat/test-none' + Labels = @('patch') + ExpectedShouldPublish = $false + ExpectedReleaseType = 'None' + ExpectedVersion = '1.0.2' + ExpectedPrerelease = 'feattestnone001' + ExpectedFullVersion = 'v1.0.2-feattestnone001' + } + @{ + Name = 'Prerelease type with incremental counter' + LatestVersion = '1.0.1' + ReleaseType = 'Prerelease' + AutoPatching = $false + IncrementalPrerelease = $true + VersionPrefix = 'v' + HeadRef = 'feat/add-prerelease-support' + Labels = @('minor') + ExpectedShouldPublish = $true + ExpectedReleaseType = 'Prerelease' + ExpectedVersion = '1.1.0' + ExpectedPrerelease = 'feataddprereleasesupport001' + ExpectedFullVersion = 'v1.1.0-feataddprereleasesupport001' + } + @{ + Name = 'No label and no AutoPatching falls back to prerelease' + LatestVersion = '1.0.1' + ReleaseType = 'Release' + AutoPatching = $false + IncrementalPrerelease = $false + VersionPrefix = 'v' + HeadRef = 'feat/no-label' + Labels = @() + ExpectedShouldPublish = $false + ExpectedReleaseType = 'None' + ExpectedVersion = '1.0.2' + ExpectedPrerelease = 'featnolabel001' + ExpectedFullVersion = 'v1.0.2-featnolabel001' + } + ) +} diff --git a/tests/Helpers.Tests.ps1 b/tests/Helpers.Tests.ps1 new file mode 100644 index 0000000..364c521 --- /dev/null +++ b/tests/Helpers.Tests.ps1 @@ -0,0 +1,190 @@ +#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } + +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', + Justification = 'Variables are used across Pester BeforeAll/It blocks.')] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', + Justification = 'Parameters in LogGroup mock are required by the caller signature.')] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSProvideCommentHelp', '', + Justification = 'LogGroup is a test helper mock, not a public function.')] +param() + +# Load test data at script scope so it is available during Pester discovery (-ForEach) +$TestData = Import-PowerShellDataFile -Path "$PSScriptRoot/Helpers.Tests.Data.psd1" + +BeforeAll { + # Install PSSemVer for version handling + if (-not (Get-Module -ListAvailable -Name PSSemVer)) { + Install-PSResource -Name PSSemVer -Repository PSGallery -TrustRepository -Scope CurrentUser + } + Import-Module -Name PSSemVer -Force + + # Mock LogGroup so module functions execute their blocks without console decoration + function LogGroup { + param([string]$Name, [scriptblock]$ScriptBlock) + & $ScriptBlock + } + + # Import the module under test + Import-Module -Name "$PSScriptRoot/../scripts/Helpers.psm1" -Force +} + +Describe 'Resolve-ReleaseDecision' { + BeforeAll { + $baseConfig = [PSCustomObject]@{ + AutoPatching = $false + IncrementalPrerelease = $false + DatePrereleaseFormat = '' + VersionPrefix = 'v' + ReleaseType = 'Release' + IgnoreLabels = @('skip-release') + MajorLabels = @('major') + MinorLabels = @('minor') + PatchLabels = @('patch') + } + } + + Context '' -ForEach $TestData.ReleaseDecision { + BeforeAll { + $config = [PSCustomObject]@{ + AutoPatching = $AutoPatching + IncrementalPrerelease = $baseConfig.IncrementalPrerelease + DatePrereleaseFormat = $baseConfig.DatePrereleaseFormat + VersionPrefix = $baseConfig.VersionPrefix + ReleaseType = $ReleaseType + IgnoreLabels = $baseConfig.IgnoreLabels + MajorLabels = $baseConfig.MajorLabels + MinorLabels = $baseConfig.MinorLabels + PatchLabels = $baseConfig.PatchLabels + } + $pullRequest = [PSCustomObject]@{ + HeadRef = $HeadRef + Labels = $Labels + } + $result = Resolve-ReleaseDecision -Configuration $config -PullRequest $pullRequest + } + + It 'ShouldPublish is ' { + $result.ShouldPublish | Should -Be $Expected.ShouldPublish + } + It 'CreateRelease is ' { + $result.CreateRelease | Should -Be $Expected.CreateRelease + } + It 'CreatePrerelease is ' { + $result.CreatePrerelease | Should -Be $Expected.CreatePrerelease + } + It 'MajorRelease is ' { + $result.MajorRelease | Should -Be $Expected.MajorRelease + } + It 'MinorRelease is ' { + $result.MinorRelease | Should -Be $Expected.MinorRelease + } + It 'PatchRelease is ' { + $result.PatchRelease | Should -Be $Expected.PatchRelease + } + It 'HasVersionBump is ' { + $result.HasVersionBump | Should -Be $Expected.HasVersionBump + } + It 'PrereleaseName is ' { + $result.PrereleaseName | Should -Be $Expected.PrereleaseName + } + } +} + +Describe 'Get-NextModuleVersion' { + BeforeAll { + Mock -CommandName Find-PSResource -ModuleName Helpers -MockWith { @() } + $emptyReleases = @([PSCustomObject]@{ tagName = 'v0.0.0'; isLatest = $false; isPrerelease = $false }) + } + + Context '' -ForEach $TestData.NextModuleVersion { + BeforeAll { + $config = [PSCustomObject]@{ + AutoPatching = $false + IncrementalPrerelease = $IncrementalPrerelease + DatePrereleaseFormat = $DatePrereleaseFormat + VersionPrefix = $VersionPrefix + ReleaseType = 'Release' + IgnoreLabels = @() + MajorLabels = @('major') + MinorLabels = @('minor') + PatchLabels = @('patch') + } + $decisionObj = [PSCustomObject]$Decision + $latestVer = New-PSSemVer -Version $LatestVersion + $result = Get-NextModuleVersion -LatestVersion $latestVer -Decision $decisionObj ` + -Configuration $config -ModuleName 'TestModule' -Releases $emptyReleases + } + + It 'Version is ' { + "$($result.Major).$($result.Minor).$($result.Patch)" | Should -Be $ExpectedVersion + } + It 'Prerelease is ' { + if ([string]::IsNullOrEmpty($ExpectedPrerelease)) { + $result.Prerelease | Should -BeNullOrEmpty + } else { + $result.Prerelease | Should -Be $ExpectedPrerelease + } + } + It 'Prefix is ' { + $result.Prefix | Should -Be $ExpectedPrefix + } + } +} + +Describe 'End-to-end: Resolve-ReleaseDecision + Get-NextModuleVersion' { + BeforeAll { + Mock -CommandName Find-PSResource -ModuleName Helpers -MockWith { @() } + $emptyReleases = @([PSCustomObject]@{ tagName = 'v0.0.0'; isLatest = $false; isPrerelease = $false }) + } + + Context '' -ForEach $TestData.EndToEnd { + BeforeAll { + $config = [PSCustomObject]@{ + AutoPatching = $AutoPatching + IncrementalPrerelease = $IncrementalPrerelease + DatePrereleaseFormat = '' + VersionPrefix = $VersionPrefix + ReleaseType = $ReleaseType + IgnoreLabels = @('skip-release') + MajorLabels = @('major') + MinorLabels = @('minor') + PatchLabels = @('patch') + } + $pullRequest = [PSCustomObject]@{ + HeadRef = $HeadRef + Labels = $Labels + } + $decision = Resolve-ReleaseDecision -Configuration $config -PullRequest $pullRequest + $latestVer = New-PSSemVer -Version $LatestVersion + $newVersion = Get-NextModuleVersion -LatestVersion $latestVer -Decision $decision ` + -Configuration $config -ModuleName 'TestModule' -Releases $emptyReleases + + # Derive resolved release type the same way Write-ActionOutput does + $resolvedReleaseType = if ($decision.ShouldPublish) { + if ($decision.CreateRelease) { 'Release' } else { 'Prerelease' } + } else { + 'None' + } + } + + It 'ShouldPublish is ' { + $decision.ShouldPublish | Should -Be $ExpectedShouldPublish + } + It 'ReleaseType is ' { + $resolvedReleaseType | Should -Be $ExpectedReleaseType + } + It 'Version is ' { + "$($newVersion.Major).$($newVersion.Minor).$($newVersion.Patch)" | Should -Be $ExpectedVersion + } + It 'Prerelease is ' { + if ([string]::IsNullOrEmpty($ExpectedPrerelease)) { + $newVersion.Prerelease | Should -BeNullOrEmpty + } else { + $newVersion.Prerelease | Should -Be $ExpectedPrerelease + } + } + It 'FullVersion is ' { + $newVersion.ToString() | Should -Be $ExpectedFullVersion + } + } +} diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 43816d3..0000000 --- a/tests/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Placeholder for tests - -Location for tests of the action.