A Buildkite plugin that creates GitHub App installation access tokens for authenticating with GitHub APIs in your Buildkite pipelines.
This plugin is inspired by and provides similar functionality to the actions/create-github-app-token GitHub Action.
Generate a GitHub App token and use it to authenticate with GitHub:
steps:
- label: "Generate GitHub App Token"
plugins:
- jasonwbarnett/create-github-app-token#v0.1.0:
app-id: "$$GITHUB_APP_ID"
private-key: "$$GITHUB_APP_PRIVATE_KEY"
command: |
# Token is now available in GITHUB_TOKEN environment variable
curl -H "Authorization: Bearer \$GITHUB_TOKEN" https://api.github.com/user
The GitHub App ID or a reference to an environment variable containing the App ID. You can find the App ID in your GitHub App's settings page.
- Direct value:
"123456"
- Environment variable reference:
"$$GITHUB_APP_ID"
(recommended for security)
Note: Use
$$
to prevent Buildkite from interpolating the variable. The plugin will handle the environment variable expansion internally.
The GitHub App's private key in PEM format or a reference to an environment variable containing the private key. This should be stored securely using Buildkite secrets.
- Environment variable reference:
"$$GITHUB_APP_PRIVATE_KEY"
(recommended) - Direct value: Not recommended for security reasons
Note: Use
$$
to prevent Buildkite from interpolating the variable. The plugin will handle the environment variable expansion internally.
Repository owner. If not specified, defaults to the current repository owner extracted from BUILDKITE_REPO
.
Example: "octocat"
Comma or newline-separated list of repository names to scope the token access. If not specified, the token will have access to all repositories the GitHub App is installed on.
Example: "repo1,repo2"
or:
repositories: |
repo1
repo2
Skip automatic token revocation during cleanup. Set to "true"
to skip revocation.
Default: "false"
GitHub REST API URL. Useful for GitHub Enterprise Server instances.
Default: "https://api.github.com"
Example: "https://github.example.com/api/v3"
The name of the environment variable to store the generated token. This is a Buildkite-specific parameter.
Default: GITHUB_TOKEN
Example: "CUSTOM_TOKEN_VAR"
You can specify granular permissions for the generated token. Each permission can be set to "read"
or "write"
.
Actions workflows permission level.
Repository administration permission level.
Code checks permission level.
Codespaces management permission level.
Repository contents permission level.
Deployments permission level.
Environments permission level.
Issues permission level.
Repository metadata permission level.
Packages permission level.
GitHub Pages permission level.
Pull requests permission level.
Repository webhooks permission level.
Repository projects permission level.
Security events permission level.
Commit statuses permission level.
Vulnerability alerts permission level.
You can specify granular organization-level permissions for the generated token. Each permission can be set to "read"
or "write"
.
Organization members permission level. Allows access to organization member information.
steps:
- label: "Use GitHub App Token"
plugins:
- jasonwbarnett/create-github-app-token#v0.1.0:
app-id: "$$GITHUB_APP_ID"
private-key: "$$GITHUB_APP_PRIVATE_KEY"
command: |
# Use the token to make authenticated requests
gh api user
steps:
- label: "Scoped GitHub App Token"
plugins:
- jasonwbarnett/create-github-app-token#v0.1.0:
app-id: "$$GITHUB_APP_ID"
private-key: "$$GITHUB_APP_PRIVATE_KEY"
repositories: "repo1,repo2"
permission-contents: "read"
permission-issues: "write"
permission-pull-requests: "write"
command: |
# Token has limited scope and permissions
gh api repos/owner/repo1/contents/README.md
steps:
- label: "Organization Members Access"
plugins:
- jasonwbarnett/create-github-app-token#v0.1.0:
app-id: "$$GITHUB_APP_ID"
private-key: "$$GITHUB_APP_PRIVATE_KEY"
permission-organization-members: "read"
command: |
# Token can access organization member information
gh api orgs/myorg/members
steps:
- label: "Enterprise GitHub App Token"
plugins:
- jasonwbarnett/create-github-app-token#v0.1.0:
app-id: "$$GITHUB_APP_ID"
private-key: "$$GITHUB_APP_PRIVATE_KEY"
github-api-url: "https://github.company.com/api/v3"
command: |
# Works with GitHub Enterprise Server
gh api user
steps:
- label: "Long-lived Token"
plugins:
- jasonwbarnett/create-github-app-token#v0.1.0:
app-id: "$$GITHUB_APP_ID"
private-key: "$$GITHUB_APP_PRIVATE_KEY"
skip-token-revoke: "true"
command: |
# Token won't be revoked automatically
echo "Token will remain active until expiration"
steps:
- label: "Custom Token Variable"
plugins:
- jasonwbarnett/create-github-app-token#v0.1.0:
app-id: "$$GITHUB_APP_ID"
private-key: "$$GITHUB_APP_PRIVATE_KEY"
output-variable: "MY_GITHUB_TOKEN"
command: |
# Token is available in MY_GITHUB_TOKEN
curl -H "Authorization: Bearer \$MY_GITHUB_TOKEN" https://api.github.com/repos/owner/repo
Create a .buildkite/hooks/pre-command
script to securely retrieve secrets:
#!/bin/bash
export GITHUB_APP_ID=$(buildkite-agent secret get GITHUB_APP_ID)
export GITHUB_APP_PRIVATE_KEY=$(buildkite-agent secret get GITHUB_APP_PRIVATE_KEY)
Then reference them in your pipeline:
steps:
- label: "Generate Token with Secrets"
plugins:
- jasonwbarnett/create-github-app-token#v0.1.0:
app-id: "$$GITHUB_APP_ID"
private-key: "$$GITHUB_APP_PRIVATE_KEY"
command: |
echo "Token generated securely using Buildkite secrets"
- Token Redaction: The generated token is automatically added to Buildkite's CLI redactor to prevent accidental logging
- Automatic Token Revocation: Tokens are automatically revoked after command execution (unless
skip-token-revoke
is set totrue
) - Environment Cleanup: Tokens are removed from the environment after command execution
- Temporary Key Storage: Private keys are stored in temporary files that are immediately cleaned up
- Scoped Permissions: Use permission parameters to limit token access to only what's needed
- Repository Scoping: Use the
repositories
parameter to limit token access to specific repositories
- Environment Variable Expansion: Resolves environment variable references (e.g.,
$GITHUB_APP_ID
) to their actual values - JWT Generation: Creates a JSON Web Token (JWT) using your GitHub App ID and private key
- Installation Discovery: Finds the GitHub App installation for the current repository
- Token Generation: Uses the JWT to request an installation access token from GitHub's API
- Security Setup: Adds the token to Buildkite's redactor and exports it as an environment variable
- Cleanup: Removes the token from the environment after command execution
The plugin supports referencing environment variables using the $VARIABLE_NAME
syntax for the app-id
and private-key
parameters. This allows you to keep sensitive values out of your pipeline configuration:
# In your pipeline YAML (secure - no secrets in config)
app-id: "$$GITHUB_APP_ID"
private-key: "$$GITHUB_APP_PRIVATE_KEY"
The plugin will automatically expand $GITHUB_APP_ID
to the value of the GITHUB_APP_ID
environment variable. Use the double-dollar ($$
) syntax in Buildkite to prevent Buildkite from interpolating the variables before the plugin receives them.
openssl
- Used for JWT signature generationcurl
- Used for GitHub API requestsjq
- Used for JSON parsingbuildkite-agent
- Required for token redaction- Repository must have the GitHub App installed
This error occurs when the plugin cannot determine the GitHub repository from the BUILDKITE_REPO
environment variable. Ensure your repository URL is in one of these formats:
git@github.com:owner/repo.git
https://github.com/owner/repo.git
If you see the error "GitHub App is not installed on owner/repository", the plugin has detected that your GitHub App is not installed on the target repository or organization. Follow the provided instructions:
- Go to your GitHub App settings
- Click 'Install App' in the left sidebar
- Select the organization/account
- Choose to install on selected repositories or all repositories
This error replaces the generic "Failed to get installation ID" message and provides clear next steps.
This typically indicates:
- Invalid private key format
- Clock skew (JWT timestamps are invalid)
- Insufficient GitHub App permissions
To contribute to this plugin:
- Clone the repository
- Make your changes
- Test with a Buildkite pipeline
- Submit a pull request
MIT (see LICENSE)