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.rb
CHANGED
@@ -1,12 +1,23 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
|
6
|
-
require
|
3
|
+
require 'colorize'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'pry'
|
7
|
+
rescue LoadError
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
require_relative './dude/settings'
|
12
|
+
require_relative './dude/version'
|
13
|
+
require_relative './dude/commands'
|
14
|
+
require_relative './dude/git'
|
15
|
+
require_relative './dude/code_management'
|
16
|
+
require_relative './dude/config'
|
7
17
|
|
8
18
|
module Dude
|
9
|
-
|
19
|
+
SETTINGS = Dude::Config.configure_with('.duderc.yml')
|
20
|
+
LIST_OF_AVAILABLE_PROJECT_MANAGEMENT_TOOLS = %w[jira trello].freeze
|
10
21
|
|
11
|
-
|
22
|
+
class ToBeImplementedError < StandardError; end
|
12
23
|
end
|
@@ -0,0 +1,27 @@
|
|
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
|
+
def client
|
10
|
+
@client ||= Faraday.new('https://api.github.com/', {
|
11
|
+
headers: { Authorization: "token #{Dude::SETTINGS.dig(:github, :token)}" }
|
12
|
+
})
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_pull_request(issue:, owner:, repo:, params:)
|
16
|
+
CreatePullRequest.new.call(client, issue: issue, owner: owner, repo: repo, params: params)
|
17
|
+
end
|
18
|
+
|
19
|
+
def health_check
|
20
|
+
client.get('https://api.github.com/user').status == 200
|
21
|
+
rescue StandardError
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Dude
|
6
|
+
module CodeManagement
|
7
|
+
module Github
|
8
|
+
class CreatePullRequest
|
9
|
+
def call(client, issue:, owner:, repo:, params:)
|
10
|
+
@issue = issue
|
11
|
+
@owner = owner
|
12
|
+
@repo = repo
|
13
|
+
@params = params
|
14
|
+
|
15
|
+
response = client.post("https://api.github.com/repos/#{owner}/#{repo}/pulls", body.to_json)
|
16
|
+
res = JSON.parse(response.body)
|
17
|
+
url = res['html_url']
|
18
|
+
puts "Pull request has been created: #{url}"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :issue, :owner, :repo, :params
|
24
|
+
|
25
|
+
def body
|
26
|
+
{
|
27
|
+
title: params[:title] || template['title'],
|
28
|
+
body: params[:body] || template['body'],
|
29
|
+
head: params[:head],
|
30
|
+
base: params[:base]
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def template
|
35
|
+
file = YAML.load_file(File.join(File.dirname(__FILE__), '../../templates/pull_request_template'))
|
36
|
+
file.tap do |template|
|
37
|
+
template['title'] = fill_variables(template['title'])
|
38
|
+
template['body'] = fill_variables(template['body'])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def fill_variables(text)
|
43
|
+
text
|
44
|
+
.then { _1.gsub('{issue_id}', issue.id) }.chomp
|
45
|
+
.then { _1.gsub('{issue_url}', issue.url) }
|
46
|
+
.then { _1.gsub('{issue_title}', issue.title) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/dude/commands.rb
CHANGED
@@ -1,24 +1,33 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
9
|
-
require_relative
|
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'
|
13
|
+
require_relative './commands/health_check'
|
10
14
|
|
11
15
|
module Dude
|
12
16
|
module Commands
|
13
17
|
extend Dry::CLI::Registry
|
14
18
|
|
15
|
-
register
|
16
|
-
register
|
17
|
-
register
|
18
|
-
register
|
19
|
-
register
|
20
|
-
register
|
21
|
-
register
|
22
|
-
register
|
19
|
+
register 'install', Dude::Commands::Install, aliases: ['install']
|
20
|
+
register 'version', Dude::Commands::Version, aliases: ['v', '-v', '--version']
|
21
|
+
register 'tasks', Dude::Commands::Tasks, aliases: ['t', '-t', '--tasks']
|
22
|
+
register 'move', Dude::Commands::Move, aliases: ['m', '-m', '--move']
|
23
|
+
register 'checkout', Dude::Commands::Checkout, aliases: ['co']
|
24
|
+
register 'track', Dude::Commands::Track, aliases: ['tr']
|
25
|
+
register 'stop', Dude::Commands::Stop
|
26
|
+
register 'start', Dude::Commands::Start, aliases: ['st']
|
27
|
+
register 'healthcheck', Dude::Commands::HealthCheck
|
28
|
+
|
29
|
+
register 'pr' do |prefix|
|
30
|
+
prefix.register 'create', Dude::Commands::PR::Create
|
31
|
+
end
|
23
32
|
end
|
24
33
|
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
|
6
|
+
desc 'Checkout to branch named as current issue'
|
5
7
|
|
6
|
-
argument :id, required: true, desc:
|
8
|
+
argument :id, required: true, desc: 'The card short ID'
|
7
9
|
|
8
10
|
def call(id:)
|
9
11
|
client = ProjectManagement::Client.new
|
@@ -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,56 +1,80 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tty-prompt'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
require_relative '../settings'
|
7
|
+
require_relative '../setup/jira'
|
8
|
+
require_relative '../setup/trello'
|
9
|
+
require_relative '../setup/toggl'
|
10
|
+
require_relative '../setup/github'
|
2
11
|
|
3
12
|
module Dude
|
4
13
|
module Commands
|
5
14
|
class Install < Dry::CLI::Command
|
6
|
-
desc
|
15
|
+
desc 'Creates .duderc for future configuration'
|
7
16
|
|
8
17
|
def call
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
16
28
|
end
|
17
29
|
|
18
30
|
private
|
19
31
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
54
78
|
end
|
55
79
|
end
|
56
80
|
end
|
data/lib/dude/commands/move.rb
CHANGED
@@ -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
|
6
|
+
desc 'Move task between board columns'
|
5
7
|
|
6
|
-
argument :id, required: true, desc:
|
7
|
-
option :list, desc:
|
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,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
|
data/lib/dude/commands/start.rb
CHANGED
@@ -1,29 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dude
|
2
4
|
module Commands
|
3
5
|
class Start < Dry::CLI::Command
|
4
|
-
|
5
|
-
|
6
|
-
desc "Start task (Do checkout, track and move actions)"
|
6
|
+
desc 'Start task (Do checkout, track and move actions)'
|
7
7
|
|
8
|
-
argument :id, required: true, desc:
|
8
|
+
argument :id, required: true, desc: 'The card short ID'
|
9
9
|
|
10
10
|
def call(id:)
|
11
11
|
Commands::Move.new.call(id: id, list: selected_list('in_progress'))
|
12
12
|
Commands::Checkout.new.call(id: id)
|
13
|
-
Commands::Track.new.call(id: id)
|
13
|
+
Commands::Track.new.call(id: id) if time_tracking_enabled?
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
17
17
|
|
18
18
|
def selected_list(list)
|
19
19
|
case list
|
20
|
-
when 'todo' then
|
21
|
-
when 'in_progress' then
|
22
|
-
when 'code_review' then
|
23
|
-
when 'testing' then
|
24
|
-
when 'done' then
|
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]
|
25
25
|
end
|
26
26
|
end
|
27
|
+
|
28
|
+
def time_tracking_enabled?
|
29
|
+
!Dude::SETTINGS.dig(:toggl, :token).nil?
|
30
|
+
end
|
27
31
|
end
|
28
32
|
end
|
29
33
|
end
|