From a1f12503873b3e8dc3184bb84d5db9f7d8fa906f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 11:51:04 +0200 Subject: [PATCH 1/4] Document GitHub App authentication Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../guides/github-app-authentication.md | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 docs/content/guides/github-app-authentication.md diff --git a/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md new file mode 100644 index 00000000..74c73a6e --- /dev/null +++ b/docs/content/guides/github-app-authentication.md @@ -0,0 +1,80 @@ +--- +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.PSMODULE_CLIENT_ID }} + GitHubAppPrivateKey: ${{ secrets.PSMODULE_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 | No explicit `permission-*` inputs | 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 }} + +- 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 b9b86a66fc1c699492487de21937f96555885ece Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 11:51:14 +0200 Subject: [PATCH 2/4] Link GitHub App authentication guide Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2773f83d..99427ae1 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. From faa72a1355e5cb2be585b64bbaafbf74581944b7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 11:51:24 +0200 Subject: [PATCH 3/4] Point README to canonical docs Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 99427ae1..d5005120 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Documentation site generation is powered by Zensical. Repositories define site c The full documentation lives on the MSX / Docs site: -📖 **[Process-PSModule documentation](https://msxorg.github.io/docs/Frameworks/Process-PSModule/)** +📖 **[Process-PSModule documentation](https://psmodule.io/docs/)** It covers getting started, the pipeline stages, usage, configuration, repository structure, and the principles behind the framework. From 900394f3a75e2b3181f62fd3b1d99c35c03b0e3d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 11:56:19 +0200 Subject: [PATCH 4/4] Fix documentation lint and build token scope Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/linters/.markdown-lint.yml | 1 + .github/workflows/Build-Module.yml | 1 + docs/content/guides/github-app-authentication.md | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml index bb432af1..8b6fce44 100644 --- a/.github/linters/.markdown-lint.yml +++ b/.github/linters/.markdown-lint.yml @@ -13,6 +13,7 @@ MD007: indent: 2 # Unordered list indentation MD013: line_length: 808 # Line length +MD025: false # Allow front-matter title + visible H1 on docs pages MD026: punctuation: ".,;:!。,;:" # List of not allowed MD029: false # Ordered list item prefix diff --git a/.github/workflows/Build-Module.yml b/.github/workflows/Build-Module.yml index 360c2797..a0ac5a91 100644 --- a/.github/workflows/Build-Module.yml +++ b/.github/workflows/Build-Module.yml @@ -49,6 +49,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/docs/content/guides/github-app-authentication.md b/docs/content/guides/github-app-authentication.md index 74c73a6e..6ed47731 100644 --- a/docs/content/guides/github-app-authentication.md +++ b/docs/content/guides/github-app-authentication.md @@ -41,7 +41,7 @@ Each job mints its own token with the repository that triggered the workflow: | 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 | No explicit `permission-*` inputs | Read repository metadata while building the module manifest. | +| 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 @@ -68,6 +68,7 @@ The token action is pinned and exposes its output only to the steps that need Gi app-id: ${{ secrets.GitHubAppClientId }} private-key: ${{ secrets.GitHubAppPrivateKey }} repositories: ${{ github.event.repository.name }} + permission-metadata: read - name: Use the token env: