{"id":13558100,"url":"https://github.com/piotrmurach/github","last_synced_at":"2025-12-18T02:02:47.720Z","repository":{"id":1725397,"uuid":"2456210","full_name":"piotrmurach/github","owner":"piotrmurach","description":"Ruby interface to GitHub API","archived":false,"fork":false,"pushed_at":"2023-05-13T06:05:32.000Z","size":7384,"stargazers_count":1177,"open_issues_count":29,"forks_count":313,"subscribers_count":49,"default_branch":"master","last_synced_at":"2025-12-17T08:00:00.902Z","etag":null,"topics":["api-client","api-navigation","api-wrapper","github-api","modular","ruby-gem"],"latest_commit_sha":null,"homepage":"https://piotrmurach.github.io/github","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/piotrmurach.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2011-09-25T19:36:22.000Z","updated_at":"2025-12-16T16:34:56.000Z","dependencies_parsed_at":"2023-07-05T17:15:25.859Z","dependency_job_id":null,"html_url":"https://github.com/piotrmurach/github","commit_stats":{"total_commits":1915,"total_committers":106,"mean_commits":"18.066037735849058","dds":"0.11174934725848562","last_synced_commit":"02ec883ee7038385559854c1081d235cb2dd1245"},"previous_names":["peter-murach/github"],"tags_count":86,"template":false,"template_full_name":null,"purl":"pkg:github/piotrmurach/github","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fgithub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fgithub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fgithub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fgithub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piotrmurach","download_url":"https://codeload.github.com/piotrmurach/github/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fgithub/sbom","scorecard":{"id":734808,"data":{"date":"2025-08-11","repo":{"name":"github.com/piotrmurach/github","commit":"02ec883ee7038385559854c1081d235cb2dd1245"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.7,"checks":[{"name":"Code-Review","score":5,"reason":"Found 12/23 approved changesets -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 19 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T15:28:15.035Z","repository_id":1725397,"created_at":"2025-08-22T15:28:15.035Z","updated_at":"2025-08-22T15:28:15.035Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27789384,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-18T02:00:09.725Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-client","api-navigation","api-wrapper","github-api","modular","ruby-gem"],"created_at":"2024-08-01T12:04:44.843Z","updated_at":"2025-12-18T02:02:47.679Z","avatar_url":"https://github.com/piotrmurach.png","language":"Ruby","readme":"\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"http://piotrmurach.github.io/github/\"\u003e\u003cimg width=\"136\" src=\"https://github.com/piotrmurach/github/raw/master/icons/github_api.png\" alt=\"github api logo\" /\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n# GithubAPI [![Gitter](https://badges.gitter.im/Join%20Chat.svg)][gitter]\n\n[![Gem Version](https://badge.fury.io/rb/github_api.svg)][gem]\n[![Build Status](https://secure.travis-ci.org/piotrmurach/github.svg?branch=master)][travis]\n[![Maintainability](https://api.codeclimate.com/v1/badges/7dc798db81a62774f99b/maintainability)][codeclimate]\n[![Coverage Status](https://coveralls.io/repos/piotrmurach/github/badge.svg?branch=master)][coverage]\n[![Inline docs](http://inch-ci.org/github/piotrmurach/github.svg)][inchpages]\n\n[gitter]: https://gitter.im/piotrmurach/github_api\n[gem]: http://badge.fury.io/rb/github_api\n[travis]: http://travis-ci.org/piotrmurach/github\n[codeclimate]: https://codeclimate.com/github/piotrmurach/github/maintainability\n[coverage]: https://coveralls.io/r/piotrmurach/github\n[inchpages]: http://inch-ci.org/github/piotrmurach/github\n\n[Website](http://piotrmurach.github.io/github/) | [Wiki](https://github.com/piotrmurach/github/wiki) | [RDocs](http://rubydoc.info/github/piotrmurach/github/master/frames)\n\nA Ruby client for the official GitHub API.\n\nSupports all the API methods. It's built in a modular way. You can either instantiate the whole API wrapper Github.new or use parts of it i.e. Github::Client::Repos.new if working solely with repositories is your main concern. Intuitive query methods allow you easily call API endpoints.\n\n## Features\n\n* Intuitive GitHub API interface navigation.\n* It's comprehensive. You can request all GitHub API resources.\n* Modular design allows for working with parts of API.\n* Fully customizable including advanced middleware stack construction.\n* Supports OAuth2 authorization.\n* Flexible argument parsing. You can write expressive and natural queries.\n* Requests pagination with convenient DSL and automatic options.\n* Easy error handling split for client and server type errors.\n* Supports multithreaded environment.\n* Custom media type specification through the 'media' parameter.\n* Request results caching\n* Fully tested with unit and feature tests hitting the live api.\n\n## Installation\n\nInstall the gem by running\n\n```ruby\ngem install github_api\n```\n\nor put it in your Gemfile and run `bundle install`\n\n```ruby\ngem \"github_api\"\n```\n\n## Contents\n\n* [1. Usage](#1-usage)\n    * [1.1 API Navigation](#11-api-navigation)\n    * [1.2 Modularity](#12-modularity)\n    * [1.3 Arguments](#13-arguments)\n    * [1.4 Response Querying](#14-response-querying)\n      * [1.4.1 Response Body](#141-response-body)\n      * [1.4.2 Response Headers](#142-response-headers)\n      * [1.4.3 Response Success](#143-response-success)\n    * [1.5 Request Headers](#15-request-headers)\n      * [1.5.1 Media Types](#151-media-types)\n* [2. Configuration](#2-configuration)\n    * [2.1 Basic](#21-basic)\n    * [2.2 Advanced](#22-advanced)\n    * [2.3 SSL](#23-ssl)\n    * [2.4 Caching](#24-caching)\n* [3. Authentication](#3-authentication)\n    * [3.1 Basic](#31-basic)\n    * [3.2 Authorizations API](#32-authorizations-api)\n    * [3.3 Scopes](#33-scopes)\n    * [3.4 Application OAuth](#34-application-oauth)\n    * [3.5 Two-Factor](#35-two-factor)\n* [4. Pagination](#4-pagination)\n  * [4.1 Auto pagination](#41-auto-pagination)\n* [5. Error Handling](#5-error-handling)\n  * [5.1 Client Error](#51-client-error)\n  * [5.2 Service Error](#52-service-error)\n    * [5.2.1 Data](#521-data)\n    * [5.2.2 Error Messages](#522-error-messages)\n* [6. Examples](#6-examples)\n  * [6.1 Rails](#61-rails)\n  * [6.2 Manipulating Files](#62-manipulating-files)\n* [7. Testing](#7-testing)\n\n## 1 Usage\n\nTo start using the gem, you can either perform requests directly on `Github` namespace:\n\n```ruby\nGithub.repos.list user: 'piotrmurach'\n```\n\nor create a new client instance like so\n\n```ruby\ngithub = Github.new\n```\n\nand then call api methods, for instance, to list a given user repositories do\n\n```ruby\ngithub.repos.list user: 'piotrmurach'\n```\n\n### 1.1 API Navigation\n\nThe **github_api** closely mirrors the [GitHub API](https://developer.github.com/v3/) hierarchy. For example, if you want to create a new file in a repository, look up the GitHub API spec. In there you will find contents sub category underneath the repository category. This would translate to the request:\n\n```ruby\ngithub = Github.new\ngithub.repos.contents.create 'piotrmurach', 'finite_machine', 'hello.rb',\n                             path: 'hello.rb',\n                             content: \"puts 'hello ruby'\"\n```\n\nThe whole library reflects the same api navigation. Therefore, if you need to list releases for a repository do:\n\n```ruby\ngithub.repos.releases.list 'piotrmurach', 'finite_machine'\n```\n\nor to list a user's followers:\n\n```ruby\ngithub.users.followers.list 'piotrmurach'\n```\n\nThe code base has been extensively documented with examples of how to use each method. Please refer to the [documentation](http://rubydoc.info/github/piotrmurach/github/master/frames) under the `Github::Client` class name.\n\nAlternatively, you can find out which methods are supported by an api by calling `actions` on a class or instance. For example, in order to find out available endpoints for `Github::Client::Repos::Contents` api call `actions` method:\n\n```ruby\nGithub::Client::Repos::Contents.actions\n=\u003e [:archive, :create, :delete, :find, :get, :readme, :update]\n```\n\n### 1.2 Modularity\n\nThe code base is modular. This means that you can work specifically with a given part of GitHub API. If you want to only work with activity starring API do the following:\n\n```ruby\nstarring = Github::Client::Activity::Starring.new oauth_token: token\nstarring.star 'piotrmurach', 'github'\n```\n\nPlease refer to the [documentation](http://rubydoc.info/github/piotrmurach/github/master/frames) and look under `Github::Client` to see all available classes.\n\n### 1.3 Arguments\n\nThe **github_api** library allows for flexible argument parsing.\n\nArguments can be passed directly inside the method called. The `required` arguments are passed in first, followed by optional parameters supplied as hash options:\n\n```ruby\nissues = Github::Client::Issues.new\nissues.milestones.list 'piotrmurach', 'github', state: 'open'\n```\n\nIn the previous example, the order of arguments is important. However, each method also allows you to specify `required` arguments using hash symbols and thus remove the need for ordering. Therefore, the same example could be rewritten like so:\n\n```ruby\nissues = Github::Client::Issues.new\nissues.milestones.list user: 'piotrmurach', repo: 'github', state: 'open'\n```\n\nFurthermore, `required` arguments can be passed during instance creation:\n\n```ruby\nissues = Github::Client::Issues.new user: 'piotrmurach', repo: 'github'\nissues.milestones.list state: 'open'\n```\n\nSimilarly, the `required` arguments for the request can be passed inside the current scope such as:\n\n```ruby\nissues = Github::Client::Issues.new\nissues.milestones(user: 'piotrmurach', repo: 'github').list state: 'open'\n```\n\nBut why limit ourselves? You can mix and match arguments, for example:\n\n```ruby\nissues = Github::Client::Issues.new user: 'piotrmurach'\nissues.milestones(repo: 'github').list\nissues.milestones(repo: 'tty').list\n```\n\nYou can also use a bit of syntactic sugar whereby \"username/repository\" can be passed as well:\n\n```ruby\nissues = Github::Client::Issues.new\nissues.milestones('piotrmurach/github').list\nissues.milestones.list 'piotrmurach/github'\n```\n\nFinally, use the `with` scope to clearly denote your requests\n\n```ruby\nissues = Github::Client::Issues.new\nissues.milestones.with(user: 'piotrmurach', repo: 'github').list\n```\n\nPlease consult the method [documentation](http://rubydoc.info/github/piotrmurach/github/master/frames) or [GitHub specification](https://developer.github.com/v3/) to see which arguments are required and what are the option parameters.\n\n### 1.4 Response Querying\n\nThe response is of type `Github::ResponseWrapper` and allows traversing all the json response attributes like method calls. In addition, if the response returns more than one resource, these will be automatically yielded to the provided block one by one.\n\nFor example, when request is issued to list all the branches on a given repository, each branch will be yielded one by one:\n\n```ruby\nrepos = Github::Client::Repos.new\nrepos.branches user: 'piotrmurach', repo: 'github' do |branch|\n  puts branch.name\nend\n```\n\n#### 1.4.1 Response Body\n\nThe `ResponseWrapper` allows you to call json attributes directly as method calls. there is no magic here, all calls are delegated to the response body. Therefore, you can directly inspect request body by calling `body` method on the `ResponseWrapper` like so:\n\n```ruby\nresponse = repos.branches user: 'piotrmurach', repo: 'github'\nresponse.body  # =\u003e Array of branches\n```\n\n#### 1.4.2 Response Headers\n\nEach response comes packaged with methods allowing for inspection of HTTP start line and headers. For example, to check for rate limits and status codes do:\n\n```ruby\nresponse = Github::Client::Repos.branches 'piotrmurach', 'github'\nresponse.headers.ratelimit_limit     # \"5000\"\nresponse.headers.ratelimit_remaining # \"4999\"\nresponse.headers.status              # \"200\"\nresponse.headers.content_type        # \"application/json; charset=utf-8\"\nresponse.headers.etag                # \"\\\"2c5dfc54b3fe498779ef3a9ada9a0af9\\\"\"\nresponse.headers.cache_control       # \"public, max-age=60, s-maxage=60\"\n```\n\n#### 1.4.3 Response Success\n\nIf you want to verify if the response was success, namely, that the `200` code was returned call the `success?` like so:\n\n```ruby\nresponse = Github::Client::Repos.branches 'piotrmurach', 'github'\nresponse.success?  # =\u003e true\n```\n\n### 1.5 Request Headers\n\nIt is possible to specify additional header information which will be added to the final request.\n\nFor example, to set `etag` and `X-Poll_Interval` headers, use the `:headers` hash key inside the `:options` hash like in the following:\n\n```ruby\nevents = Github::Client::Activity::Events.new\nevents.public headers: {\n    'X-Poll-Interval': 60,\n    'ETag': \"a18c3bded88eb5dbb5c849a489412bf3\"\n  }\n```\n\n#### 1.5.1 Media Types\n\nIn order to set custom media types for a request use the accept header. By using the `:accept` key you can determine media type like in the example:\n\n```ruby\nissues = Github::Client::Issues.new\nissues.get 'piotrmurach', 'github', 108, accept: 'application/vnd.github.raw'\n```\n\n## 2 Configuration\n\nThe **github_api** provides ability to specify global configuration options. These options will be available to all api calls.\n\n### 2.1 Basic\n\nThe configuration options can be set by using the `configure` helper\n\n```ruby\nGithub.configure do |c|\n  c.basic_auth = \"login:password\"\n  c.adapter    = :typheous\n  c.user       = 'piotrmurach'\n  c.repo       = 'finite_machine'\nend\n```\n\nAlternatively, you can configure the settings by passing a block to an instance like:\n\n```ruby\nGithub.new do |c|\n  c.endpoint    = 'https://github.company.com/api/v3'\n  c.site        = 'https://github.company.com'\n  c.upload_endpoint = 'https://github.company.com/api/uploads'\nend\n```\n\nor simply by passing hash of options to an instance like so\n\n```ruby\ngithub = Github.new basic_auth: 'login:password',\n                    adapter: :typheous,\n                    user: 'piotrmurach',\n                    repo: 'finite_machine'\n```\n\nThe following is the full list of available configuration options:\n\n```ruby\nadapter            # Http client used for performing requests. Default :net_http\nauto_pagination    # Automatically traverse requests page links. Default false\nbasic_auth         # Basic authentication in form login:password.\nclient_id          # Oauth client id.\nclient_secret      # Oauth client secret.\nconnection_options # Hash of connection options.\nendpoint           # Enterprise API endpoint. Default: 'https://api.github.com'\noauth_token        # Oauth authorization token.\norg                # Global organization used in requests if none provided\nper_page           # Number of items per page. Max of 100. Default 30.\nrepo               # Global repository used in requests in none provided\nsite               # enterprise API web endpoint\nssl                # SSL settings in hash form.\nuser               # Global user used for requests if none provided\nuser_agent         # Custom user agent name. Default 'Github API Ruby Gem'\n```\n\n### 2.2 Advanced\n\nThe **github_api** will use the default middleware stack which is exposed by calling `stack` on a client instance. However, this stack can be freely modified with methods such as `insert`, `insert_after`, `delete` and `swap`. For instance, to add your `CustomMiddleware` do:\n\n```ruby\nGithub.configure do |c|\n  c.stack.insert_after Github::Response::Helpers, CustomMiddleware\nend\n```\n\nFurthermore, you can build your entire custom stack and specify other connection options such as `adapter` by doing:\n\n```ruby\nGithub.new do |c|\n  c.adapter :excon\n\n  c.stack do |builder|\n    builder.use Github::Response::Helpers\n    builder.use Github::Response::Jsonize\n  end\nend\n```\n\n### 2.3 SSL\n\nBy default requests over SSL are set to OpenSSL::SSL::VERIFY_PEER. However, you can turn off peer verification by\n\n```ruby\ngithub = Github.new ssl: { verify: false }\n```\n\nIf your client fails to find CA certs, you can pass other SSL options to specify exactly how the information is sourced\n\n```ruby\nssl: {\n  client_cert: \"/usr/local/www.example.com/client_cert.pem\"\n  client_key:  \"/user/local/www.example.com/client_key.pem\"\n  ca_file:     \"example.com.cert\"\n  ca_path:     \"/etc/ssl/\"\n}\n```\n\nFor instance, download CA root certificates from Mozilla [cacert](http://curl.haxx.se/ca/cacert.pem) and point ca_file at your certificate bundle location. This will allow the client to verify the github.com ssl certificate as authentic.\n\n### 2.4 Caching\n\nCaching is supported through the [`faraday-http-cache` gem](https://github.com/plataformatec/faraday-http-cache).\n\nAdd the gem to your Gemfile:\n\n```ruby\ngem 'faraday-http-cache'\n```\n\nYou can now configure cache parameters as follows\n\n```ruby\nGithub.configure do |config|\n  config.stack = proc do |builder|\n    builder.use Faraday::HttpCache, store: Rails.cache\n  end\nend\n```\n\nMore details on the available options can be found in the gem's own documentation: https://github.com/plataformatec/faraday-http-cache#faraday-http-cache\n\n## 3 Authentication\n\n### 3.1 Basic\n\nTo start making requests as authenticated user you can use your GitHub username and password like so\n\n```ruby\nGithub.new basic_auth: 'login:password'\n```\n\nThough this method is convenient you should strongly consider using `OAuth` for improved security reasons.\n\n### 3.2 Authorizations API\n\n#### 3.2.1 For a User\n\nTo create an access token through the GitHub Authorizations API, you are required to pass your basic credentials and scopes you wish to have for the authentication token.\n\n```ruby\ngithub = Github.new basic_auth: 'login:password'\ngithub.auth.create scopes: ['repo'], note: 'admin script'\n```\n\nYou can add more than one scope from the `user`, `public_repo`, `repo`, `gist` or leave the scopes parameter out, in which case, the default read-only access will be assumed (includes public user profile info, public repo info, and gists).\n\n#### 3.2.2 For an App\n\nFurthermore, to create auth token for an application you need to pass `:app` argument together with `:client_id` and `:client_secret` parameters.\n\n```ruby\ngithub = Github.new basic_auth: 'login:password'\ngithub.auth.app.create 'client-id', scopes: ['repo']\n```\n\nIn order to revoke auth token(s) for an application you must use basic authentication with `client_id` as login and `client_secret` as password.\n\n```ruby\ngithub = Github.new basic_auth: \"client_id:client_secret\"\ngithub.auth.app.delete 'client-id'\n```\n\nRevoke a specific app token.\n\n```ruby\ngithub.auth.app.delete 'client-id', 'access-token'\n```\n\n### 3.3 Scopes\n\nYou can check OAuth scopes you have by:\n\n```ruby\ngithub = Github.new oauth_token: 'token'\ngithub.scopes.list    # =\u003e ['repo']\n```\n\nor inidividually for a given user:\n\n```ruby\ngithub = Github.new\ngithub.scopes.list 'token'\n```\n\nTo list the scopes that the particular GitHub API action checks for do:\n\n```ruby\nrepos = Github::Client::Repos.new\nresponse = repos.list user: 'piotrmurach'\nresponse.headers.accepted_oauth_scopes  # =\u003e ['delete_repo', 'repo', 'public_repo']\n```\n\nTo understand what each scope means refer to [documentation](http://developer.github.com/v3/oauth/#scopes)\n\n### 3.4 Application OAuth\n\nIn order to authenticate your app through OAuth2 on GitHub you need to\n\n* Visit https://github.com/settings/applications/new and register your app.\n  You will need to be logged in to initially register the application.\n\n* Authorize your credentials https://github.com/login/oauth/authorize\n\nYou can use convenience methods to help you achieve this using **GithubAPI** gem:\n\n```ruby\ngithub = Github.new client_id: '...', client_secret: '...'\ngithub.authorize_url redirect_uri: 'http://localhost', scope: 'repo'\n# =\u003e \"https://github.com/login/oauth/authorize?scope=repo\u0026response_type=code\u0026client_id='...'\u0026redirect_uri=http%3A%2F%2Flocalhost\"\n```\nAfter you get your authorization code, call to receive your access_token\n\n```ruby\ntoken = github.get_token( authorization_code )\n```\n\nOnce you have your access token, configure your github instance following instructions under Configuration.\n\n**Note**: If you are working locally (i.e. your app URL and callback URL are localhost), do not specify a ```:redirect_uri``` otherwise you will get a ```redirect_uri_mismatch``` error.\n\n### 3.5 Two-Factor\n\nIn order to use [Two-Factor](https://help.github.com/articles/about-two-factor-authentication) authentication you need provide `X-GitHub-OTP: required; :2fa-type` header.\n\nYou can add headers during initialization:\n\n```ruby\nGithub.new do |config|\n  config.basic_auth         = \"user:password\"\n  config.connection_options = {headers: {\"X-GitHub-OTP\" =\u003e '2fa token'}}\nend\n```\n\nor per request:\n\n```ruby\ngithub = Github.new basic_auth: 'login:password'\ngithub.oauth.create scopes: [\"public_repo\"],\n                    headers: {\"X-GitHub-OTP\" =\u003e \"2fa token\"}\n```\n\n## 4 Pagination\n\nAny request that returns multiple items will be paginated to 30 items by default. You can specify custom `page` and `per_page` query parameters to alter default behavior. For instance:\n\n```ruby\nrepos    = Github::Client::Repos.new\nresponse = repos.list user: 'wycats', per_page: 10, page: 5\n```\n\nThen you can query the pagination information included in the link header by:\n\n```ruby\nresponse.links.first  # Shows the URL of the first page of results.\nresponse.links.next   # Shows the URL of the immediate next page of results.\nresponse.links.prev   # Shows the URL of the immediate previous page of results.\nresponse.links.last   # Shows the URL of the last page of results.\n```\n\nIn order to iterate through the entire result set page by page, you can use convenience methods:\n\n```ruby\nresponse.each_page do |page|\n  page.each do |repo|\n    puts repo.name\n  end\nend\n```\n\nor use `has_next_page?` and `next_page` helper methods like in the following:\n\n```ruby\nwhile response.has_next_page?\n  ... process response ...\n  res.next_page\nend\n```\n\nOne can also navigate straight to the specific page by:\n\n```ruby\nres.count_pages  # Number of pages\nres.page 5       # Requests given page if it exists, nil otherwise\nres.first_page   # Get first page\nres.next_page    # Get next page\nres.prev_page    # Get previous page\nres.last_page    # Get last page\n```\n\n### 4.1 Auto pagination\n\nYou can retrieve all pages in one invocation by passing the `auto_pagination` option like so:\n\n```ruby\ngithub = Github.new auto_pagination: true\n```\n\nDepending at what stage you pass the `auto_pagination` it will affect all or only a single request. For example, in order to auto paginate all Repository API methods do:\n\n```ruby\nGithub::Сlient::Repos.new auto_pagination: true\n```\n\nHowever, to only auto paginate results for a single request do:\n\n```ruby\nGithub::Client::Repos.new.list user: '...', auto_pagination: true\n```\n\n## 5 Error Handling\n\nThe generic error class `Github::Error::GithubError` will handle both the client (`Github::Error::ClientError`) and service (`Github::Error::ServiceError`) side errors.\n\nFor instance in your code you can catch errors like\n\n```ruby\nbegin\n  # Do something with github_api gem\nrescue Github::Error::GithubError =\u003e e\n  puts e.message\n  if e.is_a? Github::Error::ServiceError\n    # handle GitHub service errors such as 404\n  elsif e.is_a? Github::Error::ClientError\n    # handle client errors e.i. missing required parameter in request\n  end\nend\n```\n\n### 5.1 Client Error\n\nAny time **Github** client has a problem sending request a `Github::Error::ClientError` is raised that will provide a summary of the problem and possible solutions.\n\n### 5.2 Service Error\n\nWhen the **Github** client receives a HTTP response from GitHub service that indicates error then `Github::Error::ServiceError` is raised.\n\nThere are number of specific error types such as `Github::Error::NotAcceptable` when `406` status code is returned.\n\n#### 5.2.1 Data\n\nWhen `Github::Error::ServiceError` is raised you can call `data` to access it payload in JSON format.\n\n#### 5.2.2 Error messages\n\nAnytime there are error messages provided with `Github::Error::ServiceError` you can access them by calling `error_messages` helper.\n\n## 6 Examples\n\n### 6.1 Rails\n\nA Rails controller that allows a user to authorize their GitHub account and then performs a request.\n\n```ruby\nclass GithubController \u003c ApplicationController\n\n  def authorize\n    address = github.authorize_url redirect_uri: 'http://...', scope: 'repo'\n    redirect_to address\n  end\n\n  def callback\n    authorization_code = params[:code]\n    access_token = github.get_token authorization_code\n    access_token.token   # =\u003e returns token value\n  end\n\n  private\n\n   def github\n    @github ||= Github.new client_id: '...', client_secret: '...'\n   end\nend\n```\n\n### 6.2 Manipulating Files\n\nIn order to be able to create/update/remove files you need to use Contents API like so:\n\n```ruby\ncontents = Github::Client::Repos::Contents.new oauth_token: '...'\n```\n\nHaving instantiated the contents, to create a file do:\n\n```ruby\ncontents.create 'username', 'repo_name', 'full_path_to/file.ext',\n  path: 'full_path_to/file.ext',\n  message: 'Your commit message',\n  content: 'The contents of your file'\n```\n\nContent is all Base64 encoded to/from the API, and when you create a file it encodes it automatically for you.\n\nTo update a file, first you need to find the file so you can get the SHA you're updating off of:\n\n```ruby\nfile = contents.find path: 'full_path_to/file.ext'\n```\n\nThen update the file just like you do with creating:\n\n```ruby\ncontents.update 'username', 'repo_name', 'full_path_to/file.ext',\n  path: 'full_path_to/file.ext'\n  message: 'Your commit message',\n  content: 'The contents to be updated',\n  sha: file.sha\n```\n\nFinally to remove a file, find the file so you can get the SHA you're removing:\n\n```ruby\nfile = contents.find path: 'full_path_to/file.ext'\n```\n\nThen delete the file like so:\n\n```ruby\ngithub.delete 'username', 'tome-of-knowledge', 'full_path_to/file.ext',\n  path: 'full_path_to/file.ext',\n  message: 'Your Commit Message',\n  sha: file.sha\n```\n\n## 7 Testing\n\nThe test suite is split into two groups, `live` and `mock`.\n\nThe `live` tests are in the `features` folder and exercise the GitHub API directly by making live requests and then caching responses with VCR in directory named `features\\cassettes`. For details on how to get set up, please navigate to the `features` folder.\n\nTo run all feature tests do:\n\n```ruby\nbundle exec rake features\n```\n\nThe `mock` tests are in the `spec` folder and their primary concern is to test the gem internals without the hindrance of external calls.\n\nTo run all specs do:\n\n```ruby\nbundle exec rake spec\n```\n\nFinally to run all tests do:\n\n```ruby\nbundle exec rake\n```\n\n## Development\n\nQuestions or problems? Please post them on the [issue tracker](https://github.com/piotrmurach/github/issues). You can contribute changes by forking the project and submitting a pull request. You can ensure the tests are passing by running `bundle` and `rake`.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/piotrmurach/github. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.\n\n## Copyright\n\nCopyright (c) 2011 Piotr Murach. See LICENSE.txt for further details.\n","funding_links":[],"categories":["Ruby","github-api"],"sub_categories":["Gems"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiotrmurach%2Fgithub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiotrmurach%2Fgithub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiotrmurach%2Fgithub/lists"}