dude-cli 2.0.5 → 2.1.0.alpha3
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/.github/workflows/verify.yml +32 -0
- data/.rspec +0 -1
- data/.rubocop.yml +13 -0
- data/CHANGELOG.md +7 -3
- data/Gemfile +3 -1
- data/Gemfile.lock +62 -9
- data/LICENCE +20 -0
- data/README.md +60 -35
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/bin/dude +2 -2
- data/demo/dude.gif +0 -0
- data/demo/wizard.gif +0 -0
- data/dude.gemspec +26 -18
- data/lib/dude.rb +18 -7
- data/lib/dude/code_management.rb +10 -0
- data/lib/dude/code_management/github/client.rb +27 -0
- data/lib/dude/code_management/github/create_pull_request.rb +51 -0
- data/lib/dude/commands.rb +26 -17
- data/lib/dude/commands/checkout.rb +4 -2
- data/lib/dude/commands/health_check.rb +15 -0
- data/lib/dude/commands/install.rb +67 -43
- data/lib/dude/commands/move.rb +5 -3
- data/lib/dude/commands/pr.rb +11 -0
- data/lib/dude/commands/pr/create.rb +49 -0
- data/lib/dude/commands/pr/remove.rb +15 -0
- data/lib/dude/commands/start.rb +14 -10
- data/lib/dude/commands/stop.rb +4 -4
- data/lib/dude/commands/tasks.rb +6 -5
- data/lib/dude/commands/track.rb +7 -7
- data/lib/dude/commands/version.rb +3 -1
- data/lib/dude/config.rb +18 -0
- data/lib/dude/git.rb +3 -0
- data/lib/dude/git/checkout.rb +20 -1
- data/lib/dude/git/current_branch_name.rb +3 -1
- data/lib/dude/git/remote_name.rb +21 -0
- data/lib/dude/health_check.rb +39 -0
- data/lib/dude/project_management/client.rb +14 -7
- data/lib/dude/project_management/entities/issue.rb +10 -7
- data/lib/dude/project_management/jira.rb +2 -1
- data/lib/dude/project_management/jira/client.rb +35 -18
- data/lib/dude/project_management/jira/fetch_current_task.rb +35 -0
- data/lib/dude/project_management/jira/fetch_current_tasks.rb +46 -0
- data/lib/dude/project_management/jira/get_task_name_by_id.rb +1 -3
- data/lib/dude/project_management/jira/move_task_to_list.rb +15 -15
- data/lib/dude/project_management/{entities/board.rb → trello.rb} +3 -4
- data/lib/dude/project_management/trello/client.rb +56 -0
- data/lib/dude/project_management/trello/fetch_current_task.rb +41 -0
- data/lib/dude/project_management/trello/fetch_current_tasks.rb +51 -0
- data/lib/dude/project_management/trello/fetch_lists.rb +22 -0
- data/lib/dude/project_management/trello/get_task_name_by_id.rb +23 -0
- data/lib/dude/project_management/trello/move_task_to_list.rb +53 -0
- data/lib/dude/settings.rb +3 -0
- data/lib/dude/setup/github.rb +35 -0
- data/lib/dude/setup/jira.rb +64 -0
- data/lib/dude/setup/toggl.rb +47 -0
- data/lib/dude/setup/trello.rb +58 -0
- data/lib/dude/templates/duderc_template +32 -0
- data/lib/dude/time_trackers/toggl.rb +2 -0
- data/lib/dude/time_trackers/toggl/base.rb +4 -4
- data/lib/dude/time_trackers/toggl/start_time_entry.rb +3 -2
- data/lib/dude/time_trackers/toggl/stop_time_entry.rb +3 -1
- data/lib/dude/version.rb +3 -1
- metadata +99 -14
- data/lib/dude/project_management/jira/get_current_tasks.rb +0 -40
data/lib/dude/commands/stop.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../time_trackers/toggl/stop_time_entry'
|
2
4
|
|
3
5
|
module Dude
|
4
6
|
module Commands
|
5
7
|
class Stop < Dry::CLI::Command
|
6
|
-
|
7
|
-
|
8
|
-
desc "Stop current time entry in Toggl"
|
8
|
+
desc 'Stop current time entry in Toggl'
|
9
9
|
|
10
10
|
def call
|
11
11
|
Dude::Toggl::StopTimeEntry.new.call
|
data/lib/dude/commands/tasks.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../project_management/client'
|
2
4
|
|
3
5
|
module Dude
|
4
6
|
module Commands
|
5
7
|
class Tasks < Dry::CLI::Command
|
6
|
-
include Settings
|
7
|
-
|
8
8
|
desc "Print tasks as list with ID's and assignees"
|
9
9
|
|
10
10
|
def call
|
11
|
-
tasks = Dude::ProjectManagement::Client.new.
|
12
|
-
lists = tasks.map
|
11
|
+
tasks = Dude::ProjectManagement::Client.new.fetch_current_tasks
|
12
|
+
lists = tasks.map(&:status).uniq
|
13
13
|
|
14
14
|
lists.each do |list|
|
15
15
|
puts "#{list}:".green.bold
|
@@ -24,6 +24,7 @@ module Dude
|
|
24
24
|
|
25
25
|
def printable_issue_template(issue)
|
26
26
|
return "#{issue.id.to_s.bold}: #{issue.title}" + " (#{issue.assignee})".blue if issue.assignee
|
27
|
+
|
27
28
|
"#{issue.id.to_s.bold}: #{issue.title}"
|
28
29
|
end
|
29
30
|
end
|
data/lib/dude/commands/track.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../time_trackers/toggl/start_time_entry'
|
2
4
|
|
3
5
|
module Dude
|
4
6
|
module Commands
|
5
7
|
class Track < Dry::CLI::Command
|
6
|
-
|
7
|
-
|
8
|
-
desc "Start time entry in Toggl with issue title and id"
|
8
|
+
desc 'Start time entry in Toggl with issue title and id'
|
9
9
|
|
10
|
-
argument :id, required: true, desc:
|
10
|
+
argument :id, required: true, desc: 'The card short ID'
|
11
11
|
|
12
12
|
def call(id:)
|
13
13
|
@id = id
|
14
|
-
Dude::Toggl::StartTimeEntry.new.call(task_title: task_title, project:
|
14
|
+
Dude::Toggl::StartTimeEntry.new.call(task_title: task_title, project: Dude::SETTINGS.dig(:toggl, :project_name))
|
15
15
|
end
|
16
16
|
|
17
17
|
private
|
@@ -21,7 +21,7 @@ module Dude
|
|
21
21
|
def task_title
|
22
22
|
client = ProjectManagement::Client.new
|
23
23
|
issue_title = client.get_task_name_by_id(id)
|
24
|
-
|
24
|
+
Dude::SETTINGS.dig(:toggl, :task_format).sub(/{issue_id}/, id).sub(/{issue_title}/, issue_title)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
data/lib/dude/config.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dude
|
4
|
+
class Config
|
5
|
+
FILE_NAME = '.duderc.yml'
|
6
|
+
|
7
|
+
# Configure through yaml file
|
8
|
+
def self.configure_with(path_to_yaml_file)
|
9
|
+
YAML.safe_load(IO.read(path_to_yaml_file), [Symbol])
|
10
|
+
rescue StandardError
|
11
|
+
{}
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.style_prompt(text)
|
15
|
+
"#{'=>'.green.bold} #{text}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/dude/git.rb
CHANGED
data/lib/dude/git/checkout.rb
CHANGED
@@ -1,8 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dude
|
2
4
|
module Git
|
3
5
|
class Checkout
|
4
6
|
def call(branch_name)
|
5
|
-
|
7
|
+
@branch_name = branch_name
|
8
|
+
branch_exists? ? checkout_on_exising_branch : checkout_and_create
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
attr_reader :branch_name
|
14
|
+
|
15
|
+
def branch_exists?
|
16
|
+
!`git show-ref refs/heads/#{branch_name}`.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def checkout_and_create
|
20
|
+
`git checkout -b #{branch_name}`
|
21
|
+
end
|
22
|
+
|
23
|
+
def checkout_on_exising_branch
|
24
|
+
`git checkout #{branch_name}`
|
6
25
|
end
|
7
26
|
end
|
8
27
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dude
|
4
|
+
module Git
|
5
|
+
class RemoteName
|
6
|
+
def call
|
7
|
+
extract_name push_url
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def push_url
|
13
|
+
`git remote show origin`.split("\n")[1]
|
14
|
+
end
|
15
|
+
|
16
|
+
def extract_name(url)
|
17
|
+
url.scan(%r{(?<=github\.com[/:])(.*)(?=\.git)})[0][0]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './project_management/jira/client'
|
4
|
+
require_relative './project_management/trello/client'
|
5
|
+
|
6
|
+
module Dude
|
7
|
+
class HealthCheck
|
8
|
+
def call
|
9
|
+
validate(:jira, enabled: Dude::SETTINGS.dig(:jira, :token)) do
|
10
|
+
Dude::ProjectManagement::Jira::Client.new.health_check
|
11
|
+
end
|
12
|
+
|
13
|
+
validate(:trello, enabled: Dude::SETTINGS.dig(:trello, :token)) do
|
14
|
+
Dude::ProjectManagement::Trello::Client.new.health_check
|
15
|
+
end
|
16
|
+
|
17
|
+
validate(:github, enabled: Dude::SETTINGS.dig(:github, :token)) do
|
18
|
+
Dude::CodeManagement::Github::Client.new.health_check
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def validate(check, enabled:)
|
25
|
+
prepare_validation(check)
|
26
|
+
end_validation(check, enabled ? yield : nil, enabled: enabled)
|
27
|
+
end
|
28
|
+
|
29
|
+
def prepare_validation(check)
|
30
|
+
print "#{check.capitalize} status: [#{'WAIT'.yellow}]\r"
|
31
|
+
end
|
32
|
+
|
33
|
+
def end_validation(check, status, enabled: false)
|
34
|
+
return puts "#{check.capitalize} status: [#{'DISABLED'.blue}] " unless enabled
|
35
|
+
|
36
|
+
puts "#{check.capitalize} status: [#{status ? 'OK'.green : 'FAILURE'.red}] "
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,23 +1,30 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './jira/client'
|
4
|
+
require_relative './trello/client'
|
2
5
|
|
3
6
|
module Dude
|
4
7
|
module ProjectManagement
|
5
8
|
class Client
|
6
|
-
include Settings
|
7
|
-
|
8
9
|
attr_reader :client
|
9
10
|
|
10
11
|
def initialize
|
11
|
-
|
12
|
-
|
12
|
+
tool = Dude::SETTINGS[:project_management_tool]
|
13
|
+
return unless LIST_OF_AVAILABLE_PROJECT_MANAGEMENT_TOOLS.include? tool
|
14
|
+
|
15
|
+
@client = setup_client(tool)
|
13
16
|
end
|
14
17
|
|
15
18
|
def respond_to_missing?(method_name, include_private = false)
|
16
19
|
client.respond_to_missing?(method_name, include_private)
|
17
20
|
end
|
18
21
|
|
19
|
-
def method_missing(
|
20
|
-
client.send(
|
22
|
+
def method_missing(method, *args, &block)
|
23
|
+
client.send(method, *args, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup_client(tool)
|
27
|
+
Object.const_get("Dude::ProjectManagement::#{tool.capitalize}::Client").new
|
21
28
|
end
|
22
29
|
end
|
23
30
|
end
|
@@ -1,15 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dude
|
2
4
|
module ProjectManagement
|
3
5
|
module Entities
|
4
6
|
class Issue
|
5
|
-
attr_accessor :id, :title, :description, :status, :assignee
|
7
|
+
attr_accessor :id, :title, :description, :status, :assignee, :url
|
6
8
|
|
7
|
-
def initialize(
|
8
|
-
@id = id
|
9
|
-
@title = title
|
10
|
-
@description = description
|
11
|
-
@status = status
|
12
|
-
@assignee = assignee
|
9
|
+
def initialize(params)
|
10
|
+
@id = params[:id]
|
11
|
+
@title = params[:title]
|
12
|
+
@description = params[:description]
|
13
|
+
@status = params[:status]
|
14
|
+
@assignee = params[:assignee]
|
15
|
+
@url = params[:url]
|
13
16
|
end
|
14
17
|
|
15
18
|
def todo?
|
@@ -1,39 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'jira-ruby'
|
2
|
-
|
3
|
-
|
4
|
-
|
4
|
+
require_relative './fetch_current_tasks'
|
5
|
+
require_relative './fetch_current_task'
|
6
|
+
require_relative './move_task_to_list'
|
7
|
+
require_relative './get_task_name_by_id'
|
5
8
|
|
6
9
|
module Dude
|
7
10
|
module ProjectManagement
|
8
11
|
module Jira
|
9
12
|
class Client
|
10
|
-
include Settings
|
11
|
-
|
12
13
|
attr_reader :client, :project
|
13
14
|
|
14
|
-
|
15
|
-
options
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
class << self
|
16
|
+
def options
|
17
|
+
{
|
18
|
+
username: Dude::SETTINGS.dig(:jira, :email),
|
19
|
+
password: Dude::SETTINGS.dig(:jira, :token),
|
20
|
+
site: Dude::SETTINGS.dig(:jira, :project, :url),
|
21
|
+
context_path: '',
|
22
|
+
auth_type: :basic
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
22
26
|
|
27
|
+
def initialize
|
23
28
|
@client = JIRA::Client.new(options)
|
24
|
-
@project = client.Project.find(
|
29
|
+
@project = client.Project.find(Dude::SETTINGS.dig(:jira, :project, :key))
|
30
|
+
rescue StandardError
|
31
|
+
nil
|
25
32
|
end
|
26
33
|
|
27
34
|
def respond_to_missing?(method_name, include_private = false)
|
28
35
|
client.respond_to_missing?(method_name, include_private)
|
29
36
|
end
|
30
37
|
|
31
|
-
def method_missing(
|
32
|
-
client.send(
|
38
|
+
def method_missing(method, *args, &block)
|
39
|
+
client.send(method, *args, &block)
|
33
40
|
end
|
34
41
|
|
35
|
-
def
|
36
|
-
|
42
|
+
def fetch_current_tasks
|
43
|
+
FetchCurrentTasks.new(client).call
|
44
|
+
end
|
45
|
+
|
46
|
+
def fetch_current_task(id)
|
47
|
+
FetchCurrentTask.new(client, id: id).call
|
37
48
|
end
|
38
49
|
|
39
50
|
def move_task_to_list(id, list)
|
@@ -43,6 +54,12 @@ module Dude
|
|
43
54
|
def get_task_name_by_id(id)
|
44
55
|
GetTaskNameById.new(client, id: id).call
|
45
56
|
end
|
57
|
+
|
58
|
+
def health_check
|
59
|
+
@project && true
|
60
|
+
rescue StandardError
|
61
|
+
false
|
62
|
+
end
|
46
63
|
end
|
47
64
|
end
|
48
65
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../entities/issue'
|
4
|
+
|
5
|
+
module Dude
|
6
|
+
module ProjectManagement
|
7
|
+
module Jira
|
8
|
+
class FetchCurrentTask
|
9
|
+
def initialize(client, id:)
|
10
|
+
@client = client
|
11
|
+
@id = id
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
create_issue(client.Issue.find(id))
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :client, :id
|
21
|
+
|
22
|
+
def create_issue(issue)
|
23
|
+
Entities::Issue.new(
|
24
|
+
id: issue.key,
|
25
|
+
title: issue.summary,
|
26
|
+
description: issue.description,
|
27
|
+
status: issue.status.name,
|
28
|
+
assignee: issue&.assignee&.displayName,
|
29
|
+
url: "#{Dude::SETTINGS.dig(:dig, :project, :url)}/browse/#{issue.key}"
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../entities/issue'
|
4
|
+
|
5
|
+
module Dude
|
6
|
+
module ProjectManagement
|
7
|
+
module Jira
|
8
|
+
class FetchCurrentTasks
|
9
|
+
def initialize(client)
|
10
|
+
@client = client
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
board = client.Board.find(Dude::SETTINGS.dig(:jira, :board_id))
|
15
|
+
|
16
|
+
all_issues = board_type(board)
|
17
|
+
|
18
|
+
all_issues.map { |issue| create_issue(issue) }
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :client
|
24
|
+
|
25
|
+
def board_type(board)
|
26
|
+
case board.type
|
27
|
+
when 'kanban' then board.issues
|
28
|
+
when 'simple', 'scrum' then board.sprints(state: 'active').flat_map(&:issues)
|
29
|
+
else raise Dude::ToBeImplementedError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_issue(issue)
|
34
|
+
Entities::Issue.new(
|
35
|
+
id: issue.key,
|
36
|
+
title: issue.summary,
|
37
|
+
description: issue.description,
|
38
|
+
status: issue.status.name,
|
39
|
+
assignee: issue&.assignee&.displayName,
|
40
|
+
url: "#{Dude::SETTINGS.dig(:jira, :project, :url)}/browse/#{issue.key}"
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|