abt-cli 0.0.21 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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