abt-cli 0.0.26 → 0.0.31

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/abt.rb +0 -4
  3. data/lib/abt/cli.rb +5 -1
  4. data/lib/abt/directory_config.rb +28 -10
  5. data/lib/abt/docs.rb +10 -6
  6. data/lib/abt/providers/asana.rb +1 -0
  7. data/lib/abt/providers/asana/base_command.rb +33 -3
  8. data/lib/abt/providers/asana/commands/add.rb +0 -4
  9. data/lib/abt/providers/asana/commands/branch_name.rb +0 -13
  10. data/lib/abt/providers/asana/commands/clear.rb +1 -1
  11. data/lib/abt/providers/asana/commands/current.rb +0 -18
  12. data/lib/abt/providers/asana/commands/finalize.rb +2 -4
  13. data/lib/abt/providers/asana/commands/pick.rb +11 -41
  14. data/lib/abt/providers/asana/commands/tasks.rb +2 -7
  15. data/lib/abt/providers/asana/commands/write_config.rb +73 -0
  16. data/lib/abt/providers/asana/configuration.rb +1 -1
  17. data/lib/abt/providers/asana/path.rb +2 -2
  18. data/lib/abt/providers/asana/services/project_picker.rb +54 -0
  19. data/lib/abt/providers/asana/services/task_picker.rb +83 -0
  20. data/lib/abt/providers/devops.rb +1 -0
  21. data/lib/abt/providers/devops/api.rb +27 -20
  22. data/lib/abt/providers/devops/base_command.rb +42 -25
  23. data/lib/abt/providers/devops/commands/branch_name.rb +8 -16
  24. data/lib/abt/providers/devops/commands/clear.rb +1 -1
  25. data/lib/abt/providers/devops/commands/current.rb +2 -21
  26. data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +8 -16
  27. data/lib/abt/providers/devops/commands/pick.rb +11 -60
  28. data/lib/abt/providers/devops/commands/work_items.rb +3 -7
  29. data/lib/abt/providers/devops/commands/write_config.rb +47 -0
  30. data/lib/abt/providers/devops/configuration.rb +1 -1
  31. data/lib/abt/providers/devops/path.rb +24 -8
  32. data/lib/abt/providers/devops/services/board_picker.rb +69 -0
  33. data/lib/abt/providers/devops/services/project_picker.rb +73 -0
  34. data/lib/abt/providers/devops/services/work_item_picker.rb +99 -0
  35. data/lib/abt/providers/harvest.rb +1 -0
  36. data/lib/abt/providers/harvest/base_command.rb +45 -3
  37. data/lib/abt/providers/harvest/commands/clear.rb +1 -1
  38. data/lib/abt/providers/harvest/commands/current.rb +0 -28
  39. data/lib/abt/providers/harvest/commands/pick.rb +12 -27
  40. data/lib/abt/providers/harvest/commands/projects.rb +2 -9
  41. data/lib/abt/providers/harvest/commands/tasks.rb +2 -19
  42. data/lib/abt/providers/harvest/commands/track.rb +72 -39
  43. data/lib/abt/providers/harvest/commands/write_config.rb +41 -0
  44. data/lib/abt/providers/harvest/configuration.rb +1 -1
  45. data/lib/abt/providers/harvest/harvest_helpers.rb +25 -0
  46. data/lib/abt/providers/harvest/path.rb +1 -1
  47. data/lib/abt/providers/harvest/services/project_picker.rb +53 -0
  48. data/lib/abt/providers/harvest/services/task_picker.rb +50 -0
  49. data/lib/abt/version.rb +1 -1
  50. metadata +13 -6
  51. data/lib/abt/providers/asana/commands/init.rb +0 -42
  52. data/lib/abt/providers/devops/commands/boards.rb +0 -34
  53. data/lib/abt/providers/devops/commands/init.rb +0 -79
  54. data/lib/abt/providers/harvest/commands/init.rb +0 -53
@@ -15,7 +15,7 @@ module Abt
15
15
  end
16
16
 
17
17
  def path
18
- Path.new(local_available? && git["path"] || Abt.directory_config.dig("harvest", "path") || "")
18
+ Path.new(local_available? && git["path"] || cli.directory_config.dig("harvest", "path") || "")
19
19
  end
20
20
 
21
21
  def path=(new_path)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ module Providers
5
+ module Harvest
6
+ class HarvestHelpers
7
+ class << self
8
+ HOURS_REGEX = /(?<hours>\d+)/.freeze
9
+ MINUTES_REGEX = /(?<minutes>[0-5][0-9])/.freeze
10
+ SECONDS_REGEX = /(?<seconds>[0-5][0-9])/.freeze
11
+ TIME_REGEX = /^#{HOURS_REGEX}:#{MINUTES_REGEX}(?::#{SECONDS_REGEX})?$/.freeze
12
+
13
+ def decimal_hours_from_string(hh_mm_ss)
14
+ match = TIME_REGEX.match(hh_mm_ss)
15
+ raise Abt::Cli::Abort, "Invalid time: #{hh_mm_ss}, supported formats are: HH:MM, HH:MM:SS" if match.nil?
16
+
17
+ match[:hours].to_i +
18
+ match[:minutes].to_i / 60.0 +
19
+ match[:seconds].to_i / 60.0 / 60.0
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -28,7 +28,7 @@ module Abt
28
28
  private
29
29
 
30
30
  def match
31
- @match ||= PATH_REGEX.match(self)
31
+ @match ||= PATH_REGEX.match(to_s)
32
32
  end
33
33
  end
34
34
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ module Providers
5
+ module Harvest
6
+ module Services
7
+ class ProjectPicker
8
+ class Result
9
+ attr_reader :project, :path
10
+
11
+ def initialize(project:, path:)
12
+ @project = project
13
+ @path = path
14
+ end
15
+ end
16
+
17
+ def self.call(**args)
18
+ new(**args).call
19
+ end
20
+
21
+ attr_reader :cli, :project_assignments
22
+
23
+ def initialize(cli:, project_assignments:)
24
+ @cli = cli
25
+ @project_assignments = project_assignments
26
+ end
27
+
28
+ def call
29
+ project = cli.prompt.search("Select a project", searchable_projects)["project"]
30
+
31
+ path = Path.from_ids(project_id: project["id"])
32
+
33
+ Result.new(project: project, path: path)
34
+ end
35
+
36
+ private
37
+
38
+ def searchable_projects
39
+ @searchable_projects ||= project_assignments.map do |project_assignment|
40
+ client = project_assignment["client"]
41
+ project = project_assignment["project"]
42
+
43
+ project_assignment.merge(
44
+ "name" => "#{client['name']} > #{project['name']}",
45
+ "project" => project
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ module Providers
5
+ module Harvest
6
+ module Services
7
+ class TaskPicker
8
+ class Result
9
+ attr_reader :task, :path
10
+
11
+ def initialize(task:, path:)
12
+ @task = task
13
+ @path = path
14
+ end
15
+ end
16
+
17
+ def self.call(**args)
18
+ new(**args).call
19
+ end
20
+
21
+ attr_reader :cli, :path, :project_assignment
22
+
23
+ def initialize(cli:, path:, project_assignment:)
24
+ @cli = cli
25
+ @path = path
26
+ @project_assignment = project_assignment
27
+ end
28
+
29
+ def call
30
+ task = cli.prompt.choice("Select a task from #{project['name']}", tasks)
31
+
32
+ path_with_task = Path.from_ids(project_id: path.project_id, task_id: task["id"])
33
+
34
+ Result.new(task: task, path: path_with_task)
35
+ end
36
+
37
+ private
38
+
39
+ def project
40
+ project_assignment["project"]
41
+ end
42
+
43
+ def tasks
44
+ @tasks ||= project_assignment["task_assignments"].map { |ta| ta["task"] }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/abt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Abt
4
- VERSION = "0.0.26"
4
+ VERSION = "0.0.31"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abt-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.26
4
+ version: 0.0.31
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesper Sørensen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-24 00:00:00.000000000 Z
11
+ date: 2021-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-inflector
@@ -105,28 +105,32 @@ files:
105
105
  - "./lib/abt/providers/asana/commands/current.rb"
106
106
  - "./lib/abt/providers/asana/commands/finalize.rb"
107
107
  - "./lib/abt/providers/asana/commands/harvest_time_entry_data.rb"
108
- - "./lib/abt/providers/asana/commands/init.rb"
109
108
  - "./lib/abt/providers/asana/commands/pick.rb"
110
109
  - "./lib/abt/providers/asana/commands/projects.rb"
111
110
  - "./lib/abt/providers/asana/commands/share.rb"
112
111
  - "./lib/abt/providers/asana/commands/start.rb"
113
112
  - "./lib/abt/providers/asana/commands/tasks.rb"
113
+ - "./lib/abt/providers/asana/commands/write_config.rb"
114
114
  - "./lib/abt/providers/asana/configuration.rb"
115
115
  - "./lib/abt/providers/asana/path.rb"
116
+ - "./lib/abt/providers/asana/services/project_picker.rb"
117
+ - "./lib/abt/providers/asana/services/task_picker.rb"
116
118
  - "./lib/abt/providers/devops.rb"
117
119
  - "./lib/abt/providers/devops/api.rb"
118
120
  - "./lib/abt/providers/devops/base_command.rb"
119
- - "./lib/abt/providers/devops/commands/boards.rb"
120
121
  - "./lib/abt/providers/devops/commands/branch_name.rb"
121
122
  - "./lib/abt/providers/devops/commands/clear.rb"
122
123
  - "./lib/abt/providers/devops/commands/current.rb"
123
124
  - "./lib/abt/providers/devops/commands/harvest_time_entry_data.rb"
124
- - "./lib/abt/providers/devops/commands/init.rb"
125
125
  - "./lib/abt/providers/devops/commands/pick.rb"
126
126
  - "./lib/abt/providers/devops/commands/share.rb"
127
127
  - "./lib/abt/providers/devops/commands/work_items.rb"
128
+ - "./lib/abt/providers/devops/commands/write_config.rb"
128
129
  - "./lib/abt/providers/devops/configuration.rb"
129
130
  - "./lib/abt/providers/devops/path.rb"
131
+ - "./lib/abt/providers/devops/services/board_picker.rb"
132
+ - "./lib/abt/providers/devops/services/project_picker.rb"
133
+ - "./lib/abt/providers/devops/services/work_item_picker.rb"
130
134
  - "./lib/abt/providers/git.rb"
131
135
  - "./lib/abt/providers/git/commands/branch.rb"
132
136
  - "./lib/abt/providers/harvest.rb"
@@ -134,7 +138,6 @@ files:
134
138
  - "./lib/abt/providers/harvest/base_command.rb"
135
139
  - "./lib/abt/providers/harvest/commands/clear.rb"
136
140
  - "./lib/abt/providers/harvest/commands/current.rb"
137
- - "./lib/abt/providers/harvest/commands/init.rb"
138
141
  - "./lib/abt/providers/harvest/commands/pick.rb"
139
142
  - "./lib/abt/providers/harvest/commands/projects.rb"
140
143
  - "./lib/abt/providers/harvest/commands/share.rb"
@@ -142,8 +145,12 @@ files:
142
145
  - "./lib/abt/providers/harvest/commands/stop.rb"
143
146
  - "./lib/abt/providers/harvest/commands/tasks.rb"
144
147
  - "./lib/abt/providers/harvest/commands/track.rb"
148
+ - "./lib/abt/providers/harvest/commands/write_config.rb"
145
149
  - "./lib/abt/providers/harvest/configuration.rb"
150
+ - "./lib/abt/providers/harvest/harvest_helpers.rb"
146
151
  - "./lib/abt/providers/harvest/path.rb"
152
+ - "./lib/abt/providers/harvest/services/project_picker.rb"
153
+ - "./lib/abt/providers/harvest/services/task_picker.rb"
147
154
  - "./lib/abt/version.rb"
148
155
  - bin/abt
149
156
  homepage: https://github.com/abtion/abt
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Abt
4
- module Providers
5
- module Asana
6
- module Commands
7
- class Init < BaseCommand
8
- def self.usage
9
- "abt init asana"
10
- end
11
-
12
- def self.description
13
- "Pick Asana project for current git repository"
14
- end
15
-
16
- def perform
17
- require_local_config!
18
-
19
- projects # Load projects up front to make it obvious that searches are instant
20
- project = cli.prompt.search("Select a project", projects)
21
-
22
- config.path = Path.from_ids(project_gid: project["gid"])
23
-
24
- print_project(project)
25
- end
26
-
27
- private
28
-
29
- def projects
30
- @projects ||= begin
31
- warn("Fetching projects...")
32
- api.get_paged("projects",
33
- workspace: config.workspace_gid,
34
- archived: false,
35
- opt_fields: "name,permalink_url")
36
- end
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Abt
4
- module Providers
5
- module Devops
6
- module Commands
7
- class Boards < BaseCommand
8
- def self.usage
9
- "abt boards devops"
10
- end
11
-
12
- def self.description
13
- "List all boards - useful for piping into grep etc"
14
- end
15
-
16
- def perform
17
- abort("No organization selected. Did you initialize DevOps?") if organization_name.nil?
18
- abort("No project selected. Did you initialize DevOps?") if project_name.nil?
19
-
20
- boards.map do |board|
21
- print_board(organization_name, project_name, board)
22
- end
23
- end
24
-
25
- private
26
-
27
- def boards
28
- @boards ||= api.get_paged("work/boards")
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Abt
4
- module Providers
5
- module Devops
6
- module Commands
7
- class Init < BaseCommand
8
- AZURE_DEV_URL_REGEX = %r{^https://dev\.azure\.com/(?<organization>[^/]+)/(?<project>[^/]+)}.freeze
9
- VS_URL_REGEX = %r{^https://(?<organization>[^.]+)\.visualstudio\.com/(?<project>[^/]+)}.freeze
10
-
11
- def self.usage
12
- "abt init devops"
13
- end
14
-
15
- def self.description
16
- "Pick DevOps board for current git repository"
17
- end
18
-
19
- def perform
20
- require_local_config!
21
- board = cli.prompt.choice("Select a project work board", boards)
22
-
23
- config.path = Path.from_ids(
24
- organization_name: organization_name,
25
- project_name: project_name,
26
- board_id: board["id"]
27
- )
28
- print_board(organization_name, project_name, board)
29
- end
30
-
31
- private
32
-
33
- def boards
34
- @boards ||= api.get_paged("work/boards")
35
- end
36
-
37
- def project_name
38
- @project_name ||= begin
39
- if (match = AZURE_DEV_URL_REGEX.match(project_url)) ||
40
- (match = VS_URL_REGEX.match(project_url))
41
- match[:project]
42
- end
43
- end
44
- end
45
-
46
- def organization_name
47
- @organization_name ||= begin
48
- if (match = AZURE_DEV_URL_REGEX.match(project_url)) ||
49
- (match = VS_URL_REGEX.match(project_url))
50
- match[:organization]
51
- end
52
- end
53
- end
54
-
55
- def project_url
56
- @project_url ||= begin
57
- loop do
58
- url = cli.prompt.text(project_url_prompt_text)
59
-
60
- break url if AZURE_DEV_URL_REGEX =~ url || VS_URL_REGEX =~ url
61
-
62
- warn("Invalid URL")
63
- end
64
- end
65
- end
66
-
67
- def project_url_prompt_text
68
- <<~TXT
69
- Please provide the URL for the devops project
70
- For instance https://{organization}.visualstudio.com/{project} or https://dev.azure.com/{organization}/{project}
71
-
72
- Enter URL
73
- TXT
74
- end
75
- end
76
- end
77
- end
78
- end
79
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Abt
4
- module Providers
5
- module Harvest
6
- module Commands
7
- class Init < BaseCommand
8
- def self.usage
9
- "abt init harvest"
10
- end
11
-
12
- def self.description
13
- "Pick Harvest project for current git repository"
14
- end
15
-
16
- def perform
17
- require_local_config!
18
- projects # Load projects up front to make it obvious that searches are instant
19
- project = cli.prompt.search("Select a project", searchable_projects)["project"]
20
-
21
- config.path = Path.from_ids(project_id: project["id"])
22
-
23
- print_project(project)
24
- end
25
-
26
- private
27
-
28
- def searchable_projects
29
- @searchable_projects ||= projects.map do |project|
30
- {
31
- "name" => "#{project['client']['name']} > #{project['name']}",
32
- "project" => project
33
- }
34
- end
35
- end
36
-
37
- def projects
38
- @projects ||= begin
39
- warn("Fetching projects...")
40
- project_assignments.map do |project_assignment|
41
- project_assignment["project"].merge("client" => project_assignment["client"])
42
- end
43
- end
44
- end
45
-
46
- def project_assignments
47
- @project_assignments ||= api.get_paged("users/me/project_assignments")
48
- end
49
- end
50
- end
51
- end
52
- end
53
- end