abt-cli 0.0.22 → 0.0.27
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/abt +2 -2
- data/lib/abt.rb +5 -0
- data/lib/abt/cli.rb +28 -9
- data/lib/abt/cli/prompt.rb +37 -53
- data/lib/abt/directory_config.rb +25 -0
- data/lib/abt/docs.rb +10 -6
- data/lib/abt/docs/markdown.rb +5 -2
- data/lib/abt/helpers.rb +26 -8
- data/lib/abt/providers/asana.rb +1 -0
- data/lib/abt/providers/asana/base_command.rb +37 -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/current.rb +1 -20
- data/lib/abt/providers/asana/commands/finalize.rb +6 -2
- data/lib/abt/providers/asana/commands/harvest_time_entry_data.rb +7 -5
- data/lib/abt/providers/asana/commands/pick.rb +12 -46
- data/lib/abt/providers/asana/commands/start.rb +9 -3
- data/lib/abt/providers/asana/commands/tasks.rb +2 -7
- data/lib/abt/providers/asana/configuration.rb +28 -12
- data/lib/abt/providers/asana/path.rb +1 -1
- 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 +10 -0
- data/lib/abt/providers/devops/base_command.rb +38 -14
- data/lib/abt/providers/devops/commands/boards.rb +1 -2
- data/lib/abt/providers/devops/commands/branch_name.rb +10 -16
- data/lib/abt/providers/devops/commands/current.rb +1 -21
- data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +16 -20
- data/lib/abt/providers/devops/commands/pick.rb +18 -39
- data/lib/abt/providers/devops/commands/work_items.rb +3 -6
- data/lib/abt/providers/devops/configuration.rb +10 -14
- data/lib/abt/providers/devops/path.rb +4 -4
- data/lib/abt/providers/devops/services/board_picker.rb +54 -0
- data/lib/abt/providers/devops/services/project_picker.rb +79 -0
- data/lib/abt/providers/devops/services/work_item_picker.rb +93 -0
- data/lib/abt/providers/git/commands/branch.rb +7 -3
- data/lib/abt/providers/harvest.rb +1 -0
- data/lib/abt/providers/harvest/base_command.rb +49 -3
- data/lib/abt/providers/harvest/commands/current.rb +1 -30
- data/lib/abt/providers/harvest/commands/pick.rb +12 -23
- data/lib/abt/providers/harvest/commands/projects.rb +0 -5
- data/lib/abt/providers/harvest/commands/tasks.rb +1 -16
- data/lib/abt/providers/harvest/commands/track.rb +33 -19
- data/lib/abt/providers/harvest/configuration.rb +1 -1
- 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 +10 -5
- data/lib/abt/providers/asana/commands/init.rb +0 -42
- data/lib/abt/providers/devops/commands/init.rb +0 -76
- data/lib/abt/providers/harvest/commands/init.rb +0 -54
@@ -6,7 +6,7 @@ module Abt
|
|
6
6
|
class Path < String
|
7
7
|
PATH_REGEX = %r{^(?<project_id>\d+)?/?(?<task_id>\d+)?$}.freeze
|
8
8
|
|
9
|
-
def self.from_ids(project_id
|
9
|
+
def self.from_ids(project_id: nil, task_id: nil)
|
10
10
|
path = project_id ? [project_id, *task_id].join("/") : ""
|
11
11
|
new(path)
|
12
12
|
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.new([path, task["id"]].join("/"))
|
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.27
|
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-
|
11
|
+
date: 2021-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-inflector
|
@@ -88,6 +88,7 @@ files:
|
|
88
88
|
- "./lib/abt/cli/global_commands/share.rb"
|
89
89
|
- "./lib/abt/cli/global_commands/version.rb"
|
90
90
|
- "./lib/abt/cli/prompt.rb"
|
91
|
+
- "./lib/abt/directory_config.rb"
|
91
92
|
- "./lib/abt/docs.rb"
|
92
93
|
- "./lib/abt/docs/cli.rb"
|
93
94
|
- "./lib/abt/docs/markdown.rb"
|
@@ -104,7 +105,6 @@ files:
|
|
104
105
|
- "./lib/abt/providers/asana/commands/current.rb"
|
105
106
|
- "./lib/abt/providers/asana/commands/finalize.rb"
|
106
107
|
- "./lib/abt/providers/asana/commands/harvest_time_entry_data.rb"
|
107
|
-
- "./lib/abt/providers/asana/commands/init.rb"
|
108
108
|
- "./lib/abt/providers/asana/commands/pick.rb"
|
109
109
|
- "./lib/abt/providers/asana/commands/projects.rb"
|
110
110
|
- "./lib/abt/providers/asana/commands/share.rb"
|
@@ -112,6 +112,8 @@ files:
|
|
112
112
|
- "./lib/abt/providers/asana/commands/tasks.rb"
|
113
113
|
- "./lib/abt/providers/asana/configuration.rb"
|
114
114
|
- "./lib/abt/providers/asana/path.rb"
|
115
|
+
- "./lib/abt/providers/asana/services/project_picker.rb"
|
116
|
+
- "./lib/abt/providers/asana/services/task_picker.rb"
|
115
117
|
- "./lib/abt/providers/devops.rb"
|
116
118
|
- "./lib/abt/providers/devops/api.rb"
|
117
119
|
- "./lib/abt/providers/devops/base_command.rb"
|
@@ -120,12 +122,14 @@ files:
|
|
120
122
|
- "./lib/abt/providers/devops/commands/clear.rb"
|
121
123
|
- "./lib/abt/providers/devops/commands/current.rb"
|
122
124
|
- "./lib/abt/providers/devops/commands/harvest_time_entry_data.rb"
|
123
|
-
- "./lib/abt/providers/devops/commands/init.rb"
|
124
125
|
- "./lib/abt/providers/devops/commands/pick.rb"
|
125
126
|
- "./lib/abt/providers/devops/commands/share.rb"
|
126
127
|
- "./lib/abt/providers/devops/commands/work_items.rb"
|
127
128
|
- "./lib/abt/providers/devops/configuration.rb"
|
128
129
|
- "./lib/abt/providers/devops/path.rb"
|
130
|
+
- "./lib/abt/providers/devops/services/board_picker.rb"
|
131
|
+
- "./lib/abt/providers/devops/services/project_picker.rb"
|
132
|
+
- "./lib/abt/providers/devops/services/work_item_picker.rb"
|
129
133
|
- "./lib/abt/providers/git.rb"
|
130
134
|
- "./lib/abt/providers/git/commands/branch.rb"
|
131
135
|
- "./lib/abt/providers/harvest.rb"
|
@@ -133,7 +137,6 @@ files:
|
|
133
137
|
- "./lib/abt/providers/harvest/base_command.rb"
|
134
138
|
- "./lib/abt/providers/harvest/commands/clear.rb"
|
135
139
|
- "./lib/abt/providers/harvest/commands/current.rb"
|
136
|
-
- "./lib/abt/providers/harvest/commands/init.rb"
|
137
140
|
- "./lib/abt/providers/harvest/commands/pick.rb"
|
138
141
|
- "./lib/abt/providers/harvest/commands/projects.rb"
|
139
142
|
- "./lib/abt/providers/harvest/commands/share.rb"
|
@@ -143,6 +146,8 @@ files:
|
|
143
146
|
- "./lib/abt/providers/harvest/commands/track.rb"
|
144
147
|
- "./lib/abt/providers/harvest/configuration.rb"
|
145
148
|
- "./lib/abt/providers/harvest/path.rb"
|
149
|
+
- "./lib/abt/providers/harvest/services/project_picker.rb"
|
150
|
+
- "./lib/abt/providers/harvest/services/task_picker.rb"
|
146
151
|
- "./lib/abt/version.rb"
|
147
152
|
- bin/abt
|
148
153
|
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
|
-
abort("Must be run inside a git repository") unless config.local_available?
|
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"])
|
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,76 +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
|
-
abort("Must be run inside a git repository") unless config.local_available?
|
21
|
-
|
22
|
-
board = cli.prompt.choice("Select a project work board", boards)
|
23
|
-
|
24
|
-
config.path = Path.from_ids(organization_name, project_name, board["id"])
|
25
|
-
print_board(organization_name, project_name, board)
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def boards
|
31
|
-
@boards ||= api.get_paged("work/boards")
|
32
|
-
end
|
33
|
-
|
34
|
-
def project_name
|
35
|
-
@project_name ||= begin
|
36
|
-
if (match = AZURE_DEV_URL_REGEX.match(project_url)) ||
|
37
|
-
(match = VS_URL_REGEX.match(project_url))
|
38
|
-
match[:project]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def organization_name
|
44
|
-
@organization_name ||= begin
|
45
|
-
if (match = AZURE_DEV_URL_REGEX.match(project_url)) ||
|
46
|
-
(match = VS_URL_REGEX.match(project_url))
|
47
|
-
match[:organization]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def project_url
|
53
|
-
@project_url ||= begin
|
54
|
-
loop do
|
55
|
-
url = cli.prompt.text(project_url_prompt_text)
|
56
|
-
|
57
|
-
break url if AZURE_DEV_URL_REGEX =~ url || VS_URL_REGEX =~ url
|
58
|
-
|
59
|
-
warn("Invalid URL")
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def project_url_prompt_text
|
65
|
-
<<~TXT
|
66
|
-
Please provide the URL for the devops project
|
67
|
-
For instance https://{organization}.visualstudio.com/{project} or https://dev.azure.com/{organization}/{project}
|
68
|
-
|
69
|
-
Enter URL
|
70
|
-
TXT
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,54 +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
|
-
abort("Must be run inside a git repository") unless config.local_available?
|
18
|
-
|
19
|
-
projects # Load projects up front to make it obvious that searches are instant
|
20
|
-
project = cli.prompt.search("Select a project", searchable_projects)["project"]
|
21
|
-
|
22
|
-
config.path = Path.from_ids(project["id"])
|
23
|
-
|
24
|
-
print_project(project)
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def searchable_projects
|
30
|
-
@searchable_projects ||= projects.map do |project|
|
31
|
-
{
|
32
|
-
"name" => "#{project['client']['name']} > #{project['name']}",
|
33
|
-
"project" => project
|
34
|
-
}
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def projects
|
39
|
-
@projects ||= begin
|
40
|
-
warn("Fetching projects...")
|
41
|
-
project_assignments.map do |project_assignment|
|
42
|
-
project_assignment["project"].merge("client" => project_assignment["client"])
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def project_assignments
|
48
|
-
@project_assignments ||= api.get_paged("users/me/project_assignments")
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|