Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
69a8a7c
Add generic GitHub App secret mapping
MariusStorhaug Jul 23, 2026
ac2caa1
Document reusable GitHub App secrets
MariusStorhaug Jul 23, 2026
b5cbfe3
Use GitHub App token in Plan workflow
MariusStorhaug Jul 23, 2026
eec3b84
Use GitHub App token in publish workflow
MariusStorhaug Jul 23, 2026
4b47a32
Adjust action token env precedence
MariusStorhaug Jul 23, 2026
a339e4d
Prefer app token in Get-PSModuleSettings
MariusStorhaug Jul 23, 2026
f7ded05
Make GitHub App token wiring strict
MariusStorhaug Jul 23, 2026
83568fb
Use only GH_TOKEN for app-auth steps
MariusStorhaug Jul 23, 2026
3b4410a
Use GitHub App token in Build-Module workflow
MariusStorhaug Jul 23, 2026
61be878
Scope GitHub App tokens to repo and minimum permissions
MariusStorhaug Jul 23, 2026
5f4652d
Merge remote-tracking branch 'origin/main' into github-app-planning
MariusStorhaug Aug 9, 2026
806a892
Use Shelly credentials in workflow callers
MariusStorhaug Aug 9, 2026
1fdefd1
📖 [Docs]: Document GitHub App authentication (#456)
MariusStorhaug Aug 9, 2026
a605ffe
Complete GitHub App caller contract
MariusStorhaug Aug 9, 2026
d88e264
Document Shelly permission baseline
MariusStorhaug Aug 9, 2026
bb66b8f
Require Shelly Dependabot secrets
MariusStorhaug Aug 9, 2026
9a654b8
Rename PowerShell Gallery workflow credential
MariusStorhaug Aug 9, 2026
258aaef
Use GitHub App client IDs for token minting
MariusStorhaug Aug 9, 2026
3c27c41
Fix generated documentation lint configuration
MariusStorhaug Aug 9, 2026
0ac9a29
Name PowerShell Gallery credential consistently
MariusStorhaug Aug 9, 2026
449dbb0
Align publish action credential name
MariusStorhaug Aug 9, 2026
ba92a24
Document latest GitHub App token action
MariusStorhaug Aug 9, 2026
ada4ac6
Generalize action version guidance
MariusStorhaug Aug 9, 2026
e38164d
Restore root README
MariusStorhaug Aug 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/Cleanup-PSModulePrereleases/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ runs:
shell: pwsh
working-directory: ${{ inputs.WorkingDirectory }}
env:
GH_TOKEN: ${{ env.GH_TOKEN }}
PSMODULE_CLEANUP_PSMODULEPRERELEASES_INPUT_WhatIf: ${{ inputs.WhatIf }}
PSMODULE_CLEANUP_PSMODULEPRERELEASES_CONTEXT_ReleaseTag: ${{ inputs.ReleaseTag }}
run: ${{ github.action_path }}/src/cleanup.ps1
2 changes: 2 additions & 0 deletions .github/actions/Get-PSModuleSettings/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ runs:
uses: PSModule/GitHub-Script@8083ec1f733f00357ee4d0db0c6056686e483bc0 # v1.9.0
id: Get-PSModuleSettings
env:
GH_TOKEN: ${{ env.GH_TOKEN }}
PSMODULE_GET_SETTINGS_INPUT_Name: ${{ inputs.Name }}
PSMODULE_GET_SETTINGS_INPUT_SettingsPath: ${{ inputs.SettingsPath }}
PSMODULE_GET_SETTINGS_INPUT_Debug: ${{ inputs.Debug }}
Expand All @@ -63,6 +64,7 @@ runs:
PSMODULE_GET_SETTINGS_INPUT_ImportantFilePatterns: ${{ inputs.ImportantFilePatterns }}
with:
Name: Get-PSModuleSettings
Token: ${{ env.GH_TOKEN }}
ShowInfo: false
ShowOutput: true
Debug: ${{ inputs.Debug }}
Expand Down
4 changes: 2 additions & 2 deletions .github/actions/Publish-PSModule/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<Name>/` module directory. | No | `outputs/module` |
| `ArtifactName` | Name of the module artifact to download. | No | `module` |
| `APIKey` | PowerShell Gallery API key. | 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 | `.` |

Expand All @@ -26,7 +26,7 @@ This action does not provide outputs.
Name: ExampleModule
ModulePath: outputs/module
ArtifactName: module
APIKey: ${{ secrets.APIKEY }}
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.
5 changes: 3 additions & 2 deletions .github/actions/Publish-PSModule/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ inputs:
description: Path to the folder containing the <Name>/ module subdirectory from Build-PSModule.
required: false
default: outputs/module
APIKey:
PSGALLERY_API_KEY:
description: PowerShell Gallery API Key.
required: true
WhatIf:
Expand Down Expand Up @@ -46,8 +46,9 @@ runs:
shell: pwsh
working-directory: ${{ inputs.WorkingDirectory }}
env:
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
6 changes: 3 additions & 3 deletions .github/actions/Publish-PSModule/src/publish.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSUseDeclaredVarsMoreThanAssignments', 'apiKey',
'PSUseDeclaredVarsMoreThanAssignments', 'psGalleryApiKey',
Justification = 'Variable is used in script blocks.'
)]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
Expand Down Expand Up @@ -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]"
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/Resolve-PSModuleVersion/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ runs:
shell: pwsh
working-directory: ${{ inputs.WorkingDirectory }}
env:
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ env.GH_TOKEN }}
PSMODULE_RESOLVE_PSMODULEVERSION_INPUT_Settings: ${{ inputs.Settings }}
PSMODULE_RESOLVE_PSMODULEVERSION_INPUT_Name: ${{ inputs.Name }}
PSMODULE_RESOLVE_PSMODULEVERSION_INPUT_EventJson: ${{ inputs.EventJson }}
Expand Down
20 changes: 18 additions & 2 deletions .github/workflows/Build-Module.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -36,8 +41,19 @@ jobs:
path: _wf
persist-credentials: false

- name: Create GitHub App token
id: App-Token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ secrets.GitHubAppClientId }}
private-key: ${{ secrets.GitHubAppPrivateKey }}
repositories: ${{ github.event.repository.name }}
permission-metadata: read

- 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' }}
Expand Down
21 changes: 20 additions & 1 deletion .github/workflows/Plan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -79,9 +86,21 @@ jobs:
path: _wf
persist-credentials: false

- name: Create GitHub App token
id: App-Token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-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
id: Get-Settings
env:
GH_TOKEN: ${{ steps.App-Token.outputs.token }}
with:
SettingsPath: ${{ inputs.SettingsPath }}
Debug: ${{ inputs.Debug }}
Expand All @@ -95,7 +114,7 @@ jobs:
uses: ./_wf/.github/actions/Resolve-PSModuleVersion
id: Resolve-Version
env:
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ steps.App-Token.outputs.token }}
with:
Settings: ${{ steps.Get-Settings.outputs.Settings }}
Name: ${{ fromJson(steps.Get-Settings.outputs.Settings).Name }}
Expand Down
26 changes: 21 additions & 5 deletions .github/workflows/Publish-Module.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ name: Publish-Module
on:
workflow_call:
secrets:
APIKey:
PSGALLERY_API_KEY:
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
Expand Down Expand Up @@ -37,15 +43,25 @@ jobs:
path: _wf
persist-credentials: false

- name: Create GitHub App token
id: App-Token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-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'
uses: ./_wf/.github/actions/Publish-PSModule
env:
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ steps.App-Token.outputs.token }}
with:
Name: ${{ fromJson(inputs.Settings).Name }}
ModulePath: outputs/module
APIKey: ${{ secrets.APIKey }}
PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }}
WhatIf: ${{ github.repository == 'PSModule/Process-PSModule' }}
WorkingDirectory: ${{ fromJson(inputs.Settings).WorkingDirectory }}

Expand All @@ -54,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
Expand All @@ -74,7 +90,7 @@ jobs:
steps.create-github-release.outcome == 'success')
uses: ./_wf/.github/actions/Cleanup-PSModulePrereleases
env:
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ steps.App-Token.outputs.token }}
with:
WhatIf: ${{ github.repository == 'PSModule/Process-PSModule' }}
AutoCleanup: ${{ fromJson(inputs.Settings).Publish.Module.AutoCleanup }}
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/Workflow-Test-Default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ 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: >-
{
"secrets": {
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/Workflow-Test-WithManifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ 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: >-
{
"secrets": {
Expand Down
18 changes: 16 additions & 2 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ name: Process-PSModule
on:
workflow_call:
secrets:
APIKey:
PSGALLERY_API_KEY:
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
Expand Down Expand Up @@ -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 }}
Expand Down Expand Up @@ -107,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:
Expand Down Expand Up @@ -245,7 +257,9 @@ 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:
- Plan
- Get-TestResults
Expand Down
4 changes: 2 additions & 2 deletions docs/content/get-started/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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. |

Expand Down
12 changes: 7 additions & 5 deletions docs/content/get-started/repository-setup.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -18,14 +18,14 @@ This creates an environment called `github-pages` that GitHub deploys the docume
<img src="../media/pagesEnvironment.png" alt="Remove the branch protection on main">
</details>

## 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 `APIKEY` 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

Expand Down Expand Up @@ -63,7 +63,9 @@ 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 }}
```

Every permission in that block is required. See [Workflow inputs](../reference/workflow-inputs.md) for what each one is
Expand Down
Loading
Loading