Class: RailsErrorDashboard::Services::GitLabIssueClient

Inherits:
IssueTrackerClient show all
Defined in:
lib/rails_error_dashboard/services/gitlab_issue_client.rb

Overview

GitLab REST API client for issue management.

API Docs: docs.gitlab.com/api/issues/ Auth: Personal access token or project access token Project ID: URL-encoded path (“user%2Frepo”) or numeric ID

Constant Summary

Constants inherited from IssueTrackerClient

IssueTrackerClient::MAX_BODY_LENGTH, IssueTrackerClient::REQUEST_TIMEOUT

Instance Attribute Summary

Attributes inherited from IssueTrackerClient

#api_url, #repo, #token

Instance Method Summary collapse

Methods inherited from IssueTrackerClient

for, from_config

Constructor Details

#initialize(token:, repo:, api_url: nil) ⇒ GitLabIssueClient

Returns a new instance of GitLabIssueClient.



11
12
13
14
15
# File 'lib/rails_error_dashboard/services/gitlab_issue_client.rb', line 11

def initialize(token:, repo:, api_url: nil)
  super
  @api_url = api_url || "https://gitlab.com/api/v4"
  @encoded_repo = URI.encode_www_form_component(@repo)
end

Instance Method Details

#add_comment(number:, body:) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rails_error_dashboard/services/gitlab_issue_client.rb', line 52

def add_comment(number:, body:)
  response = http_post(
    "#{@api_url}/projects/#{@encoded_repo}/issues/#{number}/notes",
    { body: truncate_body(body) },
    auth_headers
  )

  if response[:status] == 201
    # GitLab notes don't have a direct URL — construct from issue URL + note anchor
    note_id = response[:body]["id"]
    issue_url = "#{@api_url.sub("/api/v4", "")}/#{@repo}/-/issues/#{number}#note_#{note_id}"
    success_response(url: issue_url)
  else
    error_response("GitLab API error (#{response[:status]})")
  end
end

#close_issue(number:) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/rails_error_dashboard/services/gitlab_issue_client.rb', line 32

def close_issue(number:)
  response = http_put(
    "#{@api_url}/projects/#{@encoded_repo}/issues/#{number}",
    { state_event: "close" },
    auth_headers
  )

  response[:status] == 200 ? success_response({}) : error_response("GitLab API error (#{response[:status]})")
end

#create_issue(title:, body:, labels: []) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rails_error_dashboard/services/gitlab_issue_client.rb', line 17

def create_issue(title:, body:, labels: [])
  response = http_post(
    "#{@api_url}/projects/#{@encoded_repo}/issues",
    { title: title, description: truncate_body(body), labels: labels.join(",") },
    auth_headers
  )

  if response[:status] == 201
    data = response[:body]
    success_response(url: data["web_url"], number: data["iid"])
  else
    error_response("GitLab API error (#{response[:status]}): #{response[:body]&.dig("message") || response[:error]}")
  end
end

#fetch_comments(number:, per_page: 10) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/rails_error_dashboard/services/gitlab_issue_client.rb', line 69

def fetch_comments(number:, per_page: 10)
  response = http_get(
    "#{@api_url}/projects/#{@encoded_repo}/issues/#{number}/notes?per_page=#{per_page}&sort=desc",
    auth_headers
  )

  if response[:status] == 200
    comments = (response[:body] || []).reject { |n| n["system"] }.map { |n|
      {
        author: n.dig("author", "username"),
        avatar_url: n.dig("author", "avatar_url"),
        body: n["body"],
        created_at: n["created_at"],
        url: nil # GitLab notes don't have individual URLs in API response
      }
    }
    success_response(comments: comments)
  else
    error_response("GitLab API error (#{response[:status]})")
  end
end

#fetch_issue(number:) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/rails_error_dashboard/services/gitlab_issue_client.rb', line 91

def fetch_issue(number:)
  response = http_get(
    "#{@api_url}/projects/#{@encoded_repo}/issues/#{number}",
    auth_headers
  )

  if response[:status] == 200
    data = response[:body]
    success_response(
      state: data["state"],
      title: data["title"],
      assignees: (data["assignees"] || []).map { |a|
        { login: a["username"], avatar_url: a["avatar_url"] }
      },
      labels: (data["labels"] || []).map { |l|
        { name: l, color: nil }
      }
    )
  else
    error_response("GitLab API error (#{response[:status]})")
  end
end

#reopen_issue(number:) ⇒ Object



42
43
44
45
46
47
48
49
50
# File 'lib/rails_error_dashboard/services/gitlab_issue_client.rb', line 42

def reopen_issue(number:)
  response = http_put(
    "#{@api_url}/projects/#{@encoded_repo}/issues/#{number}",
    { state_event: "reopen" },
    auth_headers
  )

  response[:status] == 200 ? success_response({}) : error_response("GitLab API error (#{response[:status]})")
end