cnvrg 0.7.7 → 0.7.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/cnvrg.gemspec +1 -7
- data/lib/cnvrg/api.rb +15 -1
- data/lib/cnvrg/cli.rb +286 -722
- data/lib/cnvrg/cli/flow.rb +116 -0
- data/lib/cnvrg/cli/subcommand.rb +26 -0
- data/lib/cnvrg/cli/task.rb +116 -0
- data/lib/cnvrg/data.rb +0 -1
- data/lib/cnvrg/datafiles.rb +55 -35
- data/lib/cnvrg/dataset.rb +50 -9
- data/lib/cnvrg/files.rb +263 -76
- data/lib/cnvrg/flow.rb +75 -0
- data/lib/cnvrg/helpers.rb +54 -0
- data/lib/cnvrg/hyper.rb +21 -0
- data/lib/cnvrg/logger.rb +102 -0
- data/lib/cnvrg/project.rb +86 -19
- data/lib/cnvrg/task.rb +165 -0
- data/lib/cnvrg/version.rb +2 -1
- metadata +9 -2
data/lib/cnvrg/files.rb
CHANGED
@@ -16,7 +16,121 @@ module Cnvrg
|
|
16
16
|
@project_slug = project_slug
|
17
17
|
@owner = owner
|
18
18
|
@base_resource = "users/#{owner}/projects/#{project_slug}/"
|
19
|
-
@project_home = project_home
|
19
|
+
@project_home = project_home.presence || Cnvrg::CLI.get_project_home
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_upload_options(number_of_items: 0, progress: false)
|
23
|
+
options = {
|
24
|
+
in_processes: Cnvrg::CLI::ParallelProcesses,
|
25
|
+
in_thread: Cnvrg::CLI::ParallelThreads,
|
26
|
+
isolation: true
|
27
|
+
}
|
28
|
+
if progress
|
29
|
+
options[:progress] = {
|
30
|
+
:title => "Upload Progress",
|
31
|
+
:progress_mark => '=',
|
32
|
+
:format => "%b>>%i| %p%% %t",
|
33
|
+
:starting_at => 0,
|
34
|
+
:total => number_of_items,
|
35
|
+
:autofinish => true
|
36
|
+
}
|
37
|
+
end
|
38
|
+
options
|
39
|
+
end
|
40
|
+
|
41
|
+
def upload_files_old(files_list, commit_sha1, progress: nil)
|
42
|
+
Parallel.map(files_list) do |file|
|
43
|
+
Cnvrg::Helpers.try_until_success{self.upload_file("#{@project_home}/#{file}", file, commit_sha1)}
|
44
|
+
progress.progress += 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def upload_multiple_files(files_list, commit_sha1, progress: nil)
|
49
|
+
#open files on the server.
|
50
|
+
Cnvrg::Logger.log_info("Uploading project files")
|
51
|
+
return if files_list.blank?
|
52
|
+
if Cnvrg::Helpers.server_version < 1
|
53
|
+
return self.upload_files_old(files_list, commit_sha1, progress: progress)
|
54
|
+
end
|
55
|
+
files_list = files_list.map{|x| [x,self.parse_file(x)]}.to_h
|
56
|
+
resp = Cnvrg::API.request(@base_resource + "upload_files", 'POST', {files: files_list, commit: commit_sha1})
|
57
|
+
unless Cnvrg::CLI.is_response_success(resp, false)
|
58
|
+
raise Exception.new("Cant upload files to the server.")
|
59
|
+
end
|
60
|
+
|
61
|
+
# resolve bucket
|
62
|
+
res = resp['result']
|
63
|
+
files = res['files']
|
64
|
+
props = Cnvrg::Helpers.get_s3_props(res)
|
65
|
+
client = props[:client]
|
66
|
+
bucket = props[:bucket]
|
67
|
+
upload_options = props[:upload_options]
|
68
|
+
s3_bucket = Aws::S3::Resource.new(client: client).bucket(bucket)
|
69
|
+
#upload files
|
70
|
+
files.keys.map do |file|
|
71
|
+
# Parallel.map(files.keys, self.get_upload_options) do |file|
|
72
|
+
resp = Cnvrg::Helpers.try_until_success{self.upload_single_file(files[file].merge(files_list[file]), s3_bucket, options: upload_options)}
|
73
|
+
raise Exception.new("Cant upload #{file}") unless resp
|
74
|
+
progress.progress += 1 if progress.present?
|
75
|
+
end
|
76
|
+
|
77
|
+
#save files on the server.
|
78
|
+
blob_ids = files.values.map {|f| f['bv_id']}
|
79
|
+
resp = Cnvrg::API.request(@base_resource + "upload_files_save", 'POST', {blob_ids: blob_ids, commit: commit_sha1})
|
80
|
+
unless Cnvrg::CLI.is_response_success(resp, false)
|
81
|
+
raise Exception.new("Cant save uploaded files to the server.")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def delete_files_from_server_old(files, commit_sha1)
|
87
|
+
#files are absolute path here.
|
88
|
+
files.each do |file|
|
89
|
+
if file.ends_with? '/'
|
90
|
+
#dir
|
91
|
+
self.delete_dir(file, commit_sha1)
|
92
|
+
else
|
93
|
+
#file
|
94
|
+
self.delete_file(file, commit_sha1)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def delete_files_from_server(files, commit_sha1)
|
100
|
+
#files are absolute path files here. ^^
|
101
|
+
if Cnvrg::Helpers.server_version < 1
|
102
|
+
return self.delete_files_from_server_old(files, commit_sha1)
|
103
|
+
end
|
104
|
+
#convert files to relative path
|
105
|
+
files = files.map{|file| file.gsub(/^#{@project_home + "/"}/, "")}
|
106
|
+
return if files.blank?
|
107
|
+
resp = Cnvrg::API.request(@base_resource + "delete_files", 'DELETE', {files: files, commit: commit_sha1})
|
108
|
+
unless Cnvrg::CLI.is_response_success(resp, false)
|
109
|
+
raise Exception.new("Cant delete the following files from the server.")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def upload_single_file(file, bucket, options: {})
|
114
|
+
path = file['path']
|
115
|
+
absolute_path = file[:absolute_path]
|
116
|
+
resp = bucket.object(path).
|
117
|
+
upload_file(absolute_path, options)
|
118
|
+
unless resp
|
119
|
+
raise Exception.new("Cant upload #{absolute_path}")
|
120
|
+
end
|
121
|
+
resp
|
122
|
+
end
|
123
|
+
|
124
|
+
def parse_file(file)
|
125
|
+
abs_path = "#{@project_home}/#{file}"
|
126
|
+
return {relative_path: file, absolute_path: abs_path} if file.ends_with? '/'
|
127
|
+
file_name = File.basename(file)
|
128
|
+
file_size = File.size abs_path
|
129
|
+
mime_type = MimeMagic.by_path(abs_path)
|
130
|
+
content_type = !(mime_type.nil? or mime_type.text?) ? mime_type.type : "text/plain"
|
131
|
+
sha1 = OpenSSL::Digest::SHA1.file(abs_path).hexdigest
|
132
|
+
|
133
|
+
{relative_path: file, absolute_path: abs_path, file_name: file_name, file_size: file_size, content_type: content_type, sha1: sha1}
|
20
134
|
end
|
21
135
|
|
22
136
|
def upload_file(absolute_path, relative_path, commit_sha1)
|
@@ -30,24 +144,9 @@ module Cnvrg
|
|
30
144
|
file_size: file_size, file_content_type: content_type, sha1: sha1,
|
31
145
|
new_version:true,only_large:true})
|
32
146
|
|
33
|
-
|
34
147
|
if Cnvrg::CLI.is_response_success(upload_resp, false)
|
35
|
-
|
36
|
-
path = upload_resp["result"]["path"]
|
37
148
|
s3_res = upload_large_files_s3(upload_resp, absolute_path)
|
38
|
-
|
39
|
-
# if file_size.to_f>= Cnvrg::Files::LARGE_FILE.to_f
|
40
|
-
# s3_res = upload_large_files_s3(upload_resp, absolute_path)
|
41
|
-
# else
|
42
|
-
# s3_res = upload_small_files_s3(path, absolute_path, content_type)
|
43
|
-
# end
|
44
149
|
return s3_res
|
45
|
-
# if s3_res
|
46
|
-
# update_s3_resp = Cnvrg::API.request(@base_resource + "update_s3", 'POST', {path: path, commit_id: upload_resp["result"]["commit_id"],
|
47
|
-
# blob_id: upload_resp["result"]["id"]})
|
48
|
-
# is_suc = Cnvrg::CLI.is_response_success(update_s3_resp, false)
|
49
|
-
#
|
50
|
-
# return is_suc
|
51
150
|
end
|
52
151
|
return false
|
53
152
|
|
@@ -248,14 +347,78 @@ module Cnvrg
|
|
248
347
|
end
|
249
348
|
|
250
349
|
rescue => e
|
251
|
-
|
350
|
+
Cnvrg::Logger.log_error(e)
|
252
351
|
return false
|
352
|
+
end
|
353
|
+
|
354
|
+
def resolve_bucket(response)
|
355
|
+
begin
|
356
|
+
sts_path = response["path_sts"]
|
357
|
+
sts_body = self.download_and_read(sts_path)
|
358
|
+
split = sts_body.split("\n")
|
359
|
+
key = split[0]
|
360
|
+
iv = split[1]
|
361
|
+
access = Cnvrg::Helpers.decrypt(key, iv, response["sts_a"])
|
362
|
+
|
363
|
+
secret = Cnvrg::Helpers.decrypt(key, iv, response["sts_s"])
|
364
|
+
|
365
|
+
session = Cnvrg::Helpers.decrypt(key, iv, response["sts_st"])
|
366
|
+
region = Cnvrg::Helpers.decrypt(key, iv, response["region"])
|
367
|
+
|
368
|
+
bucket = Cnvrg::Helpers.decrypt(key, iv, response["bucket"])
|
369
|
+
Cnvrg::Logger.log_info("Resolving bucket #{bucket}, region: #{region}")
|
370
|
+
is_s3 = response["is_s3"]
|
371
|
+
if is_s3 or is_s3.nil?
|
372
|
+
client = Aws::S3::Client.new(
|
373
|
+
:access_key_id => access,
|
374
|
+
:secret_access_key => secret,
|
375
|
+
:session_token => session,
|
376
|
+
:region => region,
|
377
|
+
:use_accelerate_endpoint => true,
|
378
|
+
:http_open_timeout => 60, :retry_limit => 20)
|
379
|
+
else
|
380
|
+
endpoint = Cnvrg::Helpers.decrypt(key, iv, response["endpoint"])
|
381
|
+
client = Aws::S3::Client.new(
|
382
|
+
:access_key_id => access,
|
383
|
+
:secret_access_key => secret,
|
384
|
+
:region => region,
|
385
|
+
:endpoint => endpoint, :force_path_style => true, :ssl_verify_peer => false,
|
386
|
+
:use_accelerate_endpoint => false,
|
387
|
+
:server_side_encryption => 'AES256',
|
388
|
+
:http_open_timeout => 60, :retry_limit => 20)
|
389
|
+
end
|
253
390
|
|
391
|
+
s3 = Aws::S3::Resource.new(client: client)
|
392
|
+
s3.bucket(bucket)
|
393
|
+
rescue => e
|
394
|
+
Cnvrg::Logger.log_error(e)
|
395
|
+
Cnvrg::Logger.log_method(bind: binding)
|
396
|
+
end
|
397
|
+
end
|
254
398
|
|
399
|
+
def download_and_read(path)
|
400
|
+
body = nil
|
401
|
+
retries = 0
|
402
|
+
success= false
|
403
|
+
while !success and retries < 20
|
404
|
+
begin
|
405
|
+
if !Helpers.is_verify_ssl
|
406
|
+
body = open(path, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
|
407
|
+
else
|
408
|
+
body = open(path).read
|
409
|
+
end
|
410
|
+
success = true
|
411
|
+
rescue => e
|
412
|
+
retries +=1
|
413
|
+
sleep(1)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
body
|
255
417
|
end
|
256
418
|
|
257
419
|
def upload_large_files_s3(upload_resp, file_path)
|
258
420
|
begin
|
421
|
+
return true if upload_resp['result']['already_exists'].present?
|
259
422
|
sts_path = upload_resp["result"]["path_sts"]
|
260
423
|
|
261
424
|
retries = 0
|
@@ -360,13 +523,13 @@ module Cnvrg
|
|
360
523
|
|
361
524
|
end
|
362
525
|
|
363
|
-
def delete_file(
|
364
|
-
response = Cnvrg::API.request(@base_resource + "delete_file", 'DELETE', {
|
526
|
+
def delete_file(relative_path, commit_sha1)
|
527
|
+
response = Cnvrg::API.request(@base_resource + "delete_file", 'DELETE', {relative_path: relative_path, commit_sha1: commit_sha1})
|
365
528
|
return Cnvrg::CLI.is_response_success(response, false)
|
366
529
|
end
|
367
530
|
|
368
|
-
def delete_dir(
|
369
|
-
response = Cnvrg::API.request(@base_resource + "delete_dir", 'DELETE', {
|
531
|
+
def delete_dir(relative_path, commit_sha1)
|
532
|
+
response = Cnvrg::API.request(@base_resource + "delete_dir", 'DELETE', {relative_path: relative_path, commit_sha1: commit_sha1})
|
370
533
|
return Cnvrg::CLI.is_response_success(response, false)
|
371
534
|
end
|
372
535
|
|
@@ -376,6 +539,18 @@ module Cnvrg
|
|
376
539
|
end
|
377
540
|
|
378
541
|
|
542
|
+
def calculate_sha1(files_list)
|
543
|
+
files_list = files_list.map{|file| "#{@project_home}/#{file}"}
|
544
|
+
files_list = files_list.select{|file| !file.ends_with? '/'}
|
545
|
+
#TODO: parallel
|
546
|
+
files_list.map do |file|
|
547
|
+
next [file, nil] unless File.exists? file
|
548
|
+
sha1 = OpenSSL::Digest::SHA1.file(file).hexdigest
|
549
|
+
[file.gsub("#{@project_home}/", ""), sha1]
|
550
|
+
end.to_h
|
551
|
+
end
|
552
|
+
|
553
|
+
|
379
554
|
def download_file_s3(absolute_path, relative_path, project_home, commit_sha1=nil, conflict=false)
|
380
555
|
begin
|
381
556
|
res = Cnvrg::API.request(@base_resource + "download_file", 'POST', {absolute_path: absolute_path, relative_path: relative_path,
|
@@ -456,73 +631,78 @@ module Cnvrg
|
|
456
631
|
|
457
632
|
end
|
458
633
|
end
|
459
|
-
|
634
|
+
|
635
|
+
def download_files(files, commit, postfix: '', progress: nil)
|
636
|
+
res = Cnvrg::API.request(@base_resource + "download_files", 'POST', {files: files, commit: commit})
|
637
|
+
unless Cnvrg::CLI.is_response_success(res, false)
|
638
|
+
raise Exception.new("Cant download files from the server.")
|
639
|
+
end
|
640
|
+
self.download_multpile_files_s3(res['result'], @project_home, postfix: postfix, progress: progress)
|
641
|
+
end
|
642
|
+
|
643
|
+
def delete_files_local(deleted, conflicted: [], progress: nil)
|
644
|
+
deleted -= conflicted
|
645
|
+
deleted.each{|file| self.delete(file); progress.progress += 1 if progress.present?}
|
646
|
+
conflicted.each{|file| self.delete_conflict(file); progress.progress += 1 if progress.present?}
|
647
|
+
end
|
648
|
+
|
649
|
+
def download_multpile_files_s3(files, project_home, postfix: '', progress: nil)
|
460
650
|
begin
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
}
|
479
|
-
Parallel.map(files["keys"], parallel_options) do |f|
|
480
|
-
|
481
|
-
file_path = f["name"]
|
482
|
-
if file_path.end_with? "/"
|
483
|
-
# dir
|
484
|
-
if download_dir(file_path, file_path, project_home)
|
485
|
-
download_succ_count += 1
|
486
|
-
else
|
487
|
-
return Cnvrg::Result.new(false,"Could not create directory: #{file_path}")
|
488
|
-
raise Parallel::Kill
|
489
|
-
end
|
651
|
+
props = Cnvrg::Helpers.get_s3_props(files)
|
652
|
+
client = props[:client]
|
653
|
+
iv = props[:iv]
|
654
|
+
key = props[:key]
|
655
|
+
bucket = props[:bucket]
|
656
|
+
download_succ_count = 0
|
657
|
+
parallel_options = {
|
658
|
+
in_threads: Cnvrg::Helpers.parallel_threads,
|
659
|
+
isolation: true
|
660
|
+
}
|
661
|
+
Parallel.map(files["keys"], parallel_options) do |f|
|
662
|
+
|
663
|
+
file_path = f["name"]
|
664
|
+
if file_path.end_with? "/"
|
665
|
+
# dir
|
666
|
+
if download_dir(file_path, file_path, project_home)
|
667
|
+
download_succ_count += 1
|
490
668
|
else
|
491
|
-
#
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
669
|
+
return Cnvrg::Result.new(false,"Could not create directory: #{file_path}")
|
670
|
+
raise Parallel::Kill
|
671
|
+
end
|
672
|
+
else
|
673
|
+
file_path += postfix
|
674
|
+
# blob
|
675
|
+
begin
|
676
|
+
if not File.exists?(project_home+"/"+File.dirname(file_path))
|
677
|
+
FileUtils.makedirs(project_home+"/"+File.dirname(file_path))
|
678
|
+
end
|
496
679
|
|
497
680
|
file_key = Cnvrg::Helpers.decrypt(key,iv, f["path"])
|
498
681
|
resp = false
|
499
|
-
|
500
|
-
|
682
|
+
Cnvrg::Helpers.try_until_success(tries: 10) {
|
683
|
+
File.open(project_home+"/"+file_path, 'w+') do |file|
|
684
|
+
resp = client.get_object({bucket:bucket,
|
501
685
|
key:file_key}, target: file)
|
502
|
-
|
503
|
-
|
504
|
-
if
|
505
|
-
|
506
|
-
else
|
507
|
-
return Cnvrg::Result.new(false,"Could not create file: #{file_path}")
|
508
|
-
end
|
686
|
+
end
|
687
|
+
}
|
688
|
+
progress.progress += 1 if progress.present?
|
689
|
+
download_succ_count += 1
|
509
690
|
|
510
691
|
|
511
692
|
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
693
|
+
rescue => e
|
694
|
+
return Cnvrg::Result.new(false,"Could not create file: #{file_path}", e.message, e.backtrace)
|
695
|
+
raise Parallel::Kill
|
696
|
+
end
|
516
697
|
|
517
698
|
|
518
699
|
|
519
|
-
end
|
520
700
|
end
|
701
|
+
end
|
521
702
|
if download_succ_count == files["keys"].size
|
522
703
|
return Cnvrg::Result.new(true,"Done.\nDownloaded #{download_succ_count} files")
|
523
704
|
end
|
524
705
|
rescue => e
|
525
|
-
|
526
706
|
return Cnvrg::Result.new(false,"Could not download some files", e.message, e.backtrace)
|
527
707
|
end
|
528
708
|
|
@@ -530,8 +710,7 @@ module Cnvrg
|
|
530
710
|
|
531
711
|
|
532
712
|
end
|
533
|
-
|
534
|
-
def download_file(absolute_path, relative_path, project_home, conflict=false)
|
713
|
+
def download_file(absolute_path, relative_path, project_home, conflict=false)
|
535
714
|
res = Cnvrg::API.request(@base_resource + "download_file", 'POST', {absolute_path: absolute_path, relative_path: relative_path})
|
536
715
|
Cnvrg::CLI.is_response_success(res, false)
|
537
716
|
if res["result"]
|
@@ -658,9 +837,9 @@ module Cnvrg
|
|
658
837
|
return true
|
659
838
|
|
660
839
|
end
|
661
|
-
def start_commit(new_branch,force:false, exp_start_commit:nil, job_slug: nil, job_type: nil, start_commit: nil)
|
840
|
+
def start_commit(new_branch,force:false, exp_start_commit:nil, job_slug: nil, job_type: nil, start_commit: nil, message: nil)
|
662
841
|
response = Cnvrg::API.request("#{base_resource}/commit/start", 'POST', {project_slug: @project_slug, new_branch: new_branch,force:force,
|
663
|
-
username: @owner, exp_start_commit:exp_start_commit, job_slug: job_slug, job_type: job_type, start_commit: start_commit})
|
842
|
+
username: @owner, exp_start_commit:exp_start_commit, job_slug: job_slug, job_type: job_type, start_commit: start_commit, message: message})
|
664
843
|
Cnvrg::CLI.is_response_success(response,false)
|
665
844
|
return response
|
666
845
|
end
|
@@ -680,9 +859,17 @@ module Cnvrg
|
|
680
859
|
end
|
681
860
|
|
682
861
|
def delete(file)
|
862
|
+
file = "#{@project_home}/#{file}" unless File.exists? file
|
863
|
+
return unless File.exists? file
|
683
864
|
FileUtils.rm_rf(file)
|
684
865
|
end
|
685
866
|
|
867
|
+
def delete_conflict(file)
|
868
|
+
file = "#{@project_home}/#{file}" unless File.exists? file
|
869
|
+
return unless File.exists? file
|
870
|
+
File.rename(file, "#{file}.deleted")
|
871
|
+
end
|
872
|
+
|
686
873
|
def handle_compare_idx(compared, resolver: {})
|
687
874
|
begin
|
688
875
|
all_files = compared.values.flatten.uniq
|
@@ -710,7 +897,7 @@ module Cnvrg
|
|
710
897
|
self.download_file(file_path: "#{file}.conflict", key: key, iv: iv, bucket: bucket, path: files[file]['path'], client: client)
|
711
898
|
next
|
712
899
|
end
|
713
|
-
if compared['updated_on_server'].include? file
|
900
|
+
if compared['updated_on_server'].include? file
|
714
901
|
self.download_file(file_path: file, key: key, iv: iv, bucket: bucket, path: files[file]['path'], client: client)
|
715
902
|
next
|
716
903
|
end
|
data/lib/cnvrg/flow.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
module Cnvrg
|
2
|
+
class Flows
|
3
|
+
def initialize(project_path, fullpath)
|
4
|
+
@project = Cnvrg::Project.new(project_path)
|
5
|
+
@fullpath = fullpath
|
6
|
+
@tasks = {}
|
7
|
+
@relations = {}
|
8
|
+
@title = nil
|
9
|
+
@slug = nil
|
10
|
+
@base_resource = @project.base_resource + "flows"
|
11
|
+
|
12
|
+
self.reload_flow
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.create_flow(path, flow)
|
16
|
+
File.open(path, "w"){|file| file.write flow.to_yaml}
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_flow
|
20
|
+
unless File.exists? @fullpath
|
21
|
+
raise StandardError.new("Cant find flow in #{@fullpath}")
|
22
|
+
end
|
23
|
+
YAML.load_file(@fullpath)
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_flow(new_flow)
|
27
|
+
File.open(@fullpath, "w"){|file| file.write new_flow.to_yaml}
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_flow_slug(slug)
|
31
|
+
flow = self.get_flow
|
32
|
+
flow[:slug] = slug
|
33
|
+
self.set_flow(flow)
|
34
|
+
end
|
35
|
+
|
36
|
+
def reload_flow
|
37
|
+
flow = self.get_flow
|
38
|
+
@title = flow[:title]
|
39
|
+
@slug = flow[:slug]
|
40
|
+
@relations = flow[:relations]
|
41
|
+
local_tasks = flow[:tasks] || {}
|
42
|
+
@relations.each do |relation|
|
43
|
+
relation.values.each do |task|
|
44
|
+
if local_tasks[task].present?
|
45
|
+
@tasks[task] = Cnvrg::Task.new(@project.local_path, content: local_tasks[task])
|
46
|
+
else
|
47
|
+
@tasks[task] = Cnvrg::Task.new(@project.local_path, path: task)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def run
|
54
|
+
resp = Cnvrg::API.request(@base_resource, 'POST', {data: to_api})
|
55
|
+
Cnvrg::CLI.is_response_success(resp, true)
|
56
|
+
flow_slug = resp['result']['flow']
|
57
|
+
self.set_flow_slug(flow_slug)
|
58
|
+
url = Cnvrg::Helpers.remote_url + resp['result']['url']
|
59
|
+
return url
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
private
|
64
|
+
def to_api
|
65
|
+
{
|
66
|
+
relations: @relations,
|
67
|
+
tasks: @tasks.keys.map{|task| [task, @tasks[task].to_api]}.to_h,
|
68
|
+
title: @title,
|
69
|
+
slug: @slug
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|