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.
- checksums.yaml +4 -4
- data/bin/abt +3 -3
- data/lib/abt.rb +6 -6
- data/lib/abt/ari.rb +1 -1
- data/lib/abt/ari_list.rb +1 -1
- data/lib/abt/base_command.rb +7 -7
- data/lib/abt/cli.rb +27 -40
- data/lib/abt/cli/arguments_parser.rb +5 -9
- data/lib/abt/cli/global_commands.rb +23 -0
- data/lib/abt/cli/global_commands/commands.rb +2 -2
- data/lib/abt/cli/global_commands/examples.rb +2 -2
- data/lib/abt/cli/global_commands/help.rb +2 -2
- data/lib/abt/cli/global_commands/readme.rb +2 -2
- data/lib/abt/cli/global_commands/share.rb +6 -6
- data/lib/abt/cli/global_commands/version.rb +2 -2
- data/lib/abt/cli/prompt.rb +51 -20
- data/lib/abt/docs.rb +39 -33
- data/lib/abt/docs/cli.rb +3 -3
- data/lib/abt/docs/markdown.rb +5 -5
- data/lib/abt/git_config.rb +4 -6
- data/lib/abt/providers/asana/api.rb +9 -9
- data/lib/abt/providers/asana/base_command.rb +8 -10
- data/lib/abt/providers/asana/commands/add.rb +13 -12
- data/lib/abt/providers/asana/commands/branch_name.rb +8 -8
- data/lib/abt/providers/asana/commands/clear.rb +7 -8
- data/lib/abt/providers/asana/commands/current.rb +14 -14
- data/lib/abt/providers/asana/commands/finalize.rb +11 -12
- data/lib/abt/providers/asana/commands/harvest_time_entry_data.rb +11 -11
- data/lib/abt/providers/asana/commands/init.rb +8 -41
- data/lib/abt/providers/asana/commands/pick.rb +17 -17
- data/lib/abt/providers/asana/commands/projects.rb +5 -5
- data/lib/abt/providers/asana/commands/share.rb +5 -5
- data/lib/abt/providers/asana/commands/start.rb +21 -20
- data/lib/abt/providers/asana/commands/tasks.rb +6 -6
- data/lib/abt/providers/asana/configuration.rb +25 -25
- data/lib/abt/providers/asana/path.rb +5 -5
- data/lib/abt/providers/devops/api.rb +12 -12
- data/lib/abt/providers/devops/base_command.rb +10 -10
- data/lib/abt/providers/devops/commands/boards.rb +5 -7
- data/lib/abt/providers/devops/commands/branch_name.rb +9 -9
- data/lib/abt/providers/devops/commands/clear.rb +7 -8
- data/lib/abt/providers/devops/commands/current.rb +17 -17
- data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +13 -13
- data/lib/abt/providers/devops/commands/init.rb +17 -13
- data/lib/abt/providers/devops/commands/pick.rb +11 -11
- data/lib/abt/providers/devops/commands/share.rb +5 -5
- data/lib/abt/providers/devops/commands/{work-items.rb → work_items.rb} +3 -3
- data/lib/abt/providers/devops/configuration.rb +19 -15
- data/lib/abt/providers/devops/path.rb +5 -4
- data/lib/abt/providers/git/commands/branch.rb +17 -19
- data/lib/abt/providers/harvest/api.rb +8 -8
- data/lib/abt/providers/harvest/base_command.rb +6 -8
- data/lib/abt/providers/harvest/commands/clear.rb +7 -8
- data/lib/abt/providers/harvest/commands/current.rb +13 -13
- data/lib/abt/providers/harvest/commands/init.rb +10 -38
- data/lib/abt/providers/harvest/commands/pick.rb +11 -11
- data/lib/abt/providers/harvest/commands/projects.rb +5 -5
- data/lib/abt/providers/harvest/commands/share.rb +5 -5
- data/lib/abt/providers/harvest/commands/start.rb +5 -3
- data/lib/abt/providers/harvest/commands/stop.rb +12 -12
- data/lib/abt/providers/harvest/commands/tasks.rb +7 -7
- data/lib/abt/providers/harvest/commands/track.rb +21 -20
- data/lib/abt/providers/harvest/configuration.rb +18 -18
- data/lib/abt/providers/harvest/path.rb +5 -5
- data/lib/abt/version.rb +1 -1
- metadata +6 -5
@@ -22,28 +22,26 @@ module Abt
|
|
22
22
|
def require_project!
|
23
23
|
return if project_id
|
24
24
|
|
25
|
-
abort
|
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
|
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
|
-
|
39
|
-
project[
|
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
|
-
|
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
|
-
|
9
|
+
"abt clear harvest"
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.description
|
13
|
-
|
13
|
+
"Clear harvest configuration"
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.flags
|
17
17
|
[
|
18
|
-
[
|
19
|
-
|
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
|
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
|
-
|
9
|
+
"abt current harvest[:<project-id>[/<task-id>]]"
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.description
|
13
|
-
|
13
|
+
"Get or set project and or task for current git repository"
|
14
14
|
end
|
15
15
|
|
16
16
|
def perform
|
17
|
-
abort
|
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
|
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
|
42
|
-
abort
|
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?
|
46
|
+
return @project if instance_variable_defined?(:@project)
|
47
47
|
|
48
48
|
@project = if project_assignment
|
49
|
-
project_assignment[
|
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?
|
54
|
+
return @task if instance_variable_defined?(:@task)
|
55
55
|
|
56
56
|
@task = if project_assignment
|
57
|
-
project_assignment[
|
58
|
-
task[
|
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[
|
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(
|
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
|
-
|
9
|
+
"abt init harvest"
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.description
|
13
|
-
|
13
|
+
"Pick Harvest project for current git repository"
|
14
14
|
end
|
15
15
|
|
16
16
|
def perform
|
17
|
-
abort
|
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 =
|
20
|
+
project = cli.prompt.search("Select a project", searchable_projects)["project"]
|
21
21
|
|
22
|
-
config.path = Path.from_ids(project[
|
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
|
-
|
61
|
-
|
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
|
40
|
+
warn("Fetching projects...")
|
69
41
|
project_assignments.map do |project_assignment|
|
70
|
-
project_assignment[
|
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(
|
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
|
-
|
9
|
+
"abt pick harvest[:<project-id>]"
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.description
|
13
|
-
|
13
|
+
"Pick task for current git repository"
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.flags
|
17
17
|
[
|
18
|
-
[
|
18
|
+
["-d", "--dry-run", "Keep existing configuration"]
|
19
19
|
]
|
20
20
|
end
|
21
21
|
|
22
22
|
def perform
|
23
|
-
abort
|
23
|
+
abort("Must be run inside a git repository") unless config.local_available?
|
24
24
|
require_project!
|
25
25
|
|
26
|
-
warn
|
27
|
-
task = cli.prompt.choice
|
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[
|
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[
|
39
|
+
project_assignment["project"]
|
40
40
|
end
|
41
41
|
|
42
42
|
def tasks
|
43
|
-
@tasks ||= project_assignment[
|
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[
|
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(
|
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
|
-
|
9
|
+
"abt projects harvest"
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.description
|
13
|
-
|
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
|
26
|
+
warn("Fetching projects...")
|
27
27
|
project_assignments.map do |project_assignment|
|
28
|
-
project_assignment[
|
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(
|
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
|
-
|
9
|
+
"abt share harvest[:<project-id>[/<task-id>]]"
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.description
|
13
|
-
|
13
|
+
"Print project/task ARI"
|
14
14
|
end
|
15
15
|
|
16
16
|
def perform
|
17
|
-
if path !=
|
18
|
-
cli.print_ari(
|
17
|
+
if path != ""
|
18
|
+
cli.print_ari("harvest", path)
|
19
19
|
elsif cli.output.isatty
|
20
|
-
warn
|
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
|
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
|
-
|
11
|
+
"abt start harvest[:<project-id>/<task-id>] [options]"
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.description
|
15
|
-
|
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
|
-
|
9
|
+
"abt stop harvest"
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.description
|
13
|
-
|
13
|
+
"Stop running harvest tracker"
|
14
14
|
end
|
15
15
|
|
16
16
|
def perform
|
17
|
-
abort
|
17
|
+
abort("No running time entry") if time_entry.nil?
|
18
18
|
|
19
19
|
stop_time_entry
|
20
20
|
|
21
|
-
warn
|
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
|
31
|
-
abort
|
30
|
+
warn(e)
|
31
|
+
abort("Unable to stop time entry")
|
32
32
|
end
|
33
33
|
|
34
34
|
def project
|
35
|
-
time_entry[
|
35
|
+
time_entry["project"]
|
36
36
|
end
|
37
37
|
|
38
38
|
def task
|
39
|
-
time_entry[
|
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
|
-
|
45
|
+
"time_entries",
|
46
46
|
is_running: true,
|
47
47
|
user_id: config.user_id
|
48
48
|
).first
|
49
|
-
rescue Abt::HttpError::HttpError => e
|
50
|
-
warn
|
51
|
-
abort
|
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
|
-
|
9
|
+
"abt tasks harvest"
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.description
|
13
|
-
|
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[
|
27
|
+
project_assignment["project"]
|
28
28
|
end
|
29
29
|
|
30
30
|
def tasks
|
31
31
|
@tasks ||= begin
|
32
|
-
warn
|
33
|
-
project_assignment[
|
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[
|
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(
|
44
|
+
@project_assignments ||= api.get_paged("users/me/project_assignments")
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|