dude-cli 2.0.7 → 2.1.0.alpha5
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/.rspec +0 -1
- data/.rubocop.yml +5 -1
- data/Gemfile.lock +36 -15
- data/README.md +43 -35
- data/dude.gemspec +3 -2
- data/lib/dude.rb +12 -2
- 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 +61 -0
- data/lib/dude/commands.rb +7 -0
- data/lib/dude/commands/health_check.rb +15 -0
- data/lib/dude/commands/install.rb +63 -41
- 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 +10 -8
- data/lib/dude/commands/stop.rb +0 -2
- data/lib/dude/commands/tasks.rb +0 -2
- data/lib/dude/commands/track.rb +2 -4
- data/lib/dude/config.rb +18 -0
- data/lib/dude/git.rb +1 -0
- data/lib/dude/git/remote_name.rb +21 -0
- data/lib/dude/health_check.rb +39 -0
- data/lib/dude/project_management/client.rb +8 -4
- data/lib/dude/project_management/entities/issue.rb +8 -7
- data/lib/dude/project_management/jira/client.rb +21 -8
- data/lib/dude/project_management/jira/fetch_current_task.rb +37 -0
- data/lib/dude/project_management/jira/fetch_current_tasks.rb +3 -4
- data/lib/dude/project_management/jira/get_task_name_by_id.rb +0 -2
- data/lib/dude/project_management/jira/move_task_to_list.rb +0 -2
- data/lib/dude/project_management/{entities/board.rb → trello.rb} +1 -3
- 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/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/base.rb +2 -4
- data/lib/dude/version.rb +1 -1
- metadata +42 -6
@@ -0,0 +1,37 @@
|
|
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
|
+
rescue JIRA::HTTPError
|
17
|
+
puts "#{'Error:'.red.bold} Task #{id.bold} not found. Try again with correct task ID"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :client, :id
|
23
|
+
|
24
|
+
def create_issue(issue)
|
25
|
+
Entities::Issue.new(
|
26
|
+
id: issue.key,
|
27
|
+
title: issue.summary,
|
28
|
+
description: issue.description,
|
29
|
+
status: issue.status.name,
|
30
|
+
assignee: issue&.assignee&.displayName,
|
31
|
+
url: "#{Dude::SETTINGS.dig(:dig, :project, :url)}/browse/#{issue.key}"
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -6,14 +6,12 @@ module Dude
|
|
6
6
|
module ProjectManagement
|
7
7
|
module Jira
|
8
8
|
class FetchCurrentTasks
|
9
|
-
include Settings
|
10
|
-
|
11
9
|
def initialize(client)
|
12
10
|
@client = client
|
13
11
|
end
|
14
12
|
|
15
13
|
def call
|
16
|
-
board = client.Board.find(
|
14
|
+
board = client.Board.find(Dude::SETTINGS.dig(:jira, :board_id))
|
17
15
|
|
18
16
|
all_issues = board_type(board)
|
19
17
|
|
@@ -38,7 +36,8 @@ module Dude
|
|
38
36
|
title: issue.summary,
|
39
37
|
description: issue.description,
|
40
38
|
status: issue.status.name,
|
41
|
-
assignee: issue&.assignee&.displayName
|
39
|
+
assignee: issue&.assignee&.displayName,
|
40
|
+
url: "#{Dude::SETTINGS.dig(:jira, :project, :url)}/browse/#{issue.key}"
|
42
41
|
)
|
43
42
|
end
|
44
43
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './fetch_current_tasks'
|
4
|
+
require_relative './fetch_current_task'
|
5
|
+
require_relative './move_task_to_list'
|
6
|
+
require_relative './get_task_name_by_id'
|
7
|
+
|
8
|
+
require 'faraday'
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
module Dude
|
12
|
+
module ProjectManagement
|
13
|
+
module Trello
|
14
|
+
class Client
|
15
|
+
def client
|
16
|
+
@client ||= Faraday.new('https://api.trello.com/', {
|
17
|
+
params: {
|
18
|
+
key: Dude::SETTINGS.dig(:trello, :key),
|
19
|
+
token: Dude::SETTINGS.dig(:trello, :token)
|
20
|
+
}
|
21
|
+
})
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(method, *args, &block)
|
25
|
+
faraday_client.send(method, *args, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def respond_to_missing?(method_name, include_private = false)
|
29
|
+
client.respond_to?(method_name, include_private)
|
30
|
+
end
|
31
|
+
|
32
|
+
def fetch_current_tasks
|
33
|
+
FetchCurrentTasks.new(client).call
|
34
|
+
end
|
35
|
+
|
36
|
+
def fetch_current_task(id)
|
37
|
+
FetchCurrentTask.new(client, id: id).call
|
38
|
+
end
|
39
|
+
|
40
|
+
def move_task_to_list(id, list)
|
41
|
+
MoveTaskToList.new(client, id: id, list_name: list).call
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_task_name_by_id(id)
|
45
|
+
GetTaskNameById.new(client, id: id).call
|
46
|
+
end
|
47
|
+
|
48
|
+
def health_check
|
49
|
+
client.get("/1/tokens/#{Dude::SETTINGS.dig(:trello, :token)}").status == 200
|
50
|
+
rescue StandardError
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dude
|
4
|
+
module ProjectManagement
|
5
|
+
module Trello
|
6
|
+
class FetchCurrentTask
|
7
|
+
def initialize(client, id:)
|
8
|
+
@client = client
|
9
|
+
@id = id
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
response = client.get("/1/boards/#{Dude::SETTINGS.dig(:jira, :board_id)}/cards/#{id}")
|
14
|
+
create_issue JSON.parse(response.body)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :client, :id
|
20
|
+
|
21
|
+
def create_issue(issue)
|
22
|
+
Entities::Issue.new(
|
23
|
+
id: issue['idShort'],
|
24
|
+
title: issue['name'],
|
25
|
+
description: issue['desc'],
|
26
|
+
status: Dude::SETTINGS[:in_progress_list_name], # OMG, let's fix this later
|
27
|
+
assignee: members(issue),
|
28
|
+
url: issue['shortUrl']
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def members(issue)
|
33
|
+
people = issue['idMembers'].map do |person|
|
34
|
+
JSON.parse(client.get("/1/members/#{person}", fields: 'fullName').body)['fullName']
|
35
|
+
end
|
36
|
+
people.empty? ? nil : people.join(', ')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './fetch_lists'
|
4
|
+
|
5
|
+
module Dude
|
6
|
+
module ProjectManagement
|
7
|
+
module Trello
|
8
|
+
class FetchCurrentTasks
|
9
|
+
attr_reader :fetch_lists
|
10
|
+
|
11
|
+
def initialize(client, fetch_lists: nil)
|
12
|
+
@client = client
|
13
|
+
|
14
|
+
@fetch_lists = fetch_lists || FetchLists.new(client)
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
lists = fetch_lists.call
|
19
|
+
lists.map { |list| retrieve_list_issues(list) }.flatten
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :client
|
25
|
+
|
26
|
+
def retrieve_list_issues(list)
|
27
|
+
response = client.get("/1/lists/#{list['id']}/cards")
|
28
|
+
body = JSON.parse(response.body)
|
29
|
+
body.map { |issue| create_issue(issue, list) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_issue(issue, current_list)
|
33
|
+
Entities::Issue.new(
|
34
|
+
id: issue['idShort'],
|
35
|
+
title: issue['name'],
|
36
|
+
description: issue['desc'],
|
37
|
+
status: current_list['name'],
|
38
|
+
assignee: members(issue)
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def members(issue)
|
43
|
+
people = issue['idMembers'].map do |person|
|
44
|
+
JSON.parse(client.get("/1/members/#{person}", fields: 'fullName').body)['fullName']
|
45
|
+
end
|
46
|
+
people.empty? ? nil : people.join(', ')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dude
|
4
|
+
module ProjectManagement
|
5
|
+
module Trello
|
6
|
+
class FetchLists
|
7
|
+
def initialize(client)
|
8
|
+
@client = client
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
response = client.get("/1/board/#{Dude::SETTINGS.dig(:jira, :board_id)}/lists", { fields: 'name' })
|
13
|
+
JSON.parse(response.body)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :client
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dude
|
4
|
+
module ProjectManagement
|
5
|
+
module Trello
|
6
|
+
class GetTaskNameById
|
7
|
+
def initialize(client, id:)
|
8
|
+
@client = client
|
9
|
+
@id = id
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
response = client.get("/1/boards/#{Dude::SETTINGS.dig(:jira, :board_id)}/cards/#{id}")
|
14
|
+
JSON.parse(response.body)['name']
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :client, :id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './fetch_lists'
|
4
|
+
|
5
|
+
module Dude
|
6
|
+
module ProjectManagement
|
7
|
+
module Trello
|
8
|
+
class MoveTaskToList
|
9
|
+
def initialize(client, id:, list_name:)
|
10
|
+
@client = client
|
11
|
+
@id = id
|
12
|
+
@list_name = list_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
response = client.get("/1/boards/#{Dude::SETTINGS.dig(:jira, :board_id)}/cards/#{id}", { fields: 'id' })
|
17
|
+
card_id = JSON.parse(response.body)['id']
|
18
|
+
client.put("/1/cards/#{card_id}", { idList: list_id })
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :client, :id, :list_name
|
24
|
+
|
25
|
+
def list_id
|
26
|
+
if list_name
|
27
|
+
lists.find { |list| list['name'] == list_name }['id']
|
28
|
+
else
|
29
|
+
select_list_for_moving['id']
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def select_list_for_moving
|
34
|
+
puts 'Please, select list for moving:'.green.bold
|
35
|
+
|
36
|
+
print_lists
|
37
|
+
|
38
|
+
print "\nList index: ".bold
|
39
|
+
list_index = $stdin.gets.chomp
|
40
|
+
lists[list_index.to_i - 1]
|
41
|
+
end
|
42
|
+
|
43
|
+
def print_lists
|
44
|
+
lists.map { |list| list['name'] }.each_with_index { |name, index| puts "#{index + 1}: #{name.bold}" }
|
45
|
+
end
|
46
|
+
|
47
|
+
def lists
|
48
|
+
@lists ||= FetchLists.new(client).call
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dude
|
4
|
+
module Setup
|
5
|
+
class Github
|
6
|
+
def initialize(prompt)
|
7
|
+
@prompt = prompt
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(settings:)
|
11
|
+
settings[:github][:token] = setup_token
|
12
|
+
settings
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_reader :prompt
|
18
|
+
|
19
|
+
def setup_token
|
20
|
+
puts <<~HEREDOC
|
21
|
+
You need to create personal token
|
22
|
+
|
23
|
+
#{'1.'.bold} Log in to https://github.com/settings/tokens
|
24
|
+
#{'2.'.bold} Copy the token and paste it below
|
25
|
+
HEREDOC
|
26
|
+
|
27
|
+
if prompt.yes?(Dude::Config.style_prompt('Open Github token creation page in your browser?'))
|
28
|
+
`open https://github.com/settings/tokens`
|
29
|
+
end
|
30
|
+
|
31
|
+
prompt.ask(Dude::Config.style_prompt('Github token:'), required: true)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dude
|
4
|
+
module Setup
|
5
|
+
class Jira
|
6
|
+
def initialize(prompt)
|
7
|
+
@prompt = prompt
|
8
|
+
end
|
9
|
+
|
10
|
+
# rubocop:disable Metrics/AbcSize
|
11
|
+
def call(settings:)
|
12
|
+
settings[:jira][:email] = setup_email
|
13
|
+
settings[:jira][:token] = setup_token
|
14
|
+
settings[:jira][:project][:url] = setup_project_url
|
15
|
+
settings[:jira][:project][:key] = setup_project_key
|
16
|
+
settings[:jira][:board_id] = setup_board_id
|
17
|
+
settings
|
18
|
+
end
|
19
|
+
# rubocop:enable Metrics/AbcSize
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :prompt
|
24
|
+
|
25
|
+
def setup_email
|
26
|
+
prompt.ask(Dude::Config.style_prompt('Jira user email:'), required: true)
|
27
|
+
end
|
28
|
+
|
29
|
+
def setup_token
|
30
|
+
puts <<~HEREDOC
|
31
|
+
You need to create personal token
|
32
|
+
|
33
|
+
#{'1.'.bold} Log in to https://id.atlassian.com/manage/api-tokens
|
34
|
+
#{'2.'.bold} Click 'Create API token.'
|
35
|
+
#{'3.'.bold} From the dialog that appears, enter a memorable and concise 'Label' for your token and click 'Create.'
|
36
|
+
#{'4.'.bold} Use 'Copy to clipboard' and paste the token below
|
37
|
+
HEREDOC
|
38
|
+
|
39
|
+
if prompt.yes?(Dude::Config.style_prompt('Open Atlassian token creation page in your browser?'))
|
40
|
+
`open https://id.atlassian.com/manage-profile/security/api-tokens`
|
41
|
+
end
|
42
|
+
|
43
|
+
prompt.ask(Dude::Config.style_prompt('Jira token:'), required: true)
|
44
|
+
end
|
45
|
+
|
46
|
+
def setup_project_url
|
47
|
+
prompt.ask(Dude::Config.style_prompt('URL of your project (Example: https://example.atlassian.net):'), {
|
48
|
+
required: true
|
49
|
+
})
|
50
|
+
end
|
51
|
+
|
52
|
+
def setup_project_key
|
53
|
+
prompt.ask(Dude::Config.style_prompt('KEY of your project (If your issues have id BT-123 - BT is the key):'), {
|
54
|
+
required: true
|
55
|
+
})
|
56
|
+
end
|
57
|
+
|
58
|
+
def setup_board_id
|
59
|
+
puts 'Just open your atlassian main board and copy id from the url after rapidView=ID part.'
|
60
|
+
prompt.ask(Dude::Config.style_prompt('Board ID:'), required: true)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|