From 69a8a7c7d174ef5edd538025d0e20eeeeff39877 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 20:52:47 +0200 Subject: [PATCH 01/23] Add generic GitHub App secret mapping Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Workflow-Test-Default.yml | 2 ++ .github/workflows/Workflow-Test-WithManifest.yml | 2 ++ .github/workflows/workflow.yml | 11 +++++++++++ 3 files changed, 15 insertions(+) diff --git a/.github/workflows/Workflow-Test-Default.yml b/.github/workflows/Workflow-Test-Default.yml index 511b4b1c..c7ebccf1 100644 --- a/.github/workflows/Workflow-Test-Default.yml +++ b/.github/workflows/Workflow-Test-Default.yml @@ -30,6 +30,8 @@ jobs: uses: ./.github/workflows/workflow.yml secrets: APIKey: ${{ secrets.APIKey }} + GitHubAppClientId: ${{ secrets.PSMODULE_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.PSMODULE_PRIVATE_KEY }} TestData: >- { "secrets": { diff --git a/.github/workflows/Workflow-Test-WithManifest.yml b/.github/workflows/Workflow-Test-WithManifest.yml index 82f80f55..ad048a79 100644 --- a/.github/workflows/Workflow-Test-WithManifest.yml +++ b/.github/workflows/Workflow-Test-WithManifest.yml @@ -30,6 +30,8 @@ jobs: uses: ./.github/workflows/workflow.yml secrets: APIKey: ${{ secrets.APIKey }} + GitHubAppClientId: ${{ secrets.PSMODULE_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.PSMODULE_PRIVATE_KEY }} TestData: >- { "secrets": { diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 099afc34..789bef75 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -6,6 +6,12 @@ on: APIKey: description: The API key for the PowerShell Gallery. required: true + GitHubAppClientId: + description: Generic GitHub App client ID secret for caller mapping. + required: true + GitHubAppPrivateKey: + description: Generic GitHub App private key secret for caller mapping. + required: true TestData: description: | Optional single-line JSON object carrying all data the module test jobs @@ -77,6 +83,9 @@ jobs: # - ✅ Manual run - Always runs to load configuration Plan: uses: ./.github/workflows/Plan.yml + secrets: + GitHubAppClientId: ${{ secrets.GitHubAppClientId }} + GitHubAppPrivateKey: ${{ secrets.GitHubAppPrivateKey }} with: SettingsPath: ${{ inputs.SettingsPath }} Debug: ${{ inputs.Debug }} @@ -246,6 +255,8 @@ jobs: uses: ./.github/workflows/Publish-Module.yml secrets: APIKey: ${{ secrets.APIKey }} + GitHubAppClientId: ${{ secrets.GitHubAppClientId }} + GitHubAppPrivateKey: ${{ secrets.GitHubAppPrivateKey }} needs: - Plan - Get-TestResults From ac2caa122b3fa6d75c978cfa1f0d98c2041a7b7e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 20:52:49 +0200 Subject: [PATCH 02/23] Document reusable GitHub App secrets Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index db35db76..1230fb72 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,21 @@ 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. + +## Reusable workflow secrets (GitHub App auth) + +When calling `./.github/workflows/workflow.yml`, pass GitHub App credentials using these generic reusable-workflow secret names: + +- `GitHubAppClientId` +- `GitHubAppPrivateKey` + +Consumer repositories can keep their own secret names and map them in the caller workflow, for example: + +```yaml +jobs: + ProcessPSModule: + uses: ./.github/workflows/workflow.yml + secrets: + GitHubAppClientId: ${{ secrets.PSMODULE_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.PSMODULE_PRIVATE_KEY }} +``` From b5cbfe31b06fdb4d66b9442825c82b448744bc67 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 20:53:05 +0200 Subject: [PATCH 03/23] Use GitHub App token in Plan workflow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Plan.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Plan.yml b/.github/workflows/Plan.yml index 3fad50eb..65e6e48c 100644 --- a/.github/workflows/Plan.yml +++ b/.github/workflows/Plan.yml @@ -9,6 +9,13 @@ name: Plan on: workflow_call: + secrets: + GitHubAppClientId: + description: The client ID of the GitHub App used for repository API calls. + required: true + GitHubAppPrivateKey: + description: The private key of the GitHub App used for repository API calls. + required: true inputs: SettingsPath: type: string @@ -80,9 +87,19 @@ jobs: path: _wf persist-credentials: false + - name: Create GitHub App token + id: App-Token + uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2 + with: + app-id: ${{ secrets.GitHubAppClientId }} + private-key: ${{ secrets.GitHubAppPrivateKey }} + - name: Get-Settings uses: ./_wf/.github/actions/Get-PSModuleSettings id: Get-Settings + env: + GH_TOKEN: ${{ steps.App-Token.outputs.token }} + GITHUB_TOKEN: ${{ steps.App-Token.outputs.token }} with: SettingsPath: ${{ inputs.SettingsPath }} Debug: ${{ inputs.Debug }} @@ -96,7 +113,8 @@ jobs: uses: ./_wf/.github/actions/Resolve-PSModuleVersion id: Resolve-Version env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.App-Token.outputs.token }} + GITHUB_TOKEN: ${{ steps.App-Token.outputs.token }} with: Settings: ${{ steps.Get-Settings.outputs.Settings }} Name: ${{ fromJson(steps.Get-Settings.outputs.Settings).Name }} From eec3b8440393cdd7a2fa50a004a997fc3953dfbc Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 20:53:07 +0200 Subject: [PATCH 04/23] Use GitHub App token in publish workflow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Publish-Module.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Publish-Module.yml b/.github/workflows/Publish-Module.yml index ee1bbcb6..81d02fe7 100644 --- a/.github/workflows/Publish-Module.yml +++ b/.github/workflows/Publish-Module.yml @@ -6,6 +6,12 @@ on: APIKey: description: The API key for the PowerShell Gallery. required: true + GitHubAppClientId: + description: The client ID of the GitHub App used for repository API calls. + required: true + GitHubAppPrivateKey: + description: The private key of the GitHub App used for repository API calls. + required: true inputs: Settings: type: string @@ -37,11 +43,19 @@ jobs: path: _wf persist-credentials: false + - name: Create GitHub App token + id: App-Token + uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2 + with: + app-id: ${{ secrets.GitHubAppClientId }} + private-key: ${{ secrets.GitHubAppPrivateKey }} + - name: Publish module if: fromJson(inputs.Settings).Publish.Module.Resolution.ReleaseType != 'None' uses: ./_wf/.github/actions/Publish-PSModule env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.App-Token.outputs.token }} + GITHUB_TOKEN: ${{ steps.App-Token.outputs.token }} with: Name: ${{ fromJson(inputs.Settings).Name }} ModulePath: outputs/module @@ -56,7 +70,8 @@ jobs: if: fromJson(inputs.Settings).Publish.Module.Resolution.ReleaseType != 'Prerelease' uses: ./_wf/.github/actions/Cleanup-PSModulePrereleases env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.App-Token.outputs.token }} + GITHUB_TOKEN: ${{ steps.App-Token.outputs.token }} with: WhatIf: ${{ github.repository == 'PSModule/Process-PSModule' }} AutoCleanup: ${{ fromJson(inputs.Settings).Publish.Module.AutoCleanup }} From 4b47a32dcb4ed934511a5bf9b0843c81b0717c9a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 20:53:08 +0200 Subject: [PATCH 05/23] Adjust action token env precedence Prefer caller-provided GH_TOKEN/GITHUB_TOKEN for GitHub API/CLI calls while keeping github.token fallback for compatibility. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/actions/Cleanup-PSModulePrereleases/action.yml | 2 ++ .github/actions/Get-PSModuleSettings/action.yml | 2 ++ .github/actions/Publish-PSModule/action.yml | 2 ++ .github/actions/Resolve-PSModuleVersion/action.yml | 3 ++- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/actions/Cleanup-PSModulePrereleases/action.yml b/.github/actions/Cleanup-PSModulePrereleases/action.yml index 3c076b45..cf6b97c4 100644 --- a/.github/actions/Cleanup-PSModulePrereleases/action.yml +++ b/.github/actions/Cleanup-PSModulePrereleases/action.yml @@ -27,6 +27,8 @@ runs: shell: pwsh working-directory: ${{ inputs.WorkingDirectory }} env: + GH_TOKEN: ${{ env.GH_TOKEN || env.GITHUB_TOKEN || github.token }} + GITHUB_TOKEN: ${{ env.GITHUB_TOKEN || env.GH_TOKEN || github.token }} PSMODULE_CLEANUP_PSMODULEPRERELEASES_INPUT_WhatIf: ${{ inputs.WhatIf }} PSMODULE_CLEANUP_PSMODULEPRERELEASES_CONTEXT_ReleaseTag: ${{ env.PSMODULE_PUBLISH_PSMODULE_CONTEXT_ReleaseTag }} run: ${{ github.action_path }}/src/cleanup.ps1 diff --git a/.github/actions/Get-PSModuleSettings/action.yml b/.github/actions/Get-PSModuleSettings/action.yml index 86a49b3a..3597f8fe 100644 --- a/.github/actions/Get-PSModuleSettings/action.yml +++ b/.github/actions/Get-PSModuleSettings/action.yml @@ -53,6 +53,8 @@ runs: uses: PSModule/GitHub-Script@8083ec1f733f00357ee4d0db0c6056686e483bc0 # v1.9.0 id: Get-PSModuleSettings env: + GH_TOKEN: ${{ env.GH_TOKEN || env.GITHUB_TOKEN || github.token }} + GITHUB_TOKEN: ${{ env.GITHUB_TOKEN || env.GH_TOKEN || github.token }} PSMODULE_GET_SETTINGS_INPUT_Name: ${{ inputs.Name }} PSMODULE_GET_SETTINGS_INPUT_SettingsPath: ${{ inputs.SettingsPath }} PSMODULE_GET_SETTINGS_INPUT_Debug: ${{ inputs.Debug }} diff --git a/.github/actions/Publish-PSModule/action.yml b/.github/actions/Publish-PSModule/action.yml index 0ff0a534..1e7ffd0d 100644 --- a/.github/actions/Publish-PSModule/action.yml +++ b/.github/actions/Publish-PSModule/action.yml @@ -58,6 +58,8 @@ runs: shell: pwsh working-directory: ${{ inputs.WorkingDirectory }} env: + GH_TOKEN: ${{ env.GH_TOKEN || env.GITHUB_TOKEN || github.token }} + GITHUB_TOKEN: ${{ env.GITHUB_TOKEN || env.GH_TOKEN || github.token }} PSMODULE_PUBLISH_PSMODULE_INPUT_Name: ${{ inputs.Name }} PSMODULE_PUBLISH_PSMODULE_INPUT_ModulePath: ${{ inputs.ModulePath }} PSMODULE_PUBLISH_PSMODULE_INPUT_APIKey: ${{ inputs.APIKey }} diff --git a/.github/actions/Resolve-PSModuleVersion/action.yml b/.github/actions/Resolve-PSModuleVersion/action.yml index 20b41883..c3a399c4 100644 --- a/.github/actions/Resolve-PSModuleVersion/action.yml +++ b/.github/actions/Resolve-PSModuleVersion/action.yml @@ -65,7 +65,8 @@ runs: shell: pwsh working-directory: ${{ inputs.WorkingDirectory }} env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ env.GH_TOKEN || env.GITHUB_TOKEN || github.token }} + GITHUB_TOKEN: ${{ env.GITHUB_TOKEN || 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 }} From a339e4dd615283aaabf2cf6f8d00ba1d83893c08 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 20:52:34 +0200 Subject: [PATCH 06/23] Prefer app token in Get-PSModuleSettings Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/Get-PSModuleSettings/action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/actions/Get-PSModuleSettings/action.yml b/.github/actions/Get-PSModuleSettings/action.yml index 3597f8fe..208a4b00 100644 --- a/.github/actions/Get-PSModuleSettings/action.yml +++ b/.github/actions/Get-PSModuleSettings/action.yml @@ -65,6 +65,8 @@ runs: PSMODULE_GET_SETTINGS_INPUT_ImportantFilePatterns: ${{ inputs.ImportantFilePatterns }} with: Name: Get-PSModuleSettings + # Prefer a caller-provided GitHub App token when available. + Token: ${{ env.PSMODULE_GITHUB_APP_TOKEN || env.GITHUB_APP_TOKEN || env.GH_APP_TOKEN || env.GH_TOKEN || github.token }} ShowInfo: false ShowOutput: true Debug: ${{ inputs.Debug }} From f7ded053debd13d329c6094dfe3461027769c3fd Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 21:07:38 +0200 Subject: [PATCH 07/23] Make GitHub App token wiring strict Remove github.token fallbacks from GitHub-facing composite actions so reusable workflow paths require explicit app-token env wiring. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/Cleanup-PSModulePrereleases/action.yml | 4 ++-- .github/actions/Get-PSModuleSettings/action.yml | 7 +++---- .github/actions/Publish-PSModule/action.yml | 4 ++-- .github/actions/Resolve-PSModuleVersion/action.yml | 4 ++-- README.md | 2 ++ 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/actions/Cleanup-PSModulePrereleases/action.yml b/.github/actions/Cleanup-PSModulePrereleases/action.yml index cf6b97c4..2e46f71e 100644 --- a/.github/actions/Cleanup-PSModulePrereleases/action.yml +++ b/.github/actions/Cleanup-PSModulePrereleases/action.yml @@ -27,8 +27,8 @@ runs: shell: pwsh working-directory: ${{ inputs.WorkingDirectory }} env: - GH_TOKEN: ${{ env.GH_TOKEN || env.GITHUB_TOKEN || github.token }} - GITHUB_TOKEN: ${{ env.GITHUB_TOKEN || env.GH_TOKEN || github.token }} + GH_TOKEN: ${{ env.GH_TOKEN }} + GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }} PSMODULE_CLEANUP_PSMODULEPRERELEASES_INPUT_WhatIf: ${{ inputs.WhatIf }} PSMODULE_CLEANUP_PSMODULEPRERELEASES_CONTEXT_ReleaseTag: ${{ env.PSMODULE_PUBLISH_PSMODULE_CONTEXT_ReleaseTag }} run: ${{ github.action_path }}/src/cleanup.ps1 diff --git a/.github/actions/Get-PSModuleSettings/action.yml b/.github/actions/Get-PSModuleSettings/action.yml index 208a4b00..70e2e703 100644 --- a/.github/actions/Get-PSModuleSettings/action.yml +++ b/.github/actions/Get-PSModuleSettings/action.yml @@ -53,8 +53,8 @@ runs: uses: PSModule/GitHub-Script@8083ec1f733f00357ee4d0db0c6056686e483bc0 # v1.9.0 id: Get-PSModuleSettings env: - GH_TOKEN: ${{ env.GH_TOKEN || env.GITHUB_TOKEN || github.token }} - GITHUB_TOKEN: ${{ env.GITHUB_TOKEN || env.GH_TOKEN || github.token }} + GH_TOKEN: ${{ env.GH_TOKEN }} + GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }} PSMODULE_GET_SETTINGS_INPUT_Name: ${{ inputs.Name }} PSMODULE_GET_SETTINGS_INPUT_SettingsPath: ${{ inputs.SettingsPath }} PSMODULE_GET_SETTINGS_INPUT_Debug: ${{ inputs.Debug }} @@ -65,8 +65,7 @@ runs: PSMODULE_GET_SETTINGS_INPUT_ImportantFilePatterns: ${{ inputs.ImportantFilePatterns }} with: Name: Get-PSModuleSettings - # Prefer a caller-provided GitHub App token when available. - Token: ${{ env.PSMODULE_GITHUB_APP_TOKEN || env.GITHUB_APP_TOKEN || env.GH_APP_TOKEN || env.GH_TOKEN || github.token }} + Token: ${{ env.GITHUB_TOKEN }} ShowInfo: false ShowOutput: true Debug: ${{ inputs.Debug }} diff --git a/.github/actions/Publish-PSModule/action.yml b/.github/actions/Publish-PSModule/action.yml index 1e7ffd0d..18b1811d 100644 --- a/.github/actions/Publish-PSModule/action.yml +++ b/.github/actions/Publish-PSModule/action.yml @@ -58,8 +58,8 @@ runs: shell: pwsh working-directory: ${{ inputs.WorkingDirectory }} env: - GH_TOKEN: ${{ env.GH_TOKEN || env.GITHUB_TOKEN || github.token }} - GITHUB_TOKEN: ${{ env.GITHUB_TOKEN || env.GH_TOKEN || github.token }} + GH_TOKEN: ${{ env.GH_TOKEN }} + GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }} PSMODULE_PUBLISH_PSMODULE_INPUT_Name: ${{ inputs.Name }} PSMODULE_PUBLISH_PSMODULE_INPUT_ModulePath: ${{ inputs.ModulePath }} PSMODULE_PUBLISH_PSMODULE_INPUT_APIKey: ${{ inputs.APIKey }} diff --git a/.github/actions/Resolve-PSModuleVersion/action.yml b/.github/actions/Resolve-PSModuleVersion/action.yml index c3a399c4..072f2d47 100644 --- a/.github/actions/Resolve-PSModuleVersion/action.yml +++ b/.github/actions/Resolve-PSModuleVersion/action.yml @@ -65,8 +65,8 @@ runs: shell: pwsh working-directory: ${{ inputs.WorkingDirectory }} env: - GH_TOKEN: ${{ env.GH_TOKEN || env.GITHUB_TOKEN || github.token }} - GITHUB_TOKEN: ${{ env.GITHUB_TOKEN || env.GH_TOKEN || github.token }} + GH_TOKEN: ${{ env.GH_TOKEN }} + GITHUB_TOKEN: ${{ env.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/README.md b/README.md index 1230fb72..052b35b1 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,5 @@ jobs: GitHubAppClientId: ${{ secrets.PSMODULE_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.PSMODULE_PRIVATE_KEY }} ``` + +This is a required contract for GitHub operations in the reusable workflow path; `github.token` fallback is intentionally not used. From 83568fb790c9f1e6e11c42f3ccb84962ea08bdd0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 21:12:48 +0200 Subject: [PATCH 08/23] Use only GH_TOKEN for app-auth steps For GitHub App-enabled workflow/action paths, remove dual-token env usage and keep explicit GH_TOKEN-only wiring with no github.token fallback. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/Cleanup-PSModulePrereleases/action.yml | 1 - .github/actions/Get-PSModuleSettings/action.yml | 3 +-- .github/actions/Publish-PSModule/action.yml | 1 - .github/actions/Resolve-PSModuleVersion/action.yml | 1 - .github/workflows/Plan.yml | 2 -- .github/workflows/Publish-Module.yml | 2 -- README.md | 2 +- 7 files changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/actions/Cleanup-PSModulePrereleases/action.yml b/.github/actions/Cleanup-PSModulePrereleases/action.yml index 2e46f71e..5bba40c0 100644 --- a/.github/actions/Cleanup-PSModulePrereleases/action.yml +++ b/.github/actions/Cleanup-PSModulePrereleases/action.yml @@ -28,7 +28,6 @@ runs: working-directory: ${{ inputs.WorkingDirectory }} env: GH_TOKEN: ${{ env.GH_TOKEN }} - GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }} PSMODULE_CLEANUP_PSMODULEPRERELEASES_INPUT_WhatIf: ${{ inputs.WhatIf }} PSMODULE_CLEANUP_PSMODULEPRERELEASES_CONTEXT_ReleaseTag: ${{ env.PSMODULE_PUBLISH_PSMODULE_CONTEXT_ReleaseTag }} run: ${{ github.action_path }}/src/cleanup.ps1 diff --git a/.github/actions/Get-PSModuleSettings/action.yml b/.github/actions/Get-PSModuleSettings/action.yml index 70e2e703..1a209701 100644 --- a/.github/actions/Get-PSModuleSettings/action.yml +++ b/.github/actions/Get-PSModuleSettings/action.yml @@ -54,7 +54,6 @@ runs: id: Get-PSModuleSettings env: GH_TOKEN: ${{ env.GH_TOKEN }} - GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }} PSMODULE_GET_SETTINGS_INPUT_Name: ${{ inputs.Name }} PSMODULE_GET_SETTINGS_INPUT_SettingsPath: ${{ inputs.SettingsPath }} PSMODULE_GET_SETTINGS_INPUT_Debug: ${{ inputs.Debug }} @@ -65,7 +64,7 @@ runs: PSMODULE_GET_SETTINGS_INPUT_ImportantFilePatterns: ${{ inputs.ImportantFilePatterns }} with: Name: Get-PSModuleSettings - Token: ${{ env.GITHUB_TOKEN }} + Token: ${{ env.GH_TOKEN }} ShowInfo: false ShowOutput: true Debug: ${{ inputs.Debug }} diff --git a/.github/actions/Publish-PSModule/action.yml b/.github/actions/Publish-PSModule/action.yml index 18b1811d..badd74b8 100644 --- a/.github/actions/Publish-PSModule/action.yml +++ b/.github/actions/Publish-PSModule/action.yml @@ -59,7 +59,6 @@ runs: working-directory: ${{ inputs.WorkingDirectory }} env: GH_TOKEN: ${{ env.GH_TOKEN }} - GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }} PSMODULE_PUBLISH_PSMODULE_INPUT_Name: ${{ inputs.Name }} PSMODULE_PUBLISH_PSMODULE_INPUT_ModulePath: ${{ inputs.ModulePath }} PSMODULE_PUBLISH_PSMODULE_INPUT_APIKey: ${{ inputs.APIKey }} diff --git a/.github/actions/Resolve-PSModuleVersion/action.yml b/.github/actions/Resolve-PSModuleVersion/action.yml index 072f2d47..5192f28f 100644 --- a/.github/actions/Resolve-PSModuleVersion/action.yml +++ b/.github/actions/Resolve-PSModuleVersion/action.yml @@ -66,7 +66,6 @@ runs: working-directory: ${{ inputs.WorkingDirectory }} env: GH_TOKEN: ${{ env.GH_TOKEN }} - GITHUB_TOKEN: ${{ env.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/.github/workflows/Plan.yml b/.github/workflows/Plan.yml index 65e6e48c..19a0d866 100644 --- a/.github/workflows/Plan.yml +++ b/.github/workflows/Plan.yml @@ -99,7 +99,6 @@ jobs: id: Get-Settings env: GH_TOKEN: ${{ steps.App-Token.outputs.token }} - GITHUB_TOKEN: ${{ steps.App-Token.outputs.token }} with: SettingsPath: ${{ inputs.SettingsPath }} Debug: ${{ inputs.Debug }} @@ -114,7 +113,6 @@ jobs: id: Resolve-Version env: GH_TOKEN: ${{ steps.App-Token.outputs.token }} - GITHUB_TOKEN: ${{ steps.App-Token.outputs.token }} with: Settings: ${{ steps.Get-Settings.outputs.Settings }} Name: ${{ fromJson(steps.Get-Settings.outputs.Settings).Name }} diff --git a/.github/workflows/Publish-Module.yml b/.github/workflows/Publish-Module.yml index 81d02fe7..3b54e6b6 100644 --- a/.github/workflows/Publish-Module.yml +++ b/.github/workflows/Publish-Module.yml @@ -55,7 +55,6 @@ jobs: uses: ./_wf/.github/actions/Publish-PSModule env: GH_TOKEN: ${{ steps.App-Token.outputs.token }} - GITHUB_TOKEN: ${{ steps.App-Token.outputs.token }} with: Name: ${{ fromJson(inputs.Settings).Name }} ModulePath: outputs/module @@ -71,7 +70,6 @@ jobs: uses: ./_wf/.github/actions/Cleanup-PSModulePrereleases env: GH_TOKEN: ${{ steps.App-Token.outputs.token }} - GITHUB_TOKEN: ${{ steps.App-Token.outputs.token }} with: WhatIf: ${{ github.repository == 'PSModule/Process-PSModule' }} AutoCleanup: ${{ fromJson(inputs.Settings).Publish.Module.AutoCleanup }} diff --git a/README.md b/README.md index 052b35b1..2773f83d 100644 --- a/README.md +++ b/README.md @@ -30,4 +30,4 @@ jobs: GitHubAppPrivateKey: ${{ secrets.PSMODULE_PRIVATE_KEY }} ``` -This is a required contract for GitHub operations in the reusable workflow path; `github.token` fallback is intentionally not used. +This is a required contract for GitHub operations in the reusable workflow path; a GitHub App installation token is minted and used for those steps via `GH_TOKEN`, and `github.token` fallback is intentionally not used. From 3b4410a3f6b6a5fdd7c5d1c812a0125f091f22ba Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 21:19:24 +0200 Subject: [PATCH 09/23] Use GitHub App token in Build-Module workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mint an installation token in Build-Module.yml (same pinned actions/create-github-app-token@fee1f7d... as Plan and Publish-Module) and inject it as GH_TOKEN on the Build-PSModule step. This covers the three gh repo view calls in Build-PSModuleManifest.ps1 that read repo description, topics, and URL — all of which go through the gh CLI and therefore consume GH_TOKEN. The job-level GH_TOKEN: github.token fallback is removed. workflow.yml is updated to pass the GitHubAppClientId and GitHubAppPrivateKey secrets into the Build-Module reusable workflow. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Build-Module.yml | 18 ++++++++++++++++-- .github/workflows/workflow.yml | 3 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Build-Module.yml b/.github/workflows/Build-Module.yml index 411d7ed6..e8e77495 100644 --- a/.github/workflows/Build-Module.yml +++ b/.github/workflows/Build-Module.yml @@ -2,6 +2,13 @@ name: Build-Module on: workflow_call: + secrets: + GitHubAppClientId: + description: The client ID of the GitHub App used for repository API calls. + required: true + GitHubAppPrivateKey: + description: The private key of the GitHub App used for repository API calls. + required: true inputs: Settings: type: string @@ -20,8 +27,6 @@ jobs: Build-Module: name: Build-Module runs-on: ubuntu-latest - env: - GH_TOKEN: ${{ github.token }} steps: - name: Checkout Code uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -37,8 +42,17 @@ jobs: path: _wf persist-credentials: false + - name: Create GitHub App token + id: App-Token + uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2 + with: + app-id: ${{ secrets.GitHubAppClientId }} + private-key: ${{ secrets.GitHubAppPrivateKey }} + - name: Build module uses: ./_wf/.github/actions/Build-PSModule + env: + GH_TOKEN: ${{ steps.App-Token.outputs.token }} with: Name: ${{ fromJson(inputs.Settings).Name }} Version: ${{ fromJson(inputs.Settings).Publish.Module.Resolution.Version != '' && fromJson(inputs.Settings).Publish.Module.Resolution.Version || '999.0.0' }} diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 789bef75..4cea1a27 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -116,6 +116,9 @@ jobs: Build-Module: if: fromJson(needs.Plan.outputs.Settings).Build.Module.Enabled uses: ./.github/workflows/Build-Module.yml + secrets: + GitHubAppClientId: ${{ secrets.GitHubAppClientId }} + GitHubAppPrivateKey: ${{ secrets.GitHubAppPrivateKey }} needs: - Plan with: From 61be8788130af699d70e3cacb6f51e62746f6adb Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Thu, 23 Jul 2026 21:55:00 +0200 Subject: [PATCH 10/23] Scope GitHub App tokens to repo and minimum permissions Each token-minting step now requests only the permissions the job actually exercises and restricts the token to the current repository. Plan: repositories: current repo permission-contents: read (gh release list in Resolve-Version) permission-pull-requests: write (label/comment via Get-PSModuleSettings) Publish-Module: repositories: current repo permission-contents: write (gh release create/upload/delete) permission-pull-requests: write (gh pr comment) Build-Module: repositories: current repo (no permission-* needed - only gh repo view which uses metadata:read, auto-granted to all GitHub App installations) This limits blast radius: even if a compromised step obtained GH_TOKEN, it could only act on the one repository and only with the declared permission level, not on every repo in the installation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Build-Module.yml | 1 + .github/workflows/Plan.yml | 3 +++ .github/workflows/Publish-Module.yml | 3 +++ 3 files changed, 7 insertions(+) diff --git a/.github/workflows/Build-Module.yml b/.github/workflows/Build-Module.yml index e8e77495..360c2797 100644 --- a/.github/workflows/Build-Module.yml +++ b/.github/workflows/Build-Module.yml @@ -48,6 +48,7 @@ jobs: with: app-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} + repositories: ${{ github.event.repository.name }} - name: Build module uses: ./_wf/.github/actions/Build-PSModule diff --git a/.github/workflows/Plan.yml b/.github/workflows/Plan.yml index 19a0d866..d57300d8 100644 --- a/.github/workflows/Plan.yml +++ b/.github/workflows/Plan.yml @@ -93,6 +93,9 @@ jobs: with: app-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} + repositories: ${{ github.event.repository.name }} + permission-contents: read + permission-pull-requests: write - name: Get-Settings uses: ./_wf/.github/actions/Get-PSModuleSettings diff --git a/.github/workflows/Publish-Module.yml b/.github/workflows/Publish-Module.yml index 3b54e6b6..757e1c9e 100644 --- a/.github/workflows/Publish-Module.yml +++ b/.github/workflows/Publish-Module.yml @@ -49,6 +49,9 @@ jobs: with: app-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} + repositories: ${{ github.event.repository.name }} + permission-contents: write + permission-pull-requests: write - name: Publish module if: fromJson(inputs.Settings).Publish.Module.Resolution.ReleaseType != 'None' From 806a892b2d6f503566a9796268cb942114668e15 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 13:32:46 +0200 Subject: [PATCH 11/23] Use Shelly credentials in workflow callers Map Shelly's repository secrets into the generic GitHub App reusable-workflow contract in the test callers and documented example. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Workflow-Test-Default.yml | 4 ++-- .github/workflows/Workflow-Test-WithManifest.yml | 4 ++-- README.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Workflow-Test-Default.yml b/.github/workflows/Workflow-Test-Default.yml index 511cb0fa..e5bade50 100644 --- a/.github/workflows/Workflow-Test-Default.yml +++ b/.github/workflows/Workflow-Test-Default.yml @@ -31,8 +31,8 @@ jobs: uses: ./.github/workflows/workflow.yml secrets: APIKey: ${{ secrets.APIKey }} - GitHubAppClientId: ${{ secrets.PSMODULE_CLIENT_ID }} - GitHubAppPrivateKey: ${{ secrets.PSMODULE_PRIVATE_KEY }} + GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} TestData: >- { "secrets": { diff --git a/.github/workflows/Workflow-Test-WithManifest.yml b/.github/workflows/Workflow-Test-WithManifest.yml index 5798fde8..accc4287 100644 --- a/.github/workflows/Workflow-Test-WithManifest.yml +++ b/.github/workflows/Workflow-Test-WithManifest.yml @@ -31,8 +31,8 @@ jobs: uses: ./.github/workflows/workflow.yml secrets: APIKey: ${{ secrets.APIKey }} - GitHubAppClientId: ${{ secrets.PSMODULE_CLIENT_ID }} - GitHubAppPrivateKey: ${{ secrets.PSMODULE_PRIVATE_KEY }} + GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} TestData: >- { "secrets": { diff --git a/README.md b/README.md index 39925938..128c37ba 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ jobs: ProcessPSModule: uses: ./.github/workflows/workflow.yml secrets: - GitHubAppClientId: ${{ secrets.PSMODULE_CLIENT_ID }} - GitHubAppPrivateKey: ${{ secrets.PSMODULE_PRIVATE_KEY }} + GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` This is a required contract for GitHub operations in the reusable workflow path; a GitHub App installation token is minted and used for those steps via `GH_TOKEN`, and `github.token` fallback is intentionally not used. From 1fdefd1b22334a166dc442e953ee90343d54d5ce Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 13:34:08 +0200 Subject: [PATCH 12/23] =?UTF-8?q?=F0=9F=93=96=20[Docs]:=20Document=20GitHu?= =?UTF-8?q?b=20App=20authentication=20(#456)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - port the durable GitHub App authentication guidance into the Process-PSModule canonical docs tree - document the required `GitHubAppClientId` / `GitHubAppPrivateKey` reusable-workflow boundary and caller mapping - document the Plan, Build-Module, and Publish-Module repository scope, minimum permissions, and step-scoped `GH_TOKEN` injection implemented by #408 ## Stack - Stacked on #408 (`github-app-planning`) ## Validation - `git diff --check` --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/linters/.markdown-lint.yml | 2 +- .github/workflows/Build-Module.yml | 1 + README.md | 2 + .../guides/github-app-authentication.md | 81 +++++++++++++++++++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 docs/content/guides/github-app-authentication.md diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml index 4110266d..92aacaf6 100644 --- a/.github/linters/.markdown-lint.yml +++ b/.github/linters/.markdown-lint.yml @@ -12,7 +12,7 @@ MD004: false # Unordered list style MD007: indent: 2 # Unordered list indentation MD013: - line_length: 3000 # Line length +line_length: 3000 # Line length MD025: false # Allow front-matter title + visible H1 on docs pages MD026: punctuation: '.,;:!。,;:' # List of not allowed diff --git a/.github/workflows/Build-Module.yml b/.github/workflows/Build-Module.yml index 37af18f3..1924f2a3 100644 --- a/.github/workflows/Build-Module.yml +++ b/.github/workflows/Build-Module.yml @@ -48,6 +48,7 @@ jobs: app-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} repositories: ${{ github.event.repository.name }} + permission-metadata: read - name: Build module uses: ./_wf/.github/actions/Build-PSModule diff --git a/README.md b/README.md index 128c37ba..385bafef 100644 --- a/README.md +++ b/README.md @@ -31,3 +31,5 @@ jobs: ``` This is a required contract for GitHub operations in the reusable workflow path; a GitHub App installation token is minted and used for those steps via `GH_TOKEN`, and `github.token` fallback is intentionally not used. + +See the [GitHub App authentication guide](https://psmodule.io/docs/guides/github-app-authentication/) for the caller mapping, per-workflow permissions and repository scoping, and token injection details. diff --git a/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md new file mode 100644 index 00000000..e600e6aa --- /dev/null +++ b/docs/content/guides/github-app-authentication.md @@ -0,0 +1,81 @@ +--- +title: GitHub App authentication +description: Configure the GitHub App secrets and understand token scope and injection in Process-PSModule workflows. +--- + +# GitHub App authentication + +The repository API operations in the Plan, Build-Module, and Publish-Module workflows use short-lived GitHub App +installation tokens. These workflows do not use `github.token` as a fallback for those operations. + +## Caller secret contract + +The reusable workflow declares two required secrets at its `workflow_call` boundary: + +| Name | Purpose | +| --- | --- | +| `GitHubAppClientId` | The GitHub App client ID passed to the token action. | +| `GitHubAppPrivateKey` | The GitHub App private key passed to the token action. | + +The names are the reusable workflow contract, not a requirement for the caller's repository or organization secret +names. Map the caller's secrets explicitly: + +```yaml +jobs: + Process-PSModule: + uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 + secrets: + APIKey: ${{ secrets.APIKey }} + GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} +``` + +The root reusable workflow forwards these two values to the Plan, Build-Module, and Publish-Module reusable jobs. +Do not use `secrets: inherit` as a substitute for this mapping. + +## Token scope + +Each job mints its own token with the repository that triggered the workflow: +`${{ github.event.repository.name }}`. + +| Workflow | Requested repository permissions | GitHub operations | +| --- | --- | --- | +| Plan | `contents: read`, `pull-requests: write` | Read repository settings and version data, inspect pull-request files and labels, and write planning comments or labels. | +| Build-Module | `metadata: read` | Read repository metadata while building the module manifest. | +| Publish-Module | `contents: write`, `pull-requests: write` | Create and upload releases, write pull-request comments, and clean up prereleases. | + +The GitHub App installation must grant the permissions requested by each job. Keep the installation and token scope +limited to the repository set required by the workflow; add broader repository access only when a workflow explicitly +needs cross-repository operations. + +The scopes have separate ceilings: + +- `permissions:` on the caller workflow controls the default `github.token`; it does not expand an App installation + token. +- The App installation permissions are the maximum permissions any token from that installation can receive. +- The `repositories` input limits the repositories available to the minted token. +- Each `permission-` input requests only the subset needed by that job. + +## Token injection + +The token action is pinned and exposes its output only to the steps that need GitHub API access: + +```yaml +- name: Create GitHub App token + id: App-Token + uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2 + with: + app-id: ${{ secrets.GitHubAppClientId }} + private-key: ${{ secrets.GitHubAppPrivateKey }} + repositories: ${{ github.event.repository.name }} + permission-metadata: read + +- name: Use the token + env: + GH_TOKEN: ${{ steps.App-Token.outputs.token }} + run: gh repo view +``` + +Process-PSModule does not set this token as a job-wide environment variable. It injects `GH_TOKEN` on the Get-Settings +and Resolve-Version steps in Plan, the Build-PSModule step in Build-Module, and the Publish-PSModule and cleanup steps +in Publish-Module. Keep GitHub App tokens step-scoped when adding new API calls. From a605ffe8c2f373e48c306750e75bb72daa22649b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 14:25:41 +0200 Subject: [PATCH 13/23] Complete GitHub App caller contract Route the release action through Shelly's scoped installation token and update every canonical workflow example for the required GitHub App secrets. Document the separate Dependabot secret requirement. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Publish-Module.yml | 2 +- docs/content/get-started/repository-setup.md | 2 ++ docs/content/guides/calling-the-workflow.md | 13 ++++++++++--- docs/content/guides/github-app-authentication.md | 4 ++++ docs/content/reference/repository-standard.md | 2 ++ docs/content/reference/workflow-inputs.md | 4 +++- 6 files changed, 22 insertions(+), 5 deletions(-) diff --git a/.github/workflows/Publish-Module.yml b/.github/workflows/Publish-Module.yml index bf9d6ff7..ed8d0181 100644 --- a/.github/workflows/Publish-Module.yml +++ b/.github/workflows/Publish-Module.yml @@ -70,7 +70,7 @@ jobs: if: always() && !cancelled() && fromJson(inputs.Settings).Publish.Module.Resolution.ReleaseType != 'None' uses: ./_wf/.github/actions/Release-PSModule env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.App-Token.outputs.token }} with: Name: ${{ fromJson(inputs.Settings).Name }} ModulePath: outputs/module diff --git a/docs/content/get-started/repository-setup.md b/docs/content/get-started/repository-setup.md index e4ee047c..68878c69 100644 --- a/docs/content/get-started/repository-setup.md +++ b/docs/content/get-started/repository-setup.md @@ -64,6 +64,8 @@ jobs: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 secrets: APIKey: ${{ secrets.APIKey }} + GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` Every permission in that block is required. See [Workflow inputs](../reference/workflow-inputs.md) for what each one is diff --git a/docs/content/guides/calling-the-workflow.md b/docs/content/guides/calling-the-workflow.md index b420c742..2d903ac3 100644 --- a/docs/content/guides/calling-the-workflow.md +++ b/docs/content/guides/calling-the-workflow.md @@ -47,16 +47,19 @@ jobs: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 secrets: APIKey: ${{ secrets.APIKey }} + GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` ## Passing test data -The reusable workflow at `.github/workflows/workflow.yml` declares only two workflow-call secrets, +The reusable workflow at `.github/workflows/workflow.yml` declares four workflow-call secrets, which keeps the calling workflow in full control of the credentials that are exposed. -`secrets: inherit` is intentionally not required. `APIKey` publishes to the PowerShell Gallery; `TestData` carries -everything the module's own tests need. +`secrets: inherit` is intentionally not required. `APIKey` publishes to the PowerShell Gallery, +`GitHubAppClientId` and `GitHubAppPrivateKey` authenticate GitHub API operations, and `TestData` +carries everything the module's own tests need. ### Breaking change: fixed test secrets use `TestData` @@ -80,6 +83,8 @@ jobs: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 secrets: APIKey: ${{ secrets.APIKey }} + GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} TestData: >- { "secrets": { "TEST_USER_PAT": "${{ secrets.TEST_USER_PAT }}", "TEST_APP_ORG_CLIENT_ID": "${{ secrets.TEST_APP_ORG_CLIENT_ID }}" } } @@ -107,6 +112,8 @@ jobs: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 secrets: APIKey: ${{ secrets.APIKey }} + GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} TestData: >- { "secrets": { "CONFLUENCE_API_TOKEN": "${{ secrets.CONFLUENCE_API_TOKEN }}" }, "variables": { "CONFLUENCE_SITE": ${{ toJSON(vars.CONFLUENCE_SITE) }}, diff --git a/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md index e600e6aa..509dedbe 100644 --- a/docs/content/guides/github-app-authentication.md +++ b/docs/content/guides/github-app-authentication.md @@ -33,6 +33,10 @@ jobs: The root reusable workflow forwards these two values to the Plan, Build-Module, and Publish-Module reusable jobs. Do not use `secrets: inherit` as a substitute for this mapping. +For Dependabot pull requests, create `SHELLY_CLIENT_ID` and `SHELLY_PRIVATE_KEY` as Dependabot secrets as well as +Actions secrets. Dependabot-triggered workflows cannot read regular Actions secrets, so the GitHub App token cannot +be minted without separate Dependabot secret values. + ## Token scope Each job mints its own token with the repository that triggered the workflow: diff --git a/docs/content/reference/repository-standard.md b/docs/content/reference/repository-standard.md index dde5a31c..a0dce9f4 100644 --- a/docs/content/reference/repository-standard.md +++ b/docs/content/reference/repository-standard.md @@ -125,6 +125,8 @@ jobs: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@ # secrets: APIKey: ${{ secrets.APIKEY }} + GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` Name the caller file `Process-PSModule.yml`, matching [`PSModule/Template-PSModule`](https://github.com/PSModule/Template-PSModule) and every existing module repository. `workflow.yml` is the reusable workflow's own filename inside `PSModule/Process-PSModule` and belongs only in the `uses:` reference. Pin the reference to a commit SHA with the version tag in a trailing comment so Dependabot can update it. diff --git a/docs/content/reference/workflow-inputs.md b/docs/content/reference/workflow-inputs.md index 1e433413..45d02a4d 100644 --- a/docs/content/reference/workflow-inputs.md +++ b/docs/content/reference/workflow-inputs.md @@ -23,12 +23,14 @@ interface it exposes to a caller workflow. For how to wire it up, see ## Secrets -The workflow declares only two workflow-call secrets, which keeps the calling workflow in full control of the +The workflow declares four workflow-call secrets, which keeps the calling workflow in full control of the credentials that are exposed. `secrets: inherit` is intentionally not required. | Name | Location | Description | Required | | ---- | -------- | ----------- | -------- | | `APIKey` | GitHub secrets | The API key for the PowerShell Gallery, used to publish the module. | Yes | +| `GitHubAppClientId` | GitHub secrets | The GitHub App client ID used to mint scoped installation tokens for GitHub API operations. Map Shelly's `SHELLY_CLIENT_ID` in the caller. | Yes | +| `GitHubAppPrivateKey` | GitHub secrets | The GitHub App private key used to mint scoped installation tokens for GitHub API operations. Map Shelly's `SHELLY_PRIVATE_KEY` in the caller. | Yes | | `TestData` | GitHub secrets | A single-line JSON object with `secrets` and `variables` maps, exposed as environment variables to the module test jobs. Values under `secrets` are masked; values under `variables` are not. | No | See [passing test data](../guides/calling-the-workflow.md#passing-test-data) for how to build the `TestData` value. From d88e264e0d9ef1e471b943df249ce2bf7156963d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 14:37:55 +0200 Subject: [PATCH 14/23] Document Shelly permission baseline Distinguish the GitHub App installation permissions from caller github.token permissions and document the Dependabot private-key trust boundary. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../guides/github-app-authentication.md | 27 ++++++++++++++++--- docs/content/reference/workflow-inputs.md | 12 +++++++-- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md index 509dedbe..d9d48c7b 100644 --- a/docs/content/guides/github-app-authentication.md +++ b/docs/content/guides/github-app-authentication.md @@ -33,11 +33,30 @@ jobs: The root reusable workflow forwards these two values to the Plan, Build-Module, and Publish-Module reusable jobs. Do not use `secrets: inherit` as a substitute for this mapping. -For Dependabot pull requests, create `SHELLY_CLIENT_ID` and `SHELLY_PRIVATE_KEY` as Dependabot secrets as well as -Actions secrets. Dependabot-triggered workflows cannot read regular Actions secrets, so the GitHub App token cannot -be minted without separate Dependabot secret values. +Dependabot-triggered workflows cannot read regular Actions secrets. Do not duplicate Shelly's private key into +Dependabot secrets by default: a compromised dependency update could alter workflow code that receives the key before +human review. If an organization requires the Process-PSModule workflow to run on Dependabot pull requests, its +security owners must explicitly accept that trust boundary and provision separate Dependabot secrets. Otherwise, +skip token-consuming jobs for Dependabot pull requests and run the full workflow after review or merge. -## Token scope +## GitHub App installation permissions + +Install Shelly only on repositories that the process must manage. The complete permission baseline for the current +Process-PSModule GitHub App path is: + +| Repository permission | Access | Why it is needed | +| --- | --- | --- | +| Contents | Write | Read releases during version resolution; create, upload to, and delete releases during publish and cleanup. | +| Pull requests | Write | Read pull-request files and labels; add process and release comments to pull requests. | +| Metadata | Read | Read repository description, topics, and URL while building the module manifest. This permission is granted automatically to GitHub Apps. | + +Do not grant Shelly Actions, Issues, Statuses, Pages, Workflows, or administration permissions for the current +Process-PSModule GitHub App path. Those permissions are not used by installation tokens minted here. + +The caller workflow's `permissions:` block is separate: it scopes only `github.token` for non-App operations such as +artifact handling, linting, and Pages deployment. It cannot expand or restrict Shelly's installation token. + +## Per-workflow token scope Each job mints its own token with the repository that triggered the workflow: `${{ github.event.repository.name }}`. diff --git a/docs/content/reference/workflow-inputs.md b/docs/content/reference/workflow-inputs.md index 45d02a4d..bcc784c3 100644 --- a/docs/content/reference/workflow-inputs.md +++ b/docs/content/reference/workflow-inputs.md @@ -35,9 +35,10 @@ credentials that are exposed. `secrets: inherit` is intentionally not required. See [passing test data](../guides/calling-the-workflow.md#passing-test-data) for how to build the `TestData` value. -## Permissions +## Workflow `github.token` permissions -The following permissions are needed for the workflow to be able to perform all tasks. +The following permissions are needed by the caller workflow's default `github.token` for operations that do not use +Shelly, such as linting and GitHub Pages deployment: ```yaml permissions: @@ -49,3 +50,10 @@ permissions: ``` For more info, see [Deploy GitHub Pages site](https://github.com/marketplace/actions/deploy-github-pages-site). + +## GitHub App permissions + +The `permissions:` block above does not apply to Shelly's installation tokens. Shelly needs only the repository +permissions documented in [GitHub App authentication](../guides/github-app-authentication.md#github-app-installation-permissions): +Contents: write, Pull requests: write, and automatically granted Metadata: read. Each job requests a smaller, +repository-scoped subset when it mints its token. From bb66b8fcda0e087c1e96a90f175a33f484421982 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 14:45:17 +0200 Subject: [PATCH 15/23] Require Shelly Dependabot secrets Document the required Dependabot secret mappings and their pre-review trust boundary. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/content/guides/github-app-authentication.md | 9 ++++----- docs/content/reference/workflow-inputs.md | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md index d9d48c7b..98be4017 100644 --- a/docs/content/guides/github-app-authentication.md +++ b/docs/content/guides/github-app-authentication.md @@ -33,11 +33,10 @@ jobs: The root reusable workflow forwards these two values to the Plan, Build-Module, and Publish-Module reusable jobs. Do not use `secrets: inherit` as a substitute for this mapping. -Dependabot-triggered workflows cannot read regular Actions secrets. Do not duplicate Shelly's private key into -Dependabot secrets by default: a compromised dependency update could alter workflow code that receives the key before -human review. If an organization requires the Process-PSModule workflow to run on Dependabot pull requests, its -security owners must explicitly accept that trust boundary and provision separate Dependabot secrets. Otherwise, -skip token-consuming jobs for Dependabot pull requests and run the full workflow after review or merge. +Dependabot-triggered workflows cannot read regular Actions secrets. To run Process-PSModule on Dependabot pull +requests, create `SHELLY_CLIENT_ID` and `SHELLY_PRIVATE_KEY` as Dependabot secrets in addition to Actions secrets. +This is a deliberate trust boundary: review the App's installation scope and every dependency update carefully, +because the workflow can mint a Shelly token before human review. ## GitHub App installation permissions diff --git a/docs/content/reference/workflow-inputs.md b/docs/content/reference/workflow-inputs.md index bcc784c3..e8c5af24 100644 --- a/docs/content/reference/workflow-inputs.md +++ b/docs/content/reference/workflow-inputs.md @@ -29,8 +29,8 @@ credentials that are exposed. `secrets: inherit` is intentionally not required. | Name | Location | Description | Required | | ---- | -------- | ----------- | -------- | | `APIKey` | GitHub secrets | The API key for the PowerShell Gallery, used to publish the module. | Yes | -| `GitHubAppClientId` | GitHub secrets | The GitHub App client ID used to mint scoped installation tokens for GitHub API operations. Map Shelly's `SHELLY_CLIENT_ID` in the caller. | Yes | -| `GitHubAppPrivateKey` | GitHub secrets | The GitHub App private key used to mint scoped installation tokens for GitHub API operations. Map Shelly's `SHELLY_PRIVATE_KEY` in the caller. | Yes | +| `GitHubAppClientId` | GitHub secrets | The GitHub App client ID used to mint scoped installation tokens for GitHub API operations. Map Shelly's `SHELLY_CLIENT_ID` in the caller and Dependabot secret store. | Yes | +| `GitHubAppPrivateKey` | GitHub secrets | The GitHub App private key used to mint scoped installation tokens for GitHub API operations. Map Shelly's `SHELLY_PRIVATE_KEY` in the caller and Dependabot secret store. | Yes | | `TestData` | GitHub secrets | A single-line JSON object with `secrets` and `variables` maps, exposed as environment variables to the module test jobs. Values under `secrets` are masked; values under `variables` are not. | No | See [passing test data](../guides/calling-the-workflow.md#passing-test-data) for how to build the `TestData` value. From 9a654b887410d75b099d928ba0d10674396ec4f6 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 14:55:54 +0200 Subject: [PATCH 16/23] Rename PowerShell Gallery workflow credential Replace the ambiguous APIKey workflow secret with PSGALLERY_API_KEY across the reusable workflow contract, test callers, and documentation. Keep the Publish-PSModule action input unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/Publish-PSModule/README.md | 2 +- .github/workflows/Publish-Module.yml | 4 ++-- .github/workflows/Workflow-Test-Default.yml | 2 +- .github/workflows/Workflow-Test-WithManifest.yml | 2 +- .github/workflows/workflow.yml | 4 ++-- README.md | 6 ++++-- docs/content/get-started/repository-setup.md | 4 ++-- docs/content/guides/calling-the-workflow.md | 6 +++--- docs/content/guides/github-app-authentication.md | 2 +- docs/content/reference/repository-standard.md | 2 +- docs/content/reference/workflow-inputs.md | 2 +- 11 files changed, 19 insertions(+), 17 deletions(-) diff --git a/.github/actions/Publish-PSModule/README.md b/.github/actions/Publish-PSModule/README.md index 1a24f4f4..a0ed6a8e 100644 --- a/.github/actions/Publish-PSModule/README.md +++ b/.github/actions/Publish-PSModule/README.md @@ -26,7 +26,7 @@ This action does not provide outputs. Name: ExampleModule ModulePath: outputs/module ArtifactName: module - APIKey: ${{ secrets.APIKEY }} + APIKey: ${{ secrets.PSGALLERY_API_KEY }} ``` Use [Release-PSModule](../Release-PSModule/README.md) in a separate workflow step to create the GitHub release from the same artifact. diff --git a/.github/workflows/Publish-Module.yml b/.github/workflows/Publish-Module.yml index ed8d0181..ad622b7c 100644 --- a/.github/workflows/Publish-Module.yml +++ b/.github/workflows/Publish-Module.yml @@ -3,7 +3,7 @@ name: Publish-Module on: workflow_call: secrets: - APIKey: + PSGALLERY_API_KEY: description: The API key for the PowerShell Gallery. required: true GitHubAppClientId: @@ -61,7 +61,7 @@ jobs: with: Name: ${{ fromJson(inputs.Settings).Name }} ModulePath: outputs/module - APIKey: ${{ secrets.APIKey }} + APIKey: ${{ secrets.PSGALLERY_API_KEY }} WhatIf: ${{ github.repository == 'PSModule/Process-PSModule' }} WorkingDirectory: ${{ fromJson(inputs.Settings).WorkingDirectory }} diff --git a/.github/workflows/Workflow-Test-Default.yml b/.github/workflows/Workflow-Test-Default.yml index e5bade50..03ed7cfa 100644 --- a/.github/workflows/Workflow-Test-Default.yml +++ b/.github/workflows/Workflow-Test-Default.yml @@ -30,7 +30,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} uses: ./.github/workflows/workflow.yml secrets: - APIKey: ${{ secrets.APIKey }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} TestData: >- diff --git a/.github/workflows/Workflow-Test-WithManifest.yml b/.github/workflows/Workflow-Test-WithManifest.yml index accc4287..0340f329 100644 --- a/.github/workflows/Workflow-Test-WithManifest.yml +++ b/.github/workflows/Workflow-Test-WithManifest.yml @@ -30,7 +30,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} uses: ./.github/workflows/workflow.yml secrets: - APIKey: ${{ secrets.APIKey }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} TestData: >- diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 4cea1a27..32de93a0 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -3,7 +3,7 @@ name: Process-PSModule on: workflow_call: secrets: - APIKey: + PSGALLERY_API_KEY: description: The API key for the PowerShell Gallery. required: true GitHubAppClientId: @@ -257,7 +257,7 @@ jobs: if: fromJson(needs.Plan.outputs.Settings).Publish.Module.Enabled && needs.Plan.result == 'success' && !cancelled() && (needs.Get-TestResults.result == 'success' || needs.Get-TestResults.result == 'skipped') && (needs.Get-CodeCoverage.result == 'success' || needs.Get-CodeCoverage.result == 'skipped') && (needs.Build-Site.result == 'success' || needs.Build-Site.result == 'skipped') uses: ./.github/workflows/Publish-Module.yml secrets: - APIKey: ${{ secrets.APIKey }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.GitHubAppClientId }} GitHubAppPrivateKey: ${{ secrets.GitHubAppPrivateKey }} needs: diff --git a/README.md b/README.md index 385bafef..859e7c46 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,9 @@ It covers getting started, the pipeline stages, usage, configuration, repository ## Reusable workflow secrets (GitHub App auth) -When calling `./.github/workflows/workflow.yml`, pass GitHub App credentials using these generic reusable-workflow secret names: +When calling `./.github/workflows/workflow.yml`, pass the PowerShell Gallery API key and GitHub App credentials using these reusable-workflow secret names: +- `PSGALLERY_API_KEY` - `GitHubAppClientId` - `GitHubAppPrivateKey` @@ -26,10 +27,11 @@ jobs: ProcessPSModule: uses: ./.github/workflows/workflow.yml secrets: + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` -This is a required contract for GitHub operations in the reusable workflow path; a GitHub App installation token is minted and used for those steps via `GH_TOKEN`, and `github.token` fallback is intentionally not used. +This is a required contract. `PSGALLERY_API_KEY` publishes the module to the PowerShell Gallery; the GitHub App credentials mint an installation token for GitHub operations via `GH_TOKEN`, with no `github.token` fallback in that path. This is a breaking rename from the previous `APIKey`/`APIKEY` workflow secret. See the [GitHub App authentication guide](https://psmodule.io/docs/guides/github-app-authentication/) for the caller mapping, per-workflow permissions and repository scoping, and token injection details. diff --git a/docs/content/get-started/repository-setup.md b/docs/content/get-started/repository-setup.md index 68878c69..7b6c9edd 100644 --- a/docs/content/get-started/repository-setup.md +++ b/docs/content/get-started/repository-setup.md @@ -22,7 +22,7 @@ This creates an environment called `github-pages` that GitHub deploys the docume 1. [Create an API key on the PowerShell Gallery](https://www.powershellgallery.com/account/apikeys). Give it permission to manage the module you are working on. -2. Create a repository secret called `APIKEY` and set the API key as its value. +2. Create a repository secret called `PSGALLERY_API_KEY` and set the API key as its value. If you plan to create many modules, use a glob pattern for the API key permissions in the PowerShell Gallery and store the secret on the organization instead of on each repository. @@ -63,7 +63,7 @@ jobs: Process-PSModule: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 secrets: - APIKey: ${{ secrets.APIKey }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` diff --git a/docs/content/guides/calling-the-workflow.md b/docs/content/guides/calling-the-workflow.md index 2d903ac3..5839b284 100644 --- a/docs/content/guides/calling-the-workflow.md +++ b/docs/content/guides/calling-the-workflow.md @@ -46,7 +46,7 @@ jobs: Process-PSModule: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 secrets: - APIKey: ${{ secrets.APIKey }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` @@ -82,7 +82,7 @@ jobs: Process-PSModule: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 secrets: - APIKey: ${{ secrets.APIKey }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} TestData: >- @@ -111,7 +111,7 @@ jobs: Process-PSModule: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 secrets: - APIKey: ${{ secrets.APIKey }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} TestData: >- diff --git a/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md index 98be4017..7d104525 100644 --- a/docs/content/guides/github-app-authentication.md +++ b/docs/content/guides/github-app-authentication.md @@ -25,7 +25,7 @@ jobs: Process-PSModule: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5 secrets: - APIKey: ${{ secrets.APIKey }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` diff --git a/docs/content/reference/repository-standard.md b/docs/content/reference/repository-standard.md index a0dce9f4..dbe7a6d0 100644 --- a/docs/content/reference/repository-standard.md +++ b/docs/content/reference/repository-standard.md @@ -124,7 +124,7 @@ jobs: Process-PSModule: uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@ # secrets: - APIKey: ${{ secrets.APIKEY }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` diff --git a/docs/content/reference/workflow-inputs.md b/docs/content/reference/workflow-inputs.md index e8c5af24..dd290c06 100644 --- a/docs/content/reference/workflow-inputs.md +++ b/docs/content/reference/workflow-inputs.md @@ -28,7 +28,7 @@ credentials that are exposed. `secrets: inherit` is intentionally not required. | Name | Location | Description | Required | | ---- | -------- | ----------- | -------- | -| `APIKey` | GitHub secrets | The API key for the PowerShell Gallery, used to publish the module. | Yes | +| `PSGALLERY_API_KEY` | GitHub secrets | The API key for the PowerShell Gallery, used to publish the module. | Yes | | `GitHubAppClientId` | GitHub secrets | The GitHub App client ID used to mint scoped installation tokens for GitHub API operations. Map Shelly's `SHELLY_CLIENT_ID` in the caller and Dependabot secret store. | Yes | | `GitHubAppPrivateKey` | GitHub secrets | The GitHub App private key used to mint scoped installation tokens for GitHub API operations. Map Shelly's `SHELLY_PRIVATE_KEY` in the caller and Dependabot secret store. | Yes | | `TestData` | GitHub secrets | A single-line JSON object with `secrets` and `variables` maps, exposed as environment variables to the module test jobs. Values under `secrets` are masked; values under `variables` are not. | No | From 258aaefaf838bf73fe05e15d4b2334c910b2a271 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 15:00:14 +0200 Subject: [PATCH 17/23] Use GitHub App client IDs for token minting Upgrade create-github-app-token to pinned v3 and use its client-id input, matching the reusable workflow credential contract. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Build-Module.yml | 4 ++-- .github/workflows/Plan.yml | 4 ++-- .github/workflows/Publish-Module.yml | 4 ++-- docs/content/guides/github-app-authentication.md | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/Build-Module.yml b/.github/workflows/Build-Module.yml index 1924f2a3..b92dab5b 100644 --- a/.github/workflows/Build-Module.yml +++ b/.github/workflows/Build-Module.yml @@ -43,9 +43,9 @@ jobs: - name: Create GitHub App token id: App-Token - uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 with: - app-id: ${{ secrets.GitHubAppClientId }} + client-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} repositories: ${{ github.event.repository.name }} permission-metadata: read diff --git a/.github/workflows/Plan.yml b/.github/workflows/Plan.yml index f3f0fd3c..e3a3b06a 100644 --- a/.github/workflows/Plan.yml +++ b/.github/workflows/Plan.yml @@ -88,9 +88,9 @@ jobs: - name: Create GitHub App token id: App-Token - uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 with: - app-id: ${{ secrets.GitHubAppClientId }} + client-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} repositories: ${{ github.event.repository.name }} permission-contents: read diff --git a/.github/workflows/Publish-Module.yml b/.github/workflows/Publish-Module.yml index ad622b7c..db4dd72d 100644 --- a/.github/workflows/Publish-Module.yml +++ b/.github/workflows/Publish-Module.yml @@ -45,9 +45,9 @@ jobs: - name: Create GitHub App token id: App-Token - uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 with: - app-id: ${{ secrets.GitHubAppClientId }} + client-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} repositories: ${{ github.event.repository.name }} permission-contents: write diff --git a/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md index 7d104525..a4bd4c5e 100644 --- a/docs/content/guides/github-app-authentication.md +++ b/docs/content/guides/github-app-authentication.md @@ -85,9 +85,9 @@ The token action is pinned and exposes its output only to the steps that need Gi ```yaml - name: Create GitHub App token id: App-Token - uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 with: - app-id: ${{ secrets.GitHubAppClientId }} + client-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} repositories: ${{ github.event.repository.name }} permission-metadata: read From 3c27c4114be81f9e56da77d1b3fa84a14455935f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 15:18:49 +0200 Subject: [PATCH 18/23] Fix generated documentation lint configuration Nest the Markdown line-length setting under MD013 so Super-Linter applies the repository limit to generated help files. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/linters/.markdown-lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml index 92aacaf6..4110266d 100644 --- a/.github/linters/.markdown-lint.yml +++ b/.github/linters/.markdown-lint.yml @@ -12,7 +12,7 @@ MD004: false # Unordered list style MD007: indent: 2 # Unordered list indentation MD013: -line_length: 3000 # Line length + line_length: 3000 # Line length MD025: false # Allow front-matter title + visible H1 on docs pages MD026: punctuation: '.,;:!。,;:' # List of not allowed From 0ac9a29dab6da288d57942d9e3eaf84d803f2bd9 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 15:33:06 +0200 Subject: [PATCH 19/23] Name PowerShell Gallery credential consistently Make PSGALLERY_API_KEY explicit across Process-PSModule documentation while retaining the Publish-PSModule action input name as APIKey. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/Publish-PSModule/README.md | 2 +- README.md | 4 ++-- docs/content/get-started/index.md | 4 ++-- docs/content/get-started/repository-setup.md | 8 ++++---- docs/content/guides/calling-the-workflow.md | 2 +- docs/content/index.md | 2 +- docs/content/specification/design.md | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/actions/Publish-PSModule/README.md b/.github/actions/Publish-PSModule/README.md index a0ed6a8e..a5b0b9a5 100644 --- a/.github/actions/Publish-PSModule/README.md +++ b/.github/actions/Publish-PSModule/README.md @@ -9,7 +9,7 @@ Publishes a pre-versioned PowerShell module artifact to the PowerShell Gallery. | `Name` | Name of the module to publish. | No | Repository name | | `ModulePath` | Path containing the built `/` module directory. | No | `outputs/module` | | `ArtifactName` | Name of the module artifact to download. | No | `module` | -| `APIKey` | PowerShell Gallery API key. | Yes | N/A | +| `APIKey` | PowerShell Gallery API key supplied from the caller's `PSGALLERY_API_KEY` secret. | Yes | N/A | | `WhatIf` | Logs publishing operations without publishing the module. | No | `false` | | `WorkingDirectory` | Directory where the publishing script runs. | No | `.` | diff --git a/README.md b/README.md index 859e7c46..c37d2ecf 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ It covers getting started, the pipeline stages, usage, configuration, repository ## Reusable workflow secrets (GitHub App auth) -When calling `./.github/workflows/workflow.yml`, pass the PowerShell Gallery API key and GitHub App credentials using these reusable-workflow secret names: +When calling `./.github/workflows/workflow.yml`, pass the PowerShell Gallery credential as `PSGALLERY_API_KEY` and GitHub App credentials using these reusable-workflow secret names: - `PSGALLERY_API_KEY` - `GitHubAppClientId` @@ -32,6 +32,6 @@ jobs: GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} ``` -This is a required contract. `PSGALLERY_API_KEY` publishes the module to the PowerShell Gallery; the GitHub App credentials mint an installation token for GitHub operations via `GH_TOKEN`, with no `github.token` fallback in that path. This is a breaking rename from the previous `APIKey`/`APIKEY` workflow secret. +This is a required contract. `PSGALLERY_API_KEY` publishes the module to the PowerShell Gallery; the GitHub App credentials mint an installation token for GitHub operations via `GH_TOKEN`, with no `github.token` fallback in that path. See the [GitHub App authentication guide](https://psmodule.io/docs/guides/github-app-authentication/) for the caller mapping, per-workflow permissions and repository scoping, and token injection details. diff --git a/docs/content/get-started/index.md b/docs/content/get-started/index.md index 7b4f0b8b..b641b85d 100644 --- a/docs/content/get-started/index.md +++ b/docs/content/get-started/index.md @@ -11,7 +11,7 @@ Start new modules from the PSModule template repository: ## Quickstart 1. [Create a new repository from the template](https://github.com/new?template_name=Template-PSModule&template_owner=PSModule&description=Add%20a%20description%20(required)&name=%3CModule%20name%3E). -2. [Configure the repository](repository-setup.md) — GitHub Pages, the PowerShell Gallery API key, and the caller workflow. +2. [Configure the repository](repository-setup.md) — GitHub Pages, `PSGALLERY_API_KEY`, and the caller workflow. 3. Replace placeholder metadata and remove scaffold sample files. 4. Add your first public command and tests. 5. Validate `.github/PSModule.yml` defaults for your module. @@ -30,7 +30,7 @@ If the module needs several interdependent commands before it is usable at all, | Page | Description | | --- | --- | -| [Repository setup](repository-setup.md) | GitHub Pages, the PowerShell Gallery API key, permissions, and the caller workflow. | +| [Repository setup](repository-setup.md) | GitHub Pages, `PSGALLERY_API_KEY`, permissions, and the caller workflow. | | [Your first release](your-first-release.md) | The pull request flow, version labels, and what happens on merge. | | [Module bootstrap](module-bootstrap.md) | Getting a brand-new module to its first release with an integration branch. | diff --git a/docs/content/get-started/repository-setup.md b/docs/content/get-started/repository-setup.md index 7b6c9edd..821dada5 100644 --- a/docs/content/get-started/repository-setup.md +++ b/docs/content/get-started/repository-setup.md @@ -1,6 +1,6 @@ --- title: Repository setup -description: Configure GitHub Pages, the PowerShell Gallery API key, permissions, and the caller workflow so Process-PSModule can build and publish the module. +description: Configure GitHub Pages, `PSGALLERY_API_KEY`, permissions, and the caller workflow so Process-PSModule can build and publish the module. --- # Repository setup @@ -18,14 +18,14 @@ This creates an environment called `github-pages` that GitHub deploys the docume Remove the branch protection on main -## 2. Create a PowerShell Gallery API key +## 2. Create `PSGALLERY_API_KEY` 1. [Create an API key on the PowerShell Gallery](https://www.powershellgallery.com/account/apikeys). Give it permission to manage the module you are working on. -2. Create a repository secret called `PSGALLERY_API_KEY` and set the API key as its value. +2. Create a repository or organization secret called `PSGALLERY_API_KEY` and set the API key as its value. If you plan to create many modules, use a glob pattern for the API key permissions in the PowerShell Gallery and store -the secret on the organization instead of on each repository. +`PSGALLERY_API_KEY` on the organization instead of on each repository. ## 3. Add the caller workflow diff --git a/docs/content/guides/calling-the-workflow.md b/docs/content/guides/calling-the-workflow.md index 5839b284..799da79e 100644 --- a/docs/content/guides/calling-the-workflow.md +++ b/docs/content/guides/calling-the-workflow.md @@ -57,7 +57,7 @@ jobs: The reusable workflow at `.github/workflows/workflow.yml` declares four workflow-call secrets, which keeps the calling workflow in full control of the credentials that are exposed. -`secrets: inherit` is intentionally not required. `APIKey` publishes to the PowerShell Gallery, +`secrets: inherit` is intentionally not required. `PSGALLERY_API_KEY` publishes to the PowerShell Gallery, `GitHubAppClientId` and `GitHubAppPrivateKey` authenticate GitHub API operations, and `TestData` carries everything the module's own tests need. diff --git a/docs/content/index.md b/docs/content/index.md index 8e126e11..0a63f3b5 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -22,7 +22,7 @@ New to Process-PSModule? Work through these in order. | Page | Description | | --- | --- | | [Get started](get-started/index.md) | Create a module repository from the template and get the pipeline running. | -| [Repository setup](get-started/repository-setup.md) | Configure GitHub Pages, the PowerShell Gallery API key, permissions, and the caller workflow. | +| [Repository setup](get-started/repository-setup.md) | Configure GitHub Pages, `PSGALLERY_API_KEY`, permissions, and the caller workflow. | | [Your first release](get-started/your-first-release.md) | The pull request flow, version labels, and what happens on merge. | ## Guides diff --git a/docs/content/specification/design.md b/docs/content/specification/design.md index 2f17fb13..9990831b 100644 --- a/docs/content/specification/design.md +++ b/docs/content/specification/design.md @@ -12,7 +12,7 @@ The behaviour in the [spec](spec.md) is delivered by a **single reusable GitHub ### Single entry point The reusable workflow accepts a caller workflow and minimal caller configuration: a `pull_request`-triggered job that -calls `workflow.yml` and passes the `APIKey` secret. The full caller template is in +calls `workflow.yml` and passes the `PSGALLERY_API_KEY` secret. The full caller template is in [Repository setup](../get-started/repository-setup.md#3-add-the-caller-workflow), and the interface it targets is documented in [Workflow inputs](../reference/workflow-inputs.md). From 449dbb06649b8c8437b8347f23cff9a1b54011d5 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 15:35:41 +0200 Subject: [PATCH 20/23] Align publish action credential name Rename the Publish-PSModule action input and environment variable to PSGALLERY_API_KEY while retaining the PowerShell cmdlet parameter name. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/Publish-PSModule/README.md | 4 ++-- .github/actions/Publish-PSModule/action.yml | 4 ++-- .github/actions/Publish-PSModule/src/publish.ps1 | 6 +++--- .github/workflows/Publish-Module.yml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/actions/Publish-PSModule/README.md b/.github/actions/Publish-PSModule/README.md index a5b0b9a5..6b97fed0 100644 --- a/.github/actions/Publish-PSModule/README.md +++ b/.github/actions/Publish-PSModule/README.md @@ -9,7 +9,7 @@ Publishes a pre-versioned PowerShell module artifact to the PowerShell Gallery. | `Name` | Name of the module to publish. | No | Repository name | | `ModulePath` | Path containing the built `/` module directory. | No | `outputs/module` | | `ArtifactName` | Name of the module artifact to download. | No | `module` | -| `APIKey` | PowerShell Gallery API key supplied from the caller's `PSGALLERY_API_KEY` secret. | Yes | N/A | +| `PSGALLERY_API_KEY` | PowerShell Gallery API key. | Yes | N/A | | `WhatIf` | Logs publishing operations without publishing the module. | No | `false` | | `WorkingDirectory` | Directory where the publishing script runs. | No | `.` | @@ -26,7 +26,7 @@ This action does not provide outputs. Name: ExampleModule ModulePath: outputs/module ArtifactName: module - APIKey: ${{ secrets.PSGALLERY_API_KEY }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} ``` Use [Release-PSModule](../Release-PSModule/README.md) in a separate workflow step to create the GitHub release from the same artifact. diff --git a/.github/actions/Publish-PSModule/action.yml b/.github/actions/Publish-PSModule/action.yml index 3fed0db7..038ddaea 100644 --- a/.github/actions/Publish-PSModule/action.yml +++ b/.github/actions/Publish-PSModule/action.yml @@ -10,7 +10,7 @@ inputs: description: Path to the folder containing the / module subdirectory from Build-PSModule. required: false default: outputs/module - APIKey: + PSGALLERY_API_KEY: description: PowerShell Gallery API Key. required: true WhatIf: @@ -49,6 +49,6 @@ runs: GH_TOKEN: ${{ env.GH_TOKEN }} PSMODULE_PUBLISH_PSMODULE_INPUT_Name: ${{ inputs.Name }} PSMODULE_PUBLISH_PSMODULE_INPUT_ModulePath: ${{ inputs.ModulePath }} - PSMODULE_PUBLISH_PSMODULE_INPUT_APIKey: ${{ inputs.APIKey }} + PSMODULE_PUBLISH_PSMODULE_INPUT_PSGALLERY_API_KEY: ${{ inputs.PSGALLERY_API_KEY }} PSMODULE_PUBLISH_PSMODULE_INPUT_WhatIf: ${{ inputs.WhatIf }} run: ${{ github.action_path }}/src/publish.ps1 diff --git a/.github/actions/Publish-PSModule/src/publish.ps1 b/.github/actions/Publish-PSModule/src/publish.ps1 index 13c6c92e..dc512c0a 100644 --- a/.github/actions/Publish-PSModule/src/publish.ps1 +++ b/.github/actions/Publish-PSModule/src/publish.ps1 @@ -1,5 +1,5 @@ [Diagnostics.CodeAnalysis.SuppressMessageAttribute( - 'PSUseDeclaredVarsMoreThanAssignments', 'apiKey', + 'PSUseDeclaredVarsMoreThanAssignments', 'psGalleryApiKey', Justification = 'Variable is used in script blocks.' )] [Diagnostics.CodeAnalysis.SuppressMessageAttribute( @@ -38,7 +38,7 @@ LogGroup 'Load inputs' { exit 1 } $modulePath = Resolve-Path -Path $modulePathCandidate | Select-Object -ExpandProperty Path - $apiKey = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_APIKey + $psGalleryApiKey = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_PSGALLERY_API_KEY $whatIf = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_WhatIf -eq 'true' Write-Host "Module name: [$name]" @@ -138,7 +138,7 @@ LogGroup 'Publish to PSGallery' { Write-Host "Publish-PSResource -Path $modulePath -Repository PSGallery -ApiKey ***" } else { try { - Publish-PSResource -Path $modulePath -Repository PSGallery -ApiKey $apiKey + Publish-PSResource -Path $modulePath -Repository PSGallery -ApiKey $psGalleryApiKey } catch { Write-Error $_.Exception.Message exit 1 diff --git a/.github/workflows/Publish-Module.yml b/.github/workflows/Publish-Module.yml index db4dd72d..4ecfe506 100644 --- a/.github/workflows/Publish-Module.yml +++ b/.github/workflows/Publish-Module.yml @@ -61,7 +61,7 @@ jobs: with: Name: ${{ fromJson(inputs.Settings).Name }} ModulePath: outputs/module - APIKey: ${{ secrets.PSGALLERY_API_KEY }} + PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} WhatIf: ${{ github.repository == 'PSModule/Process-PSModule' }} WorkingDirectory: ${{ fromJson(inputs.Settings).WorkingDirectory }} From ba92a24ae0c040aca2338b1d4e0df0e026224be8 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 15:44:54 +0200 Subject: [PATCH 21/23] Document latest GitHub App token action Identify the pinned actions/create-github-app-token release as v3.2.0 in workflow and documentation references. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Build-Module.yml | 2 +- .github/workflows/Plan.yml | 2 +- .github/workflows/Publish-Module.yml | 2 +- docs/content/guides/github-app-authentication.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/Build-Module.yml b/.github/workflows/Build-Module.yml index b92dab5b..655e2618 100644 --- a/.github/workflows/Build-Module.yml +++ b/.github/workflows/Build-Module.yml @@ -43,7 +43,7 @@ jobs: - name: Create GitHub App token id: App-Token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: client-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} diff --git a/.github/workflows/Plan.yml b/.github/workflows/Plan.yml index e3a3b06a..8e9b4657 100644 --- a/.github/workflows/Plan.yml +++ b/.github/workflows/Plan.yml @@ -88,7 +88,7 @@ jobs: - name: Create GitHub App token id: App-Token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: client-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} diff --git a/.github/workflows/Publish-Module.yml b/.github/workflows/Publish-Module.yml index 4ecfe506..149bb78a 100644 --- a/.github/workflows/Publish-Module.yml +++ b/.github/workflows/Publish-Module.yml @@ -45,7 +45,7 @@ jobs: - name: Create GitHub App token id: App-Token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: client-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} diff --git a/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md index a4bd4c5e..858cfd5e 100644 --- a/docs/content/guides/github-app-authentication.md +++ b/docs/content/guides/github-app-authentication.md @@ -85,7 +85,7 @@ The token action is pinned and exposes its output only to the steps that need Gi ```yaml - name: Create GitHub App token id: App-Token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: client-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} From ada4ac60999f68c74072edb94294e9dc43b21a55 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 15:48:38 +0200 Subject: [PATCH 22/23] Generalize action version guidance Document the latest-release SHA pinning pattern without hard-coding a release in the authentication guide. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/content/guides/github-app-authentication.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md index 858cfd5e..7be1620b 100644 --- a/docs/content/guides/github-app-authentication.md +++ b/docs/content/guides/github-app-authentication.md @@ -80,12 +80,13 @@ The scopes have separate ceilings: ## Token injection -The token action is pinned and exposes its output only to the steps that need GitHub API access: +Use the latest released version of the token action, resolved to its full immutable commit SHA. Record the exact +release tag in the trailing comment. The token action exposes its output only to the steps that need GitHub API access: ```yaml - name: Create GitHub App token id: App-Token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + uses: actions/create-github-app-token@ # vx.y.z with: client-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} From e38164dac5cc1bd966021a67043e518d83f929ff Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 15:52:26 +0200 Subject: [PATCH 23/23] Restore root README Keep GitHub App and publishing credential guidance in the canonical documentation tree instead of the repository root README. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/README.md b/README.md index c37d2ecf..b960411a 100644 --- a/README.md +++ b/README.md @@ -11,27 +11,3 @@ The full documentation is published at: 📖 **[Process-PSModule documentation](https://psmodule.io/docs/)** It covers getting started, the pipeline stages, usage, configuration, repository structure, and the principles behind the framework. - -## Reusable workflow secrets (GitHub App auth) - -When calling `./.github/workflows/workflow.yml`, pass the PowerShell Gallery credential as `PSGALLERY_API_KEY` and GitHub App credentials using these reusable-workflow secret names: - -- `PSGALLERY_API_KEY` -- `GitHubAppClientId` -- `GitHubAppPrivateKey` - -Consumer repositories can keep their own secret names and map them in the caller workflow, for example: - -```yaml -jobs: - ProcessPSModule: - uses: ./.github/workflows/workflow.yml - secrets: - PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} - GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }} - GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }} -``` - -This is a required contract. `PSGALLERY_API_KEY` publishes the module to the PowerShell Gallery; the GitHub App credentials mint an installation token for GitHub operations via `GH_TOKEN`, with no `github.token` fallback in that path. - -See the [GitHub App authentication guide](https://psmodule.io/docs/guides/github-app-authentication/) for the caller mapping, per-workflow permissions and repository scoping, and token injection details.