dude-cli 2.1.0.alpha2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/verify.yml +2 -2
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +1 -1
  5. data/CHANGELOG.md +7 -0
  6. data/Gemfile.lock +29 -9
  7. data/README.md +44 -44
  8. data/dude.gemspec +3 -2
  9. data/lib/dude.rb +11 -1
  10. data/lib/dude/code_management/github/client.rb +7 -3
  11. data/lib/dude/code_management/github/create_pull_request.rb +16 -8
  12. data/lib/dude/commands.rb +4 -0
  13. data/lib/dude/commands/commit.rb +23 -0
  14. data/lib/dude/commands/health_check.rb +15 -0
  15. data/lib/dude/commands/install.rb +63 -53
  16. data/lib/dude/commands/pr/remove.rb +1 -1
  17. data/lib/dude/commands/start.rb +6 -8
  18. data/lib/dude/commands/stop.rb +0 -2
  19. data/lib/dude/commands/tasks.rb +0 -2
  20. data/lib/dude/commands/track.rb +2 -4
  21. data/lib/dude/config.rb +18 -0
  22. data/lib/dude/git.rb +1 -0
  23. data/lib/dude/git/commit.rb +20 -0
  24. data/lib/dude/health_check.rb +39 -0
  25. data/lib/dude/project_management/client.rb +1 -3
  26. data/lib/dude/project_management/jira/client.rb +16 -8
  27. data/lib/dude/project_management/jira/fetch_current_task.rb +3 -3
  28. data/lib/dude/project_management/jira/fetch_current_tasks.rb +2 -4
  29. data/lib/dude/project_management/jira/get_task_name_by_id.rb +0 -2
  30. data/lib/dude/project_management/jira/move_task_to_list.rb +0 -2
  31. data/lib/dude/project_management/trello/client.rb +9 -5
  32. data/lib/dude/project_management/trello/fetch_current_task.rb +2 -4
  33. data/lib/dude/project_management/trello/fetch_current_tasks.rb +0 -2
  34. data/lib/dude/project_management/trello/fetch_lists.rb +1 -3
  35. data/lib/dude/project_management/trello/get_task_name_by_id.rb +1 -3
  36. data/lib/dude/project_management/trello/move_task_to_list.rb +1 -3
  37. data/lib/dude/setup/github.rb +35 -0
  38. data/lib/dude/setup/jira.rb +64 -0
  39. data/lib/dude/setup/toggl.rb +47 -0
  40. data/lib/dude/setup/trello.rb +58 -0
  41. data/lib/dude/templates/duderc_template +32 -0
  42. data/lib/dude/time_trackers/toggl/base.rb +2 -4
  43. data/lib/dude/version.rb +1 -1
  44. metadata +29 -6
  45. data/lib/dude/templates/pull_request_template +0 -7
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dude
4
+ module Commands
5
+ class Commit < Dry::CLI::Command
6
+ desc 'Create a commit with id and title of current story'
7
+
8
+ argument :id, required: true, desc: 'The card short ID'
9
+
10
+ def call(id:)
11
+ Dude::Git::Commit.new.call(commit_name(id))
12
+ end
13
+
14
+ private
15
+
16
+ def commit_name(id)
17
+ client = ProjectManagement::Client.new
18
+ issue_title = client.get_task_name_by_id(id)
19
+ "[#{id}] #{issue_title}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../health_check'
4
+
5
+ module Dude
6
+ module Commands
7
+ class HealthCheck < Dry::CLI::Command
8
+ desc 'Run healthcheck for enabled integrations'
9
+
10
+ def call
11
+ Dude::HealthCheck.new.call
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,6 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tty-prompt'
4
+ require 'fileutils'
5
+
3
6
  require_relative '../settings'
7
+ require_relative '../setup/jira'
8
+ require_relative '../setup/trello'
9
+ require_relative '../setup/toggl'
10
+ require_relative '../setup/github'
4
11
 
5
12
  module Dude
6
13
  module Commands
@@ -8,63 +15,66 @@ module Dude
8
15
  desc 'Creates .duderc for future configuration'
9
16
 
10
17
  def call
11
- path = File.join(Dir.home, Settings::CONFIG_FILE)
12
- if File.exist?(path)
13
- puts 'Config file already exists'
14
- else
15
- File.open(path, 'w') { |f| f.write(duderc_file_content) }
16
- puts '.duderc created in your HOME directory'
17
- end
18
+ @prompt = TTY::Prompt.new
19
+
20
+ create_file_if_not_exists
21
+
22
+ @current_settings = Dude::Config.configure_with('.duderc.yml')
23
+ @current_settings[:project_management_tool] = setup_project_management_tool # jira, trello
24
+ @current_settings = send("setup_#{current_settings[:project_management_tool]}")
25
+ setup_features.each { send("setup_#{_1}") } # toggl, github
26
+
27
+ save
18
28
  end
19
29
 
20
30
  private
21
31
 
22
- def duderc_file_content
23
- <<~HEREDOC
24
- # Please, don't use quotes and spaces.
25
- # Write all variables using following format: NAME=VALUE
26
-
27
- # Replace it with your project list names. Skip for empty lists
28
- TODO_LIST_NAME=To Do
29
- IN_PROGRESS_LIST_NAME=In Progress
30
- CODE_REVIEW_LIST_NAME=Code Review
31
- TESTING_LIST_NAME=TESTABLE
32
- DONE_LIST_NAME=Done
33
-
34
- # Your Toggl project name
35
- TOGGL_PROJECT_NAME=
36
- # Your Toggl API token can be found at the bottom of the page: https://track.toggl.com/profile
37
- TOGGL_TOKEN=
38
- # Can be copied from url here: https://toggl.com/app/projects/. Example: 123456
39
- TOGGL_WORKSPACE_ID=
40
- # Use the *id* and *title* and specify format for the task titles in Trello or keep it as it is
41
- TOGGL_TASK_FORMAT=[id] title
42
-
43
- # Now jira/trello only (Github, Gitlab)
44
- # Choose one and uncomment section for Jira or Trello
45
-
46
- # [TRELLO setup start]
47
- # # https://trello.com/app-key
48
- # PROJECT_MANAGEMENT_TOOL=trello
49
- # TRELLO_KEY=
50
- # TRELLO_TOKEN=
51
- # [TRELLO setup end]
52
-
53
- # [JIRA setup start]
54
- PROJECT_MANAGEMENT_TOOL=jira
55
- ATLASSIAN_EMAIL=
56
- # How to create Atlassian token: https://support.siteimprove.com/hc/en-gb/articles/360004317332-How-to-create-an-API-token-from-your-Atlassian-account
57
- ATLASSIAN_TOKEN=
58
- # URL of your project. Example: https://example.atlassian.net
59
- ATLASSIAN_URL=
60
- # KEY of your project. If your issues have id BT-123 - BT is the key
61
- ATLASSIAN_PROJECT_KEY=
62
- # Just open your atlassian main board and copy id from the url after rapidView=*ID* part.
63
- # Example: https://dealmakerns.atlassian.net/secure/RapidBoard.jspa?rapidView=23&projectKey=DT - 23 is the id
64
- ATLASSIAN_BOARD_ID=
65
- # [JIRA setup end]
66
-
67
- HEREDOC
32
+ attr_reader :prompt, :current_settings
33
+
34
+ def setup_project_management_tool
35
+ prompt.select(Dude::Config.style_prompt("Select project management tool you're going to use:")) do |menu|
36
+ menu.choice name: 'Jira', value: 'jira'
37
+ menu.choice name: 'Trello', value: 'trello'
38
+ menu.choice name: 'Pivotal Tracker', value: 'pivotal', disabled: '(coming in future)'
39
+ menu.choice name: 'Github', value: 'github', disabled: '(coming in future)'
40
+ end
41
+ end
42
+
43
+ def method_missing(method, *args, &block)
44
+ return super unless method.start_with?('setup_')
45
+
46
+ const_name = method.to_s.split('setup_').last
47
+ Object.const_get("Dude::Setup::#{const_name.capitalize}").new(prompt).call(settings: current_settings)
48
+ end
49
+
50
+ def respond_to_missing?(method_name, include_private = false)
51
+ client.respond_to_missing?(method_name, include_private)
52
+ end
53
+
54
+ def setup_features
55
+ prompt.multi_select(Dude::Config.style_prompt('Select features you want to use:')) do |menu|
56
+ menu.choice 'Toggl time tracking features (Create/stop time entries)', :toggl
57
+ menu.choice 'Github PR creation', :github
58
+ end
59
+ end
60
+
61
+ def save
62
+ File.open('.duderc.yml', 'w') { |file| file.write(current_settings.to_yaml) }
63
+ puts 'Configuration file has been sucessfully updated'.green.bold
64
+ puts 'Your settings are in the .duderc.yml file'.yellow
65
+ puts 'You could change it manually for editing Toggl task format and Github PR template'.yellow
66
+ rescue StandardError => e
67
+ puts "Something went wrong: #{e}"
68
+ end
69
+
70
+ def create_file_if_not_exists
71
+ path = File.join(Dir.pwd, Config::FILE_NAME)
72
+ if File.exist?(path)
73
+ puts 'Config file already exists. All settings will be rewrited'
74
+ else
75
+ FileUtils.cp(File.join(File.dirname(__FILE__), '../templates/duderc_template'), path)
76
+ puts '.duderc created in your HOME directory'
77
+ end
68
78
  end
69
79
  end
70
80
  end
@@ -7,7 +7,7 @@ module Dude
7
7
  desc 'Remove'
8
8
 
9
9
  def call(*)
10
- puts '123'
10
+ puts 'To be created later'
11
11
  end
12
12
  end
13
13
  end
@@ -3,8 +3,6 @@
3
3
  module Dude
4
4
  module Commands
5
5
  class Start < Dry::CLI::Command
6
- include Settings
7
-
8
6
  desc 'Start task (Do checkout, track and move actions)'
9
7
 
10
8
  argument :id, required: true, desc: 'The card short ID'
@@ -19,16 +17,16 @@ module Dude
19
17
 
20
18
  def selected_list(list)
21
19
  case list
22
- when 'todo' then settings['TODO_LIST_NAME']
23
- when 'in_progress' then settings['IN_PROGRESS_LIST_NAME']
24
- when 'code_review' then settings['CODE_REVIEW_LIST_NAME']
25
- when 'testing' then settings['TESTING_LIST_NAME']
26
- when 'done' then settings['DONE_LIST_NAME']
20
+ when 'todo' then Dude::SETTINGS[:todo_list_name]
21
+ when 'in_progress' then Dude::SETTINGS[:in_progress_list_name]
22
+ when 'code_review' then Dude::SETTINGS[:code_review_list_name]
23
+ when 'testing' then Dude::SETTINGS[:testing_list_name]
24
+ when 'done' then Dude::SETTINGS[:done_list_name]
27
25
  end
28
26
  end
29
27
 
30
28
  def time_tracking_enabled?
31
- !settings['TOGGL_TOKEN'].nil?
29
+ !Dude::SETTINGS.dig(:toggl, :token).nil?
32
30
  end
33
31
  end
34
32
  end
@@ -5,8 +5,6 @@ require_relative '../time_trackers/toggl/stop_time_entry'
5
5
  module Dude
6
6
  module Commands
7
7
  class Stop < Dry::CLI::Command
8
- include Settings
9
-
10
8
  desc 'Stop current time entry in Toggl'
11
9
 
12
10
  def call
@@ -5,8 +5,6 @@ require_relative '../project_management/client'
5
5
  module Dude
6
6
  module Commands
7
7
  class Tasks < Dry::CLI::Command
8
- include Settings
9
-
10
8
  desc "Print tasks as list with ID's and assignees"
11
9
 
12
10
  def call
@@ -5,15 +5,13 @@ require_relative '../time_trackers/toggl/start_time_entry'
5
5
  module Dude
6
6
  module Commands
7
7
  class Track < Dry::CLI::Command
8
- include Settings
9
-
10
8
  desc 'Start time entry in Toggl with issue title and id'
11
9
 
12
10
  argument :id, required: true, desc: 'The card short ID'
13
11
 
14
12
  def call(id:)
15
13
  @id = id
16
- Dude::Toggl::StartTimeEntry.new.call(task_title: task_title, project: settings['TOGGL_PROJECT_NAME'])
14
+ Dude::Toggl::StartTimeEntry.new.call(task_title: task_title, project: Dude::SETTINGS.dig(:toggl, :project_name))
17
15
  end
18
16
 
19
17
  private
@@ -23,7 +21,7 @@ module Dude
23
21
  def task_title
24
22
  client = ProjectManagement::Client.new
25
23
  issue_title = client.get_task_name_by_id(id)
26
- settings['TOGGL_TASK_FORMAT'].sub(/id/, id).sub(/title/, issue_title)
24
+ Dude::SETTINGS.dig(:toggl, :task_format).sub(/{issue_id}/, id).sub(/{issue_title}/, issue_title)
27
25
  end
28
26
  end
29
27
  end
@@ -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
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative './git/checkout'
4
4
  require_relative './git/current_branch_name'
5
+ require_relative './git/commit'
5
6
  require_relative './git/remote_name'
6
7
 
7
8
  module Git
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dude
4
+ module Git
5
+ class Commit
6
+ def call(commit_name)
7
+ @commit_name = commit_name
8
+ create_commit
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :commit_name
14
+
15
+ def create_commit
16
+ `git commit -m "#{commit_name}"`
17
+ end
18
+ end
19
+ end
20
+ 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
@@ -6,12 +6,10 @@ require_relative './trello/client'
6
6
  module Dude
7
7
  module ProjectManagement
8
8
  class Client
9
- include Settings
10
-
11
9
  attr_reader :client
12
10
 
13
11
  def initialize
14
- tool = settings['PROJECT_MANAGEMENT_TOOL']
12
+ tool = Dude::SETTINGS[:project_management_tool]
15
13
  return unless LIST_OF_AVAILABLE_PROJECT_MANAGEMENT_TOOLS.include? tool
16
14
 
17
15
  @client = setup_client(tool)
@@ -10,21 +10,23 @@ module Dude
10
10
  module ProjectManagement
11
11
  module Jira
12
12
  class Client
13
- include Settings
14
-
15
13
  attr_reader :client, :project
16
14
 
17
- def initialize
18
- options = {
19
- username: settings['ATLASSIAN_EMAIL'],
20
- password: settings['ATLASSIAN_TOKEN'],
21
- site: settings['ATLASSIAN_URL'],
15
+ def options
16
+ {
17
+ username: Dude::SETTINGS.dig(:jira, :email),
18
+ password: Dude::SETTINGS.dig(:jira, :token),
19
+ site: Dude::SETTINGS.dig(:jira, :project, :url),
22
20
  context_path: '',
23
21
  auth_type: :basic
24
22
  }
23
+ end
25
24
 
25
+ def initialize
26
26
  @client = JIRA::Client.new(options)
27
- @project = client.Project.find(settings['ATLASSIAN_PROJECT_KEY'])
27
+ @project = client.Project.find(Dude::SETTINGS.dig(:jira, :project, :key))
28
+ rescue StandardError
29
+ nil
28
30
  end
29
31
 
30
32
  def respond_to_missing?(method_name, include_private = false)
@@ -50,6 +52,12 @@ module Dude
50
52
  def get_task_name_by_id(id)
51
53
  GetTaskNameById.new(client, id: id).call
52
54
  end
55
+
56
+ def health_check
57
+ @project && true
58
+ rescue StandardError
59
+ false
60
+ end
53
61
  end
54
62
  end
55
63
  end
@@ -6,8 +6,6 @@ module Dude
6
6
  module ProjectManagement
7
7
  module Jira
8
8
  class FetchCurrentTask
9
- include Settings
10
-
11
9
  def initialize(client, id:)
12
10
  @client = client
13
11
  @id = id
@@ -15,6 +13,8 @@ module Dude
15
13
 
16
14
  def call
17
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
18
  end
19
19
 
20
20
  private
@@ -28,7 +28,7 @@ module Dude
28
28
  description: issue.description,
29
29
  status: issue.status.name,
30
30
  assignee: issue&.assignee&.displayName,
31
- url: "#{settings['ATLASSIAN_URL']}/browse/#{issue.key}"
31
+ url: "#{Dude::SETTINGS.dig(:jira, :project, :url)}/browse/#{issue.key}"
32
32
  )
33
33
  end
34
34
  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(settings['ATLASSIAN_BOARD_ID'])
14
+ board = client.Board.find(Dude::SETTINGS.dig(:jira, :board_id))
17
15
 
18
16
  all_issues = board_type(board)
19
17
 
@@ -39,7 +37,7 @@ module Dude
39
37
  description: issue.description,
40
38
  status: issue.status.name,
41
39
  assignee: issue&.assignee&.displayName,
42
- url: "#{settings['ATLASSIAN_URL']}/browse/#{issue.key}"
40
+ url: "#{Dude::SETTINGS.dig(:jira, :project, :url)}/browse/#{issue.key}"
43
41
  )
44
42
  end
45
43
  end