tempest-time 0.5.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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +133 -0
- data/LICENSE +21 -0
- data/README.md +8 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/tempest +18 -0
- data/lib/tempest_time.rb +4 -0
- data/lib/tempest_time/api/authorization.rb +17 -0
- data/lib/tempest_time/api/jira_api/authorization.rb +27 -0
- data/lib/tempest_time/api/jira_api/models/issue.rb +28 -0
- data/lib/tempest_time/api/jira_api/request.rb +40 -0
- data/lib/tempest_time/api/jira_api/requests/get_issue.rb +29 -0
- data/lib/tempest_time/api/jira_api/requests/get_user_issues.rb +36 -0
- data/lib/tempest_time/api/jira_api/response.rb +5 -0
- data/lib/tempest_time/api/jira_api/responses/get_issue.rb +16 -0
- data/lib/tempest_time/api/jira_api/responses/get_user_issues.rb +14 -0
- data/lib/tempest_time/api/request.rb +87 -0
- data/lib/tempest_time/api/response.rb +34 -0
- data/lib/tempest_time/api/tempo_api/authorization.rb +23 -0
- data/lib/tempest_time/api/tempo_api/models/worklog.rb +36 -0
- data/lib/tempest_time/api/tempo_api/request.rb +35 -0
- data/lib/tempest_time/api/tempo_api/requests/create_worklog.rb +51 -0
- data/lib/tempest_time/api/tempo_api/requests/delete_worklog.rb +29 -0
- data/lib/tempest_time/api/tempo_api/requests/get_worklog.rb +29 -0
- data/lib/tempest_time/api/tempo_api/requests/list_worklogs.rb +41 -0
- data/lib/tempest_time/api/tempo_api/requests/report.rb +0 -0
- data/lib/tempest_time/api/tempo_api/requests/submit_timesheet.rb +49 -0
- data/lib/tempest_time/api/tempo_api/response.rb +5 -0
- data/lib/tempest_time/api/tempo_api/responses/create_worklog.rb +28 -0
- data/lib/tempest_time/api/tempo_api/responses/delete_worklog.rb +8 -0
- data/lib/tempest_time/api/tempo_api/responses/get_worklog.rb +22 -0
- data/lib/tempest_time/api/tempo_api/responses/list_worklogs.rb +40 -0
- data/lib/tempest_time/api/tempo_api/responses/submit_timesheet.rb +13 -0
- data/lib/tempest_time/cli.rb +92 -0
- data/lib/tempest_time/command.rb +60 -0
- data/lib/tempest_time/commands/config.rb +30 -0
- data/lib/tempest_time/commands/config/edit.rb +38 -0
- data/lib/tempest_time/commands/config/setup.rb +55 -0
- data/lib/tempest_time/commands/delete.rb +31 -0
- data/lib/tempest_time/commands/issues.rb +37 -0
- data/lib/tempest_time/commands/list.rb +32 -0
- data/lib/tempest_time/commands/report.rb +83 -0
- data/lib/tempest_time/commands/submit.rb +26 -0
- data/lib/tempest_time/commands/teams.rb +30 -0
- data/lib/tempest_time/commands/teams/add.rb +29 -0
- data/lib/tempest_time/commands/teams/delete.rb +32 -0
- data/lib/tempest_time/commands/teams/edit.rb +49 -0
- data/lib/tempest_time/commands/track.rb +70 -0
- data/lib/tempest_time/helpers/formatting_helper.rb +16 -0
- data/lib/tempest_time/helpers/time_helper.rb +63 -0
- data/lib/tempest_time/models/report.rb +58 -0
- data/lib/tempest_time/services/generate_report.rb +54 -0
- data/lib/tempest_time/setting.rb +47 -0
- data/lib/tempest_time/settings/authorization.rb +19 -0
- data/lib/tempest_time/settings/teams.rb +19 -0
- data/lib/tempest_time/templates/config/.gitkeep +1 -0
- data/lib/tempest_time/templates/config/auth/.gitkeep +1 -0
- data/lib/tempest_time/templates/config/setup/.gitkeep +1 -0
- data/lib/tempest_time/templates/config/teams/.gitkeep +1 -0
- data/lib/tempest_time/templates/delete/.gitkeep +1 -0
- data/lib/tempest_time/templates/issue/.gitkeep +1 -0
- data/lib/tempest_time/templates/issues/.gitkeep +1 -0
- data/lib/tempest_time/templates/list/.gitkeep +1 -0
- data/lib/tempest_time/templates/report/.gitkeep +1 -0
- data/lib/tempest_time/templates/setup/.gitkeep +1 -0
- data/lib/tempest_time/templates/submit/.gitkeep +1 -0
- data/lib/tempest_time/templates/teams/.gitkeep +1 -0
- data/lib/tempest_time/templates/track/.gitkeep +1 -0
- data/lib/tempest_time/templates/view/.gitkeep +1 -0
- data/lib/tempest_time/version.rb +3 -0
- data/tempest-time.gemspec +62 -0
- metadata +517 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative '../response'
|
2
|
+
require_relative '../models/issue'
|
3
|
+
|
4
|
+
module JiraAPI
|
5
|
+
module Responses
|
6
|
+
class GetIssue < JiraAPI::Response
|
7
|
+
def message
|
8
|
+
puts issue.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def issue
|
12
|
+
@issue ||= JiraAPI::Models::Issue.new(raw_response)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative '../response'
|
2
|
+
require_relative '../models/issue'
|
3
|
+
|
4
|
+
module JiraAPI
|
5
|
+
module Responses
|
6
|
+
class GetUserIssues < JiraAPI::Response
|
7
|
+
def issues
|
8
|
+
@issues ||= raw_response['issues'].map do |issue|
|
9
|
+
JiraAPI::Models::Issue.new(issue)
|
10
|
+
end.reverse
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require_relative './authorization'
|
5
|
+
require_relative './response'
|
6
|
+
|
7
|
+
module TempestTime
|
8
|
+
module API
|
9
|
+
class Request
|
10
|
+
include HTTParty
|
11
|
+
|
12
|
+
DATE_FORMAT = "%Y-%m-%d".freeze
|
13
|
+
|
14
|
+
def initialize(*args)
|
15
|
+
self.class.base_uri credentials.fetch(:url)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @abstract Subclass is expected to implement #send_request
|
19
|
+
# @!method send_request
|
20
|
+
# HTTParty call to API
|
21
|
+
|
22
|
+
def response
|
23
|
+
@response ||= response_klass.new(raw_response, self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def response_message
|
27
|
+
response.message
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :raw_response
|
33
|
+
|
34
|
+
# @abstract Subclass is expected to implement #request_method
|
35
|
+
# @!method request_method
|
36
|
+
# RESTful operation: one of 'get', 'post', 'put', 'delete'
|
37
|
+
|
38
|
+
# @abstract Subclass is expected to implement #request_path
|
39
|
+
# @!method request_path
|
40
|
+
# Path for the operation. i.e. /users
|
41
|
+
|
42
|
+
# @abstract Subclass is expected to implement #response_klass
|
43
|
+
# @!method request_klass
|
44
|
+
# The class used to parse the response object.
|
45
|
+
|
46
|
+
# @abstract Subclass is expected to implement #authorization_klass
|
47
|
+
# @!method authorization_klass
|
48
|
+
# Define as Authorization.new in each subclass so class is dynamic.
|
49
|
+
|
50
|
+
def request_body
|
51
|
+
{}
|
52
|
+
end
|
53
|
+
|
54
|
+
def query_params
|
55
|
+
{}
|
56
|
+
end
|
57
|
+
|
58
|
+
def credentials
|
59
|
+
authorization_klass.new.credentials
|
60
|
+
end
|
61
|
+
|
62
|
+
def user
|
63
|
+
credentials.fetch(:user, nil)
|
64
|
+
end
|
65
|
+
|
66
|
+
def token
|
67
|
+
credentials.fetch(:token, nil)
|
68
|
+
end
|
69
|
+
|
70
|
+
def headers
|
71
|
+
content_type_header
|
72
|
+
end
|
73
|
+
|
74
|
+
def content_type_header
|
75
|
+
{ 'Content-Type' => 'application/json' }
|
76
|
+
end
|
77
|
+
|
78
|
+
def authorization_header
|
79
|
+
{ 'Authorization' => "Bearer #{token}" }
|
80
|
+
end
|
81
|
+
|
82
|
+
def basic_auth
|
83
|
+
{ username: user, password: token }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module TempestTime
|
2
|
+
module API
|
3
|
+
class Response
|
4
|
+
def initialize(raw_response, request)
|
5
|
+
@raw_response = raw_response
|
6
|
+
@request = request
|
7
|
+
end
|
8
|
+
|
9
|
+
def success?
|
10
|
+
raw_response.success?
|
11
|
+
end
|
12
|
+
|
13
|
+
def failure?
|
14
|
+
!success?
|
15
|
+
end
|
16
|
+
|
17
|
+
def message
|
18
|
+
raw_response.success? ? success_message : failure_message
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :raw_response, :request
|
24
|
+
|
25
|
+
def success_message
|
26
|
+
'Success!'
|
27
|
+
end
|
28
|
+
|
29
|
+
def failure_message
|
30
|
+
'Failed!'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative '../authorization'
|
2
|
+
|
3
|
+
module TempoAPI
|
4
|
+
class Authorization < TempestTime::API::Authorization
|
5
|
+
private
|
6
|
+
|
7
|
+
def url
|
8
|
+
'https://api.tempo.io/2'
|
9
|
+
end
|
10
|
+
|
11
|
+
def user
|
12
|
+
settings.read('username')
|
13
|
+
end
|
14
|
+
|
15
|
+
def email
|
16
|
+
settings.read('email')
|
17
|
+
end
|
18
|
+
|
19
|
+
def token
|
20
|
+
settings.read('tempo_token')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module TempoAPI
|
2
|
+
module Models
|
3
|
+
class Worklog
|
4
|
+
attr_reader :id, :issue, :seconds, :description
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
@id = options.fetch(:id)
|
8
|
+
@issue = options.fetch(:issue)
|
9
|
+
@seconds = options.fetch(:seconds)
|
10
|
+
@description = options.fetch(:description)
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
"#{id}: #{issue}: #{time_output}: #{description}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def project
|
18
|
+
issue.split('-').first
|
19
|
+
end
|
20
|
+
|
21
|
+
def minutes
|
22
|
+
seconds / 60.to_f
|
23
|
+
end
|
24
|
+
|
25
|
+
def hours
|
26
|
+
minutes / 60.to_f
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def time_output
|
32
|
+
minutes < 60 ? "#{minutes.to_i}m" : "#{hours.to_i}h"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require_relative '../request'
|
5
|
+
require_relative './response'
|
6
|
+
require_relative './authorization'
|
7
|
+
require 'byebug'
|
8
|
+
module TempoAPI
|
9
|
+
class Request < TempestTime::API::Request
|
10
|
+
def send_request
|
11
|
+
@raw_response = self.class.send(
|
12
|
+
request_method,
|
13
|
+
request_path,
|
14
|
+
headers: headers,
|
15
|
+
body: request_body.empty? ? request_body : request_body.to_json,
|
16
|
+
query: query_params
|
17
|
+
)
|
18
|
+
response
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def authorization_klass
|
24
|
+
Authorization
|
25
|
+
end
|
26
|
+
|
27
|
+
def headers
|
28
|
+
super.merge(authorization_header)
|
29
|
+
end
|
30
|
+
|
31
|
+
def response_klass
|
32
|
+
TempoAPI::Response
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative '../request'
|
2
|
+
require_relative '../responses/create_worklog'
|
3
|
+
|
4
|
+
module TempoAPI
|
5
|
+
module Requests
|
6
|
+
class CreateWorklog < TempoAPI::Request
|
7
|
+
def initialize(seconds, options)
|
8
|
+
super
|
9
|
+
@seconds = seconds
|
10
|
+
@remaining = options['remaining']
|
11
|
+
@ticket = options['ticket']
|
12
|
+
@message = options['message']
|
13
|
+
@date = options['date'] ? Date.parse(options['date']) : Date.today
|
14
|
+
@billable = options['billable']
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :ticket, :remaining, :seconds, :message, :date, :billable
|
20
|
+
|
21
|
+
def request_method
|
22
|
+
'post'
|
23
|
+
end
|
24
|
+
|
25
|
+
def request_path
|
26
|
+
'/worklogs'
|
27
|
+
end
|
28
|
+
|
29
|
+
def response_klass
|
30
|
+
TempoAPI::Responses::CreateWorklog
|
31
|
+
end
|
32
|
+
|
33
|
+
def request_body
|
34
|
+
{
|
35
|
+
"issueKey": ticket,
|
36
|
+
"timeSpentSeconds": seconds,
|
37
|
+
"billableSeconds": billable_time,
|
38
|
+
"remainingEstimateSeconds": remaining,
|
39
|
+
"startDate": date.strftime('%Y-%m-%d'),
|
40
|
+
"startTime": '12:00:00',
|
41
|
+
"authorUsername": user,
|
42
|
+
"description": message
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def billable_time
|
47
|
+
billable ? seconds : 0
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative '../request'
|
2
|
+
require_relative '../responses/delete_worklog'
|
3
|
+
|
4
|
+
module TempoAPI
|
5
|
+
module Requests
|
6
|
+
class DeleteWorklog < TempoAPI::Request
|
7
|
+
attr_reader :worklog_id
|
8
|
+
|
9
|
+
def initialize(worklog_id)
|
10
|
+
super
|
11
|
+
@worklog_id = worklog_id
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def request_method
|
17
|
+
'delete'
|
18
|
+
end
|
19
|
+
|
20
|
+
def request_path
|
21
|
+
"/worklogs/#{worklog_id}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def response_klass
|
25
|
+
TempoAPI::Responses::DeleteWorklog
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative '../request'
|
2
|
+
require_relative '../responses/get_worklog'
|
3
|
+
|
4
|
+
module TempoAPI
|
5
|
+
module Requests
|
6
|
+
class GetWorklog < TempoAPI::Request
|
7
|
+
attr_reader :worklog_id
|
8
|
+
|
9
|
+
def initialize(worklog_id)
|
10
|
+
super
|
11
|
+
@worklog_id = worklog_id
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def request_method
|
17
|
+
'get'
|
18
|
+
end
|
19
|
+
|
20
|
+
def request_path
|
21
|
+
"/worklogs/#{worklog_id}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def response_klass
|
25
|
+
TempoAPI::Responses::GetWorklog
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../request'
|
2
|
+
require_relative '../responses/list_worklogs'
|
3
|
+
|
4
|
+
module TempoAPI
|
5
|
+
module Requests
|
6
|
+
class ListWorklogs < TempoAPI::Request
|
7
|
+
attr_reader :start_date, :end_date
|
8
|
+
|
9
|
+
def initialize(start_date, end_date, requested_user)
|
10
|
+
super
|
11
|
+
@start_date = start_date
|
12
|
+
@end_date = end_date || start_date
|
13
|
+
@requested_user = requested_user || user
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :requested_user
|
19
|
+
|
20
|
+
def response_klass
|
21
|
+
TempoAPI::Responses::ListWorklogs
|
22
|
+
end
|
23
|
+
|
24
|
+
def request_method
|
25
|
+
'get'
|
26
|
+
end
|
27
|
+
|
28
|
+
def request_path
|
29
|
+
"/worklogs/user/#{requested_user}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def query_params
|
33
|
+
{
|
34
|
+
"from": start_date.strftime(DATE_FORMAT),
|
35
|
+
"to": end_date.strftime(DATE_FORMAT),
|
36
|
+
"limit": 1000
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
File without changes
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative '../request'
|
2
|
+
require_relative '../../../helpers/time_helper'
|
3
|
+
require_relative '../responses/submit_timesheet'
|
4
|
+
|
5
|
+
module TempoAPI
|
6
|
+
module Requests
|
7
|
+
class SubmitTimesheet < TempoAPI::Request
|
8
|
+
include TempestTime::Helpers::TimeHelper
|
9
|
+
|
10
|
+
attr_reader :reviewer
|
11
|
+
|
12
|
+
def initialize(reviewer)
|
13
|
+
super
|
14
|
+
@reviewer = reviewer
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def request_method
|
20
|
+
'post'
|
21
|
+
end
|
22
|
+
|
23
|
+
def request_path
|
24
|
+
"/timesheet-approvals/user/#{user}/submit"
|
25
|
+
end
|
26
|
+
|
27
|
+
def response_klass
|
28
|
+
TempoAPI::Responses::SubmitTimesheet
|
29
|
+
end
|
30
|
+
|
31
|
+
def query_params
|
32
|
+
{
|
33
|
+
from: week_dates.first.strftime(DATE_FORMAT),
|
34
|
+
to: week_dates.last.strftime(DATE_FORMAT)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def request_body
|
39
|
+
{
|
40
|
+
reviewerUsername: reviewer
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def week_dates
|
45
|
+
parsed_date_input('week')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|