GitHub App Token Buildkite Plugin
Generate a GitHub App installation access token and export it as an environment variable for Buildkite steps.
This is the Buildkite equivalent of actions/create-github-app-token.
How it works
- Reads the App ID, private key, and installation ID from Buildkite secrets
- Signs a JWT (RS256) using the private key
- Exchanges the JWT for an installation access token via the GitHub API
- Exports the token as
GH_TOKEN(or a configured variable name)
The token is valid for one hour and has the permissions granted to the GitHub App installation.
Example
steps:
- label: ":github: Create Release"
plugins:
- github-app-token#v1.0.0: ~
command: gh release create v1.0.0 --generate-notes
This requires three Buildkite secrets: GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY,
and GITHUB_APP_INSTALLATION_ID. The gh CLI automatically uses the exported
GH_TOKEN.
Custom Secret Names
If your secrets use different env var names:
plugins:
- github-app-token#v1.0.0:
app-id-env: MY_GITHUB_APP_ID
private-key-env: MY_GITHUB_APP_KEY
installation-id-env: MY_GITHUB_APP_INSTALL_ID
GitHub Enterprise Server
plugins:
- github-app-token#v1.0.0:
api-url: https://github.example.com/api/v3
Configuration
| Option | Default | Description |
|---|---|---|
app-id-env | GITHUB_APP_ID | Env var containing the GitHub App ID |
private-key-env | GITHUB_APP_PRIVATE_KEY | Env var containing the PEM private key |
installation-id-env | GITHUB_APP_INSTALLATION_ID | Env var containing the installation ID |
token-variable | GH_TOKEN | Env var name to export the token as |
api-url | https://api.github.com | GitHub API base URL |
hook | environment | Which hook to run in: environment or pre-command |
Config values are env var names, not secrets themselves — secrets never appear in pipeline YAML.
Requirements
bashcurlopenssljq
All four are available on Buildkite hosted agents and most CI environments.
Secrets Setup
- Create a GitHub App with the permissions your pipeline needs
- Install the app on your organization or repository
- Note the App ID (from the app’s settings page) and Installation ID (from
the URL after installing:
https://github.com/settings/installations/<ID>) - Generate a private key (PEM format) from the app’s settings page
- Add all three as Buildkite secrets:
bk secret set GITHUB_APP_ID "12345"
bk secret set GITHUB_APP_PRIVATE_KEY "$(cat private-key.pem)"
bk secret set GITHUB_APP_INSTALLATION_ID "67890"
Why GitHub Apps over Personal Access Tokens?
- Not tied to a human — Apps are their own identity; no single point of failure
- Fine-grained permissions — Request only what the pipeline needs
- Higher rate limits — 5,000 requests/hour per installation vs 5,000/hour per user
- Automatic expiry — Installation tokens expire after 1 hour; PATs can live forever
- Audit trail — Actions are attributed to the app, not a person
Development
bats tests/plugin.bats
docker run --rm -v "$PWD:/plugin" -w /plugin buildkite/plugin-linter --id tommeier/github-app-token --path /plugin
shellcheck hooks/* lib/*.bash