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.
- checksums.yaml +4 -4
- data/lib/abt.rb +0 -4
- data/lib/abt/cli.rb +5 -1
- data/lib/abt/directory_config.rb +28 -10
- data/lib/abt/docs.rb +10 -6
- data/lib/abt/providers/asana.rb +1 -0
- data/lib/abt/providers/asana/base_command.rb +33 -3
- data/lib/abt/providers/asana/commands/add.rb +0 -4
- data/lib/abt/providers/asana/commands/branch_name.rb +0 -13
- data/lib/abt/providers/asana/commands/clear.rb +1 -1
- data/lib/abt/providers/asana/commands/current.rb +0 -18
- data/lib/abt/providers/asana/commands/finalize.rb +2 -4
- data/lib/abt/providers/asana/commands/pick.rb +11 -41
- data/lib/abt/providers/asana/commands/tasks.rb +2 -7
- data/lib/abt/providers/asana/commands/write_config.rb +73 -0
- data/lib/abt/providers/asana/configuration.rb +1 -1
- data/lib/abt/providers/asana/path.rb +2 -2
- data/lib/abt/providers/asana/services/project_picker.rb +54 -0
- data/lib/abt/providers/asana/services/task_picker.rb +83 -0
- data/lib/abt/providers/devops.rb +1 -0
- data/lib/abt/providers/devops/api.rb +27 -20
- data/lib/abt/providers/devops/base_command.rb +42 -25
- data/lib/abt/providers/devops/commands/branch_name.rb +8 -16
- data/lib/abt/providers/devops/commands/clear.rb +1 -1
- data/lib/abt/providers/devops/commands/current.rb +2 -21
- data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +8 -16
- data/lib/abt/providers/devops/commands/pick.rb +11 -60
- data/lib/abt/providers/devops/commands/work_items.rb +3 -7
- data/lib/abt/providers/devops/commands/write_config.rb +47 -0
- data/lib/abt/providers/devops/configuration.rb +1 -1
- data/lib/abt/providers/devops/path.rb +24 -8
- data/lib/abt/providers/devops/services/board_picker.rb +69 -0
- data/lib/abt/providers/devops/services/project_picker.rb +73 -0
- data/lib/abt/providers/devops/services/work_item_picker.rb +99 -0
- data/lib/abt/providers/harvest.rb +1 -0
- data/lib/abt/providers/harvest/base_command.rb +45 -3
- data/lib/abt/providers/harvest/commands/clear.rb +1 -1
- data/lib/abt/providers/harvest/commands/current.rb +0 -28
- data/lib/abt/providers/harvest/commands/pick.rb +12 -27
- data/lib/abt/providers/harvest/commands/projects.rb +2 -9
- data/lib/abt/providers/harvest/commands/tasks.rb +2 -19
- data/lib/abt/providers/harvest/commands/track.rb +72 -39
- data/lib/abt/providers/harvest/commands/write_config.rb +41 -0
- data/lib/abt/providers/harvest/configuration.rb +1 -1
- data/lib/abt/providers/harvest/harvest_helpers.rb +25 -0
- data/lib/abt/providers/harvest/path.rb +1 -1
- data/lib/abt/providers/harvest/services/project_picker.rb +53 -0
- data/lib/abt/providers/harvest/services/task_picker.rb +50 -0
- data/lib/abt/version.rb +1 -1
- metadata +13 -6
- data/lib/abt/providers/asana/commands/init.rb +0 -42
- data/lib/abt/providers/devops/commands/boards.rb +0 -34
- data/lib/abt/providers/devops/commands/init.rb +0 -79
- 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"] ||
|
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
|
@@ -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
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.
|
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-
|
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
|