dude-cli 2.0.4 → 2.1.0.alpha2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) 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 -9
  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 -21
  57. data/lib/dude/project_management/entities/board.rb +0 -9
  58. data/lib/dude/project_management/jira/get_current_tasks.rb +0 -40
  59. data/lib/dude/project_management/trello/checkout.rb +0 -4
  60. data/lib/dude/project_management/trello/get_current_tasks.rb +0 -24
  61. data/lib/dude/project_management/trello/get_lists.rb +0 -15
  62. data/lib/dude/project_management/trello/move_tasks_to_list.rb +0 -14
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './create_pull_request'
4
+
5
+ module Dude
6
+ module CodeManagement
7
+ module Github
8
+ class Client
9
+ include Settings
10
+
11
+ def client
12
+ @client ||= Faraday.new('https://api.github.com/', {
13
+ headers: { Authorization: "token #{settings['GITHUB_TOKEN']}" }
14
+ })
15
+ end
16
+
17
+ def create_pull_request(issue:, owner:, repo:, params:)
18
+ CreatePullRequest.new.call(client, issue: issue, owner: owner, repo: repo, params: params)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module Dude
6
+ module CodeManagement
7
+ module Github
8
+ class CreatePullRequest
9
+ include Settings
10
+
11
+ def call(client, issue:, owner:, repo:, params:)
12
+ @issue = issue
13
+ @owner = owner
14
+ @repo = repo
15
+ @params = params
16
+
17
+ response = client.post("https://api.github.com/repos/#{owner}/#{repo}/pulls", body.to_json)
18
+ res = JSON.parse(response.body)
19
+ url = res['html_url']
20
+ puts "Pull request has been created: #{url}"
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :issue, :owner, :repo, :params
26
+
27
+ def body
28
+ {
29
+ title: params[:title] || template['title'],
30
+ body: params[:body] || template['body'],
31
+ head: params[:head],
32
+ base: params[:base]
33
+ }
34
+ end
35
+
36
+ def template
37
+ file = YAML.load_file(File.join(File.dirname(__FILE__), '../../templates/pull_request_template'))
38
+ file.tap do |template|
39
+ template['title'] = fill_variables(template['title'])
40
+ template['body'] = fill_variables(template['body'])
41
+ end
42
+ end
43
+
44
+ def fill_variables(text)
45
+ text
46
+ .then { _1.gsub('{issue_id}', issue.id) }.chomp
47
+ .then { _1.gsub('{issue_url}', issue.url) }
48
+ .then { _1.gsub('{issue_title}', issue.title) }
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
data/lib/dude/commands.rb CHANGED
@@ -1,24 +1,31 @@
1
- require "dry/cli"
2
- require_relative "./commands/version"
3
- require_relative "./commands/tasks"
4
- require_relative "./commands/move"
5
- require_relative "./commands/checkout"
6
- require_relative "./commands/start"
7
- require_relative "./commands/track"
8
- require_relative "./commands/stop"
9
- require_relative "./commands/install"
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/cli'
4
+ require_relative './commands/version'
5
+ require_relative './commands/tasks'
6
+ require_relative './commands/move'
7
+ require_relative './commands/checkout'
8
+ require_relative './commands/start'
9
+ require_relative './commands/track'
10
+ require_relative './commands/stop'
11
+ require_relative './commands/install'
12
+ require_relative './commands/pr'
10
13
 
11
14
  module Dude
12
15
  module Commands
13
16
  extend Dry::CLI::Registry
14
17
 
15
- register "install", Dude::Commands::Install, aliases: ["install"]
16
- register "version", Dude::Commands::Version, aliases: ["v", "-v", "--version"]
17
- register "tasks", Dude::Commands::Tasks, aliases: ["t", "-t", "--tasks"]
18
- register "move", Dude::Commands::Move, aliases: ["m", "-m", "--move"]
19
- register "checkout", Dude::Commands::Checkout, aliases: ["co"]
20
- register "track", Dude::Commands::Track, aliases: ["tr"]
21
- register "stop", Dude::Commands::Stop
22
- register "start", Dude::Commands::Start, aliases: ["st"]
18
+ register 'install', Dude::Commands::Install, aliases: ['install']
19
+ register 'version', Dude::Commands::Version, aliases: ['v', '-v', '--version']
20
+ register 'tasks', Dude::Commands::Tasks, aliases: ['t', '-t', '--tasks']
21
+ register 'move', Dude::Commands::Move, aliases: ['m', '-m', '--move']
22
+ register 'checkout', Dude::Commands::Checkout, aliases: ['co']
23
+ register 'track', Dude::Commands::Track, aliases: ['tr']
24
+ register 'stop', Dude::Commands::Stop
25
+ register 'start', Dude::Commands::Start, aliases: ['st']
26
+
27
+ register 'pr' do |prefix|
28
+ prefix.register 'create', Dude::Commands::PR::Create
29
+ end
23
30
  end
24
31
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dude
2
4
  module Commands
3
5
  class Checkout < Dry::CLI::Command
4
- desc "Checkout to branch named as current issue"
6
+ desc 'Checkout to branch named as current issue'
5
7
 
6
- argument :id, required: true, desc: "The card short ID"
8
+ argument :id, required: true, desc: 'The card short ID'
7
9
 
8
10
  def call(id:)
9
11
  client = ProjectManagement::Client.new
@@ -1,17 +1,19 @@
1
- require 'dude/settings'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../settings'
2
4
 
3
5
  module Dude
4
6
  module Commands
5
7
  class Install < Dry::CLI::Command
6
- desc "Creates .duderc for future configuration"
8
+ desc 'Creates .duderc for future configuration'
7
9
 
8
10
  def call
9
11
  path = File.join(Dir.home, Settings::CONFIG_FILE)
10
12
  if File.exist?(path)
11
- puts "Config file already exists"
13
+ puts 'Config file already exists'
12
14
  else
13
- File.open(path, 'w') {|f| f.write(duderc_file_content) }
14
- puts ".duderc created in your HOME directory"
15
+ File.open(path, 'w') { |f| f.write(duderc_file_content) }
16
+ puts '.duderc created in your HOME directory'
15
17
  end
16
18
  end
17
19
 
@@ -21,19 +23,6 @@ module Dude
21
23
  <<~HEREDOC
22
24
  # Please, don't use quotes and spaces.
23
25
  # Write all variables using following format: NAME=VALUE
24
- #
25
- # Now jira only (Github, Gitlab, Trello later)
26
- PROJECT_MANAGEMENT_TOOL=jira
27
- ATLASSIAN_EMAIL=
28
- # How to create Atlassian token: https://support.siteimprove.com/hc/en-gb/articles/360004317332-How-to-create-an-API-token-from-your-Atlassian-account
29
- ATLASSIAN_TOKEN=
30
- # URL of your project. Example: https://example.atlassian.net
31
- ATLASSIAN_URL=
32
- # KEY of your project. If your issues have id BT-123 - BT is the key
33
- ATLASSIAN_PROJECT_KEY=
34
- # Just open your atlassian main board and copy id from the url after rapidView=*ID* part.
35
- # Example: https://dealmakerns.atlassian.net/secure/RapidBoard.jspa?rapidView=23&projectKey=DT - 23 is the id
36
- ATLASSIAN_BOARD_ID=
37
26
 
38
27
  # Replace it with your project list names. Skip for empty lists
39
28
  TODO_LIST_NAME=To Do
@@ -50,6 +39,31 @@ module Dude
50
39
  TOGGL_WORKSPACE_ID=
51
40
  # Use the *id* and *title* and specify format for the task titles in Trello or keep it as it is
52
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
+
53
67
  HEREDOC
54
68
  end
55
69
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dude
2
4
  module Commands
3
5
  class Move < Dry::CLI::Command
4
- desc "Move task between board columns"
6
+ desc 'Move task between board columns'
5
7
 
6
- argument :id, required: true, desc: "The card short ID"
7
- option :list, desc: "List name for moving card"
8
+ argument :id, required: true, desc: 'The card short ID'
9
+ option :list, desc: 'List name for moving card'
8
10
 
9
11
  def call(id:, **options)
10
12
  client = ProjectManagement::Client.new
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './pr/create'
4
+ require_relative './pr/remove'
5
+
6
+ module Dude
7
+ module Commands
8
+ module PR
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dude
4
+ module Commands
5
+ module PR
6
+ BASE_BRANCH = 'master'
7
+
8
+ class Create < Dry::CLI::Command
9
+ desc 'Create PR with custom template description'
10
+
11
+ argument :id, required: true, desc: 'The card short ID'
12
+
13
+ def call(id:)
14
+ @id = id
15
+ client = CodeManagement::Github::Client.new
16
+ client.create_pull_request(issue: issue, owner: owner, repo: repo, params: params)
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :id
22
+
23
+ def owner
24
+ repository_name.split('/')[0]
25
+ end
26
+
27
+ def issue
28
+ client = ProjectManagement::Client.new
29
+ client.fetch_current_task(id)
30
+ end
31
+
32
+ def repo
33
+ repository_name.split('/')[1]
34
+ end
35
+
36
+ def params
37
+ {
38
+ head: Git::CurrentBranchName.new.call,
39
+ base: BASE_BRANCH
40
+ }
41
+ end
42
+
43
+ def repository_name
44
+ @repository_name ||= Git::RemoteName.new.call
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dude
4
+ module Commands
5
+ module PR
6
+ class Remove < Dry::CLI::Command
7
+ desc 'Remove'
8
+
9
+ def call(*)
10
+ puts '123'
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,16 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dude
2
4
  module Commands
3
5
  class Start < Dry::CLI::Command
4
6
  include Settings
5
7
 
6
- desc "Start task (Do checkout, track and move actions)"
8
+ desc 'Start task (Do checkout, track and move actions)'
7
9
 
8
- argument :id, required: true, desc: "The card short ID"
10
+ argument :id, required: true, desc: 'The card short ID'
9
11
 
10
12
  def call(id:)
11
13
  Commands::Move.new.call(id: id, list: selected_list('in_progress'))
12
14
  Commands::Checkout.new.call(id: id)
13
- Commands::Track.new.call(id: id)
15
+ Commands::Track.new.call(id: id) if time_tracking_enabled?
14
16
  end
15
17
 
16
18
  private
@@ -24,6 +26,10 @@ module Dude
24
26
  when 'done' then settings['DONE_LIST_NAME']
25
27
  end
26
28
  end
29
+
30
+ def time_tracking_enabled?
31
+ !settings['TOGGL_TOKEN'].nil?
32
+ end
27
33
  end
28
34
  end
29
35
  end
@@ -1,11 +1,13 @@
1
- require 'dude/time_trackers/toggl/stop_time_entry'
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
8
  include Settings
7
9
 
8
- desc "Stop current time entry in Toggl"
10
+ desc 'Stop current time entry in Toggl'
9
11
 
10
12
  def call
11
13
  Dude::Toggl::StopTimeEntry.new.call
@@ -1,4 +1,6 @@
1
- require 'dude/project_management/client'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../project_management/client'
2
4
 
3
5
  module Dude
4
6
  module Commands
@@ -8,8 +10,8 @@ module Dude
8
10
  desc "Print tasks as list with ID's and assignees"
9
11
 
10
12
  def call
11
- tasks = Dude::ProjectManagement::Client.new.get_current_tasks
12
- lists = tasks.map {|issue| issue.status}.uniq
13
+ tasks = Dude::ProjectManagement::Client.new.fetch_current_tasks
14
+ lists = tasks.map(&:status).uniq
13
15
 
14
16
  lists.each do |list|
15
17
  puts "#{list}:".green.bold
@@ -24,6 +26,7 @@ module Dude
24
26
 
25
27
  def printable_issue_template(issue)
26
28
  return "#{issue.id.to_s.bold}: #{issue.title}" + " (#{issue.assignee})".blue if issue.assignee
29
+
27
30
  "#{issue.id.to_s.bold}: #{issue.title}"
28
31
  end
29
32
  end
@@ -1,13 +1,15 @@
1
- require 'dude/time_trackers/toggl/start_time_entry'
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
8
  include Settings
7
9
 
8
- desc "Start time entry in Toggl with issue title and id"
10
+ desc 'Start time entry in Toggl with issue title and id'
9
11
 
10
- argument :id, required: true, desc: "The card short ID"
12
+ argument :id, required: true, desc: 'The card short ID'
11
13
 
12
14
  def call(id:)
13
15
  @id = id
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dude
2
4
  module Commands
3
5
  class Version < Dry::CLI::Command
4
- desc "Print version"
6
+ desc 'Print version'
5
7
 
6
8
  def call
7
9
  puts Dude::VERSION
data/lib/dude/git.rb CHANGED
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative './git/checkout'
2
4
  require_relative './git/current_branch_name'
5
+ require_relative './git/remote_name'
3
6
 
4
7
  module Git
5
8
  end
@@ -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
- %x(git checkout -b #{branch_name})
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