Class: Hubstats::GithubAPI

Inherits:
Object
  • Object
show all
Includes:
HubHelper
Defined in:
lib/hubstats/github_api.rb

Class Method Summary collapse

Methods included from HubHelper

comment_setup, get_pull_number, pull_setup

Class Method Details

.add_labels(repo) ⇒ Object

Public - Gets all the labels for a repo, adds all labels to a pull

repo - the particular repository, you want to add labels to



213
214
215
216
217
# File 'lib/hubstats/github_api.rb', line 213

def self.add_labels(repo)
  get_labels(repo).each do |label|
    inline(repo.full_name,'issues', labels: label.name, state: 'all')
  end
end

.client(options = {}) ⇒ Object

Public - Checks that the options passed in are valid and configured correctly

options - the options to be checked or an empty hash

Returns - the new configured info



28
29
30
31
32
33
# File 'lib/hubstats/github_api.rb', line 28

def self.client(options = {})
  configure(Hubstats.config.github_auth) if @@auth_info.nil?
  ent = Octokit::Client.new(@@auth_info.merge(options))
  ent.user #making sure it was configured properly
  return ent
end

.configure(options = {}) ⇒ Object

Public - configures the information needed to receive webhooks from GitHub

options - the options to be passed in or an empty hash

Returns - the configured auth_info



12
13
14
15
16
17
18
19
20
21
# File 'lib/hubstats/github_api.rb', line 12

def self.configure(options = {})
  @@auth_info = {}
  if access_token = ENV['GITHUB_API_TOKEN'] || options["access_token"]
    @@auth_info[:access_token] = access_token
  else
    @@auth_info[:client_id] = ENV['CLIENT_ID'] || options["client_id"]
    @@auth_info[:client_secret] = ENV['CLIENT_SECRET'] || options["client_secret"]
  end
  @@auth_info
end

.create_org_hook(org_name) ⇒ Object

Public - Makes a new webhook from an organization

org_name - the name of the organization that is attempting to have a hook made with

Returns - the hook and a message (or just a message and no hook)



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/hubstats/github_api.rb', line 160

def self.create_org_hook(org_name)
  begin
    client.create_org_hook(
      org_name,
      {
        :url => Hubstats.config.webhook_endpoint,
        :content_type => 'json',
        :secret => Hubstats.config.webhook_secret
      },
      {
        :events => ['membership', 'repository', 'team'],
        :active => true
      }
    )
    puts "Hook on #{org_name} successfully created"
  rescue Octokit::UnprocessableEntity
    puts "Hook on #{org_name} already existed"
  rescue Octokit::NotFound
    puts "You don't have sufficient privileges to add an event hook to #{org_name}"
  end
end

.create_repo_hook(repo) ⇒ Object

Public - Makes a new webhook from a repository

repo - the repository that is attempting to have a hook made with

Returns - the hook and a message (or just a message and no hook)



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/hubstats/github_api.rb', line 130

def self.create_repo_hook(repo)
  repo_name = repo[:full_name] ? repo[:full_name] : repo.full_name
  puts "Repo that we're going to make a hook on: #{repo_name}"
  begin
    client.create_hook(
      repo_name,
      'web',
      {
        :url => Hubstats.config.webhook_endpoint,
        :content_type => 'json',
        :secret => Hubstats.config.webhook_secret
      },
      {
        :events => ['pull_request', 'pull_request_review_comment', 'commit_comment', 'issues', 'issue_comment'],
        :active => true
      }
    )
    puts "Hook on #{repo_name} successfully created"
  rescue Octokit::UnprocessableEntity
    puts "Hook on #{repo_name} already existed"
  rescue Octokit::NotFound
    puts "You don't have sufficient privileges to add an event hook to #{repo_name}"
  end
end

.get_labels(repo) ⇒ Object

Public - gets labels for a particular label

repo - a repo github object

Returns - all the labels for a given repo



187
188
189
190
191
192
193
194
195
196
197
# File 'lib/hubstats/github_api.rb', line 187

def self.get_labels(repo)
  labels = []
  octo = Hubstats::GithubAPI.client({:auto_paginate => true})
  github_labels = octo.labels(repo.full_name)
  github_labels.each do |label|
    label_hash = label.to_h if label.respond_to? :to_h
    label_data = label_hash.slice(*Hubstats::Label.column_names.map(&:to_sym))
    labels << Hubstats::Label.where(:name => label_data[:name]).first_or_create(label_data)
  end
  labels
end

.get_labels_for_pull(repo_name, pull_request_number) ⇒ Object

Public - gets the label for a given pull request

repo_name - a the repo_name pull_request_number - the number of the pull_request you want labels of

Returns - the issue



205
206
207
208
# File 'lib/hubstats/github_api.rb', line 205

def self.get_labels_for_pull(repo_name, pull_request_number)
  issue = client.issue(repo_name, pull_request_number)
  issue[:labels]
end

.get_reposObject

Public - Gets repos found in configuration file

Returns - an array of github repo objects



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/hubstats/github_api.rb', line 54

def self.get_repos
  if Hubstats.config.github_config.has_key?("org_name") == false
    raise RuntimeError, "COULD NOT COMPLETE RAKE TASK! Organization name in .octokit.yml is required, but was not found."
  end

  if Hubstats.config.github_config.has_key?("repo_list")
    repos = []
    Hubstats.config.github_config["repo_list"].each do |repo|
      repos << client.repository(repo)
    end
  elsif Hubstats.config.github_config.has_key?("org_name")
    repos = client.organization_repositories(Hubstats.config.github_config["org_name"])
  end
  repos
end

.inline(repo_name, kind, options = {}) ⇒ Object

Public - Gets all of a specific kind from a repo, and processes them.

repo_name - the name of a repo kind - a kind of object (pull,comment) options - any possible option a particular kind of object

Returns an array of that particular kind



42
43
44
45
46
47
48
49
# File 'lib/hubstats/github_api.rb', line 42

def self.inline(repo_name, kind, options = {})
  path = ["repos",repo_name,kind].join('/')
  octo = client({:auto_paginate => true})
  octo.paginate(path, options) do |data, last_response|
    last_response.data.each{|v| route(v,kind,repo_name)}.clear
    wait_limit(false, 1, octo.rate_limit)
  end.each{|v| route(v,kind,repo_name)}.clear
end

.route(object, kind, repo_name = nil) ⇒ Object

Public - Routes to the correct setup methods to be used to update or create comments or PRs

object - the new thing to be updated or created kind - the type of thing (pull comment, issue comment, normal comment, pull, or issue) repo_name - the name of the repository to which object belongs (optional)

Returns - nothing, but does update the object



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/hubstats/github_api.rb', line 242

def self.route(object, kind, repo_name = nil)
  if kind == "pulls/comments"
    repo = Hubstats::Repo.where(full_name: repo_name).first
    Hubstats::Comment.create_or_update(HubHelper.comment_setup(object,repo.id,"PullRequest"))
  elsif kind == "issues/comments"
    repo = Hubstats::Repo.where(full_name: repo_name).first
    Hubstats::Comment.create_or_update(HubHelper.comment_setup(object,repo.id,"Issue"))
  elsif kind == "comments"
    repo = Hubstats::Repo.where(full_name: repo_name).first
    Hubstats::Comment.create_or_update(HubHelper.comment_setup(object,repo.id,"Commit"))
  elsif kind == "pulls"
    Hubstats::PullRequest.create_or_update(HubHelper.pull_setup(object))
  elsif kind == "issues"
    if object[:pull_request]
      repo = Hubstats::Repo.where(full_name: repo_name).first
      pull_request = Hubstats::PullRequest.where(repo_id: repo.id).where(number: object[:number]).first
      pull_request.add_labels(object[:labels])
    end
  end
end

.update_pullsObject

Public - Gets extra information on pull requests, e.g. size, additions …

Returns - nothing



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/hubstats/github_api.rb', line 73

def self.update_pulls
  grab_size = 250
  begin
    while Hubstats::PullRequest.where(deletions: nil).where(additions: nil).count > 0
      client = Hubstats::GithubAPI.client
      pull_requests = Hubstats::PullRequest.where(deletions: nil).where(additions: nil).limit(grab_size)

      pull_requests.each do |pull|
        repo = Hubstats::Repo.where(id: pull.repo_id).first
        pr = client.pull_request(repo.full_name, pull.number)
        Hubstats::PullRequest.create_or_update(HubHelper.pull_setup(pr))
      end
      wait_limit(false, grab_size, client.rate_limit)
    end
    puts "All Pull Requests are up to date"
  rescue Faraday::ConnectionFailed
    puts "Connection Timeout, restarting pull request updating"
    update_pulls
  end
end

.update_teamsObject

Public - Gets information on teams, e.g. name

Returns - nothing



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/hubstats/github_api.rb', line 97

def self.update_teams
  grab_size = 250
  begin
    Octokit.auto_paginate = true
    client = Hubstats::GithubAPI.client
    all_teams_in_org = client.organization_teams(Hubstats.config.github_config["org_name"])

    all_teams_in_org.each do |team|
      if Hubstats::Team.designed_for_hubstats?(team[:description])
        puts "Making a team"
        Hubstats::Team.create_or_update(team)
        users = client.team_members(team[:id])
        users.each do |user|
          hubstats_team = Hubstats::Team.where(name: team[:name]).first
          hubstats_user = Hubstats::User.create_or_update(user)
          puts "Adding a user to a team"
          Hubstats::Team.update_users_in_team(hubstats_team, hubstats_user, "added")
        end
      end
    end
    wait_limit(false, grab_size, client.rate_limit)
    puts "All teams are up to date"
  rescue Faraday::ConnectionFailed
    puts "Connection Timeout, restarting team updating"
    update_teams
  end
end

.wait_limit(force, grab_size = nil, rate_limit = nil) ⇒ Object

Public - Puts the process to sleep if there is a “timeout” before continuing

grab_size - the amount of data that is being attempted to grab rate_limit - the amount of time to wait to grab data

Returns - nothing



225
226
227
228
229
230
231
232
233
# File 'lib/hubstats/github_api.rb', line 225

def self.wait_limit(force, grab_size=nil, rate_limit=nil)
  rate_limit = client.rate_limit unless rate_limit
  grab_size = 250 unless grab_size

  if force || rate_limit.remaining < grab_size
    puts "We don't want to hit the GitHub wait limit; waiting #{Time.at(rate_limit.resets_in).utc.strftime("%H:%M:%S")} to get more"
    sleep(rate_limit.resets_in)
  end
end