sfctl 0.0.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87640e37bddf52afff13b5ac880334429e8357308c4ca069df10cb06d5627463
4
- data.tar.gz: 7431952f8f7d62c6ce5676276f6dc50218389c6d3433e8886e08351f0670dee6
3
+ metadata.gz: 8b7cfd503a3b18b2441f5cff3c07e2fbfa595abb035b93d4ecba4acb9765ff29
4
+ data.tar.gz: 7c73df09e0f4b7b1b9093744e09ea662165612e468efd9e0c850f81725d61af4
5
5
  SHA512:
6
- metadata.gz: 5d4518ccdd8dfb1595954e19169402db62511a6be21b3011c082f1bf67661fa3156c44aedd80afdc79ab2fe5a5d991068127b51af02080eef644478f64c93cd2
7
- data.tar.gz: 4ec95937e28e42fb82fc289851eadb46d475c2aa59fc9d6819f744e9df6a0ecf266596882cd70828d7aec4e67385008c7117e8552aee8f78811c98a37e5c018c
6
+ metadata.gz: bc9efd5ac1521f8d519dfde47a46366995b9ecb5a8ed40db41ba0b8e419689f785f6a9c1f148022db78e6794840ceade2de4c9ee192b3a6c4d0e24acf91bee23
7
+ data.tar.gz: cd16f04c78c00f8b54e1e45e201a32f93cc1733040934a2a2aa1dfdc9ca36bcddc630c53995f526518e9f33bbc8fbc3df0c99de83515a24d5ef8fabce4faa477
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  .DS_Store
13
13
  sfctl-*.gem
14
14
  /.sflink
15
+ .byebug_history
@@ -1,7 +1,33 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sfctl (0.0.1)
4
+ sfctl (1.0.1)
5
+ faraday (~> 1.0)
6
+ pastel (~> 0.7)
7
+ rake (~> 12.0)
8
+ thor (~> 1.0)
9
+ tty-box (~> 0.5.0)
10
+ tty-color (~> 0.5.1)
11
+ tty-command (~> 0.9.0)
12
+ tty-config (~> 0.4.0)
13
+ tty-cursor (~> 0.7.1)
14
+ tty-editor (~> 0.5.1)
15
+ tty-file (~> 0.8.0)
16
+ tty-font (~> 0.5.0)
17
+ tty-link (~> 0.1.1)
18
+ tty-logger (~> 0.3.0)
19
+ tty-markdown (~> 0.6.0)
20
+ tty-pager (~> 0.12.1)
21
+ tty-pie (~> 0.3.0)
22
+ tty-platform (~> 0.3.0)
23
+ tty-progressbar (~> 0.17.0)
24
+ tty-prompt (~> 0.21.0)
25
+ tty-reader (~> 0.7.0)
26
+ tty-screen (~> 0.7.1)
27
+ tty-spinner (~> 0.9.3)
28
+ tty-table (~> 0.11.0)
29
+ tty-tree (~> 0.4.0)
30
+ tty-which (~> 0.4.2)
5
31
 
6
32
  GEM
7
33
  remote: https://rubygems.org/
@@ -28,22 +54,22 @@ GEM
28
54
  multipart-post (2.1.1)
29
55
  necromancer (0.5.1)
30
56
  parallel (1.19.1)
31
- parser (2.7.0.5)
57
+ parser (2.7.1.1)
32
58
  ast (~> 2.4.0)
33
59
  pastel (0.7.3)
34
60
  equatable (~> 0.6)
35
61
  tty-color (~> 0.5)
36
- pry (0.13.0)
62
+ pry (0.13.1)
37
63
  coderay (~> 1.1)
38
64
  method_source (~> 1.0)
39
65
  pry-byebug (3.9.0)
40
66
  byebug (~> 11.0)
41
67
  pry (~> 0.13.0)
42
- public_suffix (4.0.3)
68
+ public_suffix (4.0.4)
43
69
  rainbow (3.0.0)
44
70
  rake (12.3.3)
45
71
  rexml (3.2.4)
46
- rouge (3.17.0)
72
+ rouge (3.18.0)
47
73
  rspec (3.9.0)
48
74
  rspec-core (~> 3.9.0)
49
75
  rspec-expectations (~> 3.9.0)
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) [year] [fullname]
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 all
13
+ 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 THE
21
+ SOFTWARE.
22
+
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # sfctl [![Build status](https://badge.buildkite.com/22ecc67f358163f4714383ff0fde8e847d1e3ae488fc10312f.svg)](https://buildkite.com/starfish/sf-control)
2
+ [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Falphatier-works%2Fsfctl.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Falphatier-works%2Fsfctl?ref=badge_shield)
2
3
 
3
4
  ```
4
5
  sfctl is a command line interface for the Starfish API.
@@ -270,3 +271,7 @@ Uploading to starfish.team: [IN PROGRESS|DONE]
270
271
 
271
272
  [NEXT CONNECTION]
272
273
  ```
274
+
275
+
276
+ ## License
277
+ [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Falphatier-works%2Fsfctl.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Falphatier-works%2Fsfctl?ref=badge_large)
@@ -21,7 +21,7 @@ module Sfctl
21
21
  end
22
22
 
23
23
  class_option :"no-color", type: :boolean, default: false, desc: 'Disable colorization in output'
24
- class_option :"starfish-host", type: :string, default: 'https://starfish.team',
24
+ class_option :"starfish-host", type: :string, default: 'https://app.starfish.team',
25
25
  desc: 'The starfish API endpoint',
26
26
  banner: 'HOST'
27
27
 
@@ -13,8 +13,10 @@ module Sfctl
13
13
  LINK_CONFIG_PATH = "#{Dir.pwd}/#{LINK_CONFIG_FILENAME}"
14
14
 
15
15
  TOGGL_PROVIDER = 'toggl'
16
+ HARVEST_PROVIDER = 'harvest'
16
17
  PROVIDERS_LIST = [
17
- TOGGL_PROVIDER
18
+ TOGGL_PROVIDER,
19
+ HARVEST_PROVIDER
18
20
  ].freeze
19
21
 
20
22
  def_delegators :command, :run
@@ -1,7 +1,7 @@
1
1
  require 'pastel'
2
2
  require 'tty-table'
3
3
  require_relative '../../command'
4
- require_relative '../../starfish'
4
+ require_relative '../../starfish/client'
5
5
 
6
6
  module Sfctl
7
7
  module Commands
@@ -15,7 +15,7 @@ module Sfctl
15
15
  def execute(output: $stdout)
16
16
  return unless config_present?(output)
17
17
 
18
- success, data = Starfish.account_assignments(@options['starfish-host'], @options['all'], access_token)
18
+ success, data = Starfish::Client.account_assignments(@options['starfish-host'], @options['all'], access_token)
19
19
 
20
20
  unless success
21
21
  output.puts @pastel.red('Something went wrong. Unable to fetch assignments')
@@ -1,7 +1,7 @@
1
1
  require 'pastel'
2
2
  require 'tty-table'
3
3
  require_relative '../../command'
4
- require_relative '../../starfish'
4
+ require_relative '../../starfish/client'
5
5
 
6
6
  module Sfctl
7
7
  module Commands
@@ -15,7 +15,7 @@ module Sfctl
15
15
  def execute(output: $stdout)
16
16
  return unless config_present?(output)
17
17
 
18
- success, info = Starfish.account_info(@options['starfish-host'], access_token)
18
+ success, info = Starfish::Client.account_info(@options['starfish-host'], access_token)
19
19
 
20
20
  unless success
21
21
  output.puts @pastel.red('Something went wrong. Unable to fetch account info')
@@ -1,5 +1,5 @@
1
1
  require_relative '../../command'
2
- require_relative '../../starfish'
2
+ require_relative '../../starfish/client'
3
3
  require 'pastel'
4
4
  require 'tty-prompt'
5
5
  require 'tty-spinner'
@@ -23,7 +23,7 @@ module Sfctl
23
23
  private
24
24
 
25
25
  def token_valid?(access_token)
26
- Starfish.check_authorization(@options['starfish-host'], access_token)
26
+ Starfish::Client.check_authorization(@options['starfish-host'], access_token)
27
27
  end
28
28
 
29
29
  def token_accepted_message
@@ -12,6 +12,8 @@ module Sfctl
12
12
  desc: 'Check the data first respectively prevent data from being overwritten'
13
13
  method_option :touchy, aliases: '-touchy', type: :boolean, default: false,
14
14
  desc: 'The synchronizsation will be skipped if there is preexisting data.'
15
+ method_option :all, aliases: '-all', type: :boolean, default: false,
16
+ desc: 'Skip selecting assignments and sync all of them.'
15
17
  long_desc <<~HEREDOC
16
18
  It will gets for each assignment the next reporting segment from starfish.team
17
19
  and loads the corresponding time reports from the provider.
@@ -3,8 +3,9 @@ require 'pastel'
3
3
  require 'tty-spinner'
4
4
  require 'tty-prompt'
5
5
  require_relative '../../../command'
6
- require_relative '../../../starfish'
7
- require_relative '../../../toggl'
6
+ require_relative '../../../starfish/client'
7
+ require_relative '../../../toggl/client'
8
+ require_relative '../../../harvest/client'
8
9
 
9
10
  module Sfctl
10
11
  module Commands
@@ -22,7 +23,7 @@ module Sfctl
22
23
 
23
24
  ltoken = access_token
24
25
  config.delete(:access_token)
25
- success, data = Starfish.account_assignments(@options['starfish-host'], @options['all'], ltoken)
26
+ success, data = Starfish::Client.account_assignments(@options['starfish-host'], @options['all'], ltoken)
26
27
  unless success
27
28
  output.puts @pastel.red('Something went wrong. Unable to fetch assignments')
28
29
  return
@@ -38,14 +39,20 @@ module Sfctl
38
39
 
39
40
  assignment_obj = select_assignment(assignments)
40
41
 
42
+ setup_connection!(provider, output, assignment_obj)
43
+ end
44
+
45
+ private
46
+
47
+ def setup_connection!(provider, output, assignment_obj)
41
48
  case provider
42
49
  when TOGGL_PROVIDER
43
50
  setup_toggl_connection!(output, assignment_obj)
51
+ when HARVEST_PROVIDER
52
+ setup_harvest_connection!(output, assignment_obj)
44
53
  end
45
54
  end
46
55
 
47
- private
48
-
49
56
  def clear_conf_and_print_success!(output)
50
57
  delete_providers_from_link_config!
51
58
  save_link_config!
@@ -75,6 +82,14 @@ module Sfctl
75
82
  list
76
83
  end
77
84
 
85
+ def ask_for_billable
86
+ @prompt.select('Billable?', %w[yes no both])
87
+ end
88
+
89
+ def ask_for_rounding
90
+ @prompt.select('Rounding?', %w[on off])
91
+ end
92
+
78
93
  def setup_toggl_connection!(output, assignment_obj) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
79
94
  spinner = ::TTY::Spinner.new('[:spinner] Loading ...')
80
95
 
@@ -82,7 +97,7 @@ module Sfctl
82
97
  toggl_token = read_link_config['providers'][TOGGL_PROVIDER]['access_token']
83
98
 
84
99
  spinner.auto_spin
85
- _success, workspaces = Toggl.workspaces(toggl_token)
100
+ _success, workspaces = Toggl::Client.workspaces(toggl_token)
86
101
  spinner.pause
87
102
  output.puts
88
103
  workspace = @prompt.select('Please select Workspace:') do |menu|
@@ -93,7 +108,7 @@ module Sfctl
93
108
  workspace_id = workspace['id']
94
109
 
95
110
  spinner.resume
96
- _success, projects = Toggl.workspace_projects(toggl_token, workspace_id)
111
+ _success, projects = Toggl::Client.workspace_projects(toggl_token, workspace_id)
97
112
 
98
113
  if projects.nil? || projects.empty?
99
114
  spinner.stop
@@ -113,7 +128,7 @@ module Sfctl
113
128
  spinner.resume
114
129
  tasks_objs = []
115
130
  project_ids.each do |pj_id|
116
- _success, tasks = Toggl.project_tasks(toggl_token, pj_id)
131
+ _success, tasks = Toggl::Client.project_tasks(toggl_token, pj_id)
117
132
  tasks_objs << tasks
118
133
  end
119
134
  tasks_objs.flatten!
@@ -131,9 +146,9 @@ module Sfctl
131
146
  output.puts @pastel.yellow("You don't have tasks. Continue...")
132
147
  end
133
148
 
134
- billable = @prompt.select('Billable?', %w[yes no both])
149
+ billable = ask_for_billable
135
150
 
136
- rounding = @prompt.select('Rounding?', %w[on off])
151
+ rounding = ask_for_rounding
137
152
 
138
153
  config.set("connections.#{assignment_id}.name", value: assignment_obj['name'])
139
154
  config.set("connections.#{assignment_id}.service", value: assignment_obj['service'])
@@ -146,6 +161,66 @@ module Sfctl
146
161
 
147
162
  clear_conf_and_print_success!(output)
148
163
  end
164
+
165
+ def setup_harvest_connection!(output, assignment_obj) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
166
+ spinner = ::TTY::Spinner.new('[:spinner] Loading ...')
167
+
168
+ assignment_id = assignment_obj['id']
169
+ harvest_account_id = read_link_config['providers'][HARVEST_PROVIDER]['account_id']
170
+ harvest_token = read_link_config['providers'][HARVEST_PROVIDER]['access_token']
171
+
172
+ spinner.auto_spin
173
+ _success, projects = Harvest::Client.projects(harvest_account_id, harvest_token)
174
+
175
+ if projects.nil? || projects.empty?
176
+ spinner.stop
177
+ error_message = "There is no projects. Please visit #{HARVEST_PROVIDER} and create them before continue."
178
+ output.puts @pastel.red(error_message)
179
+ return
180
+ end
181
+
182
+ spinner.pause
183
+ output.puts
184
+ project = @prompt.select('Please select Project:') do |menu|
185
+ projects.each do |pj|
186
+ menu.choice name: pj['name'], value: pj
187
+ end
188
+ end
189
+ project_id = project['id']
190
+
191
+ spinner.resume
192
+ _success, tasks = Harvest::Client.tasks(harvest_account_id, harvest_token)
193
+
194
+ if tasks.nil? || tasks.empty?
195
+ spinner.stop
196
+ error_message = "There is no tasks. Please visit #{HARVEST_PROVIDER} and create them before continue."
197
+ output.puts @pastel.red(error_message)
198
+ return
199
+ end
200
+
201
+ spinner.success
202
+ output.puts
203
+ task = @prompt.select('Please select Task:') do |menu|
204
+ tasks.each do |t|
205
+ menu.choice name: t['name'], value: t
206
+ end
207
+ end
208
+ task_id = task['id']
209
+
210
+ billable = ask_for_billable
211
+
212
+ rounding = ask_for_rounding
213
+
214
+ config.set("connections.#{assignment_id}.name", value: assignment_obj['name'])
215
+ config.set("connections.#{assignment_id}.service", value: assignment_obj['service'])
216
+ config.set("connections.#{assignment_id}.provider", value: HARVEST_PROVIDER)
217
+ config.set("connections.#{assignment_id}.project_id", value: project_id.to_s)
218
+ config.set("connections.#{assignment_id}.task_id", value: task_id.to_s)
219
+ config.set("connections.#{assignment_id}.billable", value: billable)
220
+ config.set("connections.#{assignment_id}.rounding", value: rounding)
221
+
222
+ clear_conf_and_print_success!(output)
223
+ end
149
224
  end
150
225
  end
151
226
  end
@@ -29,23 +29,41 @@ module Sfctl
29
29
 
30
30
  def print_connections(output)
31
31
  config.fetch(:connections).each_key do |assignment_id|
32
+ print_header!(output, assignment_id)
33
+
32
34
  case config.fetch(:connections, assignment_id, :provider)
33
35
  when TOGGL_PROVIDER
34
36
  print_toggl_connection!(output, assignment_id)
37
+ when HARVEST_PROVIDER
38
+ print_harvest_connection!(output, assignment_id)
35
39
  end
40
+
41
+ print_footer!(output, assignment_id)
36
42
  end
37
43
  end
38
44
 
39
- def print_toggl_connection!(output, assignment_id) # rubocop:disable Metrics/AbcSize
45
+ def print_header!(output, assignment_id)
40
46
  output.puts "Connection: #{config.fetch(:connections, assignment_id, :name)}"
41
47
  output.puts " service: #{config.fetch(:connections, assignment_id, :service)}"
48
+ end
49
+
50
+ def print_footer!(output, assignment_id)
51
+ output.puts " billable: #{config.fetch(:connections, assignment_id, :billable)}"
52
+ output.puts " rounding: #{config.fetch(:connections, assignment_id, :rounding)}"
53
+ output.puts
54
+ end
55
+
56
+ def print_toggl_connection!(output, assignment_id)
42
57
  output.puts " provider: #{TOGGL_PROVIDER}"
43
58
  output.puts " workspace_id: #{config.fetch(:connections, assignment_id, :workspace_id)}"
44
59
  output.puts " project_ids: #{config.fetch(:connections, assignment_id, :project_ids)}"
45
60
  output.puts " task_ids: #{config.fetch(:connections, assignment_id, :task_ids)}"
46
- output.puts " billable: #{config.fetch(:connections, assignment_id, :billable)}"
47
- output.puts " rounding: #{config.fetch(:connections, assignment_id, :rounding)}"
48
- output.puts
61
+ end
62
+
63
+ def print_harvest_connection!(output, assignment_id)
64
+ output.puts " provider: #{HARVEST_PROVIDER}"
65
+ output.puts " project_id: #{config.fetch(:connections, assignment_id, :project_id)}"
66
+ output.puts " task_id: #{config.fetch(:connections, assignment_id, :task_id)}"
49
67
  end
50
68
  end
51
69
  end
@@ -28,7 +28,7 @@ module Sfctl
28
28
  else
29
29
  output.puts "Provider: #{@pastel.cyan(provider)}"
30
30
  info.each_key do |k|
31
- output.puts " #{k.upcase}: #{info[k]}"
31
+ output.puts " #{k.upcase}: #{@pastel.magenta(info[k])}"
32
32
  end
33
33
  end
34
34
  end
@@ -18,11 +18,13 @@ module Sfctl
18
18
  prompt = ::TTY::Prompt.new
19
19
  provider = prompt.select('Setting up:', PROVIDERS_LIST)
20
20
 
21
- !ask_for_replace(output, prompt) && return unless config.fetch("providers.#{TOGGL_PROVIDER}").nil?
21
+ !ask_for_replace(output, prompt) && return unless config.fetch("providers.#{provider}").nil?
22
22
 
23
23
  case provider
24
24
  when TOGGL_PROVIDER
25
25
  setup_toggl_provider!(output, prompt)
26
+ when HARVEST_PROVIDER
27
+ setup_harvest_provider!(output, prompt)
26
28
  end
27
29
  end
28
30
 
@@ -33,22 +35,46 @@ module Sfctl
33
35
  prompt.yes?('Do you want to replace it?')
34
36
  end
35
37
 
36
- def save_toggl_config!(output, access_token)
37
- config.set("providers.#{TOGGL_PROVIDER}.access_token", value: access_token)
38
+ def correct?(prompt)
39
+ prompt.yes?('Is that information correct?')
40
+ end
41
+
42
+ def save_config_and_print_message!(output)
38
43
  save_config!
39
44
  output.puts @pastel.green('Everything saved.')
40
45
  end
41
46
 
47
+ def save_toggl_config!(output, access_token)
48
+ config.set("providers.#{TOGGL_PROVIDER}.access_token", value: access_token)
49
+ save_config_and_print_message!(output)
50
+ end
51
+
42
52
  def setup_toggl_provider!(output, prompt)
43
53
  output.puts
44
54
  access_token = prompt.ask("Your access token at [#{@pastel.green(TOGGL_PROVIDER)}]:", required: true)
45
- is_correct = prompt.yes?('Is that information correct?')
46
- if is_correct
55
+ if correct?(prompt)
47
56
  save_toggl_config!(output, access_token)
48
57
  else
49
58
  setup_toggl_provider!(output, prompt)
50
59
  end
51
60
  end
61
+
62
+ def save_harvest_config!(output, account_id, access_token)
63
+ config.set("providers.#{HARVEST_PROVIDER}.account_id", value: account_id)
64
+ config.set("providers.#{HARVEST_PROVIDER}.access_token", value: access_token)
65
+ save_config_and_print_message!(output)
66
+ end
67
+
68
+ def setup_harvest_provider!(output, prompt)
69
+ output.puts
70
+ account_id = prompt.ask("Your Account ID at [#{@pastel.green(HARVEST_PROVIDER)}]:", required: true)
71
+ access_token = prompt.ask("Your Token at [#{@pastel.green(HARVEST_PROVIDER)}]:", required: true)
72
+ if correct?(prompt)
73
+ save_harvest_config!(output, account_id, access_token)
74
+ else
75
+ setup_harvest_provider!(output, prompt)
76
+ end
77
+ end
52
78
  end
53
79
  end
54
80
  end