sfctl 0.0.2 → 1.0.1

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 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