Class: GitReflow::GitServer::GitHub

Inherits:
Base
  • Object
show all
Extended by:
GitReflow::GitHelpers
Includes:
Sandbox
Defined in:
lib/git_reflow/git_server/git_hub.rb,
lib/git_reflow/git_server/git_hub/pull_request.rb

Defined Under Namespace

Classes: PullRequest

Constant Summary

Constants included from Sandbox

Sandbox::COLOR_FOR_LABEL

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from GitReflow::GitHelpers

append_to_merge_commit_message, current_branch, default_base_branch, default_editor, fetch_destination, get_first_commit_message, git_editor_command, git_root_dir, merge_commit_template, merge_message_path, pull_request_template, push_current_branch, remote_repo_name, remote_user, update_current_branch, update_destination, update_feature_branch

Methods included from Sandbox

#run, #run_command_with_label, #say

Methods inherited from Base

project_only?

Constructor Details

#initialize(config_options = {}) ⇒ GitHub

Returns a new instance of GitHub.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/git_reflow/git_server/git_hub.rb', line 14

def initialize(config_options = {})
  project_only     = !!config_options.delete(:project_only)
  using_enterprise = !!config_options.delete(:enterprise)

  gh_site_url     = self.class.site_url
  gh_api_endpoint = self.class.api_endpoint

  if using_enterprise
    gh_site_url     = ask("Please enter your Enterprise site URL (e.g. https://github.company.com):")
    gh_api_endpoint = ask("Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):")
  end

  self.class.site_url     = gh_site_url
  self.class.api_endpoint = gh_api_endpoint

  # We remove any existing setup first, then setup our required config settings
  GitReflow::Config.unset('reflow.local-projects', value: "#{self.class.remote_user}/#{self.class.remote_repo_name}")
  GitReflow::Config.add('reflow.local-projects', "#{self.class.remote_user}/#{self.class.remote_repo_name}") if project_only
  GitReflow::Config.set('reflow.git-server', 'GitHub', local: project_only)
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.



12
13
14
# File 'lib/git_reflow/git_server/git_hub.rb', line 12

def connection
  @connection
end

Class Method Details

.api_endpointObject



62
63
64
65
# File 'lib/git_reflow/git_server/git_hub.rb', line 62

def self.api_endpoint
  endpoint         = "#{GitReflow::Config.get('github.endpoint')}".strip
  (endpoint.length > 0) ? endpoint : ::Github.endpoint
end

.api_endpoint=(api_endpoint) ⇒ Object



67
68
69
70
# File 'lib/git_reflow/git_server/git_hub.rb', line 67

def self.api_endpoint=(api_endpoint)
  GitReflow::Config.set("github.endpoint", api_endpoint, local: project_only?)
  api_endpoint
end

.connectionObject



35
36
37
38
39
40
41
42
43
# File 'lib/git_reflow/git_server/git_hub.rb', line 35

def self.connection
  if self.oauth_token.length > 0
    @connection ||= ::Github.new do |config|
      config.oauth_token = GitServer::GitHub.oauth_token
      config.endpoint    = GitServer::GitHub.api_endpoint
      config.site        = GitServer::GitHub.site_url
    end
  end
end

.oauth_tokenObject



53
54
55
# File 'lib/git_reflow/git_server/git_hub.rb', line 53

def self.oauth_token
  GitReflow::Config.get('github.oauth-token')
end

.oauth_token=(oauth_token) ⇒ Object



57
58
59
60
# File 'lib/git_reflow/git_server/git_hub.rb', line 57

def self.oauth_token=(oauth_token)
  GitReflow::Config.set('github.oauth-token', oauth_token, local: project_only?)
  oauth_token
end

.site_urlObject



72
73
74
75
# File 'lib/git_reflow/git_server/git_hub.rb', line 72

def self.site_url
  site_url     = "#{GitReflow::Config.get('github.site')}".strip
  (site_url.length > 0) ? site_url : ::Github.site
end

.site_url=(site_url) ⇒ Object



77
78
79
80
# File 'lib/git_reflow/git_server/git_hub.rb', line 77

def self.site_url=(site_url)
  GitReflow::Config.set("github.site", site_url, local: project_only?)
  site_url
end

.userObject



45
46
47
# File 'lib/git_reflow/git_server/git_hub.rb', line 45

def self.user
  GitReflow::Config.get('github.user')
end

.user=(github_user) ⇒ Object



49
50
51
# File 'lib/git_reflow/git_server/git_hub.rb', line 49

def self.user=(github_user)
  GitReflow::Config.set('github.user', github_user, local: project_only?)
end

Instance Method Details

#authenticate(options = {silent: false}) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
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
124
125
126
127
128
129
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/git_reflow/git_server/git_hub.rb', line 86

def authenticate(options = {silent: false})
  if !options[:user].to_s.empty?
    self.class.user = options[:user]
  elsif self.class.user.empty?
    self.class.user = ask("Please enter your GitHub username: ")
  end

  if connection and self.class.oauth_token.length > 0
    begin
      connection.users.get
      unless options[:silent]
        GitReflow.say "Your GitHub account was already setup with: "
        GitReflow.say "\tUser Name: #{self.class.user}"
        GitReflow.say "\tEndpoint: #{self.class.api_endpoint}"
      end
      return connection
    rescue ::Github::Error::Unauthorized => e
      GitReflow.logger.debug "[GitHub Error] Current oauth-token is invalid or expired..."
    end
  end

  begin
    gh_password = options[:password] || ask("Please enter your GitHub password (we do NOT store this): ") { |q| q.echo = false }

    @connection = ::Github.new do |config|
      config.basic_auth = "#{self.class.user}:#{gh_password}"
      config.endpoint   = GitServer::GitHub.api_endpoint
      config.site       = GitServer::GitHub.site_url
      config.adapter    = :net_http
    end

    @connection.connection_options = {headers: {"X-GitHub-OTP" => options[:two_factor_auth_code]}} if options[:two_factor_auth_code]

    previous_authorizations = @connection.oauth.all.select {|auth| auth.note == "git-reflow (#{run('hostname', loud: false).strip})" }
    if previous_authorizations.any?
      authorization = previous_authorizations.last
      GitReflow.say "You have previously setup git-reflow on this machine, but we can no longer find the stored token.", :error
      GitReflow.say "Please visit https://github.com/settings/tokens and delete the token for: git-reflow (#{run('hostname', loud: false).strip})", :notice
      raise "Setup could not be completed."
    else
      authorization = @connection.oauth.create scopes: ['repo'], note: "git-reflow (#{run('hostname', loud: false).strip})"
    end

    self.class.oauth_token = authorization.token

  rescue ::Github::Error::Unauthorized => e
    if e.inspect.to_s.include?('two-factor')
      begin
        # dummy request to trigger a 2FA SMS since a HTTP GET won't do it
        @connection.oauth.create scopes: ['repo'], note: "thank Github for not making this straightforward"
      rescue ::Github::Error::Unauthorized
      ensure
        two_factor_code = ask("Please enter your two-factor authentication code: ")
        self.authenticate options.merge({user: self.class.user, password: gh_password, two_factor_auth_code: two_factor_code})
      end
    else
      GitReflow.say "Github Authentication Error: #{e.inspect}", :error
      raise "Setup could not be completed."
    end
  rescue StandardError => e
    raise "We were unable to authenticate with Github."
  else
    GitReflow.say "Your GitHub account was successfully setup!", :success

  end

  @connection
end

#colorized_build_description(state, description) ⇒ Object



159
160
161
162
163
164
165
166
# File 'lib/git_reflow/git_server/git_hub.rb', line 159

def colorized_build_description(state, description)
  colorized_statuses = {
    pending: :yellow,
    success: :green,
    error: :red,
    failure: :red }
  description.colorize( colorized_statuses[state.to_sym] )
end

#create_pull_request(options = {}) ⇒ Object



168
169
170
# File 'lib/git_reflow/git_server/git_hub.rb', line 168

def create_pull_request(options = {})
  PullRequest.create(options)
end

#find_open_pull_request(options = {}) ⇒ Object



172
173
174
# File 'lib/git_reflow/git_server/git_hub.rb', line 172

def find_open_pull_request(options = {})
  PullRequest.find_open(options)
end

#get_build_status(sha) ⇒ Object



155
156
157
# File 'lib/git_reflow/git_server/git_hub.rb', line 155

def get_build_status(sha)
  connection.repos.statuses.all(self.class.remote_user, self.class.remote_repo_name, sha).first
end