Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 107 additions & 29 deletions .github/workflows/AfterAll-ModuleLocal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,18 @@ name: AfterAll-ModuleLocal
on:
workflow_call:
secrets:
TEST_APP_ENT_CLIENT_ID:
description: The client ID of an Enterprise GitHub App for running tests.
required: false
TEST_APP_ENT_PRIVATE_KEY:
description: The private key of an Enterprise GitHub App for running tests.
required: false
TEST_APP_ORG_CLIENT_ID:
description: The client ID of an Organization GitHub App for running tests.
required: false
TEST_APP_ORG_PRIVATE_KEY:
description: The private key of an Organization GitHub App for running tests.
required: false
TEST_USER_ORG_FG_PAT:
description: The fine-grained personal access token with org access for running tests.
required: false
TEST_USER_USER_FG_PAT:
description: The fine-grained personal access token with user account access for running tests.
required: false
TEST_USER_PAT:
description: The classic personal access token for running tests.
TestData:
description: |
Optional single-line JSON object with 'secrets' and 'variables' maps. Each entry is exposed
as an environment variable available to the AfterAll teardown script; 'secrets' values are
masked in the logs, 'variables' values are not.
required: false
inputs:
Settings:
type: string
description: The complete settings object including test suites.
required: true

env:
TEST_APP_ENT_CLIENT_ID: ${{ secrets.TEST_APP_ENT_CLIENT_ID }}
TEST_APP_ENT_PRIVATE_KEY: ${{ secrets.TEST_APP_ENT_PRIVATE_KEY }}
TEST_APP_ORG_CLIENT_ID: ${{ secrets.TEST_APP_ORG_CLIENT_ID }}
TEST_APP_ORG_PRIVATE_KEY: ${{ secrets.TEST_APP_ORG_PRIVATE_KEY }}
TEST_USER_ORG_FG_PAT: ${{ secrets.TEST_USER_ORG_FG_PAT }}
TEST_USER_USER_FG_PAT: ${{ secrets.TEST_USER_USER_FG_PAT }}
TEST_USER_PAT: ${{ secrets.TEST_USER_PAT }}

permissions:
contents: read # to checkout the repo

Expand All @@ -55,6 +31,108 @@ jobs:
persist-credentials: false
fetch-depth: 0

- name: Expose caller-provided test data
shell: pwsh
env:
PSMODULE_TEST_DATA: ${{ secrets.TestData }}
run: |
Comment thread
MariusStorhaug marked this conversation as resolved.
if ([string]::IsNullOrWhiteSpace($env:PSMODULE_TEST_DATA)) {
Write-Host 'No test data was provided by the calling workflow.'
return
}
try {
$data = $env:PSMODULE_TEST_DATA | ConvertFrom-Json -ErrorAction Stop
} catch {
throw "The 'TestData' secret must be valid JSON with 'secrets' and/or 'variables' maps."
}
if ($null -eq $data -or $data -isnot [pscustomobject]) {
throw "The 'TestData' secret must be a JSON object with 'secrets' and/or 'variables' maps."
}
$allowedTopLevelKeys = @('secrets', 'variables')
foreach ($propertyName in $data.PSObject.Properties.Name) {
if ($allowedTopLevelKeys -notcontains $propertyName) {
throw "The 'TestData' secret only supports 'secrets' and 'variables' maps."
}
}
$reservedNames = @('CI', 'HOME', 'PATH', 'PWD', 'SHELL', 'PSMODULE_TEST_DATA')
$reservedPrefixes = @('GITHUB_', 'RUNNER_', 'ACTIONS_')
function Assert-EnvironmentName {
param([string] $Name)
if ($Name -notmatch '^[A-Za-z_][A-Za-z0-9_]*$') {
throw "TestData keys must be valid environment variable names."
}
$normalized = $Name.ToUpperInvariant()
if ($reservedNames -contains $normalized) {
throw "TestData keys must not override reserved environment variables."
}
foreach ($prefix in $reservedPrefixes) {
if ($normalized.StartsWith($prefix)) {
throw "TestData keys must not override reserved environment variables."
}
}
}
function Assert-Map {
param(
[object] $Map,
[string] $Name
)
if ($null -eq $Map) { return }
if ($Map -isnot [pscustomobject]) {
throw "The 'TestData.$Name' value must be a JSON object."
}
}
function Get-EnvironmentValue {
param(
[object] $Value,
[string] $Name
)
if ($null -eq $Value) { return '' }
if ($Value -is [pscustomobject] -or ($Value -is [System.Collections.IEnumerable] -and $Value -isnot [string])) {
throw "Values in 'TestData.$Name' must be scalar values."
}
return [string]$Value
}
function Add-EnvFromMap {
param(
[object] $Map,
[string] $Name,
[switch] $Mask
)
Assert-Map -Map $Map -Name $Name
if ($null -eq $Map) { return }
$count = 0
foreach ($item in $Map.PSObject.Properties) {
$name = $item.Name
Assert-EnvironmentName -Name $name
$value = Get-EnvironmentValue -Value $item.Value -Name $Name
if ($Mask) {
foreach ($line in ($value -split "`n")) {
$line = $line.TrimEnd("`r")
if ($line.Length -gt 0) {
Write-Host "::add-mask::$line"
}
}
}
do {
$delimiter = "GHENV_$([guid]::NewGuid().ToString('N'))"
} while ($value.Contains($delimiter))
Add-Content -Path $env:GITHUB_ENV -Value "$name<<$delimiter"
Add-Content -Path $env:GITHUB_ENV -Value $value
Add-Content -Path $env:GITHUB_ENV -Value $delimiter
$count++
}
if ($count -gt 0) {
if ($Mask) {
Write-Host "Exposed $count secret value(s) as environment variables."
} else {
Write-Host "Exposed $count variable value(s) as environment variables."
}
}
}

Add-EnvFromMap -Map $data.secrets -Name 'secrets' -Mask
Add-EnvFromMap -Map $data.variables -Name 'variables'

- name: Run AfterAll Teardown Scripts
if: always()
uses: PSModule/GitHub-Script@1ee97bbc652d19c38ae12f6e1e47e9d9fbd12d0a # v1.8.0
Expand Down
136 changes: 107 additions & 29 deletions .github/workflows/BeforeAll-ModuleLocal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,18 @@ name: BeforeAll-ModuleLocal
on:
workflow_call:
secrets:
TEST_APP_ENT_CLIENT_ID:
description: The client ID of an Enterprise GitHub App for running tests.
required: false
TEST_APP_ENT_PRIVATE_KEY:
description: The private key of an Enterprise GitHub App for running tests.
required: false
TEST_APP_ORG_CLIENT_ID:
description: The client ID of an Organization GitHub App for running tests.
required: false
TEST_APP_ORG_PRIVATE_KEY:
description: The private key of an Organization GitHub App for running tests.
required: false
TEST_USER_ORG_FG_PAT:
description: The fine-grained personal access token with org access for running tests.
required: false
TEST_USER_USER_FG_PAT:
description: The fine-grained personal access token with user account access for running tests.
required: false
TEST_USER_PAT:
description: The classic personal access token for running tests.
TestData:
description: |
Optional single-line JSON object with 'secrets' and 'variables' maps. Each entry is exposed
as an environment variable available to the BeforeAll setup script; 'secrets' values are
masked in the logs, 'variables' values are not.
required: false
inputs:
Settings:
type: string
description: The complete settings object including test suites.
required: true

env:
TEST_APP_ENT_CLIENT_ID: ${{ secrets.TEST_APP_ENT_CLIENT_ID }}
TEST_APP_ENT_PRIVATE_KEY: ${{ secrets.TEST_APP_ENT_PRIVATE_KEY }}
TEST_APP_ORG_CLIENT_ID: ${{ secrets.TEST_APP_ORG_CLIENT_ID }}
TEST_APP_ORG_PRIVATE_KEY: ${{ secrets.TEST_APP_ORG_PRIVATE_KEY }}
TEST_USER_ORG_FG_PAT: ${{ secrets.TEST_USER_ORG_FG_PAT }}
TEST_USER_USER_FG_PAT: ${{ secrets.TEST_USER_USER_FG_PAT }}
TEST_USER_PAT: ${{ secrets.TEST_USER_PAT }}

permissions:
contents: read # to checkout the repo

Expand All @@ -55,6 +31,108 @@ jobs:
persist-credentials: false
fetch-depth: 0

- name: Expose caller-provided test data
shell: pwsh
env:
PSMODULE_TEST_DATA: ${{ secrets.TestData }}
run: |
Comment thread
MariusStorhaug marked this conversation as resolved.
if ([string]::IsNullOrWhiteSpace($env:PSMODULE_TEST_DATA)) {
Write-Host 'No test data was provided by the calling workflow.'
return
}
try {
$data = $env:PSMODULE_TEST_DATA | ConvertFrom-Json -ErrorAction Stop
} catch {
throw "The 'TestData' secret must be valid JSON with 'secrets' and/or 'variables' maps."
}
if ($null -eq $data -or $data -isnot [pscustomobject]) {
throw "The 'TestData' secret must be a JSON object with 'secrets' and/or 'variables' maps."
}
$allowedTopLevelKeys = @('secrets', 'variables')
foreach ($propertyName in $data.PSObject.Properties.Name) {
if ($allowedTopLevelKeys -notcontains $propertyName) {
throw "The 'TestData' secret only supports 'secrets' and 'variables' maps."
}
}
$reservedNames = @('CI', 'HOME', 'PATH', 'PWD', 'SHELL', 'PSMODULE_TEST_DATA')
$reservedPrefixes = @('GITHUB_', 'RUNNER_', 'ACTIONS_')
function Assert-EnvironmentName {
param([string] $Name)
if ($Name -notmatch '^[A-Za-z_][A-Za-z0-9_]*$') {
throw "TestData keys must be valid environment variable names."
}
$normalized = $Name.ToUpperInvariant()
if ($reservedNames -contains $normalized) {
throw "TestData keys must not override reserved environment variables."
}
foreach ($prefix in $reservedPrefixes) {
if ($normalized.StartsWith($prefix)) {
throw "TestData keys must not override reserved environment variables."
}
}
}
function Assert-Map {
param(
[object] $Map,
[string] $Name
)
if ($null -eq $Map) { return }
if ($Map -isnot [pscustomobject]) {
throw "The 'TestData.$Name' value must be a JSON object."
}
}
function Get-EnvironmentValue {
param(
[object] $Value,
[string] $Name
)
if ($null -eq $Value) { return '' }
if ($Value -is [pscustomobject] -or ($Value -is [System.Collections.IEnumerable] -and $Value -isnot [string])) {
throw "Values in 'TestData.$Name' must be scalar values."
}
return [string]$Value
}
function Add-EnvFromMap {
param(
[object] $Map,
[string] $Name,
[switch] $Mask
)
Assert-Map -Map $Map -Name $Name
if ($null -eq $Map) { return }
$count = 0
foreach ($item in $Map.PSObject.Properties) {
$name = $item.Name
Assert-EnvironmentName -Name $name
$value = Get-EnvironmentValue -Value $item.Value -Name $Name
if ($Mask) {
foreach ($line in ($value -split "`n")) {
$line = $line.TrimEnd("`r")
if ($line.Length -gt 0) {
Write-Host "::add-mask::$line"
}
}
}
do {
$delimiter = "GHENV_$([guid]::NewGuid().ToString('N'))"
} while ($value.Contains($delimiter))
Add-Content -Path $env:GITHUB_ENV -Value "$name<<$delimiter"
Add-Content -Path $env:GITHUB_ENV -Value $value
Add-Content -Path $env:GITHUB_ENV -Value $delimiter
$count++
}
if ($count -gt 0) {
if ($Mask) {
Write-Host "Exposed $count secret value(s) as environment variables."
} else {
Write-Host "Exposed $count variable value(s) as environment variables."
}
}
}

Add-EnvFromMap -Map $data.secrets -Name 'secrets' -Mask
Add-EnvFromMap -Map $data.variables -Name 'variables'

- name: Run BeforeAll Setup Scripts
uses: PSModule/GitHub-Script@1ee97bbc652d19c38ae12f6e1e47e9d9fbd12d0a # v1.8.0
with:
Expand Down
Loading
Loading