dude-cli 2.1.0.alpha2 → 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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +15 -1
  3. data/README.md +43 -44
  4. data/demo/dude.gif +0 -0
  5. data/demo/wizard.gif +0 -0
  6. data/dude.gemspec +1 -0
  7. data/lib/dude.rb +10 -2
  8. data/lib/dude/code_management/github/client.rb +7 -3
  9. data/lib/dude/code_management/github/create_pull_request.rb +0 -2
  10. data/lib/dude/commands.rb +2 -0
  11. data/lib/dude/commands/health_check.rb +15 -0
  12. data/lib/dude/commands/install.rb +63 -53
  13. data/lib/dude/commands/start.rb +6 -8
  14. data/lib/dude/commands/stop.rb +0 -2
  15. data/lib/dude/commands/tasks.rb +0 -2
  16. data/lib/dude/commands/track.rb +2 -4
  17. data/lib/dude/config.rb +18 -0
  18. data/lib/dude/health_check.rb +39 -0
  19. data/lib/dude/project_management/client.rb +1 -3
  20. data/lib/dude/project_management/jira/client.rb +21 -11
  21. data/lib/dude/project_management/jira/fetch_current_task.rb +1 -3
  22. data/lib/dude/project_management/jira/fetch_current_tasks.rb +2 -4
  23. data/lib/dude/project_management/jira/get_task_name_by_id.rb +0 -2
  24. data/lib/dude/project_management/jira/move_task_to_list.rb +0 -2
  25. data/lib/dude/project_management/trello/client.rb +9 -5
  26. data/lib/dude/project_management/trello/fetch_current_task.rb +2 -4
  27. data/lib/dude/project_management/trello/fetch_current_tasks.rb +0 -2
  28. data/lib/dude/project_management/trello/fetch_lists.rb +1 -3
  29. data/lib/dude/project_management/trello/get_task_name_by_id.rb +1 -3
  30. data/lib/dude/project_management/trello/move_task_to_list.rb +1 -3
  31. data/lib/dude/setup/github.rb +35 -0
  32. data/lib/dude/setup/jira.rb +64 -0
  33. data/lib/dude/setup/toggl.rb +47 -0
  34. data/lib/dude/setup/trello.rb +58 -0
  35. data/lib/dude/templates/duderc_template +32 -0
  36. data/lib/dude/time_trackers/toggl/base.rb +2 -4
  37. data/lib/dude/version.rb +1 -1
  38. metadata +26 -3
  39. data/lib/dude/templates/pull_request_template +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6031769a356f360e4c2dcc232c0018aec9b00353908c4158e3fe3e7c030f8a6d
4
- data.tar.gz: 5e8697a8d8606d30029996965b347c00e025de94570366804fe9e2f29285a295
3
+ metadata.gz: 5a37ec9e7b502cf8da43c6e20431f452321dc55fd6ac0be38444e80cf0796fd0
4
+ data.tar.gz: fce3bf1daa29bc55f29cc4b96ccfc92ebcf694890b18153c3c4f162f5b641749
5
5
  SHA512:
6
- metadata.gz: 14ec971a8a01102bbca10813e4e3603d0a8bb132f7055f463016532cc9a28e170fdff23bb99749c0616cd800033d252a1a0eaac3800f093f7329b42dab3e60af
7
- data.tar.gz: 8ff94ed54537ea464c7f747d5a572ae98807081ad71ae8e7aa9ac2976c4d002c06af9004a6f8b48d787d87439df6517923a7a4ab113d340a23b45f0899dfb494
6
+ metadata.gz: b9e295659a902a6d904bab212191e1a19ff8a9b584a717008b493b9ec77c0583207033989cb65ab4afda97ff1653c20ff781bf44595e23f543446cd16acb2656
7
+ data.tar.gz: 0a1f084399039789b96b6bef5e24189ad4d7e4cd96cf57ef229f5ae1e31c2c877521dd3b0f81e9eaa62d4c2085f6d09e107ecc14a5ce201a8ec9d70b7f51f710
data/Gemfile.lock CHANGED
@@ -1,11 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dude-cli (2.1.0.alpha2)
4
+ dude-cli (2.1.0.alpha3)
5
5
  colorize (~> 0.8.1)
6
6
  dry-cli (~> 0.6)
7
7
  faraday (~> 1.1)
8
8
  jira-ruby (~> 2.1)
9
+ tty-prompt (~> 0.23.1)
9
10
 
10
11
  GEM
11
12
  remote: https://rubygems.org/
@@ -53,6 +54,8 @@ GEM
53
54
  parallel (1.20.1)
54
55
  parser (3.0.1.1)
55
56
  ast (~> 2.4.1)
57
+ pastel (0.8.0)
58
+ tty-color (~> 0.5)
56
59
  pry (0.14.1)
57
60
  coderay (~> 1.1)
58
61
  method_source (~> 1.0)
@@ -94,9 +97,20 @@ GEM
94
97
  simplecov (~> 0.8)
95
98
  simplecov-html (0.12.3)
96
99
  simplecov_json_formatter (0.1.2)
100
+ tty-color (0.6.0)
101
+ tty-cursor (0.7.1)
102
+ tty-prompt (0.23.1)
103
+ pastel (~> 0.8)
104
+ tty-reader (~> 0.8)
105
+ tty-reader (0.9.0)
106
+ tty-cursor (~> 0.7)
107
+ tty-screen (~> 0.8)
108
+ wisper (~> 2.0)
109
+ tty-screen (0.8.1)
97
110
  tzinfo (2.0.4)
98
111
  concurrent-ruby (~> 1.0)
99
112
  unicode-display_width (2.0.0)
113
+ wisper (2.0.1)
100
114
  zeitwerk (2.4.2)
101
115
 
102
116
  PLATFORMS
data/README.md CHANGED
@@ -8,7 +8,9 @@
8
8
 
9
9
  A daily assistant in the hard work of a programmer
10
10
 
11
- This program helps to combine such services as [Jira](https://atlassian.net), [Toggl](https://toggl.com) and replace most routine activities with one simple CLI utility.
11
+ This program helps to combine such services as [Jira](https://atlassian.net), [Trello](https://trello.com), [Toggl](https://toggl.com), etc. and replace most routine activities with one simple CLI utility.
12
+
13
+ ![Dude](/demo/dude.gif)
12
14
 
13
15
  ## Installation
14
16
 
@@ -26,54 +28,49 @@ Or install it yourself as:
26
28
 
27
29
  $ gem install dude-cli
28
30
 
29
- After that create .duderc file in your HOME directory by command:
31
+ After that create .duderc.yml file in your work project directory by command:
30
32
 
31
33
  $ dude install
32
34
 
33
- And configure all variables in this file
34
-
35
- `PROJECT_MANAGEMENT_TOOL=jira|trello` - Project management (Now only Jira and Trello supported)
36
-
37
- ##### Jira setup
38
-
39
- `ATLASSIAN_EMAIL` - Your Jira email
40
-
41
- `ATLASSIAN_TOKEN` - How to create Atlassian token: https://support.siteimprove.com/hc/en-gb/articles/360004317332-How-to-create-an-API-token-from-your-Atlassian-account
42
-
43
- `ATLASSIAN_URL` - URL of your project. Example: https://example.atlassian.net
35
+ It will offer you a step by step instruction how to setup dude:
44
36
 
45
- `ATLASSIAN_PROJECT_KEY` - KEY of your project. If your issues have id BT-123 - BT is the key
37
+ ![Setup Wizard](/demo/wizard.gif)
46
38
 
47
- `ATLASSIAN_BOARD_ID`:
48
- Just open your atlassian main board and copy id from the url after rapidView=*ID* part.
39
+ You always could edit this file manually and setup some stuff like Toggl time entry name or Github PR template
49
40
 
50
- Example: https://dealmakerns.atlassian.net/secure/RapidBoard.jspa?rapidView=23&projectKey=DT - 23 is the id
41
+ Default template could be found here: [lib/dude/templates/duderc_template](/lib/dude/templates/duderc_template)
51
42
 
52
- ##### Trello setup
53
- You could generate your key and token here: https://trello.com/app-key
54
-
55
- `TRELLO_KEY`
56
-
57
- `TRELLO_TOKEN`
43
+ ### Additional configuration variables:
58
44
 
59
45
  #### Replace it with your project list names. Skip for empty lists
60
46
 
61
- ```
62
- TODO_LIST_NAME=To Do
63
- IN_PROGRESS_LIST_NAME=In Progress
64
- CODE_REVIEW_LIST_NAME=Code Review
65
- TESTING_LIST_NAME=TESTABLE
66
- DONE_LIST_NAME=Done
47
+ ```yaml
48
+ :todo_list_name: To Do
49
+ :in_progress_list_name: In Progress
50
+ :code_review_list_name: Code Review
51
+ :testing_list_name: TESTABLE
52
+ :done_list_name: Done
67
53
  ```
68
54
 
69
- `TOGGL_PROJECT_NAME` - Your Toggl project name
55
+ #### Use the *{issue_id}* and *{issue_title}* and specify format for the task titles in Toggl or keep it as it is
70
56
 
71
- `TOGGL_TOKEN` - Your Toggl API token can be found at the bottom of the page: https://track.toggl.com/profile
72
-
73
- `TOGGL_WORKSPACE_ID` - Can be copied from url here: https://toggl.com/app/projects/. Example: 123456
57
+ ```yaml
58
+ :toggl:
59
+ :task_format: [{issue_id}] {issue_title}
60
+ ```
74
61
 
75
- #### Use the *id* and *title* and specify format for the task titles in Toggl or keep it as it is
76
- `TOGGL_TASK_FORMAT=[id] title`
62
+ #### Github PR template looks like this (Available variables: *{issue_id}*, *{issue_title}*, *{issue_url}*)
63
+
64
+ ```yaml
65
+ :github:
66
+ :pr_template:
67
+ :title: "[{issue_id}] {issue_title}\n"
68
+ :body: |
69
+ ## Story
70
+ [**\[{issue_id}\] {issue_title}**]({issue_url})
71
+ ## Description
72
+ Example description of the issue
73
+ ```
77
74
 
78
75
  ## Usage
79
76
 
@@ -88,14 +85,16 @@ alias dude="rvm 2.7.2 do dude"
88
85
 
89
86
  | Command | Required parameters | Optional parameters | Description |
90
87
  |:-------------:|:-------------------|:-------------------|:--------------------------------------------------------------------------------------|
91
- | dude install | - | - | Create .duderc file in your home directory |
92
- | dude checkout | ISSUE_ID | - | Checkout to branch with name "ID-issue-title" |
93
- | dude track | ISSUE_ID | - | Start time entry in Toggl with issue project, title and id |
94
- | dude tasks | - | - | Show all issues in current project (For current sprint) |
95
- | dude stop | - | - | Stop current time entry in Toggl |
96
- | dude start | ISSUE_ID | - | Do `checkout`, `track` and `move` actions |
97
- | dude move | ISSUE_ID | --list=NAME | Move issue to another column (Will provide options if called without --list parameter) |
98
- | dude version | - | - | Display gem version |
88
+ | dude install | - | - | Create .duderc file in your home directory |
89
+ | dude checkout | ISSUE_ID | - | Checkout to branch with name "ID-issue-title" |
90
+ | dude track | ISSUE_ID | - | Start time entry in Toggl with issue project, title and id |
91
+ | dude tasks | - | - | Show all issues in current project (For current sprint) |
92
+ | dude stop | - | - | Stop current time entry in Toggl |
93
+ | dude start | ISSUE_ID | - | Do `checkout`, `track` and `move` actions |
94
+ | dude move | ISSUE_ID | --list=NAME | Move issue to another column (Will provide options if called without --list parameter) |
95
+ | dude pr create | | | Creates PR in Github using template |
96
+ | dude version | - | - | Display gem version |
97
+ | dude healthcheck | - | - | Check configuration of all dependencies |
99
98
 
100
99
  You also can use `dude help` for short description of every command.
101
100
 
@@ -109,4 +108,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
109
108
 
110
109
  ## Changelog
111
110
 
112
- https://github.com/npupko/dude/blob/master/CHANGELOG.md
111
+ [CHANGELOG.md](/CHANGELOG.md)
data/demo/dude.gif ADDED
Binary file
data/demo/wizard.gif ADDED
Binary file
data/dude.gemspec CHANGED
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_runtime_dependency 'dry-cli', '~> 0.6'
33
33
  spec.add_runtime_dependency 'faraday', '~> 1.1'
34
34
  spec.add_runtime_dependency 'jira-ruby', '~> 2.1'
35
+ spec.add_runtime_dependency 'tty-prompt', '~> 0.23.1'
35
36
 
36
37
  spec.add_development_dependency 'pry', '~> 0.14.0'
37
38
  spec.add_development_dependency 'rake', '~> 13.0'
data/lib/dude.rb CHANGED
@@ -2,14 +2,22 @@
2
2
 
3
3
  require 'colorize'
4
4
 
5
+ begin
6
+ require 'pry'
7
+ rescue LoadError
8
+ nil
9
+ end
10
+
5
11
  require_relative './dude/settings'
6
12
  require_relative './dude/version'
7
13
  require_relative './dude/commands'
8
14
  require_relative './dude/git'
9
15
  require_relative './dude/code_management'
16
+ require_relative './dude/config'
10
17
 
11
18
  module Dude
12
- class ToBeImplementedError < StandardError; end
13
-
19
+ SETTINGS = Dude::Config.configure_with('.duderc.yml')
14
20
  LIST_OF_AVAILABLE_PROJECT_MANAGEMENT_TOOLS = %w[jira trello].freeze
21
+
22
+ class ToBeImplementedError < StandardError; end
15
23
  end
@@ -6,17 +6,21 @@ module Dude
6
6
  module CodeManagement
7
7
  module Github
8
8
  class Client
9
- include Settings
10
-
11
9
  def client
12
10
  @client ||= Faraday.new('https://api.github.com/', {
13
- headers: { Authorization: "token #{settings['GITHUB_TOKEN']}" }
11
+ headers: { Authorization: "token #{Dude::SETTINGS.dig(:github, :token)}" }
14
12
  })
15
13
  end
16
14
 
17
15
  def create_pull_request(issue:, owner:, repo:, params:)
18
16
  CreatePullRequest.new.call(client, issue: issue, owner: owner, repo: repo, params: params)
19
17
  end
18
+
19
+ def health_check
20
+ client.get('https://api.github.com/user').status == 200
21
+ rescue StandardError
22
+ false
23
+ end
20
24
  end
21
25
  end
22
26
  end
@@ -6,8 +6,6 @@ module Dude
6
6
  module CodeManagement
7
7
  module Github
8
8
  class CreatePullRequest
9
- include Settings
10
-
11
9
  def call(client, issue:, owner:, repo:, params:)
12
10
  @issue = issue
13
11
  @owner = owner
data/lib/dude/commands.rb CHANGED
@@ -10,6 +10,7 @@ require_relative './commands/track'
10
10
  require_relative './commands/stop'
11
11
  require_relative './commands/install'
12
12
  require_relative './commands/pr'
13
+ require_relative './commands/health_check'
13
14
 
14
15
  module Dude
15
16
  module Commands
@@ -23,6 +24,7 @@ module Dude
23
24
  register 'track', Dude::Commands::Track, aliases: ['tr']
24
25
  register 'stop', Dude::Commands::Stop
25
26
  register 'start', Dude::Commands::Start, aliases: ['st']
27
+ register 'healthcheck', Dude::Commands::HealthCheck
26
28
 
27
29
  register 'pr' do |prefix|
28
30
  prefix.register 'create', Dude::Commands::PR::Create
@@ -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
@@ -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
@@ -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,25 @@ 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'],
22
- context_path: '',
23
- auth_type: :basic
24
- }
15
+ class << self
16
+ def options
17
+ {
18
+ username: Dude::SETTINGS.dig(:jira, :email),
19
+ password: Dude::SETTINGS.dig(:jira, :token),
20
+ site: Dude::SETTINGS.dig(:jira, :project, :url),
21
+ context_path: '',
22
+ auth_type: :basic
23
+ }
24
+ end
25
+ end
25
26
 
27
+ def initialize
26
28
  @client = JIRA::Client.new(options)
27
- @project = client.Project.find(settings['ATLASSIAN_PROJECT_KEY'])
29
+ @project = client.Project.find(Dude::SETTINGS.dig(:jira, :project, :key))
30
+ rescue StandardError
31
+ nil
28
32
  end
29
33
 
30
34
  def respond_to_missing?(method_name, include_private = false)
@@ -50,6 +54,12 @@ module Dude
50
54
  def get_task_name_by_id(id)
51
55
  GetTaskNameById.new(client, id: id).call
52
56
  end
57
+
58
+ def health_check
59
+ @project && true
60
+ rescue StandardError
61
+ false
62
+ end
53
63
  end
54
64
  end
55
65
  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
@@ -28,7 +26,7 @@ module Dude
28
26
  description: issue.description,
29
27
  status: issue.status.name,
30
28
  assignee: issue&.assignee&.displayName,
31
- url: "#{settings['ATLASSIAN_URL']}/browse/#{issue.key}"
29
+ url: "#{Dude::SETTINGS.dig(:dig, :project, :url)}/browse/#{issue.key}"
32
30
  )
33
31
  end
34
32
  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
@@ -4,8 +4,6 @@ module Dude
4
4
  module ProjectManagement
5
5
  module Jira
6
6
  class GetTaskNameById
7
- include Settings
8
-
9
7
  def initialize(client, id:)
10
8
  @client = client
11
9
  @id = id
@@ -4,8 +4,6 @@ module Dude
4
4
  module ProjectManagement
5
5
  module Jira
6
6
  class MoveTaskToList
7
- include Settings
8
-
9
7
  def initialize(client, id:, list_name:)
10
8
  @client = client
11
9
  @id = id
@@ -12,13 +12,11 @@ module Dude
12
12
  module ProjectManagement
13
13
  module Trello
14
14
  class Client
15
- include Settings
16
-
17
15
  def client
18
16
  @client ||= Faraday.new('https://api.trello.com/', {
19
17
  params: {
20
- key: settings['TRELLO_KEY'],
21
- token: settings['TRELLO_TOKEN']
18
+ key: Dude::SETTINGS.dig(:trello, :key),
19
+ token: Dude::SETTINGS.dig(:trello, :token)
22
20
  }
23
21
  })
24
22
  end
@@ -28,7 +26,7 @@ module Dude
28
26
  end
29
27
 
30
28
  def respond_to_missing?(method_name, include_private = false)
31
- client.respond_to_missing?(method_name, include_private)
29
+ client.respond_to?(method_name, include_private)
32
30
  end
33
31
 
34
32
  def fetch_current_tasks
@@ -46,6 +44,12 @@ module Dude
46
44
  def get_task_name_by_id(id)
47
45
  GetTaskNameById.new(client, id: id).call
48
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
49
53
  end
50
54
  end
51
55
  end
@@ -4,15 +4,13 @@ module Dude
4
4
  module ProjectManagement
5
5
  module Trello
6
6
  class FetchCurrentTask
7
- include Settings
8
-
9
7
  def initialize(client, id:)
10
8
  @client = client
11
9
  @id = id
12
10
  end
13
11
 
14
12
  def call
15
- response = client.get("/1/boards/#{settings['ATLASSIAN_BOARD_ID']}/cards/#{id}")
13
+ response = client.get("/1/boards/#{Dude::SETTINGS.dig(:jira, :board_id)}/cards/#{id}")
16
14
  create_issue JSON.parse(response.body)
17
15
  end
18
16
 
@@ -25,7 +23,7 @@ module Dude
25
23
  id: issue['idShort'],
26
24
  title: issue['name'],
27
25
  description: issue['desc'],
28
- status: settings['IN_PROGRESS_LIST_NAME'], # OMG, let's fix this later
26
+ status: Dude::SETTINGS[:in_progress_list_name], # OMG, let's fix this later
29
27
  assignee: members(issue),
30
28
  url: issue['shortUrl']
31
29
  )
@@ -6,8 +6,6 @@ module Dude
6
6
  module ProjectManagement
7
7
  module Trello
8
8
  class FetchCurrentTasks
9
- include Settings
10
-
11
9
  attr_reader :fetch_lists
12
10
 
13
11
  def initialize(client, fetch_lists: nil)
@@ -4,14 +4,12 @@ module Dude
4
4
  module ProjectManagement
5
5
  module Trello
6
6
  class FetchLists
7
- include Settings
8
-
9
7
  def initialize(client)
10
8
  @client = client
11
9
  end
12
10
 
13
11
  def call
14
- response = client.get("/1/board/#{settings['ATLASSIAN_BOARD_ID']}/lists", { fields: 'name' })
12
+ response = client.get("/1/board/#{Dude::SETTINGS.dig(:jira, :board_id)}/lists", { fields: 'name' })
15
13
  JSON.parse(response.body)
16
14
  end
17
15
 
@@ -4,15 +4,13 @@ module Dude
4
4
  module ProjectManagement
5
5
  module Trello
6
6
  class GetTaskNameById
7
- include Settings
8
-
9
7
  def initialize(client, id:)
10
8
  @client = client
11
9
  @id = id
12
10
  end
13
11
 
14
12
  def call
15
- response = client.get("/1/boards/#{settings['ATLASSIAN_BOARD_ID']}/cards/#{id}")
13
+ response = client.get("/1/boards/#{Dude::SETTINGS.dig(:jira, :board_id)}/cards/#{id}")
16
14
  JSON.parse(response.body)['name']
17
15
  end
18
16
 
@@ -6,8 +6,6 @@ module Dude
6
6
  module ProjectManagement
7
7
  module Trello
8
8
  class MoveTaskToList
9
- include Settings
10
-
11
9
  def initialize(client, id:, list_name:)
12
10
  @client = client
13
11
  @id = id
@@ -15,7 +13,7 @@ module Dude
15
13
  end
16
14
 
17
15
  def call
18
- response = client.get("/1/boards/#{settings['ATLASSIAN_BOARD_ID']}/cards/#{id}", { fields: 'id' })
16
+ response = client.get("/1/boards/#{Dude::SETTINGS.dig(:jira, :board_id)}/cards/#{id}", { fields: 'id' })
19
17
  card_id = JSON.parse(response.body)['id']
20
18
  client.put("/1/cards/#{card_id}", { idList: list_id })
21
19
  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
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dude
4
+ module Setup
5
+ class Toggl
6
+ def initialize(prompt)
7
+ @prompt = prompt
8
+ end
9
+
10
+ def call(settings:)
11
+ settings[:toggl][:token] = setup_token
12
+ settings[:toggl][:project_name] = setup_project_name
13
+ settings[:toggl][:workspace_id] = setup_workspace_id
14
+ settings
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :prompt
20
+
21
+ def setup_token
22
+ puts <<~HEREDOC
23
+ You need to create personal token
24
+
25
+ #{'1.'.bold} Log in to https://trello.com/app-key
26
+ #{'2.'.bold} Your Toggl API token can be found at the bottom of the page
27
+ #{'3.'.bold} Press --Click to Reveal-- and paste token below
28
+ HEREDOC
29
+
30
+ if prompt.yes?(Dude::Config.style_prompt('Open Toggl profile page in your browser?'))
31
+ `open https://track.toggl.com/profile`
32
+ end
33
+
34
+ prompt.ask(Dude::Config.style_prompt('Toggl token:'), required: true)
35
+ end
36
+
37
+ def setup_project_name
38
+ prompt.ask(Dude::Config.style_prompt('Your Toggl project name:'), required: true)
39
+ end
40
+
41
+ def setup_workspace_id
42
+ puts 'Can be copied from url here: https://toggl.com/app/projects/ (Example: 123456)'
43
+ prompt.ask(Dude::Config.style_prompt('Workspace ID:'), required: true)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dude
4
+ module Setup
5
+ class Trello
6
+ def initialize(prompt)
7
+ @prompt = prompt
8
+ end
9
+
10
+ def call(settings:)
11
+ settings[:trello][:key] = setup_key
12
+ settings[:trello][:token] = setup_token
13
+ settings[:trello][:board_id] = setup_board_id
14
+ settings
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :prompt
20
+
21
+ def setup_email
22
+ prompt.ask(Dude::Config.style_prompt('Jira user email:'), required: true)
23
+ end
24
+
25
+ def setup_key
26
+ puts <<~HEREDOC
27
+ You need to create personal token
28
+
29
+ #{'1.'.bold} Log in to https://trello.com/app-key
30
+ #{'2.'.bold} Copy KEY and paste it below
31
+ HEREDOC
32
+
33
+ if prompt.yes?(Dude::Config.style_prompt('Open Trello token creation page in your browser?'))
34
+ `open https://trello.com/app-key`
35
+ end
36
+
37
+ prompt.ask(Dude::Config.style_prompt('Trello key:'), required: true)
38
+ end
39
+
40
+ def setup_token
41
+ puts <<~HEREDOC
42
+ You need to create personal token
43
+
44
+ #{'1.'.bold} Log in to https://trello.com/app-key
45
+ #{'2.'.bold} From the dialog that appears click 'Allow'
46
+ #{'3.'.bold} Copy created token to clipboard and paste the it below
47
+ HEREDOC
48
+
49
+ prompt.ask(Dude::Config.style_prompt('Trello token:'), required: true)
50
+ end
51
+
52
+ def setup_board_id
53
+ puts 'Just open your Trello main board and copy id from the url (Example: 123aBcdE)'
54
+ prompt.ask(Dude::Config.style_prompt('Board ID:'), required: true)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,32 @@
1
+ ---
2
+ :project_management_tool: jira
3
+ :jira:
4
+ :email:
5
+ :token:
6
+ :project:
7
+ :url:
8
+ :key:
9
+ :board_id:
10
+ :trello:
11
+ :board_id:
12
+ :key:
13
+ :token:
14
+ :todo_list_name: To Do
15
+ :in_progress_list_name: In Progress
16
+ :code_review_list_name: Code Review
17
+ :testing_list_name: TESTABLE
18
+ :done_list_name: Done
19
+ :toggl:
20
+ :project_name:
21
+ :token:
22
+ :workspace_id:
23
+ :task_format: "[{issue_id}] {issue_title}"
24
+ :github:
25
+ :token:
26
+ :pr_template:
27
+ :title: "[{issue_id}] {issue_title}\n"
28
+ :body: |
29
+ ## Story
30
+ [**\[{issue_id}\] {issue_title}**]({issue_url})
31
+ ## Description
32
+ Example description of the issue
@@ -5,17 +5,15 @@ require 'faraday'
5
5
  module Dude
6
6
  module Toggl
7
7
  class Base
8
- include Settings
9
-
10
8
  def toggl_api
11
9
  Faraday.new('https://api.track.toggl.com') do |conn|
12
- conn.basic_auth settings['TOGGL_TOKEN'], 'api_token'
10
+ conn.basic_auth Dude::SETTINGS.dig(:toggl, :token), 'api_token'
13
11
  conn.headers['Content-Type'] = 'application/json'
14
12
  end
15
13
  end
16
14
 
17
15
  def projects_response
18
- toggl_api.get("/api/v8/workspaces/#{settings['TOGGL_WORKSPACE_ID']}/projects")
16
+ toggl_api.get("/api/v8/workspaces/#{Dude::SETTINGS.dig(:toggl, :workspace_id)}/projects")
19
17
  end
20
18
  end
21
19
  end
data/lib/dude/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dude
4
- VERSION = '2.1.0.alpha2'
4
+ VERSION = '2.1.0.alpha3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dude-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0.alpha2
4
+ version: 2.1.0.alpha3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nikita Pupko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-01 00:00:00.000000000 Z
11
+ date: 2021-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: tty-prompt
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.23.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.23.1
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: pry
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -176,6 +190,8 @@ files:
176
190
  - bin/console
177
191
  - bin/dude
178
192
  - bin/setup
193
+ - demo/dude.gif
194
+ - demo/wizard.gif
179
195
  - dude.gemspec
180
196
  - lib/dude.rb
181
197
  - lib/dude/code_management.rb
@@ -183,6 +199,7 @@ files:
183
199
  - lib/dude/code_management/github/create_pull_request.rb
184
200
  - lib/dude/commands.rb
185
201
  - lib/dude/commands/checkout.rb
202
+ - lib/dude/commands/health_check.rb
186
203
  - lib/dude/commands/install.rb
187
204
  - lib/dude/commands/move.rb
188
205
  - lib/dude/commands/pr.rb
@@ -193,10 +210,12 @@ files:
193
210
  - lib/dude/commands/tasks.rb
194
211
  - lib/dude/commands/track.rb
195
212
  - lib/dude/commands/version.rb
213
+ - lib/dude/config.rb
196
214
  - lib/dude/git.rb
197
215
  - lib/dude/git/checkout.rb
198
216
  - lib/dude/git/current_branch_name.rb
199
217
  - lib/dude/git/remote_name.rb
218
+ - lib/dude/health_check.rb
200
219
  - lib/dude/project_management/client.rb
201
220
  - lib/dude/project_management/entities/issue.rb
202
221
  - lib/dude/project_management/jira.rb
@@ -213,7 +232,11 @@ files:
213
232
  - lib/dude/project_management/trello/get_task_name_by_id.rb
214
233
  - lib/dude/project_management/trello/move_task_to_list.rb
215
234
  - lib/dude/settings.rb
216
- - lib/dude/templates/pull_request_template
235
+ - lib/dude/setup/github.rb
236
+ - lib/dude/setup/jira.rb
237
+ - lib/dude/setup/toggl.rb
238
+ - lib/dude/setup/trello.rb
239
+ - lib/dude/templates/duderc_template
217
240
  - lib/dude/time_trackers/toggl.rb
218
241
  - lib/dude/time_trackers/toggl/base.rb
219
242
  - lib/dude/time_trackers/toggl/start_time_entry.rb
@@ -1,7 +0,0 @@
1
- title: >
2
- [{issue_id}] {issue_title}
3
- body: |
4
- ## Story
5
- [**\[{issue_id}\] {issue_title}**]({issue_url})
6
- ## Description
7
- Example description of the issue