time_log_robot 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 02779016739df4a954e1bdb2a1497dec6fc5c75f
4
+ data.tar.gz: bb7e9647e14ed514a143ac06f9e3e855388a2446
5
+ SHA512:
6
+ metadata.gz: dfec06ec09c95fef5e4085cbdbc8a8fe4a23efc9a58fa18f1f09b7f01cc0396592c78b00b4c5f1c5b225d1a54906bdaeb91ab31ca32aba5dab4e11a26b6fe916
7
+ data.tar.gz: 7fad04cb28781642f91bb496551f3cf38ddf6e5caeb633a22ce7c7d8811ba40823402fb7725e070d9839aa9b8ff0ac686b316e932aa9e884ac16b363d19f99df
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ config/settings.sample.yaml
2
+ pkg/
data/.settings.yml ADDED
@@ -0,0 +1 @@
1
+ ---
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ time_log_robot (0.1.0)
5
+ activesupport (~> 4.2, >= 4.2.6)
6
+ commander (~> 4.1, >= 4.1.6)
7
+ httparty (~> 0.13, >= 0.13.0)
8
+ json (~> 1.8, >= 1.8.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ activesupport (4.2.6)
14
+ i18n (~> 0.7)
15
+ json (~> 1.7, >= 1.7.7)
16
+ minitest (~> 5.1)
17
+ thread_safe (~> 0.3, >= 0.3.4)
18
+ tzinfo (~> 1.1)
19
+ commander (4.1.6)
20
+ highline (~> 1.6.11)
21
+ highline (1.6.21)
22
+ httparty (0.13.3)
23
+ json (~> 1.8)
24
+ multi_xml (>= 0.5.2)
25
+ i18n (0.7.0)
26
+ json (1.8.3)
27
+ minitest (5.8.4)
28
+ multi_xml (0.5.5)
29
+ rake (10.5.0)
30
+ thread_safe (0.3.5)
31
+ tzinfo (1.2.2)
32
+ thread_safe (~> 0.1)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ bundler (~> 1.3)
39
+ rake (~> 10.5)
40
+ time_log_robot!
41
+
42
+ BUNDLED WITH
43
+ 1.12.3
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 Mark J. Lehman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # Time Log Robot
2
+ ***Let the robot do your work time logging.***
3
+
4
+ This is an integration between project management tools (like JIRA) and time logging apps (like Toggl). Currently, it only works as an import from Toggl into JIRA.
5
+
6
+ ## Installation
7
+
8
+ ~~Download this gem:~~ This is not yet on RubyGems, but once it is, you will be able to download like so:
9
+
10
+ gem install time_log_robot
11
+
12
+ Until then...
13
+
14
+ rake install
15
+
16
+ ## Usage
17
+
18
+ The simplest usage is just to invoke the robot:
19
+
20
+ time_log_robot
21
+
22
+ By default, the robot will get all time entries since the previous Saturday. To specify a different time, run it with the optional `--since` flag (Note: the date given must be in YYYY-MM-DD format):
23
+
24
+ time_log_robot --since 2016-05-01
25
+
26
+ On start, the robot will ask you for these details:
27
+
28
+ TOGGL_TOKEN
29
+ TOGGL_WORKSPACE_ID
30
+ TOGGL_USER_AGENT
31
+ TOGGL_DEFAULT_LOG_TAG
32
+ JIRA_USERNAME
33
+ JIRA_PASSWORD
34
+
35
+ The robot has a memory like a steel trap, so after you run it the first time, it will remember your configuration settings and you'll never need to enter them again. However, if you enter the wrong info, or need to change it at some point, you can always overwrite the configuration:
36
+
37
+ time_log_robot --overwrite
38
+
39
+ Or, if you want to pop open the internals, the robot saves all configuration in `path/to/gem/config/settings.yml`, so open up that file and edit to your heart's content.
40
+
41
+ ### Configuration
42
+
43
+ Here are some notes about how to find the appropriate values for those environment variables:
44
+
45
+ * **TOGGL_TOKEN**: In your Toggl account, go to your profile page and look for the API token at the bottom.
46
+ * **TOGGL_WORKSPACE_ID**: This is a little trickier. Your workspaces usually only show a human-readable name to you in Toggl's UI, and here you need the workspace's machine ID. But you can do a curl request to find it like this (replacing **TOGGL_TOKEN** with your token from above):
47
+
48
+ curl -v -u TOGGL_TOKEN:api_token \ -X GET https://www.toggl.com/api/v8/workspaces
49
+
50
+ Look at the result and find the id given for the workspace you want to use.
51
+
52
+ * **TOGGL_USER_AGENT**: This is your Toggl username, usually your email.
53
+ * **TOGGL_DEFAULT_LOG_TAG**: This is the tag name you would like to use for tagging your Toggl time entries as they are logged to JIRA.
54
+ * **JIRA_USERNAME**: This is your JIRA username, which is not an email, but usually your email minus the "@domain.com"
55
+ * **JIRA_PASSWORD**: I know there's a lot of jargon, but some of these are pretty self-explanatory. :trollface:
56
+
57
+ ### Help
58
+
59
+ For more details use the help flag:
60
+
61
+ time_log_robot --help
62
+
63
+
64
+ ## Development
65
+ To see available rake tasks for development
66
+
67
+ rake -T
68
+
69
+ To run the app in IRB for debugging run
70
+
71
+ rake console
72
+
73
+ (Note: If you've built the gem and have committed the `.gem` file, none of your `rake` commands will work. You'll need to remove the built gem and commit the deletion.)
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create new Pull Request to Dev
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ desc 'Run in IRB for debugging'
4
+ task :console do
5
+ require 'irb'
6
+ require 'irb/completion'
7
+ require 'time_log_robot'
8
+ ARGV.clear
9
+ IRB.start
10
+ end
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'commander/import'
4
+ require 'time_log_robot'
5
+ require 'time_log_robot/version'
6
+ require 'time_log_robot/toggl/tagger'
7
+ require 'time_log_robot/toggl/report'
8
+ require 'time_log_robot/jira/payload_builder'
9
+ require 'time_log_robot/jira/work_logger'
10
+ require 'yaml'
11
+
12
+ program :name, 'time_log_robot'
13
+ program :version, TimeLogRobot::VERSION
14
+ program :description, 'Logs work from a time tracker tool to a project
15
+ management tool. Currently only supports Toggl and JIRA.'
16
+
17
+ program :help, 'Author', 'Mark J. Lehman <markopolo@gmail.com>'
18
+
19
+ global_option('-i', '--inputs_help', 'Learn how and where to find the inputs you need to get this working')
20
+
21
+ command :run do |c|
22
+ c.syntax = 'time_log_robot run [options]'
23
+
24
+ c.description = 'Logs your time with optional since (default is the previous Saturday).'
25
+
26
+ c.example 'usage', 'time_log_robot run'
27
+ c.example 'shorthand', 'time_log_robot'
28
+ c.example 'with optional parameter "since"', 'time_log_robot run --since "2015-10-21"'
29
+
30
+ c.option '--since STRING', String, 'The date from which to log time entries. Must be in YYYY-MM-DD format. Default is the previous Saturday.'
31
+
32
+ c.option '--overwrite', 'Your settings are automatically written to a file - `~/.time_log_robot_settings.yml` - to be used again the next time you invoke the robot. Use this flag if you need to overwrite those settings.'
33
+
34
+ c.action do |args, options|
35
+ if options.inputs_help
36
+ print_inputs_help
37
+ else
38
+ create_settings_file_if_nonexistent
39
+
40
+ fetch_envars_from_config unless options.overwrite
41
+
42
+ missing_envars = get_missing_envars
43
+
44
+ since = DateTime.parse(options.since).to_s unless options.since.nil?
45
+
46
+ TimeLogRobot.start(since)
47
+
48
+ write_missing_envars(missing_envars) if missing_envars.any?
49
+ end
50
+ end
51
+ end
52
+
53
+ def print_inputs_help
54
+ TimeLogRobot.envars_help.each_pair do |envar, help_text|
55
+ puts envar
56
+ puts help_text
57
+ end
58
+ end
59
+
60
+ def get_missing_envars
61
+ missing_envars = {}
62
+
63
+ TimeLogRobot.envars.each do |key|
64
+ string_key = key.to_s
65
+ unless ENV[string_key]
66
+ ENV[string_key] = ask "Enter your #{string_key}: " do |char|
67
+ char.echo = '*' if string_key =~ /password|token/i
68
+ end
69
+ if ENV[string_key].length == 0
70
+ puts 'Invalid input. This is a required field.'
71
+ exit
72
+ end
73
+ missing_envars[string_key] = ENV[string_key]
74
+ end
75
+ end
76
+
77
+ return missing_envars
78
+ end
79
+
80
+ def fetch_envars_from_config
81
+ return unless envars = YAML.load_file(settings_file_path)
82
+ envars.each_pair do |key, value|
83
+ ENV[key.upcase] = value
84
+ end
85
+ end
86
+
87
+ def write_missing_envars(missing_envars={})
88
+ puts "\nTo avoid entering setup information each time, the following configuration has been stored in `#{settings_file_path}`:"
89
+ missing_envars.each_pair do |key, value|
90
+ if key =~ /password|token/i
91
+ puts "\t#{key}=[FILTERED]"
92
+ else
93
+ puts "\t#{key}=#{value}"
94
+ end
95
+
96
+ data = YAML.load_file(settings_file_path) || {}
97
+ data[key.downcase] = value
98
+ File.open(settings_file_path, 'w') { |f| YAML.dump(data, f) }
99
+ end
100
+ end
101
+
102
+ def create_settings_file_if_nonexistent
103
+ File.new(settings_file_path, "w+") unless File.exists?(settings_file_path)
104
+ end
105
+
106
+ def settings_file_path
107
+ File.join(TimeLogRobot.root, '.settings.yml')
108
+ end
109
+
110
+ # set default action for gem
111
+ default_command :run
@@ -0,0 +1,21 @@
1
+ module TimeLogRobot
2
+ module JIRA
3
+ class PayloadBuilder
4
+ attr_accessor :start, :duration_in_seconds, :comment
5
+
6
+ def initialize(start:, duration_in_seconds:, comment:)
7
+ @start = start
8
+ @duration_in_seconds = duration_in_seconds
9
+ @comment = comment
10
+ end
11
+
12
+ def build
13
+ {
14
+ "comment" => comment,
15
+ "started" => start.to_s,
16
+ "timeSpentSeconds" => duration_in_seconds
17
+ }.to_json
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,100 @@
1
+ module TimeLogRobot
2
+ module JIRA
3
+ class WorkLogger
4
+ include HTTParty
5
+
6
+ attr_accessor :username, :password, :time_entries, :log_tags
7
+
8
+ base_uri 'https://hranswerlink.atlassian.net/rest/api/2'
9
+
10
+ def initialize(time_entries:, log_tags: [ENV['TOGGL_DEFAULT_LOG_TAG']])
11
+ @username = ENV['JIRA_USERNAME']
12
+ @password = ENV['JIRA_PASSWORD']
13
+ @time_entries = time_entries
14
+ @log_tags = log_tags
15
+ end
16
+
17
+ def log_all
18
+ time_entries.each do |entry|
19
+ log(entry) unless is_logged?(entry)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def is_logged?(entry)
26
+ (log_tags - entry['tags']).size < log_tags.size
27
+ end
28
+
29
+ def log(entry)
30
+ issue_key = parse_issue_key(entry)
31
+ payload = build_payload(entry)
32
+ puts "Attempting to log #{human_readable_duration(parse_duration(entry))}"
33
+ puts "starting on #{parse_start(entry)}"
34
+ puts "to #{entry['description']}"
35
+ puts "with comment #{parse_comment(entry)}" unless parse_comment(entry).nil?
36
+ response = self.class.post("/issue/#{issue_key}/worklog", basic_auth: auth, headers: headers, body: payload)
37
+ if response.success?
38
+ puts "Success"
39
+ puts '*' * 20
40
+ set_entry_as_logged(entry)
41
+ else
42
+ puts "Failed! Response from JIRA:"
43
+ puts response
44
+ puts "(Hint: Did you forget to put the JIRA issue key in your Toggl entry?"
45
+ puts '*' * 20
46
+ end
47
+ end
48
+
49
+ def set_entry_as_logged(entry)
50
+ Toggl::Tagger.new(tags: log_tags).update(entry_id: entry['id'])
51
+ end
52
+
53
+ def auth
54
+ {
55
+ username: username,
56
+ password: password
57
+ }
58
+ end
59
+
60
+ # @TODO Extract since it's used in several different models
61
+ def headers
62
+ { 'Content-Type' => 'application/json' }
63
+ end
64
+
65
+ def build_payload(entry)
66
+ JIRA::PayloadBuilder.new(
67
+ start: parse_start(entry),
68
+ duration_in_seconds: parse_duration(entry),
69
+ comment: parse_comment(entry)
70
+ ).build
71
+ end
72
+
73
+ def parse_start(entry)
74
+ DateTime.strptime(entry['start'], "%FT%T%:z").strftime("%FT%T.%L%z")
75
+ end
76
+
77
+ def parse_duration(entry)
78
+ entry['dur']/1000 # Toggl sends times in milliseconds
79
+ end
80
+
81
+ def human_readable_duration(seconds)
82
+ total_minutes = seconds/60
83
+ hours = total_minutes/60
84
+ remaining_minutes = total_minutes - hours * 60
85
+ "#{hours}h #{remaining_minutes}m"
86
+ end
87
+
88
+ # @TODO figure out how to capture both of this in one .match call with one set of regex
89
+ def parse_issue_key(entry)
90
+ matches = entry['description'].match(/(\[(?<issue_key>[^\]]*)\])/)
91
+ matches['issue_key'] if matches.present?
92
+ end
93
+
94
+ def parse_comment(entry)
95
+ matches = entry['description'].match(/(\{(?<comment>[^\}]*)\})/)
96
+ matches['comment'] if matches.present?
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,48 @@
1
+ require 'active_support/core_ext/date/calculations'
2
+
3
+ module TimeLogRobot
4
+ module Toggl
5
+ class Report
6
+ include HTTParty
7
+
8
+ attr_accessor :token, :workspace_id, :user_agent
9
+
10
+ base_uri 'https://toggl.com/reports/api/v2'
11
+
12
+ def initialize
13
+ @token = ENV['TOGGL_TOKEN']
14
+ @workspace_id = ENV['TOGGL_WORKSPACE_ID']
15
+ @user_agent = ENV['TOGGL_USER_AGENT']
16
+ end
17
+
18
+ def fetch(since: nil)
19
+ since ||= Date.today.beginning_of_week(:saturday).to_time
20
+ response = self.class.get('/details', basic_auth: auth, query: query(since))
21
+ if response.success?
22
+ response['data']
23
+ else
24
+ raise FetchError, response['error']
25
+ end
26
+ end
27
+ class FetchError < Exception; end
28
+
29
+ private
30
+
31
+ def auth
32
+ {
33
+ username: token,
34
+ password: "api_token"
35
+ }
36
+ end
37
+
38
+ def query(since)
39
+ {
40
+ workspace_id: workspace_id,
41
+ user_agent: user_agent,
42
+ since: since
43
+ }
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,42 @@
1
+ module TimeLogRobot
2
+ module Toggl
3
+ class Tagger
4
+ include HTTParty
5
+
6
+ attr_accessor :token, :tags
7
+
8
+ base_uri 'https://toggl.com/api/v8/time_entries'
9
+
10
+ def initialize(tags:[ENV['TOGGL_DEFAULT_LOG_TAG']])
11
+ @token = ENV['TOGGL_TOKEN']
12
+ @tags = tags
13
+ end
14
+
15
+ def update(entry_id:)
16
+ self.class.put("/#{entry_id}", basic_auth: auth, headers: headers, body: body)
17
+ end
18
+
19
+ private
20
+
21
+ def auth
22
+ {
23
+ username: token,
24
+ password: "api_token"
25
+ }
26
+ end
27
+
28
+ def headers
29
+ { 'Content-Type' => 'application/json' }
30
+ end
31
+
32
+ def body
33
+ {
34
+ time_entry:
35
+ {
36
+ tags: tags
37
+ }
38
+ }.to_json
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ module TimeLogRobot
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,55 @@
1
+ require 'json'
2
+ require 'httparty'
3
+
4
+ module TimeLogRobot
5
+ def self.root
6
+ File.dirname __dir__
7
+ end
8
+
9
+ def self.start(since)
10
+ time_entries = fetch_time_entries(since)
11
+ JIRA::WorkLogger.new(time_entries: time_entries).log_all
12
+ end
13
+
14
+ def self.fetch_time_entries(since)
15
+ if since.nil?
16
+ Toggl::Report.new.fetch
17
+ else
18
+ Toggl::Report.new.fetch(since: since)
19
+ end
20
+ end
21
+
22
+ def self.envars
23
+ envars_help.keys
24
+ end
25
+
26
+ def self.envars_help
27
+ {
28
+ TOGGL_TOKEN:
29
+ "In your Toggl account, go to your profile page and look for the API token at the bottom.\n\n",
30
+
31
+ TOGGL_WORKSPACE_ID:
32
+ "This is a little trickier. Your workspaces usually only show a human-readable name to you in Toggl's UI, and here you need the workspace machine ID. But you can do a curl request to find it like this (replacing TOGGL_TOKEN with your token from above):
33
+
34
+ \tcurl -v -u TOGGL_TOKEN:api_token \ -X GET https://www.toggl.com/api/v8/workspaces
35
+
36
+ Look at the result and find the id given for the workspace you want to use.\n\n",
37
+
38
+ TOGGL_USER_AGENT:
39
+ "This is your Toggl username, usually your email.\n\n",
40
+
41
+ TOGGL_DEFAULT_LOG_TAG:
42
+ "This is the tag name you would like to use for tagging your Toggl time entries as they are logged to JIRA.\n\n",
43
+
44
+ JIRA_USERNAME:
45
+ "This is your JIRA username, which is not an email, but usually your email minus the '@domain.com'\n\n",
46
+
47
+ JIRA_PASSWORD:
48
+ "I know there's a lot of jargon, but some of these are pretty self-explanatory
49
+ ┌─┐
50
+ ┴─┴
51
+ ಠ_ರೃ
52
+ \n"
53
+ }
54
+ end
55
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ # require 'time_log_robot/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'time_log_robot'
8
+ spec.version = '0.1.0'
9
+ # spec.version = TimeLogRobot::VERSION
10
+ spec.authors = ['Mark J. Lehman']
11
+ spec.email = ['markopolo@gmail.com']
12
+ spec.description = %q{Automate time logging from tools like Toggl to project management software such as JIRA}
13
+ spec.summary = %q{Automate work time logging}
14
+ spec.homepage = 'https://github.com/supremebeing7/time_log_robot'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.required_ruby_version = '>= 2.0'
23
+ spec.add_development_dependency 'bundler', '~> 1.3'
24
+ spec.add_development_dependency 'rake', '~> 10.5'
25
+
26
+ spec.add_runtime_dependency 'activesupport', '~> 4.2', '>= 4.2.6'
27
+ spec.add_runtime_dependency 'commander', '~> 4.1', '>= 4.1.6'
28
+ spec.add_runtime_dependency 'httparty', '~> 0.13', '>= 0.13.0'
29
+ spec.add_runtime_dependency 'json', '~> 1.8', '>= 1.8.1'
30
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: time_log_robot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mark J. Lehman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.2'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 4.2.6
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '4.2'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 4.2.6
61
+ - !ruby/object:Gem::Dependency
62
+ name: commander
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '4.1'
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 4.1.6
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '4.1'
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 4.1.6
81
+ - !ruby/object:Gem::Dependency
82
+ name: httparty
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '0.13'
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 0.13.0
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '0.13'
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 0.13.0
101
+ - !ruby/object:Gem::Dependency
102
+ name: json
103
+ requirement: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - "~>"
106
+ - !ruby/object:Gem::Version
107
+ version: '1.8'
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 1.8.1
111
+ type: :runtime
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.8'
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: 1.8.1
121
+ description: Automate time logging from tools like Toggl to project management software
122
+ such as JIRA
123
+ email:
124
+ - markopolo@gmail.com
125
+ executables:
126
+ - time_log_robot
127
+ extensions: []
128
+ extra_rdoc_files: []
129
+ files:
130
+ - ".gitignore"
131
+ - ".settings.yml"
132
+ - Gemfile
133
+ - Gemfile.lock
134
+ - LICENSE.txt
135
+ - README.md
136
+ - Rakefile
137
+ - bin/time_log_robot
138
+ - lib/time_log_robot.rb
139
+ - lib/time_log_robot/jira/payload_builder.rb
140
+ - lib/time_log_robot/jira/work_logger.rb
141
+ - lib/time_log_robot/toggl/report.rb
142
+ - lib/time_log_robot/toggl/tagger.rb
143
+ - lib/time_log_robot/version.rb
144
+ - time_log_robot.gemspec
145
+ homepage: https://github.com/supremebeing7/time_log_robot
146
+ licenses:
147
+ - MIT
148
+ metadata: {}
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '2.0'
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ requirements: []
164
+ rubyforge_project:
165
+ rubygems_version: 2.4.8
166
+ signing_key:
167
+ specification_version: 4
168
+ summary: Automate work time logging
169
+ test_files: []
170
+ has_rdoc: