linked_issue.rb 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class GitLab
  3. class LinkedIssue
  4. STATES_MAPPING = {
  5. 'opened' => 'open'
  6. }.freeze
  7. QUERY = <<-GRAPHQL.freeze
  8. query($fullpath: ID!, $issue_id: String) {
  9. project(fullPath: $fullpath) {
  10. issue(iid: $issue_id) {
  11. iid
  12. title
  13. state
  14. milestone {
  15. title
  16. }
  17. assignees {
  18. edges {
  19. node {
  20. name
  21. }
  22. }
  23. }
  24. labels {
  25. edges {
  26. node {
  27. title
  28. color
  29. textColor
  30. description
  31. }
  32. }
  33. }
  34. }
  35. }
  36. }
  37. GRAPHQL
  38. attr_reader :client
  39. def initialize(client)
  40. @client = client
  41. end
  42. def find_by(url)
  43. @result = query_by_url(url)
  44. return if @result.blank?
  45. to_h.merge(url: url)
  46. end
  47. private
  48. def to_h
  49. {
  50. id: @result['iid'],
  51. title: @result['title'],
  52. icon_state: STATES_MAPPING.fetch(@result['state'], @result['state']),
  53. milestone: milestone,
  54. assignees: assignees,
  55. labels: labels,
  56. }
  57. end
  58. def assignees
  59. @result['assignees']['edges'].map do |assignee|
  60. assignee['node']['name']
  61. end
  62. end
  63. def labels
  64. @result['labels']['edges'].map do |label|
  65. {
  66. text_color: label['node']['textColor'],
  67. color: label['node']['color'],
  68. title: label['node']['title']
  69. }
  70. end
  71. end
  72. def milestone
  73. @result.dig('milestone', 'title')
  74. end
  75. def query_by_url(url)
  76. variables = variables(url)
  77. return if variables.blank?
  78. response = client.perform(
  79. query: GitLab::LinkedIssue::QUERY,
  80. variables: variables
  81. )
  82. response.dig('data', 'project', 'issue')
  83. end
  84. def variables(url)
  85. if url !~ %r{^https?://([^/]+)/(.*)/-/issues/(\d+)$}
  86. raise Exceptions::UnprocessableEntity, __('Invalid GitLab issue link format')
  87. end
  88. host = $1
  89. fullpath = $2
  90. id = $3
  91. if client.endpoint_path.present?
  92. fullpath.sub!(client.endpoint_path, '')
  93. end
  94. if client.endpoint.exclude?(host)
  95. raise Exceptions::UnprocessableEntity, "Issue link doesn't match configured GitLab endpoint '#{client.endpoint}'"
  96. end
  97. {
  98. fullpath: fullpath,
  99. issue_id: id
  100. }
  101. end
  102. end
  103. end