Skip to content

Commit c3c335a

Browse files
Extract shared TestData exposure helper
1 parent cdfd9ae commit c3c335a

6 files changed

Lines changed: 120 additions & 319 deletions

File tree

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
if ([string]::IsNullOrWhiteSpace($env:PSMODULE_TEST_DATA)) {
2+
Write-Output 'No test data was provided by the calling workflow.'
3+
return
4+
}
5+
try {
6+
$data = $env:PSMODULE_TEST_DATA | ConvertFrom-Json -ErrorAction Stop
7+
} catch {
8+
throw "The 'TestData' secret must be valid JSON with 'secrets' and/or 'variables' maps."
9+
}
10+
if ($null -eq $data -or $data -isnot [pscustomobject]) {
11+
throw "The 'TestData' secret must be a JSON object with 'secrets' and/or 'variables' maps."
12+
}
13+
$allowedTopLevelKeys = @('secrets', 'variables')
14+
foreach ($propertyName in $data.PSObject.Properties.Name) {
15+
if ($allowedTopLevelKeys -notcontains $propertyName) {
16+
throw "The 'TestData' secret only supports 'secrets' and 'variables' maps."
17+
}
18+
}
19+
$reservedNames = @('CI', 'HOME', 'PATH', 'PWD', 'SHELL', 'PSMODULE_TEST_DATA')
20+
$reservedPrefixes = @('GITHUB_', 'RUNNER_', 'ACTIONS_')
21+
function Assert-EnvironmentName {
22+
<#
23+
.SYNOPSIS
24+
Validates that a TestData key can safely be written to GITHUB_ENV.
25+
#>
26+
param([string] $Name)
27+
if ($Name -notmatch '^[A-Za-z_][A-Za-z0-9_]*$') {
28+
throw 'TestData keys must be valid environment variable names.'
29+
}
30+
$normalized = $Name.ToUpperInvariant()
31+
if ($reservedNames -contains $normalized) {
32+
throw 'TestData keys must not override reserved environment variables.'
33+
}
34+
foreach ($prefix in $reservedPrefixes) {
35+
if ($normalized.StartsWith($prefix)) {
36+
throw 'TestData keys must not override reserved environment variables.'
37+
}
38+
}
39+
}
40+
function Assert-Map {
41+
<#
42+
.SYNOPSIS
43+
Validates that a TestData section is a JSON object map.
44+
#>
45+
param(
46+
[object] $Map,
47+
[string] $Name
48+
)
49+
if ($null -eq $Map) { return }
50+
if ($Map -isnot [pscustomobject]) {
51+
throw "The 'TestData.$Name' value must be a JSON object."
52+
}
53+
}
54+
function Get-EnvironmentValue {
55+
<#
56+
.SYNOPSIS
57+
Converts a scalar TestData value to an environment variable value.
58+
#>
59+
param(
60+
[object] $Value,
61+
[string] $Name
62+
)
63+
if ($null -eq $Value) { return '' }
64+
if (
65+
$Value -is [pscustomobject] -or
66+
($Value -is [System.Collections.IEnumerable] -and $Value -isnot [string])
67+
) {
68+
throw "Values in 'TestData.$Name' must be scalar values."
69+
}
70+
return [string]$Value
71+
}
72+
function Add-EnvFromMap {
73+
<#
74+
.SYNOPSIS
75+
Writes validated TestData entries to GITHUB_ENV.
76+
#>
77+
param(
78+
[object] $Map,
79+
[string] $Name,
80+
[switch] $Mask
81+
)
82+
Assert-Map -Map $Map -Name $Name
83+
if ($null -eq $Map) { return }
84+
$count = 0
85+
foreach ($item in $Map.PSObject.Properties) {
86+
$name = $item.Name
87+
Assert-EnvironmentName -Name $name
88+
$value = Get-EnvironmentValue -Value $item.Value -Name $Name
89+
if ($Mask) {
90+
foreach ($line in ($value -split "`n")) {
91+
$line = $line.TrimEnd("`r")
92+
if ($line.Length -gt 0) {
93+
Write-Output "::add-mask::$line"
94+
}
95+
}
96+
}
97+
do {
98+
$delimiter = "GHENV_$([guid]::NewGuid().ToString('N'))"
99+
} while ($value.Contains($delimiter))
100+
Add-Content -Path $env:GITHUB_ENV -Value "$name<<$delimiter"
101+
Add-Content -Path $env:GITHUB_ENV -Value $value
102+
Add-Content -Path $env:GITHUB_ENV -Value $delimiter
103+
$count++
104+
}
105+
if ($count -gt 0) {
106+
if ($Mask) {
107+
Write-Output "Exposed $count secret value(s) as environment variables."
108+
} else {
109+
Write-Output "Exposed $count variable value(s) as environment variables."
110+
}
111+
}
112+
}
113+
114+
Add-EnvFromMap -Map $data.secrets -Name 'secrets' -Mask
115+
Add-EnvFromMap -Map $data.variables -Name 'variables'

.github/workflows/AfterAll-ModuleLocal.yml

Lines changed: 1 addition & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -36,102 +36,7 @@ jobs:
3636
env:
3737
PSMODULE_TEST_DATA: ${{ secrets.TestData }}
3838
run: |
39-
if ([string]::IsNullOrWhiteSpace($env:PSMODULE_TEST_DATA)) {
40-
Write-Host 'No test data was provided by the calling workflow.'
41-
return
42-
}
43-
try {
44-
$data = $env:PSMODULE_TEST_DATA | ConvertFrom-Json -ErrorAction Stop
45-
} catch {
46-
throw "The 'TestData' secret must be valid JSON with 'secrets' and/or 'variables' maps."
47-
}
48-
if ($null -eq $data -or $data -isnot [pscustomobject]) {
49-
throw "The 'TestData' secret must be a JSON object with 'secrets' and/or 'variables' maps."
50-
}
51-
$allowedTopLevelKeys = @('secrets', 'variables')
52-
foreach ($propertyName in $data.PSObject.Properties.Name) {
53-
if ($allowedTopLevelKeys -notcontains $propertyName) {
54-
throw "The 'TestData' secret only supports 'secrets' and 'variables' maps."
55-
}
56-
}
57-
$reservedNames = @('CI', 'HOME', 'PATH', 'PWD', 'SHELL', 'PSMODULE_TEST_DATA')
58-
$reservedPrefixes = @('GITHUB_', 'RUNNER_', 'ACTIONS_')
59-
function Assert-EnvironmentName {
60-
param([string] $Name)
61-
if ($Name -notmatch '^[A-Za-z_][A-Za-z0-9_]*$') {
62-
throw "TestData keys must be valid environment variable names."
63-
}
64-
$normalized = $Name.ToUpperInvariant()
65-
if ($reservedNames -contains $normalized) {
66-
throw "TestData keys must not override reserved environment variables."
67-
}
68-
foreach ($prefix in $reservedPrefixes) {
69-
if ($normalized.StartsWith($prefix)) {
70-
throw "TestData keys must not override reserved environment variables."
71-
}
72-
}
73-
}
74-
function Assert-Map {
75-
param(
76-
[object] $Map,
77-
[string] $Name
78-
)
79-
if ($null -eq $Map) { return }
80-
if ($Map -isnot [pscustomobject]) {
81-
throw "The 'TestData.$Name' value must be a JSON object."
82-
}
83-
}
84-
function Get-EnvironmentValue {
85-
param(
86-
[object] $Value,
87-
[string] $Name
88-
)
89-
if ($null -eq $Value) { return '' }
90-
if ($Value -is [pscustomobject] -or ($Value -is [System.Collections.IEnumerable] -and $Value -isnot [string])) {
91-
throw "Values in 'TestData.$Name' must be scalar values."
92-
}
93-
return [string]$Value
94-
}
95-
function Add-EnvFromMap {
96-
param(
97-
[object] $Map,
98-
[string] $Name,
99-
[switch] $Mask
100-
)
101-
Assert-Map -Map $Map -Name $Name
102-
if ($null -eq $Map) { return }
103-
$count = 0
104-
foreach ($item in $Map.PSObject.Properties) {
105-
$name = $item.Name
106-
Assert-EnvironmentName -Name $name
107-
$value = Get-EnvironmentValue -Value $item.Value -Name $Name
108-
if ($Mask) {
109-
foreach ($line in ($value -split "`n")) {
110-
$line = $line.TrimEnd("`r")
111-
if ($line.Length -gt 0) {
112-
Write-Host "::add-mask::$line"
113-
}
114-
}
115-
}
116-
do {
117-
$delimiter = "GHENV_$([guid]::NewGuid().ToString('N'))"
118-
} while ($value.Contains($delimiter))
119-
Add-Content -Path $env:GITHUB_ENV -Value "$name<<$delimiter"
120-
Add-Content -Path $env:GITHUB_ENV -Value $value
121-
Add-Content -Path $env:GITHUB_ENV -Value $delimiter
122-
$count++
123-
}
124-
if ($count -gt 0) {
125-
if ($Mask) {
126-
Write-Host "Exposed $count secret value(s) as environment variables."
127-
} else {
128-
Write-Host "Exposed $count variable value(s) as environment variables."
129-
}
130-
}
131-
}
132-
133-
Add-EnvFromMap -Map $data.secrets -Name 'secrets' -Mask
134-
Add-EnvFromMap -Map $data.variables -Name 'variables'
39+
./.github/scripts/Expose-TestData.ps1
13540
13641
- name: Run AfterAll Teardown Scripts
13742
if: always()

.github/workflows/BeforeAll-ModuleLocal.yml

Lines changed: 1 addition & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -36,102 +36,7 @@ jobs:
3636
env:
3737
PSMODULE_TEST_DATA: ${{ secrets.TestData }}
3838
run: |
39-
if ([string]::IsNullOrWhiteSpace($env:PSMODULE_TEST_DATA)) {
40-
Write-Host 'No test data was provided by the calling workflow.'
41-
return
42-
}
43-
try {
44-
$data = $env:PSMODULE_TEST_DATA | ConvertFrom-Json -ErrorAction Stop
45-
} catch {
46-
throw "The 'TestData' secret must be valid JSON with 'secrets' and/or 'variables' maps."
47-
}
48-
if ($null -eq $data -or $data -isnot [pscustomobject]) {
49-
throw "The 'TestData' secret must be a JSON object with 'secrets' and/or 'variables' maps."
50-
}
51-
$allowedTopLevelKeys = @('secrets', 'variables')
52-
foreach ($propertyName in $data.PSObject.Properties.Name) {
53-
if ($allowedTopLevelKeys -notcontains $propertyName) {
54-
throw "The 'TestData' secret only supports 'secrets' and 'variables' maps."
55-
}
56-
}
57-
$reservedNames = @('CI', 'HOME', 'PATH', 'PWD', 'SHELL', 'PSMODULE_TEST_DATA')
58-
$reservedPrefixes = @('GITHUB_', 'RUNNER_', 'ACTIONS_')
59-
function Assert-EnvironmentName {
60-
param([string] $Name)
61-
if ($Name -notmatch '^[A-Za-z_][A-Za-z0-9_]*$') {
62-
throw "TestData keys must be valid environment variable names."
63-
}
64-
$normalized = $Name.ToUpperInvariant()
65-
if ($reservedNames -contains $normalized) {
66-
throw "TestData keys must not override reserved environment variables."
67-
}
68-
foreach ($prefix in $reservedPrefixes) {
69-
if ($normalized.StartsWith($prefix)) {
70-
throw "TestData keys must not override reserved environment variables."
71-
}
72-
}
73-
}
74-
function Assert-Map {
75-
param(
76-
[object] $Map,
77-
[string] $Name
78-
)
79-
if ($null -eq $Map) { return }
80-
if ($Map -isnot [pscustomobject]) {
81-
throw "The 'TestData.$Name' value must be a JSON object."
82-
}
83-
}
84-
function Get-EnvironmentValue {
85-
param(
86-
[object] $Value,
87-
[string] $Name
88-
)
89-
if ($null -eq $Value) { return '' }
90-
if ($Value -is [pscustomobject] -or ($Value -is [System.Collections.IEnumerable] -and $Value -isnot [string])) {
91-
throw "Values in 'TestData.$Name' must be scalar values."
92-
}
93-
return [string]$Value
94-
}
95-
function Add-EnvFromMap {
96-
param(
97-
[object] $Map,
98-
[string] $Name,
99-
[switch] $Mask
100-
)
101-
Assert-Map -Map $Map -Name $Name
102-
if ($null -eq $Map) { return }
103-
$count = 0
104-
foreach ($item in $Map.PSObject.Properties) {
105-
$name = $item.Name
106-
Assert-EnvironmentName -Name $name
107-
$value = Get-EnvironmentValue -Value $item.Value -Name $Name
108-
if ($Mask) {
109-
foreach ($line in ($value -split "`n")) {
110-
$line = $line.TrimEnd("`r")
111-
if ($line.Length -gt 0) {
112-
Write-Host "::add-mask::$line"
113-
}
114-
}
115-
}
116-
do {
117-
$delimiter = "GHENV_$([guid]::NewGuid().ToString('N'))"
118-
} while ($value.Contains($delimiter))
119-
Add-Content -Path $env:GITHUB_ENV -Value "$name<<$delimiter"
120-
Add-Content -Path $env:GITHUB_ENV -Value $value
121-
Add-Content -Path $env:GITHUB_ENV -Value $delimiter
122-
$count++
123-
}
124-
if ($count -gt 0) {
125-
if ($Mask) {
126-
Write-Host "Exposed $count secret value(s) as environment variables."
127-
} else {
128-
Write-Host "Exposed $count variable value(s) as environment variables."
129-
}
130-
}
131-
}
132-
133-
Add-EnvFromMap -Map $data.secrets -Name 'secrets' -Mask
134-
Add-EnvFromMap -Map $data.variables -Name 'variables'
39+
./.github/scripts/Expose-TestData.ps1
13540
13641
- name: Run BeforeAll Setup Scripts
13742
uses: PSModule/GitHub-Script@1ee97bbc652d19c38ae12f6e1e47e9d9fbd12d0a # v1.8.0

.github/workflows/Test-Module.yml

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,12 @@ name: Test-Module
22

33
on:
44
workflow_call:
5-
secrets:
6-
TEST_APP_ENT_CLIENT_ID:
7-
description: The client ID of an Enterprise GitHub App for running tests.
8-
required: false
9-
TEST_APP_ENT_PRIVATE_KEY:
10-
description: The private key of an Enterprise GitHub App for running tests.
11-
required: false
12-
TEST_APP_ORG_CLIENT_ID:
13-
description: The client ID of an Organization GitHub App for running tests.
14-
required: false
15-
TEST_APP_ORG_PRIVATE_KEY:
16-
description: The private key of an Organization GitHub App for running tests.
17-
required: false
18-
TEST_USER_ORG_FG_PAT:
19-
description: The fine-grained personal access token with org access for running tests.
20-
required: false
21-
TEST_USER_USER_FG_PAT:
22-
description: The fine-grained personal access token with user account access for running tests.
23-
required: false
24-
TEST_USER_PAT:
25-
description: The classic personal access token for running tests.
26-
required: false
275
inputs:
286
Settings:
297
type: string
308
description: The settings object as a JSON string.
319
required: true
3210

33-
env:
34-
TEST_APP_ENT_CLIENT_ID: ${{ secrets.TEST_APP_ENT_CLIENT_ID }}
35-
TEST_APP_ENT_PRIVATE_KEY: ${{ secrets.TEST_APP_ENT_PRIVATE_KEY }}
36-
TEST_APP_ORG_CLIENT_ID: ${{ secrets.TEST_APP_ORG_CLIENT_ID }}
37-
TEST_APP_ORG_PRIVATE_KEY: ${{ secrets.TEST_APP_ORG_PRIVATE_KEY }}
38-
TEST_USER_ORG_FG_PAT: ${{ secrets.TEST_USER_ORG_FG_PAT }}
39-
TEST_USER_USER_FG_PAT: ${{ secrets.TEST_USER_USER_FG_PAT }}
40-
TEST_USER_PAT: ${{ secrets.TEST_USER_PAT }}
41-
4211
permissions:
4312
contents: read # to checkout the repo and create releases on the repo
4413

0 commit comments

Comments
 (0)