transcriptic 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/bin/transcriptic +2 -4
  3. data/lib/thor/monkies.rb +3 -0
  4. data/lib/thor/monkies/shell.rb +3 -0
  5. data/lib/transcriptic.rb +86 -2
  6. data/lib/transcriptic/auth.rb +2 -63
  7. data/lib/transcriptic/base_generator.rb +25 -0
  8. data/lib/transcriptic/cli.rb +199 -8
  9. data/lib/transcriptic/client.rb +45 -38
  10. data/lib/transcriptic/commands/project.rb +37 -0
  11. data/lib/transcriptic/core_ext.rb +3 -0
  12. data/lib/transcriptic/core_ext/file.rb +7 -0
  13. data/lib/transcriptic/core_ext/file_utils.rb +15 -0
  14. data/lib/transcriptic/core_ext/pathname.rb +13 -0
  15. data/lib/transcriptic/core_ext/string.rb +8 -0
  16. data/lib/transcriptic/dependencies_generator.rb +13 -0
  17. data/lib/transcriptic/errors.rb +32 -0
  18. data/lib/transcriptic/labfile.rb +73 -0
  19. data/lib/transcriptic/project_generator.rb +56 -0
  20. data/lib/transcriptic/sbt.rb +58 -0
  21. data/lib/transcriptic/templates/LICENSE.erb +20 -0
  22. data/lib/transcriptic/templates/Labfile.erb +12 -0
  23. data/lib/transcriptic/templates/README.erb +3 -0
  24. data/lib/transcriptic/templates/app/Main.erb +11 -0
  25. data/lib/transcriptic/templates/project/Build.erb +59 -0
  26. data/lib/transcriptic/templates/project/Dependencies.erb +10 -0
  27. data/lib/transcriptic/templates/project/build.properties +1 -0
  28. data/lib/transcriptic/templates/project/plugins.sbt +5 -0
  29. data/lib/transcriptic/templates/sbt +1 -0
  30. data/lib/transcriptic/{helpers.rb → ui.rb} +124 -109
  31. data/lib/transcriptic/version.rb +2 -1
  32. data/lib/vendor/{transcriptic/okjson.rb → okjson.rb} +0 -0
  33. metadata +203 -46
  34. data/lib/transcriptic/command.rb +0 -233
  35. data/lib/transcriptic/command/base.rb +0 -157
  36. data/lib/transcriptic/command/console.rb +0 -10
  37. data/lib/transcriptic/command/data.rb +0 -29
  38. data/lib/transcriptic/command/help.rb +0 -124
  39. data/lib/transcriptic/command/login.rb +0 -35
  40. data/lib/transcriptic/command/run.rb +0 -108
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee17a7a6a96eb5b4e97c7162815443cfca424bec
4
+ data.tar.gz: addfe85a94f4b2856ef5f7ac2ac1f72435801ed9
5
+ SHA512:
6
+ metadata.gz: 350b2fdd82bd58ed2fe9427560a5b89b0fc9fcb70a55d1198c9882c06cf833321a2213f7d6d06d09da6ec00386a23af7b87a8a1d20fbe0b9cd8cd277eac3756d
7
+ data.tar.gz: bcd5b9f30c299b61098115c54a017963bb2cccf921bddf121336e21c19405f21a6d110f9fb797a134bce9931f601694d2618ea9e047a31ee5190847d73d65602
data/bin/transcriptic CHANGED
@@ -3,10 +3,8 @@
3
3
  # resolve bin path, ignoring symlinks
4
4
  require "pathname"
5
5
  bin_file = Pathname.new(__FILE__).realpath
6
-
7
- # add self to libpath
8
6
  $:.unshift File.expand_path("../../lib", bin_file)
9
7
 
10
8
  # start up the CLI
11
- require "transcriptic/cli"
12
- Transcriptic::CLI.start(*ARGV)
9
+ require "transcriptic"
10
+ Transcriptic::CLI::Base.start(ARGV)
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/monkies/*.rb"].sort.each do |path|
2
+ require "thor/monkies/#{File.basename(path, '.rb')}"
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'transcriptic/ui'
2
+
3
+ Thor::Base.shell.send(:include, Transcriptic::UI)
data/lib/transcriptic.rb CHANGED
@@ -1,3 +1,87 @@
1
- module Transcriptic; end
1
+ require 'digest'
2
+ require 'forwardable'
3
+ require 'hashie'
4
+ require 'json'
5
+ require 'pathname'
6
+ require 'solve'
7
+ require 'thor'
8
+ require 'tmpdir'
9
+ require 'uri'
10
+ require 'zlib'
11
+ require 'celluloid'
12
+ require 'active_support/core_ext'
13
+ require 'chozo/core_ext'
14
+ require 'rexml/document'
15
+ require 'rest-client'
16
+ require 'uri'
17
+ require 'net/http'
18
+ require 'time'
2
19
 
3
- require "transcriptic/client"
20
+ require 'vendor/okjson'
21
+
22
+ require 'transcriptic/version'
23
+ require 'transcriptic/core_ext'
24
+ require 'transcriptic/errors'
25
+ require 'thor/monkies'
26
+
27
+ module Transcriptic
28
+ class << self
29
+ attr_accessor :ui
30
+
31
+ def root
32
+ @root ||= Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
33
+ end
34
+
35
+ def find_labfile(path = Dir.pwd)
36
+ path = Pathname.new(path)
37
+ path.ascend do |potential_root|
38
+ if potential_root.entries.collect(&:to_s).include?('Labfile')
39
+ return potential_root.join('Labfile')
40
+ end
41
+ end
42
+ end
43
+
44
+ def home_directory
45
+ running_on_windows? ? ENV['USERPROFILE'].gsub("\\","/") : ENV['HOME']
46
+ end
47
+
48
+ def running_on_windows?
49
+ RUBY_PLATFORM =~ /mswin32|mingw32/
50
+ end
51
+
52
+ def running_on_a_mac?
53
+ RUBY_PLATFORM =~ /-darwin\d/
54
+ end
55
+
56
+ def transcriptic_path
57
+ ENV['TRANSCRIPTIC_PATH'] || File.expand_path('~/.transcriptic')
58
+ end
59
+
60
+ def ui
61
+ @ui ||= Thor::Base.shell.new
62
+ end
63
+
64
+ def logger
65
+ Celluloid.logger
66
+ end
67
+
68
+ def tmp_dir
69
+ File.join(transcriptic_path, 'tmp')
70
+ end
71
+
72
+ def mktmpdir
73
+ FileUtils.mkdir_p(tmp_dir)
74
+ Dir.mktmpdir(nil, tmp_dir)
75
+ end
76
+
77
+ end
78
+ end
79
+
80
+
81
+ require 'transcriptic/auth'
82
+ require 'transcriptic/labfile'
83
+ require 'transcriptic/project_generator'
84
+ require 'transcriptic/dependencies_generator'
85
+ require 'transcriptic/client'
86
+ require 'transcriptic/sbt'
87
+ require 'transcriptic/cli'
@@ -1,7 +1,3 @@
1
- require "transcriptic"
2
- require "transcriptic/client"
3
- require "transcriptic/helpers"
4
-
5
1
  class Transcriptic::Auth
6
2
  class << self
7
3
  attr_accessor :credentials
@@ -28,8 +24,6 @@ class Transcriptic::Auth
28
24
  @client = nil
29
25
  end
30
26
 
31
- include Transcriptic::Helpers
32
-
33
27
  # just a stub; will raise if not authenticated
34
28
  def check
35
29
  client.list
@@ -59,9 +53,9 @@ class Transcriptic::Auth
59
53
 
60
54
  def credentials_file
61
55
  if host == default_host
62
- "#{home_directory}/.transcriptic/credentials"
56
+ "#{Transcriptic.home_directory}/.transcriptic/credentials"
63
57
  else
64
- "#{home_directory}/.transcriptic/credentials.#{host}"
58
+ "#{Transcriptic.home_directory}/.transcriptic/credentials.#{host}"
65
59
  end
66
60
  end
67
61
 
@@ -138,61 +132,6 @@ class Transcriptic::Auth
138
132
  delete_credentials
139
133
  raise e
140
134
  end
141
- check_for_associated_ssh_key unless Transcriptic::Command.current_command == "keys:add"
142
- end
143
-
144
- def check_for_associated_ssh_key
145
- return unless client.get_keys.length.zero?
146
- associate_or_generate_ssh_key
147
- end
148
-
149
- def associate_or_generate_ssh_key
150
- public_keys = available_ssh_public_keys.sort
151
-
152
- case public_keys.length
153
- when 0 then
154
- display "Could not find an existing public key."
155
- display "Would you like to generate one? [Yn] ", false
156
- unless ask.strip.downcase == "n"
157
- display "Generating new SSH public key."
158
- generate_ssh_key("id_rsa")
159
- associate_key("#{home_directory}/.ssh/id_rsa.pub")
160
- end
161
- when 1 then
162
- display "Found existing public key: #{public_keys.first}"
163
- associate_key(public_keys.first)
164
- else
165
- display "Found the following SSH public keys:"
166
- public_keys.each_with_index do |key, index|
167
- display "#{index+1}) #{File.basename(key)}"
168
- end
169
- display "Which would you like to use with your Transcriptic account? ", false
170
- chosen = public_keys[ask.to_i-1] rescue error("Invalid choice")
171
- associate_key(chosen)
172
- end
173
- end
174
-
175
- def generate_ssh_key(keyfile)
176
- ssh_dir = File.join(home_directory, ".ssh")
177
- unless File.exists?(ssh_dir)
178
- FileUtils.mkdir_p ssh_dir
179
- File.chmod(0700, ssh_dir)
180
- end
181
- `ssh-keygen -t rsa -N "" -f \"#{home_directory}/.ssh/#{keyfile}\" 2>&1`
182
- end
183
-
184
- def associate_key(key)
185
- display "Uploading ssh public key #{key}"
186
- client.add_key(File.read(key)).inspect
187
- end
188
-
189
- def available_ssh_public_keys
190
- keys = [
191
- "#{home_directory}/.ssh/id_rsa.pub",
192
- "#{home_directory}/.ssh/id_dsa.pub"
193
- ]
194
- keys.concat(Dir["#{home_directory}/.ssh/*.pub"])
195
- keys.select { |d| File.exists?(d) }.uniq
196
135
  end
197
136
 
198
137
  def retry_login?
@@ -0,0 +1,25 @@
1
+ require 'thor/group'
2
+
3
+ module Transcriptic
4
+ class BaseGenerator < Thor::Group
5
+ class << self
6
+ def source_root
7
+ Transcriptic.root.join('lib/transcriptic/templates')
8
+ end
9
+ end
10
+
11
+ shell = Transcriptic.ui
12
+
13
+ argument :path,
14
+ type: :string,
15
+ required: true
16
+
17
+ include Thor::Actions
18
+
19
+ private
20
+
21
+ def target
22
+ @target ||= Pathname.new(File.expand_path(path))
23
+ end
24
+ end
25
+ end
@@ -1,12 +1,203 @@
1
- require "transcriptic"
2
- require "transcriptic/command"
1
+ module Transcriptic
2
+ module CLI
3
+ class Base < Thor
4
+ include Transcriptic::UI
3
5
 
4
- class Transcriptic::CLI
6
+ class << self
7
+ def dispatch(meth, given_args, given_opts, config)
8
+ unless (given_args & ['-h', '--help']).empty?
9
+ if given_args.length == 1
10
+ # transcriptic --help
11
+ super
12
+ else
13
+ command = given_args.first
14
+ super(meth, ['help', command].compact, nil, config)
15
+ end
16
+ else
17
+ super
18
+ end
19
+ end
20
+ end
5
21
 
6
- def self.start(*args)
7
- command = args.shift.strip rescue "help"
8
- Transcriptic::Command.load
9
- Transcriptic::Command.run(command, args)
10
- end
22
+ def initialize(*args)
23
+ super(*args)
24
+
25
+ Transcriptic.logger.level = ::Logger::INFO
26
+
27
+ if @options[:debug]
28
+ Transcriptic.logger.level = ::Logger::DEBUG
29
+ end
30
+
31
+ if @options[:quiet]
32
+ Transcriptic.ui.mute!
33
+ end
34
+
35
+ @options = options.dup # unfreeze frozen options Hash from Thor
36
+ end
37
+
38
+ desc "login", "Log in with your Transcriptic account"
39
+ def login
40
+ Transcriptic::Auth.login
41
+ say "Authentication successful."
42
+ end
43
+
44
+ desc "logout", "Clear local authentication credentials"
45
+ def logout
46
+ Transcriptic::Auth.logout
47
+ say "Local credentials cleared."
48
+ end
49
+
50
+ desc "token", "Display your API token"
51
+ def token
52
+ say Transcriptic::Auth.api_key
53
+ end
54
+
55
+ desc "new NAME", "Generate a new project"
56
+ method_option :package,
57
+ type: :string,
58
+ desc: "Package name (example: edu.stanford.professorname.projectname)"
59
+ method_option :email,
60
+ type: :string,
61
+ desc: 'Email address of project author'
62
+ method_option :author,
63
+ type: :string,
64
+ desc: 'Name of project author'
65
+ method_option :description,
66
+ type: :string,
67
+ desc: 'Brief one-line description of the project'
68
+ def new(name)
69
+ Transcriptic::ProjectGenerator.new([File.join(Dir.pwd, name), name], options).invoke_all
70
+ end
71
+
72
+ desc "logs RUNID", "Get log data from a run"
73
+ def logs(run_id)
74
+ transcriptic.read_logs(run_id)
75
+ end
76
+
77
+ desc "status RUNID", "Show status for a given run ID"
78
+ def status(run_id)
79
+ ret = transcriptic.status(run_id)
80
+ if ret.nil?
81
+ error "#{run_id} not found for #{transcriptic.user}"
82
+ end
83
+ say(ret.inspect)
84
+ end
11
85
 
86
+ desc "list", "List your in-flight run IDs"
87
+ def list
88
+ ret = transcriptic.list
89
+ if ret.empty?
90
+ say "No runs for #{transcriptic.user}"
91
+ return
92
+ end
93
+ say("Runs:")
94
+ ret.each do |run|
95
+ say " #{run.name}"
96
+ end
97
+ end
98
+
99
+ desc "update", "Update the project's dependencies"
100
+ def update
101
+ require_labfile!
102
+ output_with_arrow "Updating dependencies..."
103
+ labfile = Transcriptic::Labfile.from_file(Transcriptic.find_labfile)
104
+ Transcriptic::DependenciesGenerator.new([Dir.pwd, labfile.dependencies], options).invoke_all
105
+ end
106
+
107
+ desc "compile", "Compile the project"
108
+ def compile
109
+ require_labfile!
110
+ update
111
+ Transcriptic::SBT.compile
112
+ end
113
+
114
+ desc "analyze OBJECTPATH", "Analyze a protocol. Object path is of the form edu.foo.bar where bar is the name of your Protocol object."
115
+ method_options :raw => :boolean, :iterations => :integer
116
+ def analyze(object_path)
117
+ raw = options.raw ? "--raw" : ""
118
+ iterations = options.iterations ? options.iterations : 5
119
+ require_labfile!
120
+ update
121
+ Transcriptic::SBT.stage
122
+ data = `target/start #{object_path} --verify #{raw} --iterations #{iterations}`
123
+ if not options.raw
124
+ json = json_decode(data)
125
+ output_with_arrow "Verification successful for #{object_path}"
126
+ output_with_indent "Expected cost: $#{json["price_avg"]}, maximum observed cost: $#{json["price_max"]}"
127
+ else
128
+ say data
129
+ end
130
+ end
131
+
132
+ desc "publish", "Packages up the current project and uploads it to the Autoprotocol central repository"
133
+ def publish
134
+ labfile = require_labfile!
135
+ if compile
136
+ dependencies = labfile.dependencies.map {|d| "#{d[:group]}.#{d[:name]}/#{d[:version]}" }.join(", ")
137
+ output_with_arrow "Preparing to publish..."
138
+ output_with_arrow "Project name: #{labfile.options[:name]}, Author: #{labfile.options[:author]}, Email: #{labfile.options[:email]}"
139
+ if labfile.options[:description]
140
+ output_with_arrow "Description: #{labfile.options[:description]}"
141
+ else
142
+ display format_with_bang("Warning: No description provided.")
143
+ end
144
+ if labfile.dependencies.length > 0
145
+ output_with_arrow "Dependencies: #{dependencies}}"
146
+ end
147
+ confirm(format_with_bang("Are you sure you want to publish version #{labfile.options[:version]} of this project? (y/N)"))
148
+ output_with_arrow "Not yet available!"
149
+ end
150
+ end
151
+
152
+ desc "launch OBJECTPATH", "Packages up the current project, uploads it to Transcriptic, and starts the protocol object at OBJECTPATH running."
153
+ def launch(object_path)
154
+ require_labfile!
155
+ output_with_arrow "Not yet available!"
156
+ return
157
+
158
+ fd = create_protocol_fd_for_path(path)
159
+ if 1 == fd
160
+ Transcriptic.ui.error_with_failure "Couldn't packaged protocol filename or directory!"
161
+ end
162
+ if args.empty?
163
+ project_id = "default"
164
+ else
165
+ project_id = args.shift
166
+ end
167
+ run = action("Uploading `#{path}`") {
168
+ transcriptic.create_run(fd, project_id)
169
+ }
170
+
171
+ if run["success"]
172
+ Transcriptic.ui.output_with_arrow "Protocol received: #{run["protocol_format"]} detected"
173
+ Transcriptic.ui.output_with_arrow "Protocol received: #{run["nsteps"]} steps, expected cost: #{run["exp_cost"]}, total possible cost: #{run["max_cost"]}"
174
+ Transcriptic.ui.output_with_arrow "Protocol received: expected runtime: #{run["exp_time"]}, total possible runtime: #{run["max_time"]}"
175
+ if Transcriptic.ui.confirm_quote
176
+ Transcriptic.ui.display
177
+ Transcriptic.ui.action("Launching") {
178
+ transcriptic.launch_run(run["run_id"])
179
+ }
180
+ Transcriptic.ui.output_with_arrow "Protocol run launched. ID: #{run["run_id"]}"
181
+ Transcriptic.ui.output_with_arrow "Monitor at: https://secure.transcriptic.com/#{run["organization_id"]}/#{run["project_id"]}/runs/#{run["run_id"]}"
182
+ end
183
+ else
184
+ Transcriptic.ui.error_with_failure "Error creating protocol run."
185
+ end
186
+ end
187
+
188
+ private
189
+ def transcriptic
190
+ Transcriptic::Auth.client
191
+ end
192
+
193
+ def require_labfile!
194
+ labfile = Transcriptic.find_labfile
195
+ if labfile.nil?
196
+ error("Can't find Labfile! You must run this command from within an autoprotocol project directory.")
197
+ end
198
+ Transcriptic::Labfile.from_file(labfile)
199
+ end
200
+
201
+ end
202
+ end
12
203
  end