cnvrg 1.6.0.8 → 1.6.0.9

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: 319b1e08fd56c2a26834b3a2e2fc94565e2abad1d0244c72e4e45c11a8cc7d3d
4
- data.tar.gz: 60edde88d619c8aae0afded8314c2688545712445718e99576a7ec20222d795e
3
+ metadata.gz: 3a578311b787d26b7a510ce7c6ff9b845d55300b82a5c75e70a787e334693779
4
+ data.tar.gz: 7bea7b961282523b23dfbe01014d658147dfa354240246ff4722e165d5603895
5
5
  SHA512:
6
- metadata.gz: 9dc2c22f8c1f4c696c0580f2ab2c3122d57061a95591bff13403a2e93412f6268b50a23119ba5ccbaa0830bd8f87474490be50ccf6d128c378b39d4a1cffaca3
7
- data.tar.gz: 4628fee3352fb89fb639ed3aef3e76ce2cadff9c916d153a940416d25ac81f8e700b2891cca6682c95e9526342c089ef631f2c16d9df9ca84cc4faccaac70e28
6
+ metadata.gz: f8d23528d8fe271b4f4dde1c585b2a0991e8aaf4445a4b33436355caaed5dff153dd72afa1574123de627a894d38ba78157caa79ba77ba4e52f13ba92e0c6c45
7
+ data.tar.gz: 1cfa9cddbd3af489be308bf496f0e4b1079a9a007eafe97cf5255b31187fbb15ab9978797b2a8fbec3b8f4b08c8a74ec042a7088f6e3b799cf0a41e80792c5f3
@@ -30,6 +30,7 @@ module Cnvrg
30
30
  end
31
31
  end
32
32
  def self.request(resource, method = 'GET', data = {}, parse_request = true)
33
+ resource = URI::encode resource
33
34
  begin
34
35
  n = Netrc.read
35
36
  rescue => e
@@ -163,22 +164,25 @@ module Cnvrg
163
164
 
164
165
  # what if windows?
165
166
  # data[:file] = Faraday::UploadIO.new(data[:absolute_path], content_type)
167
+ if not File.exists? data[:relative_path]
166
168
  file_base = File.basename(data[:relative_path])
167
- begin
168
- temp_path = File.expand_path('~')+"/.cnvrg/tmp_files/#{file_base}"
169
- FileUtils.touch(temp_path)
170
- rescue
171
- temp_path ="/tmp/#{file_base}"
172
- FileUtils.touch(temp_path)
173
- end
174
169
 
170
+ begin
171
+ temp_path = File.expand_path('~')+"/.cnvrg/tmp_files/#{file_base}"
172
+ FileUtils.touch(temp_path)
173
+ rescue
174
+ temp_path ="/tmp/#{file_base}"
175
+ FileUtils.touch(temp_path)
176
+ end
177
+ else
178
+ temp_path = data[:relative_path]
179
+ end
175
180
 
176
181
 
177
- data[:file] = Faraday::UploadIO.new("#{temp_path}", "plain/text")
182
+ data[:file] = Faraday::UploadIO.new("#{temp_path}", "application/tar+gzip")
178
183
 
179
184
  response = conn.post "#{endpoint_uri}/#{resource}", data
180
185
  Cnvrg::API.parse_version(response)
181
-
182
186
  FileUtils.rm_rf(temp_path)
183
187
  if response.to_hash[:status] == 404
184
188
  return false
@@ -41,6 +41,7 @@ require 'cnvrg/org_helpers'
41
41
  require 'cnvrg/cli/subcommand'
42
42
  require 'cnvrg/cli/flow'
43
43
  require 'cnvrg/cli/task'
44
+ require 'cnvrg/cli/library_cli'
44
45
  require 'cnvrg/image_cli'
45
46
  require 'cnvrg/helpers/executer'
46
47
  require 'cnvrg/downloader/client'
@@ -177,6 +178,9 @@ module Cnvrg
177
178
  desc "image [COMMAND]", "build existing images", :hide => true
178
179
  subcommand "image", ImageCli
179
180
 
181
+ desc "library [COMMAND]", "Upload and manage datasets", :hide => false
182
+ subcommand "library", LibraryCli
183
+
180
184
 
181
185
  desc "flow", "mange project flows", :hide => true
182
186
  subcommand "flow", Cnvrg::Commands::Flow
@@ -944,8 +948,7 @@ module Cnvrg
944
948
  Cnvrg::CLI.is_response_success(response,true)
945
949
  dataset_name = response["results"]["name"]
946
950
  dataset_slug = response["results"]["slug"]
947
- # dataset_home = Dir.pwd+"/"+dataset_name
948
- dataset_home = Dir.pwd
951
+ dataset_home = File.join(Dir.pwd, dataset_name)
949
952
 
950
953
  if Dataset.blank_clone(owner, dataset_name, dataset_slug)
951
954
  dataset = Dataset.new(dataset_home)
@@ -1990,6 +1993,7 @@ module Cnvrg
1990
1993
  end
1991
1994
  end
1992
1995
  rescue => e
1996
+ Cnvrg::CLI.log_message(e.message, 'red')
1993
1997
  Cnvrg::Logger.log_error(e)
1994
1998
  say "\nAborting", Thor::Shell::Color::BLUE
1995
1999
  dataset_dir = is_cnvrg_dir(Dir.pwd)
@@ -3124,7 +3128,7 @@ module Cnvrg
3124
3128
  end
3125
3129
  end
3126
3130
  start_time = Time.now
3127
- PTY.spawn(cmd) do |stdout, stdin, pid, stderr|
3131
+ PTY.spawn(@exp.as_env, cmd) do |stdout, stdin, pid, stderr|
3128
3132
  begin
3129
3133
  stdout.each do |line|
3130
3134
  cur_time = Time.now
@@ -3189,7 +3193,7 @@ module Cnvrg
3189
3193
  end
3190
3194
 
3191
3195
  if sync_after
3192
- @project.job_log(["Syncing Experiment"])
3196
+ @exp.job_log(["Syncing Experiment"])
3193
3197
  # Sync after run
3194
3198
  if @project.is_git
3195
3199
  output_dir = output_dir || @exp.output_dir
@@ -3206,7 +3210,7 @@ module Cnvrg
3206
3210
  end
3207
3211
  end_commit = @project.last_local_commit
3208
3212
  if end_commit.present?
3209
- @project.job_log(["Experiment end commit: #{end_commit}"])
3213
+ @exp.job_log(["Experiment end commit: #{end_commit}"])
3210
3214
  end
3211
3215
 
3212
3216
  # log_thread.join
@@ -18,92 +18,149 @@ module Cnvrg
18
18
  end
19
19
  end
20
20
 
21
- desc "task", "Running Flow tasks", :hide => true
22
- subcommand 'task', Cnvrg::Commands::Task
23
-
24
- desc "flow verify", "verify that the flow is well formatted"
25
-
26
- def verify(path)
27
- unless @curr_dir.present?
28
- @cli.log_message("Cant run this command because you are not in project directory", Thor::Color::RED)
29
- return false
30
- end
31
- @flow = Cnvrg::Flows.new(@curr_dir, path)
32
- @cli.log_message("The Flow is Valid", Thor::Color::GREEN)
21
+ desc "flow import --file='flow.yaml'", "Import flow to the web"
22
+ method_option :file, :type => :string, :aliases => ["-f", "--file"]
23
+ def import()
24
+ run_flow_internal(file: options[:file], run: false)
33
25
  end
34
26
 
27
+ desc "flow run --file='flow.yaml'", "Import flow to the web"
28
+ method_option :file, :type => :string, :aliases => ["-f", "--file"]
29
+ def run()
30
+ run_flow_internal(file: options[:file], run: true)
31
+ end
35
32
 
36
- desc "flow run", "run a flow file"
37
- def run(flow_slug)
38
- unless @curr_dir.present?
39
- @cli.log_message("Cant run this command because you are not in project directory", Thor::Color::RED)
40
- return false
33
+ no_commands {
34
+ def run_flow_internal(file: nil, run: false)
35
+ if options[:file].blank?
36
+ Cnvrg::CLI.log_message("Flow title is required for export. please use --title='Flow 1'")
37
+ return
38
+ end
39
+ if not File.exists? options[:file]
40
+ Cnvrg::CLI.log_message("Cant find file in path #{options[:file]}.")
41
+ return
42
+ end
43
+ payload = YAML.safe_load(File.open(file).read)
44
+ @project = Cnvrg::Project.new(Cnvrg::CLI.get_project_home)
45
+ begin
46
+ @flow, version_slug = Flows.create_flow(@project, payload, run: run)
47
+ rescue => e
48
+ Cnvrg::CLI.log_message("Error while validating flow: #{e.message}", 'error')
49
+ return
41
50
  end
42
- @flow = Cnvrg::Flows.new(flow_slug)
43
- resp = @flow.run
44
- flow_version_href = resp["flow_version"]["href"]
45
- Cnvrg::CLI.log_message("Flow Live results: #{flow_version_href}")
46
- true
51
+ Cnvrg::CLI.log_message("New flow version was created successfuly!", 'green')
52
+ Cnvrg::CLI.log_message("you can find the flow in #{@flow.edit_version_href(version_slug)}", 'green')
53
+ rescue => e
54
+ Cnvrg::CLI.log_message("Failed while creating flow")
55
+ Cnvrg::Logger.log_error(e)
47
56
  end
57
+ }
48
58
 
49
- desc "flow create", "create a flow file"
50
-
51
- def create
52
- title = ask("Flow Title: ")
53
- title = title.presence || "cnvrg-flow"
54
- relations = []
55
- task = ask_for_relation
56
- while task.compact.size == 2
57
- from, to = task
58
- relations << {from: from, to: to}
59
- task = ask_for_relation
59
+ desc "flow export --file='flow.yaml' --title='Flow 1' --version='version 1'", "Export flow to the web"
60
+ method_option :file, :type => :string, :aliases => ["-f", "--file"]
61
+ method_option :title, :type => :string, :aliases => ["-t", "--title"]
62
+ method_option :version, :type => :string, :aliases => ["-v", "--version"], :default => "latest"
63
+ def export()
64
+ if options[:title].blank?
65
+ Cnvrg::CLI.log_message("Flow title is required for export. please use --title='Flow 1'", "red")
66
+ return
60
67
  end
61
- start_commit = ask("Flow Starting Commit (empty will set this value to 'latest')")
62
- Cnvrg::Flows.create_flow("#{title}.flow.yaml", {title: title, relations: relations, start_commit: start_commit})
63
- end
64
68
 
69
+ @project = Cnvrg::Project.new(Cnvrg::CLI.get_project_home)
70
+ @flow = Flows.new(options[:title], project: @project)
71
+ filename = @flow.export(options[:version], file: options[:file])
72
+ Cnvrg::CLI.log_message("Flow was saved successfuly to: #{filename}", 'green')
73
+ rescue => e
74
+ Cnvrg::CLI.log_message(e.message, 'red')
75
+ Cnvrg::Logger.log_error(e)
76
+ end
65
77
 
66
- # desc "flow resolve", "Resolve flow parameters"
67
- # def resolve(path)
68
- # @hyper = Cnvrg::Hyper.new(@curr_dir, path)
69
- # @hyper.resolve_params
78
+ # desc "task", "Running Flow tasks", :hide => true
79
+ # subcommand 'task', Cnvrg::Commands::Task
80
+ #
81
+ # desc "flow verify", "verify that the flow is well formatted"
82
+ #
83
+ # def verify(path)
84
+ # unless @curr_dir.present?
85
+ # @cli.log_message("Cant run this command because you are not in project directory", Thor::Color::RED)
86
+ # return false
87
+ # end
88
+ # @flow = Cnvrg::Flows.new(@curr_dir, path)
89
+ # @cli.log_message("The Flow is Valid", Thor::Color::GREEN)
70
90
  # end
71
91
  #
72
-
73
- private
74
-
75
- def init_tasks
76
- @tasks = Dir.glob("**/*.task*")
77
- end
78
-
79
- def ask_for_relation
80
- init_tasks if @tasks.blank?
81
- to = nil
82
- from = ask_for_task("Task To Start From: [#{@tasks.join(', ')}]")
83
- to = ask_for_task("Task To Go To: [#{@tasks.join(', ')}]") if from.present?
84
- [from, to]
85
- end
86
-
87
- def ask_for_task(text)
88
- verified = false
89
- task = nil
90
- while !verified
91
- task = ask(text)
92
- if task.blank?
93
- return nil
94
- end
95
- begin
96
- Cnvrg::Task.new(@curr_dir, path: task).verify_task
97
- verified = true
98
- rescue => e
99
- end
100
- end
101
- task
102
- end
103
-
104
- def get_all_tasks
105
- @tasks = Dir.glob("*/**.task.yaml")
106
- end
107
- end
92
+ #
93
+ # desc "flow run", "run a flow file"
94
+ # def run(flow_slug)
95
+ # unless @curr_dir.present?
96
+ # @cli.log_message("Cant run this command because you are not in project directory", Thor::Color::RED)
97
+ # return false
98
+ # end
99
+ # @flow = Cnvrg::Flows.new(flow_slug)
100
+ # resp = @flow.run
101
+ # flow_version_href = resp["flow_version"]["href"]
102
+ # Cnvrg::CLI.log_message("Flow Live results: #{flow_version_href}")
103
+ # true
104
+ # end
105
+ #
106
+ # desc "flow create", "create a flow file"
107
+ #
108
+ # def create
109
+ # title = ask("Flow Title: ")
110
+ # title = title.presence || "cnvrg-flow"
111
+ # relations = []
112
+ # task = ask_for_relation
113
+ # while task.compact.size == 2
114
+ # from, to = task
115
+ # relations << {from: from, to: to}
116
+ # task = ask_for_relation
117
+ # end
118
+ # start_commit = ask("Flow Starting Commit (empty will set this value to 'latest')")
119
+ # Cnvrg::Flows.create_flow("#{title}.flow.yaml", {title: title, relations: relations, start_commit: start_commit})
120
+ # end
121
+ #
122
+ #
123
+ # # desc "flow resolve", "Resolve flow parameters"
124
+ # # def resolve(path)
125
+ # # @hyper = Cnvrg::Hyper.new(@curr_dir, path)
126
+ # # @hyper.resolve_params
127
+ # # end
128
+ # #
129
+ #
130
+ # private
131
+ #
132
+ # def init_tasks
133
+ # @tasks = Dir.glob("**/*.task*")
134
+ # end
135
+ #
136
+ # def ask_for_relation
137
+ # init_tasks if @tasks.blank?
138
+ # to = nil
139
+ # from = ask_for_task("Task To Start From: [#{@tasks.join(', ')}]")
140
+ # to = ask_for_task("Task To Go To: [#{@tasks.join(', ')}]") if from.present?
141
+ # [from, to]
142
+ # end
143
+ #
144
+ # def ask_for_task(text)
145
+ # verified = false
146
+ # task = nil
147
+ # while !verified
148
+ # task = ask(text)
149
+ # if task.blank?
150
+ # return nil
151
+ # end
152
+ # begin
153
+ # Cnvrg::Task.new(@curr_dir, path: task).verify_task
154
+ # verified = true
155
+ # rescue => e
156
+ # end
157
+ # end
158
+ # task
159
+ # end
160
+ #
161
+ # def get_all_tasks
162
+ # @tasks = Dir.glob("*/**.task.yaml")
163
+ # end
108
164
  end
109
- end
165
+ end
166
+ end
@@ -0,0 +1,33 @@
1
+ module Cnvrg
2
+ class LibraryCli < SubCommandBase
3
+
4
+ desc "library import", description: ""
5
+ def import
6
+ unless File.exists? "library.yml"
7
+ Cnvrg::CLI.log_message("Can't find library.yml", 'red')
8
+ exit(1)
9
+ end
10
+ library = YAML.safe_load(File.open("library.yml").read)
11
+ Cnvrg::CLI.log_message("Archiving library #{library["title"]}")
12
+ files = Dir["**/*"].select{|file| not File.directory?(file)}
13
+ File.open("archive.tar.gz", "wb") do |file|
14
+ Zlib::GzipWriter.wrap(file) do |gzip|
15
+ Gem::Package::TarWriter.new(gzip) do |tar|
16
+ files.each do |filename|
17
+ f = File.open(filename)
18
+ tar.add_file_simple(filename, 0644, f.size) do |io|
19
+ io.write(f.read)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ response = Cnvrg::API.request(['users', Cnvrg::CLI.get_owner, 'libraries'].join("/"), "POST_FILE", {relative_path: "archive.tar.gz"})
26
+ if response["status"] != 200
27
+ Cnvrg::CLI.log_message("Can't create library: #{response["message"]}")
28
+ exit(1)
29
+ end
30
+ Cnvrg::CLI.log_message("Library Created successfuly", "green")
31
+ end
32
+ end
33
+ end
@@ -518,6 +518,9 @@ module Cnvrg
518
518
  #check if prefix exists do prefix/path otherwise path
519
519
  label = file.gsub(self.local_path + "/", "")
520
520
  label = "#{prefix}/#{label}" if prefix.present?
521
+ if not Cnvrg::Files.valid_file_name?(label)
522
+ raise StandardError.new("#{label} is not a valid file name.")
523
+ end
521
524
  if File.directory? file
522
525
  tree[label + "/"] = nil
523
526
  else
@@ -16,6 +16,15 @@ module Cnvrg
16
16
  @output_dir = nil
17
17
  end
18
18
 
19
+ def as_env
20
+ return {
21
+ CNVRG_JOB_ID: @slug,
22
+ CNVRG_JOB_TYPE: "Experiment",
23
+ CNVRG_PROJECT: @project_slug,
24
+ CNVRG_OWNER: @owner,
25
+ }.as_json
26
+ end
27
+
19
28
  def start(input, platform, machine_name, start_commit, name, email_notification, machine_activity,script_path,
20
29
  sync_before_terminate, periodic_sync)
21
30
 
@@ -88,6 +97,14 @@ module Cnvrg
88
97
 
89
98
  end
90
99
 
100
+ def job_log(logs, level: 'info', step: nil, job_type: nil, job_id: nil)
101
+ logs = [logs].flatten
102
+ logs.each_slice(10).each do |temp_logs|
103
+ Cnvrg::API.request("users/#{@owner}/projects/#{@project_slug}/jobs/experiment/#{@slug}/log", "POST", {job_type: "Experiment", job_id: @slug, logs: temp_logs, log_level: level, step: step, timestamp: Time.now})
104
+ sleep(1)
105
+ end
106
+ end
107
+
91
108
  def exec_remote(command, commit_to_run, instance_type, image_slug,schedule,local_timestamp, grid,path_to_cmd,data, data_commit,periodic_sync,
92
109
  sync_before_terminate, max_time, ds_sync_options=0,output_dir=nil,data_query=nil,
93
110
  git_commit=nil, git_branch=nil, restart_if_stuck=nil, local_folders=nil,title=nil, datasets=nil, prerun: true, requirements: true, recurring: nil)
@@ -6,7 +6,7 @@ require 'net/http'
6
6
  require 'cnvrg/result'
7
7
  module Cnvrg
8
8
  class Files
9
-
9
+ VALID_FILE_NAME = /[\x00\\:\*\?\"<>\|]/
10
10
  LARGE_FILE=1024*1024*5
11
11
  MULTIPART_SPLIT=10000000
12
12
 
@@ -29,6 +29,11 @@ module Cnvrg
29
29
  end
30
30
 
31
31
 
32
+ def self.valid_file_name?(fullpath)
33
+ VALID_FILE_NAME.match(fullpath).blank?
34
+ end
35
+
36
+
32
37
  def download_commit(sha1)
33
38
  response = @project.clone(false, sha1)
34
39
  log_error("Cant download commit #{sha1}") unless Cnvrg::CLI.is_response_success response, false
@@ -1,19 +1,71 @@
1
1
  module Cnvrg
2
2
  class Flows
3
- def initialize(flow_slug)
4
- @project = Cnvrg::Project.new(Cnvrg::CLI.get_project_home)
5
- @flow_slug = flow_slug
3
+ def initialize(flow_slug, project: nil)
4
+ @project = project || Cnvrg::Project.new(Cnvrg::CLI.get_project_home)
5
+ @flow_info= Flows.resolve_flow_title(flow_slug, project)
6
+ @slug = @flow_info["slug"]
6
7
  @tasks = {}
7
8
  @relations = {}
8
9
  @title = nil
9
- @slug = nil
10
- @base_resource = @project.base_resource + "flows"
11
-
10
+ @base_resource = @project.base_resource + "flows/#{@slug}"
11
+ @public_url = "#{@project.url}/flows/#{@slug}"
12
12
  # self.reload_flow
13
13
  end
14
14
 
15
- def self.create_flow(path, flow)
16
- File.open(path, "w"){|file| file.write flow.to_yaml}
15
+ def self.resolve_flow_title(title, project)
16
+ resp = Cnvrg::API.request("#{project.base_resource}/flows", 'GET')
17
+ if resp.blank?
18
+ raise StandardError.new("Can't resolve flow")
19
+ end
20
+ res = resp["result"].find{|flow| flow["slug"].downcase == title.downcase}
21
+ res ||= resp["result"].find{|flow| flow["title"].downcase == title.downcase}
22
+ if res.blank?
23
+ raise StandardError.new("Can't find flow with title #{title}")
24
+ end
25
+ res
26
+ end
27
+
28
+ def edit_href
29
+ "#{@public_url}/flow_versions/new"
30
+ end
31
+
32
+ def edit_version_href(version)
33
+ return "#{edit_href}?flow_version_slug=#{version}"
34
+ end
35
+
36
+ def version_href(version=nil)
37
+ "#{@base_resource}/flow_versions/#{version || 'latest'}"
38
+ end
39
+
40
+ def export(version, file: nil)
41
+ resp = Cnvrg::API.request(version_href(version), 'GET')
42
+ if resp["status"] != 200
43
+ raise StandardError.new("Cant find flow version: #{version} for flow: #{@slug}")
44
+ end
45
+ flow_version = resp["flow_version"]
46
+ api_recipe = flow_version["api_recipe"]
47
+ file = file.presence || "flow-#{@slug.downcase.gsub("\s", "_")}.yml"
48
+ File.open(file, "w"){|f| f.write api_recipe.to_yaml}
49
+ file
50
+ end
51
+
52
+ def get_version(version)
53
+
54
+
55
+ end
56
+
57
+ def self.create_flow(project, recipe, run: false)
58
+ url = "#{project.base_resource}flows"
59
+ if run
60
+ url += "/run"
61
+ end
62
+ resp = Cnvrg::API.request(url, 'POST', {flow_version: recipe.to_json}) || {}
63
+ if resp["status"] == 200
64
+ return [Flows.new(resp["flow_version"]["flow_id"], project: project), resp["flow_version"]["id"]]
65
+ elsif resp["status"] == 400
66
+ raise StandardError.new(resp["message"])
67
+ end
68
+ raise StandardError.new("Can't create new flow")
17
69
  end
18
70
 
19
71
  def get_flow
@@ -52,11 +104,11 @@ module Cnvrg
52
104
 
53
105
 
54
106
  def run
55
- resp = Cnvrg::API.request("#{@base_resource}/#{@flow_slug}/run", 'POST')
107
+ resp = Cnvrg::API.request("#{@base_resource}/#{@slug}/run", 'POST')
56
108
  if Cnvrg::CLI.is_response_success(resp)
57
109
  return resp
58
110
  end
59
- Cnvrg::CLI.log_message("Cant run flow #{@flow_slug}")
111
+ Cnvrg::CLI.log_message("Cant run flow #{@slug}")
60
112
  end
61
113
 
62
114
  ### in use for yaml file
@@ -428,7 +428,9 @@ module Cnvrg
428
428
  # list.each do |e|
429
429
  Parallel.map(list, in_threads: IDXParallelThreads) do |e|
430
430
  label = e.gsub(self.local_path + "/", "")
431
-
431
+ if not Cnvrg::Files.valid_file_name?(label)
432
+ raise StandardError.new("#{label} is not a valid file name")
433
+ end
432
434
  if list_ignore_new.include? label
433
435
  next
434
436
  end
@@ -1,4 +1,4 @@
1
1
  module Cnvrg
2
- VERSION = '1.6.0.8'
2
+ VERSION = '1.6.0.9'
3
3
  end
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cnvrg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0.8
4
+ version: 1.6.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yochay Ettun
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-12-01 00:00:00.000000000 Z
13
+ date: 2019-12-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -430,6 +430,7 @@ files:
430
430
  - lib/cnvrg/auth.rb
431
431
  - lib/cnvrg/cli.rb
432
432
  - lib/cnvrg/cli/flow.rb
433
+ - lib/cnvrg/cli/library_cli.rb
433
434
  - lib/cnvrg/cli/subcommand.rb
434
435
  - lib/cnvrg/cli/task.rb
435
436
  - lib/cnvrg/colors.rb