transcriptic 0.1.3 → 0.2.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/bin/transcriptic +2 -4
- data/lib/thor/monkies.rb +3 -0
- data/lib/thor/monkies/shell.rb +3 -0
- data/lib/transcriptic.rb +86 -2
- data/lib/transcriptic/auth.rb +2 -63
- data/lib/transcriptic/base_generator.rb +25 -0
- data/lib/transcriptic/cli.rb +199 -8
- data/lib/transcriptic/client.rb +45 -38
- data/lib/transcriptic/commands/project.rb +37 -0
- data/lib/transcriptic/core_ext.rb +3 -0
- data/lib/transcriptic/core_ext/file.rb +7 -0
- data/lib/transcriptic/core_ext/file_utils.rb +15 -0
- data/lib/transcriptic/core_ext/pathname.rb +13 -0
- data/lib/transcriptic/core_ext/string.rb +8 -0
- data/lib/transcriptic/dependencies_generator.rb +13 -0
- data/lib/transcriptic/errors.rb +32 -0
- data/lib/transcriptic/labfile.rb +73 -0
- data/lib/transcriptic/project_generator.rb +56 -0
- data/lib/transcriptic/sbt.rb +58 -0
- data/lib/transcriptic/templates/LICENSE.erb +20 -0
- data/lib/transcriptic/templates/Labfile.erb +12 -0
- data/lib/transcriptic/templates/README.erb +3 -0
- data/lib/transcriptic/templates/app/Main.erb +11 -0
- data/lib/transcriptic/templates/project/Build.erb +59 -0
- data/lib/transcriptic/templates/project/Dependencies.erb +10 -0
- data/lib/transcriptic/templates/project/build.properties +1 -0
- data/lib/transcriptic/templates/project/plugins.sbt +5 -0
- data/lib/transcriptic/templates/sbt +1 -0
- data/lib/transcriptic/{helpers.rb → ui.rb} +124 -109
- data/lib/transcriptic/version.rb +2 -1
- data/lib/vendor/{transcriptic/okjson.rb → okjson.rb} +0 -0
- metadata +203 -46
- data/lib/transcriptic/command.rb +0 -233
- data/lib/transcriptic/command/base.rb +0 -157
- data/lib/transcriptic/command/console.rb +0 -10
- data/lib/transcriptic/command/data.rb +0 -29
- data/lib/transcriptic/command/help.rb +0 -124
- data/lib/transcriptic/command/login.rb +0 -35
- data/lib/transcriptic/command/run.rb +0 -108
data/lib/transcriptic/client.rb
CHANGED
@@ -1,11 +1,3 @@
|
|
1
|
-
require 'rexml/document'
|
2
|
-
require 'rest-client'
|
3
|
-
require 'uri'
|
4
|
-
require 'time'
|
5
|
-
require 'transcriptic/auth'
|
6
|
-
require 'transcriptic/helpers'
|
7
|
-
require 'transcriptic/version'
|
8
|
-
|
9
1
|
# A Ruby class to call the Transcriptic REST API. You might use this if you want to
|
10
2
|
# manage your Transcriptic apps from within a Ruby program, such as Capistrano.
|
11
3
|
#
|
@@ -16,9 +8,7 @@ require 'transcriptic/version'
|
|
16
8
|
# transcriptic.create('myapp')
|
17
9
|
#
|
18
10
|
class Transcriptic::Client
|
19
|
-
|
20
|
-
include Transcriptic::Helpers
|
21
|
-
extend Transcriptic::Helpers
|
11
|
+
include Transcriptic::UI
|
22
12
|
|
23
13
|
def self.version
|
24
14
|
Transcriptic::VERSION
|
@@ -41,14 +31,12 @@ class Transcriptic::Client
|
|
41
31
|
@host = host
|
42
32
|
end
|
43
33
|
|
44
|
-
|
45
|
-
|
46
|
-
|
34
|
+
def list_projects
|
35
|
+
json_decode get("/api/projects.json").to_s
|
36
|
+
end
|
47
37
|
|
48
|
-
|
49
|
-
|
50
|
-
:accept => 'application/json'
|
51
|
-
).to_s
|
38
|
+
def project_info(name)
|
39
|
+
json_decode get("/api/projects/#{name}.json").to_s
|
52
40
|
end
|
53
41
|
|
54
42
|
class ProtocolException < RuntimeError; end
|
@@ -57,16 +45,24 @@ class Transcriptic::Client
|
|
57
45
|
def list
|
58
46
|
json_decode get('/api/runs.json').to_s
|
59
47
|
end
|
60
|
-
|
48
|
+
|
49
|
+
def list_datasets(run_id = nil, project_id = nil)
|
50
|
+
json_decode get("/api/datasets.json?run_id=#{run_id}&project_id=#{project_id}").to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_dataset_info(dataset_id)
|
54
|
+
json_decode get("/api/datasets/#{dataset_id}").to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
def delete_dataset(dataset_id)
|
58
|
+
json_decode delete("/api/datasets/#{dataset_id}").to_s
|
59
|
+
end
|
60
|
+
|
61
61
|
# Show info such as mode, custom domain, and collaborators on an app.
|
62
62
|
def info(name_or_domain)
|
63
63
|
name_or_domain = name_or_domain.gsub(/^(http:\/\/)?(www\.)?/, '')
|
64
64
|
end
|
65
65
|
|
66
|
-
def organizations
|
67
|
-
json_decode resource("/organizations").get(:accept => 'application/json').to_s
|
68
|
-
end
|
69
|
-
|
70
66
|
class Protocol
|
71
67
|
attr_accessor :attached, :upid
|
72
68
|
|
@@ -80,9 +76,9 @@ class Transcriptic::Client
|
|
80
76
|
def launch(command, attached=false)
|
81
77
|
@attached = attached
|
82
78
|
@response = @client.post(
|
83
|
-
"/runs/#{@app}/
|
79
|
+
"/api/runs/#{@app}/confirm",
|
84
80
|
command,
|
85
|
-
:content_type => '
|
81
|
+
:content_type => 'application/json'
|
86
82
|
)
|
87
83
|
@next_chunk = @response.to_s
|
88
84
|
@interval = 0
|
@@ -137,18 +133,29 @@ class Transcriptic::Client
|
|
137
133
|
json_decode get("/api/runs/#{run_id}").to_s
|
138
134
|
end
|
139
135
|
|
140
|
-
def create_run(fd)
|
141
|
-
|
136
|
+
def create_run(fd, project_id)
|
137
|
+
payload = {
|
138
|
+
'zipdata' => Base64.encode64(File.open(fd).read),
|
139
|
+
'project_id' => project_id
|
140
|
+
}
|
141
|
+
json_decode post("/api/runs", payload, { 'Content-Type' => 'application/zip; charset=UTF-8' }).to_s
|
142
|
+
end
|
143
|
+
|
144
|
+
def launch_run(run_id)
|
145
|
+
json_decode post("/api/runs/#{run_id}/confirm").to_s
|
142
146
|
end
|
143
147
|
|
144
|
-
# Get a Protocol instance to execute commands against.
|
145
148
|
def protocol(run_id, upid)
|
146
149
|
Protocol.new(self, run_id, upid)
|
147
150
|
end
|
148
151
|
|
149
152
|
def read_logs(run_id, options=[])
|
150
153
|
query = "&" + options.join("&") unless options.empty?
|
151
|
-
url = get("/api/runs/#{run_id}/logs?#{query}").to_s
|
154
|
+
url = get("/api/runs/#{run_id}/logs.json?#{query}").to_s
|
155
|
+
if 'not_found' == url
|
156
|
+
error "Run #{run_id} not found!"
|
157
|
+
end
|
158
|
+
|
152
159
|
uri = URI.parse(url);
|
153
160
|
http = Net::HTTP.new(uri.host, uri.port)
|
154
161
|
|
@@ -180,9 +187,9 @@ class Transcriptic::Client
|
|
180
187
|
|
181
188
|
##################
|
182
189
|
|
183
|
-
def resource(uri, options={})
|
190
|
+
def resource(uri, options={}, host=host)
|
184
191
|
RestClient.proxy = ENV['HTTP_PROXY'] || ENV['http_proxy']
|
185
|
-
resource = RestClient::Resource.new(realize_full_uri(uri), options)
|
192
|
+
resource = RestClient::Resource.new(realize_full_uri(uri, host), options)
|
186
193
|
resource
|
187
194
|
end
|
188
195
|
|
@@ -190,8 +197,8 @@ class Transcriptic::Client
|
|
190
197
|
process(:get, uri, extra_headers)
|
191
198
|
end
|
192
199
|
|
193
|
-
def post(uri, payload="", extra_headers={}) # :nodoc:
|
194
|
-
process(:post, uri, extra_headers, payload)
|
200
|
+
def post(uri, payload="", extra_headers={}, host=host) # :nodoc:
|
201
|
+
process(:post, uri, extra_headers, payload, host)
|
195
202
|
end
|
196
203
|
|
197
204
|
def put(uri, payload, extra_headers={}) # :nodoc:
|
@@ -202,19 +209,19 @@ class Transcriptic::Client
|
|
202
209
|
process(:delete, uri, extra_headers)
|
203
210
|
end
|
204
211
|
|
205
|
-
def process(method, uri, extra_headers={}, payload=nil)
|
212
|
+
def process(method, uri, extra_headers={}, payload=nil, host=host)
|
206
213
|
headers = transcriptic_headers.merge(extra_headers)
|
207
214
|
args = [method, payload, headers].compact
|
208
215
|
|
209
216
|
resource_options = default_resource_options_for_uri(uri)
|
210
217
|
|
211
218
|
begin
|
212
|
-
response = resource(uri, resource_options).send(*args)
|
219
|
+
response = resource(uri, resource_options, host).send(*args)
|
213
220
|
rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, SocketError
|
214
|
-
host = URI.parse(realize_full_uri(uri)).host
|
221
|
+
host = URI.parse(realize_full_uri(uri, host)).host
|
215
222
|
error " ! Unable to connect to #{host}"
|
216
223
|
rescue RestClient::SSLCertificateNotVerified => ex
|
217
|
-
host = URI.parse(realize_full_uri(uri)).host
|
224
|
+
host = URI.parse(realize_full_uri(uri, host)).host
|
218
225
|
error "WARNING: Unable to verify SSL certificate for #{host}\nTo disable SSL verification, run with TRANSCRIPTIC_SSL_VERIFY=disable"
|
219
226
|
end
|
220
227
|
|
@@ -262,7 +269,7 @@ class Transcriptic::Client
|
|
262
269
|
|
263
270
|
private
|
264
271
|
|
265
|
-
def realize_full_uri(given)
|
272
|
+
def realize_full_uri(given, host=host)
|
266
273
|
full_host = (host =~ /^http/) ? host : "https://www.#{host}"
|
267
274
|
host = URI.parse(full_host)
|
268
275
|
uri = URI.parse(given)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Transcriptic
|
2
|
+
module CLI
|
3
|
+
|
4
|
+
# manage projects
|
5
|
+
#
|
6
|
+
class Project < Thor
|
7
|
+
|
8
|
+
desc "index", "upload FILENAME or DIRECTORY and launch it"
|
9
|
+
def index
|
10
|
+
if args.empty?
|
11
|
+
error("Usage: transcriptic project NAME")
|
12
|
+
end
|
13
|
+
name = args.shift
|
14
|
+
data = transcriptic.project_info(name)
|
15
|
+
display "Project \"#{data["name"]}\":"
|
16
|
+
display " shortname: #{data["codename"]}"
|
17
|
+
display " active runs: #{data["active_runs"].length}"
|
18
|
+
display " archived runs: #{data["completed_runs"].length}"
|
19
|
+
display " datasets created: #{data["datasets"].length}"
|
20
|
+
display " created at: #{data["created_at"]}"
|
21
|
+
end
|
22
|
+
|
23
|
+
# transcriptic project:list
|
24
|
+
desc "list", "list the projects the user can see"
|
25
|
+
def list
|
26
|
+
ret = transcriptic.list_projects
|
27
|
+
if ret.empty?
|
28
|
+
error("No projects for #{transcriptic.user}")
|
29
|
+
return
|
30
|
+
end
|
31
|
+
ret.each do |project|
|
32
|
+
display "\t" + project["codename"] + "\t\t" + project["name"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module FileUtils
|
4
|
+
class << self
|
5
|
+
# Override mv to avoid several bugs (Errno::EACCES in Windows, Errno::ENOENT
|
6
|
+
# with relative softlinks on Linux), by forcing to copy and delete instead
|
7
|
+
#
|
8
|
+
# @see {FileUtils::mv}
|
9
|
+
# @see {safe_mv}
|
10
|
+
def mv(src, dest, options = {})
|
11
|
+
FileUtils.cp_r(src, dest, options)
|
12
|
+
FileUtils.rm_rf(src)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'transcriptic/base_generator'
|
2
|
+
|
3
|
+
module Transcriptic
|
4
|
+
class DependenciesGenerator < BaseGenerator
|
5
|
+
include Transcriptic::UI
|
6
|
+
|
7
|
+
argument :dependencies
|
8
|
+
|
9
|
+
def generate
|
10
|
+
template 'project/Dependencies.erb', target.join('project/Dependencies.scala'), force: true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Transcriptic
|
2
|
+
class TranscripticError < StandardError
|
3
|
+
class << self
|
4
|
+
def status_code(code)
|
5
|
+
define_method(:status_code) { code }
|
6
|
+
define_singleton_method(:status_code) { code }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
alias_method :message, :to_s
|
10
|
+
end
|
11
|
+
|
12
|
+
class LabfileReadError < TranscripticError
|
13
|
+
def initialize(original_error)
|
14
|
+
@original_error = original_error
|
15
|
+
end
|
16
|
+
|
17
|
+
status_code(113)
|
18
|
+
|
19
|
+
def status_code
|
20
|
+
@original_error.respond_to?(:status_code) ? @original_error.status_code : 113
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
[
|
25
|
+
"An error occurred while reading the Labfile:",
|
26
|
+
"",
|
27
|
+
" " + @original_error.to_s.split("\n").map(&:strip).join("\n "),
|
28
|
+
].join("\n")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#require 'transcriptic/downloader'
|
2
|
+
|
3
|
+
module Transcriptic
|
4
|
+
class Labfile
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def from_file(file)
|
9
|
+
content = File.read(file)
|
10
|
+
object = new(file)
|
11
|
+
object.load(content)
|
12
|
+
rescue Errno::ENOENT => e
|
13
|
+
raise FileNotFound, "No Labfile found at: #{file}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(path)
|
18
|
+
@filepath = path
|
19
|
+
@options = Hash.new
|
20
|
+
@dependencies = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def load(content)
|
24
|
+
begin
|
25
|
+
instance_eval(content)
|
26
|
+
rescue => e
|
27
|
+
puts e
|
28
|
+
raise LabfileReadError.new(e)
|
29
|
+
end
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def sha
|
34
|
+
@sha ||= Digest::SHA1.hexdigest File.read(filepath.to_s)
|
35
|
+
end
|
36
|
+
|
37
|
+
def options
|
38
|
+
@options
|
39
|
+
end
|
40
|
+
|
41
|
+
def name(name = nil)
|
42
|
+
@options[:name] = name
|
43
|
+
end
|
44
|
+
|
45
|
+
def author(name)
|
46
|
+
@options[:author] = name
|
47
|
+
end
|
48
|
+
|
49
|
+
def email(email)
|
50
|
+
@options[:email] = email
|
51
|
+
end
|
52
|
+
|
53
|
+
def version(arg)
|
54
|
+
@options[:version] = arg
|
55
|
+
end
|
56
|
+
|
57
|
+
def description(desc)
|
58
|
+
@options[:description] = desc
|
59
|
+
end
|
60
|
+
|
61
|
+
def dependency(group, name, version)
|
62
|
+
@dependencies << {
|
63
|
+
group: group,
|
64
|
+
name: name,
|
65
|
+
version: version
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def dependencies
|
70
|
+
@dependencies
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'transcriptic/base_generator'
|
2
|
+
|
3
|
+
module Transcriptic
|
4
|
+
class ProjectGenerator < BaseGenerator
|
5
|
+
|
6
|
+
argument :name
|
7
|
+
class_option :package,
|
8
|
+
type: :string,
|
9
|
+
default: "org.autoprotocol.unclaimed"
|
10
|
+
class_option :author,
|
11
|
+
type: :string,
|
12
|
+
default: "John Appleseed"
|
13
|
+
class_option :email,
|
14
|
+
type: :string,
|
15
|
+
default: "author@example.edu"
|
16
|
+
class_option :description,
|
17
|
+
type: :string,
|
18
|
+
default: false
|
19
|
+
|
20
|
+
def generate
|
21
|
+
empty_directory target.join('app')
|
22
|
+
empty_directory target.join('project')
|
23
|
+
empty_directory target.join('lib')
|
24
|
+
|
25
|
+
template 'app/Main.erb', target.join('app/Main.scala')
|
26
|
+
template 'project/Build.erb', target.join('project/Build.scala')
|
27
|
+
copy_file 'project/build.properties', target.join('project/build.properties')
|
28
|
+
copy_file 'project/plugins.sbt', target.join('project/plugins.sbt')
|
29
|
+
template 'LICENSE.erb', target.join('LICENSE')
|
30
|
+
template 'Labfile.erb', target.join('Labfile')
|
31
|
+
template 'README.erb', target.join('README.md')
|
32
|
+
|
33
|
+
Transcriptic::DependenciesGenerator.new([File.join(Dir.pwd, name), []], options).invoke_all
|
34
|
+
end
|
35
|
+
|
36
|
+
def description
|
37
|
+
options[:description]
|
38
|
+
end
|
39
|
+
|
40
|
+
def package
|
41
|
+
options[:package]
|
42
|
+
end
|
43
|
+
|
44
|
+
def author
|
45
|
+
options[:author]
|
46
|
+
end
|
47
|
+
|
48
|
+
def email
|
49
|
+
options[:email]
|
50
|
+
end
|
51
|
+
|
52
|
+
def copyright_year
|
53
|
+
Time.now.year
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Transcriptic
|
2
|
+
class SBT
|
3
|
+
class << self
|
4
|
+
include Transcriptic::UI
|
5
|
+
|
6
|
+
def compile
|
7
|
+
ensure_installed
|
8
|
+
sbt("package")
|
9
|
+
end
|
10
|
+
|
11
|
+
def stage
|
12
|
+
ensure_installed
|
13
|
+
sbt("stage")
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def ensure_installed
|
18
|
+
stat = `which sbt`
|
19
|
+
if stat.empty?
|
20
|
+
output_with_arrow "Downloading sbt..."
|
21
|
+
Transcriptic::SBT::Installer.new(["/usr/local"], {}).invoke_all
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def sbt(action)
|
26
|
+
base = Transcriptic.find_labfile.dirname
|
27
|
+
output_with_arrow "Detected Scala sources in app..."
|
28
|
+
output_with_arrow "Compiling..."
|
29
|
+
display
|
30
|
+
|
31
|
+
code = IO.popen("sbt #{action}") do |stream|
|
32
|
+
stream.each do |line|
|
33
|
+
output_with_indent line
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
display
|
38
|
+
|
39
|
+
if 0 == $?
|
40
|
+
output_with_arrow "Compilation succeeded."
|
41
|
+
true
|
42
|
+
else
|
43
|
+
output_with_arrow "Errors occurred!"
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Installer < BaseGenerator
|
50
|
+
def install
|
51
|
+
get "http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/0.12.3/sbt-launch.jar",
|
52
|
+
target.join("sbt/sbt-launch.jar")
|
53
|
+
copy_file 'sbt', target.join('bin/sbt')
|
54
|
+
chmod target.join('bin/sbt'), 0755
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|