Class: Abt::Providers::Devops::Api

Inherits:
Object
  • Object
show all
Defined in:
lib/abt/providers/devops/api.rb

Constant Summary collapse

VERBS =
[:get, :post, :put].freeze
CONDITIONAL_ACCESS_POLICY_ERROR_CODE =
"VS403463"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(organization_name:, username:, access_token:, cli:) ⇒ Api

Returns a new instance of Api.



21
22
23
24
25
26
# File 'lib/abt/providers/devops/api.rb', line 21

def initialize(organization_name:, username:, access_token:, cli:)
  @organization_name = organization_name
  @username = username
  @access_token = access_token
  @cli = cli
end

Instance Attribute Details

#access_tokenObject (readonly)

Returns the value of attribute access_token.



19
20
21
# File 'lib/abt/providers/devops/api.rb', line 19

def access_token
  @access_token
end

#cliObject (readonly)

Returns the value of attribute cli.



19
20
21
# File 'lib/abt/providers/devops/api.rb', line 19

def cli
  @cli
end

#organization_nameObject (readonly)

Returns the value of attribute organization_name.



19
20
21
# File 'lib/abt/providers/devops/api.rb', line 19

def organization_name
  @organization_name
end

#project_nameObject (readonly)

Returns the value of attribute project_name.



19
20
21
# File 'lib/abt/providers/devops/api.rb', line 19

def project_name
  @project_name
end

#usernameObject (readonly)

Returns the value of attribute username.



19
20
21
# File 'lib/abt/providers/devops/api.rb', line 19

def username
  @username
end

Class Method Details

.rfc_3986_encode_path_segment(string) ⇒ Object

Shamelessly copied from ERB::Util.url_encode apidock.com/ruby/ERB/Util/url_encode



9
10
11
12
13
# File 'lib/abt/providers/devops/api.rb', line 9

def self.rfc_3986_encode_path_segment(string)
  string.to_s.b.gsub(/[^a-zA-Z0-9_\-.~]/) do |match|
    format("%%%02X", match.unpack1("C"))
  end
end

Instance Method Details

#base_urlObject



67
68
69
# File 'lib/abt/providers/devops/api.rb', line 67

def base_url
  "https://#{organization_name}.visualstudio.com"
end

#connectionObject



91
92
93
94
95
96
97
# File 'lib/abt/providers/devops/api.rb', line 91

def connection
  @connection ||= Faraday.new(base_url) do |connection|
    connection.basic_auth(username, access_token)
    connection.headers["Content-Type"] = "application/json"
    connection.headers["Accept"] = "application/json; api-version=6.0"
  end
end

#get_paged(path, query = {}) ⇒ Object



34
35
36
37
38
39
# File 'lib/abt/providers/devops/api.rb', line 34

def get_paged(path, query = {})
  result = request(:get, path, query)
  result["value"]

  # TODO: Loop if necessary
end

#request(*args) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/abt/providers/devops/api.rb', line 53

def request(*args)
  response = connection.public_send(*args)

  if response.success?
    Oj.load(response.body)
  else
    error_class = Abt::HttpError.error_class_for_status(response.status)
    encoded_response_body = response.body.force_encoding("utf-8")
    raise error_class, "Code: #{response.status}, body: #{encoded_response_body}"
  end
rescue Abt::HttpError::ForbiddenError => e
  handle_denied_by_conditional_access_policy!(e)
end

#sanitize_work_item(work_item) ⇒ Object



81
82
83
84
85
86
87
88
89
# File 'lib/abt/providers/devops/api.rb', line 81

def sanitize_work_item(work_item)
  return nil if work_item.nil?

  work_item.merge(
    "id" => work_item["id"].to_s,
    "name" => work_item["fields"]["System.Title"],
    "url" => url_for_work_item(work_item)
  )
end

#url_for_board(project_name, team_name, board) ⇒ Object



76
77
78
79
# File 'lib/abt/providers/devops/api.rb', line 76

def url_for_board(project_name, team_name, board)
  board_name = self.class.rfc_3986_encode_path_segment(board["name"])
  "#{base_url}/#{project_name}/_boards/board/t/#{team_name}/#{board_name}"
end

#url_for_work_item(work_item) ⇒ Object



71
72
73
74
# File 'lib/abt/providers/devops/api.rb', line 71

def url_for_work_item(work_item)
  project_name = self.class.rfc_3986_encode_path_segment(work_item["fields"]["System.TeamProject"])
  "#{base_url}/#{project_name}/_workitems/edit/#{work_item['id']}"
end

#work_item_query(wiql) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/abt/providers/devops/api.rb', line 41

def work_item_query(wiql)
  response = post("_apis/wit/wiql", Oj.dump({ query: wiql }, mode: :json))
  ids = response["workItems"].map { |work_item| work_item["id"] }

  work_items = []
  ids.each_slice(200) do |page_ids|
    work_items += get_paged("_apis/wit/workitems", ids: page_ids.join(","))
  end

  work_items
end