Class: Tefoji::JiraApi
- Inherits:
-
Object
- Object
- Tefoji::JiraApi
- Includes:
- Logging
- Defined in:
- lib/tefoji/jira_api.rb
Overview
An interface to send API request to Jira using the rest-client gem. Contained here are the bits of knowledge necessary to form API calls to Jira.
Direct Known Subclasses
Constant Summary collapse
- FIELD_ACCOUNT_ID =
Jira field keys
'accountId'
- FIELD_ID =
'id'
- FIELD_KEY =
'key'
- FIELD_NAME =
'name'
- FIELD_VALUE =
'value'
- ISSUE_EPIC =
Issue type constants
'Epic'
- ISSUE_NEW_FEATURE =
'New Feature'
- ISSUE_SUB_TASK =
'Sub-task'
- ISSUE_TASK =
'Task'
Instance Attribute Summary collapse
-
#jira_base_rest_url ⇒ Object
readonly
Returns the value of attribute jira_base_rest_url.
-
#jira_base_url ⇒ Object
readonly
Returns the value of attribute jira_base_url.
-
#jira_username ⇒ Object
readonly
Returns the value of attribute jira_username.
-
#log_level ⇒ Object
Returns the value of attribute log_level.
-
#logger ⇒ Object
Returns the value of attribute logger.
Instance Method Summary collapse
-
#add_issue_to_epic(epic_issue, issue_to_add) ⇒ Object
Use greehopper to add an issue to an epic.
- #add_watcher(issue_key, watcher_name) ⇒ Object
-
#authenticate(jira_base_url, requested_user = nil, jira_auth = nil) ⇒ Object
Depending on how user specified their authorization we want to derive and store the username and the Base64-encoded ‘username:application-token’ string.
-
#create_issue(issue_data) ⇒ Object
Create a Jira issue.
-
#get_components(project) ⇒ Object
Get information about user in Jira.
- #get_transition_id(issue_key, status) ⇒ Object
-
#get_username(username, fail_if_not_found = true) ⇒ Object
Get information about user in Jira.
- #link_issues(inward_issue, outward_issue, type = 'Blocks') ⇒ Object
- #retrieve_issue(issue_url) ⇒ Object
-
#save_authentication(save_file_name) ⇒ Object
Save authentication YAML to the a file for reuse.
-
#test_authentication ⇒ Object
Do this so we can inform the user quickly that their credentials didn’t work There may be a better test, but this is the one the original Winston uses.
-
#transition(issue_key, status) ⇒ Object
Used to set issue items related to transitions.
-
#user_email_to_account_id(user_email) ⇒ Object
jira cloud api calls require an accountId rather than a username.
-
#user_name_to_account_name(user_name) ⇒ Object
Jira on-prem used user names (‘eric.griswold’, ‘tefoji’, etc.) to identify users.
Methods included from Logging
Instance Attribute Details
#jira_base_rest_url ⇒ Object (readonly)
Returns the value of attribute jira_base_rest_url.
12 13 14 |
# File 'lib/tefoji/jira_api.rb', line 12 def jira_base_rest_url @jira_base_rest_url end |
#jira_base_url ⇒ Object (readonly)
Returns the value of attribute jira_base_url.
12 13 14 |
# File 'lib/tefoji/jira_api.rb', line 12 def jira_base_url @jira_base_url end |
#jira_username ⇒ Object (readonly)
Returns the value of attribute jira_username.
12 13 14 |
# File 'lib/tefoji/jira_api.rb', line 12 def jira_username @jira_username end |
#log_level ⇒ Object
Returns the value of attribute log_level.
12 13 14 |
# File 'lib/tefoji/jira_api.rb', line 12 def log_level @log_level end |
#logger ⇒ Object
Returns the value of attribute logger.
13 14 15 |
# File 'lib/tefoji/jira_api.rb', line 13 def logger @logger end |
Instance Method Details
#add_issue_to_epic(epic_issue, issue_to_add) ⇒ Object
Use greehopper to add an issue to an epic. See the comments around the #greenhopper_put method for more explanation.
137 138 139 140 141 142 143 144 145 146 |
# File 'lib/tefoji/jira_api.rb', line 137 def add_issue_to_epic(epic_issue, issue_to_add) epic_key = epic_issue[FIELD_KEY] issue_key = issue_to_add[FIELD_KEY] request_path = "epics/#{epic_key}/add" request_data = { 'ignoreEpics' => true, 'issueKeys' => [issue_key] } greenhopper_put(request_path, request_data) end |
#add_watcher(issue_key, watcher_name) ⇒ Object
173 174 175 176 177 |
# File 'lib/tefoji/jira_api.rb', line 173 def add_watcher(issue_key, watcher_name) request_path = "issue/#{issue_key}/watchers" watcher_id = user_email_to_account_id(watcher_name) jira_post(request_path, watcher_id) end |
#authenticate(jira_base_url, requested_user = nil, jira_auth = nil) ⇒ Object
Depending on how user specified their authorization we want to derive and store the username and the Base64-encoded ‘username:application-token’ string.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/tefoji/jira_api.rb', line 39 def authenticate(jira_base_url, requested_user = nil, jira_auth = nil) @jira_base_url = jira_base_url @jira_base_rest_url = "#{jira_base_url}/rest/api/2" @logger.info "Using Jira instance: \"#{jira_base_url}\"" # If we found an auth string, try to use it. Allow the requested_user # to override and send us to prompt decoded_auth = nil unless jira_auth.nil? auth_user, auth_application_token = Base64.decode64(jira_auth).split(':') # Only set decoded auth if the user name in the auth string matches the # requested user name unless requested_user && requested_user != auth_user decoded_auth = [auth_user, auth_application_token] end end # If there was no auth string or the requested user didn't match the auth string # prompt for details as needed. if decoded_auth.nil? decoded_auth = [] decoded_auth[0] = requested_user if requested_user.nil? print 'Enter jira user name: ' decoded_auth[0] = $stdin.gets.chomp end decoded_auth[1] = IO.console.getpass( "Enter jira application_token for #{decoded_auth[0]}: " ) end @jira_username = decoded_auth[0] # HTTP doesn't like linefeeds in the auth string, hence #strict_encode64 @jira_auth = Base64.strict_encode64(decoded_auth.join(':')) @authentication_header = { 'Authorization' => "Basic #{@jira_auth}" } end |
#create_issue(issue_data) ⇒ Object
Create a Jira issue
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/tefoji/jira_api.rb', line 117 def create_issue(issue_data) request_path = 'issue' jira_fields = issue_data_to_jira_fields(issue_data) jira_post(request_path, jira_fields) rescue RestClient::Forbidden fatal "Forbidden: could not send #{request_path} request to Jira. " \ 'Jira may not be accepting requests.' rescue RestClient::BadRequest => e error_json = JSON.parse(e.response.body) errors = error_json['errors'].values.join("\n") fatal "Bad Request: something went wrong with this #{request_path} request: " \ "#{request_path}, #{jira_fields}\n" \ "Errors were: #{errors}" rescue RestClient::Unauthorized fatal "Unauthorized: could not send #{request_path} request to Jira. " \ 'Did you use the correct credentials?' end |
#get_components(project) ⇒ Object
Get information about user in Jira
94 95 96 97 |
# File 'lib/tefoji/jira_api.rb', line 94 def get_components(project) search_parameters = "project/#{project}/components" jira_get(search_parameters) end |
#get_transition_id(issue_key, status) ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/tefoji/jira_api.rb', line 211 def get_transition_id(issue_key, status) transitions_request_path = "issue/#{issue_key}/transitions" response = jira_get(transitions_request_path) fatal "Transitions data not found for issue: \"#{issue_key}\"" if response.empty? downcased_status = status.downcase transitions_data = response['transitions'] transition = transitions_data.find { |transition_data| transition_data['name'].downcase == downcased_status } if transition.nil? warn "No transition ID found for issue: \"#{issue_key}\" status: \"#{status}\"\n \ available transitions: #{transitions_data}" return nil end transition_id = transition['id'] @logger.debug("issue: \"#{issue_key}\" status: \"#{status}\"" \ "converted to transition ID: \"#{transition_id}\"") return transition_id.to_i end |
#get_username(username, fail_if_not_found = true) ⇒ Object
Get information about user in Jira
88 89 90 91 |
# File 'lib/tefoji/jira_api.rb', line 88 def get_username(username, fail_if_not_found = true) search_parameters = "user/search?query=#{username}" jira_get(search_parameters, fail_if_not_found) end |
#link_issues(inward_issue, outward_issue, type = 'Blocks') ⇒ Object
152 153 154 155 156 157 158 159 160 |
# File 'lib/tefoji/jira_api.rb', line 152 def link_issues(inward_issue, outward_issue, type = 'Blocks') request_path = 'issueLink' request_data = { 'type' => { 'name' => type }, 'inwardIssue' => { 'key' => inward_issue }, 'outwardIssue' => { 'key' => outward_issue } } jira_post(request_path, request_data) end |
#retrieve_issue(issue_url) ⇒ Object
148 149 150 |
# File 'lib/tefoji/jira_api.rb', line 148 def retrieve_issue(issue_url) jira_get(issue_url) end |
#save_authentication(save_file_name) ⇒ Object
Save authentication YAML to the a file for reuse.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/tefoji/jira_api.rb', line 100 def save_authentication(save_file_name) backup_file_name = "#{save_file_name}.bak" if File.readable?(save_file_name) FileUtils.cp(save_file_name, backup_file_name) @logger.info "Saved #{save_file_name} to #{backup_file_name}" end jira_auth = "jira-auth: #{@jira_auth}\n" File.write(save_file_name, jira_auth) File.chmod(0o600, save_file_name) @logger.info "Saved Jira authentication to #{save_file_name}" end |
#test_authentication ⇒ Object
Do this so we can inform the user quickly that their credentials didn’t work There may be a better test, but this is the one the original Winston uses
80 81 82 83 84 85 |
# File 'lib/tefoji/jira_api.rb', line 80 def test_authentication get_username(@jira_username) rescue RestClient::Forbidden fatal 'Forbidden: either the authentication is incorrect or ' \ 'Jira might be requiring a CAPTCHA response from the web interface.' end |
#transition(issue_key, status) ⇒ Object
Used to set issue items related to transitions. Right now, only used for ‘status’ transitions.
164 165 166 167 168 169 170 |
# File 'lib/tefoji/jira_api.rb', line 164 def transition(issue_key, status) request_path = "issue/#{issue_key}/transitions" request_data = { 'transition' => { 'id' => status } } jira_post(request_path, request_data) end |
#user_email_to_account_id(user_email) ⇒ Object
jira cloud api calls require an accountId rather than a username. This method will convert emails or display names to accountIds.
196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/tefoji/jira_api.rb', line 196 def user_email_to_account_id(user_email) account_name = user_name_to_account_name(user_email) response = get_username(account_name) fatal "Jira account ID not found for \"#{account_name}\"" if response.empty? account_id = response[0]['accountId'] @logger.debug("user account name: \"#{account_name} \" " \ "converted to account ID: \"#{account_id}\"") return account_id if account_id fatal "Jira account ID not found for #{account_name}" end |
#user_name_to_account_name(user_name) ⇒ Object
Jira on-prem used user names (‘eric.griswold’, ‘tefoji’, etc.) to identify users. Jira cloud requires an ‘@domain.extension’ suffix. Handle translating from the onprem form to the cloud form. Nothe the special case of the tefoji service user.
183 184 185 186 187 188 189 190 191 192 |
# File 'lib/tefoji/jira_api.rb', line 183 def user_name_to_account_name(user_name) case user_name when 'tefoji' '[email protected]' when %r{URI::MailTo::EMAIL_REGEXP} user_name else "#{user_name.gsub(%r{@.*}, '')}@perforce.com" end end |