Class: Geordi::LinearClient

Inherits:
Object
  • Object
show all
Defined in:
lib/geordi/linear_client.rb

Constant Summary collapse

API_ENDPOINT =
'https://api.linear.app/graphql'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeLinearClient

Returns a new instance of LinearClient.



34
35
36
37
# File 'lib/geordi/linear_client.rb', line 34

def initialize
  self.highline = HighLine.new
  self.settings = Settings.new
end

Class Method Details

.extract_issue_ids(strings) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/geordi/linear_client.rb', line 14

def self.extract_issue_ids(strings)
  found_ids = []

  regex = /^\[[A-Z]+\d*-\d+\]/

  strings&.each do |string|
    string&.scan(regex) do |match|
      found_ids << match
    end
  end

  found_ids.map { |id| id.delete('[]') } # [W-365] => W-365
end

.filter_by_issue_ids(list_of_strings, issue_ids) ⇒ Object



28
29
30
31
32
# File 'lib/geordi/linear_client.rb', line 28

def self.filter_by_issue_ids(list_of_strings, issue_ids)
  list_of_strings.select do |message|
    issue_ids.any? { |id| message.start_with?("[#{id}]") }
  end
end

Instance Method Details

#choose_issueObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/geordi/linear_client.rb', line 39

def choose_issue
  if Util.testing?
    return dummy_issue_for_testing
  end

  issues = fetch_linear_issues
  if issues.empty?
    Geordi::Interaction.fail('No issues to offer.')
  end
  issues.sort_by! { |i| -i.dig('state', 'position') }

  highline.choose do |menu|
    max_label_length = 60
    menu.header = 'Choose a started issue (ordered by state)'

    issues.each do |issue|
      id = issue['identifier']
      title = issue['title']
      state = issue['state']['name']
      assignee = issue.dig('assignee', 'displayName') || 'unassigned'

      label = "[#{id}] #{title}"
      label = "#{label[0..(max_label_length - 5)]} ..." if label.length > max_label_length
      label = HighLine::BLUE + HighLine::BOLD + label + HighLine::RESET if issue.dig('assignee', 'isMe')
      label = "#{label} (#{assignee} / #{state})"

      menu.choice(label) { return issue }
    end

    menu.hidden('') { Interaction.fail('No issue selected.') }
  end

  # Selecting an issue will return that issue. If we ever get here, return
  # nothing
  nil
end

#filter_existing_issue_ids(identifiers) ⇒ Object



76
77
78
79
80
# File 'lib/geordi/linear_client.rb', line 76

def filter_existing_issue_ids(identifiers)
  return identifiers if Util.testing?
  issues = fetch_linear_issues
  identifiers.select { |id| issues.any? { |i| i['identifier'] == id } }
end

#issue_from_branchObject



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/geordi/linear_client.rb', line 103

def issue_from_branch
  issue = if Util.testing?
    dummy_issue_for_testing if ENV['GEORDI_TESTING_ISSUE_MATCHES'] == 'true'
  else
    current_branch = Git.current_branch
    fetch_linear_issues.find { |issue| issue['branchName'] == current_branch }
  end

  if issue
    id = issue['identifier']
    title = issue['title']

    Interaction.note 'Auto-detected issue from branch name:'
    puts HighLine::BOLD + "[#{id}] #{title}" + HighLine::RESET

    issue if Interaction.prompt('Use it?', 'y', /y|yes/i)
  end
end

#move_issues_to_state(issue_identifiers, state) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/geordi/linear_client.rb', line 82

def move_issues_to_state(issue_identifiers, state)
  return if Util.testing?

  issues = fetch_linear_issues # This only retrieves issues for the configured linear team ids

  # Only look up states for teams that actually have issues being moved
  # This avoids warning about missing states in teams with no relevant issues.
  relevant_issues = issue_identifiers.filter_map { |id| issues.find { |i| i['identifier'] == id } }
  return if relevant_issues.empty?

  relevant_team_ids = relevant_issues.map { |i| i.dig('team', 'id') }.uniq

  state_ids_by_team_id = state_ids_by_team_id(state, team_ids: relevant_team_ids)

  relevant_issues.each do |issue|
    next unless (state_id = state_ids_by_team_id[issue.dig('team', 'id')])

    update_issue_state(issue['id'], state_id)
  end
end