Skip to content

Commit 1fdefd1

Browse files
📖 [Docs]: Document GitHub App authentication (#456)
## 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>
1 parent 806a892 commit 1fdefd1

4 files changed

Lines changed: 85 additions & 1 deletion

File tree

.github/linters/.markdown-lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ MD004: false # Unordered list style
1212
MD007:
1313
indent: 2 # Unordered list indentation
1414
MD013:
15-
line_length: 3000 # Line length
15+
line_length: 3000 # Line length
1616
MD025: false # Allow front-matter title + visible H1 on docs pages
1717
MD026:
1818
punctuation: '.,;:!。,;:' # List of not allowed

.github/workflows/Build-Module.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ jobs:
4848
app-id: ${{ secrets.GitHubAppClientId }}
4949
private-key: ${{ secrets.GitHubAppPrivateKey }}
5050
repositories: ${{ github.event.repository.name }}
51+
permission-metadata: read
5152

5253
- name: Build module
5354
uses: ./_wf/.github/actions/Build-PSModule

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ jobs:
3131
```
3232
3333
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.
34+
35+
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.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
title: GitHub App authentication
3+
description: Configure the GitHub App secrets and understand token scope and injection in Process-PSModule workflows.
4+
---
5+
6+
# GitHub App authentication
7+
8+
The repository API operations in the Plan, Build-Module, and Publish-Module workflows use short-lived GitHub App
9+
installation tokens. These workflows do not use `github.token` as a fallback for those operations.
10+
11+
## Caller secret contract
12+
13+
The reusable workflow declares two required secrets at its `workflow_call` boundary:
14+
15+
| Name | Purpose |
16+
| --- | --- |
17+
| `GitHubAppClientId` | The GitHub App client ID passed to the token action. |
18+
| `GitHubAppPrivateKey` | The GitHub App private key passed to the token action. |
19+
20+
The names are the reusable workflow contract, not a requirement for the caller's repository or organization secret
21+
names. Map the caller's secrets explicitly:
22+
23+
```yaml
24+
jobs:
25+
Process-PSModule:
26+
uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@v5
27+
secrets:
28+
APIKey: ${{ secrets.APIKey }}
29+
GitHubAppClientId: ${{ secrets.SHELLY_CLIENT_ID }}
30+
GitHubAppPrivateKey: ${{ secrets.SHELLY_PRIVATE_KEY }}
31+
```
32+
33+
The root reusable workflow forwards these two values to the Plan, Build-Module, and Publish-Module reusable jobs.
34+
Do not use `secrets: inherit` as a substitute for this mapping.
35+
36+
## Token scope
37+
38+
Each job mints its own token with the repository that triggered the workflow:
39+
`${{ github.event.repository.name }}`.
40+
41+
| Workflow | Requested repository permissions | GitHub operations |
42+
| --- | --- | --- |
43+
| Plan | `contents: read`, `pull-requests: write` | Read repository settings and version data, inspect pull-request files and labels, and write planning comments or labels. |
44+
| Build-Module | `metadata: read` | Read repository metadata while building the module manifest. |
45+
| Publish-Module | `contents: write`, `pull-requests: write` | Create and upload releases, write pull-request comments, and clean up prereleases. |
46+
47+
The GitHub App installation must grant the permissions requested by each job. Keep the installation and token scope
48+
limited to the repository set required by the workflow; add broader repository access only when a workflow explicitly
49+
needs cross-repository operations.
50+
51+
The scopes have separate ceilings:
52+
53+
- `permissions:` on the caller workflow controls the default `github.token`; it does not expand an App installation
54+
token.
55+
- The App installation permissions are the maximum permissions any token from that installation can receive.
56+
- The `repositories` input limits the repositories available to the minted token.
57+
- Each `permission-<scope>` input requests only the subset needed by that job.
58+
59+
## Token injection
60+
61+
The token action is pinned and exposes its output only to the steps that need GitHub API access:
62+
63+
```yaml
64+
- name: Create GitHub App token
65+
id: App-Token
66+
uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
67+
with:
68+
app-id: ${{ secrets.GitHubAppClientId }}
69+
private-key: ${{ secrets.GitHubAppPrivateKey }}
70+
repositories: ${{ github.event.repository.name }}
71+
permission-metadata: read
72+
73+
- name: Use the token
74+
env:
75+
GH_TOKEN: ${{ steps.App-Token.outputs.token }}
76+
run: gh repo view
77+
```
78+
79+
Process-PSModule does not set this token as a job-wide environment variable. It injects `GH_TOKEN` on the Get-Settings
80+
and Resolve-Version steps in Plan, the Build-PSModule step in Build-Module, and the Publish-PSModule and cleanup steps
81+
in Publish-Module. Keep GitHub App tokens step-scoped when adding new API calls.

0 commit comments

Comments
 (0)