Module: Rubyists::Linear::CLI::WhatFor
- Included in:
- SubCommands
- Defined in:
- lib/linear/cli/what_for.rb
Overview
Module for the _for methods
Constant Summary collapse
- PR_TYPES =
TODO: Make this configurable
{ fix: 'Bug fixes', feat: 'New feature work', chore: 'Chores and maintenance', eyes: 'Observability, metrics', test: 'Testing code', perf: 'Performance related work', refactor: 'Code refactoring', docs: 'Documentation Updates', sec: 'Security-related, including dependency updates', style: 'Style updates', ci: 'Continuous integration related', db: 'Database-Related (migrations, models, etc)' }.freeze
- PR_TYPE_SELECTIONS =
PR_TYPES.invert
- ALLOWED_PR_TYPES =
/#{PR_TYPES.keys.join("|")}/
Instance Method Summary collapse
- #ask_for_projects(projects, search: true) ⇒ Object
- #ask_or_edit(thing, question) ⇒ Object
- #cancelled_state_for(thingy) ⇒ Object
- #comment_for(issue, comment) ⇒ Object
- #completed_state_for(thingy) ⇒ Object
- #description_for(description = nil) ⇒ Object
- #editor_for(prefix) ⇒ Object
- #labels_for(team, labels = nil) ⇒ Object
- #pr_description_for(issue) ⇒ Object
- #pr_scope_for(title) ⇒ Object
- #pr_title_for(issue) ⇒ Object
- #pr_type_for(issue) ⇒ Object
-
#project_for(team, project = nil) ⇒ Object
rubocop:disable Metrics/AbcSize.
- #project_scores(projects, search_term) ⇒ Object
- #reason_for(reason = nil, four: nil) ⇒ Object
- #team_for(key = nil) ⇒ Object
- #title_for(title = nil) ⇒ Object
Instance Method Details
#ask_for_projects(projects, search: true) ⇒ Object
90 91 92 93 94 95 |
# File 'lib/linear/cli/what_for.rb', line 90 def ask_for_projects(projects, search: true) prompt.warn("No project found matching #{search}.") if search return projects.first if projects.size == 1 prompt.select('Project:', projects.to_h { |p| [p.name, p] }) end |
#ask_or_edit(thing, question) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/linear/cli/what_for.rb', line 68 def ask_or_edit(thing, question) return thing if thing && thing != '-' answer = prompt.ask("#{question}: ('-' to open an editor)", default: '-') return answer unless answer == '-' answer = editor_for [question.downcase, '.md'] raise SmellsBad, "No content provided for #{question}" if answer.empty? answer end |
#cancelled_state_for(thingy) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/linear/cli/what_for.rb', line 52 def cancelled_state_for(thingy) states = thingy.cancelled_states return states.first if states.size == 1 selection = prompt.select('Choose a cancelled state', states.to_h { |s| [s.name, s.id] }) Rubyists::Linear::WorkflowState.find selection end |
#comment_for(issue, comment) ⇒ Object
37 38 39 |
# File 'lib/linear/cli/what_for.rb', line 37 def comment_for(issue, comment) ask_or_edit comment, "Comment for #{issue.identifier} - #{issue.title}" end |
#completed_state_for(thingy) ⇒ Object
60 61 62 63 64 65 66 |
# File 'lib/linear/cli/what_for.rb', line 60 def completed_state_for(thingy) states = thingy.completed_states return states.first if states.size == 1 selection = prompt.select('Choose a completed state', states.to_h { |s| [s.name, s.id] }) Rubyists::Linear::WorkflowState.find selection end |
#description_for(description = nil) ⇒ Object
80 81 82 |
# File 'lib/linear/cli/what_for.rb', line 80 def description_for(description = nil) ask_or_edit description, 'Description' end |
#editor_for(prefix) ⇒ Object
28 29 30 31 32 33 34 35 |
# File 'lib/linear/cli/what_for.rb', line 28 def editor_for(prefix) file = Tempfile.open(prefix, Rubyists::Linear.tmpdir) TTY::Editor.open(file.path) file.close File.readlines(file.path).map(&:chomp).join('\\n') ensure file&.close end |
#labels_for(team, labels = nil) ⇒ Object
155 156 157 158 159 |
# File 'lib/linear/cli/what_for.rb', line 155 def labels_for(team, labels = nil) return Rubyists::Linear::Label.find_all_by_name(labels.map(&:strip)) if labels prompt.multi_select('Labels:', team.labels.to_h { |t| [t.name, t] }) end |
#pr_description_for(issue) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/linear/cli/what_for.rb', line 124 def pr_description_for(issue) tmpfile = Tempfile.new([issue.identifier, '.md'], Rubyists::Linear.tmpdir) # TODO: Look up templates proposed = "# Context\n\n#{issue.description}\n\n## Issue\n\n#{issue.identifier}\n\n# Solution\n\n# Testing\n\n# Notes\n\n" # rubocop:disable Layout/LineLength tmpfile.write(proposed) && tmpfile.close desc = TTY::Editor.open(tmpfile.path) return tmpfile if desc File.open(tmpfile.path, 'w+') do |file| file.puts prompt.ask("Description for PR for #{issue.identifier} - #{issue.title}", default: proposed) end tmpfile end |
#pr_scope_for(title) ⇒ Object
145 146 147 148 149 150 151 152 153 |
# File 'lib/linear/cli/what_for.rb', line 145 def pr_scope_for(title) proposed_scope = title.match(/^\w+\(([^\)]+)\)/) return proposed_scope[1].downcase if proposed_scope scope = prompt.ask('What is the scope of this PR?', default: 'none') return nil if scope.empty? && scope == 'none' scope end |
#pr_title_for(issue) ⇒ Object
115 116 117 118 119 120 121 122 |
# File 'lib/linear/cli/what_for.rb', line 115 def pr_title_for(issue) proposed = [pr_type_for(issue)] proposed_scope = pr_scope_for(issue.title) proposed << "(#{proposed_scope})" if proposed_scope summary = issue.title.sub(/(?:#{ALLOWED_PR_TYPES})(\([^)]+\))? /, '') proposed << ": #{issue.identifier} - #{summary}" prompt.ask("Title for PR for #{issue.identifier} - #{summary}", default: proposed.join) end |
#pr_type_for(issue) ⇒ Object
138 139 140 141 142 143 |
# File 'lib/linear/cli/what_for.rb', line 138 def pr_type_for(issue) proposed_type = issue.title.match(/^(#{ALLOWED_PR_TYPES})/i) return proposed_type[1].downcase if proposed_type prompt.select('What type of PR is this?', PR_TYPE_SELECTIONS) end |
#project_for(team, project = nil) ⇒ Object
rubocop:disable Metrics/AbcSize
101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/linear/cli/what_for.rb', line 101 def project_for(team, project = nil) # rubocop:disable Metrics/AbcSize projects = team.projects return nil if projects.empty? possibles = project ? project_scores(projects, project) : [] return ask_for_projects(projects, search: project) if possibles.empty? first = possibles.first return first if first.match_score?(project) == 100 selections = possibles + (projects - possibles) prompt.select('Project:', selections.to_h { |p| [p.name, p] }) if possibles.size.positive? end |
#project_scores(projects, search_term) ⇒ Object
97 98 99 |
# File 'lib/linear/cli/what_for.rb', line 97 def project_scores(projects, search_term) projects.select { |p| p.match_score?(search_term).positive? }.sort_by { |p| p.match_score?(search_term) } end |
#reason_for(reason = nil, four: nil) ⇒ Object
47 48 49 50 |
# File 'lib/linear/cli/what_for.rb', line 47 def reason_for(reason = nil, four: nil) question = four ? "Reason for #{TTY::Markdown.parse(four)}" : 'Reason' ask_or_edit reason, question end |
#team_for(key = nil) ⇒ Object
41 42 43 44 45 |
# File 'lib/linear/cli/what_for.rb', line 41 def team_for(key = nil) return Rubyists::Linear::Team.find(key) if key ask_for_team end |
#title_for(title = nil) ⇒ Object
84 85 86 87 88 |
# File 'lib/linear/cli/what_for.rb', line 84 def title_for(title = nil) return title if title prompt.ask('Title:') end |