durt 0.11.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a79549849f47d7161682e6dfc419395c07b1a85acb64e3fb1960564c444a1625
4
+ data.tar.gz: 349b33a912f66978bd7f9d92d0ac90d40f9747a0f5f24ef636d0897886f944c3
5
+ SHA512:
6
+ metadata.gz: 9e5facc089af1213b1b6ee26344e1e8a766d827c261294281de3004f01c84be1ac79f4adb599ecfeda7c53cd70698767ec89dc0a947f583ba8d6743a2c87ae9e
7
+ data.tar.gz: e9afa291bf22c73a703326f6312144719300001092bcbc8125885dfe1acaee92b491609306a4ad0350cd9e312abab039a1e62d6a9b3a03fa03b8a2a70594dd30
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Luis Felipe Sanchez (durt.github.io)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,99 @@
1
+ # Durt
2
+
3
+ Small Ruby program generated using https://github.com/snada/generator-ruby-cmd
4
+
5
+ ## Install
6
+
7
+ This is a Ruby program and uses Bundler to ensure dependencies consistency. On your machine navigate to the project root and run:
8
+
9
+ ```bash
10
+ # If not already installed:
11
+ gem install bundler
12
+
13
+ bundle install
14
+ ```
15
+
16
+ This code is packaged as a Ruby gem, and it should be built and installed running these commands:
17
+
18
+ ```bash
19
+ gem build durt.gemspec
20
+ gem install durt
21
+ ```
22
+
23
+ ## Setup
24
+
25
+ First, you will want to initialize your issues database.
26
+
27
+ ```
28
+ durt init
29
+ ```
30
+
31
+
32
+ Make sure Upwork client (or pick time tracker) is running and in the correct
33
+ project.
34
+
35
+ Then, create `.durt.yml` at your root folder. Example for Jira project:
36
+
37
+ ```
38
+ # ~/.durt.yml
39
+
40
+ ---
41
+ Jira:
42
+ :username: username@example.com
43
+ :password: yourpassword
44
+ :site: http://yourproject.atlassian.net:443/
45
+ :context_path: ''
46
+ :auth_type: :basic
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ If you followed the above instruction and the gem is installed on the system, you should have the binary file ready to run from your command line.
52
+
53
+ Start by choosing the issue statuses that you'll be able to choose from:
54
+
55
+ ```bash
56
+ durt statuses
57
+ ```
58
+
59
+ Next, pick an issue to work on:
60
+
61
+ ```bash
62
+ durt memo
63
+ ```
64
+
65
+ You will be asked to estimate the time it will take you to work on this issue.
66
+ Valid inputs include: `29 minutes`, `3 hours`, `123249 sec` `3 min`, etc.
67
+ As long as it includes a number and something that resembles a time measure it
68
+ will not complain.
69
+
70
+ If you wish to execute without installing, you can by launching this command from the project root directory:
71
+
72
+ ```bash
73
+ ruby -Ilib bin/durt memo
74
+ ```
75
+
76
+ Other commands include:
77
+
78
+ ```bash
79
+ durt start
80
+ durt stop
81
+ durt stats
82
+ durt stats-all
83
+ durt edit-estimate
84
+ ```
85
+
86
+ ## Testing
87
+
88
+ This code is covered with both unit tests and feature tests, using Rspec (testing library classes) and Cucumber/Aruba (testing the actual command line program).
89
+
90
+ You can launch the test suite by running:
91
+
92
+ ```bash
93
+ bundle exec rake spec
94
+ bundle exec rake features
95
+ #launch both:
96
+ bundle exec rake
97
+ ```
98
+
99
+ For unit tests, a simple code coverage tool is provided, and you can see the results by opening the generated `coverage` folder.
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/durt'
5
+
6
+ # Read lines from both file or STDIN
7
+ # lines = (ARGV[0] ? IO.readlines(ARGV[0]) : ARGF.readlines).map(&:chomp)
8
+
9
+ # puts Durt::VERSION
10
+
11
+ command = ARGV[0]
12
+ # options = ARGV[1..-1]
13
+
14
+ def current_project
15
+ Durt::Project.current_project
16
+ end
17
+
18
+ NULL_COMMAND = Durt::Command::NullCommand
19
+ VERSION_COMMAND = Durt::Command::Version
20
+ BROWSE_DB_COMMAND = Durt::Command::BrowseDb
21
+ CONSOLE_COMMAND = Durt::Command::Console
22
+ SYNC_COMMAND = Durt::Command::SyncIssues
23
+
24
+ COMMAND_TRANSLATIONS =
25
+ {
26
+ '-v' => VERSION_COMMAND,
27
+ 'db' => BROWSE_DB_COMMAND,
28
+ 'sync' => SYNC_COMMAND,
29
+ 'c' => CONSOLE_COMMAND,
30
+ nil => NULL_COMMAND
31
+ }.freeze
32
+
33
+ command_klass =
34
+ COMMAND_TRANSLATIONS[command] ||
35
+ "Durt::Command::#{command.underscore.camelize}"
36
+ .yield_self { |name| Object.const_defined?(name) && name.constantize } ||
37
+ NULL_COMMAND
38
+
39
+ begin
40
+ command_klass.call
41
+ rescue ActiveRecord::StatementInvalid => e
42
+ raise e unless Durt.env.production?
43
+
44
+ puts e.message
45
+ puts "Database structure is incorrect"
46
+ puts "You might need to run 'durt init'"
47
+ end
@@ -0,0 +1,22 @@
1
+ default: &default
2
+ adapter: sqlite3
3
+ encoding: unicode
4
+ pool: 5
5
+ timeout: 5000
6
+ host: localhost
7
+
8
+ development:
9
+ <<: *default
10
+ database: <%= ENV['HOME'] %>/.durt/db/development.sqlite3
11
+
12
+ test: &test
13
+ <<: *default
14
+ database: <%= ENV['HOME'] %>/.durt/db/test.sqlite3
15
+
16
+ production:
17
+ <<: *default
18
+ database: <%= ENV['HOME'] %>/.durt/db/production.sqlite3
19
+
20
+ sample:
21
+ <<: *default
22
+ database: db/sample.sqlite3
Binary file
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pry'
4
+ require 'active_support'
5
+ require 'active_support/inflector'
6
+ require 'erb'
7
+
8
+ ENV['RAILS_ENV'] = ENV.fetch('DURT_ENV', 'production')
9
+
10
+ require 'active_record'
11
+
12
+ module Durt
13
+ def self.env
14
+ ActiveSupport::StringInquirer.new(ENV['RAILS_ENV'])
15
+ end
16
+ end
17
+
18
+ config_file_path = File.expand_path('../db/config.yml', __dir__)
19
+
20
+ db_config =
21
+ YAML.load(ERB.new(IO.read(config_file_path)).result)
22
+
23
+ raise 'Sample db should be blank and remain unused' if Durt.env.sample?
24
+
25
+ ActiveRecord::Base.establish_connection(db_config[Durt.env])
26
+
27
+ require_relative 'durt/version'
28
+ require_relative 'durt/configurable'
29
+ require_relative 'durt/project'
30
+ require_relative 'durt/service'
31
+ require_relative 'durt/command'
32
+
33
+ require_relative 'durt/global_controller'
34
+ require_relative 'durt/project_controller'
35
+ require_relative 'durt/local_plugin'
36
+ require_relative 'durt/notify_plugin'
37
+ require_relative 'durt/upwork_plugin'
38
+ require_relative 'durt/github_plugin'
39
+ require_relative 'durt/jira_plugin'
40
+ require_relative 'durt/pivotal_plugin'
41
+ require_relative 'durt/ebs_plugin'
42
+
43
+ require_relative 'durt/issue'
44
+ require_relative 'durt/session'
45
+ require_relative 'durt/status'
46
+
47
+ require_relative 'durt/null_time_tracker'
48
+ require_relative 'durt/local_bug_tracker'
49
+ require_relative 'durt/notify_tracker'
50
+ require_relative 'durt/upwork_tracker'
51
+ require_relative 'durt/null_bug_tracker'
52
+ require_relative 'durt/github_bug_tracker'
53
+ require_relative 'durt/jira_bug_tracker'
54
+ require_relative 'durt/pivotal_bug_tracker'
55
+
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Durt
4
+ class ApplicationRecord < ::ActiveRecord::Base
5
+ self.abstract_class = true
6
+
7
+ scope :to_choice_h, -> { Hash[map { |r| [r.to_s, r] }] }
8
+
9
+ def active!
10
+ reload.update(active: true)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jira-ruby'
4
+
5
+ module Durt
6
+ class BugTracker
7
+ attr_reader :project
8
+
9
+ def initialize(project, config = nil)
10
+ @project = project
11
+ @config = config
12
+
13
+ after_initialize
14
+ end
15
+
16
+ def after_initialize; end
17
+
18
+ def active?
19
+ true
20
+ end
21
+
22
+ def fetch_issues
23
+ raise NotImplementedError
24
+ end
25
+
26
+ def fetch_statuses
27
+ raise NotImplementedError
28
+ end
29
+
30
+ def source_name
31
+ self.class.name.split('::').last.sub('BugTracker', '')
32
+ end
33
+
34
+ def issues
35
+ project.issues.where(source: source_name)
36
+ end
37
+
38
+ def statuses
39
+ Durt::Status.where(source: source_name)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Durt
4
+ module Command
5
+ class Init < ::Durt::Service
6
+ def initialize
7
+ durt_db_dir = File.expand_path('~/.durt/db')
8
+ db_sample = File.expand_path('../../db/sample.sqlite3', __dir__)
9
+ copy_dest = File.join(durt_db_dir, 'production.sqlite3')
10
+ dest_exist = File.exist?(copy_dest)
11
+
12
+ FileUtils.mkdir_p(durt_db_dir, verbose: true)
13
+ FileUtils.cp(db_sample, copy_dest, noop: dest_exist, verbose: true)
14
+ end
15
+ end
16
+
17
+ class BrowseDb < ::Durt::Service
18
+ def initialize
19
+ system("sqlitebrowser #{ActiveRecord::Base.connection_config[:database]}")
20
+ end
21
+ end
22
+
23
+ class Version < ::Durt::Service
24
+ def initialize
25
+ puts Durt::VERSION
26
+ end
27
+ end
28
+
29
+ class NullCommand < ::Durt::Service
30
+ def initialize
31
+ puts 'Unknown command'
32
+ exit
33
+ end
34
+ end
35
+
36
+ class Console < ::Durt::Service
37
+ def initialize
38
+ controller = Durt::GlobalController.new
39
+
40
+ steps << ->(_) { controller.console }
41
+ end
42
+ end
43
+
44
+ class NewProject < ::Durt::Service
45
+ def initialize
46
+ controller = Durt::GlobalController.new
47
+
48
+ steps << ->(_) { controller.create_project }
49
+ steps << ->(project) { controller.create_project_config(project) }
50
+ steps << ->(project) { controller.select_project(project) }
51
+ steps << ->(project) { controller.switch_to_project(project) }
52
+ end
53
+ end
54
+
55
+ class SelectProject < ::Durt::Service
56
+ def initialize
57
+ controller = Durt::GlobalController.new
58
+
59
+ steps << ->(_) { controller.select_project }
60
+ steps << ->(project) { controller.switch_to_project(project) }
61
+ end
62
+ end
63
+
64
+ class Filter < ::Durt::Service
65
+ def initialize
66
+ project = Durt::Project.current_project
67
+ controller = Durt::ProjectController.new(project)
68
+
69
+ steps << ->(_) { controller.filter }
70
+ end
71
+ end
72
+
73
+ class Memo < ::Durt::Service
74
+ def initialize
75
+ project = Durt::Project.current_project
76
+ controller = Durt::ProjectController.new(project)
77
+
78
+ steps << ->(_) { controller.sync_issues }
79
+ steps << ->(_) { controller.select_issue }
80
+ steps << ->(issue) { controller.enter_issue(issue) }
81
+ end
82
+ end
83
+
84
+ class SelectIssue < ::Durt::Service
85
+ def initialize
86
+ project = Durt::Project.current_project
87
+ controller = Durt::ProjectController.new(project)
88
+
89
+ steps << ->(_) { controller.select_issue }
90
+ end
91
+ end
92
+
93
+ class SyncIssues < ::Durt::Service
94
+ def initialize
95
+ project = Durt::Project.current_project
96
+ controller = Durt::ProjectController.new(project)
97
+
98
+ steps << ->(_) { controller.sync_issues }
99
+ end
100
+ end
101
+
102
+ class NewIssue < ::Durt::Service
103
+ def initialize
104
+ project = Durt::Project.current_project
105
+ controller = Durt::ProjectController.new(project)
106
+
107
+ steps << ->(_) { controller.new_issue }
108
+ steps << ->(issue) { controller.select_issue(issue) }
109
+ steps << ->(issue) { controller.push_issue(issue) }
110
+ end
111
+ end
112
+
113
+ class Start < ::Durt::Service
114
+ def initialize
115
+ project = Durt::Project.current_project
116
+ controller = Durt::ProjectController.new(project)
117
+
118
+ steps << ->(_) { controller.current_issue }
119
+ steps << ->(issue) { controller.start_issue(issue) }
120
+ end
121
+ end
122
+
123
+ class Stop < ::Durt::Service
124
+ def initialize
125
+ project = Durt::Project.current_project
126
+ controller = Durt::ProjectController.new(project)
127
+
128
+ steps << ->(_) { controller.current_issue }
129
+ steps << ->(issue) { controller.stop_issue(issue) }
130
+ end
131
+ end
132
+
133
+ class Stats < ::Durt::Service
134
+ def initialize
135
+ Durt::Project.current_project.active_issue.puts_stats
136
+ end
137
+ end
138
+
139
+ class ProjectStats < ::Durt::Service
140
+ def initialize
141
+ Durt::Project.current_project.puts_stats
142
+ end
143
+ end
144
+ end
145
+ end