abt-cli 0.0.21 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/bin/abt +3 -3
  3. data/lib/abt.rb +6 -6
  4. data/lib/abt/ari.rb +1 -1
  5. data/lib/abt/ari_list.rb +1 -1
  6. data/lib/abt/base_command.rb +7 -7
  7. data/lib/abt/cli.rb +27 -40
  8. data/lib/abt/cli/arguments_parser.rb +5 -9
  9. data/lib/abt/cli/global_commands.rb +23 -0
  10. data/lib/abt/cli/global_commands/commands.rb +2 -2
  11. data/lib/abt/cli/global_commands/examples.rb +2 -2
  12. data/lib/abt/cli/global_commands/help.rb +2 -2
  13. data/lib/abt/cli/global_commands/readme.rb +2 -2
  14. data/lib/abt/cli/global_commands/share.rb +6 -6
  15. data/lib/abt/cli/global_commands/version.rb +2 -2
  16. data/lib/abt/cli/prompt.rb +51 -20
  17. data/lib/abt/docs.rb +39 -33
  18. data/lib/abt/docs/cli.rb +3 -3
  19. data/lib/abt/docs/markdown.rb +5 -5
  20. data/lib/abt/git_config.rb +4 -6
  21. data/lib/abt/providers/asana/api.rb +9 -9
  22. data/lib/abt/providers/asana/base_command.rb +8 -10
  23. data/lib/abt/providers/asana/commands/add.rb +13 -12
  24. data/lib/abt/providers/asana/commands/branch_name.rb +8 -8
  25. data/lib/abt/providers/asana/commands/clear.rb +7 -8
  26. data/lib/abt/providers/asana/commands/current.rb +14 -14
  27. data/lib/abt/providers/asana/commands/finalize.rb +11 -12
  28. data/lib/abt/providers/asana/commands/harvest_time_entry_data.rb +11 -11
  29. data/lib/abt/providers/asana/commands/init.rb +8 -41
  30. data/lib/abt/providers/asana/commands/pick.rb +17 -17
  31. data/lib/abt/providers/asana/commands/projects.rb +5 -5
  32. data/lib/abt/providers/asana/commands/share.rb +5 -5
  33. data/lib/abt/providers/asana/commands/start.rb +21 -20
  34. data/lib/abt/providers/asana/commands/tasks.rb +6 -6
  35. data/lib/abt/providers/asana/configuration.rb +25 -25
  36. data/lib/abt/providers/asana/path.rb +5 -5
  37. data/lib/abt/providers/devops/api.rb +12 -12
  38. data/lib/abt/providers/devops/base_command.rb +10 -10
  39. data/lib/abt/providers/devops/commands/boards.rb +5 -7
  40. data/lib/abt/providers/devops/commands/branch_name.rb +9 -9
  41. data/lib/abt/providers/devops/commands/clear.rb +7 -8
  42. data/lib/abt/providers/devops/commands/current.rb +17 -17
  43. data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +13 -13
  44. data/lib/abt/providers/devops/commands/init.rb +17 -13
  45. data/lib/abt/providers/devops/commands/pick.rb +11 -11
  46. data/lib/abt/providers/devops/commands/share.rb +5 -5
  47. data/lib/abt/providers/devops/commands/{work-items.rb → work_items.rb} +3 -3
  48. data/lib/abt/providers/devops/configuration.rb +19 -15
  49. data/lib/abt/providers/devops/path.rb +5 -4
  50. data/lib/abt/providers/git/commands/branch.rb +17 -19
  51. data/lib/abt/providers/harvest/api.rb +8 -8
  52. data/lib/abt/providers/harvest/base_command.rb +6 -8
  53. data/lib/abt/providers/harvest/commands/clear.rb +7 -8
  54. data/lib/abt/providers/harvest/commands/current.rb +13 -13
  55. data/lib/abt/providers/harvest/commands/init.rb +10 -38
  56. data/lib/abt/providers/harvest/commands/pick.rb +11 -11
  57. data/lib/abt/providers/harvest/commands/projects.rb +5 -5
  58. data/lib/abt/providers/harvest/commands/share.rb +5 -5
  59. data/lib/abt/providers/harvest/commands/start.rb +5 -3
  60. data/lib/abt/providers/harvest/commands/stop.rb +12 -12
  61. data/lib/abt/providers/harvest/commands/tasks.rb +7 -7
  62. data/lib/abt/providers/harvest/commands/track.rb +21 -20
  63. data/lib/abt/providers/harvest/configuration.rb +18 -18
  64. data/lib/abt/providers/harvest/path.rb +5 -5
  65. data/lib/abt/version.rb +1 -1
  66. metadata +6 -5
@@ -22,28 +22,26 @@ module Abt
22
22
  def require_project!
23
23
  return if project_id
24
24
 
25
- abort 'No current/specified project. Did you initialize Harvest?'
25
+ abort("No current/specified project. Did you initialize Harvest?")
26
26
  end
27
27
 
28
28
  def require_task!
29
- unless project_id
30
- abort 'No current/specified project. Did you initialize Harvest and pick a task?'
31
- end
29
+ abort("No current/specified project. Did you initialize Harvest and pick a task?") unless project_id
32
30
 
33
- abort 'No current/specified task. Did you pick a Harvest task?' if task_id.nil?
31
+ abort("No current/specified task. Did you pick a Harvest task?") if task_id.nil?
34
32
  end
35
33
 
36
34
  def print_project(project)
37
35
  cli.print_ari(
38
- 'harvest',
39
- project['id'],
36
+ "harvest",
37
+ project["id"],
40
38
  "#{project['client']['name']} > #{project['name']}"
41
39
  )
42
40
  end
43
41
 
44
42
  def print_task(project, task)
45
43
  cli.print_ari(
46
- 'harvest',
44
+ "harvest",
47
45
  "#{project['id']}/#{task['id']}",
48
46
  "#{project['name']} > #{task['name']}"
49
47
  )
@@ -6,29 +6,28 @@ module Abt
6
6
  module Commands
7
7
  class Clear < BaseCommand
8
8
  def self.usage
9
- 'abt clear harvest'
9
+ "abt clear harvest"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Clear harvest configuration'
13
+ "Clear harvest configuration"
14
14
  end
15
15
 
16
16
  def self.flags
17
17
  [
18
- ['-g', '--global', 'Clear global instead of local harvest configuration (credentials etc.)'],
19
- ['-a', '--all', 'Clear all harvest configuration']
18
+ ["-g", "--global",
19
+ "Clear global instead of local harvest configuration (credentials etc.)"],
20
+ ["-a", "--all", "Clear all harvest configuration"]
20
21
  ]
21
22
  end
22
23
 
23
24
  def perform
24
- if flags[:global] && flags[:all]
25
- abort('Flags --global and --all cannot be used at the same time')
26
- end
25
+ abort("Flags --global and --all cannot be used at the same time") if flags[:global] && flags[:all]
27
26
 
28
27
  config.clear_local unless flags[:global]
29
28
  config.clear_global if flags[:global] || flags[:all]
30
29
 
31
- warn 'Configuration cleared'
30
+ warn("Configuration cleared")
32
31
  end
33
32
  end
34
33
  end
@@ -6,22 +6,22 @@ module Abt
6
6
  module Commands
7
7
  class Current < BaseCommand
8
8
  def self.usage
9
- 'abt current harvest[:<project-id>[/<task-id>]]'
9
+ "abt current harvest[:<project-id>[/<task-id>]]"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Get or set project and or task for current git repository'
13
+ "Get or set project and or task for current git repository"
14
14
  end
15
15
 
16
16
  def perform
17
- abort 'Must be run inside a git repository' unless config.local_available?
17
+ abort("Must be run inside a git repository") unless config.local_available?
18
18
 
19
19
  require_project!
20
20
  ensure_valid_configuration!
21
21
 
22
22
  if path != config.path
23
23
  config.path = path
24
- warn 'Configuration updated'
24
+ warn("Configuration updated")
25
25
  end
26
26
 
27
27
  print_configuration
@@ -38,36 +38,36 @@ module Abt
38
38
  end
39
39
 
40
40
  def ensure_valid_configuration!
41
- abort "Invalid project: #{project_id}" if project.nil?
42
- abort "Invalid task: #{task_id}" if task_id && task.nil?
41
+ abort("Invalid project: #{project_id}") if project.nil?
42
+ abort("Invalid task: #{task_id}") if task_id && task.nil?
43
43
  end
44
44
 
45
45
  def project
46
- return @project if instance_variable_defined? :@project
46
+ return @project if instance_variable_defined?(:@project)
47
47
 
48
48
  @project = if project_assignment
49
- project_assignment['project'].merge('client' => project_assignment['client'])
49
+ project_assignment["project"].merge("client" => project_assignment["client"])
50
50
  end
51
51
  end
52
52
 
53
53
  def task
54
- return @task if instance_variable_defined? :@task
54
+ return @task if instance_variable_defined?(:@task)
55
55
 
56
56
  @task = if project_assignment
57
- project_assignment['task_assignments'].map { |ta| ta['task'] }.find do |task|
58
- task['id'].to_s == task_id
57
+ project_assignment["task_assignments"].map { |ta| ta["task"] }.find do |task|
58
+ task["id"].to_s == task_id
59
59
  end
60
60
  end
61
61
  end
62
62
 
63
63
  def project_assignment
64
64
  @project_assignment ||= begin
65
- project_assignments.find { |pa| pa['project']['id'].to_s == project_id }
65
+ project_assignments.find { |pa| pa["project"]["id"].to_s == project_id }
66
66
  end
67
67
  end
68
68
 
69
69
  def project_assignments
70
- @project_assignments ||= api.get_paged('users/me/project_assignments')
70
+ @project_assignments ||= api.get_paged("users/me/project_assignments")
71
71
  end
72
72
  end
73
73
  end
@@ -6,74 +6,46 @@ module Abt
6
6
  module Commands
7
7
  class Init < BaseCommand
8
8
  def self.usage
9
- 'abt init harvest'
9
+ "abt init harvest"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Pick Harvest project for current git repository'
13
+ "Pick Harvest project for current git repository"
14
14
  end
15
15
 
16
16
  def perform
17
- abort 'Must be run inside a git repository' unless config.local_available?
17
+ abort("Must be run inside a git repository") unless config.local_available?
18
18
 
19
19
  projects # Load projects up front to make it obvious that searches are instant
20
- project = find_search_result
20
+ project = cli.prompt.search("Select a project", searchable_projects)["project"]
21
21
 
22
- config.path = Path.from_ids(project['id'])
22
+ config.path = Path.from_ids(project["id"])
23
23
 
24
24
  print_project(project)
25
25
  end
26
26
 
27
27
  private
28
28
 
29
- def find_search_result
30
- warn 'Select a project'
31
-
32
- loop do
33
- matches = matches_for_string cli.prompt.text('Enter search')
34
- if matches.empty?
35
- warn 'No matches'
36
- next
37
- end
38
-
39
- warn 'Showing the 10 first matches' if matches.size > 10
40
- choice = cli.prompt.choice 'Select a project', matches[0...10], true
41
- break choice['project'] unless choice.nil?
42
- end
43
- end
44
-
45
- def matches_for_string(string)
46
- search_string = sanitize_string(string)
47
-
48
- searchable_projects.select do |project|
49
- sanitize_string(project['name']).include?(search_string)
50
- end
51
- end
52
-
53
- def sanitize_string(string)
54
- string.downcase.gsub(/[^\w]/, '')
55
- end
56
-
57
29
  def searchable_projects
58
30
  @searchable_projects ||= projects.map do |project|
59
31
  {
60
- 'name' => "#{project['client']['name']} > #{project['name']}",
61
- 'project' => project
32
+ "name" => "#{project['client']['name']} > #{project['name']}",
33
+ "project" => project
62
34
  }
63
35
  end
64
36
  end
65
37
 
66
38
  def projects
67
39
  @projects ||= begin
68
- warn 'Fetching projects...'
40
+ warn("Fetching projects...")
69
41
  project_assignments.map do |project_assignment|
70
- project_assignment['project'].merge('client' => project_assignment['client'])
42
+ project_assignment["project"].merge("client" => project_assignment["client"])
71
43
  end
72
44
  end
73
45
  end
74
46
 
75
47
  def project_assignments
76
- @project_assignments ||= api.get_paged('users/me/project_assignments')
48
+ @project_assignments ||= api.get_paged("users/me/project_assignments")
77
49
  end
78
50
  end
79
51
  end
@@ -6,51 +6,51 @@ module Abt
6
6
  module Commands
7
7
  class Pick < BaseCommand
8
8
  def self.usage
9
- 'abt pick harvest[:<project-id>]'
9
+ "abt pick harvest[:<project-id>]"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Pick task for current git repository'
13
+ "Pick task for current git repository"
14
14
  end
15
15
 
16
16
  def self.flags
17
17
  [
18
- ['-d', '--dry-run', 'Keep existing configuration']
18
+ ["-d", "--dry-run", "Keep existing configuration"]
19
19
  ]
20
20
  end
21
21
 
22
22
  def perform
23
- abort 'Must be run inside a git repository' unless config.local_available?
23
+ abort("Must be run inside a git repository") unless config.local_available?
24
24
  require_project!
25
25
 
26
- warn project['name']
27
- task = cli.prompt.choice 'Select a task', tasks
26
+ warn(project["name"])
27
+ task = cli.prompt.choice("Select a task", tasks)
28
28
 
29
29
  print_task(project, task)
30
30
 
31
31
  return if flags[:"dry-run"]
32
32
 
33
- config.path = Path.from_ids(project_id, task['id'])
33
+ config.path = Path.from_ids(project_id, task["id"])
34
34
  end
35
35
 
36
36
  private
37
37
 
38
38
  def project
39
- project_assignment['project']
39
+ project_assignment["project"]
40
40
  end
41
41
 
42
42
  def tasks
43
- @tasks ||= project_assignment['task_assignments'].map { |ta| ta['task'] }
43
+ @tasks ||= project_assignment["task_assignments"].map { |ta| ta["task"] }
44
44
  end
45
45
 
46
46
  def project_assignment
47
47
  @project_assignment ||= begin
48
- project_assignments.find { |pa| pa['project']['id'].to_s == project_id }
48
+ project_assignments.find { |pa| pa["project"]["id"].to_s == project_id }
49
49
  end
50
50
  end
51
51
 
52
52
  def project_assignments
53
- @project_assignments ||= api.get_paged('users/me/project_assignments')
53
+ @project_assignments ||= api.get_paged("users/me/project_assignments")
54
54
  end
55
55
  end
56
56
  end
@@ -6,11 +6,11 @@ module Abt
6
6
  module Commands
7
7
  class Projects < BaseCommand
8
8
  def self.usage
9
- 'abt projects harvest'
9
+ "abt projects harvest"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'List all available projects - useful for piping into grep etc.'
13
+ "List all available projects - useful for piping into grep etc."
14
14
  end
15
15
 
16
16
  def perform
@@ -23,15 +23,15 @@ module Abt
23
23
 
24
24
  def projects
25
25
  @projects ||= begin
26
- warn 'Fetching projects...'
26
+ warn("Fetching projects...")
27
27
  project_assignments.map do |project_assignment|
28
- project_assignment['project'].merge('client' => project_assignment['client'])
28
+ project_assignment["project"].merge("client" => project_assignment["client"])
29
29
  end
30
30
  end
31
31
  end
32
32
 
33
33
  def project_assignments
34
- @project_assignments ||= api.get_paged('users/me/project_assignments')
34
+ @project_assignments ||= api.get_paged("users/me/project_assignments")
35
35
  end
36
36
  end
37
37
  end
@@ -6,18 +6,18 @@ module Abt
6
6
  module Commands
7
7
  class Share < BaseCommand
8
8
  def self.usage
9
- 'abt share harvest[:<project-id>[/<task-id>]]'
9
+ "abt share harvest[:<project-id>[/<task-id>]]"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Print project/task ARI'
13
+ "Print project/task ARI"
14
14
  end
15
15
 
16
16
  def perform
17
- if path != ''
18
- cli.print_ari('harvest', path)
17
+ if path != ""
18
+ cli.print_ari("harvest", path)
19
19
  elsif cli.output.isatty
20
- warn 'No configuration for project. Did you initialize Harvest?'
20
+ warn("No configuration for project. Did you initialize Harvest?")
21
21
  end
22
22
  end
23
23
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'track'
3
+ require_relative "track"
4
4
 
5
5
  module Abt
6
6
  module Providers
@@ -8,11 +8,13 @@ module Abt
8
8
  module Commands
9
9
  class Start < Track
10
10
  def self.usage
11
- 'abt start harvest[:<project-id>/<task-id>] [options]'
11
+ "abt start harvest[:<project-id>/<task-id>] [options]"
12
12
  end
13
13
 
14
14
  def self.description
15
- 'Alias for: `abt track harvest`. Meant to used in combination with other ARIs, e.g. `abt start harvest asana`'
15
+ <<~TXT
16
+ Alias for: `abt track harvest`. Meant to used in combination with other ARIs, e.g. `abt start harvest asana`
17
+ TXT
16
18
  end
17
19
  end
18
20
  end
@@ -6,19 +6,19 @@ module Abt
6
6
  module Commands
7
7
  class Stop < BaseCommand
8
8
  def self.usage
9
- 'abt stop harvest'
9
+ "abt stop harvest"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Stop running harvest tracker'
13
+ "Stop running harvest tracker"
14
14
  end
15
15
 
16
16
  def perform
17
- abort 'No running time entry' if time_entry.nil?
17
+ abort("No running time entry") if time_entry.nil?
18
18
 
19
19
  stop_time_entry
20
20
 
21
- warn 'Harvest time entry stopped'
21
+ warn("Harvest time entry stopped")
22
22
  print_task(project, task)
23
23
  end
24
24
 
@@ -27,28 +27,28 @@ module Abt
27
27
  def stop_time_entry
28
28
  api.patch("time_entries/#{time_entry['id']}/stop")
29
29
  rescue Abt::HttpError::HttpError => e
30
- warn e
31
- abort 'Unable to stop time entry'
30
+ warn(e)
31
+ abort("Unable to stop time entry")
32
32
  end
33
33
 
34
34
  def project
35
- time_entry['project']
35
+ time_entry["project"]
36
36
  end
37
37
 
38
38
  def task
39
- time_entry['task']
39
+ time_entry["task"]
40
40
  end
41
41
 
42
42
  def time_entry
43
43
  @time_entry ||= begin
44
44
  api.get_paged(
45
- 'time_entries',
45
+ "time_entries",
46
46
  is_running: true,
47
47
  user_id: config.user_id
48
48
  ).first
49
- rescue Abt::HttpError::HttpError => e # rubocop:disable Layout/RescueEnsureAlignment
50
- warn e
51
- abort 'Unable to fetch running time entry'
49
+ rescue Abt::HttpError::HttpError => e
50
+ warn(e)
51
+ abort("Unable to fetch running time entry")
52
52
  end
53
53
  end
54
54
  end
@@ -6,11 +6,11 @@ module Abt
6
6
  module Commands
7
7
  class Tasks < BaseCommand
8
8
  def self.usage
9
- 'abt tasks harvest'
9
+ "abt tasks harvest"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'List available tasks on project - useful for piping into grep etc.'
13
+ "List available tasks on project - useful for piping into grep etc."
14
14
  end
15
15
 
16
16
  def perform
@@ -24,24 +24,24 @@ module Abt
24
24
  private
25
25
 
26
26
  def project
27
- project_assignment['project']
27
+ project_assignment["project"]
28
28
  end
29
29
 
30
30
  def tasks
31
31
  @tasks ||= begin
32
- warn 'Fetching tasks...'
33
- project_assignment['task_assignments'].map { |ta| ta['task'] }
32
+ warn("Fetching tasks...")
33
+ project_assignment["task_assignments"].map { |ta| ta["task"] }
34
34
  end
35
35
  end
36
36
 
37
37
  def project_assignment
38
38
  @project_assignment ||= begin
39
- project_assignments.find { |pa| pa['project']['id'].to_s == project_id }
39
+ project_assignments.find { |pa| pa["project"]["id"].to_s == project_id }
40
40
  end
41
41
  end
42
42
 
43
43
  def project_assignments
44
- @project_assignments ||= api.get_paged('users/me/project_assignments')
44
+ @project_assignments ||= api.get_paged("users/me/project_assignments")
45
45
  end
46
46
  end
47
47
  end