Skip to content

Commit 9acddbd

Browse files
🪲 [Fix]: Configured report paths are honored (#42)
Configured `TestResult_OutputPath` and `CodeCoverage_OutputPath` values now reach `Invoke-Pester` unchanged, so enabled reports are written to the locations selected by the caller. Callers that leave either input empty retain the existing `Invoke-Pester` fallback path relative to `WorkingDirectory`. ## Fixed: Configured report paths The action now uses `Invoke-Pester` v5.1.1, which honors configured report output paths and keeps its action-private temporary state outside the caller worktree. Set either input independently when that report needs a custom destination; the other report continues to use its configured or default behavior. ```yaml with: TestResult_OutputPath: artifacts/TestResult/results.xml CodeCoverage_OutputPath: artifacts/CodeCoverage/coverage.xml ``` ## Adopting this release 1. Select the release containing this fix in the `PSModule/Invoke-ScriptAnalyzer` workflow reference. 2. Existing callers that leave both output-path inputs empty need no configuration, code, or invocation changes; reports continue to use the established `Invoke-Pester` defaults below `WorkingDirectory`. 3. Existing callers that already set `TestResult_OutputPath` or `CodeCoverage_OutputPath` need no configuration change; the configured location is now honored. Set either input when a report should use a new custom destination. ## Release impact | Field | Value | | --- | --- | | Effective decision | `release:patch`, selected for a backward-compatible report-path correction. | | Semantic effect | Patch, stable; configured output paths now work as documented and omitted inputs retain their prior behavior. | | Release/base coordinates | Final coordinates are resolved by the release process at publication. The published record supplies the target version, tag, immutable source, version-computation base, and release/source baseline. | --- <details> <summary>Technical details</summary> ### Consumer change record | Identifier / surface | Before | After | Applicability / prerequisites | Consumer action | Verification | | --- | --- | --- | --- | --- | --- | | REPORT-PATH-OVERRIDE / `TestResult_OutputPath`, `CodeCoverage_OutputPath` | `Invoke-Pester` v5.1.0 overwrote values forwarded by this action, so configured destinations were not used. | `Invoke-Pester` v5.1.1 retains each configured path. Empty inputs retain `TestResult/PSScriptAnalyzer-TestResult-Report.xml` and `CodeCoverage/PSScriptAnalyzer-CodeCoverage-Report.xml` below `WorkingDirectory`. | Callers that enable test-result or code-coverage reports. | Select this release. No change is needed for existing configured paths or omitted inputs; optionally set either input to choose a destination. | The action-test suite verifies explicit generic `artifacts/...` paths, XML and JSON report creation, absence of legacy root report and `.temp` directories for the explicit case, and preserved fallback paths when inputs are omitted. | ### Template baseline Not applicable. This composite action does not consume an integration template. Downstream framework adoption is tracked separately in PSModule/Process-PSModule#541. ### Maintainer evidence - `action.yml` pins the published `Invoke-Pester` v5.1.1 fix to immutable commit `c5494aba3c07d7bfd81bdbbc9f301e8fa4a729fb`. - The focused action-test jobs cover both explicit overrides and omitted-input fallback behavior; `tests/Assert-ReportPaths.ps1` verifies generated XML and JSON reports and expected directory isolation. - `README.md` documents the preserved fallback behavior and generic explicit override example. - Implementation plan progress: complete. The report-path regression was made red against v5.1.0 before the dependency was updated, then passed with v5.1.1. - Standards and framework alignment: reviewed GitHub Actions dependency pinning, action input contracts, PowerShell test conventions, and Markdown documentation; aligned. - Issue convergence sweep: the completed diff addresses the configured report-path regression only; no additional issues were identified as fully satisfied. | Changed surface | Standards checked | Framework docs checked | Result | | --- | --- | --- | --- | | `action.yml` | Dependencies, GitHub Actions | Composite action input contract; Invoke-Pester v5.1.1 release notes | Aligned | | `.github/workflows/Action-Test.yml`, `tests/Assert-ReportPaths.ps1` | Testing, GitHub Actions, PowerShell | Invoke-Pester report-path and temporary-state contract | Aligned | | `README.md` | Documentation, Markdown | GitHub Action input documentation | Aligned | </details> <details> <summary>Relevant issues (or links)</summary> ### Related work - Depends on PSModule/Invoke-Pester#78 - Followed by PSModule/Process-PSModule#541 - Followed by PSModule/Invoke-Pester#85 </details>
1 parent 4d633e4 commit 9acddbd

5 files changed

Lines changed: 167 additions & 1 deletion

File tree

.github/workflows/Action-Test.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,70 @@ jobs:
121121
Write-Host "Outcome: ${{ steps.action-test.outcome }}"
122122
Write-Host "Conclusion: ${{ steps.action-test.conclusion }}"
123123
124+
ActionTestReportPaths:
125+
name: Action-Test - [Report Paths]
126+
runs-on: ubuntu-latest
127+
steps:
128+
- name: Checkout repo
129+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
130+
with:
131+
persist-credentials: false
132+
133+
- name: Action-Test
134+
uses: ./
135+
id: action-test
136+
with:
137+
Path: src
138+
WorkingDirectory: tests/srcTestRepo
139+
TestResult_Enabled: true
140+
TestResult_OutputFormat: NUnitXml
141+
TestResult_OutputPath: artifacts/TestResult/results.xml
142+
CodeCoverage_Enabled: true
143+
CodeCoverage_OutputFormat: JaCoCo
144+
CodeCoverage_OutputPath: artifacts/CodeCoverage/coverage.xml
145+
CodeCoverage_Path: ../../src/tests/PSScriptAnalyzer/PSScriptAnalyzer.Tests.ps1
146+
147+
- name: Assert report paths
148+
shell: pwsh
149+
run: |
150+
tests/Assert-ReportPaths.ps1 `
151+
-WorkingDirectory tests/srcTestRepo `
152+
-TestResultPath artifacts/TestResult/results.xml `
153+
-CodeCoveragePath artifacts/CodeCoverage/coverage.xml `
154+
-ArtifactDirectory artifacts `
155+
-UnexpectedDirectory TestResult,CodeCoverage,.temp
156+
157+
ActionTestInvokePesterDefaultReportPaths:
158+
name: Action-Test - [Invoke-Pester Default Report Paths]
159+
runs-on: ubuntu-latest
160+
steps:
161+
- name: Checkout repo
162+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
163+
with:
164+
persist-credentials: false
165+
166+
- name: Action-Test
167+
uses: ./
168+
id: action-test
169+
with:
170+
Path: src
171+
WorkingDirectory: tests/srcTestRepo
172+
TestResult_Enabled: true
173+
TestResult_OutputFormat: NUnitXml
174+
CodeCoverage_Enabled: true
175+
CodeCoverage_OutputFormat: JaCoCo
176+
CodeCoverage_Path: ../../src/tests/PSScriptAnalyzer/PSScriptAnalyzer.Tests.ps1
177+
178+
- name: Assert report paths
179+
shell: pwsh
180+
run: |
181+
tests/Assert-ReportPaths.ps1 `
182+
-WorkingDirectory tests/srcTestRepo `
183+
-TestResultPath TestResult/PSScriptAnalyzer-TestResult-Report.xml `
184+
-CodeCoveragePath CodeCoverage/PSScriptAnalyzer-CodeCoverage-Report.xml `
185+
-ArtifactDirectory . `
186+
-UnexpectedDirectory .temp
187+
124188
ActionTestOutputs:
125189
name: Action-Test - [outputs]
126190
runs-on: ubuntu-latest
@@ -153,6 +217,8 @@ jobs:
153217
- ActionTestSrcCustom
154218
- ActionTestSrcWithManifest
155219
- ActionTestSrcWithManifestDefault
220+
- ActionTestReportPaths
221+
- ActionTestInvokePesterDefaultReportPaths
156222
- ActionTestOutputs
157223
if: always()
158224
runs-on: ubuntu-latest
@@ -165,6 +231,8 @@ jobs:
165231
WithManifestConclusion: ${{ needs.ActionTestSrcWithManifest.outputs.Conclusion }}
166232
WithManifestDefaultOutcome: ${{ needs.ActionTestSrcWithManifestDefault.outputs.Outcome }}
167233
WithManifestDefaultConclusion: ${{ needs.ActionTestSrcWithManifestDefault.outputs.Conclusion }}
234+
ReportPathsResult: ${{ needs.ActionTestReportPaths.result }}
235+
InvokePesterDefaultReportPathsResult: ${{ needs.ActionTestInvokePesterDefaultReportPaths.result }}
168236
OutputsOutcome: ${{ needs.ActionTestOutputs.outputs.Outcome }}
169237
OutputsConclusion: ${{ needs.ActionTestOutputs.outputs.Conclusion }}
170238
steps:

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,21 @@ customize rule selection, severity filtering, and custom rule inclusion.
6868
| `TestDrive_Enabled` | Enable TestDrive. | false | |
6969
| `TestRegistry_Enabled` | Enable TestRegistry. | false | |
7070

71+
When a report output path is empty, `Invoke-Pester` uses its default location
72+
relative to `WorkingDirectory`:
73+
74+
```text
75+
TestResult/PSScriptAnalyzer-TestResult-Report.xml
76+
CodeCoverage/PSScriptAnalyzer-CodeCoverage-Report.xml
77+
```
78+
79+
Set either input to override only that report's location:
80+
81+
```text
82+
TestResult_OutputPath: artifacts/TestResult/results.xml
83+
CodeCoverage_OutputPath: artifacts/CodeCoverage/coverage.xml
84+
```
85+
7186
## Outputs
7287

7388
The action provides the following outputs:

action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ runs:
282282
Script: ${{ github.action_path }}/src/main.ps1
283283

284284
- name: Invoke-Pester
285-
uses: PSModule/Invoke-Pester@4ff33199141fdf22568990b6107fe3148ae93a1c # v5.1.0
285+
uses: PSModule/Invoke-Pester@c5494aba3c07d7bfd81bdbbc9f301e8fa4a729fb # v5.1.1
286286
id: test
287287
env:
288288
SettingsFilePath: ${{ fromJson(steps.paths.outputs.result).SettingsFilePath }}

tests/Assert-ReportPaths.ps1

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
[CmdletBinding()]
2+
param(
3+
[Parameter(Mandatory)]
4+
[string] $WorkingDirectory,
5+
6+
[Parameter(Mandatory)]
7+
[string] $TestResultPath,
8+
9+
[Parameter(Mandatory)]
10+
[string] $CodeCoveragePath,
11+
12+
[Parameter(Mandatory)]
13+
[string] $ArtifactDirectory,
14+
15+
[string[]] $UnexpectedDirectory = @()
16+
)
17+
18+
function Assert-ReportPath {
19+
<#
20+
.SYNOPSIS
21+
Confirms that an action report is generated in the fixture artifact directory.
22+
#>
23+
[CmdletBinding()]
24+
param(
25+
[Parameter(Mandatory)]
26+
[string] $Path,
27+
28+
[Parameter(Mandatory)]
29+
[string] $ReportName,
30+
31+
[Parameter(Mandatory)]
32+
[string] $ArtifactDirectory
33+
)
34+
35+
$resolvedPath = [System.IO.Path]::GetFullPath($Path)
36+
$resolvedArtifactDirectory = [System.IO.Path]::GetFullPath($ArtifactDirectory).TrimEnd(
37+
[System.IO.Path]::DirectorySeparatorChar,
38+
[System.IO.Path]::AltDirectorySeparatorChar
39+
) + [System.IO.Path]::DirectorySeparatorChar
40+
41+
if (-not $resolvedPath.StartsWith($resolvedArtifactDirectory, [System.StringComparison]::OrdinalIgnoreCase)) {
42+
throw "Expected $ReportName report beneath [$resolvedArtifactDirectory], but found [$resolvedPath]."
43+
}
44+
45+
foreach ($reportPath in @($resolvedPath, [System.IO.Path]::ChangeExtension($resolvedPath, '.json'))) {
46+
if (-not (Test-Path -Path $reportPath -PathType Leaf)) {
47+
throw "Expected $ReportName report at [$reportPath]."
48+
}
49+
}
50+
51+
try {
52+
$null = [xml](Get-Content -Path $resolvedPath -Raw)
53+
} catch {
54+
throw "Expected an XML $ReportName report at [$resolvedPath]."
55+
}
56+
}
57+
58+
$resolvedWorkingDirectory = [System.IO.Path]::GetFullPath($WorkingDirectory)
59+
$artifactDirectory = Join-Path -Path $resolvedWorkingDirectory -ChildPath $ArtifactDirectory
60+
61+
Assert-ReportPath -Path (Join-Path -Path $resolvedWorkingDirectory -ChildPath $TestResultPath) `
62+
-ReportName 'test result' `
63+
-ArtifactDirectory $artifactDirectory
64+
Assert-ReportPath -Path (Join-Path -Path $resolvedWorkingDirectory -ChildPath $CodeCoveragePath) `
65+
-ReportName 'code coverage' `
66+
-ArtifactDirectory $artifactDirectory
67+
68+
foreach ($unexpectedDirectory in $UnexpectedDirectory) {
69+
$unexpectedPath = Join-Path -Path $resolvedWorkingDirectory -ChildPath $unexpectedDirectory
70+
if (Test-Path -Path $unexpectedPath) {
71+
throw "Did not expect generated action state at [$unexpectedPath]."
72+
}
73+
}

tests/Get-AggregatedStatus.ps1

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ $jobs = @(
5151
Outcome = @{ Actual = $env:WithManifestDefaultOutcome; Expected = 'failure' }
5252
Conclusion = @{ Actual = $env:WithManifestDefaultConclusion; Expected = 'success' }
5353
}
54+
@{
55+
Name = 'Action-Test - [Report Paths]'
56+
Outcome = @{ Actual = $env:ReportPathsResult; Expected = 'success' }
57+
Conclusion = @{ Actual = $env:ReportPathsResult; Expected = 'success' }
58+
}
59+
@{
60+
Name = 'Action-Test - [Invoke-Pester Default Report Paths]'
61+
Outcome = @{ Actual = $env:InvokePesterDefaultReportPathsResult; Expected = 'success' }
62+
Conclusion = @{ Actual = $env:InvokePesterDefaultReportPathsResult; Expected = 'success' }
63+
}
5464
@{
5565
Name = 'Action-Test - [outputs]'
5666
Outcome = @{ Actual = $env:OutputsOutcome; Expected = 'success' }

0 commit comments

Comments
 (0)