class Gitlab::QA::Report::GitlabIssueClient

The GitLab client is used for API access: github.com/NARKOZ/gitlab

def abort_not_permitted

def abort_not_permitted
  abort "You must have at least Maintainer access to the project to use this feature."
end

def add_note_to_issue_discussion_as_thread(iid:, discussion_id:, body:)

def add_note_to_issue_discussion_as_thread(iid:, discussion_id:, body:)
  handle_gitlab_client_exceptions do
    Gitlab.add_note_to_issue_discussion_as_thread(project, iid, discussion_id, body: body)
  end
end

def assert_user_permission!

def assert_user_permission!
  handle_gitlab_client_exceptions do
    user = Gitlab.user
    member = Gitlab.team_member(project, user.id)
    abort_not_permitted if member.access_level < MAINTAINER_ACCESS_LEVEL
  end
rescue Gitlab::Error::NotFound
  abort_not_permitted
end

def configure_gitlab_client

def configure_gitlab_client
  Gitlab.configure do |config|
    config.endpoint = Runtime::Env.gitlab_api_base
    config.private_token = token
  end
end

def create_issue(title:, description:, labels:)

def create_issue(title:, description:, labels:)
  attrs = { description: description, labels: labels }
  handle_gitlab_client_exceptions do
    Gitlab.create_issue(project, title, attrs)
  end
end

def create_issue_note(iid:, note:)

def create_issue_note(iid:, note:)
  handle_gitlab_client_exceptions do
    Gitlab.create_issue_note(project, iid, note)
  end
end

def edit_issue(iid:, options: {})

def edit_issue(iid:, options: {})
  handle_gitlab_client_exceptions do
    Gitlab.edit_issue(project, iid, options)
  end
end

def find_issue_discussions(iid:)

def find_issue_discussions(iid:)
  handle_gitlab_client_exceptions do
    Gitlab.issue_discussions(project, iid, order_by: 'created_at', sort: 'asc').auto_paginate
  end
end

def find_issues(iid: nil, options: {}, &select)

def find_issues(iid: nil, options: {}, &select)
  select ||= :itself
  handle_gitlab_client_exceptions do
    return [Gitlab.issue(project, iid)] if iid
    Gitlab.issues(project, options)
      .auto_paginate
      .select(&select)
  end
end

def handle_gitlab_client_exceptions

def handle_gitlab_client_exceptions
  yield
rescue Gitlab::Error::NotFound
  # This error could be raised in assert_user_permission!
  # If so, we want it to terminate at that point
  raise
rescue SystemCallError, OpenSSL::SSL::SSLError, Net::OpenTimeout, Net::ReadTimeout, Gitlab::Error::InternalServerError, Gitlab::Error::Parsing => e
  @retry_backoff += RETRY_BACK_OFF_DELAY
  raise if @retry_backoff > RETRY_BACK_OFF_DELAY * MAX_RETRY_ATTEMPTS
  warn_exception(e)
  warn("Sleeping for #{@retry_backoff} seconds before retrying...")
  sleep @retry_backoff
  retry
rescue StandardError => e
  pipeline = QA::Runtime::Env.pipeline_from_project_name
  channel = pipeline == "canary" ? "qa-production" : "qa-#{pipeline}"
  error_msg = warn_exception(e)
  return unless QA::Runtime::Env.ci_commit_ref_name == 'master'
  slack_options = {
    channel: channel,
    icon_emoji: ':ci_failing:',
    message: <<~MSG
      An unexpected error occurred while reporting test results in issues.
      The error occurred in job: #{QA::Runtime::Env.ci_job_url}
      `#{error_msg}`
    MSG
  }
  puts "Posting Slack message to channel: #{channel}"
  Gitlab::QA::Slack::PostToSlack.new(**slack_options).invoke!
end

def initialize(token:, project:)

def initialize(token:, project:)
  @token = token
  @project = project
  @retry_backoff = 0
  configure_gitlab_client
end

def warn_exception(error)

def warn_exception(error)
  error_msg = "#{error.class.name} #{error.message}"
  warn(error_msg)
  error_msg
end