Add bin and edit workflow
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 9s

This commit is contained in:
2026-09-16 13:11:16 -06:00
parent c8ac4fcae5
commit 4cee170d66
17576 changed files with 895740 additions and 2 deletions
@@ -0,0 +1,14 @@
# frozen_string_literal: true
module Octokit
# Extracts options from method arguments
# @private
class Arguments < Array
attr_reader :options
def initialize(args)
@options = args.last.is_a?(::Hash) ? args.pop : {}
super(args)
end
end
end
@@ -0,0 +1,80 @@
# frozen_string_literal: true
module Octokit
# Authentication methods for {Octokit::Client}
module Authentication
# In Faraday 2.x, the authorization middleware uses new interface
FARADAY_BASIC_AUTH_KEYS =
if Gem::Version.new(Faraday::VERSION) >= Gem::Version.new('2.0')
%i[authorization basic]
else
[:basic_auth]
end
# Indicates if the client was supplied Basic Auth
# username and password
#
# @see https://developer.github.com/v3/#authentication
# @return [Boolean]
def basic_authenticated?
!!(@login && @password)
end
# Indicates if the client was supplied an OAuth
# access token
#
# @see https://developer.github.com/v3/#authentication
# @return [Boolean]
def token_authenticated?
!!@access_token
end
# Indicates if the client was supplied a bearer token
#
# @see https://developer.github.com/early-access/integrations/authentication/#as-an-integration
# @return [Boolean]
def bearer_authenticated?
!!@bearer_token
end
# Indicates if the client was supplied an OAuth
# access token or Basic Auth username and password
#
# @see https://developer.github.com/v3/#authentication
# @return [Boolean]
def user_authenticated?
basic_authenticated? || token_authenticated?
end
# Indicates if the client has OAuth Application
# client_id and secret credentials to make anonymous
# requests at a higher rate limit
#
# @see https://developer.github.com/v3/#unauthenticated-rate-limited-requests
# @return [Boolean]
def application_authenticated?
!!(@client_id && @client_secret)
end
private
def login_from_netrc
return unless netrc?
require 'netrc'
info = Netrc.read netrc_file
netrc_host = URI.parse(api_endpoint).host
creds = info[netrc_host]
if creds.nil?
# creds will be nil if there is no netrc for this end point
octokit_warn "Error loading credentials from netrc file for #{api_endpoint}"
else
creds = creds.to_a
self.login = creds.shift
self.password = creds.shift
end
rescue LoadError
octokit_warn 'Please install netrc gem for .netrc support'
end
end
end
@@ -0,0 +1,272 @@
# frozen_string_literal: true
require 'octokit/connection'
require 'octokit/warnable'
require 'octokit/arguments'
require 'octokit/repo_arguments'
require 'octokit/configurable'
require 'octokit/authentication'
require 'octokit/gist'
require 'octokit/rate_limit'
require 'octokit/repository'
require 'octokit/user'
require 'octokit/organization'
require 'octokit/client/actions_artifacts'
require 'octokit/client/actions_secrets'
require 'octokit/client/actions_workflows'
require 'octokit/client/actions_workflow_jobs'
require 'octokit/client/actions_workflow_runs'
require 'octokit/client/apps'
require 'octokit/client/checks'
require 'octokit/client/commits'
require 'octokit/client/commit_comments'
require 'octokit/client/commit_pulls'
require 'octokit/client/commit_branches'
require 'octokit/client/community_profile'
require 'octokit/client/contents'
require 'octokit/client/downloads'
require 'octokit/client/deployments'
require 'octokit/client/environments'
require 'octokit/client/emojis'
require 'octokit/client/events'
require 'octokit/client/feeds'
require 'octokit/client/gists'
require 'octokit/client/gitignore'
require 'octokit/client/hooks'
require 'octokit/client/issues'
require 'octokit/client/labels'
require 'octokit/client/legacy_search'
require 'octokit/client/licenses'
require 'octokit/client/meta'
require 'octokit/client/markdown'
require 'octokit/client/marketplace'
require 'octokit/client/milestones'
require 'octokit/client/notifications'
require 'octokit/client/oauth_applications'
require 'octokit/client/objects'
require 'octokit/client/organizations'
require 'octokit/client/pages'
require 'octokit/client/projects'
require 'octokit/client/pub_sub_hubbub'
require 'octokit/client/pull_requests'
require 'octokit/client/rate_limit'
require 'octokit/client/reactions'
require 'octokit/client/refs'
require 'octokit/client/releases'
require 'octokit/client/repositories'
require 'octokit/client/repository_invitations'
require 'octokit/client/reviews'
require 'octokit/client/say'
require 'octokit/client/search'
require 'octokit/client/service_status'
require 'octokit/client/source_import'
require 'octokit/client/stats'
require 'octokit/client/statuses'
require 'octokit/client/tokens'
require 'octokit/client/traffic'
require 'octokit/client/users'
require 'ext/sawyer/relation'
module Octokit
# Client for the GitHub API
#
# @see https://developer.github.com
class Client
include Octokit::Authentication
include Octokit::Configurable
include Octokit::Connection
include Octokit::Warnable
include Octokit::Client::ActionsArtifacts
include Octokit::Client::ActionsSecrets
include Octokit::Client::Checks
include Octokit::Client::Commits
include Octokit::Client::CommitComments
include Octokit::Client::CommitPulls
include Octokit::Client::CommitBranches
include Octokit::Client::CommunityProfile
include Octokit::Client::Contents
include Octokit::Client::Deployments
include Octokit::Client::Downloads
include Octokit::Client::Environments
include Octokit::Client::Emojis
include Octokit::Client::Events
include Octokit::Client::Feeds
include Octokit::Client::Gists
include Octokit::Client::Gitignore
include Octokit::Client::Hooks
include Octokit::Client::ActionsWorkflows
include Octokit::Client::ActionsWorkflowJobs
include Octokit::Client::ActionsWorkflowRuns
include Octokit::Client::Apps
include Octokit::Client::Issues
include Octokit::Client::Labels
include Octokit::Client::LegacySearch
include Octokit::Client::Licenses
include Octokit::Client::Meta
include Octokit::Client::Markdown
include Octokit::Client::Marketplace
include Octokit::Client::Milestones
include Octokit::Client::Notifications
include Octokit::Client::OauthApplications
include Octokit::Client::Objects
include Octokit::Client::Organizations
include Octokit::Client::Pages
include Octokit::Client::Projects
include Octokit::Client::PubSubHubbub
include Octokit::Client::PullRequests
include Octokit::Client::RateLimit
include Octokit::Client::Reactions
include Octokit::Client::Refs
include Octokit::Client::Releases
include Octokit::Client::Repositories
include Octokit::Client::RepositoryInvitations
include Octokit::Client::Reviews
include Octokit::Client::Say
include Octokit::Client::Search
include Octokit::Client::ServiceStatus
include Octokit::Client::SourceImport
include Octokit::Client::Stats
include Octokit::Client::Statuses
include Octokit::Client::Tokens
include Octokit::Client::Traffic
include Octokit::Client::Users
# Header keys that can be passed in options hash to {#get},{#head}
CONVENIENCE_HEADERS = Set.new(%i[accept content_type])
def initialize(options = {})
# Use options passed in, but fall back to module defaults
#
# rubocop:disable Style/HashEachMethods
#
# This may look like a `.keys.each` which should be replaced with `#each_key`, but
# this doesn't actually work, since `#keys` is just a method we've defined ourselves.
# The class doesn't fulfill the whole `Enumerable` contract.
Octokit::Configurable.keys.each do |key|
# rubocop:enable Style/HashEachMethods
value = options[key].nil? ? Octokit.instance_variable_get(:"@#{key}") : options[key]
instance_variable_set(:"@#{key}", value)
end
login_from_netrc unless user_authenticated? || application_authenticated?
end
# Text representation of the client, masking tokens and passwords
#
# @return [String]
def inspect
inspected = super
# mask password
inspected.gsub! @password, '*******' if @password
if @management_console_password
inspected.gsub! @management_console_password, '*******'
end
inspected.gsub! @bearer_token, '********' if @bearer_token
# Only show last 4 of token, secret
if @access_token
inspected.gsub! @access_token, "#{'*' * 36}#{@access_token[36..]}"
end
if @client_secret
inspected.gsub! @client_secret, "#{'*' * 36}#{@client_secret[36..]}"
end
inspected
end
# Duplicate client using client_id and client_secret as
# Basic Authentication credentials.
# @example
# Octokit.client_id = "foo"
# Octokit.client_secret = "bar"
#
# # GET https://api.github.com/?client_id=foo&client_secret=bar
# Octokit.get "/"
#
# Octokit.client.as_app do |client|
# # GET https://foo:bar@api.github.com/
# client.get "/"
# end
def as_app(key = client_id, secret = client_secret)
if key.to_s.empty? || secret.to_s.empty?
raise ApplicationCredentialsRequired, 'client_id and client_secret required'
end
app_client = dup
app_client.client_id = app_client.client_secret = nil
app_client.login = key
app_client.password = secret
yield app_client if block_given?
end
# Set username for authentication
#
# @param value [String] GitHub username
def login=(value)
reset_agent
@login = value
end
# Set password for authentication
#
# @param value [String] GitHub password
def password=(value)
reset_agent
@password = value
end
# Set OAuth access token for authentication
#
# @param value [String] 40 character GitHub OAuth access token
def access_token=(value)
reset_agent
@access_token = value
end
# Set Bearer Token for authentication
#
# @param value [String] JWT
def bearer_token=(value)
reset_agent
@bearer_token = value
end
# Set OAuth app client_id
#
# @param value [String] 20 character GitHub OAuth app client_id
def client_id=(value)
reset_agent
@client_id = value
end
# Set OAuth app client_secret
#
# @param value [String] 40 character GitHub OAuth app client_secret
def client_secret=(value)
reset_agent
@client_secret = value
end
def client_without_redirects(options = {})
conn_opts = @connection_options
conn_opts[:url] = @api_endpoint
conn_opts[:builder] = @middleware.dup if @middleware
conn_opts[:proxy] = @proxy if @proxy
conn_opts[:ssl] = { verify_mode: @ssl_verify_mode } if @ssl_verify_mode
conn = Faraday.new(conn_opts) do |http|
if basic_authenticated?
http.request(*FARADAY_BASIC_AUTH_KEYS, @login, @password)
elsif token_authenticated?
http.request :authorization, 'token', @access_token
elsif bearer_authenticated?
http.request :authorization, 'Bearer', @bearer_token
end
http.headers['accept'] = options[:accept] if options.key?(:accept)
end
conn.builder.delete(Octokit::Middleware::FollowRedirects)
conn
end
end
end
@@ -0,0 +1,71 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Actions Artifacts API
#
# @see https://developer.github.com/v3/actions/artifacts
module ActionsArtifacts
# List all artifacts for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
#
# @return [Sawyer::Resource] the total count and an array of artifacts
# @see https://developer.github.com/v3/actions/artifacts#list-artifacts-for-a-repository
def repository_artifacts(repo, options = {})
paginate "#{Repository.path repo}/actions/artifacts", options do |data, last_response|
data.artifacts.concat last_response.data.artifacts
end
end
# List all artifacts for a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param workflow_run_id [Integer] Id of a workflow run
#
# @return [Sawyer::Resource] the total count and an array of artifacts
# @see https://docs.github.com/en/rest/actions/artifacts#list-workflow-run-artifacts
def workflow_run_artifacts(repo, workflow_run_id, options = {})
paginate "#{Repository.path repo}/actions/runs/#{workflow_run_id}/artifacts", options do |data, last_response|
data.artifacts.concat last_response.data.artifacts
end
end
# Get an artifact
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of an artifact
#
# @return [Sawyer::Resource] Artifact information
# @see https://docs.github.com/en/rest/actions/artifacts#get-an-artifact
def artifact(repo, id, options = {})
get "#{Repository.path repo}/actions/artifacts/#{id}", options
end
# Get a download URL for an artifact
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of an artifact
#
# @return [String] URL to the .zip archive of the artifact
# @see https://docs.github.com/en/rest/actions/artifacts#download-an-artifact
def artifact_download_url(repo, id, options = {})
url = "#{Repository.path repo}/actions/artifacts/#{id}/zip"
response = client_without_redirects.head(url, options)
response.headers['Location']
end
# Delete an artifact
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of an artifact
#
# @return [Boolean] Return true if the artifact was successfully deleted
# @see https://docs.github.com/en/rest/actions/artifacts#delete-an-artifact
def delete_artifact(repo, id, options = {})
boolean_from_response :delete, "#{Repository.path repo}/actions/artifacts/#{id}", options
end
end
end
end
@@ -0,0 +1,59 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Actions Secrets API
#
# @see https://developer.github.com/v3/actions/secrets/
module ActionsSecrets
# Get public key for secrets encryption
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Hash] key_id and key
# @see https://developer.github.com/v3/actions/secrets/#get-your-public-key
def get_public_key(repo)
get "#{Repository.path repo}/actions/secrets/public-key"
end
# List secrets
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Hash] total_count and list of secrets (each item is hash with name, created_at and updated_at)
# @see https://developer.github.com/v3/actions/secrets/#list-secrets-for-a-repository
def list_secrets(repo)
paginate "#{Repository.path repo}/actions/secrets" do |data, last_response|
data.secrets.concat last_response.data.secrets
end
end
# Get a secret
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param name [String] Name of secret
# @return [Hash] name, created_at and updated_at
# @see https://developer.github.com/v3/actions/secrets/#get-a-secret
def get_secret(repo, name)
get "#{Repository.path repo}/actions/secrets/#{name}"
end
# Create or update secrets
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param name [String] Name of secret
# @param options [Hash] encrypted_value and key_id
# @see https://developer.github.com/v3/actions/secrets/#create-or-update-a-secret-for-a-repository
def create_or_update_secret(repo, name, options)
put "#{Repository.path repo}/actions/secrets/#{name}", options
end
# Delete a secret
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param name [String] Name of secret
# @see https://developer.github.com/v3/actions/secrets/#delete-a-secret-from-a-repository
def delete_secret(repo, name)
boolean_from_response :delete, "#{Repository.path repo}/actions/secrets/#{name}"
end
end
end
end
@@ -0,0 +1,65 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Actions Workflows jobs API
#
# @see https://docs.github.com/rest/actions/workflow-jobs
module ActionsWorkflowJobs
# Get a job for a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param job_id [Integer, String] Id of the job
#
# @return [Sawyer::Resource] Job information
# @see https://docs.github.com/rest/actions/workflow-jobs#get-a-job-for-a-workflow-run
def workflow_run_job(repo, job_id, options = {})
get "#{Repository.path repo}/actions/jobs/#{job_id}", options
end
# Download job logs for a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param job_id [Integer, String] Id of the job
#
# @return [String] URL to the archived log files of the job
# @see https://docs.github.com/rest/actions/workflow-jobs#download-job-logs-for-a-workflow-run
def workflow_run_job_logs(repo, job_id, options = {})
url = "#{Repository.path repo}/actions/jobs/#{job_id}/logs"
response = client_without_redirects.head(url, options)
response.headers['Location']
end
# List jobs for a workflow run attempt
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param run_id [Integer, String] Id of the workflow run
# @param attempt_number [Integer, String] Attempt number of the workflow run
#
# @return [Sawyer::Resource] Jobs information
# @see https://docs.github.com/rest/actions/workflow-jobs#list-jobs-for-a-workflow-run-attempt
def workflow_run_attempt_jobs(repo, run_id, attempt_number, options = {})
paginate "#{Repository.path repo}/actions/runs/#{run_id}/attempts/#{attempt_number}/jobs", options do |data, last_response|
data.jobs.concat last_response.data.jobs
end
end
alias list_workflow_run_attempt_jobs workflow_run_attempt_jobs
# List jobs for a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param run_id [Integer, String] Id of the workflow run
# @option options [String] :filter Optional filtering by a `completed_at` timestamp
#
# @return [Sawyer::Resource] Jobs information
# @see https://docs.github.com/rest/actions/workflow-jobs#list-jobs-for-a-workflow-run
def workflow_run_jobs(repo, run_id, options = {})
paginate "#{Repository.path repo}/actions/runs/#{run_id}/jobs", options do |data, last_response|
data.jobs.concat last_response.data.jobs
end
end
alias list_workflow_run_jobs workflow_run_jobs
end
end
end
@@ -0,0 +1,125 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Actions Workflows runs API
#
# @see https://docs.github.com/rest/actions/workflow-runs
module ActionsWorkflowRuns
# List all runs for a repository workflow
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param workflow [Integer, String] Id or file name of the workflow
# @option options [String] :actor Optional filtering by a user
# @option options [String] :branch Optional filtering by a branch
# @option options [String] :event Optional filtering by the event type
# @option options [String] :status Optional filtering by a status or conclusion
#
# @return [Sawyer::Resource] the total count and an array of workflows
# @see https://developer.github.com/v3/actions/workflow-runs/#list-workflow-runs
def workflow_runs(repo, workflow, options = {})
paginate "#{Repository.path repo}/actions/workflows/#{workflow}/runs", options do |data, last_response|
data.workflow_runs.concat last_response.data.workflow_runs
end
end
alias list_workflow_runs workflow_runs
# List all workflow runs for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @option options [String] :actor Optional filtering by the login of a user
# @option options [String] :branch Optional filtering by a branch
# @option options [String] :event Optional filtering by the event type (e.g. push, pull_request, issue)
# @option options [String] :status Optional filtering by a status or conclusion (e.g. success, completed...)
#
# @return [Sawyer::Resource] the total count and an array of workflows
# @see https://developer.github.com/v3/actions/workflow-runs/#list-repository-workflow-runs
def repository_workflow_runs(repo, options = {})
paginate "#{Repository.path repo}/actions/runs", options do |data, last_response|
data.workflow_runs.concat last_response.data.workflow_runs
end
end
alias list_repository_workflow_runs repository_workflow_runs
# Get a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of a workflow run
#
# @return [Sawyer::Resource] Run information
# @see https://developer.github.com/v3/actions/workflow-runs/#get-a-workflow-run
def workflow_run(repo, id, options = {})
get "#{Repository.path repo}/actions/runs/#{id}", options
end
# Re-runs a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of a workflow run
#
# @return [Boolean] Returns true if the re-run request was accepted
# @see https://developer.github.com/v3/actions/workflow-runs/#re-run-a-workflow
def rerun_workflow_run(repo, id, options = {})
boolean_from_response :post, "#{Repository.path repo}/actions/runs/#{id}/rerun", options
end
# Cancels a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of a workflow run
#
# @return [Boolean] Returns true if the cancellation was accepted
# @see https://developer.github.com/v3/actions/workflow-runs/#cancel-a-workflow-run
def cancel_workflow_run(repo, id, options = {})
boolean_from_response :post, "#{Repository.path repo}/actions/runs/#{id}/cancel", options
end
# Deletes a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of a workflow run
#
# @return [Boolean] Returns true if the run is deleted
# @see https://docs.github.com/en/rest/reference/actions#delete-a-workflow-run
def delete_workflow_run(repo, id, options = {})
boolean_from_response :delete, "#{Repository.path repo}/actions/runs/#{id}", options
end
# Get a download url for archived log files of a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of a workflow run
#
# @return [String] URL to the archived log files of the run
# @see https://developer.github.com/v3/actions/workflow-runs/#download-workflow-run-logs
def workflow_run_logs(repo, id, options = {})
url = "#{Repository.path repo}/actions/runs/#{id}/logs"
response = client_without_redirects.head(url, options)
response.headers['Location']
end
# Delete all log files of a workflow run
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of a workflow run
#
# @return [Boolean] Returns true if the logs are deleted
# @see https://developer.github.com/v3/actions/workflow-runs/#delete-workflow-run-logs
def delete_workflow_run_logs(repo, id, options = {})
boolean_from_response :delete, "#{Repository.path repo}/actions/runs/#{id}/logs", options
end
# Get workflow run usage
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] Id of a workflow run
#
# @return [Sawyer::Resource] Run usage
# @see https://developer.github.com/v3/actions/workflow-runs/#get-workflow-run-usage
def workflow_run_usage(repo, id, options = {})
get "#{Repository.path repo}/actions/runs/#{id}/timing", options
end
end
end
end
@@ -0,0 +1,68 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Actions Workflows API
#
# @see https://developer.github.com/v3/actions/workflows
module ActionsWorkflows
# Get the workflows in a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
#
# @return [Sawyer::Resource] the total count and an array of workflows
# @see https://developer.github.com/v3/actions/workflows/#list-repository-workflows
def workflows(repo, options = {})
paginate "#{Repository.path repo}/actions/workflows", options do |data, last_response|
data.workflows.concat last_response.data.workflows
end
end
alias list_workflows workflows
# Get single workflow in a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer, String] Id or file name of the workflow
#
# @return [Sawyer::Resource] A single workflow
# @see https://developer.github.com/v3/actions/workflows/#get-a-workflow
def workflow(repo, id, options = {})
get "#{Repository.path repo}/actions/workflows/#{id}", options
end
# Create a workflow dispatch event
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer, String] Id or file name of the workflow
# @param ref [String] A SHA, branch name, or tag name
#
# @return [Boolean] True if event was dispatched, false otherwise
# @see https://docs.github.com/en/rest/reference/actions#create-a-workflow-dispatch-event
def workflow_dispatch(repo, id, ref, options = {})
boolean_from_response :post, "#{Repository.path repo}/actions/workflows/#{id}/dispatches", options.merge({ ref: ref })
end
# Enable a workflow
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer, String] Id or file name of the workflow
#
# @return [Boolean] True if workflow was enabled, false otherwise
# @see https://docs.github.com/en/rest/actions/workflows#enable-a-workflow
def workflow_enable(repo, id, options = {})
boolean_from_response :put, "#{Repository.path repo}/actions/workflows/#{id}/enable", options
end
# Disable a workflow
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer, String] Id or file name of the workflow
#
# @return [Boolean] True if workflow was disabled, false otherwise
# @see https://docs.github.com/en/rest/actions/workflows#disable-a-workflow
def workflow_disable(repo, id, options = {})
boolean_from_response :put, "#{Repository.path repo}/actions/workflows/#{id}/disable", options
end
end
end
end
@@ -0,0 +1,222 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Apps API
module Apps
# Get the authenticated App
#
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/#get-the-authenticated-app
#
# @return [Sawyer::Resource] App information
def app(options = {})
get 'app', options
end
# Find all installations that belong to an App
#
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/#list-installations
#
# @return [Array<Sawyer::Resource>] the total_count and an array of installations
def find_app_installations(options = {})
paginate 'app/installations', options
end
alias find_installations find_app_installations
def find_integration_installations(options = {})
octokit_warn(
'Deprecated: Octokit::Client::Apps#find_integration_installations ' \
'method is deprecated. Please update your call to use ' \
'Octokit::Client::Apps#find_app_installations before the next major ' \
'Octokit version update.'
)
find_app_installations(options)
end
# Find all installations that are accessible to the authenticated user
#
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/installations/#list-installations-for-a-user
#
# @return [Sawyer::Resource] the total_count and an array of installations
def find_user_installations(options = {})
paginate('user/installations', options) do |data, last_response|
data.installations.concat last_response.data.installations
end
end
# Get a single installation
#
# @param id [Integer] Installation id
#
# @see https://developer.github.com/v3/apps/#get-an-installation
#
# @return [Sawyer::Resource] Installation information
def installation(id, options = {})
get "app/installations/#{id}", options
end
# Create a new installation token
#
# @param installation [Integer] The id of a GitHub App Installation
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/#create-a-new-installation-token
#
# @return [<Sawyer::Resource>] An installation token
def create_app_installation_access_token(installation, options = {})
post "app/installations/#{installation}/access_tokens", options
end
alias create_installation_access_token create_app_installation_access_token
def create_integration_installation_access_token(installation, options = {})
octokit_warn(
'Deprecated: Octokit::Client::Apps#create_integration_installation_access_token ' \
'method is deprecated. Please update your call to use ' \
'Octokit::Client::Apps#create_app_installation_access_token before the next major ' \
'Octokit version update.'
)
create_app_installation_access_token(installation, options)
end
# Enables an app to find the organization's installation information.
#
# @param organization [String] Organization GitHub login
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/#get-an-organization-installation
#
# @return [Sawyer::Resource] Installation information
def find_organization_installation(organization, options = {})
get "#{Organization.path(organization)}/installation", options
end
# Enables an app to find the repository's installation information.
#
# @param repo [String] A GitHub repository
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/#get-a-repository-installation
#
# @return [Sawyer::Resource] Installation information
def find_repository_installation(repo, options = {})
get "#{Repository.path(repo)}/installation", options
end
# Enables an app to find the user's installation information.
#
# @param user [String] GitHub user login
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/#get-a-user-installation
#
# @return [Sawyer::Resource] Installation information
def find_user_installation(user, options = {})
get "#{User.path(user)}/installation", options
end
# List repositories that are accessible to the authenticated installation
#
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/installations/#list-repositories
#
# @return [Sawyer::Resource] the total_count and an array of repositories
def list_app_installation_repositories(options = {})
paginate('installation/repositories', options) do |data, last_response|
data.repositories.concat last_response.data.repositories
end
end
alias list_installation_repos list_app_installation_repositories
def list_integration_installation_repositories(options = {})
octokit_warn(
'Deprecated: Octokit::Client::Apps#list_integration_installation_repositories ' \
'method is deprecated. Please update your call to use ' \
'Octokit::Client::Apps#list_app_installation_repositories before the next major ' \
'Octokit version update.'
)
list_app_installation_repositories(options)
end
# Add a single repository to an installation
#
# @param installation [Integer] The id of a GitHub App Installation
# @param repo [Integer] The id of the GitHub repository
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/installations/#add-repository-to-installation
#
# @return [Boolean] Success
def add_repository_to_app_installation(installation, repo, options = {})
boolean_from_response :put, "user/installations/#{installation}/repositories/#{repo}", options
end
alias add_repo_to_installation add_repository_to_app_installation
def add_repository_to_integration_installation(installation, repo, options = {})
octokit_warn(
'Deprecated: Octokit::Client::Apps#add_repository_to_integration_installation ' \
'method is deprecated. Please update your call to use ' \
'Octokit::Client::Apps#add_repository_to_app_installation before the next major ' \
'Octokit version update.'
)
add_repository_to_app_installation(installation, repo, options)
end
# Remove a single repository to an installation
#
# @param installation [Integer] The id of a GitHub App Installation
# @param repo [Integer] The id of the GitHub repository
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/installations/#remove-repository-from-installation
#
# @return [Boolean] Success
def remove_repository_from_app_installation(installation, repo, options = {})
boolean_from_response :delete, "user/installations/#{installation}/repositories/#{repo}", options
end
alias remove_repo_from_installation remove_repository_from_app_installation
def remove_repository_from_integration_installation(installation, repo, options = {})
octokit_warn(
'Deprecated: Octokit::Client::Apps#remove_repository_from_integration_installation ' \
'method is deprecated. Please update your call to use ' \
'Octokit::Client::Apps#remove_repository_from_app_installation before the next major ' \
'Octokit version update.'
)
remove_repository_from_app_installation(installation, repo, options)
end
# List repositories accessible to the user for an installation
#
# @param installation [Integer] The id of a GitHub App Installation
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/installations/#list-repositories-accessible-to-the-user-for-an-installation
#
# @return [Sawyer::Resource] the total_count and an array of repositories
def find_installation_repositories_for_user(installation, options = {})
paginate("user/installations/#{installation}/repositories", options) do |data, last_response|
data.repositories.concat last_response.data.repositories
end
end
# Delete an installation and uninstall a GitHub App
#
# @param installation [Integer] The id of a GitHub App Installation
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/#delete-an-installation
#
# @return [Boolean] Success
def delete_installation(installation, options = {})
boolean_from_response :delete, "app/installations/#{installation}", options
end
end
end
end
@@ -0,0 +1,200 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Checks API
#
# @see https://developer.github.com/v3/checks/
module Checks
# Methods for Check Runs
#
# @see https://developer.github.com/v3/checks/runs/
# Create a check run
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param name [String] The name of the check
# @param head_sha [String] The SHA of the commit to check
# @return [Sawyer::Resource] A hash representing the new check run
# @see https://developer.github.com/v3/checks/runs/#create-a-check-run
# @example Create a check run
# check_run = @client.create_check_run("octocat/Hello-World", "my-check", "7638417db6d59f3c431d3e1f261cc637155684cd")
# check_run.name # => "my-check"
# check_run.head_sha # => "7638417db6d59f3c431d3e1f261cc637155684cd"
# check_run.status # => "queued"
def create_check_run(repo, name, head_sha, options = {})
options[:name] = name
options[:head_sha] = head_sha
post "#{Repository.path repo}/check-runs", options
end
# Update a check run
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The ID of the check run
# @return [Sawyer::Resource] A hash representing the updated check run
# @see https://developer.github.com/v3/checks/runs/#update-a-check-run
# @example Update a check run
# check_run = @client.update_check_run("octocat/Hello-World", 51295429, status: "in_progress")
# check_run.id # => 51295429
# check_run.status # => "in_progress"
def update_check_run(repo, id, options = {})
patch "#{Repository.path repo}/check-runs/#{id}", options
end
# List check runs for a specific ref
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param ref [String] A SHA, branch name, or tag name
# @param options [Hash] A set of optional filters
# @option options [String] :check_name Returns check runs with the specified <tt>name</tt>
# @option options [String] :status Returns check runs with the specified <tt>status</tt>
# @option options [String] :filter Filters check runs by their <tt>completed_at</tt> timestamp
# @return [Sawyer::Resource] A hash representing a collection of check runs
# @see https://developer.github.com/v3/checks/runs/#list-check-runs-for-a-specific-ref
# @example List check runs for a specific ref
# result = @client.check_runs_for_ref("octocat/Hello-World", "7638417db6d59f3c431d3e1f261cc637155684cd", status: "in_progress")
# result.total_count # => 1
# result.check_runs.count # => 1
# result.check_runs[0].id # => 51295429
# result.check_runs[0].status # => "in_progress"
def check_runs_for_ref(repo, ref, options = {})
paginate "#{Repository.path repo}/commits/#{ref}/check-runs", options do |data, last_response|
data.check_runs.concat last_response.data.check_runs
data.total_count += last_response.data.total_count
end
end
alias list_check_runs_for_ref check_runs_for_ref
# List check runs in a check suite
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The ID of the check suite
# @param options [Hash] A set of optional filters
# @option options [String] :check_name Returns check runs with the specified <tt>name</tt>
# @option options [String] :status Returns check runs with the specified <tt>status</tt>
# @option options [String] :filter Filters check runs by their <tt>completed_at</tt> timestamp
# @return [Sawyer::Resource] A hash representing a collection of check runs
# @see https://developer.github.com/v3/checks/runs/#list-check-runs-in-a-check-suite
# @example List check runs in a check suite
# result = @client.check_runs_for_check_suite("octocat/Hello-World", 50440400, status: "in_progress")
# result.total_count # => 1
# result.check_runs.count # => 1
# result.check_runs[0].check_suite.id # => 50440400
# result.check_runs[0].status # => "in_progress"
def check_runs_for_check_suite(repo, id, options = {})
paginate "#{Repository.path repo}/check-suites/#{id}/check-runs", options do |data, last_response|
data.check_runs.concat last_response.data.check_runs
data.total_count += last_response.data.total_count
end
end
alias list_check_runs_for_check_suite check_runs_for_check_suite
# Get a single check run
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The ID of the check run
# @return [Sawyer::Resource] A hash representing the check run
# @see https://developer.github.com/v3/checks/runs/#get-a-single-check-run
def check_run(repo, id, options = {})
get "#{Repository.path repo}/check-runs/#{id}", options
end
# List annotations for a check run
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The ID of the check run
# @return [Array<Sawyer::Resource>] An array of hashes representing check run annotations
# @see https://developer.github.com/v3/checks/runs/#list-annotations-for-a-check-run
# @example List annotations for a check run
# annotations = @client.check_run_annotations("octocat/Hello-World", 51295429)
# annotations.count # => 1
# annotations[0].path # => "README.md"
# annotations[0].message # => "Looks good!"
def check_run_annotations(repo, id, options = {})
paginate "#{Repository.path repo}/check-runs/#{id}/annotations", options
end
# Methods for Check Suites
#
# @see https://developer.github.com/v3/checks/suites/
# Get a single check suite
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The ID of the check suite
# @return [Sawyer::Resource] A hash representing the check suite
# @see https://developer.github.com/v3/checks/suites/#get-a-single-check-suite
def check_suite(repo, id, options = {})
get "#{Repository.path repo}/check-suites/#{id}", options
end
# List check suites for a specific ref
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param ref [String] A SHA, branch name, or tag name
# @param options [Hash] A set of optional filters
# @option options [Integer] :app_id Filters check suites by GitHub App <tt>id</tt>
# @option options [String] :check_name Filters checks suites by the <tt>name</tt> of the check run
# @return [Sawyer::Resource] A hash representing a collection of check suites
# @see https://developer.github.com/v3/checks/suites/#list-check-suites-for-a-specific-ref
# @example List check suites for a specific ref
# result = @client.check_suites_for_ref("octocat/Hello-World", "7638417db6d59f3c431d3e1f261cc637155684cd", app_id: 76765)
# result.total_count # => 1
# result.check_suites.count # => 1
# result.check_suites[0].id # => 50440400
# result.check_suites[0].app.id # => 76765
def check_suites_for_ref(repo, ref, options = {})
paginate "#{Repository.path repo}/commits/#{ref}/check-suites", options do |data, last_response|
data.check_suites.concat last_response.data.check_suites
data.total_count += last_response.data.total_count
end
end
alias list_check_suites_for_ref check_suites_for_ref
# Set preferences for check suites on a repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param options [Hash] Preferences to set
# @return [Sawyer::Resource] A hash representing the repository's check suite preferences
# @see https://developer.github.com/v3/checks/suites/#set-preferences-for-check-suites-on-a-repository
# @example Set preferences for check suites on a repository
# result = @client.set_check_suite_preferences("octocat/Hello-World", auto_trigger_checks: [{ app_id: 76765, setting: false }])
# result.preferences.auto_trigger_checks.count # => 1
# result.preferences.auto_trigger_checks[0].app_id # => 76765
# result.preferences.auto_trigger_checks[0].setting # => false
# result.repository.full_name # => "octocat/Hello-World"
def set_check_suite_preferences(repo, options = {})
patch "#{Repository.path repo}/check-suites/preferences", options
end
# Create a check suite
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param head_sha [String] The SHA of the commit to check
# @return [Sawyer::Resource] A hash representing the new check suite
# @see https://developer.github.com/v3/checks/suites/#create-a-check-suite
# @example Create a check suite
# check_suite = @client.create_check_suite("octocat/Hello-World", "7638417db6d59f3c431d3e1f261cc637155684cd")
# check_suite.head_sha # => "7638417db6d59f3c431d3e1f261cc637155684cd"
# check_suite.status # => "queued"
def create_check_suite(repo, head_sha, options = {})
options[:head_sha] = head_sha
post "#{Repository.path repo}/check-suites", options
end
# Rerequest check suite
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The ID of the check suite
# @return [Boolean] True if successful, raises an error otherwise
# @see https://developer.github.com/v3/checks/suites/#rerequest-check-suite
def rerequest_check_suite(repo, id, options = {})
post "#{Repository.path repo}/check-suites/#{id}/rerequest", options
true
end
end
end
end
@@ -0,0 +1,20 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Branches for HEAD API
#
# @see https://developer.github.com/v3/repos/commits/
module CommitBranches
# List branches for a single HEAD commit
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param sha [String] The SHA of the commit whose branches will be fetched
# @return [Array] List of branches
# @see https://developer.github.com/v3/repos/commits/#list-branches-for-head-commit
def commit_branches(repo, sha, options = {})
paginate "#{Repository.path repo}/commits/#{sha}/branches-where-head", options
end
end
end
end
@@ -0,0 +1,95 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Commit Comments API
#
# @see https://developer.github.com/v3/repos/comments/
module CommitComments
# List all commit comments
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Array] List of commit comments
# @see https://developer.github.com/v3/repos/comments/#list-commit-comments-for-a-repository
def list_commit_comments(repo, options = {})
paginate "#{Repository.path repo}/comments", options
end
# List comments for a single commit
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param sha [String] The SHA of the commit whose comments will be fetched
# @return [Array] List of commit comments
# @see https://developer.github.com/v3/repos/comments/#list-comments-for-a-single-commit
def commit_comments(repo, sha, options = {})
paginate "#{Repository.path repo}/commits/#{sha}/comments", options
end
# Get a single commit comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [String] The ID of the comment to fetch
# @return [Sawyer::Resource] Commit comment
# @see https://developer.github.com/v3/repos/comments/#get-a-single-commit-comment
def commit_comment(repo, id, options = {})
get "#{Repository.path repo}/comments/#{id}", options
end
# Create a commit comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param sha [String] Sha of the commit to comment on
# @param body [String] Message
# @param path [String] Relative path of file to comment on
# @param line [Integer] Line number in the file to comment on
# @param position [Integer] Line index in the diff to comment on
# @return [Sawyer::Resource] Commit comment
# @see https://developer.github.com/v3/repos/comments/#create-a-commit-comment
# @example Create a commit comment
# comment = Octokit.create_commit_comment("octocat/Hello-World", "827efc6d56897b048c772eb4087f854f46256132", "My comment message", "README.md", 10, 1)
# comment.commit_id # => "827efc6d56897b048c772eb4087f854f46256132"
# comment.id # => 54321
# comment.body # => "My comment message"
# comment.path # => "README.md"
# comment.line # => 10
# comment.position # => 1
def create_commit_comment(repo, sha, body, path = nil, line = nil, position = nil, options = {})
params = {
body: body,
path: path,
line: line,
position: position
}
post "#{Repository.path repo}/commits/#{sha}/comments", options.merge(params)
end
# Update a commit comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [String] The ID of the comment to update
# @param body [String] Message
# @return [Sawyer::Resource] Updated commit comment
# @see https://developer.github.com/v3/repos/comments/#update-a-commit-comment
# @example Update a commit comment
# comment = Octokit.update_commit_comment("octocat/Hello-World", "860296", "Updated commit comment")
# comment.id # => 860296
# comment.body # => "Updated commit comment"
def update_commit_comment(repo, id, body, options = {})
params = {
body: body
}
patch "#{Repository.path repo}/comments/#{id}", options.merge(params)
end
# Delete a commit comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [String] The ID of the comment to delete
# @return [Boolean] Success
# @see https://developer.github.com/v3/repos/comments/#delete-a-commit-comment
def delete_commit_comment(repo, id, options = {})
boolean_from_response :delete, "#{Repository.path repo}/comments/#{id}", options
end
end
end
end
@@ -0,0 +1,20 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Commit Pulls API
#
# @see https://developer.github.com/v3/repos/comments/
module CommitPulls
# List pulls for a single commit
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param sha [String] The SHA of the commit whose pulls will be fetched
# @return [Array] List of commit pulls
# @see https://developer.github.com/v3/repos/commits/#list-pull-requests-associated-with-commit
def commit_pulls(repo, sha, options = {})
paginate "#{Repository.path repo}/commits/#{sha}/pulls", options
end
end
end
end
@@ -0,0 +1,236 @@
# frozen_string_literal: true
require 'date'
module Octokit
class Client
# Methods for the Commits API
#
# @see https://developer.github.com/v3/repos/commits/
module Commits
# List commits
#
# @overload commits(repo, sha_or_branch, options = {})
# @deprecated
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param sha_or_branch [String] A commit SHA or branch name
# @param options [String] :sha Commit SHA or branch name from which to start the list
# @overload commits(repo, options = {})
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param options [String] :sha Commit SHA or branch name from which to start the list
# @return [Array<Sawyer::Resource>] An array of hashes representing commits
# @see https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
def commits(*args)
arguments = Octokit::RepoArguments.new(args)
sha_or_branch = arguments.pop
arguments.options[:sha] = sha_or_branch if sha_or_branch
paginate "#{Repository.new(arguments.repo).path}/commits", arguments.options
end
alias list_commits commits
# Get commits after a specified date
#
# @overload commits_since(repo, date, options = {})
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param date [String] Date on which we want to compare
# @param options [String] :sha Commit SHA or branch name from which to start the list
# @overload commits_since(repo, date, sha_or_branch, options = {})
# @deprecated
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param date [String] Date on which we want to compare
# @param sha_or_branch [String] A commit SHA or branch name
# @param options [String] :sha Commit SHA or branch name from which to start the list
# @return [Array<Sawyer::Resource>] An array of hashes representing commits
# @see https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
# @example
# Octokit.commits_since('octokit/octokit.rb', '2012-10-01')
def commits_since(*args)
arguments = Octokit::RepoArguments.new(args)
date = parse_date(arguments.shift)
params = arguments.options
params.merge!(since: iso8601(date))
sha_or_branch = arguments.pop
params[:sha] = sha_or_branch if sha_or_branch
commits(arguments.repo, params)
end
# Get commits before a specified date
#
# @overload commits_before(repo, date, options = {})
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param date [String] Date on which we want to compare
# @overload commits_before(repo, date, sha_or_branch, options = {})
# @deprecated
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param date [String] Date on which we want to compare
# @param sha_or_branch [String] Commit SHA or branch name from which to start the list
# @return [Array<Sawyer::Resource>] An array of hashes representing commits
# @see https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
# @example
# Octokit.commits_before('octokit/octokit.rb', '2012-10-01')
def commits_before(*args)
arguments = Octokit::RepoArguments.new(args)
date = parse_date(arguments.shift)
params = arguments.options
params.merge!(until: iso8601(date))
sha_or_branch = arguments.pop
params[:sha] = sha_or_branch if sha_or_branch
commits(arguments.repo, params)
end
# Get commits on a specified date
#
# @overload commits_on(repo, date, options = {})
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param date [String] Date on which we want to compare
# @overload commits_on(repo, date, sha_or_branch, options = {})
# @deprecated
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param date [String] Date on which we want to compare
# @param sha_or_branch [String] Commit SHA or branch name from which to start the list
# @return [Array<Sawyer::Resource>] An array of hashes representing commits
# @see https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
# @example
# Octokit.commits_on('octokit/octokit.rb', '2012-10-01')
def commits_on(*args)
arguments = Octokit::RepoArguments.new(args)
date = parse_date(arguments.shift)
params = arguments.options
end_date = date + 1
params.merge!(since: iso8601(date), until: iso8601(end_date))
sha_or_branch = arguments.pop
params[:sha] = sha_or_branch if sha_or_branch
commits(arguments.repo, params)
end
# Get commits made between two nominated dates
#
# @overload commits_between(repo, start_date, end_date, options = {})
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param start_date [String] Start Date on which we want to compare
# @param end_date [String] End Date on which we want to compare
# @overload commits_between(repo, start_date, end_date, sha_or_branch, options = {})
# @deprecated
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param start_date [String] Start Date on which we want to compare
# @param end_date [String] End Date on which we want to compare
# @param sha_or_branch [String] Commit SHA or branch name from which to start the list
# @return [Array<Sawyer::Resource>] An array of hashes representing commits
# @see https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
# @example
# Octokit.commits_between('octokit/octokit.rb', '2012-10-01', '2012-11-01')
def commits_between(*args)
arguments = Octokit::RepoArguments.new(args)
date = parse_date(arguments.shift)
end_date = parse_date(arguments.shift)
if date > end_date
raise ArgumentError, "Start date #{date} does not precede #{end_date}"
end
params = arguments.options
params.merge!(since: iso8601(date), until: iso8601(end_date))
sha_or_branch = arguments.pop
params[:sha] = sha_or_branch if sha_or_branch
commits(arguments.repo, params)
end
# Get a single commit
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param sha [String] The SHA of the commit to fetch
# @return [Sawyer::Resource] A hash representing the commit
# @see https://developer.github.com/v3/repos/commits/#get-a-single-commit
def commit(repo, sha, options = {})
get "#{Repository.path repo}/commits/#{sha}", options
end
# Get a detailed git commit
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param sha [String] The SHA of the commit to fetch
# @return [Sawyer::Resource] A hash representing the commit
# @see https://developer.github.com/v3/git/commits/#get-a-commit
def git_commit(repo, sha, options = {})
get "#{Repository.path repo}/git/commits/#{sha}", options
end
# Create a commit
#
# Optionally pass <tt>author</tt> and <tt>committer</tt> hashes in <tt>options</tt>
# if you'd like manual control over those parameters. If absent, details will be
# inferred from the authenticated user. See <a href="http://developer.github.com/v3/git/commits/">GitHub's documentation</a>
# for details about how to format committer identities.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param message [String] The commit message
# @param tree [String] The SHA of the tree object the new commit will point to
# @param parents [String, Array] One SHA (for a normal commit) or an array of SHAs (for a merge) of the new commit's parent commits. If ommitted or empty, a root commit will be created
# @return [Sawyer::Resource] A hash representing the new commit
# @see https://developer.github.com/v3/git/commits/#create-a-commit
# @example Create a commit
# commit = Octokit.create_commit("octocat/Hello-World", "My commit message", "827efc6d56897b048c772eb4087f854f46256132", "7d1b31e74ee336d15cbd21741bc88a537ed063a0")
# commit.sha # => "7638417db6d59f3c431d3e1f261cc637155684cd"
# commit.tree.sha # => "827efc6d56897b048c772eb4087f854f46256132"
# commit.message # => "My commit message"
# commit.committer # => { "name" => "Wynn Netherland", "email" => "wynn@github.com", ... }
def create_commit(repo, message, tree, parents = nil, options = {})
params = { message: message, tree: tree }
params[:parents] = [parents].flatten if parents
post "#{Repository.path repo}/git/commits", options.merge(params)
end
# Compare two commits
#
# When using auto_pagination, commits from all pages will be concatenated
# into the <tt>commits</tt> attribute of the first page's response.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param start [String] The sha of the starting commit
# @param endd [String] The sha of the ending commit
# @return [Sawyer::Resource] A hash representing the comparison
# @see https://developer.github.com/v3/repos/commits/#compare-two-commits
def compare(repo, start, endd, options = {})
paginate "#{Repository.path repo}/compare/#{start}...#{endd}", options do |data, last_response|
data.commits.concat last_response.data.commits
end
end
# Merge a branch or sha
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param base [String] The name of the base branch to merge into
# @param head [String] The branch or SHA1 to merge
# @option options [String] :commit_message The commit message for the merge
# @return [Sawyer::Resource] A hash representing the comparison
# @see https://developer.github.com/v3/repos/merging/#perform-a-merge
def merge(repo, base, head, options = {})
params = {
base: base,
head: head
}.merge(options)
post "#{Repository.path repo}/merges", params
end
protected
def iso8601(date)
if date.respond_to?(:iso8601)
date.iso8601
else
date.strftime('%Y-%m-%dT%H:%M:%S%Z')
end
end
# Parses the given string representation of a date, throwing a meaningful exception
# (containing the date that failed to parse) in case of failure.
#
# @param date [String] String representation of a date
# @return [DateTime]
def parse_date(date)
date = DateTime.parse(date.to_s)
rescue ArgumentError
raise ArgumentError, "#{date} is not a valid date"
end
end
end
end
@@ -0,0 +1,21 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Community Profile API
#
# @see https://developer.github.com/v3/repos/community/
module CommunityProfile
# Get community profile metrics for a repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Sawyer::Resource] Community profile metrics
# @see https://developer.github.com/v3/repos/community/#retrieve-community-profile-metrics
# @example Get community profile metrics for octokit/octokit.rb
# @client.community_profile('octokit/octokit.rb')
def community_profile(repo, options = {})
get "#{Repository.path repo}/community/profile", options
end
end
end
end
@@ -0,0 +1,167 @@
# frozen_string_literal: true
require 'base64'
module Octokit
class Client
# Methods for the Repo Contents API
#
# @see https://developer.github.com/v3/repos/contents/
module Contents
# Receive the default Readme for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @option options [String] :ref name of the Commit/Branch/Tag. Defaults to “master”.
# @return [Sawyer::Resource] The detail of the readme
# @see https://developer.github.com/v3/repos/contents/#get-the-readme
# @example Get the readme file for a repo
# Octokit.readme("octokit/octokit.rb")
# @example Get the readme file for a particular branch of the repo
# Octokit.readme("octokit/octokit.rb", :query => {:ref => 'some-other-branch'})
def readme(repo, options = {})
get "#{Repository.path repo}/readme", options
end
# Receive a listing of a repository folder or the contents of a file
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @option options [String] :path A folder or file path
# @option options [String] :ref name of the Commit/Branch/Tag. Defaults to “master”.
# @return [Sawyer::Resource] The contents of a file or list of the files in the folder
# @see https://developer.github.com/v3/repos/contents/#get-contents
# @example List the contents of lib/octokit.rb
# Octokit.contents("octokit/octokit.rb", :path => 'lib/octokit.rb')
# @example Lists the contents of lib /octokit.rb on a particular branch
# Octokit.contents("octokit/octokit.rb", :path => 'lib/octokit.rb', :query => {:ref => 'some-other-branch'})
def contents(repo, options = {})
options = options.dup
repo_path = options.delete :path
url = "#{Repository.path repo}/contents/#{repo_path}"
get url, options
end
alias content contents
# Add content to a repository
#
# @overload create_contents(repo, path, message, content = nil, options = {})
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param path [String] A path for the new content
# @param message [String] A commit message for adding the content
# @param optional content [String] The content for the file
# @option options [String] :branch The branch on which to add the content
# @option options [String] :file Path or Ruby File object for content
# @return [Sawyer::Resource] The contents and commit info for the addition
# @see https://developer.github.com/v3/repos/contents/#create-a-file
# @example Add content at lib/octokit.rb
# Octokit.create_contents("octokit/octokit.rb",
# "lib/octokit.rb",
# "Adding content",
# "File content",
# :branch => "my-new-feature")
def create_contents(*args)
args = args.map { |item| item&.dup }
options = args.last.is_a?(Hash) ? args.pop : {}
repo = args.shift
path = args.shift
message = args.shift
content = args.shift
if content.nil? && file = options.delete(:file)
case file
when String
if File.exist?(file)
file = File.open(file, 'r')
content = file.read
file.close
end
when File, Tempfile
content = file.read
file.close
end
end
raise ArgumentError, 'content or :file option required' if content.nil?
options[:content] = Base64.strict_encode64(content)
options[:message] = message
url = "#{Repository.path repo}/contents/#{path}"
put url, options
end
alias create_content create_contents
alias add_content create_contents
alias add_contents create_contents
# Update content in a repository
#
# @overload update_contents(repo, path, message, sha, content = nil, options = {})
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param path [String] A path for the content to update
# @param message [String] A commit message for updating the content
# @param sha [String] The _blob sha_ of the content to update
# @param content [String] The content for the file
# @option options [String] :branch The branch on which to update the content
# @option options [String] :file Path or Ruby File object for content
# @return [Sawyer::Resource] The contents and commit info for the update
# @see https://developer.github.com/v3/repos/contents/#update-a-file
# @example Update content at lib/octokit.rb
# Octokit.update_contents("octokit/octokit.rb",
# "lib/octokit.rb",
# "Updating content",
# "7eb95f97e1a0636015df3837478d3f15184a5f49",
# "File content",
# :branch => "my-new-feature")
def update_contents(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
repo = args.shift
path = args.shift
message = args.shift
sha = args.shift
content = args.shift
options.merge!(sha: sha)
create_contents(repo, path, message, content, options)
end
alias update_content update_contents
# Delete content in a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param path [String] A path for the content to delete
# @param message [String] A commit message for deleting the content
# @param sha [String] The _blob sha_ of the content to delete
# @option options [String] :branch The branch on which to delete the content
# @return [Sawyer::Resource] The commit info for the delete
# @see https://developer.github.com/v3/repos/contents/#delete-a-file
# @example Delete content at lib/octokit.rb
# Octokit.delete_contents("octokit/octokit.rb",
# "lib/octokit.rb",
# "Deleting content",
# "7eb95f97e1a0636015df3837478d3f15184a5f49",
# :branch => "my-new-feature")
def delete_contents(repo, path, message, sha, options = {})
options[:message] = message
options[:sha] = sha
url = "#{Repository.path repo}/contents/#{path}"
delete url, options
end
alias delete_content delete_contents
alias remove_content delete_contents
alias remove_contents delete_contents
# This method will provide a URL to download a tarball or zipball archive for a repository.
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository.
# @option options format [String] Either tarball (default) or zipball.
# @option options [String] :ref Optional valid Git reference, defaults to master.
# @return [String] Location of the download
# @see https://developer.github.com/v3/repos/contents/#get-archive-link
# @example Get archive link for octokit/octokit.rb
# Octokit.archive_link("octokit/octokit.rb")
def archive_link(repo, options = {})
repo_ref = ERB::Util.url_encode(options.delete(:ref))
format = (options.delete :format) || 'tarball'
url = "#{Repository.path repo}/#{format}/#{repo_ref}"
response = client_without_redirects.head(url, options)
response.headers['Location']
end
end
end
end
@@ -0,0 +1,82 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Deployments API
#
# @see https://developer.github.com/v3/repos/commits/deployments/
module Deployments
# Fetch a single deployment for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param deployment_id [Integer, String, Repository, Hash] A GitHub repository
# @return <Sawyer::Resource> A single deployment
# @see https://developer.github.com/v3/repos/deployments/#get-a-single-deployment
def deployment(repo, deployment_id, options = {})
get("#{Repository.path repo}/deployments/#{deployment_id}", options)
end
# List all deployments for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] A list of deployments
# @see https://developer.github.com/v3/repos/deployments/#list-deployments
def deployments(repo, options = {})
get("#{Repository.path repo}/deployments", options)
end
alias list_deployments deployments
# Create a deployment for a ref
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param ref [String] The ref to deploy
# @option options [String] :task Used by the deployment system to allow different execution paths. Defaults to "deploy".
# @option options [String] :payload Meta info about the deployment
# @option options [Boolean] :auto_merge Optional parameter to merge the default branch into the requested deployment branch if necessary. Default: true
# @option options [Array<String>] :required_contexts Optional array of status contexts verified against commit status checks.
# @option options [String] :environment Optional name for the target deployment environment (e.g., production, staging, qa). Default: "production"
# @option options [String] :description Optional short description.
# @return [Sawyer::Resource] A deployment
# @see https://developer.github.com/v3/repos/deployments/#create-a-deployment
def create_deployment(repo, ref, options = {})
options[:ref] = ref
post("#{Repository.path repo}/deployments", options)
end
# Delete a Deployment
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param deployment_id [Integer, String, Repository, Hash] A GitHub repository
# @return [No Content]
# @see https://developer.github.com/v3/repos/deployments/#delete-a-deployment
def delete_deployment(repo, deployment_id, options = {})
delete("#{Repository.path repo}/deployments/#{deployment_id}", options)
end
# List all statuses for a Deployment
#
# @param deployment_url [String] A URL for a deployment resource
# @return [Array<Sawyer::Resource>] A list of deployment statuses
# @see https://developer.github.com/v3/repos/deployments/#list-deployment-statuses
def deployment_statuses(deployment_url, options = {})
deployment = get(deployment_url, accept: options[:accept])
get(deployment.rels[:statuses].href, options)
end
alias list_deployment_statuses deployment_statuses
# Create a deployment status for a Deployment
#
# @param deployment_url [String] A URL for a deployment resource
# @param state [String] The state: pending, success, failure, error
# @option options [String] :target_url The target URL to associate with this status. Default: ""
# @option options [String] :description A short description of the status. Maximum length of 140 characters. Default: ""
# @return [Sawyer::Resource] A deployment status
# @see https://developer.github.com/v3/repos/deployments/#create-a-deployment-status
def create_deployment_status(deployment_url, state, options = {})
deployment = get(deployment_url, accept: options[:accept])
options[:state] = state.to_s.downcase
post(deployment.rels[:statuses].href, options)
end
end
end
end
@@ -0,0 +1,49 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Repo Downloads API
#
# @see https://developer.github.com/v3/repos/downloads/
module Downloads
# List available downloads for a repository
#
# @param repo [Integer, String, Repository, Hash] A Github Repository
# @return [Array] A list of available downloads
# @deprecated As of December 11th, 2012: https://github.com/blog/1302-goodbye-uploads
# @see https://developer.github.com/v3/repos/downloads/#list-downloads-for-a-repository
# @example List all downloads for Github/Hubot
# Octokit.downloads("github/hubot")
def downloads(repo, options = {})
paginate "#{Repository.path repo}/downloads", options
end
alias list_downloads downloads
# Get single download for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] ID of the download
# @return [Sawyer::Resource] A single download from the repository
# @deprecated As of December 11th, 2012: https://github.com/blog/1302-goodbye-uploads
# @see https://developer.github.com/v3/repos/downloads/#get-a-single-download
# @example Get the "Robawt" download from Github/Hubot
# Octokit.download("github/hubot")
def download(repo, id, options = {})
get "#{Repository.path repo}/downloads/#{id}", options
end
# Delete a single download for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer] ID of the download
# @deprecated As of December 11th, 2012: https://github.com/blog/1302-goodbye-uploads
# @see https://developer.github.com/v3/repos/downloads/#delete-a-download
# @return [Boolean] Status
# @example Get the "Robawt" download from Github/Hubot
# Octokit.delete_download("github/hubot", 1234)
def delete_download(repo, id, options = {})
boolean_from_response :delete, "#{Repository.path repo}/downloads/#{id}", options
end
end
end
end
@@ -0,0 +1,18 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Emojis API
module Emojis
# List all emojis used on GitHub
#
# @return [Sawyer::Resource] A list of all emojis on GitHub
# @see https://developer.github.com/v3/emojis/#emojis
# @example List all emojis
# Octokit.emojis
def emojis(options = {})
get 'emojis', options
end
end
end
end
@@ -0,0 +1,55 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Environments API
#
# @see https://docs.github.com/en/rest/deployments/environments
module Environments
# Fetch a single environment for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param environment_name [String] The name of the environment
# @return <Sawyer::Resource> A single environment
# @see https://docs.github.com/en/rest/deployments/environments#get-an-environment
def environment(repo, environment_name, options = {})
get("#{Repository.path repo}/environments/#{environment_name}", options)
end
# Lists the environments for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @option options [Integer] :per_page The number of results per page (max 100). Default: 30
# @option options [Integer] :page Page number of the results to fetch. Default: 1
# @return [Sawyer::Resource] Total count of environments and list of environments
# @see https://docs.github.com/en/rest/deployments/environments#list-environments
def environments(repo, options = {})
get("#{Repository.path repo}/environments", options)
end
alias list_environments environments
# Create or update an environment with protection rules, such as required reviewers
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param environment_name [String] The name of the environment
# @option options [Integer] :wait_timer The amount of time to delay a job after the job is initially triggered. The time (in minutes) must be an integer between 0 and 43,200 (30 days).
# @option options [Array] :reviewers The people or teams that may review jobs that reference the environment. You can list up to six users or teams as reviewers.
# @option options [Object] :deployment_branch_policy The type of deployment branch policy for this environment. To allow all branches to deploy, set to null.
# @return [Sawyer::Resource] An environment
# @see https://docs.github.com/en/rest/deployments/environments#create-or-update-an-environment
def create_or_update_environment(repo, environment_name, options = {})
put("#{Repository.path repo}/environments/#{environment_name}", options)
end
# Delete an Environment
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param environment_name [String] The name of the environment
# @return [No Content]
# @see https://docs.github.com/en/rest/deployments/environments#delete-an-environment
def delete_environment(repo, environment_name, options = {})
delete("#{Repository.path repo}/environments/#{environment_name}", options)
end
end
end
end
@@ -0,0 +1,151 @@
# frozen_string_literal: true
module Octokit
class Client
# Method for the Events API
#
# @see https://developer.github.com/v3/activity/events/
# @see https://developer.github.com/v3/issues/events/
module Events
# List all public events for GitHub
#
# @return [Array<Sawyer::Resource>] A list of all public events from GitHub
# @see https://developer.github.com/v3/activity/events/#list-public-events
# @example List all pubilc events
# Octokit.public_events
def public_events(options = {})
paginate 'events', options
end
# List all user events
#
# @param user [Integer, String] GitHub user login or id.
# @return [Array<Sawyer::Resource>] A list of all user events
# @see https://developer.github.com/v3/activity/events/#list-events-performed-by-a-user
# @example List all user events
# Octokit.user_events("sferik")
def user_events(user, options = {})
paginate "#{User.path user}/events", options
end
# List public user events
#
# @param user [Integer, String] GitHub user login or id
# @return [Array<Sawyer::Resource>] A list of public user events
# @see https://developer.github.com/v3/activity/events/#list-public-events-performed-by-a-user
# @example List public user events
# Octokit.user_events("sferik")
def user_public_events(user, options = {})
paginate "#{User.path user}/events/public", options
end
# List events that a user has received
#
# @param user [Integer, String] GitHub user login or id
# @return [Array<Sawyer::Resource>] A list of all user received events
# @see https://developer.github.com/v3/activity/events/#list-events-that-a-user-has-received
# @example List all user received events
# Octokit.received_events("sferik")
def received_events(user, options = {})
paginate "#{User.path user}/received_events", options
end
# List public events a user has received
#
# @param user [Integer, String] GitHub user login or id
# @return [Array<Sawyer::Resource>] A list of public user received events
# @see https://developer.github.com/v3/activity/events/#list-public-events-that-a-user-has-received
# @example List public user received events
# Octokit.received_public_events("sferik")
def received_public_events(user, options = {})
paginate "#{User.path user}/received_events/public", options
end
# List events for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] A list of events for a repository
# @see https://developer.github.com/v3/activity/events/#list-repository-events
# @example List events for a repository
# Octokit.repository_events("sferik/rails_admin")
def repository_events(repo, options = {})
paginate "#{Repository.path repo}/events", options
end
# List public events for a repository's network
#
# @param repo [String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] A list of events for a repository's network
# @see https://developer.github.com/v3/activity/events/#list-public-events-for-a-network-of-repositories
# @example List events for a repository's network
# Octokit.repository_network_events("sferik/rails_admin")
def repository_network_events(repo, options = {})
paginate "networks/#{Repository.new(repo)}/events", options
end
# List all events for an organization
#
# Requires authenticated client.
#
# @param org [String] Organization GitHub handle
# @return [Array<Sawyer::Resource>] List of all events from a GitHub organization
# @see https://developer.github.com/v3/activity/events/#list-events-for-an-organization
# @example List events for the lostisland organization
# @client.organization_events("lostisland")
def organization_events(org, options = {})
paginate "users/#{login}/events/orgs/#{org}", options
end
# List an organization's public events
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Array<Sawyer::Resource>] List of public events from a GitHub organization
# @see https://developer.github.com/v3/activity/events/#list-public-events-for-an-organization
# @example List public events for GitHub
# Octokit.organization_public_events("GitHub")
def organization_public_events(org, options = {})
paginate "#{Organization.path org}/events", options
end
# Get all Issue Events for a given Repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
#
# @return [Array<Sawyer::Resource>] Array of all Issue Events for this Repository
# @see https://developer.github.com/v3/issues/events/#list-events-for-a-repository
# @see https://developer.github.com/v3/activity/events/#list-issue-events-for-a-repository
# @example Get all Issue Events for Octokit
# Octokit.repository_issue_events("octokit/octokit.rb")
def repository_issue_events(repo, options = {})
paginate "#{Repository.path repo}/issues/events", options
end
alias repo_issue_events repository_issue_events
# List events for an Issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Issue number
#
# @return [Array<Sawyer::Resource>] Array of events for that issue
# @see https://developer.github.com/v3/issues/events/#list-events-for-an-issue
# @example List all issues events for issue #38 on octokit/octokit.rb
# Octokit.issue_events("octokit/octokit.rb", 38)
def issue_events(repo, number, options = {})
paginate "#{Repository.path repo}/issues/#{number}/events", options
end
# Get information on a single Issue Event
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Event number
#
# @return [Sawyer::Resource] A single Event for an Issue
# @see https://developer.github.com/v3/issues/events/#get-a-single-event
# @example Get Event information for ID 3094334 (a pull request was closed)
# Octokit.issue_event("octokit/octokit.rb", 3094334)
def issue_event(repo, number, options = {})
paginate "#{Repository.path repo}/issues/events/#{number}", options
end
end
end
end
@@ -0,0 +1,32 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Feeds API
#
# @see https://developer.github.com/v3/activity/feeds/
module Feeds
# List Feeds
#
# The feeds returned depend on authentication, see the GitHub API docs
# for more information.
#
# @return [Array<Sawyer::Resource>] list of feeds
# @see https://developer.github.com/v3/activity/feeds/#list-feeds
def feeds
get 'feeds'
end
# Get a Feed by name
#
# @param name [Symbol, String] Name of feed to retrieve.
# @return [Feed] Parsed feed in the format returned by the configured
# parser.
def feed(name, options = {})
if rel = feeds._links[name]
get rel.href, accept: rel.type, options: options
end
end
end
end
end
@@ -0,0 +1,234 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Gists API
#
# @see https://developer.github.com/v3/gists/
module Gists
# List gists for a user or all public gists
#
# @param user [String] An optional user to filter listing
# @return [Array<Sawyer::Resource>] A list of gists
# @example Fetch all gists for defunkt
# Octokit.gists('defunkt')
# @example Fetch all public gists
# Octokit.gists
# @see https://developer.github.com/v3/gists/#list-gists
def gists(user = nil, options = {})
if user.nil?
paginate 'gists', options
else
paginate "#{User.path user}/gists", options
end
end
alias list_gists gists
# List public gists
#
# @return [Array<Sawyer::Resource>] A list of gists
# @example Fetch all public gists
# Octokit.public_gists
# @see https://developer.github.com/v3/gists/#list-gists
def public_gists(options = {})
paginate 'gists/public', options
end
# List the authenticated user’s starred gists
#
# @return [Array<Sawyer::Resource>] A list of gists
# @see https://developer.github.com/v3/gists/#list-gists
def starred_gists(options = {})
paginate 'gists/starred', options
end
# Get a single gist
#
# @param gist [String] ID of gist to fetch
# @option options [String] :sha Specific gist revision SHA
# @return [Sawyer::Resource] Gist information
# @see https://developer.github.com/v3/gists/#get-a-single-gist
# @see https://developer.github.com/v3/gists/#get-a-specific-revision-of-a-gist
def gist(gist, options = {})
options = options.dup
if sha = options.delete(:sha)
get "gists/#{Gist.new(gist)}/#{sha}", options
else
get "gists/#{Gist.new(gist)}", options
end
end
# Create a gist
#
# @param options [Hash] Gist information.
# @option options [String] :description
# @option options [Boolean] :public Sets gist visibility
# @option options [Array<Hash>] :files Files that make up this gist. Keys
# should be the filename, the value a Hash with a :content key with text
# content of the Gist.
# @return [Sawyer::Resource] Newly created gist info
# @see https://developer.github.com/v3/gists/#create-a-gist
def create_gist(options = {})
post 'gists', options
end
# Edit a gist
#
# @param options [Hash] Gist information.
# @option options [String] :description
# @option options [Hash] :files Files that make up this gist. Keys
# should be the filename, the value a Hash with a :content key with text
# content of the Gist.
#
# NOTE: All files from the previous version of the
# gist are carried over by default if not included in the hash. Deletes
# can be performed by including the filename with a null hash.
# @return
# [Sawyer::Resource] Newly created gist info
# @see https://developer.github.com/v3/gists/#edit-a-gist
# @example Update a gist
# @client.edit_gist('some_id', {
# :files => {"boo.md" => {"content" => "updated stuff"}}
# })
def edit_gist(gist, options = {})
patch "gists/#{Gist.new(gist)}", options
end
# List gist commits
#
# @param gist [String] Gist ID
# @return [Array] List of commits to the gist
# @see https://developer.github.com/v3/gists/#list-gist-commits
# @example List commits for a gist
# @client.gist_commits('some_id')
def gist_commits(gist, options = {})
paginate "gists/#{Gist.new(gist)}/commits", options
end
#
# Star a gist
#
# @param gist [String] Gist ID
# @return [Boolean] Indicates if gist is starred successfully
# @see https://developer.github.com/v3/gists/#star-a-gist
def star_gist(gist, options = {})
boolean_from_response :put, "gists/#{Gist.new(gist)}/star", options
end
# Unstar a gist
#
# @param gist [String] Gist ID
# @return [Boolean] Indicates if gist is unstarred successfully
# @see https://developer.github.com/v3/gists/#unstar-a-gist
def unstar_gist(gist, options = {})
boolean_from_response :delete, "gists/#{Gist.new(gist)}/star", options
end
# Check if a gist is starred
#
# @param gist [String] Gist ID
# @return [Boolean] Indicates if gist is starred
# @see https://developer.github.com/v3/gists/#check-if-a-gist-is-starred
def gist_starred?(gist, options = {})
boolean_from_response :get, "gists/#{Gist.new(gist)}/star", options
end
# Fork a gist
#
# @param gist [String] Gist ID
# @return [Sawyer::Resource] Data for the new gist
# @see https://developer.github.com/v3/gists/#fork-a-gist
def fork_gist(gist, options = {})
post "gists/#{Gist.new(gist)}/forks", options
end
# List gist forks
#
# @param gist [String] Gist ID
# @return [Array] List of gist forks
# @see https://developer.github.com/v3/gists/#list-gist-forks
# @example List gist forks
# @client.gist_forks('some-id')
def gist_forks(gist, options = {})
paginate "gists/#{Gist.new(gist)}/forks", options
end
# Delete a gist
#
# @param gist [String] Gist ID
# @return [Boolean] Indicating success of deletion
# @see https://developer.github.com/v3/gists/#delete-a-gist
def delete_gist(gist, options = {})
boolean_from_response :delete, "gists/#{Gist.new(gist)}", options
end
# List gist comments
#
# @param gist_id [String] Gist Id.
# @return [Array<Sawyer::Resource>] Array of hashes representing comments.
# @see https://developer.github.com/v3/gists/comments/#list-comments-on-a-gist
# @example
# Octokit.gist_comments('3528ae645')
def gist_comments(gist_id, options = {})
paginate "gists/#{gist_id}/comments", options
end
# Get gist comment
#
# @param gist_id [String] Id of the gist.
# @param gist_comment_id [Integer] Id of the gist comment.
# @return [Sawyer::Resource] Hash representing gist comment.
# @see https://developer.github.com/v3/gists/comments/#get-a-single-comment
# @example
# Octokit.gist_comment('208sdaz3', 1451398)
def gist_comment(gist_id, gist_comment_id, options = {})
get "gists/#{gist_id}/comments/#{gist_comment_id}", options
end
# Create gist comment
#
# Requires authenticated client.
#
# @param gist_id [String] Id of the gist.
# @param comment [String] Comment contents.
# @return [Sawyer::Resource] Hash representing the new comment.
# @see https://developer.github.com/v3/gists/comments/#create-a-comment
# @example
# @client.create_gist_comment('3528645', 'This is very helpful.')
def create_gist_comment(gist_id, comment, options = {})
options = options.merge({ body: comment })
post "gists/#{gist_id}/comments", options
end
# Update gist comment
#
# Requires authenticated client
#
# @param gist_id [String] Id of the gist.
# @param gist_comment_id [Integer] Id of the gist comment to update.
# @param comment [String] Updated comment contents.
# @return [Sawyer::Resource] Hash representing the updated comment.
# @see https://developer.github.com/v3/gists/comments/#edit-a-comment
# @example
# @client.update_gist_comment('208sdaz3', '3528645', ':heart:')
def update_gist_comment(gist_id, gist_comment_id, comment, options = {})
options = options.merge({ body: comment })
patch "gists/#{gist_id}/comments/#{gist_comment_id}", options
end
# Delete gist comment
#
# Requires authenticated client.
#
# @param gist_id [String] Id of the gist.
# @param gist_comment_id [Integer] Id of the gist comment to delete.
# @return [Boolean] True if comment deleted, false otherwise.
# @see https://developer.github.com/v3/gists/comments/#delete-a-comment
# @example
# @client.delete_gist_comment('208sdaz3', '586399')
def delete_gist_comment(gist_id, gist_comment_id, options = {})
boolean_from_response(:delete, "gists/#{gist_id}/comments/#{gist_comment_id}", options)
end
end
end
end
@@ -0,0 +1,43 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Gitignore API
#
# @see https://developer.github.com/v3/gitignore/
module Gitignore
# Listing available gitignore templates.
#
# These templates can be passed option when creating a repository.
#
# @see https://developer.github.com/v3/gitignore/#listing-available-templates
#
# @return [Array<String>] List of templates.
#
# @example Git all the gitignore templates
# @client.gitignore_templates
def gitignore_templates(options = {})
get 'gitignore/templates', options
end
# Get a gitignore template.
#
# Use the raw {http://developer.github.com/v3/media/ media type} to get
# the raw contents.
#
# @param template_name [String] Name of the template. Template names are
# case sensitive, make sure to use a valid name from the
# .gitignore_templates list.
#
# @see https://developer.github.com/v3/gitignore/#get-a-single-template
#
# @return [Sawyer::Resource] Gitignore template
#
# @example Get the Ruby gitignore template
# @client.gitignore_template('Ruby')
def gitignore_template(template_name, options = {})
get "gitignore/templates/#{template_name}", options
end
end
end
end
@@ -0,0 +1,287 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Hooks API
module Hooks
# List repo hooks
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of hashes representing hooks.
# @see https://developer.github.com/v3/repos/hooks/#list-hooks
# @example
# @client.hooks('octokit/octokit.rb')
def hooks(repo, options = {})
paginate "#{Repository.path repo}/hooks", options
end
# Get single hook
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param id [Integer] Id of the hook to get.
# @return [Sawyer::Resource] Hash representing hook.
# @see https://developer.github.com/v3/repos/hooks/#get-single-hook
# @example
# @client.hook('octokit/octokit.rb', 100000)
def hook(repo, id, options = {})
get "#{Repository.path repo}/hooks/#{id}", options
end
# Create a hook
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param name [String] The name of the service that is being called. See
# {https://api.github.com/hooks Hooks} for the possible names.
# @param config [Hash] A Hash containing key/value pairs to provide
# settings for this hook. These settings vary between the services and
# are defined in the {https://github.com/github/github-services github-services} repo.
# @option options [Array<String>] :events ('["push"]') Determines what
# events the hook is triggered for.
# @option options [Boolean] :active Determines whether the hook is
# actually triggered on pushes.
# @return [Sawyer::Resource] Hook info for the new hook
# @see https://api.github.com/hooks
# @see https://github.com/github/github-services
# @see https://developer.github.com/v3/repos/hooks/#create-a-hook
# @example
# @client.create_hook(
# 'octokit/octokit.rb',
# 'web',
# {
# :url => 'http://something.com/webhook',
# :content_type => 'json'
# },
# {
# :events => ['push', 'pull_request'],
# :active => true
# }
# )
def create_hook(repo, name, config, options = {})
options = { name: name, config: config, events: ['push'], active: true }.merge(options)
post "#{Repository.path repo}/hooks", options
end
# Edit a hook
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param id [Integer] Id of the hook being updated.
# @param name [String] The name of the service that is being called. See
# {https://api.github.com/hooks Hooks} for the possible names.
# @param config [Hash] A Hash containing key/value pairs to provide
# settings for this hook. These settings vary between the services and
# are defined in the {https://github.com/github/github-services github-services} repo.
# @option options [Array<String>] :events ('["push"]') Determines what
# events the hook is triggered for.
# @option options [Array<String>] :add_events Determines a list of events
# to be added to the list of events that the Hook triggers for.
# @option options [Array<String>] :remove_events Determines a list of events
# to be removed from the list of events that the Hook triggers for.
# @option options [Boolean] :active Determines whether the hook is
# actually triggered on pushes.
# @return [Sawyer::Resource] Hook info for the updated hook
# @see https://api.github.com/hooks
# @see https://github.com/github/github-services
# @see https://developer.github.com/v3/repos/hooks/#edit-a-hook
# @example
# @client.edit_hook(
# 'octokit/octokit.rb',
# 100000,
# 'web',
# {
# :url => 'http://something.com/webhook',
# :content_type => 'json'
# },
# {
# :add_events => ['status'],
# :remove_events => ['pull_request'],
# :active => true
# }
# )
def edit_hook(repo, id, name, config, options = {})
options = { name: name, config: config }.merge(options)
patch "#{Repository.path repo}/hooks/#{id}", options
end
# Delete hook
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param id [Integer] Id of the hook to remove.
# @return [Boolean] True if hook removed, false otherwise.
# @see https://developer.github.com/v3/repos/hooks/#delete-a-hook
# @example
# @client.remove_hook('octokit/octokit.rb', 1000000)
def remove_hook(repo, id, options = {})
boolean_from_response :delete, "#{Repository.path repo}/hooks/#{id}", options
end
# Test hook
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param id [Integer] Id of the hook to test.
# @return [Boolean] Success
# @see https://developer.github.com/v3/repos/hooks/#test-a-push-hook
# @example
# @client.test_hook('octokit/octokit.rb', 1000000)
def test_hook(repo, id, options = {})
boolean_from_response :post, "#{Repository.path repo}/hooks/#{id}/tests", options
end
# Ping hook
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param id [Integer] Id of the hook to send a ping.
# @return [Boolean] Ping requested?
# @see https://developer.github.com/v3/repos/hooks/#ping-a-hook
# @example
# @client.ping_hook('octokit/octokit.rb', 1000000)
def ping_hook(repo, id, options = {})
boolean_from_response :post, "#{Repository.path repo}/hooks/#{id}/pings", options
end
# List org hooks
#
# Requires client authenticated as admin for the org.
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Array<Sawyer::Resource>] Array of hashes representing hooks.
# @see https://developer.github.com/v3/orgs/hooks/#list-hooks
# @example
# @client.org_hooks('octokit')
def org_hooks(org, options = {})
paginate "#{Organization.path org}/hooks", options
end
alias list_org_hooks org_hooks
# Get an org hook
#
# Requires client authenticated as admin for the org.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param id [Integer] Id of the hook to get.
# @return [Sawyer::Resource] Hash representing hook.
# @see https://developer.github.com/v3/orgs/hooks/#get-single-hook
# @example
# @client.org_hook('octokit', 123)
def org_hook(org, id, options = {})
get "#{Organization.path org}/hooks/#{id}", options
end
# Create an org hook
#
# Requires client authenticated as admin for the org.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param config [Hash] A Hash containing key/value pairs to provide
# settings for this hook.
# @option options [Array<String>] :events ('["push"]') Determines what
# events the hook is triggered for.
# @option options [Boolean] :active Determines whether the hook is
# actually triggered on pushes.
# @return [Sawyer::Resource] Hook info for the new hook
# @see https://api.github.com/hooks
# @see https://developer.github.com/v3/orgs/hooks/#create-a-hook
# @example
# @client.create_org_hook(
# 'octokit',
# {
# :url => 'http://something.com/webhook',
# :content_type => 'json'
# },
# {
# :events => ['push', 'pull_request'],
# :active => true
# }
# )
def create_org_hook(org, config, options = {})
options = { name: 'web', config: config }.merge(options)
post "#{Organization.path org}/hooks", options
end
# Update an org hook
#
# Requires client authenticated as admin for the org.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param id [Integer] Id of the hook to update.
# @param config [Hash] A Hash containing key/value pairs to provide
# settings for this hook.
# @option options [Array<String>] :events ('["push"]') Determines what
# events the hook is triggered for.
# @option options [Boolean] :active Determines whether the hook is
# actually triggered on pushes.
# @return [Sawyer::Resource] Hook info for the new hook
# @see https://api.github.com/hooks
# @see https://developer.github.com/v3/orgs/hooks/#edit-a-hook
# @example
# @client.edit_org_hook(
# 'octokit',
# 123,
# {
# :url => 'http://something.com/webhook',
# :content_type => 'json'
# },
# {
# :events => ['push', 'pull_request'],
# :active => true
# }
# )
def edit_org_hook(org, id, config, options = {})
options = { config: config }.merge(options)
patch "#{Organization.path org}/hooks/#{id}", options
end
alias update_org_hook edit_org_hook
# Ping org hook
#
# Requires client authenticated as admin for the org.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param id [Integer] Id of the hook to update.
# @return [Boolean] Success
# @see https://developer.github.com/v3/orgs/hooks/#ping-a-hook
# @example
# @client.ping_org_hook('octokit', 1000000)
def ping_org_hook(org, id, options = {})
boolean_from_response :post, "#{Organization.path org}/hooks/#{id}/pings", options
end
# Remove org hook
#
# Requires client authenticated as admin for the org.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param id [Integer] Id of the hook to update.
# @return [Boolean] True if hook removed, false otherwise.
# @see https://developer.github.com/v3/orgs/hooks/#delete-a-hook
# @example
# @client.remove_org_hook('octokit', 1000000)
def remove_org_hook(org, id, options = {})
boolean_from_response :delete, "#{Organization.path org}/hooks/#{id}", options
end
# Parse payload string
#
# @param payload_string [String] The payload
# @return [Sawyer::Resource] The payload object
# @see https://developer.github.com/v3/activity/events/types/
def parse_payload(payload_string)
payload_hash = agent.class.decode payload_string
Sawyer::Resource.new agent, payload_hash
end
end
end
end
@@ -0,0 +1,367 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Issues API
#
# @see https://developer.github.com/v3/issues/
module Issues
# List issues for the authenticated user or repository
#
# @param repository [Integer, String, Repository, Hash] A GitHub repository.
# @param options [Sawyer::Resource] A customizable set of options.
# @option options [Integer] :milestone Milestone number.
# @option options [String] :state (open) State: <tt>open</tt>, <tt>closed</tt>, or <tt>all</tt>.
# @option options [String] :assignee User login.
# @option options [String] :creator User login.
# @option options [String] :mentioned User login.
# @option options [String] :labels List of comma separated Label names. Example: <tt>bug,ui,@high</tt>.
# @option options [String] :sort (created) Sort: <tt>created</tt>, <tt>updated</tt>, or <tt>comments</tt>.
# @option options [String] :direction (desc) Direction: <tt>asc</tt> or <tt>desc</tt>.
# @option options [Integer] :page (1) Page number.
# @return [Array<Sawyer::Resource>] A list of issues for a repository.
# @see https://developer.github.com/v3/issues/#list-issues-for-a-repository
# @see https://developer.github.com/v3/issues/#list-issues
# @example List issues for a repository
# Octokit.list_issues("sferik/rails_admin")
# @example List issues for the authenticated user across repositories
# @client = Octokit::Client.new(:login => 'foo', :password => 'bar')
# @client.list_issues
def list_issues(repository = nil, options = {})
path = repository ? "#{Repository.new(repository).path}/issues" : 'issues'
paginate path, options
end
alias issues list_issues
# List all issues across owned and member repositories for the authenticated user
#
# @param options [Sawyer::Resource] A customizable set of options.
# @option options [String] :filter (assigned) State: <tt>assigned</tt>, <tt>created</tt>, <tt>mentioned</tt>, <tt>subscribed</tt> or <tt>closed</tt>.
# @option options [String] :state (open) State: <tt>open</tt>, <tt>closed</tt>, or <tt>all</tt>.
# @option options [Array<String>] :labels List of Label names. Example: <tt>['bug', 'ui', '@high']</tt>.
# @option options [String] :sort (created) Sort: <tt>created</tt>, <tt>updated</tt>, or <tt>comments</tt>.
# @option options [String] :direction (desc) Direction: <tt>asc</tt> or <tt>desc</tt>.
# @option options [Integer] :page (1) Page number.
# @option options [String] :since Timestamp in ISO 8601
# format: YYYY-MM-DDTHH:MM:SSZ
# @return [Array<Sawyer::Resource>] A list of issues for a repository.
# @see https://developer.github.com/v3/issues/#list-issues
# @example List issues for the authenticated user across owned and member repositories
# @client = Octokit::Client.new(:login => 'foo', :password => 'bar')
# @client.user_issues
def user_issues(options = {})
paginate 'user/issues', options
end
# List all issues for a given organization for the authenticated user
#
# @param org [String, Integer] Organization GitHub login or id.
# @param options [Sawyer::Resource] A customizable set of options.
# @option options [String] :filter (assigned) State: <tt>assigned</tt>, <tt>created</tt>, <tt>mentioned</tt>, <tt>subscribed</tt> or <tt>closed</tt>.
# @option options [String] :state (open) State: <tt>open</tt>, <tt>closed</tt>, or <tt>all</tt>.
# @option options [Array<String>] :labels List of Label names. Example: <tt>['bug', 'ui', '@high']</tt>.
# @option options [String] :sort (created) Sort: <tt>created</tt>, <tt>updated</tt>, or <tt>comments</tt>.
# @option options [String] :direction (desc) Direction: <tt>asc</tt> or <tt>desc</tt>.
# @option options [Integer] :page (1) Page number.
# @option options [String] :since Timestamp in ISO 8601
# format: YYYY-MM-DDTHH:MM:SSZ
# @return [Array<Sawyer::Resource>] A list of issues.
# @see https://developer.github.com/v3/issues/#list-issues
# @example List all issues for a given organization for the authenticated user
# @client = Octokit::Client.new(:login => 'foo', :password => 'bar')
# @client.org_issues("octokit")
def org_issues(org, options = {})
paginate "#{Organization.path org}/issues", options
end
# Create an issue for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param title [String] A descriptive title
# @param body [String] An optional concise description
# @param options [Hash] A customizable set of options.
# @option options [String] :assignee User login.
# @option options [Array<String>] :assignees User login.
# @option options [Integer] :milestone Milestone number.
# @option options [String] :labels List of comma separated Label names. Example: <tt>bug,ui,@high</tt>.
# @return [Sawyer::Resource] Your newly created issue
# @see https://developer.github.com/v3/issues/#create-an-issue
# @example Create a new Issues for a repository
# Octokit.create_issue("sferik/rails_admin", 'Updated Docs', 'Added some extra links')
def create_issue(repo, title, body = nil, options = {})
options[:labels] = case options[:labels]
when String
options[:labels].split(',').map(&:strip)
when Array
options[:labels]
else
[]
end
parameters = { title: title }
parameters[:body] = body unless body.nil?
post "#{Repository.path repo}/issues", options.merge(parameters)
end
alias open_issue create_issue
# Get a single issue from a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @return [Sawyer::Resource] The issue you requested, if it exists
# @see https://developer.github.com/v3/issues/#get-a-single-issue
# @example Get issue #25 from octokit/octokit.rb
# Octokit.issue("octokit/octokit.rb", "25")
def issue(repo, number, options = {})
get "#{Repository.path repo}/issues/#{number}", options
end
# Close an issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @param options [Hash] A customizable set of options.
# @option options [String] :assignee User login.
# @option options [Array<String>] :assignees User login.
# @option options [Integer] :milestone Milestone number.
# @option options [Array<String>] :labels List of Label names. Example: <tt>['bug', 'ui', '@high']</tt>.
# @return [Sawyer::Resource] The updated Issue
# @see https://developer.github.com/v3/issues/#edit-an-issue
# @example Close Issue #25 from octokit/octokit.rb
# Octokit.close_issue("octokit/octokit.rb", "25")
def close_issue(repo, number, options = {})
patch "#{Repository.path repo}/issues/#{number}", options.merge({ state: 'closed' })
end
# Reopen an issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @param options [Hash] A customizable set of options.
# @option options [String] :assignee User login.
# @option options [Array<String>] :assignees User login.
# @option options [Integer] :milestone Milestone number.
# @option options [Array<String>] :labels List of Label names. Example: <tt>['bug', 'ui', '@high']</tt>.
# @return [Sawyer::Resource] The updated Issue
# @see https://developer.github.com/v3/issues/#edit-an-issue
# @example Reopen Issue #25 from octokit/octokit.rb
# Octokit.reopen_issue("octokit/octokit.rb", "25")
def reopen_issue(repo, number, options = {})
patch "#{Repository.path repo}/issues/#{number}", options.merge({ state: 'open' })
end
# Lock an issue's conversation, limiting it to collaborators
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @return [Boolean] Success
# @see https://developer.github.com/v3/issues/#lock-an-issue
# @example Lock Issue #25 from octokit/octokit.rb
# Octokit.lock_issue("octokit/octokit.rb", "25")
def lock_issue(repo, number, options = {})
boolean_from_response :put, "#{Repository.path repo}/issues/#{number}/lock", options
end
# Unlock an issue's conversation, opening it to all viewers
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @return [Boolean] Success
# @see https://developer.github.com/v3/issues/#unlock-an-issue
# @example Unlock Issue #25 from octokit/octokit.rb
# Octokit.close_issue("octokit/octokit.rb", "25")
def unlock_issue(repo, number, options = {})
boolean_from_response :delete, "#{Repository.path repo}/issues/#{number}/lock", options
end
# Update an issue
#
# @overload update_issue(repo, number, title, body, options)
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @param title [String] Updated title for the issue
# @param body [String] Updated body of the issue
# @param options [Hash] A customizable set of options.
# @option options [String] :assignee User login.
# @option options [Array<String>] :assignees User login.
# @option options [Integer] :milestone Milestone number.
# @option options [String] :labels List of comma separated Label names. Example: <tt>bug,ui,@high</tt>.
# @option options [String] :state State of the issue. <tt>open</tt> or <tt>closed</tt>
#
# @overload update_issue(repo, number, options)
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @param options [Hash] A customizable set of options.
# @option options [String] :title Updated title for the issue
# @option options [String] :body Updated body of the issue
# @option options [String] :assignee User login.
# @option options [Array<String>] :assignees User login.
# @option options [Integer] :milestone Milestone number.
# @option options [Array<String>] :labels List of Label names. Example: <tt>['bug', 'ui', '@high']</tt>.
# @option options [String] :state State of the issue. <tt>open</tt> or <tt>closed</tt>
# @return [Sawyer::Resource] The updated Issue
# @see https://developer.github.com/v3/issues/#edit-an-issue
#
# @example Change the title of Issue #25
# Octokit.update_issue("octokit/octokit.rb", "25", "A new title", "the same body")
#
# @example Change only the assignee of Issue #25
# Octokit.update_issue("octokit/octokit.rb", "25", :assignee => "pengwynn")
def update_issue(repo, number, *args)
arguments = Arguments.new(args)
opts = arguments.options
unless arguments.empty?
opts[:title] = arguments.shift
opts[:body] = arguments.shift
end
patch "#{Repository.path repo}/issues/#{number}", opts
end
# Get all comments attached to issues for the repository
#
# By default, Issue Comments are ordered by ascending ID.
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param options [Hash] Optional parameters
# @option options [String] :sort created or updated
# @option options [String] :direction asc or desc. Ignored without sort
# parameter.
# @option options [String] :since Timestamp in ISO 8601
# format: YYYY-MM-DDTHH:MM:SSZ
#
# @return [Array<Sawyer::Resource>] List of issues comments.
#
# @see https://developer.github.com/v3/issues/comments/#list-comments-in-a-repository
#
# @example Get the comments for issues in the octokit repository
# @client.issues_comments("octokit/octokit.rb")
#
# @example Get issues comments, sort by updated descending since a time
# @client.issues_comments("octokit/octokit.rb", {
# :sort => 'desc',
# :direction => 'asc',
# :since => '2010-05-04T23:45:02Z'
# })
def issues_comments(repo, options = {})
paginate "#{Repository.path repo}/issues/comments", options
end
# Get all comments attached to an issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @return [Array<Sawyer::Resource>] Array of comments that belong to an issue
# @see https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue
# @example Get comments for issue #25 from octokit/octokit.rb
# Octokit.issue_comments("octokit/octokit.rb", "25")
def issue_comments(repo, number, options = {})
paginate "#{Repository.path repo}/issues/#{number}/comments", options
end
# Get a single comment attached to an issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the comment
# @return [Sawyer::Resource] The specific comment in question
# @see https://developer.github.com/v3/issues/comments/#get-a-single-comment
# @example Get comment #1194549 from an issue on octokit/octokit.rb
# Octokit.issue_comment("octokit/octokit.rb", 1194549)
def issue_comment(repo, number, options = {})
paginate "#{Repository.path repo}/issues/comments/#{number}", options
end
# Add a comment to an issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Issue number
# @param comment [String] Comment to be added
# @return [Sawyer::Resource] Comment
# @see https://developer.github.com/v3/issues/comments/#create-a-comment
# @example Add the comment "Almost to v1" to Issue #23 on octokit/octokit.rb
# Octokit.add_comment("octokit/octokit.rb", 23, "Almost to v1")
def add_comment(repo, number, comment, options = {})
post "#{Repository.path repo}/issues/#{number}/comments", options.merge({ body: comment })
end
# Update a single comment on an issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Comment number
# @param comment [String] Body of the comment which will replace the existing body.
# @return [Sawyer::Resource] Comment
# @see https://developer.github.com/v3/issues/comments/#edit-a-comment
# @example Update the comment #1194549 with body "I've started this on my 25-issue-comments-v3 fork" on an issue on octokit/octokit.rb
# Octokit.update_comment("octokit/octokit.rb", 1194549, "Almost to v1, added this on my fork")
def update_comment(repo, number, comment, options = {})
patch "#{Repository.path repo}/issues/comments/#{number}", options.merge({ body: comment })
end
# Delete a single comment
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Comment number
# @return [Boolean] Success
# @see https://developer.github.com/v3/issues/comments/#delete-a-comment
# @example Delete the comment #1194549 on an issue on octokit/octokit.rb
# Octokit.delete_comment("octokit/octokit.rb", 1194549)
def delete_comment(repo, number, options = {})
boolean_from_response :delete, "#{Repository.path repo}/issues/comments/#{number}", options
end
# Get the timeline for an issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the comment
# @return [Sawyer::Resource] The timeline for this issue
# @see https://developer.github.com/v3/issues/timeline/
# @example Get timeline for issue #1435 on octokit/octokit.rb
# Octokit.issue_timeline("octokit/octokit.rb", 1435)
def issue_timeline(repo, number, options = {})
paginate "#{Repository.path repo}/issues/#{number}/timeline", options
end
# Lists the available assignees for issues in a repository.
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] List of GitHub users.
# @see https://developer.github.com/v3/issues/assignees/#list-assignees
# @example Get available assignees on repository octokit/octokit.rb
# Octokit.list_assignees("octokit/octokit.rb")
def list_assignees(repo, options = {})
paginate "#{Repository.path repo}/assignees", options
end
# Add assignees to an issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Issue number
# @param assignees [Array<String>] Assignees to be added
# @return [Sawyer::Resource] Issue
# @see https://developer.github.com/v3/issues/assignees/#add-assignees-to-an-issue
# @example Add assignees "pengwynn" and "joeyw" to Issue #23 on octokit/octokit.rb
# Octokit.add_assignees("octokit/octokit.rb", 23, ["pengwynn", "joeyw"])
def add_assignees(repo, number, assignees, options = {})
post "#{Repository.path repo}/issues/#{number}/assignees", options.merge({ assignees: assignees })
end
# Remove assignees from an issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Issue number
# @param assignees [Array<String>] Assignees to be removed
# @param options [Hash] Header params for request
# @return [Sawyer::Resource] Issue
# @see https://developer.github.com/v3/issues/assignees/#remove-assignees-from-an-issue
# @example Remove assignees "pengwynn" and "joeyw" from Issue #23 on octokit/octokit.rb
# Octokit.remove_assignees("octokit/octokit.rb", 23, ["pengwynn", "joeyw"])
#
# @example Remove assignees "pengwynn" from Issue #23 on octokit/octokit.rb
# Octokit.remove_assignees("octokit/octokit.rb", 23, ["pengwynn"],
# :accept => "application/vnd.github.v3+json")
def remove_assignees(repo, number, assignees, options = {})
delete "#{Repository.path repo}/issues/#{number}/assignees", options.merge({ assignees: assignees })
end
end
end
end
@@ -0,0 +1,156 @@
# frozen_string_literal: true
require 'erb'
module Octokit
class Client
# Methods for the Issue Labels API
#
# @see https://developer.github.com/v3/issues/labels/
module Labels
# List available labels for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] A list of the labels across the repository
# @see https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository
# @example List labels for octokit/octokit.rb
# Octokit.labels("octokit/octokit.rb")
def labels(repo, options = {})
paginate "#{Repository.path repo}/labels", options
end
# Get single label for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param name [String] Name of the label
# @return [Sawyer::Resource] A single label from the repository
# @see https://developer.github.com/v3/issues/labels/#get-a-single-label
# @example Get the "V3 Addition" label from octokit/octokit.rb
# Octokit.label("octokit/octokit.rb", "V3 Addition")
def label(repo, name, options = {})
get "#{Repository.path repo}/labels/#{ERB::Util.url_encode(name)}", options
end
# Add a label to a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param label [String] A new label
# @param color [String] A color, in hex, without the leading #
# @return [Sawyer::Resource] The new label
# @see https://developer.github.com/v3/issues/labels/#create-a-label
# @example Add a new label "Version 1.0" with color "#cccccc"
# Octokit.add_label("octokit/octokit.rb", "Version 1.0", "cccccc")
def add_label(repo, label, color = 'ffffff', options = {})
post "#{Repository.path repo}/labels", options.merge({ name: label, color: color })
end
# Update a label
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param label [String] The name of the label which will be updated
# @param options [Hash] A customizable set of options.
# @option options [String] :name An updated label name
# @option options [String] :color An updated color value, in hex, without leading #
# @return [Sawyer::Resource] The updated label
# @see https://developer.github.com/v3/issues/labels/#update-a-label
# @example Update the label "Version 1.0" with new color "#cceeaa"
# Octokit.update_label("octokit/octokit.rb", "Version 1.0", {:color => "cceeaa"})
def update_label(repo, label, options = {})
patch "#{Repository.path repo}/labels/#{ERB::Util.url_encode(label)}", options
end
# Delete a label from a repository.
#
# This deletes the label from the repository, and removes it from all issues.
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param label [String] String name of the label
# @return [Boolean] Success
# @see https://developer.github.com/v3/issues/labels/#delete-a-label
# @example Delete the label "Version 1.0" from the repository.
# Octokit.delete_label!("octokit/octokit.rb", "Version 1.0")
def delete_label!(repo, label, options = {})
boolean_from_response :delete, "#{Repository.path repo}/labels/#{ERB::Util.url_encode(label)}", options
end
# Remove a label from an Issue
#
# This removes the label from the Issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @param label [String] String name of the label
# @return [Array<Sawyer::Resource>] A list of the labels currently on the issue
# @see https://developer.github.com/v3/issues/labels/#remove-a-label-from-an-issue
# @example Remove the label "Version 1.0" from the repository.
# Octokit.remove_label("octokit/octokit.rb", 23, "Version 1.0")
def remove_label(repo, number, label, options = {})
delete "#{Repository.path repo}/issues/#{number}/labels/#{ERB::Util.url_encode(label)}", options
end
# Remove all label from an Issue
#
# This removes the label from the Issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @return [Boolean] Success of operation
# @see https://developer.github.com/v3/issues/labels/#remove-all-labels-from-an-issue
# @example Remove all labels from Issue #23
# Octokit.remove_all_labels("octokit/octokit.rb", 23)
def remove_all_labels(repo, number, options = {})
boolean_from_response :delete, "#{Repository.path repo}/issues/#{number}/labels", options
end
# List labels for a given issue
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the issue
# @return [Array<Sawyer::Resource>] A list of the labels currently on the issue
# @see https://developer.github.com/v3/issues/labels/#list-labels-on-an-issue
# @example List labels for octokit/octokit.rb, issue # 1
# Octokit.labels_for_issue("octokit/octokit.rb", 1)
def labels_for_issue(repo, number, options = {})
paginate "#{Repository.path repo}/issues/#{number}/labels", options
end
# Add label(s) to an Issue
#
# @param repo [Integer, String, Repository, Hash] A Github repository
# @param number [Integer] Number ID of the issue
# @param labels [Array] An array of labels to apply to this Issue
# @return [Array<Sawyer::Resource>] A list of the labels currently on the issue
# @see https://developer.github.com/v3/issues/labels/#add-labels-to-an-issue
# @example Add two labels for octokit/octokit.rb
# Octokit.add_labels_to_an_issue("octokit/octokit.rb", 10, ['V3 Transition', 'Improvement'])
def add_labels_to_an_issue(repo, number, labels)
post "#{Repository.path repo}/issues/#{number}/labels", labels
end
# Replace all labels on an Issue
#
# @param repo [Integer, String, Repository, Hash] A Github repository
# @param number [Integer] Number ID of the issue
# @param labels [Array] An array of labels to use as replacement
# @return [Array<Sawyer::Resource>] A list of the labels currently on the issue
# @see https://developer.github.com/v3/issues/labels/#replace-all-labels-for-an-issue
# @example Replace labels for octokit/octokit.rb Issue #10
# Octokit.replace_all_labels("octokit/octokit.rb", 10, ['V3 Transition', 'Improvement'])
def replace_all_labels(repo, number, labels, _options = {})
put "#{Repository.path repo}/issues/#{number}/labels", labels
end
# Get labels for every issue in a milestone
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param number [Integer] Number ID of the milestone
# @return [Array<Sawyer::Resource>] A list of the labels across the milestone
# @see http://developer.github.com/v3/issues/labels/#get-labels-for-every-issue-in-a-milestone
# @example List all labels for milestone #2 on octokit/octokit.rb
# Octokit.labels_for_milestone("octokit/octokit.rb", 2)
def labels_for_milestone(repo, number, options = {})
paginate "#{Repository.path repo}/milestones/#{number}/labels", options
end
end
end
end
@@ -0,0 +1,42 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Legacy Search API
#
# @see https://developer.github.com/v3/search/
module LegacySearch
# Legacy repository search
#
# @see https://developer.github.com/v3/search/#search-repositories
# @param q [String] Search keyword
# @return [Array<Sawyer::Resource>] List of repositories found
def legacy_search_repositories(q, options = {})
get("legacy/repos/search/#{q}", options)['repositories']
end
# Legacy search issues within a repository
#
# @param repo [String, Repository, Hash] A GitHub repository
# @param search_term [String] The term to search for
# @param state [String] :state (open) <tt>open</tt> or <tt>closed</tt>.
# @return [Array<Sawyer::Resource>] A list of issues matching the search term and state
# @example Search for 'test' in the open issues for sferik/rails_admin
# Octokit.search_issues("sferik/rails_admin", 'test', 'open')
def legacy_search_issues(repo, search_term, state = 'open', options = {})
get("legacy/issues/search/#{Repository.new(repo)}/#{state}/#{search_term}", options)['issues']
end
# Search for user.
#
# @param search [String] User to search for.
# @return [Array<Sawyer::Resource>] Array of hashes representing users.
# @see https://developer.github.com/v3/search/#search-users
# @example
# Octokit.search_users('pengwynn')
def legacy_search_users(search, options = {})
get("legacy/user/search/#{search}", options)['users']
end
end
end
end
@@ -0,0 +1,42 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for licenses API
#
module Licenses
# List all licenses
#
# @see https://developer.github.com/v3/licenses/#list-all-licenses
# @return [Array<Sawyer::Resource>] A list of licenses
# @example
# Octokit.licenses
def licenses(options = {})
paginate 'licenses', options
end
# List an individual license
#
# @see https://developer.github.com/v3/licenses/#get-an-individual-license
# @param license_name [String] The license name
# @return <Sawyer::Resource> An individual license
# @example
# Octokit.license 'mit'
def license(license_name, options = {})
get "licenses/#{license_name}", options
end
# Returns the contents of the repository’s license file, if one is detected.
#
# @see https://developer.github.com/v3/licenses/#get-the-contents-of-a-repositorys-license
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @option options [String] :ref name of the Commit/Branch/Tag. Defaults to 'master'.
# @return [Sawyer::Resource] The detail of the license file
# @example
# Octokit.repository_license_contents 'benbalter/licensee'
def repository_license_contents(repo, options = {})
get "#{Repository.path repo}/license", options
end
end
end
end
@@ -0,0 +1,27 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Markdown API
#
# @see https://developer.github.com/v3/markdown/
module Markdown
# Render an arbitrary Markdown document
#
# @param text [String] Markdown source
# @option options [String] (optional) :mode (`markdown` or `gfm`)
# @option options [String] (optional) :context Repo context
# @return [String] HTML renderization
# @see https://developer.github.com/v3/markdown/#render-an-arbitrary-markdown-document
# @example Render some GFM
# Octokit.markdown('Fixed in #111', :mode => "gfm", :context => "octokit/octokit.rb")
def markdown(text, options = {})
options[:text] = text
options[:repo] = Repository.new(options[:repo]) if options[:repo]
options[:accept] = 'application/vnd.github.raw'
post 'markdown', options
end
end
end
end
@@ -0,0 +1,56 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Marketplace Listing API
#
# @see https://developer.github.com/v3/apps/marketplace/
module Marketplace
# List all plans for an app's marketplace listing
#
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/marketplace/#list-all-plans-for-your-marketplace-listing
#
# @return [Array<Sawyer::Resource>] A list of plans
def list_plans(options = {})
paginate '/marketplace_listing/plans', options
end
# List all GitHub accounts on a specific plan
#
# @param plan_id [Integer] The id of the GitHub plan
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/marketplace/#list-all-github-accounts-user-or-organization-on-a-specific-plan
#
# @return [Array<Sawyer::Resource>] A list of accounts
def list_accounts_for_plan(plan_id, options = {})
paginate "/marketplace_listing/plans/#{plan_id}/accounts", options
end
# Get the plan associated with a given GitHub account
#
# @param account_id [Integer] The id of the GitHub account
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/marketplace/#check-if-a-github-account-is-associated-with-any-marketplace-listing
#
# @return <Sawyer::Resource> Account with plan details, or nil
def plan_for_account(account_id, options = {})
get "/marketplace_listing/accounts/#{account_id}", options
end
# Get user's Marketplace purchases
#
# @param options [Hash] A customizable set of options
#
# @see https://developer.github.com/v3/apps/marketplace/#get-a-users-marketplace-purchases
#
# @return [Array<Sawyer::Resource>] A list of Marketplace purchases
def marketplace_purchases(options = {})
get '/user/marketplace_purchases', options
end
end
end
end
@@ -0,0 +1,20 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Meta API
#
# @see https://developer.github.com/v3/meta/
module Meta
# Get meta information about GitHub.com, the service.
# @see https://developer.github.com/v3/meta/#meta
# @return [Sawyer::Resource] Hash with meta information.
# @example Get GitHub meta information
# @client.github_meta
def meta(options = {})
get 'meta', options
end
alias github_meta meta
end
end
end
@@ -0,0 +1,87 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Issues Milestones API
#
# @see https://developer.github.com/v3/issues/milestones/
module Milestones
# List milestones for a repository
#
# @param repository [Integer, String, Repository, Hash] A GitHub repository
# @param options [Hash] A customizable set of options.
# @option options [Integer] :milestone Milestone number.
# @option options [String] :state (open) State: <tt>open</tt>, <tt>closed</tt>, or <tt>all</tt>.
# @option options [String] :sort (created) Sort: <tt>created</tt>, <tt>updated</tt>, or <tt>comments</tt>.
# @option options [String] :direction (desc) Direction: <tt>asc</tt> or <tt>desc</tt>.
# @return [Array<Sawyer::Resource>] A list of milestones for a repository.
# @see https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository
# @example List milestones for a repository
# Octokit.list_milestones("octokit/octokit.rb")
def list_milestones(repository, options = {})
paginate "#{Repository.path repository}/milestones", options
end
alias milestones list_milestones
# Get a single milestone for a repository
#
# @param repository [Integer, String, Repository, Hash] A GitHub repository
# @param options [Hash] A customizable set of options.
# @option options [Integer] :milestone Milestone number.
# @return [Sawyer::Resource] A single milestone from a repository.
# @see https://developer.github.com/v3/issues/milestones/#get-a-single-milestone
# @example Get a single milestone for a repository
# Octokit.milestone("octokit/octokit.rb", 1)
def milestone(repository, number, options = {})
get "#{Repository.path repository}/milestones/#{number}", options
end
# Create a milestone for a repository
#
# @param repository [Integer, String, Repository, Hash] A GitHub repository
# @param title [String] A unique title.
# @param options [Hash] A customizable set of options.
# @option options [String] :state (open) State: <tt>open</tt> or <tt>closed</tt>.
# @option options [String] :description A meaningful description
# @option options [Time] :due_on Set if the milestone has a due date
# @return [Sawyer::Resource] A single milestone object
# @see https://developer.github.com/v3/issues/milestones/#create-a-milestone
# @example Create a milestone for a repository
# Octokit.create_milestone("octokit/octokit.rb", "0.7.0", {:description => 'Add support for v3 of Github API'})
def create_milestone(repository, title, options = {})
post "#{Repository.path repository}/milestones", options.merge({ title: title })
end
# Update a milestone for a repository
#
# @param repository [Integer, String, Repository, Hash] A GitHub repository
# @param number [String, Integer] ID of the milestone
# @param options [Hash] A customizable set of options.
# @option options [String] :title A unique title.
# @option options [String] :state (open) State: <tt>open</tt> or <tt>closed</tt>.
# @option options [String] :description A meaningful description
# @option options [Time] :due_on Set if the milestone has a due date
# @return [Sawyer::Resource] A single milestone object
# @see https://developer.github.com/v3/issues/milestones/#update-a-milestone
# @example Update a milestone for a repository
# Octokit.update_milestone("octokit/octokit.rb", 1, {:description => 'Add support for v3 of Github API'})
def update_milestone(repository, number, options = {})
patch "#{Repository.path repository}/milestones/#{number}", options
end
alias edit_milestone update_milestone
# Delete a single milestone for a repository
#
# @param repository [Integer, String, Repository, Hash] A GitHub repository
# @param options [Hash] A customizable set of options.
# @option options [Integer] :milestone Milestone number.
# @return [Boolean] Success
# @see https://developer.github.com/v3/issues/milestones/#delete-a-milestone
# @example Delete a single milestone from a repository
# Octokit.delete_milestone("octokit/octokit.rb", 1)
def delete_milestone(repository, number, options = {})
boolean_from_response :delete, "#{Repository.path repository}/milestones/#{number}", options
end
end
end
end
@@ -0,0 +1,167 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Notifications API
#
# @see https://developer.github.com/v3/activity/notifications/
module Notifications
# List your notifications
#
# @param options [Hash] Optional parameters
# @option options [Boolean] :all 'true' to show notifications marked as
# read.
# @option options [Boolean] :participating 'true' to show only
# notifications in which the user is directly participating or
# mentioned.
# @option options [String] :since Time filters out any notifications
# updated before the given time. The time should be passed in as UTC in
# the ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. Ex. '2012-10-09T23:39:01Z'
# @return [Array<Sawyer::Resource>] Array of notifications.
# @see https://developer.github.com/v3/activity/notifications/#list-your-notifications
# @example Get users notifications
# @client.notifications
# @example Get all notifications since a certain time.
# @client.notifications({all: true, since: '2012-10-09T23:39:01Z'})
def notifications(options = {})
paginate 'notifications', options
end
# List your notifications in a repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param options [Hash] Optional parameters
# @option options [Boolean] :all 'true' to show notifications marked as
# read.
# @option options [Boolean] :participating 'true' to show only
# notifications in which the user is directly participating or
# mentioned.
# @option options [String] :since Time filters out any notifications
# updated before the given time. The time should be passed in as UTC in
# the ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. Ex. '2012-10-09T23:39:01Z'
# @return [Array<Sawyer::Resource>] Array of notifications.
# @see https://developer.github.com/v3/activity/notifications/#list-your-notifications-in-a-repository
# @example Get your notifications for octokit/octokit.rb
# @client.repository_notifications('octokit/octokit.rb')
# @example Get your notifications for octokit/octokit.rb since a time.
# @client.repository_notifications({since: '2012-10-09T23:39:01Z'})
def repository_notifications(repo, options = {})
paginate "#{Repository.path repo}/notifications", options
end
alias repo_notifications repository_notifications
# Mark notifications as read
#
# @param options [Hash] Optional parameters
# @option options [Boolean] :unread Changes the unread status of the
# threads.
# @option options [Boolean] :read Inverse of 'unread'.
# @option options [String] :last_read_at ('Now') Describes the last point
# that notifications were checked. Anything updated since this time
# will not be updated. The time should be passed in as UTC in the
# ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. Ex. '2012-10-09T23:39:01Z'
# @return [Boolean] True if marked as read, false otherwise
# @see https://developer.github.com/v3/activity/notifications/#mark-as-read
#
# @example
# @client.mark_notifications_as_read
def mark_notifications_as_read(options = {})
request :put, 'notifications', options
last_response.status == 205
end
# Mark notifications from a specific repository as read
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param options [Hash] Optional parameters
# @option options [Boolean] :unread Changes the unread status of the
# threads.
# @option options [Boolean] :read Inverse of 'unread'.
# @option options [String] :last_read_at ('Now') Describes the last point
# that notifications were checked. Anything updated since this time
# will not be updated. The time should be passed in as UTC in the
# ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. Ex. '2012-10-09T23:39:01Z'
# @return [Boolean] True if marked as read, false otherwise
# @see https://developer.github.com/v3/activity/notifications/#mark-notifications-as-read-in-a-repository
# @example
# @client.mark_notifications_as_read("octokit/octokit.rb")
def mark_repository_notifications_as_read(repo, options = {})
request :put, "#{Repository.path repo}/notifications", options
last_response.status == 205
end
alias mark_repo_notifications_as_read mark_repository_notifications_as_read
# List notifications for a specific thread
#
# @param thread_id [Integer] Id of the thread.
# @return [Array<Sawyer::Resource>] Array of notifications.
# @see https://developer.github.com/v3/activity/notifications/#view-a-single-thread
#
# @example
# @client.notification_thread(1000)
def thread_notifications(thread_id, options = {})
get "notifications/threads/#{thread_id}", options
end
# Mark thread as read
#
# @param thread_id [Integer] Id of the thread to update.
# @return [Boolean] True if updated, false otherwise.
# @see https://developer.github.com/v3/activity/notifications/#mark-a-thread-as-read
# @example
# @client.mark_thread_as_read(1, :read => false)
def mark_thread_as_read(thread_id, options = {})
request :patch, "notifications/threads/#{thread_id}", options
last_response.status == 205
end
# Get thread subscription
#
# @param thread_id [Integer] Id of the thread.
# @return [Sawyer::Resource] Subscription.
# @see https://developer.github.com/v3/activity/notifications/#get-a-thread-subscription
# @example
# @client.thread_subscription(1)
def thread_subscription(thread_id, options = {})
get "notifications/threads/#{thread_id}/subscription", options
end
# Update thread subscription
#
# This lets you subscribe to a thread, or ignore it. Subscribing to a
# thread is unnecessary if the user is already subscribed to the
# repository. Ignoring a thread will mute all future notifications (until
# you comment or get @mentioned).
#
# @param thread_id [Integer] Id of the thread.
# @param options
# @option options [Boolean] :subscribed Determines if notifications
# should be received from this repository.
# @option options [Boolean] :ignored Deterimines if all notifications
# should be blocked from this repository.
# @return [Sawyer::Resource] Updated subscription.
# @see https://developer.github.com/v3/activity/notifications/#set-a-thread-subscription
# @example Subscribe to notifications
# @client.update_thread_subscription(1, :subscribed => true)
# @example Ignore notifications from a repo
# @client.update_thread_subscription(1, :ignored => true)
def update_thread_subscription(thread_id, options = {})
put "notifications/threads/#{thread_id}/subscription", options
end
# Delete a thread subscription
#
# @param thread_id [Integer] Id of the thread.
# @return [Boolean] True if delete successful, false otherwise.
# @see https://developer.github.com/v3/activity/notifications/#delete-a-thread-subscription
# @example
# @client.delete_thread_subscription(1)
def delete_thread_subscription(thread_id, options = {})
boolean_from_response :delete, "notifications/threads/#{thread_id}/subscription", options
end
end
end
end
@@ -0,0 +1,116 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the OauthApplications API
#
# @see https://developer.github.com/v3/apps/oauth_applications
module OauthApplications
# Check if a token is valid.
#
# Applications can check if a token is valid without rate limits.
#
# @param access_token [String] 40 character GitHub OAuth access token
#
# @return [Sawyer::Resource] A single authorization for the authenticated user
# @see https://developer.github.com/v3/apps/oauth_applications/#check-a-token
#
# @example
# client = Octokit::Client.new(:client_id => 'abcdefg12345', :client_secret => 'secret')
# client.check_token('deadbeef1234567890deadbeef987654321')
def check_token(access_token, options = {})
options[:access_token] = access_token
key = options.delete(:client_id) || client_id
secret = options.delete(:client_secret) || client_secret
as_app(key, secret) do |app_client|
app_client.post "applications/#{client_id}/token", options
end
end
alias check_application_authorization check_token
# Reset a token
#
# Applications can reset a token without requiring a user to re-authorize.
#
# @param access_token [String] 40 character GitHub OAuth access token
#
# @return [Sawyer::Resource] A single authorization for the authenticated user
# @see https://developer.github.com/v3/apps/oauth_applications/#reset-a-token
#
# @example
# client = Octokit::Client.new(:client_id => 'abcdefg12345', :client_secret => 'secret')
# client.reset_token('deadbeef1234567890deadbeef987654321')
def reset_token(access_token, options = {})
options[:access_token] = access_token
key = options.delete(:client_id) || client_id
secret = options.delete(:client_secret) || client_secret
as_app(key, secret) do |app_client|
app_client.patch "applications/#{client_id}/token", options
end
end
alias reset_application_authorization reset_token
# Delete an app token
#
# Applications can revoke (delete) a token
#
# @param access_token [String] 40 character GitHub OAuth access token
#
# @return [Boolean] Result
# @see https://developer.github.com/v3/apps/oauth_applications/#delete-an-app-token
#
# @example
# client = Octokit::Client.new(:client_id => 'abcdefg12345', :client_secret => 'secret')
# client.delete_token('deadbeef1234567890deadbeef987654321')
def delete_app_token(access_token, options = {})
options[:access_token] = access_token
key = options.delete(:client_id) || client_id
secret = options.delete(:client_secret) || client_secret
begin
as_app(key, secret) do |app_client|
app_client.delete "applications/#{client_id}/token", options
app_client.last_response.status == 204
end
rescue Octokit::NotFound
false
end
end
alias delete_application_authorization delete_app_token
alias revoke_application_authorization delete_app_token
# Delete an app authorization
#
# OAuth application owners can revoke a grant for their OAuth application and a specific user.
#
# @param access_token [String] 40 character GitHub OAuth access token
#
# @return [Boolean] Result
# @see https://developer.github.com/v3/apps/oauth_applications/#delete-an-app-token
#
# @example
# client = Octokit::Client.new(:client_id => 'abcdefg12345', :client_secret => 'secret')
# client.delete_app_authorization('deadbeef1234567890deadbeef987654321')
def delete_app_authorization(access_token, options = {})
options[:access_token] = access_token
key = options.delete(:client_id) || client_id
secret = options.delete(:client_secret) || client_secret
begin
as_app(key, secret) do |app_client|
app_client.delete "applications/#{client_id}/grant", options
app_client.last_response.status == 204
end
rescue Octokit::NotFound
false
end
end
end
end
end
@@ -0,0 +1,141 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Git Data API
#
# @see https://developer.github.com/v3/git/
module Objects
# Get a single tree, fetching information about its root-level objects
#
# Pass <tt>:recursive => true</tt> in <tt>options</tt> to fetch information about all of the tree's objects, including those in subdirectories.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param tree_sha [String] The SHA of the tree to fetch
# @return [Sawyer::Resource] A hash representing the fetched tree
# @see https://developer.github.com/v3/git/trees/#get-a-tree
# @see https://developer.github.com/v3/git/trees/#get-a-tree-recursively
# @example Fetch a tree and inspect the path of one of its files
# tree = Octokit.tree("octocat/Hello-World", "9fb037999f264ba9a7fc6274d15fa3ae2ab98312")
# tree.tree.first.path # => "file.rb"
# @example Fetch a tree recursively
# tree = Octokit.tree("octocat/Hello-World", "fc6274d15fa3ae2ab983129fb037999f264ba9a7", :recursive => true)
# tree.tree.first.path # => "subdir/file.txt"
def tree(repo, tree_sha, options = {})
get "#{Repository.path repo}/git/trees/#{tree_sha}", options
end
# Create a tree
#
# Pass <tt>:base_tree => "827efc6..."</tt> in <tt>options</tt> to update an existing tree with new data.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param tree [Array] An array of hashes representing a tree structure
# @return [Sawyer::Resource] A hash representing the new tree
# @see https://developer.github.com/v3/git/trees/#create-a-tree
# @example Create a tree containing one file
# tree = Octokit.create_tree("octocat/Hello-World", [ { :path => "file.rb", :mode => "100644", :type => "blob", :sha => "44b4fc6d56897b048c772eb4087f854f46256132" } ])
# tree.sha # => "cd8274d15fa3ae2ab983129fb037999f264ba9a7"
# tree.tree.first.path # => "file.rb"
def create_tree(repo, tree, options = {})
parameters = { tree: tree }
post "#{Repository.path repo}/git/trees", options.merge(parameters)
end
# Get a single blob, fetching its content and encoding
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param blob_sha [String] The SHA of the blob to fetch
# @return [Sawyer::Resource] A hash representing the fetched blob
# @see https://developer.github.com/v3/git/blobs/#get-a-blob
# @example Fetch a blob and inspect its contents
# blob = Octokit.blob("octocat/Hello-World", "827efc6d56897b048c772eb4087f854f46256132")
# blob.encoding # => "utf-8"
# blob.content # => "Foo bar baz"
# @example Fetch a base64-encoded blob and inspect its contents
# require "base64"
# blob = Octokit.blob("octocat/Hello-World", "827efc6d56897b048c772eb4087f854f46256132")
# blob.encoding # => "base64"
# blob.content # => "Rm9vIGJhciBiYXo="
# Base64.decode64(blob.content) # => "Foo bar baz"
def blob(repo, blob_sha, options = {})
get "#{Repository.path repo}/git/blobs/#{blob_sha}", options
end
# Create a blob
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param content [String] Content of the blob
# @param encoding [String] The content's encoding. <tt>utf-8</tt> and <tt>base64</tt> are accepted. If your data cannot be losslessly sent as a UTF-8 string, you can base64 encode it
# @return [String] The new blob's SHA, e.g. <tt>827efc6d56897b048c772eb4087f854f46256132</tt>
# @see https://developer.github.com/v3/git/blobs/#create-a-blob
# @example Create a blob containing <tt>foo bar baz</tt>
# Octokit.create_blob("octocat/Hello-World", "foo bar baz")
# @example Create a blob containing <tt>foo bar baz</tt>, encoded using base64
# require "base64"
# Octokit.create_blob("octocat/Hello-World", Base64.encode64("foo bar baz"), "base64")
def create_blob(repo, content, encoding = 'utf-8', options = {})
parameters = {
content: content,
encoding: encoding
}
blob = post "#{Repository.path repo}/git/blobs", options.merge(parameters)
blob.sha
end
# Get a tag
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param tag_sha [String] The SHA of the tag to fetch.
# @return [Sawyer::Resource] Hash representing the tag.
# @see https://developer.github.com/v3/git/tags/#get-a-tag
# @example Fetch a tag
# Octokit.tag('octokit/octokit.rb', '23aad20633f4d2981b1c7209a800db3014774e96')
def tag(repo, tag_sha, options = {})
get "#{Repository.path repo}/git/tags/#{tag_sha}", options
end
# Create a tag
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param tag [String] Tag string.
# @param message [String] Tag message.
# @param object_sha [String] SHA of the git object this is tagging.
# @param type [String] Type of the object we're tagging. Normally this is
# a `commit` but it can also be a `tree` or a `blob`.
# @param tagger_name [String] Name of the author of the tag.
# @param tagger_email [String] Email of the author of the tag.
# @param tagger_date [string] Timestamp of when this object was tagged.
# @return [Sawyer::Resource] Hash representing new tag.
# @see https://developer.github.com/v3/git/tags/#create-a-tag-object
# @example
# @client.create_tag(
# "octokit/octokit.rb",
# "v9000.0.0",
# "Version 9000\n",
# "f4cdf6eb734f32343ce3f27670c17b35f54fd82e",
# "commit",
# "Wynn Netherland",
# "wynn.netherland@gmail.com",
# "2012-06-03T17:03:11-07:00"
# )
def create_tag(repo, tag, message, object_sha, type, tagger_name, tagger_email, tagger_date, options = {})
options.merge!(
tag: tag,
message: message,
object: object_sha,
type: type,
tagger: {
name: tagger_name,
email: tagger_email,
date: tagger_date
}
)
post "#{Repository.path repo}/git/tags", options
end
end
end
end
@@ -0,0 +1,864 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Organizations API
#
# @see https://developer.github.com/v3/orgs/
module Organizations
# Get an organization
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Sawyer::Resource] Hash representing GitHub organization.
# @see https://developer.github.com/v3/orgs/#get-an-organization
# @example
# Octokit.organization('github')
# @example
# Octokit.org('github')
def organization(org, options = {})
get Organization.path(org), options
end
alias org organization
# Update an organization.
#
# Requires authenticated client with proper organization permissions.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param values [Hash] The updated organization attributes.
# @option values [String] :billing_email Billing email address. This address is not publicized.
# @option values [String] :company Company name.
# @option values [String] :email Publicly visible email address.
# @option values [String] :location Location of organization.
# @option values [String] :name GitHub username for organization.
# @option values [String] :default_repository_permission The default permission members have on organization repositories.
# @option values [Boolean] :members_can_create_repositories Set true to allow members to create repositories on the organization.
# @return [Sawyer::Resource] Hash representing GitHub organization.
# @see https://developer.github.com/v3/orgs/#edit-an-organization
# @example
# @client.update_organization('github', {
# :billing_email => 'support@github.com',
# :company => 'GitHub',
# :email => 'support@github.com',
# :location => 'San Francisco',
# :name => 'github'
# })
# @example
# @client.update_org('github', {:company => 'Unicorns, Inc.'})
def update_organization(org, values, options = {})
patch Organization.path(org), options.merge(values)
end
alias update_org update_organization
# Delete an organization.
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization login or ID.
# @return [Boolean] True if deletion successful, otherwise false.
# @see https://docs.github.com/rest/orgs/orgs#delete-an-organization
# @example
# @client.delete_organization("my-org")
# @example
# @client.delete_org("my-org")
def delete_organization(org)
boolean_from_response :delete, Organization.path(org)
end
alias delete_org delete_organization
# Get organizations for a user.
#
# Nonauthenticated calls to this method will return organizations that
# the user is a public member.
#
# Use an authenicated client to get both public and private organizations
# for a user.
#
# Calling this method on a `@client` will return that users organizations.
# Private organizations are included only if the `@client` is authenticated.
#
# @param user [Integer, String] GitHub user login or id of the user to get
# list of organizations.
# @return [Array<Sawyer::Resource>] Array of hashes representing organizations.
# @see https://developer.github.com/v3/orgs/#list-your-organizations
# @see https://developer.github.com/v3/orgs/#list-user-organizations
# @example
# Octokit.organizations('pengwynn')
# @example
# @client.organizations('pengwynn')
# @example
# Octokit.orgs('pengwynn')
# @example
# Octokit.list_organizations('pengwynn')
# @example
# Octokit.list_orgs('pengwynn')
# @example
# @client.organizations
def organizations(user = nil, options = {})
paginate "#{User.path user}/orgs", options
end
alias list_organizations organizations
alias list_orgs organizations
alias orgs organizations
# List all GitHub organizations
#
# This provides a list of every organization, in the order that they
# were created.
#
# @param options [Hash] Optional options.
# @option options [Integer] :since The integer ID of the last
# Organization that you’ve seen.
#
# @see https://developer.github.com/v3/orgs/#list-all-organizations
#
# @return [Array<Sawyer::Resource>] List of GitHub organizations.
def all_organizations(options = {})
paginate 'organizations', options
end
alias all_orgs all_organizations
# List organization repositories
#
# Public repositories are available without authentication. Private repos
# require authenticated organization member.
#
# @param org [String, Integer] Organization GitHub login or id for which
# to list repos.
# @option options [String] :type ('all') Filter by repository type.
# `all`, `public`, `member`, `sources`, `forks`, or `private`.
#
# @return [Array<Sawyer::Resource>] List of repositories
# @see https://developer.github.com/v3/repos/#list-organization-repositories
# @example
# Octokit.organization_repositories('github')
# @example
# Octokit.org_repositories('github')
# @example
# Octokit.org_repos('github')
# @example
# @client.org_repos('github', {:type => 'private'})
def organization_repositories(org, options = {})
paginate "#{Organization.path org}/repos", options
end
alias org_repositories organization_repositories
alias org_repos organization_repositories
# Get organization members
#
# Public members of the organization are returned by default. An
# authenticated client that is a member of the GitHub organization
# is required to get private members.
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Array<Sawyer::Resource>] Array of hashes representing users.
# @see https://developer.github.com/v3/orgs/members/#members-list
# @example
# Octokit.organization_members('github')
# @example
# Octokit.org_members('github')
def organization_members(org, options = {})
options = options.dup
path = 'public_' if options.delete(:public)
paginate "#{Organization.path org}/#{path}members", options
end
alias org_members organization_members
# Get organization public members
#
# Lists the public members of an organization
#
# @param org [String] Organization GitHub username.
# @return [Array<Sawyer::Resource>] Array of hashes representing users.
# @see https://developer.github.com/v3/orgs/members/#public-members-list
# @example
# Octokit.organization_public_members('github')
# @example
# Octokit.org_public_members('github')
def organization_public_members(org, options = {})
organization_members org, options.merge(public: true)
end
alias org_public_members organization_public_members
# Check if a user is a member of an organization.
#
# Use this to check if another user is a member of an organization that
# you are a member. If you are not in the organization you are checking,
# use .organization_public_member? instead.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param user [String] GitHub username of the user to check.
#
# @return [Boolean] Is a member?
#
# @see https://developer.github.com/v3/orgs/members/#check-membership
#
# @example Check if a user is in your organization
# @client.organization_member?('your_organization', 'pengwynn')
# => false
def organization_member?(org, user, options = {})
result = boolean_from_response(:get, "#{Organization.path org}/members/#{user}", options)
if !result && last_response && last_response.status == 302
boolean_from_response :get, last_response.headers['Location']
else
result
end
end
alias org_member? organization_member?
# Check if a user is a public member of an organization.
#
# If you are checking for membership of a user of an organization that
# you are in, use .organization_member? instead.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param user [String] GitHub username of the user to check.
#
# @return [Boolean] Is a public member?
#
# @see https://developer.github.com/v3/orgs/members/#check-public-membership
#
# @example Check if a user is a hubbernaut
# @client.organization_public_member?('github', 'pengwynn')
# => true
def organization_public_member?(org, user, options = {})
boolean_from_response :get, "#{Organization.path org}/public_members/#{user}", options
end
alias org_public_member? organization_public_member?
# List pending organization invitations
#
# Requires authenticated organization member.
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Array<Sawyer::Resource>] Array of hashes representing invitations.
# @see https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations
#
# @example
# @client.organization_invitations('github')
def organization_invitations(org, options = {})
get "#{Organization.path org}/invitations", options
end
alias org_invitations organization_invitations
# List outside collaborators for an organization
#
# Requires authenticated organization members.
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Array<Sawyer::Resource>] Array of hashes representing users.
# @see https://developer.github.com/v3/orgs/outside_collaborators/#list-outside-collaborators
#
# @example
# @client.outside_collaborators('github')
def outside_collaborators(org, options = {})
paginate "#{Organization.path org}/outside_collaborators", options
end
# Remove outside collaborator from an organization
#
# Requires authenticated organization members.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param user [String] GitHub username to be removed as outside collaborator
# @return [Boolean] Return true if outside collaborator removed from organization, false otherwise.
# @see https://developer.github.com/v3/orgs/outside-collaborators/#remove-outside-collaborator
#
# @example
# @client.remove_outside_collaborator('github', 'lizzhale')
def remove_outside_collaborator(org, user, options = {})
boolean_from_response :delete, "#{Organization.path org}/outside_collaborators/#{user}", options
end
# Converts an organization member to an outside collaborator
#
# Requires authenticated organization members.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param user [String] GitHub username to be removed as outside collaborator
# @return [Boolean] Return true if outside collaborator removed from organization, false otherwise.
# @see https://developer.github.com/v3/orgs/outside-collaborators/#convert-member-to-outside-collaborator
#
# @example
# @client.convert_to_outside_collaborator('github', 'lizzhale')
def convert_to_outside_collaborator(org, user, options = {})
boolean_from_response :put, "#{Organization.path org}/outside_collaborators/#{user}", options
end
# List teams
#
# Requires authenticated organization member.
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Array<Sawyer::Resource>] Array of hashes representing teams.
# @see https://developer.github.com/v3/orgs/teams/#list-teams
# @example
# @client.organization_teams('github')
# @example
# @client.org_teams('github')
def organization_teams(org, options = {})
paginate "#{Organization.path org}/teams", options
end
alias org_teams organization_teams
# Create team
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @option options [String] :name Team name.
# @option options [Array<String>] :repo_names Repositories for the team.
# @option options [Array<String>] :maintainers Maintainers for the team.
# @option options [Integer] :parent_team_id ID of a team to set as the parent team.
# @return [Sawyer::Resource] Hash representing new team.
# @see https://developer.github.com/v3/orgs/teams/#create-team
# @example
# @client.create_team('github', {
# :name => 'Designers',
# :repo_names => ['github/dotfiles']
# })
def create_team(org, options = {})
if options.key?(:permission)
octokit_warn 'Deprecated: Passing :permission option to #create_team. Assign team repository permission by passing :permission to #add_team_repository instead.'
end
post "#{Organization.path org}/teams", options
end
# Get team
#
# Requires authenticated organization member.
#
# @param team_id [Integer] Team id.
# @return [Sawyer::Resource] Hash representing team.
# @see https://developer.github.com/v3/orgs/teams/#get-team
# @example
# @client.team(100000)
def team(team_id, options = {})
get "teams/#{team_id}", options
end
# Get team by name and org
#
# Requires authenticated organization member.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param team_slug [String] Team slug.
# @return [Sawyer::Resource] Hash representing team.
# @see https://developer.github.com/v3/teams/#get-team-by-name
# @example
# @client.team_by_name("github", "justice-league")
def team_by_name(org, team_slug, options = {})
get "#{Organization.path(org)}/teams/#{team_slug}", options
end
# Check team permissions for a repository
#
# Requires authenticated organization member.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param team_slug_or_id [String, Integer] Team slug or Team ID.
# @param owner [String] Owner name for the repository.
# @param repo [String] Name of the repo to check permissions against.
# @return [String, Sawyer::Resource] Depending on options it may be an empty string or a resource.
# @example
# # Check whether the team has any permissions with the repository
# @client.team_permissions_for_repo("github", "justice-league", "octocat", "hello-world")
#
# @example
# # Get the full repository object including the permissions level and role for the team
# @client.team_permissions_for_repo("github", "justice-league", "octocat", "hello-world", :accept => 'application/vnd.github.v3.repository+json')
# @see https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-repository
def team_permissions_for_repo(org, team_slug_or_id, owner, repo, options = {})
get "#{Organization.path(org)}/teams/#{team_slug_or_id}/repos/#{owner}/#{repo}", options
end
# List child teams
#
# Requires authenticated organization member.
#
# @param team_id [Integer] Team id.
# @return [Sawyer::Resource] Hash representing team.
# @see https://developer.github.com/v3/orgs/teams/#list-child-teams
# @example
# @client.child_teams(100000, :accept => "application/vnd.github.hellcat-preview+json")
def child_teams(team_id, options = {})
paginate "teams/#{team_id}/teams", options
end
# Update team
#
# Requires authenticated organization owner.
#
# @param team_id [Integer] Team id.
# @option options [String] :name Team name.
# @option options [String] :permission Permissions the team has for team repositories.
#
# `pull` - team members can pull, but not push to or administer these repositories.
# `push` - team members can pull and push, but not administer these repositories.
# `admin` - team members can pull, push and administer these repositories.
# @option options [Integer] :parent_team_id ID of a team to set as the parent team.
# @return [Sawyer::Resource] Hash representing updated team.
# @see https://developer.github.com/v3/orgs/teams/#edit-team
# @example
# @client.update_team(100000, {
# :name => 'Front-end Designers',
# :permission => 'push'
# })
def update_team(team_id, options = {})
patch "teams/#{team_id}", options
end
# Delete team
#
# Requires authenticated organization owner.
#
# @param team_id [Integer] Team id.
# @return [Boolean] True if deletion successful, false otherwise.
# @see https://developer.github.com/v3/orgs/teams/#delete-team
# @example
# @client.delete_team(100000)
def delete_team(team_id, options = {})
boolean_from_response :delete, "teams/#{team_id}", options
end
# List team members
#
# Requires authenticated organization member.
#
# @param team_id [Integer] Team id.
# @return [Array<Sawyer::Resource>] Array of hashes representing users.
# @see https://developer.github.com/v3/orgs/teams/#list-team-members
# @example
# @client.team_members(100000)
def team_members(team_id, options = {})
paginate "teams/#{team_id}/members", options
end
# Add team member
#
# Requires authenticated organization owner or member with team
# `admin` permission.
#
# @param team_id [Integer] Team id.
# @param user [String] GitHub username of new team member.
# @return [Boolean] True on successful addition, false otherwise.
# @see https://developer.github.com/v3/orgs/teams/#add-team-member
# @example
# @client.add_team_member(100000, 'pengwynn')
#
# @example
# # Opt-in to future behavior for this endpoint. Adds the member to the
# # team if they're already an org member. If not, the method will return
# # 422 and indicate the user should call the new Team Membership endpoint.
# @client.add_team_member \
# 100000,
# 'pengwynn',
# :accept => "application/vnd.github.the-wasp-preview+json"
# @see https://developer.github.com/changes/2014-08-05-team-memberships-api/
def add_team_member(team_id, user, options = {})
# There's a bug in this API call. The docs say to leave the body blank,
# but it fails if the body is both blank and the content-length header
# is not 0.
boolean_from_response :put, "teams/#{team_id}/members/#{user}", options.merge({ name: user })
end
# Remove team member
#
# Requires authenticated organization owner or member with team
# `admin` permission.
#
# @param team_id [Integer] Team id.
# @param user [String] GitHub username of the user to boot.
# @return [Boolean] True if user removed, false otherwise.
# @see https://developer.github.com/v3/orgs/teams/#remove-team-member
# @example
# @client.remove_team_member(100000, 'pengwynn')
def remove_team_member(team_id, user, options = {})
boolean_from_response :delete, "teams/#{team_id}/members/#{user}", options
end
# Check if a user is a member of a team.
#
# Use this to check if another user is a member of a team that
# you are a member.
#
# @param team_id [Integer] Team id.
# @param user [String] GitHub username of the user to check.
#
# @return [Boolean] Is a member?
#
# @see https://developer.github.com/v3/orgs/teams/#get-team-member
#
# @example Check if a user is in your team
# @client.team_member?(100000, 'pengwynn')
# => false
def team_member?(team_id, user, options = {})
boolean_from_response :get, "teams/#{team_id}/members/#{user}", options
end
# List pending team invitations
#
# Requires authenticated organization member.
#
# @param team_id [Integer] Team id.
# @return [Array<Sawyer::Resource>] Array of hashes representing invitations.
# @see https://developer.github.com/v3/orgs/teams/#list-pending-team-invitations
#
# @example
# @client.team_invitations('github')
def team_invitations(team_id, options = {})
get "teams/#{team_id}/invitations", options
end
# List team repositories
#
# Requires authenticated organization member.
#
# @param team_id [Integer] Team id.
# @return [Array<Sawyer::Resource>] Array of hashes representing repositories.
# @see https://developer.github.com/v3/orgs/teams/#list-team-repos
# @example
# @client.team_repositories(100000)
# @example
# @client.team_repos(100000)
def team_repositories(team_id, options = {})
paginate "teams/#{team_id}/repos", options
end
alias team_repos team_repositories
# Check if a repo is managed by a specific team
#
# @param team_id [Integer] Team ID.
# @param repo [String, Hash, Repository] A GitHub repository.
# @return [Boolean] True if managed by a team. False if not managed by
# the team OR the requesting user does not have authorization to access
# the team information.
# @see https://developer.github.com/v3/orgs/teams/#check-if-a-team-manages-a-repository
# @example
# @client.team_repository?(8675309, 'octokit/octokit.rb')
# @example
# @client.team_repo?(8675309, 'octokit/octokit.rb')
def team_repository?(team_id, repo, _options = {})
boolean_from_response :get, "teams/#{team_id}/repos/#{Repository.new(repo)}"
end
alias team_repo? team_repository?
# Add team repository
#
# This can also be used to update the permission of an existing team
#
# Requires authenticated user to be an owner of the organization that the
# team is associated with. Also, the repo must be owned by the
# organization, or a direct form of a repo owned by the organization.
#
# @param team_id [Integer] Team id.
# @param repo [String, Hash, Repository] A GitHub repository.
# @option options [String] :permission The permission to grant the team.
# Only valid on organization-owned repositories.
# Can be one of: <tt>pull</tt>, <tt>push</tt>, or <tt>admin</tt>.
# If not specified, the team's <tt>permission</tt> attribute will be
# used to determine what permission to grant the team on this repository.
# @return [Boolean] True if successful, false otherwise.
# @see Octokit::Repository
# @see https://developer.github.com/v3/orgs/teams/#add-or-update-team-repository
# @example
# @client.add_team_repository(100000, 'github/developer.github.com')
# @example
# @client.add_team_repo(100000, 'github/developer.github.com')
# @example Add a team with admin permissions
# @client.add_team_repository(100000, 'github/developer.github.com', permission: 'admin')
def add_team_repository(team_id, repo, options = {})
boolean_from_response :put, "teams/#{team_id}/repos/#{Repository.new(repo)}", options
end
alias add_team_repo add_team_repository
# Remove team repository
#
# Removes repository from team. Does not delete the repository.
#
# Requires authenticated organization owner.
#
# @param team_id [Integer] Team id.
# @param repo [String, Hash, Repository] A GitHub repository.
# @return [Boolean] Return true if repo removed from team, false otherwise.
# @see Octokit::Repository
# @see https://developer.github.com/v3/orgs/teams/#remove-team-repository
# @example
# @client.remove_team_repository(100000, 'github/developer.github.com')
# @example
# @client.remove_team_repo(100000, 'github/developer.github.com')
def remove_team_repository(team_id, repo, _options = {})
boolean_from_response :delete, "teams/#{team_id}/repos/#{Repository.new(repo)}"
end
alias remove_team_repo remove_team_repository
# Remove organization member
#
# Requires authenticated organization owner or member with team `admin` access.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param user [String] GitHub username of user to remove.
# @return [Boolean] True if removal is successful, false otherwise.
# @see https://developer.github.com/v3/orgs/members/#remove-a-member
# @example
# @client.remove_organization_member('github', 'pengwynn')
# @example
# @client.remove_org_member('github', 'pengwynn')
def remove_organization_member(org, user, options = {})
# this is a synonym for: for team in org.teams: remove_team_member(team.id, user)
# provided in the GH API v3
boolean_from_response :delete, "#{Organization.path org}/members/#{user}", options
end
alias remove_org_member remove_organization_member
# Publicize a user's membership of an organization
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param user [String] GitHub username of user to publicize.
# @return [Boolean] True if publicization successful, false otherwise.
# @see https://developer.github.com/v3/orgs/members/#publicize-a-users-membership
# @example
# @client.publicize_membership('github', 'pengwynn')
def publicize_membership(org, user, options = {})
boolean_from_response :put, "#{Organization.path org}/public_members/#{user}", options
end
# Conceal a user's membership of an organization.
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param user [String] GitHub username of user to unpublicize.
# @return [Boolean] True of unpublicization successful, false otherwise.
# @see https://developer.github.com/v3/orgs/members/#conceal-a-users-membership
# @example
# @client.unpublicize_membership('github', 'pengwynn')
# @example
# @client.conceal_membership('github', 'pengwynn')
def unpublicize_membership(org, user, options = {})
boolean_from_response :delete, "#{Organization.path org}/public_members/#{user}", options
end
alias conceal_membership unpublicize_membership
# List all teams for the authenticated user across all their orgs
#
# @return [Array<Sawyer::Resource>] Array of team resources.
# @see https://developer.github.com/v3/orgs/teams/#list-user-teams
def user_teams(options = {})
paginate 'user/teams', options
end
# Check if a user has a team membership.
#
# @param team_id [Integer] Team id.
# @param user [String] GitHub username of the user to check.
#
# @return [Sawyer::Resource] Hash of team membership info
#
# @see https://developer.github.com/v3/orgs/teams/#get-team-membership
#
# @example Check if a user has a membership for a team
# @client.team_membership(1234, 'pengwynn')
def team_membership(team_id, user, options = {})
get "teams/#{team_id}/memberships/#{user}", options
end
# Add or invite a user to a team
#
# @param team_id [Integer] Team id.
# @param user [String] GitHub username of the user to invite.
#
# @return [Sawyer::Resource] Hash of team membership info
#
# @see https://developer.github.com/v3/orgs/teams/#add-or-update-team-membership
#
# @example Check if a user has a membership for a team
# @client.add_team_membership(1234, 'pengwynn')
def add_team_membership(team_id, user, options = {})
put "teams/#{team_id}/memberships/#{user}", options
end
# Remove team membership
#
# @param team_id [Integer] Team id.
# @param user [String] GitHub username of the user to boot.
# @return [Boolean] True if user removed, false otherwise.
# @see https://developer.github.com/v3/orgs/teams/#remove-team-membership
# @example
# @client.remove_team_membership(100000, 'pengwynn')
def remove_team_membership(team_id, user, options = {})
boolean_from_response :delete, "teams/#{team_id}/memberships/#{user}", options
end
# List all organizations memberships for the authenticated user
#
# @return [Array<Sawyer::Resource>] Array of organizations memberships.
# @see https://developer.github.com/v3/orgs/members/#list-your-organization-memberships
def organization_memberships(options = {})
paginate 'user/memberships/orgs', options
end
alias org_memberships organization_memberships
# Get an organization membership
#
# @param org [Integer, String] The GitHub Organization.
# @option options [String] :user The login of the user, otherwise authenticated user.
# @return [Sawyer::Resource] Hash representing the organization membership.
# @see https://developer.github.com/v3/orgs/members/#get-your-organization-membership
# @see https://developer.github.com/v3/orgs/members/#get-organization-membership
def organization_membership(org, options = {})
options = options.dup
if user = options.delete(:user)
get "#{Organization.path(org)}/memberships/#{user}", options
else
get "user/memberships/orgs/#{org}", options
end
end
alias org_membership organization_membership
# Edit an organization membership
#
# @param org [String, Integer] Organization GitHub login or id.
# @option options [String] :role The role of the user in the organization.
# @option options [String] :state The state that the membership should be in.
# @option options [String] :user The login of the user, otherwise authenticated user.
# @return [Sawyer::Resource] Hash representing the updated organization membership.
# @see https://developer.github.com/v3/orgs/members/#edit-your-organization-membership
# @see https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership
def update_organization_membership(org, options = {})
options = options.dup
if user = options.delete(:user)
options.delete(:state)
put "#{Organization.path(org)}/memberships/#{user}", options
else
options.delete(:role)
patch "user/memberships/orgs/#{org}", options
end
end
alias update_org_membership update_organization_membership
# Remove an organization membership
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Boolean] Success
# @see https://developer.github.com/v3/orgs/members/#remove-organization-membership
def remove_organization_membership(org, options = {})
options = options.dup
user = options.delete(:user)
user && boolean_from_response(:delete, "#{Organization.path(org)}/memberships/#{user}", options)
end
alias remove_org_membership remove_organization_membership
# Initiates the generation of a migration archive.
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param repositories [Array<String>] :repositories Repositories for the organization.
# @option options [Boolean, optional] :lock_repositories Indicates whether repositories should be locked during migration
# @return [Sawyer::Resource] Hash representing the new migration.
# @example
# @client.start_migration('github', ['github/dotfiles'])
# @see https://docs.github.com/en/rest/reference/migrations#start-an-organization-migration
def start_migration(org, repositories, options = {})
options[:repositories] = repositories
post "#{Organization.path(org)}/migrations", options
end
# Lists the most recent migrations.
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Array<Sawyer::Resource>] Array of migration resources.
# @see https://docs.github.com/en/rest/reference/migrations#list-organization-migrations
def migrations(org, options = {})
paginate "#{Organization.path(org)}/migrations", options
end
# Fetches the status of a migration.
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param id [Integer] ID number of the migration.
# @see https://docs.github.com/en/rest/reference/migrations#get-an-organization-migration-status
def migration_status(org, id, options = {})
get "#{Organization.path(org)}/migrations/#{id}", options
end
# Fetches the URL to a migration archive.
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param id [Integer] ID number of the migration.
# @see https://docs.github.com/en/rest/reference/migrations#download-an-organization-migration-archive
def migration_archive_url(org, id, options = {})
url = "#{Organization.path(org)}/migrations/#{id}/archive"
response = client_without_redirects(options).get(url)
response.headers['location']
end
# Deletes a previous migration archive.
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param id [Integer] ID number of the migration.
# @see https://docs.github.com/en/rest/reference/migrations#delete-an-organization-migration-archive
def delete_migration_archive(org, id, options = {})
delete "#{Organization.path(org)}/migrations/#{id}/archive", options
end
# Unlock a previous migration archive.
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @param id [Integer] ID number of the migration.
# @param repo [String] Name of the repository.
# @see https://docs.github.com/en/rest/reference/migrations#unlock-an-organization-repository
def unlock_repository(org, id, repo, options = {})
delete "#{Organization.path(org)}/migrations/#{id}/repos/#{repo}/lock", options
end
# Get GitHub Actions billing for an organization
#
# Requires authenticated organization owner.
#
# @param org [String, Integer] Organization GitHub login or id.
# @return [Sawyer::Resource] Hash representing GitHub Actions billing for an organization.
# @see https://docs.github.com/en/rest/reference/billing#get-github-actions-billing-for-an-organization
#
# @example
# @client.billing_actions('github')
def billing_actions(org)
get "#{Organization.path(org)}/settings/billing/actions"
end
# Get organization audit log.
#
# Gets the audit log for an organization.
#
# @param org [String, Integer] Organization GitHub login or id for which
# to retrieve the audit log.
# @option options [String] :include ('all') Filter by event type.
# `all`, `git` or `web`.
# @option options [String] :phrase A search phrase.
# @option options [String] :order ('desc') The order of audit log events. To list newest events first, specify desc.
# To list oldest events first, specify asc.
#
# @return [Array<Sawyer::Resource>] List of events
# @see https://docs.github.com/en/enterprise-cloud@latest/rest/orgs/orgs#get-the-audit-log-for-an-organization
# @example
# Octokit.organization_audit_log('github', {include: 'all', phrase: 'action:org.add_member created:>2022-08-29 user:octocat'})
def organization_audit_log(org, options = {})
paginate "#{Organization.path org}/audit-log", options
end
end
end
end
@@ -0,0 +1,61 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Pages API
#
# @see https://developer.github.com/v3/repos/pages/
module Pages
# List Pages information for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return Sawyer::Resource A GitHub Pages resource
# @see https://developer.github.com/v3/repos/pages/#get-information-about-a-pages-site
def pages(repo, options = {})
get "#{Repository.path repo}/pages", options
end
# Get a specific Pages build by ID
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param id [Integer, String] Build ID
# @return [Sawyer::Resource] Pages build information
# @see https://developer.github.com/v3/repos/pages/#list-a-specific-pages-build
# @example
# Octokit.pages_build("github/developer.github.com", 5472601)
def pages_build(repo, id, options = {})
get "#{Repository.path repo}/pages/builds/#{id}", options
end
# List Pages builds for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] A list of build history for a repository.
# @see https://developer.github.com/v3/repos/pages/#list-pages-builds
def pages_builds(repo, options = {})
get "#{Repository.path repo}/pages/builds", options
end
alias list_pages_builds pages_builds
# List the latest Pages build information for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return Sawyer::Resource A GitHub Pages resource about a build
# @see https://developer.github.com/v3/repos/pages/#list-latest-pages-build
def latest_pages_build(repo, options = {})
get "#{Repository.path repo}/pages/builds/latest", options
end
# Request a page build for the latest revision of the default branch
#
# You can only request builds for your repositories
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Sawyer::Resource] Request result
# @see https://developer.github.com/v3/repos/pages/#request-a-page-build
def request_page_build(repo, options = {})
post "#{Repository.path repo}/pages/builds", options
end
end
end
end
@@ -0,0 +1,294 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for Projects API
#
# @see https://docs.github.com/en/rest/projects
module Projects
# List projects for a repository
#
# Requires authenticated client
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] Repository projects
# @see https://developer.github.com/v3/projects/#list-repository-projects
# @example
# @client.projects('octokit/octokit.rb')
def projects(repo, options = {})
paginate "#{Repository.path repo}/projects", options
end
# Create a project
#
# Requires authenticated client
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param name [String] Project name
# @option options [String] :body Body of the project
# @return [Sawyer::Resource] Fresh new project
# @see https://developer.github.com/v3/projects/#create-a-repository-project
# @example Create project with only a name
# @client.create_project('octokit/octokit.rb', 'implement new APIs')
#
# @example Create project with name and body
# @client.create_project('octokit/octokit.rb', 'bugs be gone', body: 'Fix all the bugs @joeyw creates')
def create_project(repo, name, options = {})
options[:name] = name
post "#{Repository.path repo}/projects", options
end
# List organization projects
#
# Requires authenticated client
#
# @param org [String] A GitHub organization
# @return [Array<Sawyer::Resource>] Organization projects
# @see https://developer.github.com/v3/projects/#list-organization-projects
# @example
# @client.org_projects("octokit")
def org_projects(org, options = {})
paginate "orgs/#{org}/projects", options
end
alias organization_projects org_projects
# Create organization project
#
# Requires authenticated client
#
# @param org [String] A GitHub organization
# @param name [String] Project name
# @option options [String] :body Project body
# @return [Sawyer::Resource] Organization project
# @see https://developer.github.com/v3/projects/#create-an-organization-project
# @example Create with only a name
# @client.create_org_project("octocat", "make more octocats")
# @example Create a project with name and body
# @client.create_org_project("octokit", "octocan", body: 'Improve clients')
def create_org_project(org, name, options = {})
options[:name] = name
post "orgs/#{org}/projects", options
end
alias create_organization_project create_org_project
# Get a project by id
#
# @param id [Integer] Project id
# @return [Sawyer::Resource] Project
# @see https://developer.github.com/v3/projects/#get-a-project
# @example
# Octokit.project(123942)
def project(id, options = {})
get "projects/#{id}", options
end
# Update a project
#
# Requires authenticated client
#
# @param id [Integer] Project id
# @option options [String] :name Project name
# @option options [String] :body Project body
# @return [Sawyer::Resource] Project
# @see https://developer.github.com/v3/projects/#update-a-project
# @example Update project name
# @client.update_project(123942, name: 'New name')
def update_project(id, options = {})
patch "projects/#{id}", options
end
# Delete a project
#
# Requires authenticated client
#
# @param id [Integer] Project id
# @return [Boolean] Result of deletion
# @see https://developer.github.com/v3/projects/#delete-a-project
# @example
# @client.delete_project(123942)
def delete_project(id, options = {})
boolean_from_response :delete, "projects/#{id}", options
end
# List project columns
#
# @param id [Integer] Project id
# @return [Array<Sawyer::Resource>] List of project columns
# @see https://developer.github.com/v3/projects/columns/#list-project-columns
# @example
# @client.project_columns(123942)
def project_columns(id, options = {})
paginate "projects/#{id}/columns", options
end
# Create a project column
#
# Requires authenticated client
#
# @param id [Integer] Project column id
# @param name [String] New column name
# @return [Sawyer::Resource] Newly created column
# @see https://developer.github.com/v3/projects/columns/#create-a-project-column
# @example
# @client.create_project_column(123942, "To Dones")
def create_project_column(id, name, options = {})
options[:name] = name
post "projects/#{id}/columns", options
end
# Get a project column by ID
#
# @param id [Integer] Project column id
# @return [Sawyer::Resource] Project column
# @see https://developer.github.com/v3/projects/columns/#get-a-project-column
# @example
# Octokit.project_column(30294)
def project_column(id, options = {})
get "projects/columns/#{id}", options
end
# Update a project column
#
# Requires authenticated client
#
# @param id [Integer] Project column id
# @param name [String] New column name
# @return [Sawyer::Resource] Updated column
# @see https://developer.github.com/v3/projects/columns/#update-a-project-column
# @example
# @client.update_project_column(30294, "new column name")
def update_project_column(id, name, options = {})
options[:name] = name
patch "projects/columns/#{id}", options
end
# Delete a project column
#
# Requires authenticated client
#
# @param id [Integer] Project column id
# @return [Boolean] Result of deletion request, true when deleted
# @see https://developer.github.com/v3/projects/columns/#delete-a-project-column
# @example
# @client.delete_project_column(30294)
def delete_project_column(id, options = {})
boolean_from_response :delete, "projects/columns/#{id}", options
end
# Move a project column
#
# Requires authenticated client
#
# @param id [Integer] Project column id
# @param position [String] New position for the column. Can be one of
# <tt>first</tt>, <tt>last</tt>, or <tt>after:<column-id></tt>, where
# <tt><column-id></tt> is the id value of a column in the same project.
# @return [Sawyer::Resource] Result
# @see https://developer.github.com/v3/projects/columns/#move-a-project-column
# @example
# @client.move_project_column(30294, "last")
def move_project_column(id, position, options = {})
options[:position] = position
post "projects/columns/#{id}/moves", options
end
# List columns cards
#
# Requires authenticated client
#
# @param id [Integer] Project column id
# @return [Array<Sawyer::Resource>] Cards in the column
# @see https://developer.github.com/v3/projects/cards/#list-project-cards
# @example
# @client.column_cards(30294)
def column_cards(id, options = {})
paginate "projects/columns/#{id}/cards", options
end
# Create project card
#
# Requires authenticated client
#
# @param id [Integer] Project column id
# @option options [String] :note Card contents for a note type
# @option options [Integer] :content_id Issue ID for the card contents
# @option options [String] :content_type Type of content to associate
# with the card. <tt>Issue</tt> is presently the only avaiable value
# @note If :note is supplied, :content_id and :content_type must be
# excluded. Similarly, if :content_id is supplied, :content_type must
# be set and :note must not be included.
# @return [Sawyer::Resource] Newly created card
# @see https://developer.github.com/v3/projects/cards/#create-a-project-card
# @example Create a project card with a note
# @client.create_project_card(123495, note: 'New note card')
# @example Create a project card for an repository issue
# @client.create_project_card(123495, content_id: 1, content_type: 'Issue')
def create_project_card(id, options = {})
post "projects/columns/#{id}/cards", options
end
# Get a project card
#
# Requires authenticated client
#
# @param id [Integer] Project card id
# @return [Sawyer::Resource] Project card
# @see https://developer.github.com/v3/projects/cards/#get-a-project-card
# @example
# @client.project_card(123495)
def project_card(id, options = {})
get "projects/columns/cards/#{id}", options
end
# Update a project card
#
# Requires authenticated client
#
# @param id [Integer] Project card id
# @option options [String] :note The card's note content. Only valid for
# cards without another type of content, so this cannot be specified if
# the card already has a content_id and content_type.
# @return [Sawyer::Resource] Updated project card
# @see https://developer.github.com/v3/projects/cards/#update-a-project-card
# @example
# @client.update_project_card(12345, note: 'new note')
def update_project_card(id, options = {})
patch "projects/columns/cards/#{id}", options
end
# Move a project card
#
# Requires authenticated client
#
# @param id [Integer] Project card id
# @param position [String] Can be one of <tt>top</tt>, <tt>bottom</tt>,
# or <tt>after:<card-id></tt>, where <card-id> is the id value of a
# card in the same column, or in the new column specified by column_id.
# @option options [Integer] :column_id The column id to move the card to,
# must be column in same project
# @return [Sawyer::Resource] Empty sawyer resource
# @see https://developer.github.com/v3/projects/cards/#move-a-project-card
# @example Move a card to the bottom of the same column
# @client.move_project_card(123495, 'bottom')
# @example Move a card to the top of another column
# @client.move_project_card(123495, 'top', column_id: 59402)
def move_project_card(id, position, options = {})
options[:position] = position
post "projects/columns/cards/#{id}/moves", options
end
# Delete a project card
#
# Requires authenticated client
#
# @param id [Integer] Project card id
# @return [Boolean] True of deleted, false otherwise
# @see https://developer.github.com/v3/projects/cards/#delete-a-project-card
# @example
# @client.delete_project_card(123495)
def delete_project_card(id, options = {})
boolean_from_response :delete, "projects/columns/cards/#{id}", options
end
end # Projects
end
end
@@ -0,0 +1,111 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the PubSubHubbub API
#
# @see https://developer.github.com/v3/repos/hooks/#pubsubhubbub
module PubSubHubbub
# Subscribe to a pubsub topic
#
# @param topic [String] A recoginized and supported pubsub topic
# @param callback [String] A callback url to be posted to when the topic event is fired
# @param secret [String] An optional shared secret used to generate a SHA1 HMAC of the outgoing body content
# @return [Boolean] true if the subscribe was successful, otherwise an error is raised
# @see https://developer.github.com/v3/repos/hooks/#subscribing
# @example Subscribe to push events from one of your repositories, having an email sent when fired
# client = Octokit::Client.new(:oauth_token = "token")
# client.subscribe("https://github.com/joshk/devise_imapable/events/push", "github://Email?address=josh.kalderimis@gmail.com")
def subscribe(topic, callback, secret = nil)
options = {
'hub.callback': callback,
'hub.mode': 'subscribe',
'hub.topic': topic
}
options.merge!('hub.secret': secret) unless secret.nil?
response = pub_sub_hubbub_request(options)
response.status == 204
end
# Unsubscribe from a pubsub topic
#
# @param topic [String] A recoginized pubsub topic
# @param callback [String] A callback url to be unsubscribed from
# @return [Boolean] true if the unsubscribe was successful, otherwise an error is raised
# @see https://developer.github.com/v3/repos/hooks/#subscribing
# @example Unsubscribe to push events from one of your repositories, no longer having an email sent when fired
# client = Octokit::Client.new(:oauth_token = "token")
# client.unsubscribe("https://github.com/joshk/devise_imapable/events/push", "github://Email?address=josh.kalderimis@gmail.com")
def unsubscribe(topic, callback)
options = {
'hub.callback': callback,
'hub.mode': 'unsubscribe',
'hub.topic': topic
}
response = pub_sub_hubbub_request(options)
response.status == 204
end
# Subscribe to a repository through pubsub
#
# @param repo [String, Repository, Hash] A GitHub repository
# @param service_name [String] service name owner
# @param service_arguments [Hash] params that will be passed by subscribed hook.
# List of services is available @ https://github.com/github/github-services/tree/master/docs.
# Please refer Data node for complete list of arguments.
# @param secret [String] An optional shared secret used to generate a SHA1 HMAC of the outgoing body content
# @return [Boolean] True if subscription successful, false otherwise
# @see https://developer.github.com/v3/repos/hooks/#subscribing
# @example Subscribe to push events to one of your repositories to Travis-CI
# client = Octokit::Client.new(:oauth_token = "token")
# client.subscribe_service_hook('joshk/device_imapable', 'Travis', { :token => "test", :domain => "domain", :user => "user" })
def subscribe_service_hook(repo, service_name, service_arguments = {}, secret = nil)
topic = "#{Octokit.web_endpoint}#{Repository.new(repo)}/events/push"
callback = "github://#{service_name}?#{service_arguments.collect { |k, v| [k, v].map { |p| URI.encode_www_form_component(p) }.join('=') }.join('&')}"
subscribe(topic, callback, secret)
end
# Unsubscribe repository through pubsub
#
# @param repo [String, Repository, Hash] A GitHub repository
# @param service_name [String] service name owner
# List of services is available @ https://github.com/github/github-services/tree/master/docs.
# @see https://developer.github.com/v3/repos/hooks/#subscribing
# @example Subscribe to push events to one of your repositories to Travis-CI
# client = Octokit::Client.new(:oauth_token = "token")
# client.unsubscribe_service_hook('joshk/device_imapable', 'Travis')
def unsubscribe_service_hook(repo, service_name)
topic = "#{Octokit.web_endpoint}#{Repository.new(repo)}/events/push"
callback = "github://#{service_name}"
unsubscribe(topic, callback)
end
private
def pub_sub_hubbub_request(options = {})
# This method is janky, bypass normal stack so we don't
# serialize request as JSON
conn = Faraday.new(url: @api_endpoint) do |http|
http.headers[:user_agent] = user_agent
if basic_authenticated?
http.request(*FARADAY_BASIC_AUTH_KEYS, @login, @password)
elsif token_authenticated?
http.request :authorization, 'token', @access_token
end
http.request :url_encoded
http.use Octokit::Response::RaiseError
http.adapter Faraday.default_adapter
end
conn.post do |req|
req.url 'hub'
req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
req.body = options
end
end
end
end
end
@@ -0,0 +1,313 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Pull Requests API
#
# @see https://developer.github.com/v3/pulls/
module PullRequests
# List pull requests for a repository
#
# @overload pull_requests(repo, options)
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param options [Hash] Method options
# @option options [String] :state `open` or `closed` or `all`.
# @return [Array<Sawyer::Resource>] Array of pulls
# @see https://developer.github.com/v3/pulls/#list-pull-requests
# @example
# Octokit.pull_requests('rails/rails', :state => 'closed')
def pull_requests(repo, options = {})
paginate "#{Repository.path repo}/pulls", options
end
alias pulls pull_requests
# Get a pull request
#
# @see https://developer.github.com/v3/pulls/#get-a-single-pull-request
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number of the pull request to fetch
# @return [Sawyer::Resource] Pull request info
# @example
# Octokit.pull_request('rails/rails', 42, :state => 'closed')
def pull_request(repo, number, options = {})
get "#{Repository.path repo}/pulls/#{number}", options
end
alias pull pull_request
# Create a pull request
#
# @see https://developer.github.com/v3/pulls/#create-a-pull-request
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param base [String] The branch (or git ref) you want your changes
# pulled into. This should be an existing branch on the current
# repository. You cannot submit a pull request to one repo that requests
# a merge to a base of another repo.
# @param head [String] The branch (or git ref) where your changes are implemented.
# @param title [String] Title for the pull request
# @param body [String] The body for the pull request (optional). Supports GFM.
# @return [Sawyer::Resource] The newly created pull request
# @example
# @client.create_pull_request("octokit/octokit.rb", "master", "feature-branch",
# "Pull Request title", "Pull Request body")
def create_pull_request(repo, base, head, title, body = nil, options = {})
pull = {
base: base,
head: head,
title: title
}
pull[:body] = body unless body.nil?
post "#{Repository.path repo}/pulls", options.merge(pull)
end
# Create a pull request from existing issue
#
# @see https://developer.github.com/v3/pulls/#alternative-input
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param base [String] The branch (or git ref) you want your changes
# pulled into. This should be an existing branch on the current
# repository. You cannot submit a pull request to one repo that requests
# a merge to a base of another repo.
# @param head [String] The branch (or git ref) where your changes are implemented.
# @param issue [Integer] Number of Issue on which to base this pull request
# @return [Sawyer::Resource] The newly created pull request
def create_pull_request_for_issue(repo, base, head, issue, options = {})
pull = {
base: base,
head: head,
issue: issue
}
post "#{Repository.path repo}/pulls", options.merge(pull)
end
# Update a pull request
# @overload update_pull_request(repo, number, title=nil, body=nil, state=nil, options = {})
# @deprecated
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param number [Integer] Number of pull request to update.
# @param title [String] Title for the pull request.
# @param body [String] Body content for pull request. Supports GFM.
# @param state [String] State of the pull request. `open` or `closed`.
# @overload update_pull_request(repo, number, options = {})
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param number [Integer] Number of pull request to update.
# @option options [String] :title Title for the pull request.
# @option options [String] :body Body for the pull request.
# @option options [String] :state State for the pull request.
# @return [Sawyer::Resource] Hash representing updated pull request.
# @see https://developer.github.com/v3/pulls/#update-a-pull-request
# @example
# @client.update_pull_request('octokit/octokit.rb', 67, 'new title', 'updated body', 'closed')
# @example Passing nil for optional attributes to update specific attributes.
# @client.update_pull_request('octokit/octokit.rb', 67, nil, nil, 'open')
# @example Empty body by passing empty string
# @client.update_pull_request('octokit/octokit.rb', 67, nil, '')
def update_pull_request(*args)
arguments = Octokit::Arguments.new(args)
repo = arguments.shift
number = arguments.shift
patch "#{Repository.path repo}/pulls/#{number}", arguments.options
end
# Close a pull request
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param number [Integer] Number of pull request to update.
# @return [Sawyer::Resource] Hash representing updated pull request.
# @see https://developer.github.com/v3/pulls/#update-a-pull-request
# @example
# @client.close_pull_request('octokit/octokit.rb', 67)
def close_pull_request(repo, number, options = {})
options.merge! state: 'closed'
update_pull_request(repo, number, options)
end
# List commits on a pull request
#
# @see https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number of pull request
# @return [Array<Sawyer::Resource>] List of commits
def pull_request_commits(repo, number, options = {})
paginate "#{Repository.path repo}/pulls/#{number}/commits", options
end
alias pull_commits pull_request_commits
# List pull request comments for a repository
#
# By default, Review Comments are ordered by ascending ID.
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param options [Hash] Optional parameters
# @option options [String] :sort created or updated
# @option options [String] :direction asc or desc. Ignored without sort
# parameter.
# @option options [String] :since Timestamp in ISO 8601
# format: YYYY-MM-DDTHH:MM:SSZ
#
# @return [Array] List of pull request review comments.
#
# @see https://developer.github.com/v3/pulls/comments/#list-comments-in-a-repository
#
# @example Get the pull request review comments in the octokit repository
# @client.issues_comments("octokit/octokit.rb")
#
# @example Get review comments, sort by updated asc since a time
# @client.pull_requests_comments("octokit/octokit.rb", {
# :sort => 'updated',
# :direction => 'asc',
# :since => '2010-05-04T23:45:02Z'
# })
def pull_requests_comments(repo, options = {})
paginate("#{Repository.path repo}/pulls/comments", options)
end
alias pulls_comments pull_requests_comments
alias reviews_comments pull_requests_comments
# List comments on a pull request
#
# @see https://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number of pull request
# @return [Array<Sawyer::Resource>] List of comments
def pull_request_comments(repo, number, options = {})
# return the comments for a pull request
paginate("#{Repository.path repo}/pulls/#{number}/comments", options)
end
alias pull_comments pull_request_comments
alias review_comments pull_request_comments
# Get a pull request comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param comment_id [Integer] Id of comment to get
# @return [Sawyer::Resource] Hash representing the comment
# @see https://developer.github.com/v3/pulls/comments/#get-a-single-comment
# @example
# @client.pull_request_comment("pengwynn/octkit", 1903950)
def pull_request_comment(repo, comment_id, options = {})
get "#{Repository.path repo}/pulls/comments/#{comment_id}", options
end
alias pull_comment pull_request_comment
alias review_comment pull_request_comment
# Create a pull request comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param pull_id [Integer] Pull request id
# @param body [String] Comment content
# @param commit_id [String] Sha of the commit to comment on.
# @param path [String] Relative path of the file to comment on.
# @param position [Integer] Line index in the diff to comment on.
# @return [Sawyer::Resource] Hash representing the new comment
# @see https://developer.github.com/v3/pulls/comments/#create-a-comment
# @example
# @client.create_pull_request_comment("octokit/octokit.rb", 163, ":shipit:",
# "2d3201e4440903d8b04a5487842053ca4883e5f0", "lib/octokit/request.rb", 47)
def create_pull_request_comment(repo, pull_id, body, commit_id, path, position, options = {})
options.merge!({
body: body,
commit_id: commit_id,
path: path,
position: position
})
post "#{Repository.path repo}/pulls/#{pull_id}/comments", options
end
alias create_pull_comment create_pull_request_comment
alias create_view_comment create_pull_request_comment
# Create reply to a pull request comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param pull_id [Integer] Pull request id
# @param body [String] Comment contents
# @param comment_id [Integer] Comment id to reply to
# @return [Sawyer::Resource] Hash representing new comment
# @see https://developer.github.com/v3/pulls/comments/#create-a-comment
# @example
# @client.create_pull_request_comment_reply("octokit/octokit.rb", 163, "done.", 1903950)
def create_pull_request_comment_reply(repo, pull_id, body, comment_id, options = {})
options.merge!({
body: body,
in_reply_to: comment_id
})
post "#{Repository.path repo}/pulls/#{pull_id}/comments", options
end
alias create_pull_reply create_pull_request_comment_reply
alias create_review_reply create_pull_request_comment_reply
# Update pull request comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param comment_id [Integer] Id of the comment to update
# @param body [String] Updated comment content
# @return [Sawyer::Resource] Hash representing the updated comment
# @see https://developer.github.com/v3/pulls/comments/#edit-a-comment
# @example
# @client.update_pull_request_comment("octokit/octokit.rb", 1903950, ":shipit:")
def update_pull_request_comment(repo, comment_id, body, options = {})
options.merge! body: body
patch("#{Repository.path repo}/pulls/comments/#{comment_id}", options)
end
alias update_pull_comment update_pull_request_comment
alias update_review_comment update_pull_request_comment
# Delete pull request comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param comment_id [Integer] Id of the comment to delete
# @return [Boolean] True if deleted, false otherwise
# @see https://developer.github.com/v3/pulls/comments/#delete-a-comment
# @example
# @client.delete_pull_request_comment("octokit/octokit.rb", 1902707)
def delete_pull_request_comment(repo, comment_id, options = {})
boolean_from_response(:delete, "#{Repository.path repo}/pulls/comments/#{comment_id}", options)
end
alias delete_pull_comment delete_pull_request_comment
alias delete_review_comment delete_pull_request_comment
# List files on a pull request
#
# @see https://developer.github.com/v3/pulls/#list-pull-requests-files
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number of pull request
# @return [Array<Sawyer::Resource>] List of files
def pull_request_files(repo, number, options = {})
paginate "#{Repository.path repo}/pulls/#{number}/files", options
end
alias pull_files pull_request_files
# Update a pull request branch
#
# @see https://developer.github.com/v3/pulls/#update-a-pull-request-branch
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number of pull request
# @param options [Hash] Optional parameters (e.g. expected_head_sha)
# @return [Boolean] True if the pull request branch has been updated
def update_pull_request_branch(repo, number, options = {})
boolean_from_response(:put, "#{Repository.path repo}/pulls/#{number}/update-branch", options)
end
# Merge a pull request
#
# @see https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-button
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number of pull request
# @param commit_message [String] Optional commit message for the merge commit
# @return [Array<Sawyer::Resource>] Merge commit info if successful
def merge_pull_request(repo, number, commit_message = '', options = {})
put "#{Repository.path repo}/pulls/#{number}/merge", options.merge({ commit_message: commit_message })
end
# Check pull request merge status
#
# @see https://developer.github.com/v3/pulls/#get-if-a-pull-request-has-been-merged
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number of pull request
# @return [Boolean] True if the pull request has been merged
def pull_merged?(repo, number, options = {})
boolean_from_response :get, "#{Repository.path repo}/pulls/#{number}/merge", options
end
alias pull_request_merged? pull_merged?
end
end
end
@@ -0,0 +1,52 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for API rate limiting info
#
# @see https://developer.github.com/v3/#rate-limiting
module RateLimit
# Get rate limit info from last response if available
# or make a new request to fetch rate limit
#
# @see https://developer.github.com/v3/rate_limit/#rate-limit
# @return [Octokit::RateLimit] Rate limit info
def rate_limit(_options = {})
return rate_limit! if last_response.nil?
Octokit::RateLimit.from_response(last_response)
end
alias ratelimit rate_limit
# Get number of rate limted requests remaining
#
# @see https://developer.github.com/v3/rate_limit/#rate-limit
# @return [Integer] Number of requests remaining in this period
def rate_limit_remaining(_options = {})
octokit_warn 'Deprecated: Please use .rate_limit.remaining'
rate_limit.remaining
end
alias ratelimit_remaining rate_limit_remaining
# Refresh rate limit info by making a new request
#
# @see https://developer.github.com/v3/rate_limit/#rate-limit
# @return [Octokit::RateLimit] Rate limit info
def rate_limit!(_options = {})
get 'rate_limit'
Octokit::RateLimit.from_response(last_response)
end
alias ratelimit! rate_limit!
# Refresh rate limit info and get number of rate limted requests remaining
#
# @see https://developer.github.com/v3/rate_limit/#rate-limit
# @return [Integer] Number of requests remaining in this period
def rate_limit_remaining!(_options = {})
octokit_warn 'Deprecated: Please use .rate_limit!.remaining'
rate_limit!.remaining
end
alias ratelimit_remaining! rate_limit_remaining!
end
end
end
@@ -0,0 +1,153 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Reacions API
#
# @see https://developer.github.com/v3/reactions/
module Reactions
# List reactions for a commit comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The id of the commit comment
# @see https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment
#
# @example
# @client.commit_comment_reactions("octokit/octokit.rb", 1)
#
# @return [Array<Sawyer::Resource>] Array of Hashes representing the reactions.
def commit_comment_reactions(repo, id, options = {})
get "#{Repository.path repo}/comments/#{id}/reactions", options
end
# Create a reaction for a commit comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The id of the commit comment
# @param reaction [String] The Reaction
# @see https://developer.github.com/v3/reactions/#create-reaction-for-a-commit-comment
# @see https://developer.github.com/v3/reactions/#reaction-types
#
# @example
# @client.create_commit_comment_reactions("octokit/octokit.rb", 1)
#
# @return [<Sawyer::Resource>] Hash representing the reaction
def create_commit_comment_reaction(repo, id, reaction, options = {})
options = options.merge(content: reaction)
post "#{Repository.path repo}/comments/#{id}/reactions", options
end
# List reactions for an issue
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] The Issue number
# @see https://developer.github.com/v3/reactions/#list-reactions-for-an-issue
#
# @example
# @client.issue_reactions("octokit/octokit.rb", 1)
#
# @return [Array<Sawyer::Resource>] Array of Hashes representing the reactions.
def issue_reactions(repo, number, options = {})
get "#{Repository.path repo}/issues/#{number}/reactions", options
end
# Create reaction for an issue
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] The Issue number
# @param reaction [String] The Reaction
#
# @see https://developer.github.com/v3/reactions/#create-reaction-for-an-issue
# @see https://developer.github.com/v3/reactions/#reaction-types
#
# @example
# @client.create_issue_reaction("octokit/octokit.rb", 1)
#
# @return [<Sawyer::Resource>] Hash representing the reaction.
def create_issue_reaction(repo, number, reaction, options = {})
options = options.merge(content: reaction)
post "#{Repository.path repo}/issues/#{number}/reactions", options
end
# List reactions for an issue comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The Issue comment id
#
# @see https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment
#
# @example
# @client.issue_comment_reactions("octokit/octokit.rb", 1)
#
# @return [Array<Sawyer::Resource>] Array of Hashes representing the reactions.
def issue_comment_reactions(repo, id, options = {})
get "#{Repository.path repo}/issues/comments/#{id}/reactions", options
end
# Create reaction for an issue comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The Issue comment id
# @param reaction [String] The Reaction
#
# @see https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment
# @see https://developer.github.com/v3/reactions/#reaction-types
#
# @example
# @client.create_issue_comment_reaction("octokit/octokit.rb", 1)
#
# @return [<Sawyer::Resource>] Hashes representing the reaction.
def create_issue_comment_reaction(repo, id, reaction, options = {})
options = options.merge(content: reaction)
post "#{Repository.path repo}/issues/comments/#{id}/reactions", options
end
# List reactions for a pull request review comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The Issue comment id
#
# @see https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment
#
# @example
# @client.pull_request_review_comment_reactions("octokit/octokit.rb", 1)
#
# @return [Array<Sawyer::Resource>] Array of Hashes representing the reactions.
def pull_request_review_comment_reactions(repo, id, options = {})
get "#{Repository.path repo}/pulls/comments/#{id}/reactions", options
end
# Create reaction for a pull request review comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The Issue comment id
# @param reaction [String] The Reaction
#
# @see https://developer.github.com/v3/reactions/#create-reaction-for-a-pull-request-review-comment
# @see https://developer.github.com/v3/reactions/#reaction-types
#
# @example
# @client.create_pull_request_reiew_comment_reaction("octokit/octokit.rb", 1)
#
# @return [<Sawyer::Resource>] Hash representing the reaction.
def create_pull_request_review_comment_reaction(repo, id, reaction, options = {})
options = options.merge(content: reaction)
post "#{Repository.path repo}/pulls/comments/#{id}/reactions", options
end
# Delete a reaction
#
# @param id [Integer] Reaction id
#
# @see https://developer.github.com/v3/reactions/#delete-a-reaction
#
# @example
# @client.delete_reaction(1)
#
# @return [Boolean] Return true if reaction was deleted, false otherwise.
def delete_reaction(id, options = {})
boolean_from_response :delete, "reactions/#{id}", options
end
end
end
end
@@ -0,0 +1,131 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for References for Git Data API
#
# @see https://developer.github.com/v3/git/refs/
module Refs
# List all refs for a given user and repo
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param namespace [String] The ref namespace, e.g. <tt>tag</tt> or <tt>heads</tt>
# @return [Array<Sawyer::Resource>] A list of references matching the repo and the namespace
# @see https://developer.github.com/v3/git/refs/#get-all-references
# @example Fetch all refs for sferik/rails_admin
# Octokit.refs("sferik/rails_admin")
def refs(repo, namespace = nil, options = {})
path = "#{Repository.path repo}/git/refs"
path += "/#{namespace}" unless namespace.nil?
paginate path, options
end
alias list_refs refs
alias references refs
alias list_references refs
# Fetch matching refs
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param ref [String] The ref, e.g. <tt>tags/v0.0.3</tt> or <tt>heads/rails-3</tt>
# @return [Array<Sawyer::Resource>] The reference matching the given repo and the ref id
# @see https://developer.github.com/v3/git/refs/#list-matching-references
# @example Fetch refs matching tags/v2 for sferik/rails_admin
# Octokit.ref("sferik/rails_admin","tags/v2")
def matching_refs(repo, ref, options = {})
paginate "#{Repository.path repo}/git/matching-refs/#{ref}", options
end
# Fetch a given reference
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param ref [String] The ref, e.g. <tt>tags/v0.0.3</tt>
# @return [Sawyer::Resource] The reference matching the given repo and the ref id
# @see https://developer.github.com/v3/git/refs/#get-a-reference
# @example Fetch tags/v0.0.3 for sferik/rails_admin
# Octokit.ref("sferik/rails_admin","tags/v0.0.3")
def ref(repo, ref, options = {})
get "#{Repository.path repo}/git/refs/#{ref}", options
end
alias reference ref
# Create a reference
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param ref [String] The ref, e.g. <tt>tags/v0.0.3</tt>
# @param sha [String] A SHA, e.g. <tt>827efc6d56897b048c772eb4087f854f46256132</tt>
# @return [Array<Sawyer::Resource>] The list of references, already containing the new one
# @see https://developer.github.com/v3/git/refs/#create-a-reference
# @example Create refs/heads/master for octocat/Hello-World with sha 827efc6d56897b048c772eb4087f854f46256132
# Octokit.create_ref("octocat/Hello-World", "heads/master", "827efc6d56897b048c772eb4087f854f46256132")
def create_ref(repo, ref, sha, options = {})
ref = "refs/#{ref}" unless ref =~ %r{\Arefs/}
parameters = {
ref: ref,
sha: sha
}
post "#{Repository.path repo}/git/refs", options.merge(parameters)
end
alias create_reference create_ref
# Update a reference
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param ref [String] The ref, e.g. <tt>tags/v0.0.3</tt>
# @param sha [String] A SHA, e.g. <tt>827efc6d56897b048c772eb4087f854f46256132</tt>
# @param force [Boolean] A flag indicating whether to force the update or to make sure the update is a fast-forward update.
# @return [Array<Sawyer::Resource>] The list of references updated
# @see https://developer.github.com/v3/git/refs/#update-a-reference
# @example Force update heads/sc/featureA for octocat/Hello-World with sha aa218f56b14c9653891f9e74264a383fa43fefbd
# Octokit.update_ref("octocat/Hello-World", "heads/sc/featureA", "aa218f56b14c9653891f9e74264a383fa43fefbd")
def update_ref(repo, ref, sha, force = false, options = {})
parameters = {
sha: sha,
force: force
}
patch "#{Repository.path repo}/git/refs/#{ref}", options.merge(parameters)
end
alias update_reference update_ref
# Update a branch
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param branch [String] The ref, e.g. <tt>feature/new-shiny</tt>
# @param sha [String] A SHA, e.g. <tt>827efc6d56897b048c772eb4087f854f46256132</tt>
# @param force [Boolean] A flag indicating whether to force the update or to make sure the update is a fast-forward update.
# @return [Array<Sawyer::Resource>] The list of references updated
# @see https://developer.github.com/v3/git/refs/#update-a-reference
# @example Force update heads/sc/featureA for octocat/Hello-World with sha aa218f56b14c9653891f9e74264a383fa43fefbd
# Octokit.update_branch("octocat/Hello-World", "sc/featureA", "aa218f56b14c9653891f9e74264a383fa43fefbd")
# @example Fast-forward update heads/sc/featureA for octocat/Hello-World with sha aa218f56b14c9653891f9e74264a383fa43fefbd
# Octokit.update_branch("octocat/Hello-World", "sc/featureA", "aa218f56b14c9653891f9e74264a383fa43fefbd", false)
def update_branch(repo, branch, sha, force = true, options = {})
update_ref repo, "heads/#{branch}", sha, force, options
end
# Delete a single branch
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param branch [String] The branch, e.g. <tt>fix-refs</tt>
# @return [Boolean] Success
# @see https://developer.github.com/v3/git/refs/#delete-a-reference
# @example Delete uritemplate for sigmavirus24/github3.py
# Octokit.delete_branch("sigmavirus24/github3.py", "uritemplate")
def delete_branch(repo, branch, options = {})
delete_ref repo, "heads/#{branch}", options
end
# Delete a single reference
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param ref [String] The ref, e.g. <tt>tags/v0.0.3</tt>
# @return [Boolean] Success
# @see https://developer.github.com/v3/git/refs/#delete-a-reference
# @example Delete tags/v0.0.3 for sferik/rails_admin
# Octokit.delete_ref("sferik/rails_admin","tags/v0.0.3")
def delete_ref(repo, ref, options = {})
boolean_from_response :delete, "#{Repository.path repo}/git/refs/#{ref}", options
end
alias delete_reference delete_ref
end
end
end
@@ -0,0 +1,164 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Releases API
#
# @see https://developer.github.com/v3/repos/releases/
module Releases
# List releases for a repository
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] A list of releases
# @see https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository
def releases(repo, options = {})
paginate "#{Repository.path repo}/releases", options
end
alias list_releases releases
# Create a release
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param tag_name [String] Git tag from which to create release
# @option options [String] :target_commitish Specifies the commitish value that determines where the Git tag is created from.
# @option options [String] :name Name for the release
# @option options [String] :body Content for release notes
# @option options [Boolean] :draft Mark this release as a draft
# @option options [Boolean] :prerelease Mark this release as a pre-release
# @return [Sawyer::Resource] The release
# @see https://developer.github.com/v3/repos/releases/#create-a-release
def create_release(repo, tag_name, options = {})
opts = options.merge(tag_name: tag_name)
post "#{Repository.path repo}/releases", opts
end
# Get a release
#
# @param url [String] URL for the release as returned from .releases
# @return [Sawyer::Resource] The release
# @see https://developer.github.com/v3/repos/releases/#get-a-single-release
def release(url, options = {})
get url, options
end
# Update a release
#
# @param url [String] URL for the release as returned from .releases
# @option options [String] :tag_name Git tag from which to create release
# @option options [String] :target_commitish Specifies the commitish value that determines where the Git tag is created from.
# @option options [String] :name Name for the release
# @option options [String] :body Content for release notes
# @option options [Boolean] :draft Mark this release as a draft
# @option options [Boolean] :prerelease Mark this release as a pre-release
# @return [Sawyer::Resource] The release
# @see https://developer.github.com/v3/repos/releases/#edit-a-release
def update_release(url, options = {})
patch url, options
end
alias edit_release update_release
# Delete a release
#
# @param url [String] URL for the release as returned from .releases
# @return [Boolean] Success or failure
# @see https://developer.github.com/v3/repos/releases/#delete-a-release
def delete_release(url, options = {})
boolean_from_response(:delete, url, options)
end
# List release assets
#
# @param release_url [String] URL for the release as returned from .releases
# @return [Array<Sawyer::Resource>] A list of release assets
# @see https://developer.github.com/v3/repos/releases/#list-assets-for-a-release
def release_assets(release_url, options = {})
paginate release(release_url).rels[:assets].href, options
end
# Upload a release asset
#
# @param release_url [String] URL for the release as returned from .releases
# @param path_or_file [String] Path to file to upload
# @option options [String] :content_type The MIME type for the file to upload
# @option options [String] :name The name for the file
# @return [Sawyer::Resource] The release asset
# @see https://developer.github.com/v3/repos/releases/#upload-a-release-asset
def upload_asset(release_url, path_or_file, options = {})
file = path_or_file.respond_to?(:read) ? path_or_file : File.new(path_or_file, 'rb')
options[:content_type] ||= content_type_from_file(file)
raise Octokit::MissingContentType if options[:content_type].nil?
unless name = options[:name]
name = File.basename(file.path)
end
upload_url = release(release_url).rels[:upload].href_template.expand(name: name)
request :post, upload_url, file.read, parse_query_and_convenience_headers(options)
ensure
file&.close
end
# Get a single release asset
#
#
# @param asset_url [String] URL for the asset as returned from .release_assets
# @return [Sawyer::Resource] The release asset
# @see https://developer.github.com/v3/repos/releases/#get-a-single-release-asset
def release_asset(asset_url, options = {})
get(asset_url, options)
end
# Update a release asset
#
# @param asset_url [String] URL for the asset as returned from .release_assets
# @option options [String] :name The name for the file
# @option options [String] :label The download text for the file
# @return [Sawyer::Resource] The release asset
# @see https://developer.github.com/v3/repos/releases/#edit-a-release-asset
def update_release_asset(asset_url, options = {})
patch(asset_url, options)
end
alias edit_release_asset update_release_asset
# Delete a release asset
#
# @param asset_url [String] URL for the asset as returned from .release_assets
# @return [Boolean] Success or failure
# @see https://developer.github.com/v3/repos/releases/#delete-a-release-asset
def delete_release_asset(asset_url, options = {})
boolean_from_response(:delete, asset_url, options)
end
# Get the release for a given tag
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param tag_name [String] the name for a tag
# @return [Sawyer::Resource] The release
# @see https://developer.github.com/v3/repos/releases/#get-a-release-by-tag-name
def release_for_tag(repo, tag_name, options = {})
get "#{Repository.path repo}/releases/tags/#{tag_name}", options
end
# Get the latest release
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Sawyer::Resource] The release
# @see https://developer.github.com/v3/repos/releases/#get-the-latest-release
def latest_release(repo, options = {})
get "#{Repository.path repo}/releases/latest", options
end
private
def content_type_from_file(file)
require 'mime/types'
if mime_type = MIME::Types.type_for(file.path).first
mime_type.content_type
end
rescue LoadError
msg = 'Please pass content_type or install mime-types gem to guess content type from file'
raise Octokit::MissingContentType, msg
end
end
end
end
@@ -0,0 +1,779 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Repositories API
#
# @see https://developer.github.com/v3/repos/
module Repositories
# Check if a repository exists
#
# @see https://developer.github.com/v3/repos/#get
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Boolean]
def repository?(repo, options = {})
!!repository(repo, options)
rescue Octokit::InvalidRepository, Octokit::NotFound
false
end
# Get a single repository
#
# @see https://developer.github.com/v3/repos/#get
# @see https://developer.github.com/v3/licenses/#get-a-repositorys-license
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Sawyer::Resource] Repository information
def repository(repo, options = {})
get Repository.path(repo), options
end
alias repo repository
# Edit a repository
#
# @see https://developer.github.com/v3/repos/#update-a-repository
# @param repo [String, Hash, Repository] A GitHub repository
# @param options [Hash] Repository information to update
# @option options [String] :name Name of the repo
# @option options [String] :description Description of the repo
# @option options [String] :homepage Home page of the repo
# @option options [String] :private `true` makes the repository private, and `false` makes it public.
# @option options [String] :has_issues `true` enables issues for this repo, `false` disables issues.
# @option options [String] :has_wiki `true` enables wiki for this repo, `false` disables wiki.
# @option options [Boolean] :is_template `true` makes the repository a template, `false` makes it not a template.
# @option options [String] :has_downloads `true` enables downloads for this repo, `false` disables downloads.
# @option options [String] :default_branch Update the default branch for this repository.
# @return [Sawyer::Resource] Repository information
def edit_repository(repo, options = {})
repo = Repository.new(repo)
options[:name] ||= repo.name
patch "repos/#{repo}", options
end
alias edit edit_repository
alias update_repository edit_repository
alias update edit_repository
# List user repositories
#
# If user is not supplied, repositories for the current
# authenticated user are returned.
#
# @note If the user provided is a GitHub organization, only the
# organization's public repositories will be listed. For retrieving
# organization repositories the {Organizations#organization_repositories}
# method should be used instead.
# @see https://developer.github.com/v3/repos/#list-your-repositories
# @see https://developer.github.com/v3/repos/#list-user-repositories
# @param user [Integer, String] Optional GitHub user login or id for which
# to list repos.
# @return [Array<Sawyer::Resource>] List of repositories
def repositories(user = nil, options = {})
paginate "#{User.path user}/repos", options
end
alias list_repositories repositories
alias list_repos repositories
alias repos repositories
# List all repositories
#
# This provides a dump of every repository, in the order that they were
# created.
#
# @see https://developer.github.com/v3/repos/#list-all-public-repositories
#
# @param options [Hash] Optional options
# @option options [Integer] :since The integer ID of the last Repository
# that you’ve seen.
# @return [Array<Sawyer::Resource>] List of repositories.
def all_repositories(options = {})
paginate 'repositories', options
end
# Star a repository
#
# @param repo [String, Hash, Repository] A GitHub repository
# @return [Boolean] `true` if successfully starred
# @see https://developer.github.com/v3/activity/starring/#star-a-repository
def star(repo, options = {})
boolean_from_response :put, "user/starred/#{Repository.new(repo)}", options
end
# Unstar a repository
#
# @param repo [String, Hash, Repository] A GitHub repository
# @return [Boolean] `true` if successfully unstarred
# @see https://developer.github.com/v3/activity/starring/#unstar-a-repository
def unstar(repo, options = {})
boolean_from_response :delete, "user/starred/#{Repository.new(repo)}", options
end
# Watch a repository
#
# @param repo [String, Hash, Repository] A GitHub repository
# @return [Boolean] `true` if successfully watched
# @deprecated Use #star instead
# @see https://developer.github.com/v3/activity/watching/#watch-a-repository-legacy
def watch(repo, options = {})
boolean_from_response :put, "user/watched/#{Repository.new(repo)}", options
end
# Unwatch a repository
#
# @param repo [String, Hash, Repository] A GitHub repository
# @return [Boolean] `true` if successfully unwatched
# @deprecated Use #unstar instead
# @see https://developer.github.com/v3/activity/watching/#stop-watching-a-repository-legacy
def unwatch(repo, options = {})
boolean_from_response :delete, "user/watched/#{Repository.new(repo)}", options
end
# Fork a repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Sawyer::Resource] Repository info for the new fork
# @see https://developer.github.com/v3/repos/forks/#create-a-fork
def fork(repo, options = {})
post "#{Repository.path repo}/forks", options
end
# Create a repository for a user or organization
#
# @param name [String] Name of the new repo
# @option options [String] :description Description of the repo
# @option options [String] :homepage Home page of the repo
# @option options [String] :private `true` makes the repository private, and `false` makes it public.
# @option options [String] :has_issues `true` enables issues for this repo, `false` disables issues.
# @option options [String] :has_wiki `true` enables wiki for this repo, `false` disables wiki.
# @option options [Boolean] :is_template `true` makes this repo available as a template repository, `false` to prevent it.
# @option options [String] :has_downloads `true` enables downloads for this repo, `false` disables downloads.
# @option options [String] :organization Short name for the org under which to create the repo.
# @option options [Integer] :team_id The id of the team that will be granted access to this repository. This is only valid when creating a repo in an organization.
# @option options [Boolean] :auto_init `true` to create an initial commit with empty README. Default is `false`.
# @option options [String] :gitignore_template Desired language or platform .gitignore template to apply. Ignored if auto_init parameter is not provided.
# @return [Sawyer::Resource] Repository info for the new repository
# @see https://developer.github.com/v3/repos/#create
def create_repository(name, options = {})
opts = options.dup
organization = opts.delete :organization
opts.merge! name: name
if organization.nil?
post 'user/repos', opts
else
post "#{Organization.path organization}/repos", opts
end
end
alias create_repo create_repository
alias create create_repository
# Delete repository
#
# Note: If OAuth is used, 'delete_repo' scope is required
#
# @see https://developer.github.com/v3/repos/#delete-a-repository
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Boolean] `true` if repository was deleted
def delete_repository(repo, options = {})
boolean_from_response :delete, Repository.path(repo), options
end
alias delete_repo delete_repository
# Transfer repository
#
# Transfer a repository owned by your organization
#
# @see https://developer.github.com/v3/repos/#transfer-a-repository
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param new_owner [String] The username or organization name the repository will be transferred to.
# @param options [Array<Integer>] :team_ids ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories.
# @return [Sawyer::Resource] Repository info for the transferred repository
def transfer_repository(repo, new_owner, options = {})
post "#{Repository.path repo}/transfer", options.merge({ new_owner: new_owner })
end
alias transfer_repo transfer_repository
# Create a repository for a user or organization generated from a template repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub template repository
# @param name [String] Name of the new repo
# @option options [String] :owner Organization or user who the new repository will belong to.
# @option options [String] :description Description of the repo
# @option options [String] :private `true` makes the repository private, and `false` makes it public.
# @option options [Boolean] :include_all_branches `true` copies all branches from the template repository, `false` (default) makes it only copy the master branch.
# @return [Sawyer::Resource] Repository info for the new repository
def create_repository_from_template(repo, name, options = {})
options.merge! name: name
post "#{Repository.path repo}/generate", options
end
alias create_repo_from_template create_repository_from_template
# Hide a public repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Sawyer::Resource] Updated repository info
def set_private(repo, options = {})
# GitHub Api for setting private updated to use private attr, rather than public
update_repository repo, options.merge({ private: true })
end
# Unhide a private repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Sawyer::Resource] Updated repository info
def set_public(repo, options = {})
# GitHub Api for setting private updated to use private attr, rather than public
update_repository repo, options.merge({ private: false })
end
# Get deploy keys on a repo
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @return [Array<Sawyer::Resource>] Array of hashes representing deploy keys.
# @see https://developer.github.com/v3/repos/keys/#list-deploy-keys
# @example
# @client.deploy_keys('octokit/octokit.rb')
# @example
# @client.list_deploy_keys('octokit/octokit.rb')
def deploy_keys(repo, options = {})
paginate "#{Repository.path repo}/keys", options
end
alias list_deploy_keys deploy_keys
# Get a single deploy key for a repo
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param id [Integer] Deploy key ID.
# @return [Sawyer::Resource] Deploy key.
# @see https://developer.github.com/v3/repos/keys/#get-a-deploy-key
# @example
# @client.deploy_key('octokit/octokit.rb', 8675309)
def deploy_key(repo, id, options = {})
get "#{Repository.path repo}/keys/#{id}", options
end
# Add deploy key to a repo
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param title [String] Title reference for the deploy key.
# @param key [String] Public key.
# @return [Sawyer::Resource] Hash representing newly added key.
# @see https://developer.github.com/v3/repos/keys/#add-a-new-deploy-key
# @example
# @client.add_deploy_key('octokit/octokit.rb', 'Staging server', 'ssh-rsa AAA...')
def add_deploy_key(repo, title, key, options = {})
post "#{Repository.path repo}/keys", options.merge(title: title, key: key)
end
# Edit a deploy key
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param id [Integer] Deploy key ID.
# @param options [Hash] Attributes to edit.
# @option title [String] Key title.
# @option key [String] Public key.
# @return [Sawyer::Resource] Updated deploy key.
# @deprecated This method is no longer supported in the API
# @see https://developer.github.com/changes/2014-02-24-finer-grained-scopes-for-ssh-keys/
# @see https://developer.github.com/v3/repos/keys/#edit-a-deploy-key
# @example Update the key for a deploy key.
# @client.edit_deploy_key('octokit/octokit.rb', 8675309, :key => 'ssh-rsa BBB...')
# @example
# @client.update_deploy_key('octokit/octokit.rb', 8675309, :title => 'Uber', :key => 'ssh-rsa BBB...'))
def edit_deploy_key(repo, id, options)
patch "#{Repository.path repo}/keys/#{id}", options
end
alias update_deploy_key edit_deploy_key
# Remove deploy key from a repo
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param id [Integer] Id of the deploy key to remove.
# @return [Boolean] True if key removed, false otherwise.
# @see https://developer.github.com/v3/repos/keys/#remove-a-deploy-key
# @example
# @client.remove_deploy_key('octokit/octokit.rb', 100000)
def remove_deploy_key(repo, id, options = {})
boolean_from_response :delete, "#{Repository.path repo}/keys/#{id}", options
end
# List collaborators
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @option options [String] :affiliation Filters the return array by affiliation.
# Can be one of: <tt>outside</tt>, <tt>direct</tt>, or <tt>all</tt>.
# If not specified, defaults to <tt>all</tt>
# @return [Array<Sawyer::Resource>] Array of hashes representing collaborating users.
# @see https://developer.github.com/v3/repos/collaborators/#list-collaborators
# @example
# Octokit.collaborators('octokit/octokit.rb')
# @example
# Octokit.collabs('octokit/octokit.rb')
# @example
# @client.collabs('octokit/octokit.rb')
def collaborators(repo, options = {})
paginate "#{Repository.path repo}/collaborators", options
end
alias collabs collaborators
# Add collaborator to repo
#
# This can also be used to update the permission of an existing collaborator
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param collaborator [String] Collaborator GitHub username to add.
# @option options [String] :permission The permission to grant the collaborator.
# Only valid on organization-owned repositories.
# Can be one of: <tt>pull</tt>, <tt>push</tt>, or <tt>admin</tt>.
# If not specified, defaults to <tt>push</tt>
# @return [Boolean] True if collaborator added, false otherwise.
# @see https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator
# @example
# @client.add_collaborator('octokit/octokit.rb', 'holman')
# @example
# @client.add_collab('octokit/octokit.rb', 'holman')
# @example Add a collaborator with admin permissions
# @client.add_collaborator('octokit/octokit.rb', 'holman', permission: 'admin')
def add_collaborator(repo, collaborator, options = {})
boolean_from_response :put, "#{Repository.path repo}/collaborators/#{collaborator}", options
end
alias add_collab add_collaborator
# Remove collaborator from repo.
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param collaborator [String] Collaborator GitHub username to remove.
# @return [Boolean] True if collaborator removed, false otherwise.
# @see https://developer.github.com/v3/repos/collaborators/#remove-user-as-a-collaborator
# @example
# @client.remove_collaborator('octokit/octokit.rb', 'holman')
# @example
# @client.remove_collab('octokit/octokit.rb', 'holman')
def remove_collaborator(repo, collaborator, options = {})
boolean_from_response :delete, "#{Repository.path repo}/collaborators/#{collaborator}", options
end
alias remove_collab remove_collaborator
# Checks if a user is a collaborator for a repo.
#
# Requires authenticated client.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param collaborator [String] Collaborator GitHub username to check.
# @return [Boolean] True if user is a collaborator, false otherwise.
# @see https://developer.github.com/v3/repos/collaborators/#check-if-a-user-is-a-collaborator
# @example
# @client.collaborator?('octokit/octokit.rb', 'holman')
def collaborator?(repo, collaborator, options = {})
boolean_from_response :get, "#{Repository.path repo}/collaborators/#{collaborator}", options
end
# Get a user's permission level for a repo.
#
# Requires authenticated client
#
# @return [Sawyer::Resource] Hash representing the user's permission level for the given repository
# @see https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level
# @example
# @client.permission_level('octokit/octokit.rb', 'lizzhale')
def permission_level(repo, collaborator, options = {})
get "#{Repository.path repo}/collaborators/#{collaborator}/permission", options
end
# List teams for a repo
#
# Requires authenticated client that is an owner or collaborator of the repo.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of hashes representing teams.
# @see https://developer.github.com/v3/repos/#list-teams
# @example
# @client.repository_teams('octokit/pengwynn')
# @example
# @client.repo_teams('octokit/pengwynn')
# @example
# @client.teams('octokit/pengwynn')
def repository_teams(repo, options = {})
paginate "#{Repository.path repo}/teams", options
end
alias repo_teams repository_teams
alias teams repository_teams
# List all topics for a repository
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Sawyer::Resource] representing the topics for given repo
# @see https://developer.github.com/v3/repos/#list-all-topics-for-a-repository
# @example List topics for octokit/octokit.rb
# Octokit.topics('octokit/octokit.rb')
# @example List topics for octokit/octokit.rb
# client.topics('octokit/octokit.rb')
def topics(repo, options = {})
paginate "#{Repository.path repo}/topics", options
end
# Replace all topics for a repository
#
# Requires authenticated client.
#
# @param repo [Integer, String, Repository, Hash] A Github repository
# @param names [Array] An array of topics to add to the repository.
# @return [Sawyer::Resource] representing the replaced topics for given repo
# @see https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository
# @example Replace topics for octokit/octokit.rb
# client.replace_all_topics('octokit/octokit.rb', ['octocat', 'atom', 'electron', 'API'])
# @example Clear all topics for octokit/octokit.rb
# client.replace_all_topics('octokit/octokit.rb', [])
def replace_all_topics(repo, names, options = {})
put "#{Repository.path repo}/topics", options.merge(names: names)
end
# List contributors to a repo
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param anon [Boolean] Set true to include anonymous contributors.
# @return [Array<Sawyer::Resource>] Array of hashes representing users.
# @see https://developer.github.com/v3/repos/#list-contributors
# @example
# Octokit.contributors('octokit/octokit.rb', true)
# @example
# Octokit.contribs('octokit/octokit.rb')
# @example
# @client.contribs('octokit/octokit.rb')
def contributors(repo, anon = nil, options = {})
options[:anon] = 1 if anon.to_s[/1|true/]
paginate "#{Repository.path repo}/contributors", options
end
alias contribs contributors
# List stargazers of a repo
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of hashes representing users.
# @see https://developer.github.com/v3/activity/starring/#list-stargazers
# @example
# Octokit.stargazers('octokit/octokit.rb')
# @example
# @client.stargazers('octokit/octokit.rb')
def stargazers(repo, options = {})
paginate "#{Repository.path repo}/stargazers", options
end
# @deprecated Use {#stargazers} instead
#
# List watchers of repo.
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of hashes representing users.
# @see https://developer.github.com/v3/repos/watching/#list-watchers
# @example
# Octokit.watchers('octokit/octokit.rb')
# @example
# @client.watchers('octokit/octokit.rb')
def watchers(repo, options = {})
paginate "#{Repository.path repo}/watchers", options
end
# List forks
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of hashes representing repos.
# @see https://developer.github.com/v3/repos/forks/#list-forks
# @example
# Octokit.forks('octokit/octokit.rb')
# @example
# Octokit.network('octokit/octokit.rb')
# @example
# @client.forks('octokit/octokit.rb')
def forks(repo, options = {})
paginate "#{Repository.path repo}/forks", options
end
alias network forks
# List languages of code in the repo.
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of Hashes representing languages.
# @see https://developer.github.com/v3/repos/#list-languages
# @example
# Octokit.languages('octokit/octokit.rb')
# @example
# @client.languages('octokit/octokit.rb')
def languages(repo, options = {})
paginate "#{Repository.path repo}/languages", options
end
# List tags
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of hashes representing tags.
# @see https://developer.github.com/v3/repos/#list-tags
# @example
# Octokit.tags('octokit/octokit.rb')
# @example
# @client.tags('octokit/octokit.rb')
def tags(repo, options = {})
paginate "#{Repository.path repo}/tags", options
end
# List branches
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of hashes representing branches.
# @see https://developer.github.com/v3/repos/#list-branches
# @example
# Octokit.branches('octokit/octokit.rb')
# @example
# @client.branches('octokit/octokit.rb')
def branches(repo, options = {})
paginate "#{Repository.path repo}/branches", options
end
# Get a single branch from a repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param branch [String] Branch name
# @return [Sawyer::Resource] The branch requested, if it exists
# @see https://developer.github.com/v3/repos/#get-branch
# @example Get branch 'master` from octokit/octokit.rb
# Octokit.branch("octokit/octokit.rb", "master")
def branch(repo, branch, options = {})
get "#{Repository.path repo}/branches/#{CGI.escape(branch)}", options
end
alias get_branch branch
# Lock a single branch from a repository
#
# Requires authenticated client
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param branch [String] Branch name
# @option options [Hash] :required_status_checks If not null, the following keys are required:
# <tt>:enforce_admins [boolean] Enforce required status checks for repository administrators.</tt>
# <tt>:strict [boolean] Require branches to be up to date before merging.</tt>
# <tt>:contexts [Array] The list of status checks to require in order to merge into this branch</tt>
#
# @option options [Hash] :restrictions If not null, the following keys are required:
# <tt>:users [Array] The list of user logins with push access</tt>
# <tt>:teams [Array] The list of team slugs with push access</tt>.
#
# Teams and users restrictions are only available for organization-owned repositories.
# @return [Sawyer::Resource] The protected branch
# @see https://developer.github.com/v3/repos/#enabling-and-disabling-branch-protection
# @example
# @client.protect_branch('octokit/octokit.rb', 'master', foo)
def protect_branch(repo, branch, options = {})
options[:restrictions] ||= nil
options[:required_status_checks] ||= nil
put "#{Repository.path repo}/branches/#{branch}/protection", options
end
# Get branch protection summary
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param branch [String] Branch name
# @return [Sawyer::Resource, nil] Branch protection summary or nil if the branch
# is not protected
# @see https://developer.github.com/v3/repos/branches/#get-branch-protection
# @example
# @client.branch_protection('octokit/octokit.rb', 'master')
def branch_protection(repo, branch, options = {})
get "#{Repository.path repo}/branches/#{branch}/protection", options
rescue Octokit::BranchNotProtected
nil
end
# Unlock a single branch from a repository
#
# Requires authenticated client
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param branch [String] Branch name
# @return [Sawyer::Resource] The unprotected branch
# @see https://developer.github.com/v3/repos/#enabling-and-disabling-branch-protection
# @example
# @client.unprotect_branch('octokit/octokit.rb', 'master')
def unprotect_branch(repo, branch, options = {})
boolean_from_response :delete, "#{Repository.path repo}/branches/#{branch}/protection", options
end
# Rename a single branch from a repository
#
# Requires authenticated client
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param branch [String] Current branch name
# @param new_name [String] New branch name
# @return [Sawyer::Resource] The renamed branch
# @see https://developer.github.com/v3/repos/#rename-a-branch
# @example
# @client.rename_branch('octokit/octokit.rb', 'master', 'main')
def rename_branch(repo, branch, new_name, options = {})
params = {
new_name: new_name
}
post "#{Repository.path repo}/branches/#{branch}/rename", params.merge(options)
end
# List users available for assigning to issues.
#
# Requires authenticated client for private repos.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of hashes representing users.
# @see https://developer.github.com/v3/issues/assignees/#list-assignees
# @example
# Octokit.repository_assignees('octokit/octokit.rb')
# @example
# Octokit.repo_assignees('octokit/octokit.rb')
# @example
# @client.repository_assignees('octokit/octokit.rb')
def repository_assignees(repo, options = {})
paginate "#{Repository.path repo}/assignees", options
end
alias repo_assignees repository_assignees
# Check to see if a particular user is an assignee for a repository.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param assignee [String] User login to check
# @return [Boolean] True if assignable on project, false otherwise.
# @see https://developer.github.com/v3/issues/assignees/#check-assignee
# @example
# Octokit.check_assignee('octokit/octokit.rb', 'andrew')
def check_assignee(repo, assignee, options = {})
boolean_from_response :get, "#{Repository.path repo}/assignees/#{assignee}", options
end
# List watchers subscribing to notifications for a repo
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Array<Sawyer::Resource>] Array of users watching.
# @see https://developer.github.com/v3/activity/watching/#list-watchers
# @example
# @client.subscribers("octokit/octokit.rb")
def subscribers(repo, options = {})
paginate "#{Repository.path repo}/subscribers", options
end
# Get a repository subscription
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Sawyer::Resource] Repository subscription.
# @see https://developer.github.com/v3/activity/watching/#get-a-repository-subscription
# @example
# @client.subscription("octokit/octokit.rb")
def subscription(repo, options = {})
get "#{Repository.path repo}/subscription", options
end
# Update repository subscription
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param options [Hash]
#
# @option options [Boolean] :subscribed Determines if notifications
# should be received from this repository.
# @option options [Boolean] :ignored Deterimines if all notifications
# should be blocked from this repository.
# @return [Sawyer::Resource] Updated repository subscription.
# @see https://developer.github.com/v3/activity/watching/#set-a-repository-subscription
# @example Subscribe to notifications for a repository
# @client.update_subscription("octokit/octokit.rb", {subscribed: true})
def update_subscription(repo, options = {})
put "#{Repository.path repo}/subscription", options
end
# Delete a repository subscription
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Boolean] True if subscription deleted, false otherwise.
# @see https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription
#
# @example
# @client.delete_subscription("octokit/octokit.rb")
def delete_subscription(repo, options = {})
boolean_from_response :delete, "#{Repository.path repo}/subscription", options
end
# Create a repository dispatch event
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param event_type [String] A custom webhook event name.
# @option options [Hash] :client_payload payload with extra information
# about the webhook event that your action or worklow may use.
#
# @return [Boolean] True if event was dispatched, false otherwise.
# @see https://developer.github.com/v3/repos/#create-a-repository-dispatch-event
def dispatch_event(repo, event_type, options = {})
boolean_from_response :post, "#{Repository.path repo}/dispatches", options.merge({ event_type: event_type })
end
# Check to see if vulnerability alerts are enabled for a repository
#
# The authenticated user must have admin access to the repository.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Boolean] True if vulnerability alerts are enabled, false otherwise.
# @see https://docs.github.com/en/rest/reference/repos#check-if-vulnerability-alerts-are-enabled-for-a-repository
#
# @example
# @client.vulnerability_alerts_enabled?("octokit/octokit.rb")
def vulnerability_alerts_enabled?(repo, options = {})
boolean_from_response(:get, "#{Repository.path repo}/vulnerability-alerts", options)
end
# Enable vulnerability alerts for a repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param options [Hash]
#
# @return [Boolean] True if vulnerability alerts enabled, false otherwise.
# @see https://docs.github.com/en/rest/reference/repos#enable-vulnerability-alerts
# @example Enable vulnerability alerts for a repository
# @client.enable_vulnerability_alerts("octokit/octokit.rb")
def enable_vulnerability_alerts(repo, options = {})
boolean_from_response(:put, "#{Repository.path repo}/vulnerability-alerts", options)
end
# Disable vulnerability alerts for a repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param options [Hash]
#
# @return [Boolean] True if vulnerability alerts disabled, false otherwise.
# @see https://docs.github.com/en/rest/reference/repos#disable-vulnerability-alerts
# @example Disable vulnerability alerts for a repository
# @client.disable_vulnerability_alerts("octokit/octokit.rb")
def disable_vulnerability_alerts(repo, options = {})
boolean_from_response(:delete, "#{Repository.path repo}/vulnerability-alerts", options)
end
end
end
end
@@ -0,0 +1,96 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Repository Invitations API
#
# @see https://developer.github.com/v3/repos/invitations/
module RepositoryInvitations
# Invite a user to a repository
#
# Requires authenticated client
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param user [String] User GitHub username to add
# @return [Sawyer::Resource] The repository invitation
# @see https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator
def invite_user_to_repository(repo, user, options = {})
put "#{Repository.path repo}/collaborators/#{user}", options
end
alias invite_user_to_repo invite_user_to_repository
# List all invitations for a repository
#
# Requires authenticated client
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] A list of invitations
# @see https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository
def repository_invitations(repo, options = {})
paginate "#{Repository.path repo}/invitations", options
end
alias repo_invitations repository_invitations
# Delete an invitation for a repository
#
# Requires authenticated client
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param invitation_id [Integer] The id of the invitation
# @return [Boolean] True if the invitation was successfully deleted
# @see https://developer.github.com/v3/repos/invitations/#delete-a-repository-invitation
def delete_repository_invitation(repo, invitation_id, options = {})
boolean_from_response :delete, "#{Repository.path repo}/invitations/#{invitation_id}", options
end
alias delete_repo_invitation delete_repository_invitation
# Update an invitation for a repository
#
# Requires authenticated client
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param invitation_id [Integer] The id of the invitation
# @return [Sawyer::Resource] The updated repository invitation
# @see https://developer.github.com/v3/repos/invitations/#update-a-repository-invitation
def update_repository_invitation(repo, invitation_id, options = {})
patch "#{Repository.path repo}/invitations/#{invitation_id}", options
end
alias update_repo_invitation update_repository_invitation
# List all repository invitations for the user
#
# Requires authenticated client
#
# @return [Array<Sawyer::Resource>] The users repository invitations
# @see https://developer.github.com/v3/repos/invitations/#list-a-users-repository-invitations
def user_repository_invitations(options = {})
paginate '/user/repository_invitations', options
end
alias user_repo_invitations user_repository_invitations
# Accept a repository invitation
#
# Requires authenticated client
#
# @param invitation_id [Integer] The id of the invitation
# @return [Boolean] True if the acceptance of the invitation was successful
# @see https://developer.github.com/v3/repos/invitations/#accept-a-repository-invitation
def accept_repository_invitation(invitation_id, options = {})
patch "/user/repository_invitations/#{invitation_id}", options
end
alias accept_repo_invitation accept_repository_invitation
# Decline a repository invitation
#
# Requires authenticated client
#
# @param invitation_id [Integer] The id of the invitation
# @return [Boolean] True if the acceptance of the invitation was successful
# @see https://developer.github.com/v3/repos/invitations/#decline-a-repository-invitation
def decline_repository_invitation(invitation_id, options = {})
boolean_from_response :delete, "/user/repository_invitations/#{invitation_id}", options
end
alias decline_invitation decline_repository_invitation
end
end
end
@@ -0,0 +1,227 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Reviews API
#
# @see https://developer.github.com/v3/pulls/reviews/
module Reviews
# List reviews on a pull request
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @see https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request
#
# @example
# @client.pull_request_reviews('octokit/octokit.rb', 2)
#
# @return [Array<Sawyer::Resource>] Array of Hashes representing the reviews
def pull_request_reviews(repo, number, options = {})
paginate "#{Repository.path repo}/pulls/#{number}/reviews", options
end
# Get a single review
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @param review [Integer] The id of the review
# @see https://developer.github.com/v3/pulls/reviews/#get-a-single-review
#
# @example
# @client.pull_request_review('octokit/octokit.rb', 825, 6505518)
#
# @return [Sawyer::Resource] Hash representing the review
def pull_request_review(repo, number, review, options = {})
get "#{Repository.path repo}/pulls/#{number}/reviews/#{review}", options
end
# Delete a pending review
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @param review [Integer] The id of the review
# @see https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review
#
# @example
# @client.delete_pull_request_review('octokit/octokit.rb', 825, 6505518)
#
# @return [Sawyer::Resource] Hash representing the deleted review
def delete_pull_request_review(repo, number, review, options = {})
delete "#{Repository.path repo}/pulls/#{number}/reviews/#{review}", options
end
# Get comments for a single review
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @param review [Integer] The id of the review
# @see https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review
#
# @example
# @client.pull_request_review_comments('octokit/octokit.rb', 825, 6505518)
#
# @return [Array<Sawyer::Resource>] Array of Hashes representing the review comments
def pull_request_review_comments(repo, number, review, options = {})
paginate "#{Repository.path repo}/pulls/#{number}/reviews/#{review}/comments", options
end
# Create a pull request review
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @param options [Hash] Method options
# @option options [String] :event The review action (event) to perform;
# can be one of APPROVE, REQUEST_CHANGES, or COMMENT.
# If left blank, the review is left PENDING.
# @option options [String] :body The body text of the pull request review
# @option options [Array<Hash>] :comments Comments part of the review
# @option comments [String] :path The path to the file being commented on
# @option comments [Integer] :position The position in the file to be commented on
# @option comments [String] :body Body of the comment
# @see https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review
#
# @example
# comments = [
# { path: '.travis.yml', position: 10, body: 'ruby-head is under development that is not stable.' },
# { path: '.travis.yml', position: 32, body: 'ruby-head is also required in thervm section.' },
# ]
# options = { event: 'REQUEST_CHANGES', comments: comments }
# @client.create_pull_request_review('octokit/octokit.rb', 844, options)
#
# @return [Sawyer::Resource>] Hash respresenting the review
def create_pull_request_review(repo, number, options = {})
post "#{Repository.path repo}/pulls/#{number}/reviews", options
end
# Submit a pull request review
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @param review [Integer] The id of the review
# @param event [String] The review action (event) to perform; can be one of
# APPROVE, REQUEST_CHANGES, or COMMENT.
# @param options [Hash] Method options
# @option options [String] :body The body text of the pull request review
# @see https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review
#
# @example
# @client.submit_pull_request_review('octokit/octokit.rb', 825, 6505518,
# 'APPROVE', body: 'LGTM!')
#
# @return [Sawyer::Resource] Hash respresenting the review
def submit_pull_request_review(repo, number, review, event, options = {})
options = options.merge(event: event)
post "#{Repository.path repo}/pulls/#{number}/reviews/#{review}/events", options
end
# Dismiss a pull request review
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @param review [Integer] The id of the review
# @param message [String] The message for the pull request review dismissal
# @see https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review
#
# @example
# @client.dismiss_pull_request_review('octokit/octokit.rb', 825, 6505518, 'The message.')
#
# @return [Sawyer::Resource] Hash representing the dismissed review
def dismiss_pull_request_review(repo, number, review, message, options = {})
options = options.merge(message: message)
put "#{Repository.path repo}/pulls/#{number}/reviews/#{review}/dismissals", options
end
# List review requests
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @see https://developer.github.com/v3/pulls/review_requests/#list-review-requests
#
# @example
# @client.pull_request_review_requests('octokit/octokit.rb', 2)
#
# @return [Array<Sawyer::Resource>] Array of Hashes representing the review requests
def pull_request_review_requests(repo, number, options = {})
paginate "#{Repository.path repo}/pulls/#{number}/requested_reviewers", options
end
# Create a review request
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @param reviewers [Hash] :reviewers [Array<String>] An array of user logins
# @param options [Hash] :team_reviewers [Array<String>] An array of team slugs
# @see https://developer.github.com/v3/pulls/review_requests/#create-a-review-request
#
# @example
# @client.request_pull_request_review('octokit/octokit.rb', 2, reviewers: ['soudy'])
#
# @return [Sawyer::Resource>] Hash respresenting the pull request
def request_pull_request_review(repo, number, reviewers = {}, options = {})
# TODO(5.0): remove deprecated behavior
if reviewers.is_a?(Array)
octokit_warn(
'Deprecated: Octokit::Client#request_pull_request_review ' \
"no longer takes a separate :reviewers argument.\n" \
'Please update your call to pass :reviewers and :team_reviewers as part of the options hash.'
)
options = options.merge(reviewers: reviewers)
else
options = options.merge(reviewers)
end
post "#{Repository.path repo}/pulls/#{number}/requested_reviewers", options
end
# Delete a review request
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param id [Integer] The id of the pull request
# @param reviewers [Hash] :reviewers [Array] An array of user logins
# @param options [Hash] :team_reviewers [Array] An array of team slugs
#
# @see https://developer.github.com/v3/pulls/review_requests/#delete-a-review-request
#
# @example
# options = {
# "reviewers" => [ "octocat", "hubot", "other_user" ],
# "team_reviewers" => [ "justice-league" ]
# }
# @client.delete_pull_request_review_request('octokit/octokit.rb', 2, options)
#
# @return [Sawyer::Resource>] Hash representing the pull request
def delete_pull_request_review_request(repo, id, reviewers = {}, options = {})
# TODO(5.0): remove deprecated behavior
if !reviewers.empty? && !options.empty?
octokit_warn(
'Deprecated: Octokit::Client#delete_pull_request_review_request ' \
"no longer takes a separate :reviewers argument.\n" \
'Please update your call to pass :reviewers and :team_reviewers as part of the options hash.'
)
end
# For backwards compatibility, this endpoint can be called with a separate reviewers hash.
# If not called with a separate hash, then 'reviewers' is, in fact, 'options'.
options = options.merge(reviewers)
delete "#{Repository.path repo}/pulls/#{id}/requested_reviewers", options
end
# Update a review request comment
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param number [Integer] Number ID of the pull request
# @param review [Integer] The id of the review
# @param body [String] body text of the pull request review.
# @param options [Hash] Method options
# @see https://developer.github.com/v3/pulls/reviews/#update-a-pull-request-review
#
# @example
# @client.update_pull_request_review('octokit/octokit.rb', 825, 6505518, 'This is close to perfect! Please address the suggested inline change. And add more about this.')
#
# @return [Sawyer::Resource] Hash representing the review comment
def update_pull_request_review(repo, number, review, body, options = {})
options[:body] = body
put "#{Repository.path repo}/pulls/#{number}/reviews/#{review}", options
end
end
end
end
@@ -0,0 +1,18 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the unpublished Octocat API
module Say
# Return a nifty ASCII Octocat with GitHub wisdom
# or your own
#
# @return [String]
def say(text = nil, options = {})
options[:s] = text if text
get 'octocat', options
end
alias octocat say
end
end
end
@@ -0,0 +1,105 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Search API
#
# @see https://developer.github.com/v3/search/
module Search
# Search code
#
# @param query [String] Search term and qualifiers
# @param options [Hash] Sort and pagination options
# @option options [String] :sort Sort field
# @option options [String] :order Sort order (asc or desc)
# @option options [Integer] :page Page of paginated results
# @option options [Integer] :per_page Number of items per page
# @return [Sawyer::Resource] Search results object
# @see https://developer.github.com/v3/search/#search-code
def search_code(query, options = {})
search 'search/code', query, options
end
# Search commits
#
# @param query [String] Search terms and qualifiers
# @param options [Hash] Sort and pagination options
# @option options [String] :sort Sort field
# @option options [String] :order Sort order (asc or desc)
# @option options [Integer] :page Page of paginated results
# @option options [Integer] :per_page Number of items per page
# @return [Sawyer::Resource] Search results object
# @see https://developer.github.com/v3/search/#search-commits
def search_commits(query, options = {})
search 'search/commits', query, options
end
# Search issues
#
# @param query [String] Search term and qualifiers
# @param options [Hash] Sort and pagination options
# @option options [String] :sort Sort field
# @option options [String] :order Sort order (asc or desc)
# @option options [Integer] :page Page of paginated results
# @option options [Integer] :per_page Number of items per page
# @return [Sawyer::Resource] Search results object
# @see https://developer.github.com/v3/search/#search-issues-and-pull-requests
# @see https://docs.github.com/en/rest/search#limitations-on-query-length
def search_issues(query, options = {})
search 'search/issues', query, options
end
# Search repositories
#
# @param query [String] Search term and qualifiers
# @param options [Hash] Sort and pagination options
# @option options [String] :sort Sort field
# @option options [String] :order Sort order (asc or desc)
# @option options [Integer] :page Page of paginated results
# @option options [Integer] :per_page Number of items per page
# @return [Sawyer::Resource] Search results object
# @see https://developer.github.com/v3/search/#search-repositories
def search_repositories(query, options = {})
search 'search/repositories', query, options
end
alias search_repos search_repositories
# Search topics
#
# @param query [String] Search term and qualifiers
# @param options [Hash] Sort and pagination options
# @option options [String] :sort Sort field
# @option options [String] :order Sort order (asc or desc)
# @option options [Integer] :page Page of paginated results
# @option options [Integer] :per_page Number of items per page
# @return [Sawyer::Resource] Search results object
# @see https://developer.github.com/v3/search/#search-topics
def search_topics(query, options = {})
search 'search/topics', query, options
end
# Search users
#
# @param query [String] Search term and qualifiers
# @param options [Hash] Sort and pagination options
# @option options [String] :sort Sort field
# @option options [String] :order Sort order (asc or desc)
# @option options [Integer] :page Page of paginated results
# @option options [Integer] :per_page Number of items per page
# @return [Sawyer::Resource] Search results object
# @see https://developer.github.com/v3/search/#search-users
def search_users(query, options = {})
search 'search/users', query, options
end
private
def search(path, query, options = {})
opts = options.merge(q: query)
paginate(path, opts) do |data, last_response|
data.items.concat last_response.data.items
end
end
end
end
end
@@ -0,0 +1,48 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the GitHub Status API
#
# @see https://status.github.com/api
module ServiceStatus
# Root for status API
# @private
SUMMARY_ROOT = 'https://www.githubstatus.com/api/v2/summary.json'
STATUS_ROOT = 'https://www.githubstatus.com/api/v2/status.json'
COMPONENTS_ROOT = 'https://www.githubstatus.com/api/v2/components.json'
# Returns a summary with the current status and the last status messages.
#
# @return [<Sawyer::Resource>] GitHub status summary
# @see https://www.githubstatus.com/api#summory
def github_status_summary
get(SUMMARY_ROOT)
end
# Returns the current system status
#
# @return [Sawyer::Resource] GitHub status
# @see https://www.githubstatus.com/api#status
def github_status
get(STATUS_ROOT)
end
# Returns the last human communication, status, and timestamp.
#
# @return [Sawyer::Resource] GitHub status last message
# @see https://www.githubstatus.com/api/#components
def github_status_last_message
get(COMPONENTS_ROOT).components.first
end
# Returns the most recent human communications with status and timestamp.
#
# @return [Array<Sawyer::Resource>] GitHub status messages
# @see https://www.githubstatus.com/api#components
def github_status_messages
get(COMPONENTS_ROOT).components
end
end
end
end
@@ -0,0 +1,156 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Source Import API
#
# @see https://developer.github.com/v3/migration/source_imports
module SourceImport
# Start a source import to a GitHub repository using GitHub Importer.
#
# @overload start_source_import(repo, vcs, vcs_url, options = {})
# @deprecated
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param vcs [String] The originating VCS type. Can be one of "subversion", "git", "mercurial", or "tfvc".
# @param vcs_url [String] The URL of the originating repository.
# @param options [Hash]
# @option options [String] :vcs_username If authentication is required, the username to provide to vcs_url.
# @option options [String] :vcs_password If authentication is required, the password to provide to vcs_url.
# @option options [String] :tfvc_project For a tfvc import, the name of the project that is being imported.
# @overload start_source_import(repo, vcs_url, options = {})
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param vcs_url [String] The URL of the originating repository.
# @param options [Hash]
# @param options [String] :vcs The originating VCS type. Can be one of "subversion", "git", "mercurial", or "tfvc".
# @option options [String] :vcs_username If authentication is required, the username to provide to vcs_url.
# @option options [String] :vcs_password If authentication is required, the password to provide to vcs_url.
# @option options [String] :tfvc_project For a tfvc import, the name of the project that is being imported.
# @return [Sawyer::Resource] Hash representing the repository import
# @see https://developer.github.com/v3/migration/source_imports/#start-an-import
#
# @example
# @client.start_source_import("octokit/octokit.rb", "http://svn.mycompany.com/svn/myproject", {
# :vcs => "subversion",
# :vcs_username" => "octocat",
# :vcs_password => "secret"
# })
def start_source_import(*args)
arguments = Octokit::RepoArguments.new(args)
vcs_url = arguments.pop
vcs = arguments.pop
if vcs
octokit_warn 'Octokit#start_source_import vcs parameter is now an option, please update your call before the next major Octokit version update.'
arguments.options.merge!(vcs: vcs)
end
options = arguments.options.merge(vcs_url: vcs_url)
put "#{Repository.path arguments.repo}/import", options
end
# View the progress of an import.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Sawyer::Resource] Hash representing the progress of the import
# @see https://developer.github.com/v3/migration/source_imports/#get-import-progress
#
# @example
# @client.source_import_progress("octokit/octokit.rb")
def source_import_progress(repo, options = {})
get "#{Repository.path repo}/import", options
end
# Update source import with authentication or project choice
# Restart source import if no options are passed
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Sawyer::Resource] Hash representing the repository import
# @see https://developer.github.com/v3/migration/source_imports/#update-existing-import
# @option options [String] :vcs_username If authentication is required, the username to provide to vcs_url.
# @option options [String] :vcs_password If authentication is required, the password to provide to vcs_url.
# @option options [String] To update project choice, please refer to the project_choice array from the progress return hash for the exact attributes.
# https://developer.github.com/v3/migration/source_imports/#update-existing-import
#
# @example
# @client.update_source_import("octokit/octokit.rb", {
# :vcs_username" => "octocat",
# :vcs_password => "secret"
# })
def update_source_import(repo, options = {})
patch "#{Repository.path repo}/import", options
end
# List source import commit authors
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param options [Hash]
# @option options [String] :since Only authors found after this id are returned.
# @return [Array<Sawyer::Resource>] Array of hashes representing commit_authors.
# @see https://developer.github.com/v3/migration/source_imports/#get-commit-authors
#
# @example
# @client.source_import_commit_authors("octokit/octokit.rb")
def source_import_commit_authors(repo, options = {})
get "#{Repository.path repo}/import/authors", options
end
# Update an author's identity for the import.
#
# @param author_url [String] The source import API url for the commit author
# @param values [Hash] The updated author attributes
# @option values [String] :email The new Git author email.
# @option values [String] :name The new Git author name.
# @return [Sawyer::Resource] Hash representing the updated commit author
# @see https://developer.github.com/v3/migration/source_imports/#map-a-commit-author
#
# @example
# author_url = "https://api.github.com/repos/octokit/octokit.rb/import/authors/1"
# @client.map_source_import_commit_author(author_url, {
# :email => "hubot@github.com",
# :name => "Hubot the Robot"
# })
def map_source_import_commit_author(author_url, values, options = {})
options = options.merge(values)
patch author_url, options
end
# Stop an import for a repository.
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [Boolean] True if the import has been cancelled, false otherwise.
# @see https://developer.github.com/v3/migration/source_imports/#cancel-an-import
#
# @example
# @client.cancel_source_import("octokit/octokit.rb")
def cancel_source_import(repo, options = {})
boolean_from_response :delete, "#{Repository.path repo}/import", options
end
# List source import large files
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param options [Hash]
# @option options [Integer] :page Page of paginated results
# @return [Array<Sawyer::Resource>] Array of hashes representing files over 100MB.
# @see https://developer.github.com/v3/migration/source_imports/#get-large-files
#
# @example
# @client.source_import_large_files("octokit/octokit.rb")
def source_import_large_files(repo, options = {})
get "#{Repository.path repo}/import/large_files", options
end
# Set preference for using Git LFS to import files over 100MB
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @param use_lfs [String] Preference for using Git LFS to import large files. Can be one of "opt_in" or "opt_out"
# @return [Sawyer::Resource] Hash representing the repository import
# @see https://developer.github.com/v3/migration/source_imports/#set-git-lfs-preference
#
# @example
# @client.opt_in_source_import_lfs("octokit/octokit.rb", "opt_in")
def set_source_import_lfs_preference(repo, use_lfs, options = {})
options = options.merge(use_lfs: use_lfs)
patch "#{Repository.path repo}/import/lfs", options
end
end
end
end
@@ -0,0 +1,108 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Repository Statistics API
#
# @see https://developer.github.com/v3/repos/statistics/
module Stats
# Get contributors list with additions, deletions, and commit counts
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @option retry_timeout [Number] How long Octokit should keep trying to get stats (in seconds)
# @option retry_wait [Number] How long Octokit should wait between retries.
# @return [Array<Sawyer::Resource>] Array of contributor stats
# @see https://developer.github.com/v3/repos/statistics/#get-contributors-list-with-additions-deletions-and-commit-counts
# @example Get contributor stats for octokit
# @client.contributors_stats('octokit/octokit.rb')
def contributors_stats(repo, options = {})
get_stats(repo, 'contributors', options)
end
alias contributor_stats contributors_stats
# Get the last year of commit activity data
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @option retry_timeout [Number] How long Octokit should keep trying to get stats (in seconds)
# @option retry_wait [Number] How long Octokit should wait between retries.
# @return [Array<Sawyer::Resource>] The last year of commit activity grouped by
# week. The days array is a group of commits per day, starting on Sunday.
# @see https://developer.github.com/v3/repos/statistics/#get-the-last-year-of-commit-activity-data
# @example Get commit activity for octokit
# @client.commit_activity_stats('octokit/octokit.rb')
def commit_activity_stats(repo, options = {})
get_stats(repo, 'commit_activity', options)
end
# Get the number of additions and deletions per week
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @option retry_timeout [Number] How long Octokit should keep trying to get stats (in seconds)
# @option retry_wait [Number] How long Octokit should wait between retries.
# @return [Array<Sawyer::Resource>] Weekly aggregate of the number of additions
# and deletions pushed to a repository.
# @see https://developer.github.com/v3/repos/statistics/#get-the-number-of-additions-and-deletions-per-week
# @example Get code frequency stats for octokit
# @client.code_frequency_stats('octokit/octokit.rb')
def code_frequency_stats(repo, options = {})
get_stats(repo, 'code_frequency', options)
end
# Get the weekly commit count for the repo owner and everyone else
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @option retry_timeout [Number] How long Octokit should keep trying to get stats (in seconds)
# @option retry_wait [Number] How long Octokit should wait between retries.
# @return [Sawyer::Resource] Total commit counts for the owner and total commit
# counts in all. all is everyone combined, including the owner in the last
# 52 weeks. If you’d like to get the commit counts for non-owners, you can
# subtract all from owner.
# @see https://developer.github.com/v3/repos/statistics/#get-the-weekly-commit-count-for-the-repository-owner-and-everyone-else
# @example Get weekly commit counts for octokit
# @client.participation_stats("octokit/octokit.rb")
def participation_stats(repo, options = {})
get_stats(repo, 'participation', options)
end
# Get the number of commits per hour in each day
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @option retry_timeout [Number] How long Octokit should keep trying to get stats (in seconds)
# @option retry_wait [Number] How long Octokit should wait between retries.
# @return [Array<Array>] Arrays containing the day number, hour number, and
# number of commits
# @see https://developer.github.com/v3/repos/statistics/#get-the-number-of-commits-per-hour-in-each-day
# @example Get octokit punch card
# @octokit.punch_card_stats
def punch_card_stats(repo, options = {})
get_stats(repo, 'punch_card', options)
end
alias punch_card punch_card_stats
private
# @private Get stats for a repository
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param metric [String] The metrics you are looking for
# @return [Array<Sawyer::Resource> or nil] Stats in metric-specific format, or nil if not yet calculated.
# @see https://developer.github.com/v3/repos/statistics/
def get_stats(repo, metric, options = {})
options = options.dup
if retry_timeout = options.delete(:retry_timeout)
retry_wait = options.delete(:retry_wait) || 0.5
timeout = Time.now + retry_timeout
end
loop do
data = get("#{Repository.path repo}/stats/#{metric}", options)
return data if last_response.status == 200
return [] if last_response.status == 204
return nil unless retry_timeout
return nil if Time.now >= timeout
sleep retry_wait if retry_wait
end
end
end
end
end
@@ -0,0 +1,47 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Commit Statuses API
#
# @see https://developer.github.com/v3/repos/statuses/
module Statuses
# List all statuses for a given commit
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param sha [String] The SHA1 for the commit
# @return [Array<Sawyer::Resource>] A list of statuses
# @see https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref
def statuses(repo, sha, options = {})
paginate "#{Repository.path repo}/statuses/#{sha}", options
end
alias list_statuses statuses
# Get the combined status for a ref
#
# @param repo [Integer, String, Repository, Hash] a GitHub repository
# @param ref [String] A Sha or Ref to fetch the status of
# @return [Sawyer::Resource] The combined status for the commit
# @see https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref
def combined_status(repo, ref, options = {})
get "#{Repository.path repo}/commits/#{ref}/status", options
end
alias status combined_status
# Create status for a commit
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @param sha [String] The SHA1 for the commit
# @param state [String] The state: pending, success, failure, error
# @option options [String] :context A context to differentiate this status from others
# @option options [String] :target_url A link to more details about this status
# @option options [String] :description A short human-readable description of this status
# @return [Sawyer::Resource] A status
# @see https://developer.github.com/v3/repos/statuses/#create-a-status
def create_status(repo, sha, state, options = {})
options = options.merge(state: state)
post "#{Repository.path repo}/statuses/#{sha}", options
end
end
end
end
@@ -0,0 +1,31 @@
# frozen_string_literal: true
module Octokit
class Client
# Method to check scopes
#
# @see https://developer.github.com/v3/oauth_authorizations/#oauth-authorizations-api
module Tokens
# Check scopes for a token
#
# @param token [String] GitHub OAuth token
# @param options [Hash] Header params for request
# @return [Array<String>] OAuth scopes
# @see https://developer.github.com/v3/oauth/#scopes
def scopes(token = @access_token, options = {})
options = options.dup
raise ArgumentError, 'Access token required' if token.nil?
auth = { 'Authorization' => "token #{token}" }
headers = (options.delete(:headers) || {}).merge(auth)
agent.call(:get, 'user', headers: headers)
.headers['X-OAuth-Scopes']
.to_s
.split(',')
.map(&:strip)
.sort
end
end
end
end
@@ -0,0 +1,64 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Traffic API
#
# @see https://developer.github.com/v3/repos/traffic/
module Traffic
# Get the top 10 referrers over the last 14 days
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] List of referrers and stats
# @see https://developer.github.com/v3/repos/traffic/#list-referrers
# @example
# @client.top_referrers('octokit/octokit.rb')
def top_referrers(repo, options = {})
get "#{Repository.path repo}/traffic/popular/referrers", options
end
# Get the top 10 popular contents over the last 14 days
#
# @param repo [Integer, String, Repository, Hash] A GitHub repository
# @return [Array<Sawyer::Resource>] List of popular contents
# @see https://developer.github.com/v3/repos/traffic/#list-paths
# @example
# @client.top_paths('octokit/octokit.rb')
def top_paths(repo, options = {})
get "#{Repository.path repo}/traffic/popular/paths", options
end
# Get the total number of views and breakdown per day or week for the
# last 14 days
#
# @param repo [Integer, String, Repository, Hash] A GitHub Repository
# @option options [String] :per ('day') Views per. <tt>day</tt> or
# <tt>week</tt>
# @return [Sawyer::Resource] Breakdown of view stats
# @see https://developer.github.com/v3/repos/traffic/#views
# @example Views per day
# @client.views('octokit/octokit.rb')
# @example Views per week
# @client.views('octokit/octokit.rb', per: 'week')
def views(repo, options = {})
get "#{Repository.path repo}/traffic/views", options
end
# Get the total number of clones and breakdown per day or week for the
# last 14 days
#
# @param repo [Integer, String, Repository, Hash] A GitHub Repository
# @option options [String] :per ('day') Views per. <tt>day</tt> or
# <tt>week</tt>
# @return [Sawyer::Resource] Breakdown of clone stats
# @see https://developer.github.com/v3/repos/traffic/#clones
# @example Clones per day
# @client.clones('octokit/octokit.rb')
# @example Clones per week
# @client.clones('octokit/octokit.rb', per: 'week')
def clones(repo, options = {})
get "#{Repository.path repo}/traffic/clones", options
end
end
end
end
@@ -0,0 +1,435 @@
# frozen_string_literal: true
module Octokit
class Client
# Methods for the Users API
#
# @see https://developer.github.com/v3/users/
module Users
# List all GitHub users
#
# This provides a list of every user, in the order that they signed up
# for GitHub.
#
# @param options [Hash] Optional options.
# @option options [Integer] :since The integer ID of the last User that
# you’ve seen.
#
# @see https://developer.github.com/v3/users/#get-all-users
#
# @return [Array<Sawyer::Resource>] List of GitHub users.
def all_users(options = {})
paginate 'users', options
end
# Get a single user
#
# @param user [Integer, String] GitHub user login or id.
# @return [Sawyer::Resource]
# @see https://developer.github.com/v3/users/#get-a-single-user
# @see https://developer.github.com/v3/users/#get-the-authenticated-user
# @example
# Octokit.user("sferik")
def user(user = nil, options = {})
get User.path(user), options
end
# Retrieve the access_token.
#
# @param code [String] Authorization code generated by GitHub.
# @param app_id [String] Client Id we received when our application was registered with GitHub. Defaults to client_id.
# @param app_secret [String] Client Secret we received when our application was registered with GitHub. Defaults to client_secret.
# @return [Sawyer::Resource] Hash holding the access token.
# @see https://developer.github.com/v3/oauth/#web-application-flow
# @example
# Octokit.exchange_code_for_token('aaaa', 'xxxx', 'yyyy', {:accept => 'application/json'})
def exchange_code_for_token(code, app_id = client_id, app_secret = client_secret, options = {})
options = options.merge({
code: code,
client_id: app_id,
client_secret: app_secret,
headers: {
content_type: 'application/json',
accept: 'application/json'
}
})
post "#{web_endpoint}login/oauth/access_token", options
end
# Validate user username and password
#
# @param options [Hash] User credentials
# @option options [String] :login GitHub login
# @option options [String] :password GitHub password
# @return [Boolean] True if credentials are valid
def validate_credentials(options = {})
!self.class.new(options).user.nil?
rescue Octokit::Unauthorized
false
end
# Update the authenticated user
#
# @param options [Hash] A customizable set of options.
# @option options [String] :name
# @option options [String] :email Publically visible email address.
# @option options [String] :blog
# @option options [String] :company
# @option options [String] :location
# @option options [Boolean] :hireable
# @option options [String] :bio
# @return [Sawyer::Resource]
# @see https://developer.github.com/v3/users/#update-the-authenticated-user
# @example
# Octokit.update_user(:name => "Erik Michaels-Ober", :email => "sferik@gmail.com", :company => "Code for America", :location => "San Francisco", :hireable => false)
def update_user(options)
patch 'user', options
end
# Get a user's followers.
#
# @param user [Integer, String] GitHub user login or id of the user whose
# list of followers you are getting.
# @return [Array<Sawyer::Resource>] Array of hashes representing users
# followers.
# @see https://developer.github.com/v3/users/followers/#list-followers-of-a-user
# @example
# Octokit.followers('pengwynn')
def followers(user = login, options = {})
paginate "#{User.path user}/followers", options
end
# Get list of users a user is following.
#
# @param user [Intger, String] GitHub user login or id of the user who you
# are getting the list of the people they follow.
# @return [Array<Sawyer::Resource>] Array of hashes representing users a
# user is following.
# @see https://developer.github.com/v3/users/followers/#list-users-followed-by-another-user
# @example
# Octokit.following('pengwynn')
def following(user = login, options = {})
paginate "#{User.path user}/following", options
end
# Check if you are following a user. Alternatively, check if a given user
# is following a target user.
#
# Requries an authenticated client.
#
# @overload follows?(target)
# @param target [String] GitHub login of the user that you want to
# check if you are following.
# @overload follows?(user, target)
# @param user [Integer, String] GitHub user login or id of first user
# @param target [String] GitHub login of the target user
# @return [Boolean] True following target user, false otherwise.
# @see https://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user
# @see https://developer.github.com/v3/users/followers/#check-if-one-user-follows-another
# @example
# @client.follows?('pengwynn')
# @example
# @client.follows?('catsby', 'pengwynn')
def follows?(*args)
target = args.pop
user = args.first
boolean_from_response :get, "#{User.path user}/following/#{target}"
end
# Follow a user.
#
# Requires authenticatied client.
#
# @param user [String] Username of the user to follow.
# @return [Boolean] True if follow was successful, false otherwise.
# @see https://developer.github.com/v3/users/followers/#follow-a-user
# @example
# @client.follow('holman')
def follow(user, options = {})
boolean_from_response :put, "user/following/#{user}", options
end
# Unfollow a user.
#
# Requires authenticated client.
#
# @param user [String] Username of the user to unfollow.
# @return [Boolean] True if unfollow was successful, false otherwise.
# @see https://developer.github.com/v3/users/followers/#unfollow-a-user
# @example
# @client.unfollow('holman')
def unfollow(user, options = {})
boolean_from_response :delete, "user/following/#{user}", options
end
# Get list of repos starred by a user.
#
# @param user [Integer, String] GitHub user login of the user to get the
# list of their starred repositories.
# @param options [Hash] Optional options
# @option options [String] :sort (created) Sort: <tt>created</tt> or <tt>updated</tt>.
# @option options [String] :direction (desc) Direction: <tt>asc</tt> or <tt>desc</tt>.
# @return [Array<Sawyer::Resource>] Array of hashes representing repositories starred by user.
# @see https://developer.github.com/v3/activity/starring/#list-repositories-being-starred
# @example
# Octokit.starred('pengwynn')
def starred(user = login, options = {})
paginate user_path(user, 'starred'), options
end
# Check if you are starring a repo.
#
# Requires authenticated client.
#
# @param repo [String, Hash, Repository] A GitHub repository
# @return [Boolean] True if you are following the repo, false otherwise.
# @see https://developer.github.com/v3/activity/starring/#check-if-you-are-starring-a-repository
# @example
# @client.starred?('pengwynn/octokit')
def starred?(repo, options = {})
boolean_from_response :get, "user/starred/#{Repository.new(repo)}", options
end
# Get a public key.
#
# Note, when using dot notation to retrieve the values, ruby will return
# the hash key for the public keys value instead of the actual value, use
# symbol or key string to retrieve the value. See example.
#
# Requires authenticated client.
#
# @param key_id [Integer] Key to retreive.
# @return [Sawyer::Resource] Hash representing the key.
# @see https://developer.github.com/v3/users/keys/#get-a-single-public-key
# @example
# @client.key(1)
# @example Retrieve public key contents
# public_key = @client.key(1)
# public_key.key
# # => Error
#
# public_key[:key]
# # => "ssh-rsa AAA..."
#
# public_key['key']
# # => "ssh-rsa AAA..."
def key(key_id, options = {})
get "user/keys/#{key_id}", options
end
# Get list of public keys for user.
#
# Requires authenticated client.
#
# @return [Array<Sawyer::Resource>] Array of hashes representing public keys.
# @see https://developer.github.com/v3/users/keys/#list-your-public-keys
# @example
# @client.keys
def keys(options = {})
paginate 'user/keys', options
end
# Get list of public keys for user.
#
# @param user [Integer, String] GitHub user login or id.
# @return [Array<Sawyer::Resource>] Array of hashes representing public keys.
# @see https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user
# @example
# @client.user_keys('pengwynn')
def user_keys(user, options = {})
# TODO: Roll this into .keys
paginate "#{User.path user}/keys", options
end
# Add public key to user account.
#
# Requires authenticated client.
#
# @param title [String] Title to give reference to the public key.
# @param key [String] Public key.
# @return [Sawyer::Resource] Hash representing the newly added public key.
# @see https://developer.github.com/v3/users/keys/#create-a-public-key
# @example
# @client.add_key('Personal projects key', 'ssh-rsa AAA...')
def add_key(title, key, options = {})
post 'user/keys', options.merge({ title: title, key: key })
end
# Update a public key
#
# Requires authenticated client
#
# @param key_id [Integer] Id of key to update.
# @param options [Hash] Hash containing attributes to update.
# @option options [String] :title
# @option options [String] :key
# @return [Sawyer::Resource] Hash representing the updated public key.
#
# @deprecated This method is no longer supported in the API
# @see https://developer.github.com/v3/users/keys/#update-a-public-key
# @see https://developer.github.com/changes/2014-02-24-finer-grained-scopes-for-ssh-keys/
# @example
# @client.update_key(1, :title => 'new title', :key => "ssh-rsa BBB")
def update_key(key_id, options = {})
patch "user/keys/#{key_id}", options
end
# Remove a public key from user account.
#
# Requires authenticated client.
#
# @param id [String] Id of the public key to remove.
# @return [Boolean] True if removal was successful, false otherwise.
# @see https://developer.github.com/v3/users/keys/#delete-a-public-key
# @example
# @client.remove_key(1)
def remove_key(id, options = {})
boolean_from_response :delete, "user/keys/#{id}", options
end
# List email addresses for a user.
#
# Requires authenticated client.
#
# @return [Array<String>] Array of email addresses.
# @see https://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user
# @example
# @client.emails
def emails(options = {})
paginate 'user/emails', options
end
# Add email address to user.
#
# Requires authenticated client.
#
# @param email [String] Email address to add to the user.
# @return [Array<String>] Array of all email addresses of the user.
# @see https://developer.github.com/v3/users/emails/#add-email-addresses
# @example
# @client.add_email('new_email@user.com')
def add_email(email, _options = {})
email = Array(email)
post 'user/emails', email
end
# Remove email from user.
#
# Requires authenticated client.
#
# @param email [String] Email address to remove.
# @return [Array<String>] Array of all email addresses of the user.
# @see https://developer.github.com/v3/users/emails/#delete-email-addresses
# @example
# @client.remove_email('old_email@user.com')
def remove_email(email)
email = Array(email)
boolean_from_response :delete, 'user/emails', email
end
# List repositories being watched by a user.
#
# @param user [Integer, String] GitHub user login or id.
# @return [Array<Sawyer::Resource>] Array of repositories.
# @see https://developer.github.com/v3/activity/watching/#list-repositories-being-watched
# @example
# @client.subscriptions("pengwynn")
def subscriptions(user = login, options = {})
paginate user_path(user, 'subscriptions'), options
end
alias watched subscriptions
# Initiates the generation of a migration archive.
#
# Requires authenticated user.
#
# @param repositories [Array<String>] :repositories Repositories for the organization.
# @option options [Boolean, optional] :lock_repositories Indicates whether repositories should be locked during migration
# @option options [Boolean, optional] :exclude_attachments Exclude attachments fro the migration data
# @return [Sawyer::Resource] Hash representing the new migration.
# @example
# @client.start_migration(['octocat/hello-world'])
# @see https://docs.github.com/en/rest/reference/migrations#start-a-user-migration
def start_user_migration(repositories, options = {})
options[:repositories] = repositories
post 'user/migrations', options
end
# Lists the most recent migrations.
#
# Requires authenticated user.
#
# @return [Array<Sawyer::Resource>] Array of migration resources.
# @see https://docs.github.com/en/rest/reference/migrations#list-user-migrations
def user_migrations(options = {})
paginate 'user/migrations', options
end
# Fetches the status of a migration.
#
# Requires authenticated user.
#
# @param id [Integer] ID number of the migration.
# @see https://docs.github.com/en/rest/reference/migrations#get-a-user-migration-status
def user_migration_status(id, options = {})
get "user/migrations/#{id}", options
end
# Fetches the URL to a migration archive.
#
# Requires authenticated user.
#
# @param id [Integer] ID number of the migration.
# @see https://docs.github.com/en/rest/reference/migrations#download-a-user-migration-archive
def user_migration_archive_url(id, options = {})
url = "user/migrations/#{id}/archive"
response = client_without_redirects(options).get(url)
response.headers['location']
end
# Deletes a previous migration archive.
#
# Requires authenticated user.
#
# @param id [Integer] ID number of the migration.
# @see https://docs.github.com/en/rest/reference/migrations#delete-a-user-migration-archive
def delete_user_migration_archive(id, options = {})
delete "user/migrations/#{id}/archive", options
end
# List repositories for a user migration.
#
# Requires authenticated user.
#
# @param id [Integer] ID number of the migration.
# @see https://docs.github.com/en/rest/reference/migrations#list-repositories-for-a-user-migration
def user_migration_repositories(id, options = {})
get "user/migrations/#{id}/repositories", options
end
# Unlock a user repository which has been locked by a migration.
#
# Requires authenticated user.
#
# @param id [Integer] ID number of the migration.
# @param repo [String] Name of the repository.
# @see https://docs.github.com/en/rest/reference/migrations#unlock-a-user-repository
def unlock_user_repository(id, repo, options = {})
delete "user/migrations/#{id}/repos/#{repo}/lock", options
end
end
private
# convenience method for constructing a user specific path, if the user is logged in
def user_path(user, path)
if user == login && user_authenticated?
"user/#{path}"
else
"#{User.path user}/#{path}"
end
end
end
end
@@ -0,0 +1,155 @@
# frozen_string_literal: true
module Octokit
# Configuration options for {Client}, defaulting to values
# in {Default}
module Configurable
# @!attribute [w] access_token
# @see https://developer.github.com/v3/oauth/
# @return [String] OAuth2 access token for authentication
# @!attribute api_endpoint
# @return [String] Base URL for API requests. default: https://api.github.com/
# @!attribute auto_paginate
# @return [Boolean] Auto fetch next page of results until rate limit reached
# @!attribute [w] bearer_token
# @see https://developer.github.com/early-access/integrations/authentication/#as-an-integration
# @return [String] JWT bearer token for authentication
# @!attribute client_id
# @see https://developer.github.com/v3/oauth/
# @return [String] Configure OAuth app key
# @!attribute [w] client_secret
# @see https://developer.github.com/v3/oauth/
# @return [String] Configure OAuth app secret
# @!attribute default_media_type
# @see https://developer.github.com/v3/media/
# @return [String] Configure preferred media type (for API versioning, for example)
# @!attribute connection_options
# @see https://github.com/lostisland/faraday
# @return [Hash] Configure connection options for Faraday
# @!attribute login
# @return [String] GitHub username for Basic Authentication
# @!attribute management_console_password
# @return [String] An admin password set up for your GitHub Enterprise management console
# @!attribute management_console_endpoint
# @return [String] Base URL for API requests to the GitHub Enterprise management console
# @!attribute middleware
# @see https://github.com/lostisland/faraday
# @return [Faraday::Builder or Faraday::RackBuilder] Configure middleware for Faraday
# @!attribute netrc
# @return [Boolean] Instruct Octokit to get credentials from .netrc file
# @!attribute netrc_file
# @return [String] Path to .netrc file. default: ~/.netrc
# @!attribute [w] password
# @return [String] GitHub password for Basic Authentication
# @!attribute per_page
# @return [String] Configure page size for paginated results. API default: 30
# @!attribute proxy
# @see https://github.com/lostisland/faraday
# @return [String] URI for proxy server
# @!attribute ssl_verify_mode
# @see https://github.com/lostisland/faraday
# @return [String] SSL verify mode for ssl connections
# @!attribute user_agent
# @return [String] Configure User-Agent header for requests.
# @!attribute web_endpoint
# @return [String] Base URL for web URLs. default: https://github.com/
attr_accessor :access_token, :auto_paginate, :bearer_token, :client_id,
:client_secret, :default_media_type, :connection_options,
:middleware, :netrc, :netrc_file,
:per_page, :proxy, :ssl_verify_mode, :user_agent
attr_writer :password, :web_endpoint, :api_endpoint, :login,
:management_console_endpoint, :management_console_password
class << self
# List of configurable keys for {Octokit::Client}
# @return [Array] of option keys
def keys
@keys ||= %i[
access_token
api_endpoint
auto_paginate
bearer_token
client_id
client_secret
connection_options
default_media_type
login
management_console_endpoint
management_console_password
middleware
netrc
netrc_file
per_page
password
proxy
ssl_verify_mode
user_agent
web_endpoint
]
end
end
# Set configuration options using a block
def configure
yield self
end
# Reset configuration options to default values
def reset!
# rubocop:disable Style/HashEachMethods
#
# This may look like a `.keys.each` which should be replaced with `#each_key`, but
# this doesn't actually work, since `#keys` is just a method we've defined ourselves.
# The class doesn't fulfill the whole `Enumerable` contract.
Octokit::Configurable.keys.each do |key|
# rubocop:enable Style/HashEachMethods
instance_variable_set(:"@#{key}", Octokit::Default.options[key])
end
self
end
alias setup reset!
# Compares client options to a Hash of requested options
#
# @param opts [Hash] Options to compare with current client options
# @return [Boolean]
def same_options?(opts)
opts.hash == options.hash
end
def api_endpoint
File.join(@api_endpoint, '')
end
def management_console_endpoint
File.join(@management_console_endpoint, '')
end
# Base URL for generated web URLs
#
# @return [String] Default: https://github.com/
def web_endpoint
File.join(@web_endpoint, '')
end
def login
@login ||= (user.login if token_authenticated?)
end
def netrc?
!!@netrc
end
private
def options
Octokit::Configurable.keys.to_h { |key| [key, instance_variable_get(:"@#{key}")] }
end
def fetch_client_id_and_secret(overrides = {})
opts = options.merge(overrides)
opts.values_at :client_id, :client_secret
end
end
end
@@ -0,0 +1,218 @@
# frozen_string_literal: true
require 'sawyer'
require 'octokit/authentication'
module Octokit
# Network layer for API clients.
module Connection
include Octokit::Authentication
# Header keys that can be passed in options hash to {#get},{#head}
CONVENIENCE_HEADERS = Set.new(%i[accept content_type])
# Make a HTTP GET request
#
# @param url [String] The path, relative to {#api_endpoint}
# @param options [Hash] Query and header params for request
# @return [Sawyer::Resource]
def get(url, options = {})
request :get, url, parse_query_and_convenience_headers(options)
end
# Make a HTTP POST request
#
# @param url [String] The path, relative to {#api_endpoint}
# @param options [Hash] Body and header params for request
# @return [Sawyer::Resource]
def post(url, options = {})
request :post, url, options
end
# Make a HTTP PUT request
#
# @param url [String] The path, relative to {#api_endpoint}
# @param options [Hash] Body and header params for request
# @return [Sawyer::Resource]
def put(url, options = {})
request :put, url, options
end
# Make a HTTP PATCH request
#
# @param url [String] The path, relative to {#api_endpoint}
# @param options [Hash] Body and header params for request
# @return [Sawyer::Resource]
def patch(url, options = {})
request :patch, url, options
end
# Make a HTTP DELETE request
#
# @param url [String] The path, relative to {#api_endpoint}
# @param options [Hash] Query and header params for request
# @return [Sawyer::Resource]
def delete(url, options = {})
request :delete, url, options
end
# Make a HTTP HEAD request
#
# @param url [String] The path, relative to {#api_endpoint}
# @param options [Hash] Query and header params for request
# @return [Sawyer::Resource]
def head(url, options = {})
request :head, url, parse_query_and_convenience_headers(options)
end
# Make one or more HTTP GET requests, optionally fetching
# the next page of results from URL in Link response header based
# on value in {#auto_paginate}.
#
# @param url [String] The path, relative to {#api_endpoint}
# @param options [Hash] Query and header params for request
# @param block [Block] Block to perform the data concatination of the
# multiple requests. The block is called with two parameters, the first
# contains the contents of the requests so far and the second parameter
# contains the latest response.
# @return [Sawyer::Resource]
def paginate(url, options = {})
opts = parse_query_and_convenience_headers(options)
if @auto_paginate || @per_page
opts[:query][:per_page] ||= @per_page || (@auto_paginate ? 100 : nil)
end
data = request(:get, url, opts.dup)
if @auto_paginate
while @last_response.rels[:next] && rate_limit.remaining > 0
@last_response = @last_response.rels[:next].get(headers: opts[:headers])
if block_given?
yield(data, @last_response)
else
data.concat(@last_response.data) if @last_response.data.is_a?(Array)
end
end
end
data
end
# Hypermedia agent for the GitHub API
#
# @return [Sawyer::Agent]
def agent
@agent ||= Sawyer::Agent.new(endpoint, sawyer_options) do |http|
http.headers[:accept] = default_media_type
http.headers[:content_type] = 'application/json'
http.headers[:user_agent] = user_agent
if basic_authenticated?
http.request(*FARADAY_BASIC_AUTH_KEYS, @login, @password)
elsif token_authenticated?
http.request :authorization, 'token', @access_token
elsif bearer_authenticated?
http.request :authorization, 'Bearer', @bearer_token
elsif application_authenticated?
http.request(*FARADAY_BASIC_AUTH_KEYS, @client_id, @client_secret)
end
end
end
# Fetch the root resource for the API
#
# @return [Sawyer::Resource]
def root
get '/'
end
# Response for last HTTP request
#
# @return [Sawyer::Response]
def last_response
@last_response if defined? @last_response
end
protected
def endpoint
api_endpoint
end
private
def reset_agent
@agent = nil
end
def request(method, path, data, options = {})
if data.is_a?(Hash)
options[:query] = data.delete(:query) || {}
options[:headers] = data.delete(:headers) || {}
if accept = data.delete(:accept)
options[:headers][:accept] = accept
end
end
@last_response = response = agent.call(method, Addressable::URI.parse(path.to_s).normalize.to_s, data, options)
response_data_correctly_encoded(response)
rescue Octokit::Error => e
@last_response = nil
raise e
end
# Executes the request, checking if it was successful
#
# @return [Boolean] True on success, false otherwise
def boolean_from_response(method, path, options = {})
request(method, path, options)
[201, 202, 204].include? @last_response.status
rescue Octokit::NotFound
false
end
def sawyer_options
opts = {
links_parser: Sawyer::LinkParsers::Simple.new
}
conn_opts = @connection_options
conn_opts[:builder] = @middleware.dup if @middleware
conn_opts[:proxy] = @proxy if @proxy
if conn_opts[:ssl].nil?
conn_opts[:ssl] = { verify_mode: @ssl_verify_mode } if @ssl_verify_mode
else
verify = @connection_options[:ssl][:verify]
conn_opts[:ssl] = {
verify: verify,
verify_mode: verify == false ? 0 : @ssl_verify_mode
}
end
opts[:faraday] = Faraday.new(conn_opts)
opts
end
def parse_query_and_convenience_headers(options)
options = options.dup
headers = options.delete(:headers) { {} }
CONVENIENCE_HEADERS.each do |h|
if header = options.delete(h)
headers[h] = header
end
end
query = options.delete(:query)
opts = { query: options }
opts[:query].merge!(query) if query.is_a?(Hash)
opts[:headers] = headers unless headers.empty?
opts
end
def response_data_correctly_encoded(response)
content_type = response.headers.fetch('content-type', '')
return response.data unless content_type.include?('charset') && response.data.is_a?(String)
reported_encoding = content_type.match(/charset=([^ ]+)/)[1]
response.data.force_encoding(reported_encoding)
end
end
end
@@ -0,0 +1,189 @@
# frozen_string_literal: true
require 'octokit/middleware/follow_redirects'
require 'octokit/response/raise_error'
require 'octokit/response/feed_parser'
require 'octokit/version'
require 'octokit/warnable'
if Gem::Version.new(Faraday::VERSION) >= Gem::Version.new('2.0')
begin
require 'faraday/retry'
rescue LoadError
Octokit::Warnable.octokit_warn 'To use retry middleware with Faraday v2.0+, install `faraday-retry` gem'
end
end
module Octokit
# Default configuration options for {Client}
module Default
# Default API endpoint
API_ENDPOINT = 'https://api.github.com'
# Default User Agent header string
USER_AGENT = "Octokit Ruby Gem #{Octokit::VERSION}"
# Default media type
MEDIA_TYPE = 'application/vnd.github.v3+json'
# Default WEB endpoint
WEB_ENDPOINT = 'https://github.com'
# Default Faraday middleware stack
MIDDLEWARE = Faraday::RackBuilder.new do |builder|
# In Faraday 2.x, Faraday::Request::Retry was moved to a separate gem
# so we use it only when it's available.
if defined?(Faraday::Request::Retry)
retry_exceptions = Faraday::Request::Retry::DEFAULT_EXCEPTIONS + [Octokit::ServerError]
builder.use Faraday::Request::Retry, exceptions: retry_exceptions
elsif defined?(Faraday::Retry::Middleware)
retry_exceptions = Faraday::Retry::Middleware::DEFAULT_EXCEPTIONS + [Octokit::ServerError]
builder.use Faraday::Retry::Middleware, exceptions: retry_exceptions
end
builder.use Octokit::Middleware::FollowRedirects
builder.use Octokit::Response::RaiseError
builder.use Octokit::Response::FeedParser
builder.adapter Faraday.default_adapter
end
class << self
# Configuration options
# @return [Hash]
def options
Octokit::Configurable.keys.to_h { |key| [key, send(key)] }
end
# Default access token from ENV
# @return [String]
def access_token
ENV.fetch('OCTOKIT_ACCESS_TOKEN', nil)
end
# Default API endpoint from ENV or {API_ENDPOINT}
# @return [String]
def api_endpoint
ENV.fetch('OCTOKIT_API_ENDPOINT') { API_ENDPOINT }
end
# Default pagination preference from ENV
# @return [String]
def auto_paginate
ENV.fetch('OCTOKIT_AUTO_PAGINATE', nil)
end
# Default bearer token from ENV
# @return [String]
def bearer_token
ENV.fetch('OCTOKIT_BEARER_TOKEN', nil)
end
# Default OAuth app key from ENV
# @return [String]
def client_id
ENV.fetch('OCTOKIT_CLIENT_ID', nil)
end
# Default OAuth app secret from ENV
# @return [String]
def client_secret
ENV.fetch('OCTOKIT_SECRET', nil)
end
# Default management console password from ENV
# @return [String]
def management_console_password
ENV.fetch('OCTOKIT_ENTERPRISE_MANAGEMENT_CONSOLE_PASSWORD', nil)
end
# Default management console endpoint from ENV
# @return [String]
def management_console_endpoint
ENV.fetch('OCTOKIT_ENTERPRISE_MANAGEMENT_CONSOLE_ENDPOINT', nil)
end
# Default options for Faraday::Connection
# @return [Hash]
def connection_options
{
headers: {
accept: default_media_type,
user_agent: user_agent
}
}
end
# Default media type from ENV or {MEDIA_TYPE}
# @return [String]
def default_media_type
ENV.fetch('OCTOKIT_DEFAULT_MEDIA_TYPE') { MEDIA_TYPE }
end
# Default GitHub username for Basic Auth from ENV
# @return [String]
def login
ENV.fetch('OCTOKIT_LOGIN', nil)
end
# Default middleware stack for Faraday::Connection
# from {MIDDLEWARE}
# @return [Faraday::RackBuilder or Faraday::Builder]
def middleware
MIDDLEWARE
end
# Default GitHub password for Basic Auth from ENV
# @return [String]
def password
ENV.fetch('OCTOKIT_PASSWORD', nil)
end
# Default pagination page size from ENV
# @return [Integer] Page size
def per_page
page_size = ENV.fetch('OCTOKIT_PER_PAGE', nil)
page_size&.to_i
end
# Default proxy server URI for Faraday connection from ENV
# @return [String]
def proxy
ENV.fetch('OCTOKIT_PROXY', nil)
end
# Default SSL verify mode from ENV
# @return [Integer]
def ssl_verify_mode
# 0 is OpenSSL::SSL::VERIFY_NONE
# 1 is OpenSSL::SSL::SSL_VERIFY_PEER
# the standard default for SSL is SSL_VERIFY_PEER which requires a server certificate check on the client
ENV.fetch('OCTOKIT_SSL_VERIFY_MODE', 1).to_i
end
# Default User-Agent header string from ENV or {USER_AGENT}
# @return [String]
def user_agent
ENV.fetch('OCTOKIT_USER_AGENT') { USER_AGENT }
end
# Default web endpoint from ENV or {WEB_ENDPOINT}
# @return [String]
def web_endpoint
ENV.fetch('OCTOKIT_WEB_ENDPOINT') { WEB_ENDPOINT }
end
# Default behavior for reading .netrc file
# @return [Boolean]
def netrc
ENV.fetch('OCTOKIT_NETRC', false)
end
# Default path for .netrc file
# @return [String]
def netrc_file
ENV.fetch('OCTOKIT_NETRC_FILE') { File.join(Dir.home.to_s, '.netrc') }
end
end
end
end
@@ -0,0 +1,46 @@
# frozen_string_literal: true
require 'octokit/connection'
require 'octokit/configurable'
require 'octokit/warnable'
require 'octokit/enterprise_admin_client/admin_stats'
require 'octokit/enterprise_admin_client/license'
require 'octokit/enterprise_admin_client/orgs'
require 'octokit/enterprise_admin_client/search_indexing'
require 'octokit/enterprise_admin_client/users'
module Octokit
# EnterpriseAdminClient is only meant to be used by GitHub Enterprise Admins
# and provides access the Admin only API endpoints including Admin Stats,
# Management Console, and the Search Indexing API.
#
# @see Octokit::Client Use Octokit::Client for regular API use for GitHub
# and GitHub Enterprise.
# @see https://developer.github.com/v3/enterprise/
class EnterpriseAdminClient
include Octokit::Configurable
include Octokit::Connection
include Octokit::Warnable
include Octokit::EnterpriseAdminClient::AdminStats
include Octokit::EnterpriseAdminClient::License
include Octokit::EnterpriseAdminClient::Orgs
include Octokit::EnterpriseAdminClient::SearchIndexing
include Octokit::EnterpriseAdminClient::Users
def initialize(options = {})
# Use options passed in, but fall back to module defaults
#
# rubocop:disable Style/HashEachMethods
#
# This may look like a `.keys.each` which should be replaced with `#each_key`, but
# this doesn't actually work, since `#keys` is just a method we've defined ourselves.
# The class doesn't fulfill the whole `Enumerable` contract.
Octokit::Configurable.keys.each do |key|
# rubocop:enable Style/HashEachMethods
instance_variable_set(:"@#{key}", options[key] || Octokit.instance_variable_get(:"@#{key}"))
end
login_from_netrc unless user_authenticated? || application_authenticated?
end
end
end
@@ -0,0 +1,119 @@
# frozen_string_literal: true
module Octokit
class EnterpriseAdminClient
# Methods for the Enterprise Admin Stats API
#
# @see https://developer.github.com/v3/enterprise-admin/admin_stats/
module AdminStats
# Get all available stats
#
# @return [Sawyer::Resource] All available stats
# @example Get all available stats
# @client.admin_stats
def admin_stats
get_admin_stats 'all'
end
# Get only repository-related stats
#
# @return [Sawyer::Resource] Only repository-related stats
# @example Get only repository-related stats
# @client.admin_repository_stats
def admin_repository_stats
get_admin_stats 'repos'
end
# Get only hooks-related stats
#
# @return [Sawyer::Resource] Only hooks-related stats
# @example Get only hooks-related stats
# @client.admin_hooks_stats
def admin_hooks_stats
get_admin_stats 'hooks'
end
# Get only pages-related stats
#
# @return [Sawyer::Resource] Only pages-related stats
# @example Get only pages-related stats
# @client.admin_pages_stats
def admin_pages_stats
get_admin_stats 'pages'
end
# Get only organization-related stats
#
# @return [Sawyer::Resource] Only organization-related stats
# @example Get only organization-related stats
# @client.admin_organization_stats
def admin_organization_stats
get_admin_stats 'orgs'
end
# Get only user-related stats
#
# @return [Sawyer::Resource] Only user-related stats
# @example Get only user-related stats
# @client.admin_users_stats
def admin_users_stats
get_admin_stats 'users'
end
# Get only pull request-related stats
#
# @return [Sawyer::Resource] Only pull request-related stats
# @example Get only pull request-related stats
# @client.admin_pull_requests_stats
def admin_pull_requests_stats
get_admin_stats 'pulls'
end
# Get only issue-related stats
#
# @return [Sawyer::Resource] Only issue-related stats
# @example Get only issue-related stats
# @client.admin_issues_stats
def admin_issues_stats
get_admin_stats 'issues'
end
# Get only milestone-related stats
#
# @return [Sawyer::Resource] Only milestone-related stats
# @example Get only milestone-related stats
# @client.admin_milestones_stats
def admin_milestones_stats
get_admin_stats 'milestones'
end
# Get only gist-related stats
#
# @return [Sawyer::Resource] Only only gist-related stats
# @example Get only gist-related stats
# @client.admin_gits_stats
def admin_gists_stats
get_admin_stats 'gists'
end
# Get only comment-related stats
#
# @return [Sawyer::Resource] Only comment-related stats
# @example Get only comment-related stats
# @client.admin_comments_stats
def admin_comments_stats
get_admin_stats 'comments'
end
private
# @private Get enterprise stats
#
# @param metric [String] The metrics you are looking for
# @return [Sawyer::Resource] Magical unicorn stats
def get_admin_stats(metric)
get "enterprise/stats/#{metric}"
end
end
end
end
@@ -0,0 +1,17 @@
# frozen_string_literal: true
module Octokit
class EnterpriseAdminClient
# Methods for the Enterprise License API
#
# @see https://developer.github.com/v3/enterprise-admin/license/
module License
# Get information about the Enterprise license
#
# @return [Sawyer::Resource] The license information
def license_info
get 'enterprise/settings/license'
end
end
end
end
@@ -0,0 +1,26 @@
# frozen_string_literal: true
module Octokit
class EnterpriseAdminClient
# Methods for the Enterprise Orgs API
#
# @see https://developer.github.com/v3/enterprise-admin/orgs/
module Orgs
# Create a new organization on the instance.
#
# @param login [String] The organization's username.
# @param admin [String] The login of the user who will manage this organization.
# @param options [Hash] A set of options.
# @option options [String] :profile_name The organization's display name.
# @return [nil]
# @see https://developer.github.com/v3/enterprise-admin/orgs/#create-an-organization
# @example
# @admin_client.create_organization('SuchAGreatOrg', 'gjtorikian')
def create_organization(login, admin, options = {})
options[:login] = login
options[:admin] = admin
post 'admin/organizations', options
end
end
end
end
@@ -0,0 +1,82 @@
# frozen_string_literal: true
module Octokit
class EnterpriseAdminClient
# Methods for the Enterprise Search Indexing API
#
# @see https://developer.github.com/v3/enterprise-admin/search_indexing/
module SearchIndexing
# Queue a User or Organization to be indexed
#
# @param user [String] A GitHub Enterprise user or organization
# @return [Sawyer:Resource] Result of the queuing containing `:message`
def index_user(user)
queue_index user
end
alias index_organization index_user
# Queue a Repository to be indexed
#
# @param repo [String, Hash, Repository] A GitHub repository
# @return [Sawyer:Resource] Result of the queuing containing `:message`
def index_repository(repo)
queue_index Repository.new repo
end
# Queue a repository's Issues to be indexed
#
# @param repo [String, Hash, Repository] A GitHub repository
# @return [Sawyer:Resource] Result of the queuing containing `:message`
def index_repository_issues(repo)
queue_index "#{Repository.new repo}/issues"
end
# Queue a repository's code to be indexed
#
# @param repo [String, Hash, Repository] A GitHub repository
# @return [Sawyer:Resource] Result of the queuing containing `:message`
def index_repository_code(repo)
queue_index "#{Repository.new repo}/code"
end
# Queue a user's or organization's repositories to be indexed
#
# @param user [String] A GitHub Enterprise user or organization
# @return [Sawyer:Resource] Result of the queuing containing `:message`
def index_users_repositories(user)
queue_index "#{user}/*"
end
alias index_organizations_repositories index_users_repositories
# Queue an index of all the issues across all of a user's or
# organization's repositories
#
# @param user [String] A GitHub Enterprise user or organization
# @return [Sawyer:Resource] Result of the queuing containing `:message`
def index_users_repositories_issues(user)
queue_index "#{user}/*/issues"
end
alias index_organizations_repositories_issues index_users_repositories_issues
# Queue an index of all the code contained in all of a user's or
# organization's repositories
#
# @param user [String] A GitHub Enterprise user or organization
# @return [Sawyer:Resource] Result of the queuing containing `:message`
def index_users_repositories_code(user)
queue_index "#{user}/*/code"
end
alias index_organizations_repositories_code index_users_repositories_code
private
# @private Queue a target for indexing
#
# @param target [String] Target to index
# @return [Sawyer:Resource] Result of the queuing containing `:message`
def queue_index(target)
post 'staff/indexing_jobs', target: target
end
end
end
end
@@ -0,0 +1,129 @@
# frozen_string_literal: true
module Octokit
class EnterpriseAdminClient
# Methods for the Enterprise User Administration API
#
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/
module Users
# Create a new user.
#
# @param login [String] The user's username.
# @param email [String] The user's email address.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users#create-a-new-user
# @example
# @admin_client.create_user('foobar', 'notreal@foo.bar')
def create_user(login, email, options = {})
options[:login] = login
options[:email] = email
post 'admin/users', options
end
# Promote an ordinary user to a site administrator
#
# @param user [String] Username of the user to promote.
# @return [Boolean] True if promote was successful, false otherwise.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#promote-an-ordinary-user-to-a-site-administrator
# @example
# @admin_client.promote('holman')
def promote(user, options = {})
boolean_from_response :put, "users/#{user}/site_admin", options
end
# Demote a site administrator to an ordinary user
#
# @param user [String] Username of the user to demote.
# @return [Boolean] True if demote was successful, false otherwise.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#demote-a-site-administrator-to-an-ordinary-user
# @example
# @admin_client.demote('holman')
def demote(user, options = {})
boolean_from_response :delete, "users/#{user}/site_admin", options
end
# Rename a user.
#
# @param old_login [String] The user's old username.
# @param new_login [String] The user's new username.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#rename-an-existing-user
# @example
# @admin_client.rename_user('foobar', 'foofoobar')
def rename_user(old_login, new_login, options = {})
options[:login] = new_login
patch "admin/users/#{old_login}", options
end
# Deletes a user.
#
# @param username [String] The username to delete.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-a-user
# @example
# @admin_client.delete_key(1)
def delete_user(username, options = {})
boolean_from_response :delete, "admin/users/#{username}", options
end
# Suspend a user.
#
# @param user [String] Username of the user to suspend.
# @return [Boolean] True if suspend was successful, false otherwise.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#suspend-a-user
# @example
# @admin_client.suspend('holman')
def suspend(user, options = {})
boolean_from_response :put, "users/#{user}/suspended", options
end
# Unsuspend a user.
#
# @param user [String] Username of the user to unsuspend.
# @return [Boolean] True if unsuspend was successful, false otherwise.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#unsuspend-a-user
# @example
# @admin_client.unsuspend('holman')
def unsuspend(user, options = {})
boolean_from_response :delete, "users/#{user}/suspended", options
end
# Creates an impersonation OAuth token.
#
# @param login [String] The user to create a token for.
# @param options [Array<String>] :scopes The scopes to apply.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-an-impersonation-oauth-token
# @example
# @admin_client.create_impersonation_token('foobar', {:scopes => ['repo:write']})
def create_impersonation_token(login, options = {})
post "admin/users/#{login}/authorizations", options
end
# Deletes an impersonation OAuth token.
#
# @param login [String] The user whose token should be deleted.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-an-impersonation-oauth-token
# @example
# @admin_client.delete_impersonation_token('foobar')
def delete_impersonation_token(login, options = {})
boolean_from_response :delete, "admin/users/#{login}/authorizations", options
end
# Lists all the public SSH keys.
#
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#list-all-public-keys
# @example
# @admin_client.list_all_keys
def list_all_keys(options = {})
get 'admin/keys', options
end
# Deletes a public SSH keys.
#
# @param id [Number] The ID of the key to delete.
# @see https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-a-public-key
# @example
# @admin_client.delete_key(1)
def delete_key(id, options = {})
boolean_from_response :delete, "admin/keys/#{id}", options
end
end
end
end
@@ -0,0 +1,56 @@
# frozen_string_literal: true
require 'octokit/configurable'
require 'octokit/connection'
require 'octokit/warnable'
require 'octokit/enterprise_management_console_client/management_console'
module Octokit
# EnterpriseManagementConsoleClient is only meant to be used by GitHub Enterprise Admins
# and provides access to the management console API endpoints.
#
# @see Octokit::Client Use Octokit::Client for regular API use for GitHub
# and GitHub Enterprise.
# @see https://developer.github.com/v3/enterprise-admin/management_console/
class EnterpriseManagementConsoleClient
include Octokit::Configurable
include Octokit::Connection
include Octokit::Warnable
include Octokit::EnterpriseManagementConsoleClient::ManagementConsole
def initialize(options = {})
# Use options passed in, but fall back to module defaults
# rubocop:disable Style/HashEachMethods
#
# This may look like a `.keys.each` which should be replaced with `#each_key`, but
# this doesn't actually work, since `#keys` is just a method we've defined ourselves.
# The class doesn't fulfill the whole `Enumerable` contract.
Octokit::Configurable.keys.each do |key|
# rubocop:enable Style/HashEachMethods
instance_variable_set(:"@#{key}", options[key] || Octokit.instance_variable_get(:"@#{key}"))
end
end
protected
def endpoint
management_console_endpoint
end
# Set Enterprise Management Console password
#
# @param value [String] Management console admin password
def management_console_password=(value)
reset_agent
@management_console_password = value
end
# Set Enterprise Management Console endpoint
#
# @param value [String] Management console endpoint
def management_console_endpoint=(value)
reset_agent
@management_console_endpoint = value
end
end
end
@@ -0,0 +1,176 @@
# frozen_string_literal: true
module Octokit
class EnterpriseManagementConsoleClient
# Methods for the Enterprise Management Console API
#
# @see https://developer.github.com/v3/enterprise-admin/management_console/
module ManagementConsole
# Uploads a license for the first time
#
# @param license [String] The path to your .ghl license file.
# @param settings [Hash] A hash configuration of the initial settings.
#
# @see https://docs.github.com/en/enterprise-server@3.4/rest/enterprise-admin/management-console#create-a-github-license
# @return nil
def upload_license(license, settings = nil)
conn = faraday_configuration
params = {}
params[:license] = Faraday::UploadIO.new(license, 'binary')
params[:password] = @management_console_password
params[:settings] = settings.to_json.to_s unless settings.nil?
@last_response = conn.post('/setup/api/start', params)
end
# Start a configuration process.
#
# @return nil
def start_configuration
post '/setup/api/configure', password_hash
end
# Upgrade an Enterprise installation
#
# @param license [String] The path to your .ghl license file.
#
# @return nil
def upgrade(license)
conn = faraday_configuration
params = {}
params[:license] = Faraday::UploadIO.new(license, 'binary')
params[:api_key] = @management_console_password
@last_response = conn.post('/setup/api/upgrade', params)
end
# Get information about the Enterprise installation
#
# @return [Sawyer::Resource] The installation information
def config_status
get '/setup/api/configcheck', password_hash
end
alias config_check config_status
# Get information about the Enterprise installation
#
# @return [Sawyer::Resource] The settings
def settings
get '/setup/api/settings', password_hash
end
alias get_settings settings
# Modify the Enterprise settings
#
# @param settings [Hash] A hash configuration of the new settings
#
# @return [nil]
def edit_settings(settings)
queries = password_hash
queries[:query][:settings] = settings.to_json.to_s
put '/setup/api/settings', queries
end
# Get information about the Enterprise maintenance status
#
# @return [Sawyer::Resource] The maintenance status
def maintenance_status
get '/setup/api/maintenance', password_hash
end
alias get_maintenance_status maintenance_status
# Start (or turn off) the Enterprise maintenance mode
#
# @param maintenance [Hash] A hash configuration of the maintenance settings
# @return [nil]
def set_maintenance_status(maintenance)
queries = password_hash
queries[:query][:maintenance] = maintenance.to_json.to_s
post '/setup/api/maintenance', queries
end
alias edit_maintenance_status set_maintenance_status
# Fetch the authorized SSH keys on the Enterprise install
#
# @return [Sawyer::Resource] An array of authorized SSH keys
def authorized_keys
get '/setup/api/settings/authorized-keys', password_hash
end
alias get_authorized_keys authorized_keys
# Add an authorized SSH keys on the Enterprise install
#
# @param key Either the file path to a key, a File handler to the key, or the contents of the key itself
# @return [Sawyer::Resource] An array of authorized SSH keys
def add_authorized_key(key)
queries = password_hash
case key
when String
if File.exist?(key)
key = File.open(key, 'r')
content = key.read.strip
key.close
else
content = key
end
when File
content = key.read.strip
key.close
end
queries[:query][:authorized_key] = content
post '/setup/api/settings/authorized-keys', queries
end
# Removes an authorized SSH keys from the Enterprise install
#
# @param key Either the file path to a key, a File handler to the key, or the contents of the key itself
# @return [Sawyer::Resource] An array of authorized SSH keys
def remove_authorized_key(key)
queries = password_hash
case key
when String
if File.exist?(key)
key = File.open(key, 'r')
content = key.read.strip
key.close
else
content = key
end
when File
content = key.read.strip
key.close
end
queries[:query][:authorized_key] = content
delete '/setup/api/settings/authorized-keys', queries
end
alias delete_authorized_key remove_authorized_key
end
private
def password_hash
{ query: { api_key: @management_console_password } }
end
# We fall back to raw Faraday for handling the licenses because I'm suspicious
# that Sawyer isn't handling binary POSTs correctly: https://github.com/lostisland/sawyer/blob/03fca4c020f465ec42856d0486ec3991859b0aed/lib/sawyer/agent.rb#L85
def faraday_configuration
@faraday_configuration ||= Faraday.new(url: @management_console_endpoint) do |http|
http.headers[:user_agent] = user_agent
http.request :multipart
http.request :url_encoded
# Disabling SSL is essential for certain self-hosted Enterprise instances
if connection_options[:ssl] && !connection_options[:ssl][:verify]
http.ssl[:verify] = false
end
http.use Octokit::Response::RaiseError
http.adapter Faraday.default_adapter
end
end
end
end
+363
View File
@@ -0,0 +1,363 @@
# frozen_string_literal: true
module Octokit
# Custom error class for rescuing from all GitHub errors
class Error < StandardError
attr_reader :context
# Returns the appropriate Octokit::Error subclass based
# on status and response message
#
# @param [Hash] response HTTP response
# @return [Octokit::Error]
def self.from_response(response)
status = response[:status].to_i
body = response[:body].to_s
headers = response[:response_headers]
if klass = case status
when 400 then Octokit::BadRequest
when 401 then error_for_401(headers)
when 403 then error_for_403(body)
when 404 then error_for_404(body)
when 405 then Octokit::MethodNotAllowed
when 406 then Octokit::NotAcceptable
when 409 then Octokit::Conflict
when 415 then Octokit::UnsupportedMediaType
when 422 then error_for_422(body)
when 451 then Octokit::UnavailableForLegalReasons
when 400..499 then Octokit::ClientError
when 500 then Octokit::InternalServerError
when 501 then Octokit::NotImplemented
when 502 then Octokit::BadGateway
when 503 then Octokit::ServiceUnavailable
when 500..599 then Octokit::ServerError
end
klass.new(response)
end
end
def build_error_context
if RATE_LIMITED_ERRORS.include?(self.class)
@context = Octokit::RateLimit.from_response(@response)
end
end
def initialize(response = nil)
@response = response
super(build_error_message)
build_error_context
end
# Documentation URL returned by the API for some errors
#
# @return [String]
def documentation_url
data[:documentation_url] if data.is_a? Hash
end
# Returns most appropriate error for 401 HTTP status code
# @private
# rubocop:disable Naming/VariableNumber
def self.error_for_401(headers)
# rubocop:enbale Naming/VariableNumber
if Octokit::OneTimePasswordRequired.required_header(headers)
Octokit::OneTimePasswordRequired
else
Octokit::Unauthorized
end
end
# Returns most appropriate error for 403 HTTP status code
# @private
def self.error_for_403(body)
# rubocop:enable Naming/VariableNumber
case body
when /rate limit exceeded/i, /exceeded a secondary rate limit/i
Octokit::TooManyRequests
when /login attempts exceeded/i
Octokit::TooManyLoginAttempts
when /(returns|for) blobs (up to|between) [0-9-]+ MB/i
Octokit::TooLargeContent
when /abuse/i
Octokit::AbuseDetected
when /repository access blocked/i
Octokit::RepositoryUnavailable
when /email address must be verified/i
Octokit::UnverifiedEmail
when /account was suspended/i
Octokit::AccountSuspended
when /billing issue/i
Octokit::BillingIssue
when /Resource protected by organization SAML enforcement/i
Octokit::SAMLProtected
when /suspended your access|This installation has been suspended/i
Octokit::InstallationSuspended
else
Octokit::Forbidden
end
end
# Return most appropriate error for 404 HTTP status code
# @private
# rubocop:disable Naming/VariableNumber
def self.error_for_404(body)
# rubocop:enable Naming/VariableNumber
if body =~ /Branch not protected/i
Octokit::BranchNotProtected
else
Octokit::NotFound
end
end
# Return most appropriate error for 422 HTTP status code
# @private
# rubocop:disable Naming/VariableNumber
def self.error_for_422(body)
# rubocop:enable Naming/VariableNumber
if body =~ /PullRequestReviewComment/i && body =~ /(commit_id|end_commit_oid) is not part of the pull request/i
Octokit::CommitIsNotPartOfPullRequest
elsif body =~ /Path diff too large/i
Octokit::PathDiffTooLarge
else
Octokit::UnprocessableEntity
end
end
# Array of validation errors
# @return [Array<Hash>] Error info
def errors
if data.is_a?(Hash)
data[:errors] || []
else
[]
end
end
# Status code returned by the GitHub server.
#
# @return [Integer]
def response_status
@response[:status]
end
# Headers returned by the GitHub server.
#
# @return [Hash]
def response_headers
@response[:response_headers]
end
# Body returned by the GitHub server.
#
# @return [String]
def response_body
@response[:body]
end
private
def data
@data ||=
if (body = @response[:body]) && !body.empty?
if body.is_a?(String) &&
@response[:response_headers] &&
@response[:response_headers][:content_type] =~ /json/
Sawyer::Agent.serializer.decode(body)
else
body
end
end
end
def response_message
case data
when Hash
data[:message]
when String
data
end
end
def response_error
"Error: #{data[:error]}" if data.is_a?(Hash) && data[:error]
end
def response_error_summary
return nil unless data.is_a?(Hash) && !Array(data[:errors]).empty?
summary = +"\nError summary:\n"
summary << data[:errors].map do |error|
if error.is_a? Hash
error.map { |k, v| " #{k}: #{v}" }
else
" #{error}"
end
end.join("\n")
summary
end
def build_error_message
return nil if @response.nil?
message = +"#{@response[:method].to_s.upcase} "
message << "#{redact_url(@response[:url].to_s.dup)}: "
message << "#{@response[:status]} - "
message << response_message.to_s unless response_message.nil?
message << response_error.to_s unless response_error.nil?
message << response_error_summary.to_s unless response_error_summary.nil?
message << " // See: #{documentation_url}" unless documentation_url.nil?
message
end
def redact_url(url_string)
%w[client_secret access_token api_key].each do |token|
if url_string.include? token
url_string.gsub!(/#{token}=\S+/, "#{token}=(redacted)")
end
end
url_string
end
end
# Raised on errors in the 400-499 range
class ClientError < Error; end
# Raised when GitHub returns a 400 HTTP status code
class BadRequest < ClientError; end
# Raised when GitHub returns a 401 HTTP status code
class Unauthorized < ClientError; end
# Raised when GitHub returns a 401 HTTP status code
# and headers include "X-GitHub-OTP"
class OneTimePasswordRequired < ClientError
# @private
OTP_DELIVERY_PATTERN = /required; (\w+)/i.freeze
# @private
def self.required_header(headers)
OTP_DELIVERY_PATTERN.match headers['X-GitHub-OTP'].to_s
end
# Delivery method for the user's OTP
#
# @return [String]
def password_delivery
@password_delivery ||= delivery_method_from_header
end
private
def delivery_method_from_header
if match = self.class.required_header(@response[:response_headers])
match[1]
end
end
end
# Raised when GitHub returns a 403 HTTP status code
class Forbidden < ClientError; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'rate limit exceeded'
class TooManyRequests < Forbidden; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'login attempts exceeded'
class TooManyLoginAttempts < Forbidden; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'returns blobs up to [0-9]+ MB'
class TooLargeContent < Forbidden; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'abuse'
class AbuseDetected < Forbidden; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'repository access blocked'
class RepositoryUnavailable < Forbidden; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'email address must be verified'
class UnverifiedEmail < Forbidden; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'account was suspended'
class AccountSuspended < Forbidden; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'billing issue'
class BillingIssue < Forbidden; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'Resource protected by organization SAML enforcement'
class SAMLProtected < Forbidden; end
# Raised when GitHub returns a 403 HTTP status code
# and body matches 'suspended your access'
class InstallationSuspended < Forbidden; end
# Raised when GitHub returns a 404 HTTP status code
class NotFound < ClientError; end
# Raised when GitHub returns a 404 HTTP status code
# and body matches 'Branch not protected'
class BranchNotProtected < ClientError; end
# Raised when GitHub returns a 405 HTTP status code
class MethodNotAllowed < ClientError; end
# Raised when GitHub returns a 406 HTTP status code
class NotAcceptable < ClientError; end
# Raised when GitHub returns a 409 HTTP status code
class Conflict < ClientError; end
# Raised when GitHub returns a 414 HTTP status code
class UnsupportedMediaType < ClientError; end
# Raised when GitHub returns a 422 HTTP status code
class UnprocessableEntity < ClientError; end
# Raised when GitHub returns a 422 HTTP status code
# and body matches 'PullRequestReviewComment' and 'commit_id (or end_commit_oid) is not part of the pull request'
class CommitIsNotPartOfPullRequest < UnprocessableEntity; end
# Raised when GitHub returns a 422 HTTP status code and body matches 'Path diff too large'.
# It could occur when attempting to post review comments on a "too large" file.
class PathDiffTooLarge < UnprocessableEntity; end
# Raised when GitHub returns a 451 HTTP status code
class UnavailableForLegalReasons < ClientError; end
# Raised on errors in the 500-599 range
class ServerError < Error; end
# Raised when GitHub returns a 500 HTTP status code
class InternalServerError < ServerError; end
# Raised when GitHub returns a 501 HTTP status code
class NotImplemented < ServerError; end
# Raised when GitHub returns a 502 HTTP status code
class BadGateway < ServerError; end
# Raised when GitHub returns a 503 HTTP status code
class ServiceUnavailable < ServerError; end
# Raised when client fails to provide valid Content-Type
class MissingContentType < ArgumentError; end
# Raised when a method requires an application client_id
# and secret but none is provided
class ApplicationCredentialsRequired < StandardError; end
# Raised when a repository is created with an invalid format
class InvalidRepository < ArgumentError; end
RATE_LIMITED_ERRORS = [Octokit::TooManyRequests, Octokit::AbuseDetected].freeze
end
@@ -0,0 +1,35 @@
# frozen_string_literal: true
module Octokit
# Class to parse and create Gist URLs
class Gist
# !@attribute id
# @return [String] Gist ID
attr_accessor :id
# Instantiate {Gist} object from Gist URL
# @ return [Gist]
def self.from_url(url)
Gist.new(URI.parse(url).path[1..])
end
def initialize(gist)
case gist
when Integer, String
@id = gist.to_s
end
end
# Gist ID
# @return [String]
def to_s
@id
end
# Gist URL
# @return [String]
def url
"https://gist.github.com/#{@id}"
end
end
end
@@ -0,0 +1,135 @@
# frozen_string_literal: true
require 'faraday'
require 'set'
# Adapted from lostisland/faraday_middleware. Trimmed down to just the logic
# that we need for octokit.rb.
#
# https://github.com/lostisland/faraday_middleware/blob/138766e/lib/faraday_middleware/response/follow_redirects.rb
module Octokit
module Middleware
# Public: Exception thrown when the maximum amount of requests is exceeded.
class RedirectLimitReached < Faraday::ClientError
attr_reader :response
def initialize(response)
super "too many redirects; last one to: #{response['location']}"
@response = response
end
end
# Public: Follow HTTP 301, 302, 303, and 307 redirects.
#
# For HTTP 303, the original GET, POST, PUT, DELETE, or PATCH request gets
# converted into a GET. For HTTP 301, 302, and 307, the HTTP method remains
# unchanged.
#
# This middleware currently only works with synchronous requests; i.e. it
# doesn't support parallelism.
class FollowRedirects < Faraday::Middleware
# HTTP methods for which 30x redirects can be followed
ALLOWED_METHODS = Set.new %i[head options get post put patch delete]
# HTTP redirect status codes that this middleware implements
REDIRECT_CODES = Set.new [301, 302, 303, 307]
# Keys in env hash which will get cleared between requests
ENV_TO_CLEAR = Set.new %i[status response response_headers]
# Default value for max redirects followed
FOLLOW_LIMIT = 3
# Regex that matches characters that need to be escaped in URLs, sans
# the "%" character which we assume already represents an escaped
# sequence.
URI_UNSAFE = %r{[^\-_.!~*'()a-zA-Z\d;/?:@&=+$,\[\]%]}.freeze
# Public: Initialize the middleware.
#
# options - An options Hash (default: {}):
# :limit - A Integer redirect limit (default: 3).
def initialize(app, options = {})
super(app)
@options = options
@convert_to_get = Set.new [303]
end
def call(env)
perform_with_redirection(env, follow_limit)
end
private
def convert_to_get?(response)
!%i[head options].include?(response.env[:method]) &&
@convert_to_get.include?(response.status)
end
def perform_with_redirection(env, follows)
request_body = env[:body]
response = @app.call(env)
response.on_complete do |response_env|
if follow_redirect?(response_env, response)
raise(RedirectLimitReached, response) if follows.zero?
new_request_env = update_env(response_env, request_body, response)
response = perform_with_redirection(new_request_env, follows - 1)
end
end
response
end
def update_env(env, request_body, response)
original_url = env[:url]
env[:url] += safe_escape(response['location'])
unless same_host?(original_url, env[:url])
# HACK: Faraday’s Authorization middlewares don’t touch the request if the `Authorization` header is set.
# This is a workaround to drop authentication info.
# See https://github.com/octokit/octokit.rb/pull/1359#issuecomment-925609697
env[:request_headers]['Authorization'] = 'dummy'
end
if convert_to_get?(response)
env[:method] = :get
env[:body] = nil
else
env[:body] = request_body
end
ENV_TO_CLEAR.each { |key| env.delete(key) }
env
end
def follow_redirect?(env, response)
ALLOWED_METHODS.include?(env[:method]) &&
REDIRECT_CODES.include?(response.status)
end
def follow_limit
@options.fetch(:limit, FOLLOW_LIMIT)
end
def same_host?(original_url, redirect_url)
original_uri = Addressable::URI.parse(original_url)
redirect_uri = Addressable::URI.parse(redirect_url)
redirect_uri.host.nil? || original_uri.host == redirect_uri.host
end
# Internal: Escapes unsafe characters from a URL which might be a path
# component only or a fully-qualified URI so that it can be joined onto a
# URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not
# risk double-escaping.
def safe_escape(uri)
uri.to_s.gsub(URI_UNSAFE) do |match|
"%#{match.unpack('H2' * match.bytesize).join('%').upcase}"
end
end
end
end
end
@@ -0,0 +1,19 @@
# frozen_string_literal: true
module Octokit
# GitHub organization class to generate API path urls
class Organization
# Get the api path for an organization
#
# @param org [String, Integer] GitHub organization login or id
# @return [String] Organization Api path
def self.path(org)
case org
when String
"orgs/#{org}"
when Integer
"organizations/#{org}"
end
end
end
end
@@ -0,0 +1,35 @@
# frozen_string_literal: true
module Octokit
# Class for API Rate Limit info
#
# @!attribute [w] limit
# @return [Integer] Max tries per rate limit period
# @!attribute [w] remaining
# @return [Integer] Remaining tries per rate limit period
# @!attribute [w] resets_at
# @return [Time] Indicates when rate limit resets
# @!attribute [w] resets_in
# @return [Integer] Number of seconds when rate limit resets
#
# @see https://developer.github.com/v3/#rate-limiting
class RateLimit < Struct.new(:limit, :remaining, :resets_at, :resets_in)
# Get rate limit info from HTTP response
#
# @param response [#headers] HTTP response
# @return [RateLimit]
def self.from_response(response)
info = new
headers = response.headers if response.respond_to?(:headers) && !response.headers.nil?
headers ||= response.response_headers if response.respond_to?(:response_headers) && !response.response_headers.nil?
if headers
info.limit = (headers['X-RateLimit-Limit'] || 1).to_i
info.remaining = (headers['X-RateLimit-Remaining'] || 1).to_i
info.resets_at = Time.at((headers['X-RateLimit-Reset'] || Time.now).to_i)
info.resets_in = [(info.resets_at - Time.now).to_i, 0].max
end
info
end
end
end
@@ -0,0 +1,18 @@
# frozen_string_literal: true
module Octokit
# Class to extract options from Ruby arguments for
# Repository-related methods
class RepoArguments < Arguments
# !@attribute [r] repo
# @return [Repository]
attr_reader :repo
def initialize(args)
arguments = super(args)
@repo = arguments.shift
arguments
end
end
end
@@ -0,0 +1,95 @@
# frozen_string_literal: true
module Octokit
# Class to parse GitHub repository owner and name from
# URLs and to generate URLs
class Repository
attr_accessor :owner, :name, :id
NAME_WITH_OWNER_PATTERN = %r{\A[\w.-]+/[\w.-]+\z}i.freeze
# Instantiate from a GitHub repository URL
#
# @return [Repository]
def self.from_url(url)
new URI.parse(url).path[1..]
.gsub(%r{^repos/}, '')
.split('/', 3)[0..1]
.join('/')
end
# @raise [Octokit::InvalidRepository] if the repository
# has an invalid format
def initialize(repo)
case repo
when Integer
@id = repo
when NAME_WITH_OWNER_PATTERN
@owner, @name = repo.split('/')
when Repository
@owner = repo.owner
@name = repo.name
when Hash
@name = repo[:repo] || repo[:name]
@owner = repo[:owner] || repo[:user] || repo[:username]
else
raise_invalid_repository!(repo)
end
validate_owner_and_name!(repo) if @owner && @name
end
# Repository owner/name
# @return [String]
def slug
"#{@owner}/#{@name}"
end
alias to_s slug
# @return [String] Repository API path
def path
return named_api_path if @owner && @name
return id_api_path if @id
end
# Get the api path for a repo
# @param repo [Integer, String, Hash, Repository] A GitHub repository.
# @return [String] Api path.
def self.path(repo)
new(repo).path
end
# @return [String] Api path for owner/name identified repos
def named_api_path
"repos/#{slug}"
end
# @return [String] Api path for id identified repos
def id_api_path
"repositories/#{@id}"
end
# Repository URL based on {Octokit::Client#web_endpoint}
# @return [String]
def url
"#{Octokit.web_endpoint}#{slug}"
end
alias user owner
alias username owner
alias repo name
private
def validate_owner_and_name!(repo)
if @owner.include?('/') || @name.include?('/') || !url.match(URI::ABS_URI)
raise_invalid_repository!(repo)
end
end
def raise_invalid_repository!(repo)
msg = "#{repo.inspect} is invalid as a repository identifier. " \
'Use the user/repo (String) format, or the repository ID (Integer), or a hash containing :repo and :user keys.'
raise Octokit::InvalidRepository, msg
end
end
end
@@ -0,0 +1,10 @@
# frozen_string_literal: true
require 'faraday'
module Octokit
module Response
# In Faraday 2.x, Faraday::Response::Middleware was removed
BaseMiddleware = defined?(Faraday::Response::Middleware) ? Faraday::Response::Middleware : Faraday::Middleware
end
end
@@ -0,0 +1,17 @@
# frozen_string_literal: true
require 'octokit/response/base_middleware'
module Octokit
module Response
# Parses RSS and Atom feed responses.
class FeedParser < BaseMiddleware
def on_complete(env)
if env[:response_headers]['content-type'] =~ /(\batom|\brss)/
require 'rss'
env[:body] = RSS::Parser.parse env[:body]
end
end
end
end
end
@@ -0,0 +1,19 @@
# frozen_string_literal: true
require 'octokit/response/base_middleware'
require 'octokit/error'
module Octokit
# Faraday response middleware
module Response
# This class raises an Octokit-flavored exception based
# HTTP status codes returned by the API
class RaiseError < BaseMiddleware
def on_complete(response)
if error = Octokit::Error.from_response(response)
raise error
end
end
end
end
end
@@ -0,0 +1,21 @@
# frozen_string_literal: true
module Octokit
# GitHub user class to generate API path urls
class User
# Get the api path for a user
#
# @param user [String, Integer] GitHub user login or id
# @return [String] User Api path
def self.path(user)
case user
when String
"users/#{user}"
when Integer
"user/#{user}"
else
'user'
end
end
end
end
@@ -0,0 +1,19 @@
# frozen_string_literal: true
module Octokit
# Current major release.
# @return [Integer]
MAJOR = 6
# Current minor release.
# @return [Integer]
MINOR = 1
# Current patch level.
# @return [Integer]
PATCH = 1
# Full release version.
# @return [String]
VERSION = [MAJOR, MINOR, PATCH].join('.').freeze
end
@@ -0,0 +1,16 @@
# frozen_string_literal: true
module Octokit
# Allows warnings to be suppressed via environment variable.
module Warnable
module_function
# Wrapper around Kernel#warn to print warnings unless
# OCTOKIT_SILENT is set to true.
#
# @return [nil]
def octokit_warn(*message)
warn message unless ENV['OCTOKIT_SILENT']
end
end
end