Octokit
Note We've recently renamed the
4-stable
branch tomain
. This might affect you if you're making changes to Octokit's code locally. For more details and for the steps to reconfigure your local clone for the new branch name, check out this post.
Ruby toolkit for the GitHub API.
Upgrading? Check the Upgrade Guide before bumping to a new [major version][semver].
Table of Contents
- Philosophy
- Installation
- Making requests
- Consuming resources
- Accessing HTTP responses
- Handling errors
- Authentication
- Default results per_page
- Pagination
- Working with GitHub Enterprise
- Interacting with the GitHub.com APIs in GitHub Enterprise
- Interacting with the GitHub Enterprise Admin APIs
- Interacting with the GitHub Enterprise Management Console APIs
- SSL Connection Errors
- Configuration and defaults
- Hypermedia agent
- Upgrading guide
- Advanced usage
- Hacking on Octokit.rb
- Supported Ruby Versions
- Versioning
- Making Repeating Requests
- License
Philosophy
API wrappers should reflect the idioms of the language in which they were written. Octokit.rb wraps the GitHub API in a flat API client that follows Ruby conventions and requires little knowledge of REST. Most methods have positional arguments for required input and an options hash for optional parameters, headers, or other options:
client = Octokit::Client.new
# Fetch a README with Accept header for HTML format
client.readme 'al3x/sovereign', :accept => 'application/vnd.github.html'
Installation
Install via Rubygems
gem install octokit
... or add to your Gemfile
gem "octokit"
Access the library in Ruby:
require 'octokit'
Making requests
API methods are available as client instance methods.
# Provide authentication credentials
client = Octokit::Client.new(:access_token => 'personal_access_token')
# You can still use the username/password syntax by replacing the password value with your PAT.
# client = Octokit::Client.new(:login => 'defunkt', :password => 'personal_access_token')
# Fetch the current user
client.user
Additional query parameters
When passing additional parameters to GET based request use the following syntax:
# query: { parameter_name: 'value' }
# Example: Get repository listing by owner in ascending order
client.repos({}, query: {type: 'owner', sort: 'asc'})
# Example: Get contents of a repository by ref
# https://api.github.com/repos/octokit/octokit.rb/contents/path/to/file.rb?ref=some-other-branch
client.contents('octokit/octokit.rb', path: 'path/to/file.rb', query: {ref: 'some-other-branch'})
Consuming resources
Most methods return a Resource
object which provides dot notation and []
access for fields returned in the API response.
client = Octokit::Client.new
# Fetch a user
user = client.user 'jbarnette'
puts user.name
# => "John Barnette"
puts user.fields
# => <Set: {:login, :id, :gravatar_id, :type, :name, :company, :blog, :location, :email, :hireable, :bio, :public_repos, :followers, :following, :created_at, :updated_at, :public_gists}>
puts user[:company]
# => "GitHub"
user.rels[:gists].href
# => "https://api.github.com/users/jbarnette/gists"
Note: URL fields are culled into a separate .rels
collection for easier
Hypermedia support.
Accessing HTTP responses
While most methods return a Resource
object or a Boolean, sometimes you may
need access to the raw HTTP response headers. You can access the last HTTP
response with Client#last_response
:
user = client.user 'andrewpthorp'
response = client.last_response
etag = response.headers[:etag]
Handling errors
When the API returns an error response, Octokit will raise a Ruby exception.
A range of different exceptions can be raised depending on the error returned by the API - for example:
- A
400 Bad Request
response will lead to anOctokit::BadRequest
error - A
403 Forbidden
error with a "rate limited exceeded" message will lead to aOctokit::TooManyRequests
error
All of the different exception classes inherit from Octokit::Error
and
expose the #response_status
, #response_headers
and #response_body
.
For validation errors, #errors
will return an Array
of Hash
es
with the detailed information
returned by the API.
Authentication
Octokit supports the various authentication methods supported by the GitHub API:
Basic Authentication
Using your GitHub username and password is the easiest way to get started making authenticated requests:
client = Octokit::Client.new(:login => 'defunkt', :password => 'c0d3b4ssssss!')
user = client.user
user.login
# => "defunkt"
While Basic Authentication allows you to get started quickly, OAuth access tokens are the preferred way to authenticate on behalf of users.
OAuth access tokens
OAuth access tokens provide two main benefits over using your username and password:
- Revocable access. Access tokens can be revoked, removing access for only that token without having to change your password everywhere.
- Limited access. Access tokens have access scopes which allow for more granular access to API resources. For instance, you can grant a third party access to your gists but not your private repositories.
To use an access token with the Octokit client, pass your token in the
:access_token
options parameter in lieu of your username and password:
client = Octokit::Client.new(:access_token => "<your 40 char token>")
user = client.user
user.login
# => "defunkt"
You can create access tokens through your GitHub Account Settings.
Two-Factor Authentication
Two-Factor Authentication brings added security to the account by requiring more information to login.
Using two-factor authentication for API calls is as simple as adding the required header as an option:
client = Octokit::Client.new \
:login => 'defunkt',
:password => 'c0d3b4ssssss!'
user = client.user("defunkt", :headers => { "X-GitHub-OTP" => "<your 2FA token>" })
Using a .netrc file
Octokit supports reading credentials from a netrc file (defaulting to
~/.netrc
). Given these lines in your netrc:
machine api.github.com
login defunkt
password c0d3b4ssssss!
You can now create a client with those credentials:
client = Octokit::Client.new(:netrc => true)
client.login
# => "defunkt"
But I want to use OAuth you say. Since the GitHub API supports using an OAuth token as a Basic password, you totally can:
machine api.github.com
login defunkt
password <your 40 char token>
Note: Support for netrc requires adding the [netrc gem][] to your Gemfile
or .gemspec
.
Application authentication
Octokit also supports application-only authentication using OAuth application client credentials. Using application credentials will result in making anonymous API calls on behalf of an application in order to take advantage of the higher rate limit.
client = Octokit::Client.new \
:client_id => "<your 20 char id>",
:client_secret => "<your 40 char secret>"
user = client.user 'defunkt'
GitHub App
Octokit.rb also supports authentication using a GitHub App, which requires a generated JWT token.
client = Octokit::Client.new(:bearer_token => "<your jwt token>")
client.app
# => about GitHub App info
Default results per_page
Default results from the GitHub API are 30, if you wish to add more you must do so during Octokit configuration.
Octokit::Client.new(access_token: "<your 40 char token>", per_page: 100)
Pagination
Many GitHub API resources are paginated. While you may be tempted to start
adding :page
parameters to your calls, the API returns links to the next,
previous, and last pages for you in the Link
response header as Hypermedia
link relations.
issues = client.issues 'rails/rails'
issues.concat client.get(client.last_response.rels[:next].href)
Auto pagination
For smallish resource lists, Octokit provides auto pagination. When this is enabled, calls for paginated resources will fetch and concatenate the results from every page into a single array:
client.auto_paginate = true
issues = client.issues 'rails/rails'
issues.length
# => 702
You can also enable auto pagination for all Octokit client instances:
Octokit.configure do |c|
c.auto_paginate = true
end
Note: While Octokit auto pagination will set the page size to the maximum
100
, and seek to not overstep your rate limit, you probably want to use a
custom pattern for traversing large lists.
Working with GitHub Enterprise
With a bit of setup, you can also use Octokit with your GitHub Enterprise instance.
Interacting with the GitHub.com APIs in GitHub Enterprise
To interact with the "regular" GitHub.com APIs in GitHub Enterprise, simply configure the api_endpoint
to match your hostname. For example:
Octokit.configure do |c|
c.api_endpoint = "https://<hostname>/api/v3/"
end
client = Octokit::Client.new(:access_token => "<your 40 char token>")
Interacting with the GitHub Enterprise Admin APIs
The GitHub Enterprise Admin APIs are under a different client: EnterpriseAdminClient
. You'll need to have an administrator account in order to use these APIs.
admin_client = Octokit::EnterpriseAdminClient.new(
:access_token => "<your 40 char token>",
:api_endpoint => "https://<hostname>/api/v3/"
)
# or
Octokit.configure do |c|
c.api_endpoint = "https://<hostname>/api/v3/"
c.access_token = "<your 40 char token>"
end
admin_client = Octokit.enterprise_admin_client.new
Interacting with the GitHub Enterprise Management Console APIs
The GitHub Enterprise Management Console APIs are also under a separate client: EnterpriseManagementConsoleClient
. In order to use it, you'll need to provide both your management console password as well as the endpoint to your management console. This is different from the API endpoint provided above.
management_console_client = Octokit::EnterpriseManagementConsoleClient.new(
:management_console_password => "secret",
:management_console_endpoint = "https://hostname:8633"
)
# or
Octokit.configure do |c|
c.management_console_endpoint = "https://hostname:8633"
c.management_console_password = "secret"
end
management_console_client = Octokit.enterprise_management_console_client.new
SSL Connection Errors
You may need to disable SSL temporarily while first setting up your GitHub Enterprise install. You can do that with the following configuration:
client.connection_options[:ssl] = { :verify => false }
Do remember to turn :verify
back to true
, as it's important for secure communication.
Configuration and defaults
While Octokit::Client
accepts a range of options when creating a new client
instance, Octokit's configuration API allows you to set your configuration
options at the module level. This is particularly handy if you're creating a
number of client instances based on some shared defaults. Changing options
affects new instances only and will not modify existing Octokit::Client
instances created with previous options.
Configuring module defaults
Every writable attribute in {Octokit::Configurable} can be set one at a time:
Octokit.api_endpoint = 'http://api.github.dev'
Octokit.web_endpoint = 'http://github.dev'
or in batch:
Octokit.configure do |c|
c.api_endpoint = 'http://api.github.dev'
c.web_endpoint = 'http://github.dev'
end
Using ENV variables
Default configuration values are specified in {Octokit::Default}. Many attributes will look for a default value from the ENV before returning Octokit's default.
# Given $OCTOKIT_API_ENDPOINT is "http://api.github.dev"
client.api_endpoint
# => "http://api.github.dev"
Deprecation warnings and API endpoints in development preview warnings are
printed to STDOUT by default, these can be disabled by setting the ENV
OCTOKIT_SILENT=true
.
Timeouts
By default, Octokit does not timeout network requests. To set a timeout, pass in Faraday timeout settings to Octokit's connection_options
setting.
Octokit.configure do |c|
c.api_endpoint = ENV.fetch('GITHUB_API_ENDPOINT', 'https://api.github.com/')
c.connection_options = {
request: {
open_timeout: 5,
timeout: 5
}
}
end
You should set a timeout in order to avoid Ruby’s Timeout module, which can hose your server. Here are some resources for more information on this:
- The Oldest Bug In Ruby - Why Rack::Timeout Might Hose your Server
- Timeout: Ruby's Most Dangerous API
- The Ultimate Guide to Ruby Timeouts
Hypermedia agent
Starting in version 2.0, Octokit is [hypermedia][]-enabled. Under the hood, {Octokit::Client} uses [Sawyer][], a hypermedia client built on [Faraday][].
Hypermedia in Octokit
Resources returned by Octokit methods contain not only data but hypermedia link relations:
user = client.user 'technoweenie'
# Get the repos rel, returned from the API
# as repos_url in the resource
user.rels[:repos].href
# =>