dude-cli 2.0.3 → 2.1.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/verify.yml +32 -0
  3. data/.rspec +0 -1
  4. data/.rubocop.yml +13 -0
  5. data/CHANGELOG.md +7 -3
  6. data/Gemfile +3 -1
  7. data/Gemfile.lock +48 -9
  8. data/LICENCE +20 -0
  9. data/README.md +32 -6
  10. data/Rakefile +5 -3
  11. data/bin/console +4 -3
  12. data/bin/dude +2 -2
  13. data/dude.gemspec +25 -18
  14. data/lib/dude.rb +9 -10
  15. data/lib/dude/code_management.rb +10 -0
  16. data/lib/dude/code_management/github/client.rb +23 -0
  17. data/lib/dude/code_management/github/create_pull_request.rb +53 -0
  18. data/lib/dude/commands.rb +24 -17
  19. data/lib/dude/commands/checkout.rb +4 -2
  20. data/lib/dude/commands/install.rb +32 -18
  21. data/lib/dude/commands/move.rb +5 -3
  22. data/lib/dude/commands/pr.rb +11 -0
  23. data/lib/dude/commands/pr/create.rb +49 -0
  24. data/lib/dude/commands/pr/remove.rb +15 -0
  25. data/lib/dude/commands/start.rb +9 -3
  26. data/lib/dude/commands/stop.rb +4 -2
  27. data/lib/dude/commands/tasks.rb +6 -3
  28. data/lib/dude/commands/track.rb +5 -3
  29. data/lib/dude/commands/version.rb +3 -1
  30. data/lib/dude/git.rb +3 -0
  31. data/lib/dude/git/checkout.rb +20 -1
  32. data/lib/dude/git/current_branch_name.rb +3 -1
  33. data/lib/dude/git/remote_name.rb +21 -0
  34. data/lib/dude/project_management/client.rb +14 -6
  35. data/lib/dude/project_management/entities/issue.rb +10 -7
  36. data/lib/dude/project_management/jira.rb +2 -1
  37. data/lib/dude/project_management/jira/client.rb +14 -7
  38. data/lib/dude/project_management/jira/fetch_current_task.rb +37 -0
  39. data/lib/dude/project_management/jira/fetch_current_tasks.rb +48 -0
  40. data/lib/dude/project_management/jira/get_task_name_by_id.rb +1 -1
  41. data/lib/dude/project_management/jira/move_task_to_list.rb +15 -13
  42. data/lib/dude/project_management/trello.rb +5 -3
  43. data/lib/dude/project_management/trello/client.rb +40 -21
  44. data/lib/dude/project_management/trello/fetch_current_task.rb +43 -0
  45. data/lib/dude/project_management/trello/fetch_current_tasks.rb +53 -0
  46. data/lib/dude/project_management/trello/fetch_lists.rb +24 -0
  47. data/lib/dude/project_management/trello/get_task_name_by_id.rb +25 -0
  48. data/lib/dude/project_management/trello/move_task_to_list.rb +55 -0
  49. data/lib/dude/settings.rb +3 -0
  50. data/lib/dude/templates/pull_request_template +7 -0
  51. data/lib/dude/time_trackers/toggl.rb +2 -0
  52. data/lib/dude/time_trackers/toggl/base.rb +4 -0
  53. data/lib/dude/time_trackers/toggl/start_time_entry.rb +3 -2
  54. data/lib/dude/time_trackers/toggl/stop_time_entry.rb +3 -1
  55. data/lib/dude/version.rb +3 -1
  56. metadata +77 -22
  57. data/dude-cli-2.0.2.gem +0 -0
  58. data/lib/dude/project_management/entities/board.rb +0 -9
  59. data/lib/dude/project_management/jira/get_current_tasks.rb +0 -40
  60. data/lib/dude/project_management/trello/checkout.rb +0 -4
  61. data/lib/dude/project_management/trello/get_current_tasks.rb +0 -24
  62. data/lib/dude/project_management/trello/get_lists.rb +0 -15
  63. data/lib/dude/project_management/trello/move_tasks_to_list.rb +0 -14
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dude
2
4
  module Git
3
5
  class CurrentBranchName
4
6
  def call
5
- %x(git rev-parse --abbrev-ref HEAD).chomp
7
+ `git rev-parse --abbrev-ref HEAD`.chomp
6
8
  end
7
9
  end
8
10
  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
@@ -1,5 +1,7 @@
1
- # require 'forwardable'
2
- require 'dude/project_management/jira/client'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './jira/client'
4
+ require_relative './trello/client'
3
5
 
4
6
  module Dude
5
7
  module ProjectManagement
@@ -9,16 +11,22 @@ module Dude
9
11
  attr_reader :client
10
12
 
11
13
  def initialize
12
- return unless LIST_OF_AVAILABLE_PROJECT_MANAGEMENT_TOOLS.include? settings['PROJECT_MANAGEMENT_TOOL']
13
- @client = Dude::ProjectManagement::Jira::Client.new
14
+ tool = settings['PROJECT_MANAGEMENT_TOOL']
15
+ return unless LIST_OF_AVAILABLE_PROJECT_MANAGEMENT_TOOLS.include? tool
16
+
17
+ @client = setup_client(tool)
14
18
  end
15
19
 
16
20
  def respond_to_missing?(method_name, include_private = false)
17
21
  client.respond_to_missing?(method_name, include_private)
18
22
  end
19
23
 
20
- def method_missing(m, *args, &block)
21
- client.send(m, *args, &block)
24
+ def method_missing(method, *args, &block)
25
+ client.send(method, *args, &block)
26
+ end
27
+
28
+ def setup_client(tool)
29
+ Object.const_get("Dude::ProjectManagement::#{tool.capitalize}::Client").new
22
30
  end
23
31
  end
24
32
  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(id: , title:, description:, status:, assignee: nil)
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,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dude/project_management/jira/client'
2
4
 
3
5
  module Dude
4
6
  module ProjectManagement
5
7
  module Jira
6
-
7
8
  end
8
9
  end
9
10
  end
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'jira-ruby'
2
- require 'dude/project_management/jira/get_current_tasks'
3
- require 'dude/project_management/jira/move_task_to_list'
4
- require 'dude/project_management/jira/get_task_name_by_id'
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
@@ -28,12 +31,16 @@ module Dude
28
31
  client.respond_to_missing?(method_name, include_private)
29
32
  end
30
33
 
31
- def method_missing(m, *args, &block)
32
- client.send(m, *args, &block)
34
+ def method_missing(method, *args, &block)
35
+ client.send(method, *args, &block)
36
+ end
37
+
38
+ def fetch_current_tasks
39
+ FetchCurrentTasks.new(client).call
33
40
  end
34
41
 
35
- def get_current_tasks
36
- GetCurrentTasks.new(client).call
42
+ def fetch_current_task(id)
43
+ FetchCurrentTask.new(client, id: id).call
37
44
  end
38
45
 
39
46
  def move_task_to_list(id, list)
@@ -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
+ include Settings
10
+
11
+ def initialize(client, id:)
12
+ @client = client
13
+ @id = id
14
+ end
15
+
16
+ def call
17
+ create_issue(client.Issue.find(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: "#{settings['ATLASSIAN_URL']}/browse/#{issue.key}"
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,48 @@
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
+ include Settings
10
+
11
+ def initialize(client)
12
+ @client = client
13
+ end
14
+
15
+ def call
16
+ board = client.Board.find(settings['ATLASSIAN_BOARD_ID'])
17
+
18
+ all_issues = board_type(board)
19
+
20
+ all_issues.map { |issue| create_issue(issue) }
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :client
26
+
27
+ def board_type(board)
28
+ case board.type
29
+ when 'kanban' then board.issues
30
+ when 'simple', 'scrum' then board.sprints(state: 'active').flat_map(&:issues)
31
+ else raise Dude::ToBeImplementedError
32
+ end
33
+ end
34
+
35
+ def create_issue(issue)
36
+ Entities::Issue.new(
37
+ id: issue.key,
38
+ title: issue.summary,
39
+ description: issue.description,
40
+ status: issue.status.name,
41
+ assignee: issue&.assignee&.displayName,
42
+ url: "#{settings['ATLASSIAN_URL']}/browse/#{issue.key}"
43
+ )
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,4 +1,4 @@
1
- require 'dude/project_management/jira/client'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Dude
4
4
  module ProjectManagement
@@ -1,4 +1,4 @@
1
- require 'dude/project_management/jira/client'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Dude
4
4
  module ProjectManagement
@@ -14,33 +14,35 @@ module Dude
14
14
 
15
15
  def call
16
16
  issue = client.Issue.find(id)
17
- available_transitions = client.Transition.all(:issue => issue)
17
+ available_transitions = client.Transition.all(issue: issue)
18
+ transition_id = generate_transition_id(issue, available_transitions)
19
+ transition = issue.transitions.build
20
+ transition.save!(transition: { id: transition_id })
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :client, :id, :list_name
18
26
 
19
- transition_id = if list_name
27
+ def generate_transition_id(issue, available_transitions)
28
+ if list_name
20
29
  available_transitions.find { |transition| transition.name == list_name }.id
21
30
  else
22
31
  select_list_for_moving(issue, available_transitions).id
23
32
  end
24
-
25
- transition = issue.transitions.build
26
- transition.save!(transition: { id: transition_id })
27
33
  end
28
34
 
29
- private
30
-
31
- def select_list_for_moving(issuem, available_transitions)
32
- puts "Please, select list for moving:".green.bold
35
+ def select_list_for_moving(_issue, available_transitions)
36
+ puts 'Please, select list for moving:'.green.bold
33
37
 
34
38
  available_transitions.each_with_index do |ea, index|
35
39
  puts "#{index + 1}: #{ea.name.bold}"
36
40
  end
37
41
 
38
42
  print "\nList index: ".bold
39
- list_index = STDIN.gets.chomp
43
+ list_index = $stdin.gets.chomp
40
44
  available_transitions[list_index.to_i - 1]
41
45
  end
42
-
43
- attr_reader :client, :id, :list_name
44
46
  end
45
47
  end
46
48
  end
@@ -1,6 +1,8 @@
1
- require_relative './trello/client'
1
+ # frozen_string_literal: true
2
2
 
3
- module ProjectsManagement
4
- module Trello
3
+ module Dude
4
+ module ProjectManagement
5
+ module Trello
6
+ end
5
7
  end
6
8
  end
@@ -1,32 +1,51 @@
1
- # TODO
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'
2
7
 
3
8
  require 'faraday'
4
9
  require 'json'
5
10
 
6
11
  module Dude
7
- module Trello
8
- class Client
9
- private
10
-
11
- def faraday_client
12
- @faraday_client ||= Faraday.new('https://api.trello.com/', {
13
- params: {
14
- key: "62b20e9eeab2d6e06145c69178521225",
15
- token: "6285fc2d2ff6100a5c341838d0e4acfed3601ae503beb973ddccf1cfab088537"
16
- }
17
- })
18
- end
12
+ module ProjectManagement
13
+ module Trello
14
+ class Client
15
+ include Settings
19
16
 
20
- def method_missing(method, *args, &block)
21
- faraday_client.send(method, *args, &block)
22
- end
17
+ def client
18
+ @client ||= Faraday.new('https://api.trello.com/', {
19
+ params: {
20
+ key: settings['TRELLO_KEY'],
21
+ token: settings['TRELLO_TOKEN']
22
+ }
23
+ })
24
+ end
23
25
 
24
- def get_current_tasks
25
- GetCurrentTasks.new(client).call
26
- end
26
+ def method_missing(method, *args, &block)
27
+ faraday_client.send(method, *args, &block)
28
+ end
29
+
30
+ def respond_to_missing?(method_name, include_private = false)
31
+ client.respond_to_missing?(method_name, include_private)
32
+ end
33
+
34
+ def fetch_current_tasks
35
+ FetchCurrentTasks.new(client).call
36
+ end
37
+
38
+ def fetch_current_task(id)
39
+ FetchCurrentTask.new(client, id: id).call
40
+ end
41
+
42
+ def move_task_to_list(id, list)
43
+ MoveTaskToList.new(client, id: id, list_name: list).call
44
+ end
27
45
 
28
- def move_task_to_list(id, list)
29
- MoveTasksToList.new(client, id: id, list_name: list).call
46
+ def get_task_name_by_id(id)
47
+ GetTaskNameById.new(client, id: id).call
48
+ end
30
49
  end
31
50
  end
32
51
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dude
4
+ module ProjectManagement
5
+ module Trello
6
+ class FetchCurrentTask
7
+ include Settings
8
+
9
+ def initialize(client, id:)
10
+ @client = client
11
+ @id = id
12
+ end
13
+
14
+ def call
15
+ response = client.get("/1/boards/#{settings['ATLASSIAN_BOARD_ID']}/cards/#{id}")
16
+ create_issue JSON.parse(response.body)
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :client, :id
22
+
23
+ def create_issue(issue)
24
+ Entities::Issue.new(
25
+ id: issue['idShort'],
26
+ title: issue['name'],
27
+ description: issue['desc'],
28
+ status: settings['IN_PROGRESS_LIST_NAME'], # OMG, let's fix this later
29
+ assignee: members(issue),
30
+ url: issue['shortUrl']
31
+ )
32
+ end
33
+
34
+ def members(issue)
35
+ people = issue['idMembers'].map do |person|
36
+ JSON.parse(client.get("/1/members/#{person}", fields: 'fullName').body)['fullName']
37
+ end
38
+ people.empty? ? nil : people.join(', ')
39
+ end
40
+ end
41
+ end
42
+ end
43
+ 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 FetchCurrentTasks
9
+ include Settings
10
+
11
+ attr_reader :fetch_lists
12
+
13
+ def initialize(client, fetch_lists: nil)
14
+ @client = client
15
+
16
+ @fetch_lists = fetch_lists || FetchLists.new(client)
17
+ end
18
+
19
+ def call
20
+ lists = fetch_lists.call
21
+ lists.map { |list| retrieve_list_issues(list) }.flatten
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :client
27
+
28
+ def retrieve_list_issues(list)
29
+ response = client.get("/1/lists/#{list['id']}/cards")
30
+ body = JSON.parse(response.body)
31
+ body.map { |issue| create_issue(issue, list) }
32
+ end
33
+
34
+ def create_issue(issue, current_list)
35
+ Entities::Issue.new(
36
+ id: issue['idShort'],
37
+ title: issue['name'],
38
+ description: issue['desc'],
39
+ status: current_list['name'],
40
+ assignee: members(issue)
41
+ )
42
+ end
43
+
44
+ def members(issue)
45
+ people = issue['idMembers'].map do |person|
46
+ JSON.parse(client.get("/1/members/#{person}", fields: 'fullName').body)['fullName']
47
+ end
48
+ people.empty? ? nil : people.join(', ')
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end