Class: Aireview::GitlabClient

Inherits:
Object
  • Object
show all
Defined in:
lib/aireview/gitlab_client.rb

Constant Summary collapse

OPEN_TIMEOUT =
10
READ_TIMEOUT =
30
NOTES_PER_PAGE =
100
NOTES_PAGE_LIMIT =
100
JOBS_PER_PAGE =
100
JOBS_PAGE_LIMIT =
100

Instance Method Summary collapse

Constructor Details

#initialize(base_url:, token:, logger: Logger.new($stderr), connection: nil) ⇒ GitlabClient

Returns a new instance of GitlabClient.

Raises:



14
15
16
17
18
19
20
21
22
23
# File 'lib/aireview/gitlab_client.rb', line 14

def initialize(base_url:, token:, logger: Logger.new($stderr), connection: nil)
  require 'faraday'

  raise ConfigError, 'GitLab base URL is required' if Aireview::Utils.blank?(base_url)
  raise ConfigError, 'GitLab token is required' if Aireview::Utils.blank?(token)

  @logger = logger
  @token = token
  @connection = connection || build_connection(base_url)
end

Instance Method Details

#fetch_current_user ⇒ Object



34
35
36
# File 'lib/aireview/gitlab_client.rb', line 34

def fetch_current_user
  get_json('user')
end

#fetch_merge_request(project_id, iid) ⇒ Object



25
26
27
# File 'lib/aireview/gitlab_client.rb', line 25

def fetch_merge_request(project_id, iid)
  get_json("projects/#{project_id}/merge_requests/#{iid}")
end

#fetch_merge_request_changes(project_id, iid) ⇒ Object



29
30
31
32
# File 'lib/aireview/gitlab_client.rb', line 29

def fetch_merge_request_changes(project_id, iid)
  payload = get_json("projects/#{project_id}/merge_requests/#{iid}/changes")
  Array(payload['changes'])
end

#fetch_merge_request_notes(project_id, iid) ⇒ Object

Notes come in pages sorted by creation time, and updating a comment does not move it up in that order: on a long MR our review is far from the first page. Stopping the walk silently is not an option — with an incomplete list the review would decide the note is missing and create a second one, so the limit fails with an error. The order is explicit: it decides which old unmarked note the review picks up, and the API default is not to be relied on here.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/aireview/gitlab_client.rb', line 65

def fetch_merge_request_notes(project_id, iid)
  notes = []
  page = 1

  loop do
    batch = Array(
      get_json(
        "projects/#{project_id}/merge_requests/#{iid}/notes",
        order_by: 'created_at', sort: 'desc', per_page: NOTES_PER_PAGE, page: page
      )
    )
    notes.concat(batch)
    break if batch.size < NOTES_PER_PAGE

    page += 1
    next unless page > NOTES_PAGE_LIMIT

    raise ApiError, "Merge request has more than #{NOTES_PAGE_LIMIT * NOTES_PER_PAGE} notes"
  end

  notes
end

#post_merge_request_note(project_id, iid, body) ⇒ Object



88
89
90
# File 'lib/aireview/gitlab_client.rb', line 88

def post_merge_request_note(project_id, iid, body)
  post_json("projects/#{project_id}/merge_requests/#{iid}/notes", body: body)
end

#retried_job?(project_id, job_id) ⇒ Boolean

A Retry creates a new job in the same pipeline. Earlier attempts are visible only with include_retried; a new CI_JOB_ID alone happens after an ordinary push too.

Returns:

  • (Boolean)

Raises:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/aireview/gitlab_client.rb', line 41

def retried_job?(project_id, job_id)
  current = get_json("projects/#{project_id}/jobs/#{job_id}")
  validate_retry_job!(current, pipeline: true)
  path = "projects/#{project_id}/pipelines/#{current.fetch('pipeline').fetch('id')}/jobs"

  (1..JOBS_PAGE_LIMIT).each do |page|
    jobs = get_json(path, include_retried: true, per_page: JOBS_PER_PAGE, page: page)
    raise ApiError, 'GitLab Jobs API returned an invalid jobs list' unless jobs.is_a?(Array)

    jobs.each { |job| validate_retry_job!(job) }
    return true if jobs.any? { |job| previous_attempt?(job, current) }
    return false if jobs.size < JOBS_PER_PAGE
  end

  raise ApiError, 'Too many pipeline jobs to determine whether this job is a retry'
end

#update_merge_request_note(project_id, iid, note_id, body) ⇒ Object



92
93
94
# File 'lib/aireview/gitlab_client.rb', line 92

def update_merge_request_note(project_id, iid, note_id, body)
  put_json("projects/#{project_id}/merge_requests/#{iid}/notes/#{note_id}", body: body)
end