class OrganizationAudit::Repo

Constants

HOST

Public Class Methods

all(organization: nil, user: nil, max_pages: nil, token: nil) click to toggle source
# File lib/organization_audit/repo.rb, line 45
def self.all(organization: nil, user: nil, max_pages: nil, token: nil)
  user = if organization
    "orgs/#{organization}"
  elsif user
    "users/#{user}"
  else
    "user"
  end
  url = File.join(HOST, user, "repos")

  download_all_pages(url, headers(token), max_pages: max_pages).map { |data| Repo.new(data, token) }
end
new(data, token=nil) click to toggle source
# File lib/organization_audit/repo.rb, line 20
def initialize(data, token=nil)
  @data = data
  @token = token
end

Private Class Methods

download_all_pages(url, headers, max_pages: nil) click to toggle source
# File lib/organization_audit/repo.rb, line 114
def self.download_all_pages(url, headers, max_pages: nil)
  results = []
  page = 1
  loop do
    response = http_get("#{url}?page=#{page}", headers)
    result = JSON.parse(response)
    results.concat(result)

    break if result.size == 0 || (max_pages && page >= max_pages) # stop on empty page or over max
    page += 1
  end
  results
end
headers(token) click to toggle source
# File lib/organization_audit/repo.rb, line 194
def self.headers(token)
  token ? {"Authorization" => "token #{token}"} : {}
end
http_get(url, headers) click to toggle source
# File lib/organization_audit/repo.rb, line 128
def self.http_get(url, headers)
  tries = 3
  tries.times do |i|
    uri = URI(url)
    request = Net::HTTP::Get.new(uri, headers)
    http = Net::HTTP.new(uri.hostname, uri.port)
    http.use_ssl = true if uri.instance_of? URI::HTTPS
    response =
      begin
        http.start { |http| http.request(request) }
      rescue
        raise RequestError.new("#{$!.class} error during request #{url}", url)
      end

    return response.body if response.code == '200'

    # github sends 403 with 0-limit header when rate limit is exceeded
    if i < (tries - 1) && response["x-ratelimit-remaining"] == "0"
      wait = Integer(response["x-ratelimit-reset"]) - Time.now.to_i
      warn "Github rate limit exhausted, retrying in #{wait}"
      sleep wait + 60 # wait more in case our time drifts
    else
      raise RequestError.new("HTTP get error, retried #{i} times", url, response.code, response.body)
    end
  end
end

Public Instance Methods

clone_url() click to toggle source
# File lib/organization_audit/repo.rb, line 84
def clone_url
  if private?
    url.sub("https://", "git@").sub("/", ":") + ".git"
  else
    url + ".git"
  end
end
content(file) click to toggle source
# File lib/organization_audit/repo.rb, line 58
def content(file)
  (@content ||= {})[file] ||= begin
    if private?
      download_content_via_api(file)
    else
      download_content_via_raw(file)
    end
  end
rescue RequestError => e
  raise unless e.code == 404
end
directory?(folder) click to toggle source
# File lib/organization_audit/repo.rb, line 96
def directory?(folder)
  !!list(File.dirname(folder)).detect { |f| f["path"] == folder && f["type"] == "dir" }
end
file_list(dir=".") click to toggle source
# File lib/organization_audit/repo.rb, line 92
def file_list(dir=".")
  list(dir).select { |f| f["type"] == "file" }.map { |file| file["path"] }
end
gem?() click to toggle source
# File lib/organization_audit/repo.rb, line 25
def gem?
  !!gemspec_file
end
gemspec_content() click to toggle source
# File lib/organization_audit/repo.rb, line 29
def gemspec_content
  content(gemspec_file) if gem?
end
last_commiter() click to toggle source
# File lib/organization_audit/repo.rb, line 78
def last_commiter
  response = call_api("commits/#{branch}")
  committer = response["commit"]["committer"]
  "#{committer["name"]} <#{committer["email"]}>"
end
name() click to toggle source
# File lib/organization_audit/repo.rb, line 41
def name
  api_url.split("/").last
end
private?() click to toggle source
# File lib/organization_audit/repo.rb, line 70
def private?
  @data["private"]
end
public?() click to toggle source
# File lib/organization_audit/repo.rb, line 74
def public?
  !private?
end
to_s() click to toggle source
# File lib/organization_audit/repo.rb, line 37
def to_s
  "#{url} -- #{last_commiter}"
end
url() click to toggle source
# File lib/organization_audit/repo.rb, line 33
def url
  api_url.sub("api.", "").sub("/repos", "")
end

Private Instance Methods

api_url() click to toggle source
# File lib/organization_audit/repo.rb, line 159
def api_url
  @data["url"]
end
branch() click to toggle source
# File lib/organization_audit/repo.rb, line 155
def branch
  @data["default_branch"] || @data["master_branch"] || "master"
end
call_api(path) click to toggle source
# File lib/organization_audit/repo.rb, line 173
def call_api(path)
  content = download(File.join(api_url, path), self.class.headers(@token))
  JSON.load(content)
end
download(url, headers={}) click to toggle source
# File lib/organization_audit/repo.rb, line 183
def download(url, headers={})
  self.class.http_get(url, headers)
rescue RequestError => e
  if e.message.include? "Timeout"
    retries ||= 0
    retries += 1
    retry if retries < 3
  end
  raise e
end
download_content_via_api(file) click to toggle source

increases api rate limit

# File lib/organization_audit/repo.rb, line 168
def download_content_via_api(file)
  content = call_api("contents/#{file}?branch=#{branch}").fetch("content")
  Base64.decode64(content)
end
download_content_via_raw(file) click to toggle source

unlimited

# File lib/organization_audit/repo.rb, line 179
def download_content_via_raw(file)
  download(File.join(raw_url, branch, file))
end
gemspec_file() click to toggle source
# File lib/organization_audit/repo.rb, line 110
def gemspec_file
  file_list.grep(/\.gemspec$/).first
end
list(dir) click to toggle source
# File lib/organization_audit/repo.rb, line 102
def list(dir)
  (@list ||= {})[dir] ||= begin
    call_api("contents/#{dir == "." ? "" : dir}?branch=#{branch}")
  rescue RequestError => e
    e.code == 404 ? [] : raise
  end
end
raw_url() click to toggle source
# File lib/organization_audit/repo.rb, line 163
def raw_url
  url.dup.sub!("://github.com", "://raw.githubusercontent.com") || raise("Unable to determine raw url for #{url}")
end