GitHub Apps and OAuth integrations are the backbone of modern GitHub automation, allowing you to programmatically interact with GitHub repositories and resources.

Let’s see how this looks in action. Imagine you want to automatically label pull requests that are ready for review.

import requests
import os

# Get GitHub token from environment variable
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN")
REPO_OWNER = "your-repo-owner"
REPO_NAME = "your-repo-name"
PULL_NUMBER = 123 # Example pull request number

headers = {
    "Authorization": f"token {GITHUB_TOKEN}",
    "Accept": "application/vnd.github.v3+json",
}

# Check if the PR is ready for review (e.g., has a 'ready' label)
# In a real app, you'd fetch PR details first.
# For this example, we'll assume it's ready.

# Add a label to the pull request
label_url = f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}/issues/{PULL_NUMBER}/labels"
label_data = {
    "labels": ["needs-review"]
}

response = requests.post(label_url, json=label_data, headers=headers)

if response.status_code == 200:
    print(f"Successfully added 'needs-review' label to PR #{PULL_NUMBER}")
elif response.status_code == 201: # Some label operations return 201
    print(f"Successfully added 'needs-review' label to PR #{PULL_NUMBER}")
else:
    print(f"Error adding label: {response.status_code}, {response.json()}")

This code snippet, when run with a valid GITHUB_TOKEN, would add the needs-review label to the specified pull request. The Authorization header is crucial, containing your token that grants the app permission to act on your behalf. The Accept header specifies the API version to use.

At its core, a GitHub App is a first-class entity on GitHub that can be granted specific permissions and installed on individual repositories or entire organizations. It acts on behalf of a user or itself. OAuth integrations, on the other hand, are typically user-authorized applications that grant broad access based on user consent. GitHub Apps are generally preferred for automation due to their fine-grained permissions and the ability to act without direct user intervention after installation.

When you create a GitHub App, you define its permissions (e.g., read/write access to code, issues, pull requests) and the events it can subscribe to (e.g., pull_request, issues). When the app is installed, it generates an installation access token, which is a short-lived credential used to authenticate API requests. This token is specific to the installation and the permissions granted.

The key to building robust automations lies in understanding the GitHub REST API and the different authentication methods. For GitHub Apps, you’ll use JSON Web Tokens (JWTs) to generate installation access tokens. For OAuth apps, you’ll go through an authorization flow to obtain an access token. The requests library in Python is a common tool for making these HTTP requests.

The difference between a GitHub App and a standard OAuth application is nuanced but important. A GitHub App is designed to be an autonomous agent, acting on its own behalf with specific, pre-defined permissions. It can be installed on repositories without needing a user to constantly authorize it. An OAuth application, by contrast, typically requires a user to grant it permission to access their data on GitHub. This means the OAuth app acts as the user, inheriting their permissions. For automated workflows, GitHub Apps are superior because they don’t rely on a human being logged in or actively granting consent.

When you set up a GitHub App, you’ll encounter the concept of "webhooks." These are automated messages sent from GitHub to your application when certain events occur. For instance, you can configure a webhook to trigger your application whenever a pull request is opened. Your application then receives this event data and can act accordingly, such as by using the API to add a label or comment. This event-driven architecture is fundamental to real-time automation.

The permissions you grant to your GitHub App are critical for security. Instead of giving an app broad access to everything, you can restrict it to only the repositories and actions it needs. For example, an app that only labels pull requests needs contents: read and pull_requests: write permissions on specific repositories. This principle of least privilege is paramount.

If you’re automating workflows with GitHub Actions, you’ll often use the GITHUB_TOKEN provided automatically within the workflow. This token is scoped to the repository where the workflow is running and has permissions granted by the repository’s settings. For more complex scenarios or when interacting with multiple repositories or organizations, you would typically create a dedicated GitHub App and use its installation access token.

Understanding the difference between repository-level and organization-level installations for GitHub Apps is also key. An app installed at the organization level can be granted access to multiple repositories within that organization, simplifying management for larger teams. Conversely, a repository-level installation limits the app’s scope to just that one repository.

The next step in mastering GitHub automation is exploring the GitHub GraphQL API, which offers a more efficient way to fetch data by allowing you to request only the specific fields you need, reducing the number of API calls and the amount of data transferred.

Want structured learning?

Take the full Github course →