From 4bbdf430026f98713081dea00c25d53591f20806 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 16 Jul 2026 20:24:13 +0200 Subject: [PATCH 1/2] Expose test data through a shared module-local action --- .github/actions/Expose-TestData/action.yml | 24 +++++++++++++++++ .github/workflows/AfterAll-ModuleLocal.yml | 8 +++--- .github/workflows/BeforeAll-ModuleLocal.yml | 8 +++--- .github/workflows/Test-ModuleLocal.yml | 8 +++--- .github/workflows/workflow.yml | 5 +++- README.md | 27 +++++++++++++++++++ tests/srcTestRepo/tests/AfterAll.ps1 | 2 ++ tests/srcTestRepo/tests/BeforeAll.ps1 | 2 ++ .../srcTestRepo/tests/TestData.Assertions.ps1 | 16 +++++++++++ .../tests/AfterAll.ps1 | 2 ++ .../tests/BeforeAll.ps1 | 2 ++ .../tests/TestData.Assertions.ps1 | 16 +++++++++++ 12 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 .github/actions/Expose-TestData/action.yml create mode 100644 tests/srcTestRepo/tests/TestData.Assertions.ps1 create mode 100644 tests/srcWithManifestTestRepo/tests/TestData.Assertions.ps1 diff --git a/.github/actions/Expose-TestData/action.yml b/.github/actions/Expose-TestData/action.yml new file mode 100644 index 00000000..67d9e936 --- /dev/null +++ b/.github/actions/Expose-TestData/action.yml @@ -0,0 +1,24 @@ +name: Expose-TestData +description: Exposes caller-provided Process-PSModule TestData as environment variables. +author: PSModule +branding: + icon: unlock + color: white + +inputs: + TestData: + description: | + Optional single-line JSON object with 'secrets' and 'variables' maps. Entries are validated by + Import-TestData and exported to GITHUB_ENV for later steps in the same job. + required: false + default: '' + +runs: + using: composite + steps: + - name: Expose caller-provided test data + shell: pwsh + env: + PSMODULE_TEST_DATA: ${{ inputs.TestData }} + run: | + Import-TestData diff --git a/.github/workflows/AfterAll-ModuleLocal.yml b/.github/workflows/AfterAll-ModuleLocal.yml index 32293453..9ca0b28f 100644 --- a/.github/workflows/AfterAll-ModuleLocal.yml +++ b/.github/workflows/AfterAll-ModuleLocal.yml @@ -43,11 +43,9 @@ jobs: uses: ./_wf/.github/actions/Install-PSModuleHelpers - name: Expose caller-provided test data - shell: pwsh - env: - PSMODULE_TEST_DATA: ${{ secrets.TestData }} - run: | - Import-TestData + uses: ./_wf/.github/actions/Expose-TestData + with: + TestData: ${{ secrets.TestData }} - name: Run AfterAll Teardown Scripts if: always() diff --git a/.github/workflows/BeforeAll-ModuleLocal.yml b/.github/workflows/BeforeAll-ModuleLocal.yml index ca86e503..24d9f905 100644 --- a/.github/workflows/BeforeAll-ModuleLocal.yml +++ b/.github/workflows/BeforeAll-ModuleLocal.yml @@ -43,11 +43,9 @@ jobs: uses: ./_wf/.github/actions/Install-PSModuleHelpers - name: Expose caller-provided test data - shell: pwsh - env: - PSMODULE_TEST_DATA: ${{ secrets.TestData }} - run: | - Import-TestData + uses: ./_wf/.github/actions/Expose-TestData + with: + TestData: ${{ secrets.TestData }} - name: Run BeforeAll Setup Scripts uses: PSModule/GitHub-Script@8083ec1f733f00357ee4d0db0c6056686e483bc0 # v1.9.0 diff --git a/.github/workflows/Test-ModuleLocal.yml b/.github/workflows/Test-ModuleLocal.yml index d1c84fa2..83c13788 100644 --- a/.github/workflows/Test-ModuleLocal.yml +++ b/.github/workflows/Test-ModuleLocal.yml @@ -54,11 +54,9 @@ jobs: uses: ./_wf/.github/actions/Install-PSModuleHelpers - name: Expose caller-provided test data - shell: pwsh - env: - PSMODULE_TEST_DATA: ${{ secrets.TestData }} - run: | - Import-TestData + uses: ./_wf/.github/actions/Expose-TestData + with: + TestData: ${{ secrets.TestData }} - name: Import-Module id: import-module diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 4757d745..94a5f1bc 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -15,7 +15,10 @@ on: $env:. Values under "secrets" are masked in the logs; values under "variables" are not. Build it from secrets. / vars. in the calling workflow (see the README). Keep it on a single line so GitHub registers one mask for the whole value. Omit it when the module - needs no test data. + needs no test data. The same keys are exported before BeforeAll-ModuleLocal, + Test-ModuleLocal, and AfterAll-ModuleLocal run. If setup or teardown scripts see a missing + key, confirm the caller explicitly maps a TestData JSON value; secrets: inherit only passes + an already-created TestData secret and does not build JSON from individual secrets. required: false inputs: SettingsPath: diff --git a/README.md b/README.md index 5e295557..689645eb 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,30 @@ The full documentation lives on the MSX / Docs site: 📖 **[Process-PSModule documentation](https://msxorg.github.io/docs/Frameworks/Process-PSModule/)** It covers getting started, the pipeline stages, usage, configuration, repository structure, and the principles behind the framework. + +## TestData phase parity + +Module-local setup, test, and teardown phases use the same `TestData` contract. Values under +`secrets` are masked and values under `variables` are exported unmasked, and every key is available +as `$env:` in all three phases: + +- `BeforeAll-ModuleLocal` (`tests/BeforeAll.ps1`) +- `Test-ModuleLocal` (Pester module tests) +- `AfterAll-ModuleLocal` (`tests/AfterAll.ps1`) + +Pass `TestData` as a single-line JSON object from the calling workflow: + +```yaml +jobs: + Process-PSModule: + uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v6 + secrets: + APIKey: ${{ secrets.APIKey }} + TestData: >- + { "secrets": { "TEST_TOKEN": "${{ secrets.TEST_TOKEN }}" }, + "variables": { "TEST_OWNER": ${{ toJSON(vars.TEST_OWNER) }} } } +``` + +If a key is missing in setup or teardown, verify that the caller explicitly maps `TestData` as JSON. +`secrets: inherit` only passes a repository or environment secret already named `TestData`; it does not +automatically build the JSON object from individual secrets. diff --git a/tests/srcTestRepo/tests/AfterAll.ps1 b/tests/srcTestRepo/tests/AfterAll.ps1 index 8933adae..e25904e3 100644 --- a/tests/srcTestRepo/tests/AfterAll.ps1 +++ b/tests/srcTestRepo/tests/AfterAll.ps1 @@ -1,6 +1,8 @@ Write-Warning "=== AFTERALL TEARDOWN SCRIPT EXECUTING ===" Write-Warning "Tearing down test environment..." +. "$PSScriptRoot/TestData.Assertions.ps1" + # Example teardown tasks: # - Clean up test infrastructure # - Remove test data diff --git a/tests/srcTestRepo/tests/BeforeAll.ps1 b/tests/srcTestRepo/tests/BeforeAll.ps1 index f487de58..e6bf884f 100644 --- a/tests/srcTestRepo/tests/BeforeAll.ps1 +++ b/tests/srcTestRepo/tests/BeforeAll.ps1 @@ -1,6 +1,8 @@ Write-Warning "=== BEFOREALL SETUP SCRIPT EXECUTING ===" Write-Warning "Setting up test environment..." +. "$PSScriptRoot/TestData.Assertions.ps1" + # Example setup tasks: # - Deploy test infrastructure # - Download test data diff --git a/tests/srcTestRepo/tests/TestData.Assertions.ps1 b/tests/srcTestRepo/tests/TestData.Assertions.ps1 new file mode 100644 index 00000000..d4038a1d --- /dev/null +++ b/tests/srcTestRepo/tests/TestData.Assertions.ps1 @@ -0,0 +1,16 @@ +$expectedTestData = @{ + PSMODULE_TEST_SINGLELINE_SECRET = 'psmodule-public-nonsecret-test-fixture-single-line' + PSMODULE_TEST_VARIABLE = 'psmodule-public-nonsecret-test-variable' +} + +foreach ($entry in $expectedTestData.GetEnumerator()) { + $actual = [System.Environment]::GetEnvironmentVariable($entry.Key) + if ([string]::IsNullOrEmpty($actual)) { + throw "TestData key '$($entry.Key)' is not available in the current module-local phase." + } + if ($actual -cne $entry.Value) { + throw "TestData key '$($entry.Key)' has an unexpected value in the current module-local phase." + } +} + +Write-Warning 'TestData secret and variable fixtures are available in this module-local phase.' diff --git a/tests/srcWithManifestTestRepo/tests/AfterAll.ps1 b/tests/srcWithManifestTestRepo/tests/AfterAll.ps1 index f6728d6f..83d61d6e 100644 --- a/tests/srcWithManifestTestRepo/tests/AfterAll.ps1 +++ b/tests/srcWithManifestTestRepo/tests/AfterAll.ps1 @@ -1,6 +1,8 @@ Write-Warning "=== AFTERALL TEARDOWN SCRIPT (Environments) EXECUTING ===" Write-Warning "Tearing down test environment for Environments..." +. "$PSScriptRoot/TestData.Assertions.ps1" + # Example teardown tasks for Environments directory: Write-Warning "Cleaning up Environments test environment..." diff --git a/tests/srcWithManifestTestRepo/tests/BeforeAll.ps1 b/tests/srcWithManifestTestRepo/tests/BeforeAll.ps1 index 0b6bbcdc..ffa8a5ad 100644 --- a/tests/srcWithManifestTestRepo/tests/BeforeAll.ps1 +++ b/tests/srcWithManifestTestRepo/tests/BeforeAll.ps1 @@ -1,6 +1,8 @@ Write-Warning "=== BEFOREALL SETUP SCRIPT EXECUTING ===" Write-Warning "Setting up test environment..." +. "$PSScriptRoot/TestData.Assertions.ps1" + # Example setup tasks for test environment: Write-Warning "Initializing test environment..." diff --git a/tests/srcWithManifestTestRepo/tests/TestData.Assertions.ps1 b/tests/srcWithManifestTestRepo/tests/TestData.Assertions.ps1 new file mode 100644 index 00000000..d4038a1d --- /dev/null +++ b/tests/srcWithManifestTestRepo/tests/TestData.Assertions.ps1 @@ -0,0 +1,16 @@ +$expectedTestData = @{ + PSMODULE_TEST_SINGLELINE_SECRET = 'psmodule-public-nonsecret-test-fixture-single-line' + PSMODULE_TEST_VARIABLE = 'psmodule-public-nonsecret-test-variable' +} + +foreach ($entry in $expectedTestData.GetEnumerator()) { + $actual = [System.Environment]::GetEnvironmentVariable($entry.Key) + if ([string]::IsNullOrEmpty($actual)) { + throw "TestData key '$($entry.Key)' is not available in the current module-local phase." + } + if ($actual -cne $entry.Value) { + throw "TestData key '$($entry.Key)' has an unexpected value in the current module-local phase." + } +} + +Write-Warning 'TestData secret and variable fixtures are available in this module-local phase.' From f2cb622046edc6eac8c011bd934712988d1e4a9e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 16 Jul 2026 21:13:04 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=96=20[Docs]:=20Remove=20TestData?= =?UTF-8?q?=20parity=20details=20from=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/README.md b/README.md index 689645eb..5e295557 100644 --- a/README.md +++ b/README.md @@ -9,30 +9,3 @@ The full documentation lives on the MSX / Docs site: 📖 **[Process-PSModule documentation](https://msxorg.github.io/docs/Frameworks/Process-PSModule/)** It covers getting started, the pipeline stages, usage, configuration, repository structure, and the principles behind the framework. - -## TestData phase parity - -Module-local setup, test, and teardown phases use the same `TestData` contract. Values under -`secrets` are masked and values under `variables` are exported unmasked, and every key is available -as `$env:` in all three phases: - -- `BeforeAll-ModuleLocal` (`tests/BeforeAll.ps1`) -- `Test-ModuleLocal` (Pester module tests) -- `AfterAll-ModuleLocal` (`tests/AfterAll.ps1`) - -Pass `TestData` as a single-line JSON object from the calling workflow: - -```yaml -jobs: - Process-PSModule: - uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v6 - secrets: - APIKey: ${{ secrets.APIKey }} - TestData: >- - { "secrets": { "TEST_TOKEN": "${{ secrets.TEST_TOKEN }}" }, - "variables": { "TEST_OWNER": ${{ toJSON(vars.TEST_OWNER) }} } } -``` - -If a key is missing in setup or teardown, verify that the caller explicitly maps `TestData` as JSON. -`secrets: inherit` only passes a repository or environment secret already named `TestData`; it does not -automatically build the JSON object from individual secrets.