spout 0.11.0.beta1 → 0.11.0.beta2
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 +4 -4
- data/LICENSE +1 -1
- data/README.md +4 -4
- data/lib/spout/commands/deploy.rb +111 -52
- data/lib/spout/commands/graphs.rb +1 -1
- data/lib/spout/commands/help.rb +18 -11
- data/lib/spout/models/coverage_result.rb +1 -1
- data/lib/spout/templates/test/dictionary_test.rb +7 -7
- data/lib/spout/templates/travis.yml +1 -0
- data/lib/spout/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7a873eabc85e3035b8e784628e510d8e976f15b
|
4
|
+
data.tar.gz: 90c06d0bac0ef4c772c82da29760d4007591407b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7cee73fe2aa1bec7762300e8fe24c29462a6db61fa7149bd81274950e5da9ef3071602718f061db7d603db52a5ad56ed97f2377620a08ac96144f4dfc75f2cb
|
7
|
+
data.tar.gz: 9c9038e3ea7ff18eae3485622f11d12f8523e656d331ad9274d969c7c70863cf63ad0b729e76ec5b1de7cbf2c6f59fcd946a2312d9a5602ca2c52ddf1c9ef809
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -144,8 +144,8 @@ class DictionaryTest < Minitest::Test
|
|
144
144
|
|
145
145
|
VALID_UNITS = ['minutes', 'hours']
|
146
146
|
|
147
|
-
@variables.select{|v|
|
148
|
-
define_method("
|
147
|
+
@variables.select { |v| %w(numeric integer).include?(v.type) }.each do |variable|
|
148
|
+
define_method("test_units: #{variable.path}") do
|
149
149
|
puts variable.class
|
150
150
|
# => Spout::Models::Variable
|
151
151
|
assert VALID_UNITS.include?(variable.units)
|
@@ -165,8 +165,8 @@ class DictionaryTest < Minitest::Test
|
|
165
165
|
# iterators that can be used to write custom tests
|
166
166
|
include Spout::Helpers::Iterators
|
167
167
|
|
168
|
-
@variables.select{|v|
|
169
|
-
define_method("test_at_least_two_labels:
|
168
|
+
@variables.select { |v| %w(numeric integer).include?(v.type) }.each do |variable|
|
169
|
+
define_method("test_at_least_two_labels: #{variable.path}") do
|
170
170
|
assert_operator 2, :<=, variable.labels.size
|
171
171
|
end
|
172
172
|
end
|
@@ -8,6 +8,7 @@ require 'spout/helpers/quietly'
|
|
8
8
|
require 'spout/helpers/send_file'
|
9
9
|
require 'spout/helpers/semantic'
|
10
10
|
require 'spout/helpers/json_request'
|
11
|
+
require 'spout/helpers/json_request_generic'
|
11
12
|
|
12
13
|
# - **User Authorization**
|
13
14
|
# - User authenticates via token, the user must be a dataset editor
|
@@ -48,10 +49,13 @@ module Spout
|
|
48
49
|
@version = version
|
49
50
|
@skip_checks = !(argv.delete('--skip-checks').nil? && argv.delete('--no-checks').nil?)
|
50
51
|
|
51
|
-
@
|
52
|
-
@
|
52
|
+
@skip_variables = !(argv.delete('--skip-variables').nil? && argv.delete('--no-variables').nil?)
|
53
|
+
@skip_dataset = !(argv.delete('--skip-dataset').nil? && argv.delete('--no-dataset').nil?)
|
54
|
+
@skip_dictionary = !(argv.delete('--skip-dictionary').nil? && argv.delete('--no-dictionary').nil?)
|
55
|
+
@skip_documentation = !(argv.delete('--skip-documentation').nil? && argv.delete('--no-documentation').nil?)
|
53
56
|
@clean = !(argv.delete('--no-resume').nil? && argv.delete('--clean').nil?)
|
54
|
-
@
|
57
|
+
@skip_server_scripts = !(argv.delete('--skip-server-scripts').nil? && argv.delete('--no-server-scripts').nil?)
|
58
|
+
@archive_only = !(argv.delete('--archive-only').nil?)
|
55
59
|
|
56
60
|
token_arg = argv.find { |arg| /^--token=/ =~ arg }
|
57
61
|
argv.delete(token_arg)
|
@@ -61,13 +65,10 @@ module Spout
|
|
61
65
|
argv.delete(rows_arg)
|
62
66
|
@number_of_rows = rows_arg.gsub(/--rows=/, '').to_i if rows_arg
|
63
67
|
|
64
|
-
# puts "token_arg: #{token_arg}".colorize(:red)
|
65
|
-
# puts "@token: #{@token}".colorize(:red)
|
66
|
-
# puts "rows_arg: #{rows_arg}".colorize(:red)
|
67
|
-
# puts "@number_of_rows: #{@number_of_rows}".colorize(:red)
|
68
|
-
|
69
68
|
@argv = argv
|
70
69
|
|
70
|
+
@created_folders = []
|
71
|
+
|
71
72
|
begin
|
72
73
|
run_all
|
73
74
|
rescue Interrupt
|
@@ -77,28 +78,19 @@ module Spout
|
|
77
78
|
|
78
79
|
def run_all
|
79
80
|
config_file_load
|
80
|
-
version_check
|
81
|
-
test_check
|
81
|
+
version_check
|
82
|
+
test_check
|
82
83
|
user_authorization
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
84
|
+
upload_variables
|
85
|
+
dataset_uploads
|
86
|
+
data_dictionary_uploads
|
87
|
+
markdown_uploads
|
88
|
+
trigger_server_updates
|
89
|
+
set_default_dataset_version
|
89
90
|
rescue DeployError
|
90
91
|
# Nothing on Deploy Error
|
91
92
|
end
|
92
93
|
|
93
|
-
def load_subjects_from_csvs
|
94
|
-
@dictionary_root = Dir.pwd
|
95
|
-
@variable_files = Dir.glob(File.join(@dictionary_root, 'variables', '**', '*.json'))
|
96
|
-
|
97
|
-
@subject_loader = Spout::Helpers::SubjectLoader.new(@variable_files, [], @version, @number_of_rows, @config.visit)
|
98
|
-
@subject_loader.load_subjects_from_csvs!
|
99
|
-
@subjects = @subject_loader.subjects
|
100
|
-
end
|
101
|
-
|
102
94
|
def config_file_load
|
103
95
|
print ' `.spout.yml` Check: '
|
104
96
|
@config = Spout::Helpers::ConfigReader.new
|
@@ -142,6 +134,11 @@ module Spout
|
|
142
134
|
# - `CHANGELOG.md` top line should include version, ex: `## 0.1.0`
|
143
135
|
# - "v#{VERSION}" matches HEAD git tag annotation
|
144
136
|
def version_check
|
137
|
+
if @skip_checks
|
138
|
+
puts ' Version Check: ' + 'SKIP'.colorize(:blue)
|
139
|
+
return
|
140
|
+
end
|
141
|
+
|
145
142
|
stdout = quietly do
|
146
143
|
`git status --porcelain`
|
147
144
|
end
|
@@ -179,6 +176,11 @@ module Spout
|
|
179
176
|
end
|
180
177
|
|
181
178
|
def test_check
|
179
|
+
if @skip_checks
|
180
|
+
puts ' Spout Tests: ' + 'SKIP'.colorize(:blue)
|
181
|
+
return
|
182
|
+
end
|
183
|
+
|
182
184
|
print " Spout Tests: "
|
183
185
|
|
184
186
|
stdout = quietly do
|
@@ -192,7 +194,7 @@ module Spout
|
|
192
194
|
failure message
|
193
195
|
end
|
194
196
|
|
195
|
-
puts
|
197
|
+
puts ' Spout Coverage: ' + 'SKIP'.colorize(:blue)
|
196
198
|
end
|
197
199
|
|
198
200
|
def user_authorization
|
@@ -207,43 +209,69 @@ module Spout
|
|
207
209
|
else
|
208
210
|
puts 'UNAUTHORIZED'.colorize(:red)
|
209
211
|
puts "#{INDENT}You are not set as an editor on the #{@slug} dataset or you mistyped your token."
|
210
|
-
|
212
|
+
fail DeployError
|
211
213
|
end
|
212
214
|
|
213
215
|
# failure ''
|
214
216
|
# puts 'PASS'.colorize(:green)
|
215
217
|
end
|
216
218
|
|
219
|
+
def upload_variables
|
220
|
+
if @skip_variables
|
221
|
+
puts ' Upload Variables: ' + 'SKIP'.colorize(:blue)
|
222
|
+
return
|
223
|
+
end
|
224
|
+
load_subjects_from_csvs
|
225
|
+
graph_generation
|
226
|
+
end
|
227
|
+
|
228
|
+
def load_subjects_from_csvs
|
229
|
+
@dictionary_root = Dir.pwd
|
230
|
+
@variable_files = Dir.glob(File.join(@dictionary_root, 'variables', '**', '*.json'))
|
231
|
+
@subject_loader = Spout::Helpers::SubjectLoader.new(@variable_files, [], @version, @number_of_rows, @config.visit)
|
232
|
+
@subject_loader.load_subjects_from_csvs!
|
233
|
+
@subjects = @subject_loader.subjects
|
234
|
+
end
|
235
|
+
|
217
236
|
def graph_generation
|
218
237
|
# failure ''
|
219
238
|
require 'spout/commands/graphs'
|
220
239
|
@argv << '--clean' if @clean
|
221
240
|
Spout::Commands::Graphs.new(@argv, @version, true, @url, @slug, @token, @webserver_name, @subjects)
|
222
|
-
puts "\r
|
241
|
+
puts "\r Upload Variables: " + 'DONE '.colorize(:green)
|
223
242
|
end
|
224
243
|
|
225
244
|
def dataset_uploads
|
226
|
-
|
227
|
-
|
228
|
-
csv_directory = semantic.selected_folder
|
229
|
-
|
230
|
-
if @version != csv_directory
|
231
|
-
puts "\r Dataset Uploads: " + "SKIPPED - #{csv_directory} CSV dataset already on server".colorize(:blue)
|
245
|
+
if @skip_dataset
|
246
|
+
puts ' Dataset Uploads: ' + 'SKIP'.colorize(:blue)
|
232
247
|
return
|
233
248
|
end
|
234
249
|
|
250
|
+
available_folders = (Dir.exist?('csvs') ? Dir.entries('csvs').select { |e| File.directory? File.join('csvs', e) }.reject { |e| ['.', '..'].include?(e) }.sort : [])
|
251
|
+
semantic = Spout::Helpers::Semantic.new(@version, available_folders)
|
252
|
+
csv_directory = semantic.selected_folder
|
235
253
|
csv_files = Dir.glob("csvs/#{csv_directory}/**/*.csv")
|
236
254
|
|
237
255
|
csv_files.each_with_index do |csv_file, index|
|
238
256
|
print "\r Dataset Uploads: " + "#{index + 1} of #{csv_files.count}".colorize(:green)
|
239
|
-
folder = csv_file.gsub(
|
240
|
-
|
257
|
+
folder = csv_file.gsub(%r{^csvs/#{csv_directory}}, '').gsub(/#{File.basename(csv_file)}$/, '')
|
258
|
+
folder = folder.gsub(%r{/$}, '')
|
259
|
+
@created_folders << "datasets#{folder}"
|
260
|
+
@created_folders << 'datasets/archive'
|
261
|
+
@created_folders << "datasets/archive/#{@version}#{folder}"
|
262
|
+
upload_file(csv_file, "datasets#{folder}") unless @archive_only
|
263
|
+
upload_file(csv_file, "datasets/archive/#{@version}#{folder}")
|
241
264
|
end
|
242
|
-
puts "\r Dataset Uploads: " +
|
265
|
+
puts "\r Dataset Uploads: " + 'DONE '.colorize(:green)
|
243
266
|
end
|
244
267
|
|
245
268
|
def data_dictionary_uploads
|
246
|
-
|
269
|
+
if @skip_dictionary
|
270
|
+
puts ' Dictionary Uploads: ' + 'SKIP'.colorize(:blue)
|
271
|
+
return
|
272
|
+
end
|
273
|
+
|
274
|
+
print ' Dictionary Uploads:'
|
247
275
|
|
248
276
|
require 'spout/commands/exporter'
|
249
277
|
Spout::Commands::Exporter.new(@version, ['--quiet'])
|
@@ -251,44 +279,75 @@ module Spout
|
|
251
279
|
csv_files = Dir.glob("dd/#{@version}/*.csv")
|
252
280
|
csv_files.each_with_index do |csv_file, index|
|
253
281
|
print "\r Dictionary Uploads: " + "#{index + 1} of #{csv_files.count}".colorize(:green)
|
254
|
-
|
282
|
+
@created_folders << 'datasets'
|
283
|
+
@created_folders << 'datasets/archive'
|
284
|
+
@created_folders << "datasets/archive/#{@version}"
|
285
|
+
upload_file(csv_file, 'datasets') unless @archive_only
|
286
|
+
upload_file(csv_file, "datasets/archive/#{@version}")
|
255
287
|
end
|
256
288
|
puts "\r Dictionary Uploads: " + 'DONE '.colorize(:green)
|
257
289
|
end
|
258
290
|
|
259
291
|
def markdown_uploads
|
260
|
-
|
292
|
+
if @skip_documentation
|
293
|
+
puts 'Documentation Uploads: ' + 'SKIP'.colorize(:blue)
|
294
|
+
return
|
295
|
+
end
|
296
|
+
|
297
|
+
print 'Documentation Uploads:'
|
261
298
|
markdown_files = Dir.glob(%w(CHANGELOG.md KNOWNISSUES.md))
|
262
299
|
markdown_files.each_with_index do |markdown_file, index|
|
263
300
|
print "\rDocumentation Uploads: " + "#{index + 1} of #{markdown_files.count}".colorize(:green)
|
264
|
-
|
301
|
+
@created_folders << 'datasets'
|
302
|
+
@created_folders << 'datasets/archive'
|
303
|
+
@created_folders << "datasets/archive/#{@version}"
|
304
|
+
upload_file(markdown_file, 'datasets') unless @archive_only
|
305
|
+
upload_file(markdown_file, "datasets/archive/#{@version}")
|
265
306
|
end
|
266
307
|
puts "\rDocumentation Uploads: " + 'DONE '.colorize(:green)
|
267
308
|
end
|
268
309
|
|
269
310
|
def trigger_server_updates
|
311
|
+
if @skip_server_scripts
|
312
|
+
puts 'Launch Server Scripts: ' + 'SKIP'.colorize(:blue)
|
313
|
+
return
|
314
|
+
end
|
315
|
+
|
270
316
|
print 'Launch Server Scripts: '
|
271
|
-
|
317
|
+
params = { auth_token: @token, dataset: @slug, version: @version, folders: @created_folders.compact.uniq }
|
318
|
+
(response, status) = Spout::Helpers::JsonRequestGeneric.post("#{@url}/api/v1/dictionary/refresh.json", params)
|
272
319
|
if response.is_a?(Hash) && response['refresh'] == 'success'
|
273
320
|
puts 'DONE'.colorize(:green)
|
274
|
-
elsif response.is_a?(Hash) && response['refresh'] == 'notagfound'
|
275
|
-
puts 'FAIL'.colorize(:red)
|
276
|
-
puts "#{INDENT}Tag not found in repository, resolve using: " + 'git push --tags'.colorize(:white)
|
277
|
-
raise DeployError
|
278
|
-
elsif response.is_a?(Hash) && response['refresh'] == 'gitrepodoesnotexist'
|
279
|
-
puts 'FAIL'.colorize(:red)
|
280
|
-
puts "#{INDENT}Dataset data dictionary git repository has not been cloned on the server. Contact server admin.".colorize(:white)
|
281
|
-
raise DeployError
|
282
321
|
else
|
283
322
|
puts 'FAIL'.colorize(:red)
|
284
|
-
|
323
|
+
fail DeployError
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
def set_default_dataset_version
|
328
|
+
if @archive_only
|
329
|
+
puts ' Set Default Version: ' + 'SKIP'.colorize(:blue)
|
330
|
+
return
|
331
|
+
end
|
332
|
+
|
333
|
+
print ' Set Default Version: '
|
334
|
+
params = { auth_token: @token, dataset: @slug, version: @version }
|
335
|
+
(response, status) = Spout::Helpers::JsonRequestGeneric.post("#{@url}/api/v1/dictionary/update_default_version.json", params)
|
336
|
+
if response.is_a?(Hash) && response['version_update'] == 'success'
|
337
|
+
puts @version.to_s.colorize(:green)
|
338
|
+
else
|
339
|
+
failure("#{INDENT}Unable to set default version\n#{INDENT}to " + @version.to_s.colorize(:white) + ' for ' + @slug.to_s.colorize(:white) + ' dataset.')
|
285
340
|
end
|
286
341
|
end
|
287
342
|
|
288
343
|
def failure(message)
|
289
344
|
puts 'FAIL'.colorize(:red)
|
290
345
|
puts message
|
291
|
-
|
346
|
+
fail DeployError
|
347
|
+
end
|
348
|
+
|
349
|
+
def upload_file(file, folder)
|
350
|
+
Spout::Helpers::SendFile.post("#{@url}/api/v1/dictionary/upload_file.json", file, @version, @token, @slug, folder)
|
292
351
|
end
|
293
352
|
end
|
294
353
|
end
|
@@ -108,7 +108,7 @@ module Spout
|
|
108
108
|
next unless Spout::Models::Subject.method_defined?(variable.id)
|
109
109
|
|
110
110
|
if @deploy_mode
|
111
|
-
print "\r
|
111
|
+
print "\r Upload Variables: " + "#{"% 3d" % ((file_index+1)*100/variable_files_count)}% Uploaded".colorize(:white)
|
112
112
|
else
|
113
113
|
puts "#{file_index + 1} of #{variable_files_count}: #{variable.folder}#{variable.id}"
|
114
114
|
end
|
data/lib/spout/commands/help.rb
CHANGED
@@ -132,17 +132,24 @@ Usage: spout deploy NAME
|
|
132
132
|
|
133
133
|
NAME is the name of the webserver listed in `.spout.yml` file
|
134
134
|
Optional Flags:
|
135
|
-
--clean
|
136
|
-
|
137
|
-
--rows=N
|
138
|
-
|
139
|
-
<variable>
|
140
|
-
|
141
|
-
--skip-checks
|
142
|
-
--skip-
|
143
|
-
--skip-
|
144
|
-
--
|
145
|
-
|
135
|
+
--clean Regenerate all variables (default is to
|
136
|
+
resume where command last left off)
|
137
|
+
--rows=N Limit the number of rows read from CSVs
|
138
|
+
to a maximum of N rows
|
139
|
+
<variable> Only deploy specified variable(s)
|
140
|
+
Ex: spout deploy production age gender
|
141
|
+
--skip-checks Skip Spout checks
|
142
|
+
--skip-variables Skip upload of dataset variables
|
143
|
+
--skip-dataset Skip upload of dataset CSVs
|
144
|
+
--skip-dictionary Skip upload of data dictionary
|
145
|
+
--skip-documentation Skip upload of CHANGELOG.md and
|
146
|
+
KNOWNISSUES.md
|
147
|
+
--skip-server-scripts Skips server refreshing datasets folder
|
148
|
+
to list newly uploaded files
|
149
|
+
--archive-only Only upload files to the datasets/archive
|
150
|
+
folder and not in the root datasets folder
|
151
|
+
--token=TOKEN Provide token via command-line for
|
152
|
+
automated processes
|
146
153
|
|
147
154
|
More information here:
|
148
155
|
|
@@ -17,7 +17,7 @@ module Spout
|
|
17
17
|
|
18
18
|
def load_json(column)
|
19
19
|
file = Dir.glob("variables/**/#{column.to_s.downcase}.json", File::FNM_CASEFOLD).first
|
20
|
-
@file_name_test =
|
20
|
+
@file_name_test = !file.nil?
|
21
21
|
@json = JSON.parse(File.read(file)) rescue @json = {}
|
22
22
|
@json_id_test = (@json['id'].to_s.downcase == column)
|
23
23
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
+
# Launches default Spout tests and custom tests for specific to this dictionary
|
3
4
|
class DictionaryTest < Minitest::Test
|
4
5
|
# This line includes all default Spout Dictionary tests
|
5
6
|
include Spout::Tests
|
@@ -10,18 +11,17 @@ class DictionaryTest < Minitest::Test
|
|
10
11
|
|
11
12
|
# Example 1: Create custom tests to show that `integer` and `numeric` variables have a valid unit type
|
12
13
|
# VALID_UNITS = ['minutes', 'hours'] # Add your own valid units to this array
|
13
|
-
# @variables.select{|v|
|
14
|
-
# define_method("test_units:
|
15
|
-
# message = "\"#{variable.units}\"".colorize(
|
16
|
-
#
|
17
|
-
# VALID_UNITS.sort.collect{|u| u.inspect.colorize( :white )}.join(', ')
|
14
|
+
# @variables.select { |v| %w(numeric integer).include?(v.type) }.each do |variable|
|
15
|
+
# define_method("test_units: #{variable.path}") do
|
16
|
+
# message = "\"#{variable.units}\"".colorize(:red) + " invalid units.\n Valid types: " +
|
17
|
+
# VALID_UNITS.sort.collect { |u| u.inspect.colorize(:white) }.join(', ')
|
18
18
|
# assert VALID_UNITS.include?(variable.units), message
|
19
19
|
# end
|
20
20
|
# end
|
21
21
|
|
22
22
|
# Example 2: Create custom tests to show that variables have 2 or more labels.
|
23
|
-
# @variables.select{|v|
|
24
|
-
# define_method("test_at_least_two_labels:
|
23
|
+
# @variables.select { |v| %w(numeric integer).include?(v.type) }.each do |variable|
|
24
|
+
# define_method("test_at_least_two_labels: #{variable.path}") do
|
25
25
|
# assert_operator 2, :<=, variable.labels.size
|
26
26
|
# end
|
27
27
|
# end
|
data/lib/spout/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.0.
|
4
|
+
version: 0.11.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Remo Mueller
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|