abt-cli 0.0.26 → 0.0.27
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/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/current.rb +0 -18
- 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/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 +34 -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 +0 -19
- data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +10 -16
- data/lib/abt/providers/devops/commands/pick.rb +14 -53
- data/lib/abt/providers/devops/commands/work_items.rb +3 -6
- data/lib/abt/providers/devops/path.rb +2 -2
- 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/harvest.rb +1 -0
- data/lib/abt/providers/harvest/base_command.rb +45 -3
- 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 +0 -5
- data/lib/abt/providers/harvest/commands/tasks.rb +1 -16
- 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 +9 -5
- data/lib/abt/providers/asana/commands/init.rb +0 -42
- data/lib/abt/providers/devops/commands/init.rb +0 -79
- data/lib/abt/providers/harvest/commands/init.rb +0 -53
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
Dir.glob("#{File.expand_path(__dir__)}/harvest/*.rb").sort.each { |file| require file }
|
4
4
|
Dir.glob("#{File.expand_path(__dir__)}/harvest/commands/*.rb").sort.each { |file| require file }
|
5
|
+
Dir.glob("#{File.expand_path(__dir__)}/harvest/services/*.rb").sort.each { |file| require file }
|
5
6
|
|
6
7
|
module Abt
|
7
8
|
module Providers
|
@@ -26,13 +26,55 @@ module Abt
|
|
26
26
|
def require_project!
|
27
27
|
return if project_id
|
28
28
|
|
29
|
-
abort("No current/specified project. Did you
|
29
|
+
abort("No current/specified project. Did you forget to run `pick`?")
|
30
30
|
end
|
31
31
|
|
32
32
|
def require_task!
|
33
|
-
|
33
|
+
require_project!
|
34
|
+
return if task_id
|
34
35
|
|
35
|
-
abort("No current/specified task. Did you
|
36
|
+
abort("No current/specified task. Did you forget to run `pick`?")
|
37
|
+
end
|
38
|
+
|
39
|
+
def prompt_project!
|
40
|
+
result = Services::ProjectPicker.call(cli: cli, project_assignments: project_assignments)
|
41
|
+
@path = result.path
|
42
|
+
@project = result.project
|
43
|
+
end
|
44
|
+
|
45
|
+
def prompt_task!
|
46
|
+
result = Services::TaskPicker.call(cli: cli, path: path, project_assignment: project_assignment)
|
47
|
+
@path = result.path
|
48
|
+
@task = result.task
|
49
|
+
end
|
50
|
+
|
51
|
+
def task
|
52
|
+
return @task if instance_variable_defined?(:@task)
|
53
|
+
|
54
|
+
@task = if project_assignment
|
55
|
+
project_assignment["task_assignments"].map { |ta| ta["task"] }.find do |task|
|
56
|
+
task["id"].to_s == task_id
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def project
|
62
|
+
return @project if instance_variable_defined?(:@project)
|
63
|
+
|
64
|
+
@project = if project_assignment
|
65
|
+
project_assignment["project"].merge("client" => project_assignment["client"])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def project_assignment
|
70
|
+
@project_assignment ||= project_assignments.find { |pa| pa["project"]["id"].to_s == path.project_id }
|
71
|
+
end
|
72
|
+
|
73
|
+
def project_assignments
|
74
|
+
@project_assignments ||= begin
|
75
|
+
warn("Fetching Harvest data...")
|
76
|
+
api.get_paged("users/me/project_assignments")
|
77
|
+
end
|
36
78
|
end
|
37
79
|
|
38
80
|
def print_project(project)
|
@@ -40,34 +40,6 @@ module Abt
|
|
40
40
|
abort("Invalid project: #{project_id}") if project.nil?
|
41
41
|
abort("Invalid task: #{task_id}") if task_id && task.nil?
|
42
42
|
end
|
43
|
-
|
44
|
-
def project
|
45
|
-
return @project if instance_variable_defined?(:@project)
|
46
|
-
|
47
|
-
@project = if project_assignment
|
48
|
-
project_assignment["project"].merge("client" => project_assignment["client"])
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def task
|
53
|
-
return @task if instance_variable_defined?(:@task)
|
54
|
-
|
55
|
-
@task = if project_assignment
|
56
|
-
project_assignment["task_assignments"].map { |ta| ta["task"] }.find do |task|
|
57
|
-
task["id"].to_s == task_id
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def project_assignment
|
63
|
-
@project_assignment ||= begin
|
64
|
-
project_assignments.find { |pa| pa["project"]["id"].to_s == project_id }
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def project_assignments
|
69
|
-
@project_assignments ||= api.get_paged("users/me/project_assignments")
|
70
|
-
end
|
71
43
|
end
|
72
44
|
end
|
73
45
|
end
|
@@ -15,46 +15,31 @@ module Abt
|
|
15
15
|
|
16
16
|
def self.flags
|
17
17
|
[
|
18
|
-
["-d", "--dry-run", "Keep existing configuration"]
|
18
|
+
["-d", "--dry-run", "Keep existing configuration"],
|
19
|
+
["-c", "--clean", "Don't reuse project configuration"]
|
19
20
|
]
|
20
21
|
end
|
21
22
|
|
22
23
|
def perform
|
23
|
-
|
24
|
-
require_project!
|
25
|
-
|
26
|
-
warn(project["name"])
|
27
|
-
task = pick_task
|
24
|
+
pick!
|
28
25
|
|
29
26
|
print_task(project, task)
|
30
27
|
|
31
28
|
return if flags[:"dry-run"]
|
32
29
|
|
33
|
-
config.
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def project
|
39
|
-
project_assignment["project"]
|
40
|
-
end
|
41
|
-
|
42
|
-
def pick_task
|
43
|
-
cli.prompt.choice("Select a task", tasks)
|
44
|
-
end
|
30
|
+
unless config.local_available?
|
31
|
+
warn("No local configuration to update - will function as dry run")
|
32
|
+
return
|
33
|
+
end
|
45
34
|
|
46
|
-
|
47
|
-
@tasks ||= project_assignment["task_assignments"].map { |ta| ta["task"] }
|
35
|
+
config.path = Path.from_ids(project_id: project["id"], task_id: task["id"])
|
48
36
|
end
|
49
37
|
|
50
|
-
|
51
|
-
@project_assignment ||= begin
|
52
|
-
project_assignments.find { |pa| pa["project"]["id"].to_s == project_id }
|
53
|
-
end
|
54
|
-
end
|
38
|
+
private
|
55
39
|
|
56
|
-
def
|
57
|
-
|
40
|
+
def pick!
|
41
|
+
prompt_project! if project_id.nil? || flags[:clean]
|
42
|
+
prompt_task!
|
58
43
|
end
|
59
44
|
end
|
60
45
|
end
|
@@ -23,16 +23,11 @@ module Abt
|
|
23
23
|
|
24
24
|
def projects
|
25
25
|
@projects ||= begin
|
26
|
-
warn("Fetching projects...")
|
27
26
|
project_assignments.map do |project_assignment|
|
28
27
|
project_assignment["project"].merge("client" => project_assignment["client"])
|
29
28
|
end
|
30
29
|
end
|
31
30
|
end
|
32
|
-
|
33
|
-
def project_assignments
|
34
|
-
@project_assignments ||= api.get_paged("users/me/project_assignments")
|
35
|
-
end
|
36
31
|
end
|
37
32
|
end
|
38
33
|
end
|
@@ -14,7 +14,7 @@ module Abt
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def perform
|
17
|
-
|
17
|
+
prompt_project! unless project_id
|
18
18
|
|
19
19
|
tasks.each do |task|
|
20
20
|
print_task(project, task)
|
@@ -23,26 +23,11 @@ module Abt
|
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
|
-
def project
|
27
|
-
project_assignment["project"]
|
28
|
-
end
|
29
|
-
|
30
26
|
def tasks
|
31
27
|
@tasks ||= begin
|
32
|
-
warn("Fetching tasks...")
|
33
28
|
project_assignment["task_assignments"].map { |ta| ta["task"] }
|
34
29
|
end
|
35
30
|
end
|
36
|
-
|
37
|
-
def project_assignment
|
38
|
-
@project_assignment ||= begin
|
39
|
-
project_assignments.find { |pa| pa["project"]["id"].to_s == project_id }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def project_assignments
|
44
|
-
@project_assignments ||= api.get_paged("users/me/project_assignments")
|
45
|
-
end
|
46
31
|
end
|
47
32
|
end
|
48
33
|
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
|
@@ -105,7 +105,6 @@ 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"
|
@@ -113,6 +112,8 @@ files:
|
|
113
112
|
- "./lib/abt/providers/asana/commands/tasks.rb"
|
114
113
|
- "./lib/abt/providers/asana/configuration.rb"
|
115
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"
|
116
117
|
- "./lib/abt/providers/devops.rb"
|
117
118
|
- "./lib/abt/providers/devops/api.rb"
|
118
119
|
- "./lib/abt/providers/devops/base_command.rb"
|
@@ -121,12 +122,14 @@ files:
|
|
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
128
|
- "./lib/abt/providers/devops/configuration.rb"
|
129
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"
|
130
133
|
- "./lib/abt/providers/git.rb"
|
131
134
|
- "./lib/abt/providers/git/commands/branch.rb"
|
132
135
|
- "./lib/abt/providers/harvest.rb"
|
@@ -134,7 +137,6 @@ files:
|
|
134
137
|
- "./lib/abt/providers/harvest/base_command.rb"
|
135
138
|
- "./lib/abt/providers/harvest/commands/clear.rb"
|
136
139
|
- "./lib/abt/providers/harvest/commands/current.rb"
|
137
|
-
- "./lib/abt/providers/harvest/commands/init.rb"
|
138
140
|
- "./lib/abt/providers/harvest/commands/pick.rb"
|
139
141
|
- "./lib/abt/providers/harvest/commands/projects.rb"
|
140
142
|
- "./lib/abt/providers/harvest/commands/share.rb"
|
@@ -144,6 +146,8 @@ files:
|
|
144
146
|
- "./lib/abt/providers/harvest/commands/track.rb"
|
145
147
|
- "./lib/abt/providers/harvest/configuration.rb"
|
146
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"
|
147
151
|
- "./lib/abt/version.rb"
|
148
152
|
- bin/abt
|
149
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
|
-
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,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
|