class Geordi::Gitlinear

Constants

API_ENDPOINT

Attributes

highline[RW]
settings[RW]

Public Class Methods

new() click to toggle source
# File lib/geordi/gitlinear.rb, line 13
def initialize
  self.highline = HighLine.new
  self.settings = Settings.new
end

Public Instance Methods

branch(from_master: false) click to toggle source
# File lib/geordi/gitlinear.rb, line 27
def branch(from_master: false)
  issue = choose_issue

  local_branches = local_branch_names
  matching_local_branch = local_branches.find { |branch_name| branch_name == issue['branchName'] }
  matching_local_branch ||= local_branches.find { |branch_name| branch_name.include? issue['identifier'].to_s }

  if matching_local_branch.nil?
    Util.run! ['git', 'checkout', 'master'] if from_master
    Util.run! ['git', 'checkout', '-b', issue['branchName']]
  else
    Util.run! ['git', 'checkout', matching_local_branch]
  end
end
commit(git_args) click to toggle source
# File lib/geordi/gitlinear.rb, line 18
    def commit(git_args)
      Interaction.warn <<~WARNING unless Util.staged_changes?
        No staged changes. Will create an empty commit.
      WARNING

      issue = choose_issue
      create_commit "[#{issue['identifier']}] #{issue['title']}", "Issue: #{issue['url']}", *git_args
    end

Private Instance Methods

bold(string) click to toggle source
# File lib/geordi/gitlinear.rb, line 184
def bold(string)
  HighLine::BOLD + string + HighLine::RESET
end
choose_issue() click to toggle source
# File lib/geordi/gitlinear.rb, line 62
def choose_issue
  if Util.testing?
    return dummy_issue_for_testing
  end

  loading_message = 'Connecting to Linear ...'
  print(loading_message)
  issues = fetch_linear_issues
  reset_loading_message = "\r#{' ' * (loading_message.length + issues.length)}\r"

  if issues.empty?
    print reset_loading_message
    Geordi::Interaction.fail('No issues to offer.')
  end

  highline.choose do |menu|
    menu.header = 'Choose an issue'

    issues.each do |issue|
      state = issue['state']['name']
      if issue['assignee']
        assignee = issue['assignee']['name']
        assignee_is_me = issue['assignee']['isMe']
      else
        assignee = "unassigned"
        assignee_is_me = false
      end

      state += HighLine::BOLD if assignee_is_me

      label = "(#{assignee}, #{state}) #{issue['title']}"
      label = bold(label) if assignee_is_me

      menu.choice(label) { return issue }
    end

    menu.hidden('') { Interaction.fail('No issue selected.') }
    print reset_loading_message # Once menu is build
  end

  nil # Return nothing
end
create_commit(title, description, *git_args) click to toggle source
# File lib/geordi/gitlinear.rb, line 117
def create_commit(title, description, *git_args)
  extra = highline.ask("\nAdd an optional message").strip
  title << ' - ' << extra if extra != ''
  Util.run!(['git', 'commit', '--allow-empty', '-m', title, '-m', description, *git_args])
end
dummy_issue_for_testing() click to toggle source
# File lib/geordi/gitlinear.rb, line 105
def dummy_issue_for_testing
  settings.linear_api_key
  ENV['GEORDI_TESTING_NO_LINEAR_ISSUES'] == 'true' ? Geordi::Interaction.fail('No issues to offer.') : {
    'identifier' => 'team-123',
    'title' => 'Test Issue',
    'url' => 'https://www.issue-url.com',
    'branchName' => 'testuser/team-123-test-issue',
    'assignee' => { 'name' => 'Test User', 'isMe' => true },
    'state' => { 'name' => 'In Progress' }
  }
end
fetch_linear_issues() click to toggle source
# File lib/geordi/gitlinear.rb, line 123
    def fetch_linear_issues
      team_ids = settings.linear_team_ids
      filter = {
        "team": {
          "id": {
            "in": team_ids,
          }
        },
        "state": {
          "type": {
            "eq": "started"
          }
        }
      }
      response = query_api(<<~GRAPHQL, filter: filter)
        query Issues($filter: IssueFilter) {
          issues(filter: $filter) {
            nodes {
              title
              identifier
              url
              branchName
              assignee {
                name
                isMe
              }
              state {
               name
             }
            }
          }
        }
      GRAPHQL

      response.dig(*%w[issues nodes])
    end
local_branch_names() click to toggle source
# File lib/geordi/gitlinear.rb, line 46
def local_branch_names
  @local_branch_names ||= begin
    branch_list_string = if Util.testing?
      ENV['GEORDI_TESTING_GIT_BRANCHES'].to_s
    else
      `git branch --format="%(refname:short)"`
    end

    if branch_list_string.strip.empty?
      Interaction.fail 'Could not determine local Git branches.'
    end

    branch_list_string.split("\n")
  end
end
query_api(attributes, variables) click to toggle source
# File lib/geordi/gitlinear.rb, line 160
def query_api(attributes, variables)
  uri = URI(API_ENDPOINT)

  https = Net::HTTP.new(uri.host, uri.port)
  https.use_ssl = true

  query = [{ query: attributes.split.join(' '), variables: variables }].to_json

  request = Net::HTTP::Post.new(uri.path)
  request.body = query

  request['Content-Type'] = 'application/json'
  request['Authorization'] = settings.linear_api_key

  response = https.request(request)

  parsed_response = JSON.parse(response.body)[0]
  if parsed_response.key?('errors')
    raise parsed_response.dig('errors')
  else
    parsed_response['data']
  end
end