Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 8 additions & 3 deletions docs/src/content/docs/reference/frontmatter-full.md
Original file line number Diff line number Diff line change
Expand Up @@ -1784,7 +1784,10 @@ cache: []

# Safe output processing configuration that automatically creates GitHub issues,
# comments, and pull requests from AI workflow output without requiring write
# permissions in the main job
# permissions in the main job. When using GitHub App tokens (app:), permissions
# are automatically narrowed per-job to match only what's needed, and tokens are
# auto-revoked at job end. Multiple safe outputs in the same workflow receive the
# union of their required permissions.
# (optional)
safe-outputs:
# List of allowed domains for URI filtering in AI workflow output. URLs from other
Expand Down Expand Up @@ -3412,8 +3415,10 @@ safe-outputs:
github-token: "${{ secrets.GITHUB_TOKEN }}"

# GitHub App credentials for minting installation access tokens. When configured,
# a token will be generated using the app credentials and used for all safe output
# operations.
# tokens are automatically minted per-job with permissions narrowed to match the
# job's permissions block. Tokens are auto-revoked at job end. This enables safe
# use of a broadly-permissioned GitHub App because each job only receives the
# specific permissions it needs.
# (optional)
app:
# GitHub App ID. Should reference a variable (e.g., ${{ vars.APP_ID }}).
Expand Down
19 changes: 17 additions & 2 deletions docs/src/content/docs/reference/safe-outputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ Exposes outputs: `status-update-id`, `project-id`, `status`.

### Pull Request Creation (`create-pull-request:`)

Creates PRs with code changes. Falls back to issue if creation fails (e.g., org settings block it). `expires` field (same-repo only) auto-closes after period: integers (days) or `2h`, `7d`, `2w`, `1m`, `1y` (hours < 24 treated as 1 day).
Creates PRs with code changes. By default, falls back to creating an issue if PR creation fails (e.g., org settings block it). Set `fallback-as-issue: false` to disable this fallback and avoid requiring `issues: write` permission. `expires` field (same-repo only) auto-closes after period: integers (days) or `2h`, `7d`, `2w`, `1m`, `1y` (hours < 24 treated as 1 day).

```yaml wrap
safe-outputs:
Expand All @@ -641,6 +641,7 @@ safe-outputs:
if-no-changes: "warn" # "warn" (default), "error", or "ignore"
target-repo: "owner/repo" # cross-repository
base-branch: "vnext" # target branch for PR (default: github.ref_name)
fallback-as-issue: false # disable issue fallback (default: true)
```

The `base-branch` field specifies which branch the pull request should target. This is particularly useful for cross-repository PRs where you need to target non-default branches (e.g., `vnext`, `release/v1.0`, `staging`). When not specified, defaults to the workflow's branch (`github.ref_name`).
Expand All @@ -656,7 +657,7 @@ safe-outputs:
```

> [!NOTE]
> PR creation may fail if "Allow GitHub Actions to create and approve pull requests" is disabled in Organization Settings. Fallback creates issue with branch link.
> PR creation may fail if "Allow GitHub Actions to create and approve pull requests" is disabled in Organization Settings. By default (`fallback-as-issue: true`), fallback creates an issue with branch link and requires `issues: write` permission. Set `fallback-as-issue: false` to disable fallback and only require `contents: write` + `pull-requests: write`.

### Close Pull Request (`close-pull-request:`)

Expand Down Expand Up @@ -1336,6 +1337,20 @@ safe-outputs:
create-issue:
```

#### How GitHub App Tokens Work

When you configure `app:` for safe outputs, tokens are **automatically managed per-job** for enhanced security:

1. **Per-job token minting**: Each safe output job automatically mints its own token via `actions/create-github-app-token` with permissions explicitly scoped to that job's needs
2. **Permission narrowing**: Token permissions are narrowed to match the job's `permissions:` block - only the permissions required for the safe outputs in that job are granted
3. **Automatic revocation**: Tokens are explicitly revoked at job end via `DELETE /installation/token`, even if the job fails
4. **Safe shared configuration**: A broadly-permissioned GitHub App can be safely shared across workflows because tokens are narrowed per-job

> [!TIP]
> **Why this matters**: You can configure a single GitHub App at the organization level with broad permissions (e.g., `contents: write`, `issues: write`, `pull-requests: write`), and each workflow job will only receive the specific subset of permissions it needs. This provides least-privilege access without requiring per-workflow App configuration.

**Example**: If your workflow only uses `create-issue:`, the minted token will have `contents: read` + `issues: write`, even if your GitHub App has broader permissions configured.

### Maximum Patch Size (`max-patch-size:`)

Limits git patch size for PR operations (1-10,240 KB, default: 1024 KB):
Expand Down
5 changes: 4 additions & 1 deletion docs/src/content/docs/reference/tokens.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,9 @@ gh aw secrets set APP_PRIVATE_KEY --value "$(cat path/to/private-key.pem)"

**How it works**:

At workflow start, a token is automatically minted with permissions matching your agent job's `permissions:` field. The token is passed to the GitHub MCP server and automatically revoked at workflow end (even on failure).
At workflow start, a token is automatically minted with **permissions matching your job's `permissions:` field**. The token is passed to the GitHub MCP server and automatically revoked at workflow end (even on failure).

This is the same per-job narrowing behavior used by `safe-outputs.app:` - see the [Safe Outputs documentation](/gh-aw/reference/safe-outputs/#github-app-token-app) for a detailed explanation of how GitHub App tokens are narrowed per-job.

**Token precedence and fallback**:

Expand All @@ -243,6 +245,7 @@ At workflow start, a token is automatically minted with permissions matching you
- The compiler automatically sets `GITHUB_MCP_SERVER_TOKEN` and passes it as `GITHUB_PERSONAL_ACCESS_TOKEN` (local/Docker) or an `Authorization: Bearer` header (remote).
- In most cases, you do not need to set this token separately. Use `GH_AW_GITHUB_TOKEN` instead.
- **GitHub App advantages**: Short-lived tokens (auto-revoked at workflow end), no credential rotation needed, automatic permission calculation, better auditability.
- **Per-job permission narrowing**: When using a GitHub App (via `tools.github.app:` or `safe-outputs.app:`), tokens are automatically narrowed to match the job's `permissions:` block. This means you can safely configure a broadly-permissioned GitHub App at the organization level, and each job will only receive the specific permissions it needs.
- If using a GitHub App for both safe-outputs and GitHub MCP server, you can configure them independently for different permission levels.
- Set the resource owner to the organization when the repository is organization-owned.
- `GITHUB_TOKEN` is not supported in remote mode. Use `GH_AW_GITHUB_TOKEN` or a GitHub App instead.
Expand Down