blufin-lib 1.7.6 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/blufin-lib.rb +5 -0
- data/lib/core/arrays.rb +21 -0
- data/lib/core/aws.rb +12 -3
- data/lib/core/config.rb +1 -1
- data/lib/core/git.rb +274 -0
- data/lib/core/projects.rb +285 -32
- data/lib/core/routes.rb +20 -1
- data/lib/core/strings.rb +16 -0
- data/lib/core/terminal.rb +25 -15
- data/lib/core/update.rb +15 -0
- data/lib/core/yml.rb +43 -0
- data/lib/generate/generate_base.rb +25 -0
- data/lib/generate/generate_ui_routes.rb +165 -0
- data/lib/version.rb +1 -1
- data/opt/schema/projects.yml +15 -2
- data/opt/schema/routes.yml +44 -0
- data/opt/shell/ec2-check +24 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 951694bcd607959a657e046002654767755b74d6
|
4
|
+
data.tar.gz: def507a9855268d197362bad03e915720ef2c26f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bedc142caf1e81f3aa0dcff437217451f8db5560f6d4ef4f58e3fa6540148ad913e781f28873a20a647e21877c21b0d0397a5877576a1f489d554a82ba6ca54
|
7
|
+
data.tar.gz: 6326f21a88d05ce9abf5296e14d5ccd1cf55a9cd57efd9a43628afd82b1afe095fb4ce9562f2f14618ca3562ff4df1f8989036b178fc9d1a2d95a746494cdf6e
|
data/lib/blufin-lib.rb
CHANGED
@@ -6,6 +6,9 @@ module Blufin
|
|
6
6
|
autoload :Config, 'core/config'
|
7
7
|
autoload :DateTimeUtils, 'core/datetime_utils'
|
8
8
|
autoload :Files, 'core/files'
|
9
|
+
autoload :GenerateBase, 'generate/generate_base'
|
10
|
+
autoload :GenerateUiRoutes, 'generate/generate_ui_routes'
|
11
|
+
autoload :Git, 'core/git'
|
9
12
|
autoload :Image, 'core/image'
|
10
13
|
autoload :Network, 'core/network'
|
11
14
|
autoload :Numbers, 'core/numbers'
|
@@ -14,7 +17,9 @@ module Blufin
|
|
14
17
|
autoload :Strings, 'core/strings'
|
15
18
|
autoload :Terminal, 'core/terminal'
|
16
19
|
autoload :Tools, 'core/tools'
|
20
|
+
autoload :Update, 'core/update'
|
17
21
|
autoload :Validate, 'core/validate'
|
18
22
|
autoload :Versioning, 'core/versioning'
|
23
|
+
autoload :Yml, 'core/yml'
|
19
24
|
|
20
25
|
end
|
data/lib/core/arrays.rb
CHANGED
@@ -13,6 +13,27 @@ module Blufin
|
|
13
13
|
!(array.uniq.length == array.length)
|
14
14
|
end
|
15
15
|
|
16
|
+
# Converts an Array of lines to a string (for easier gsub replacement).
|
17
|
+
# @return String
|
18
|
+
def self.convert_line_array_to_string(array_of_lines)
|
19
|
+
raise RuntimeError, "Expected Array of lines, instead got: #{array_of_lines.class}" unless array_of_lines.is_a?(Array)
|
20
|
+
string = ''
|
21
|
+
array_of_lines.each_with_index do |line, idx|
|
22
|
+
newline_or_not = (idx == (array_of_lines.length - 1)) ? '' : "\n"
|
23
|
+
string += "#{line}#{newline_or_not}"
|
24
|
+
end
|
25
|
+
string
|
26
|
+
end
|
27
|
+
|
28
|
+
# Converts a string to an Array of lines to a string.
|
29
|
+
# @return String
|
30
|
+
def self.convert_string_to_line_array(string)
|
31
|
+
raise RuntimeError, "Expected String, instead got: #{string.class}" unless string.is_a?(String)
|
32
|
+
array_of_lines = []
|
33
|
+
string.split("\n").each { |line| array_of_lines << line.gsub("\n", '') }
|
34
|
+
array_of_lines
|
35
|
+
end
|
36
|
+
|
16
37
|
end
|
17
38
|
|
18
39
|
end
|
data/lib/core/aws.rb
CHANGED
@@ -4,6 +4,15 @@ module Blufin
|
|
4
4
|
|
5
5
|
S3_EXCLUDE = "--exclude '.DS_Store' --exclude '*/.DS_Store' --exclude '*.icloud' --exclude '*/*.icloud'"
|
6
6
|
|
7
|
+
# Checks if script is running on an EC2 instance.
|
8
|
+
# Not sure if this is 100% reliable, but it's about as good as it gets I think.
|
9
|
+
# @return bool
|
10
|
+
def self.is_ec2
|
11
|
+
res = `#{Blufin::Base::get_base_path}#{Blufin::Base::OPT_PATH}/shell/ec2-check`.to_s
|
12
|
+
res = Blufin::Strings::strip_newline(res)
|
13
|
+
res.downcase.strip == 'yes'
|
14
|
+
end
|
15
|
+
|
7
16
|
# Uploads a file (or path) to S3. If path, will upload recursively (which is mandatory with s3 sync command).
|
8
17
|
# @return string (S3 URL).
|
9
18
|
def self.upload_s3_data(bucket_name, bucket_path, file_or_path, profile: nil, region: nil, is_file: false, dryrun: false)
|
@@ -25,7 +34,7 @@ module Blufin
|
|
25
34
|
Blufin::Terminal::info('Performing Dry Run:', Blufin::Terminal::format_command(cmd))
|
26
35
|
system("#{cmd} #{S3_EXCLUDE} --exclude '*.blank*'")
|
27
36
|
else
|
28
|
-
raise RuntimeError unless Blufin::Terminal::execute("#{cmd} #{S3_EXCLUDE} --exclude '*.blank*'", verbose: true, text: cmd)
|
37
|
+
raise RuntimeError unless Blufin::Terminal::execute("#{cmd} #{S3_EXCLUDE} --exclude '*.blank*'", verbose: true, text: cmd)[0]
|
29
38
|
end
|
30
39
|
s3_url
|
31
40
|
rescue
|
@@ -49,7 +58,7 @@ module Blufin
|
|
49
58
|
tmp_location = "/tmp/awx-s3-cache-#{bucket_name}#{bucket_path_tmp}"
|
50
59
|
# If path/file exists and we're using cached values, simply return.
|
51
60
|
if file.nil?
|
52
|
-
return tmp_location if Blufin::Files::path_exists(tmp_location) && use_cache
|
61
|
+
return tmp_location if Blufin::Files::path_exists(tmp_location) && use_cache && Blufin::Files::get_files_in_dir(tmp_location).any?
|
53
62
|
else
|
54
63
|
return tmp_location if Blufin::Files::file_exists(tmp_location) && use_cache
|
55
64
|
end
|
@@ -60,7 +69,7 @@ module Blufin
|
|
60
69
|
system("rm #{tmp_location}") unless file.nil?
|
61
70
|
Blufin::Files::create_directory(tmp_location)
|
62
71
|
}, verbose: true)
|
63
|
-
raise RuntimeError unless Blufin::Terminal::execute("aws s3 cp s3://#{bucket_name}#{bucket_path_s3} #{tmp_location} --recursive --region #{region}#{App::AWS::get_profile_for_cli}", verbose: true)
|
72
|
+
raise RuntimeError unless Blufin::Terminal::execute("aws s3 cp s3://#{bucket_name}#{bucket_path_s3} #{tmp_location} --recursive --region #{region}#{App::AWS::get_profile_for_cli}", verbose: true)[0]
|
64
73
|
tmp_location
|
65
74
|
rescue
|
66
75
|
system("rm -rf #{tmp_location}") if file.nil?
|
data/lib/core/config.rb
CHANGED
@@ -56,7 +56,7 @@ module Blufin
|
|
56
56
|
begin
|
57
57
|
schema_file_parsed = YAML.load_file(schema_file)
|
58
58
|
rescue => e
|
59
|
-
Blufin::Terminal::error("Failed to
|
59
|
+
Blufin::Terminal::error("Failed to schema config file: #{Blufin::Terminal::format_directory(schema_file)}", e.message)
|
60
60
|
end
|
61
61
|
validator = Kwalify::Validator.new(schema_file_parsed)
|
62
62
|
begin
|
data/lib/core/git.rb
ADDED
@@ -0,0 +1,274 @@
|
|
1
|
+
module Blufin
|
2
|
+
|
3
|
+
class Git
|
4
|
+
|
5
|
+
HISTORY_TYPES = %w(branch tag commit)
|
6
|
+
DETACHED_HEAD_REGEX = /\(HEAD\s*detached\s*at\s*/
|
7
|
+
|
8
|
+
@@branch_current_cache = {}
|
9
|
+
@@btc_exists_cache = {}
|
10
|
+
@@commit_cache = {}
|
11
|
+
@@uncommitted_files_cache = {}
|
12
|
+
|
13
|
+
# Tag a branch:
|
14
|
+
# $ git tag -a "v0.1.0-beta" -m "Version: v0.1.0-beta"
|
15
|
+
|
16
|
+
# Show all commits between 2 tags...
|
17
|
+
# $ git log v0.1.0-beta..v0.1.1-beta | grep "^commit [a-z0-9]\{40\}$" | awk '{print $2}'
|
18
|
+
|
19
|
+
# Get commit message for commit hash... (must .strip string)
|
20
|
+
# $ git show d29f2870c59ffab4abb565c3e3c06430cd62515c | grep "^commit [a-z0-9]\{40\}$" -A4 | tail -n 1
|
21
|
+
|
22
|
+
# Easy, clean way to squash all commits on a branch into 1.
|
23
|
+
# $ git reset --soft dev/master
|
24
|
+
# $ git add .
|
25
|
+
# $ git commit -m 'All changes from my branch squashed'
|
26
|
+
|
27
|
+
# Merge that single commit into dev (WITHOUT A MERGE COMMIT!).
|
28
|
+
# [feature] $ git rebase dev
|
29
|
+
# [feature] $ git checkout dev
|
30
|
+
# [dev] $ git merge --ff-only feature
|
31
|
+
|
32
|
+
# Checks out a project and returns the path to it.
|
33
|
+
# branch_tag_or_commit can be a branch, commit or tag.
|
34
|
+
# Returns current branch/tag/commit (if local) -- in case you want to revert after.
|
35
|
+
# @return string |
|
36
|
+
def self.checkout(project_id, branch: nil, tag: nil, commit: nil, is_ec2: false)
|
37
|
+
begin
|
38
|
+
project = Blufin::Projects::get_project_by_id(project_id, true)
|
39
|
+
repo_path = Blufin::Projects::get_project_path(project_id, is_ec2: is_ec2)
|
40
|
+
repo_data = project[Blufin::Projects::REPOSITORY]
|
41
|
+
type, btc = resolve_type_btc(branch, tag, commit)
|
42
|
+
errors = nil
|
43
|
+
current_head = nil
|
44
|
+
if repo_data.has_key?(Blufin::Projects::LOCAL) && !is_ec2
|
45
|
+
# Make sure branch/tag/commit exists.
|
46
|
+
raise "#{Blufin::Terminal::format_highlight(type.capitalize)} not found: #{Blufin::Terminal::format_invalid(btc)}" unless Blufin::Git::exists(repo_path, btc, type, false)
|
47
|
+
# Get current branch (need to reset to this locally after script has run).
|
48
|
+
current_head = Blufin::Git::get_current_branch(repo_path)
|
49
|
+
else
|
50
|
+
# If path already exists, do some checks...
|
51
|
+
if Blufin::Files::path_exists(repo_path)
|
52
|
+
res = Blufin::Terminal::execute("git remote -v | tail -n 1 | awk '{print $2}'", repo_path, capture: true, verbose: false, display_error: false)
|
53
|
+
wipe = false
|
54
|
+
res = res[0]
|
55
|
+
if res.nil? || Blufin::Strings::strip_newline(res) == ''
|
56
|
+
wipe = true
|
57
|
+
else
|
58
|
+
repo_expected = Blufin::Projects::get_project_repo_name(project_id)
|
59
|
+
repo_actual = extract_repo_name(res)
|
60
|
+
wipe = true if repo_expected != repo_actual
|
61
|
+
end
|
62
|
+
# Wipe /tmp folder ONLY if something weird is going on... I put the /tmp regex just in case :)
|
63
|
+
`rm -rf #{repo_path}/` if wipe && repo_path =~ /^\/tmp\/[A-Za-z0-9\.]+/
|
64
|
+
end
|
65
|
+
# Checkout repo (if not exists).
|
66
|
+
unless Blufin::Files::path_exists(repo_path)
|
67
|
+
clone_cmd = "git clone #{project[Blufin::Projects::REPOSITORY][Blufin::Projects::REMOTE]} #{repo_path}"
|
68
|
+
unless Blufin::Terminal::execute_proc(clone_cmd, Proc.new {
|
69
|
+
res = Blufin::Terminal::execute("#{clone_cmd} &>/dev/null", '/tmp', capture: true, verbose: false, display_error: false)
|
70
|
+
errors = res[1].split("\n")
|
71
|
+
res[1] =~ /^Cloning\s*into\s*('|").+/
|
72
|
+
})
|
73
|
+
raise RuntimeError, "Failed to checkout #{type}: #{Blufin::Terminal::format_invalid(btc)}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
# At this point we should have the repo checked out. Throw an error if we don't.
|
77
|
+
raise RuntimeError, "Path not found: #{repo_path}" unless Blufin::Files::path_exists(repo_path)
|
78
|
+
end
|
79
|
+
# Checkout branch/tag/commit.
|
80
|
+
unless Blufin::Terminal::execute_proc("git checkout #{btc}", Proc.new {
|
81
|
+
res = Blufin::Terminal::execute("git checkout #{btc} &>/dev/null", repo_path, capture: true, verbose: false, display_error: false)
|
82
|
+
errors = res[1].split("\n")
|
83
|
+
last_line = errors[errors.length - 1].strip
|
84
|
+
last_line =~ /^HEAD\s*is\s*now\s*at\s*.+/i || last_line =~ /^Already\s*on\s*('|")#{btc}('|")$/ || last_line =~ /^Switched\s*to(\s*a\s*new)?\s*branch\s*('|")#{btc}('|")$/
|
85
|
+
})
|
86
|
+
raise RuntimeError, "Failed to checkout #{type}: #{Blufin::Terminal::format_invalid(btc)}"
|
87
|
+
end
|
88
|
+
current_head
|
89
|
+
rescue => e
|
90
|
+
if is_ec2
|
91
|
+
err_output = nil
|
92
|
+
err_output = " - #{errors.is_a?(Array) ? errors.join(', ') : errors.to_s}" unless errors.nil? || errors.strip == ''
|
93
|
+
raise RuntimeError, Blufin::Strings::strip_ansi_colors("#{e.message}#{err_output}")
|
94
|
+
else
|
95
|
+
Blufin::Terminal::error(e.message, errors)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Gets current branch for a repository.
|
101
|
+
# @return String -> (IE: "master")
|
102
|
+
def self.get_current_branch(path = nil, verbose: false)
|
103
|
+
raise RuntimeError, "Path not found: #{path}" unless path.nil? || Blufin::Files::path_exists(path)
|
104
|
+
path = Blufin::Strings::strip_newline(`pwd`) if path.nil?
|
105
|
+
key = File.expand_path(path)
|
106
|
+
return @@branch_current_cache[key] if @@branch_current_cache.has_key?(key)
|
107
|
+
res = run("git branch | grep \\*", path, text: 'Getting Branch', verbose: verbose)
|
108
|
+
branch = Blufin::Strings::strip_newline(res).gsub(/^\*\s?/, '')
|
109
|
+
branch = branch.strip.gsub(DETACHED_HEAD_REGEX, '').gsub(/\)$/, '') if branch =~ DETACHED_HEAD_REGEX
|
110
|
+
@@branch_current_cache[key] = branch
|
111
|
+
@@branch_current_cache[key]
|
112
|
+
end
|
113
|
+
|
114
|
+
# Gets latest commit hash for a repository.
|
115
|
+
# @return String -> (IE: "5b7559e5952eacb5251a9baf81dd964fe1ef57f5")
|
116
|
+
def self.get_latest_commit_hash(path, verbose: false)
|
117
|
+
raise RuntimeError, "Path not found: #{path}" unless Blufin::Files::path_exists(path)
|
118
|
+
key = File.expand_path(path)
|
119
|
+
return @@commit_cache[key] if @@commit_cache.has_key?(key)
|
120
|
+
res = run('git rev-parse HEAD', path, text: 'Getting HEAD Commit', verbose: verbose)
|
121
|
+
@@commit_cache[key] = Blufin::Strings::strip_newline(res)
|
122
|
+
@@commit_cache[key]
|
123
|
+
end
|
124
|
+
|
125
|
+
# Gets a list of uncommitted files for a repository.
|
126
|
+
# Returns an empty Array if branch is clean.
|
127
|
+
# @return Array -> (IE: ["file-1.txt","file-2.txt"] or [])
|
128
|
+
def self.get_uncommitted_files(path, run_git_add: true, verbose: false, formatted: false, spacer: nil)
|
129
|
+
raise RuntimeError, "Path not found: #{path}" unless Blufin::Files::path_exists(path)
|
130
|
+
raise RuntimeError, "Expected String, instead got: #{spacer.class}" unless spacer.is_a?(String) || spacer.nil?
|
131
|
+
raise RuntimeError, 'Cannot pass spacer if formatted: is false.' if !formatted && !spacer.nil?
|
132
|
+
key = "#{File.expand_path(path)}-#{formatted}-#{spacer}"
|
133
|
+
return @@uncommitted_files_cache[key] if @@uncommitted_files_cache.has_key?(key)
|
134
|
+
renamed = []
|
135
|
+
modified = []
|
136
|
+
deleted = []
|
137
|
+
moved = []
|
138
|
+
new = []
|
139
|
+
run('git add .', path, verbose: verbose) if run_git_add
|
140
|
+
git_status = run('git status', path, verbose: verbose)
|
141
|
+
git_status = git_status.split("\n")
|
142
|
+
git_status.each do |line|
|
143
|
+
renamed << line.split('renamed:')[1].strip if line =~ /renamed:/i
|
144
|
+
modified << line.split('modified:')[1].strip if line =~ /modified:/i
|
145
|
+
deleted << line.split('deleted:')[1].strip if line =~ /deleted:/i
|
146
|
+
moved << line.split('moved:')[1].strip if line =~ /moved:/i
|
147
|
+
new << line.split('new file:')[1].strip if line =~ /new file:/i
|
148
|
+
end
|
149
|
+
if formatted
|
150
|
+
files = []
|
151
|
+
spacer = '' if spacer.nil?
|
152
|
+
new.each { |file| files << "#{spacer}\x1B[38;5;246m#{'New: '.rjust(10, ' ')}\x1B[38;5;48m#{file}\x1B[0m" } if new.any?
|
153
|
+
modified.each { |file| files << "#{spacer}\x1B[38;5;246m#{'Modified: '.rjust(10, ' ')}\x1B[38;5;34m#{file}\x1B[0m" } if modified.any?
|
154
|
+
renamed.each { |file| files << "#{spacer}\x1B[38;5;246m#{'Renamed: '.rjust(10, ' ')}\x1B[38;5;34m#{file}\x1B[0m" } if renamed.any?
|
155
|
+
deleted.each { |file| files << "#{spacer}\x1B[38;5;246m#{'Deleted: '.rjust(10, ' ')}\x1B[38;5;124m#{file}\x1B[0m" } if deleted.any?
|
156
|
+
moved.each { |file| files << "#{spacer}\x1B[38;5;246m#{'Moved: '.rjust(10, ' ')}\x1B[38;5;238m#{file}\x1B[0m" } if moved.any?
|
157
|
+
else
|
158
|
+
files = renamed + modified + deleted + moved + new
|
159
|
+
files.sort!
|
160
|
+
end
|
161
|
+
files.uniq!
|
162
|
+
@@uncommitted_files_cache[key] = files
|
163
|
+
@@uncommitted_files_cache[key]
|
164
|
+
end
|
165
|
+
|
166
|
+
# Checks if current branch exists.
|
167
|
+
# @return bool
|
168
|
+
def self.branch_exists(path, branch, run_git_fetch: false)
|
169
|
+
exists(path, branch, 'branch', run_git_fetch)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Checks if tag exists.
|
173
|
+
# @return bool
|
174
|
+
def self.tag_exists(path, tag, run_git_fetch: false)
|
175
|
+
exists(path, tag, 'tag', run_git_fetch)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Checks if commit exists.
|
179
|
+
# @return bool
|
180
|
+
def self.commit_exists(path, commit, run_git_fetch: false)
|
181
|
+
exists(path, commit, 'commit', run_git_fetch)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Runs $ git add .
|
185
|
+
# @return void
|
186
|
+
def self.add(path, add = '.', verbose: true)
|
187
|
+
raise RuntimeError, "Path not found: #{path}" unless path.nil? || Blufin::Files::path_exists(path)
|
188
|
+
path = Blufin::Strings::strip_newline(`pwd`) if path.nil?
|
189
|
+
run("git add #{add}", path, verbose: verbose)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Attempts to convert something like git@github.com:alb3rtuk/blufin-archetypes.git into -> blufin-archetypes.
|
193
|
+
# @return string
|
194
|
+
def self.extract_repo_name(string)
|
195
|
+
raise RuntimeError, "Expected String, instead got: #{string.class}" unless string.is_a?(String)
|
196
|
+
repo_name = Blufin::Strings::strip_newline(string).split('/')
|
197
|
+
repo_name[repo_name.length - 1].gsub(/\.git$/i, '')
|
198
|
+
end
|
199
|
+
|
200
|
+
private
|
201
|
+
|
202
|
+
# Convenience method to run commands. Throws error if anything fails.
|
203
|
+
# Returns only the output, not the error. Does not strip new lines! This must be done 1 level up.
|
204
|
+
# @return string
|
205
|
+
def self.run(cmd, path, text: nil, verbose: true)
|
206
|
+
res = Blufin::Terminal::execute(cmd, path, capture: true, text: text, verbose: verbose)
|
207
|
+
Blufin::Terminal::error("Something went wrong: #{Blufin::Terminal::format_invalid(res[1])}") unless res[1].nil?
|
208
|
+
res[0]
|
209
|
+
end
|
210
|
+
|
211
|
+
# Common code for 'exists' method(s).
|
212
|
+
# @return bool
|
213
|
+
def self.exists(path, btc, type, run_git_fetch)
|
214
|
+
raise RuntimeError, "Path not found: #{path}" unless path.nil? || Blufin::Files::path_exists(path)
|
215
|
+
raise RuntimeError, "Invalid type: #{type}" unless HISTORY_TYPES.include?(type)
|
216
|
+
key = "#{File.expand_path(path)}|#{btc}|#{type}|#{run_git_fetch}"
|
217
|
+
return @@btc_exists_cache[key] if @@btc_exists_cache.has_key?(key)
|
218
|
+
exists = false
|
219
|
+
Blufin::Terminal::execute_proc("Checking #{type} exists: #{Blufin::Terminal::format_highlight(btc)} \x1B[38;5;246m\xe2\x86\x92 \x1B[38;5;240m#{File.expand_path(path)}\x1B[0m", Proc.new {
|
220
|
+
run('git fetch -p', path, verbose: false) if run_git_fetch
|
221
|
+
cmd = %w(branch tag).include?(type) ? "git #{type} | grep #{btc}" : "git log | grep \"commit #{btc}\""
|
222
|
+
res = Blufin::Terminal::execute(cmd, path, capture: true, verbose: false)
|
223
|
+
res.each do |line|
|
224
|
+
next if line.nil? || line.strip == ''
|
225
|
+
case type
|
226
|
+
when 'branch'
|
227
|
+
line = line.gsub(/^\*\s?/, '')
|
228
|
+
when 'commit'
|
229
|
+
line = line.gsub(/^commit\s?/, '')
|
230
|
+
when 'tag'
|
231
|
+
else
|
232
|
+
raise RuntimeError, "Unrecognized type: #{type}"
|
233
|
+
end
|
234
|
+
line = Blufin::Strings::strip_newline(line)
|
235
|
+
if line =~ /^#{btc}$/
|
236
|
+
exists = true
|
237
|
+
break
|
238
|
+
end
|
239
|
+
end
|
240
|
+
exists
|
241
|
+
})
|
242
|
+
@@btc_exists_cache[key] = exists
|
243
|
+
@@btc_exists_cache[key]
|
244
|
+
end
|
245
|
+
|
246
|
+
# Convenience method to resolve type and branch/tag/commit name.
|
247
|
+
# @return Array
|
248
|
+
def self.resolve_type_btc(branch, tag, commit)
|
249
|
+
set = 0
|
250
|
+
set =+1 unless branch.nil?
|
251
|
+
set =+1 unless tag.nil?
|
252
|
+
set =+1 unless commit.nil?
|
253
|
+
raise RuntimeError, "Must set atleast one of: #{HISTORY_TYPES.join(', ')}" if set == 0
|
254
|
+
raise RuntimeError, "Can only set one of: #{HISTORY_TYPES.join(', ')}" if set > 1
|
255
|
+
type = 'branch' unless branch.nil?
|
256
|
+
type = 'tag' unless tag.nil?
|
257
|
+
type = 'commit' unless commit.nil?
|
258
|
+
case type
|
259
|
+
when 'branch'
|
260
|
+
btc = branch
|
261
|
+
when 'tag'
|
262
|
+
btc = tag
|
263
|
+
when 'commit'
|
264
|
+
btc = commit
|
265
|
+
else
|
266
|
+
raise RuntimeError, "Unrecognized type: #{type}"
|
267
|
+
end
|
268
|
+
raise RuntimeError, "#{type.capitalize} cannot be nil." if btc.nil? || btc.strip == ''
|
269
|
+
[type, btc]
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
end
|
data/lib/core/projects.rb
CHANGED
@@ -16,7 +16,10 @@ module Blufin
|
|
16
16
|
PROJECT_ROOT = 'ProjectRoot'
|
17
17
|
TYPE = 'Type'
|
18
18
|
REPOSITORY = 'Repository'
|
19
|
+
UPSTREAM = 'Upstream'
|
20
|
+
DOWNSTREAM = 'Downstream'
|
19
21
|
LOCAL = 'Local'
|
22
|
+
REMOTE = 'Remote'
|
20
23
|
FILE = 'File'
|
21
24
|
DEPLOYMENT = 'Deployment'
|
22
25
|
DEPLOYMENT_BUCKET = 'Bucket'
|
@@ -29,6 +32,8 @@ module Blufin
|
|
29
32
|
CRON = 'Cron'
|
30
33
|
WORKER = 'Worker'
|
31
34
|
LAMBDA = 'Lambda'
|
35
|
+
UI = 'UI'
|
36
|
+
ROUTES_FILE = 'RoutesFile'
|
32
37
|
TITLE = 'Title'
|
33
38
|
ALIAS = 'Alias'
|
34
39
|
DOMAIN = 'Domain'
|
@@ -40,25 +45,40 @@ module Blufin
|
|
40
45
|
TYPE_ALEXA = 'alexa'
|
41
46
|
TYPE_API = 'api'
|
42
47
|
TYPE_LAMBDA = 'lambda'
|
48
|
+
TYPE_MVN_LIB = 'mvn-lib'
|
49
|
+
TYPE_NPM_LIB = 'npm-lib'
|
43
50
|
TYPE_UI = 'ui'
|
51
|
+
TYPE_MOBILE = 'mobile'
|
44
52
|
VALID_TYPES = [
|
45
53
|
TYPE_ALEXA,
|
46
54
|
TYPE_API,
|
47
55
|
TYPE_LAMBDA,
|
56
|
+
TYPE_MVN_LIB,
|
57
|
+
TYPE_NPM_LIB,
|
48
58
|
TYPE_UI,
|
59
|
+
TYPE_MOBILE,
|
49
60
|
]
|
50
61
|
|
51
|
-
@@projects
|
52
|
-
@@
|
53
|
-
@@
|
54
|
-
@@
|
55
|
-
@@
|
62
|
+
@@projects = nil
|
63
|
+
@@projects_arr = []
|
64
|
+
@@projects_cache = {}
|
65
|
+
@@project_names = []
|
66
|
+
@@project_ids = []
|
67
|
+
@@scripts = nil
|
68
|
+
@@apis = nil
|
69
|
+
@@api_data = {}
|
70
|
+
@@lambdas = nil
|
71
|
+
@@libs = {}
|
72
|
+
@@uis = nil
|
73
|
+
@@dependant_projects_cache = {}
|
74
|
+
@@dependant_repos_cache = {}
|
75
|
+
@@project_path_cache = {}
|
56
76
|
|
57
77
|
# Takes a Hash that needs to have a 'Projects' key.
|
58
78
|
# This can come from both .awx.yml['Profiles'] or .blufin.yml (root).
|
59
79
|
# @return void
|
60
|
-
def
|
61
|
-
raise RuntimeError, 'Cannot run Blufin::Projects
|
80
|
+
def initialize(projects)
|
81
|
+
raise RuntimeError, 'Cannot run Blufin::Projects.new() more than once.' if !@@projects.nil? || !@@scripts.nil?
|
62
82
|
raise RuntimeError, "Need either a Local or S3Bucket key, found neither: #{projects.keys}" unless projects.has_key?(LOCAL) || projects.has_key?('S3Bucket')
|
63
83
|
@@projects = {}
|
64
84
|
@@scripts = {}
|
@@ -77,20 +97,40 @@ module Blufin
|
|
77
97
|
raise RuntimeError, 'Reading projects.yml from S3 is not yet implemented!'
|
78
98
|
|
79
99
|
end
|
100
|
+
|
80
101
|
end
|
81
102
|
|
82
|
-
# Gets Project(s).
|
103
|
+
# Gets Project(s) -- as a nested hash with -> [PROJECT][PROJECT_ID] as the keys.
|
83
104
|
# @return Hash
|
84
105
|
def self.get_projects
|
85
106
|
@@projects
|
86
107
|
end
|
87
108
|
|
109
|
+
# Gets Project(s) -- but in a single array.
|
110
|
+
# @return Array
|
111
|
+
def self.get_projects_as_array(type: nil)
|
112
|
+
projects_arr = []
|
113
|
+
if type.nil?
|
114
|
+
validate_type(project_type, project_id)
|
115
|
+
projects_arr = @@projects_arr
|
116
|
+
else
|
117
|
+
@@projects_arr.each { |project| projects_arr << project if project[TYPE] == type }
|
118
|
+
end
|
119
|
+
projects_arr
|
120
|
+
end
|
121
|
+
|
88
122
|
# Gets Project Name(s).
|
89
123
|
# @return Array
|
90
124
|
def self.get_project_names
|
91
125
|
@@project_names
|
92
126
|
end
|
93
127
|
|
128
|
+
# Gets Project ID(s).
|
129
|
+
# @return Array
|
130
|
+
def self.get_project_ids
|
131
|
+
@@project_ids
|
132
|
+
end
|
133
|
+
|
94
134
|
# Gets Script(s).
|
95
135
|
# @return Hash
|
96
136
|
def self.get_scripts
|
@@ -109,25 +149,147 @@ module Blufin
|
|
109
149
|
@@lambdas
|
110
150
|
end
|
111
151
|
|
112
|
-
#
|
152
|
+
# Attempts to get a project's data by ID, displays error if not exists.
|
113
153
|
# @return string
|
114
|
-
def self.
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
154
|
+
def self.get_project_by_id(project_id, runtime_error = false)
|
155
|
+
raise RuntimeError, "Expected String, instead got: #{project_id.class}" unless project_id.is_a?(String)
|
156
|
+
return @@projects_cache[project_id] if @@projects_cache.has_key?(project_id)
|
157
|
+
project_data = nil
|
158
|
+
if @@projects_arr.is_a?(Array)
|
159
|
+
@@projects_arr.each do |project|
|
160
|
+
raise RuntimeError, 'Missing Project ID.' unless project.has_key?(PROJECT_ID)
|
161
|
+
if project[PROJECT_ID].strip.downcase == project_id.strip.downcase
|
162
|
+
project_data = project
|
163
|
+
break
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
raise RuntimeError, "Unrecognized Project ID: #{project_id}" if project_data.nil? && runtime_error
|
168
|
+
Blufin::Terminal::error("Unrecognized Project ID: #{Blufin::Terminal::format_invalid(project_id)} . Available Projects IDs are:", get_project_ids) if project_data.nil? && !runtime_error
|
169
|
+
@@projects_cache[project_id] = project_data
|
170
|
+
@@projects_cache[project_id]
|
171
|
+
end
|
172
|
+
|
173
|
+
# Gets an array of project(s) from current path.
|
174
|
+
# @return Array
|
175
|
+
def self.get_projects_by_path
|
176
|
+
projects = {}
|
177
|
+
current_path = Blufin::Strings::strip_newline(`pwd`)
|
178
|
+
get_projects_as_array.each do |project|
|
179
|
+
if project.has_key?(REPOSITORY)
|
180
|
+
if project[REPOSITORY].has_key?(LOCAL)
|
181
|
+
project_path = File.expand_path(project[REPOSITORY][LOCAL])
|
182
|
+
if current_path =~ /^#{project_path}/
|
183
|
+
raise RuntimeError, 'Missing Project ID.' unless project.has_key?(PROJECT_ID)
|
184
|
+
projects[project[PROJECT_ID]] = project
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
projects
|
190
|
+
end
|
191
|
+
|
192
|
+
# Gets the path to a project. By default, gets the root (IE: doesn't take into account 'Repository.ProjectRoot' key).
|
193
|
+
# If you want the full path to the inner project, to_inner_project must be set to TRUE.
|
194
|
+
# If local, simply returns path in projects.yml.
|
195
|
+
# If not local (IE: on EC2), returns a standardized /tmp path.
|
196
|
+
# @return string
|
197
|
+
def self.get_project_path(project_id, to_inner_project = false, is_ec2: false, project: nil)
|
198
|
+
key = "#{project_id}|#{to_inner_project}|#{is_ec2}"
|
199
|
+
return @@project_path_cache[key] if @@project_path_cache.has_key?(key)
|
200
|
+
project = project.nil? ? get_project_by_id(project_id, true) : project
|
201
|
+
repo_data = project[REPOSITORY]
|
202
|
+
inner_path = repo_data.has_key?(PROJECT_ROOT) ? Blufin::Strings::remove_surrounding_slashes(repo_data[PROJECT_ROOT]) : ''
|
203
|
+
project_path = nil
|
204
|
+
if repo_data.has_key?(LOCAL) && !is_ec2
|
205
|
+
root_path = Blufin::Strings::remove_surrounding_slashes(File.expand_path(repo_data[LOCAL]))
|
206
|
+
project_path = "/#{root_path}" unless to_inner_project
|
207
|
+
project_path = "/#{root_path}#{inner_path.length > 0 ? '/' : ''}#{inner_path}" if to_inner_project
|
121
208
|
else
|
122
|
-
|
209
|
+
rs = repo_data[REMOTE].split('/')
|
210
|
+
tmp_path = "/tmp/repo-#{rs[rs.length - 1].gsub(/\.git$/i, '')}"
|
211
|
+
project_path = tmp_path unless to_inner_project
|
212
|
+
project_path = "#{tmp_path}#{inner_path.length > 0 ? '/' : ''}#{inner_path}" if to_inner_project
|
213
|
+
end
|
214
|
+
raise RuntimeError, "Project Path should never be nil or an empty string: #{key}" if project_path.nil? || project_path.strip == ''
|
215
|
+
@@project_path_cache[key] = project_path
|
216
|
+
@@project_path_cache[key]
|
217
|
+
end
|
218
|
+
|
219
|
+
# Gets a hash of dependant projects (with the Project IDs as keys).
|
220
|
+
# processed_projects Array prevents cyclic-dependency stack overflow.
|
221
|
+
# @return Hash
|
222
|
+
def self.get_dependant_projects(project_id, streams: [UPSTREAM, DOWNSTREAM], processed_projects: [])
|
223
|
+
valid_streams = [UPSTREAM, DOWNSTREAM]
|
224
|
+
raise RuntimeError, "Expected Array, instead got: #{streams.class}" unless streams.is_a?(Array)
|
225
|
+
streams.each { |s| raise RuntimeError, "Invalid stream: #{s}" unless valid_streams.include?(s) }
|
226
|
+
key = "#{project_id}-#{streams.join('-')}"
|
227
|
+
return @@dependant_projects_cache[key] if @@dependant_projects_cache.has_key?(key)
|
228
|
+
dependant_projects = {}
|
229
|
+
project = get_project_by_id(project_id, true)
|
230
|
+
streams.each do |stream|
|
231
|
+
if project.has_key?(stream)
|
232
|
+
project[stream].each do |dependant_project_id|
|
233
|
+
unless processed_projects.include?(dependant_project_id)
|
234
|
+
processed_projects << dependant_project_id
|
235
|
+
dependant_projects[dependant_project_id] = get_project_by_id(dependant_project_id, true) unless dependant_projects.has_key?(dependant_project_id)
|
236
|
+
dependant_projects_inner = Blufin::Projects::get_dependant_projects(dependant_project_id, streams: streams, processed_projects: processed_projects)
|
237
|
+
# Add nested dependant projects (if any).
|
238
|
+
dependant_projects_inner.each { |k, v| dependant_projects[k] = v unless dependant_projects.has_key?(k) } if dependant_projects_inner.any?
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
123
242
|
end
|
243
|
+
# Don't include project itself in dependant projects.
|
244
|
+
dependant_projects.delete(project_id) if dependant_projects.has_key?(project_id)
|
245
|
+
@@dependant_projects_cache[key] = dependant_projects
|
246
|
+
@@dependant_projects_cache[key]
|
247
|
+
end
|
248
|
+
|
249
|
+
# Same as above, but only gets the repositories.
|
250
|
+
# Sometimes multiple dependant_project IDs may have the same repository.
|
251
|
+
# @return Hash
|
252
|
+
def self.get_dependant_repos(project_id, streams: [UPSTREAM, DOWNSTREAM])
|
253
|
+
key = "#{project_id}-#{streams.join('-')}"
|
254
|
+
return @@dependant_repos_cache[key] if @@dependant_repos_cache.has_key?(key)
|
255
|
+
dependant_repos = {}
|
256
|
+
get_dependant_projects(project_id, streams: streams).each do |k, v|
|
257
|
+
next if k == project_id
|
258
|
+
repo = v[REPOSITORY][REMOTE]
|
259
|
+
dependant_repos[repo] = {
|
260
|
+
:projects => []
|
261
|
+
} unless dependant_repos.include?(repo)
|
262
|
+
dependant_repos[repo][:path] = v[REPOSITORY][LOCAL] if v[REPOSITORY].has_key?(LOCAL)
|
263
|
+
dependant_repos[repo][:projects] << k unless dependant_repos[repo][:projects].include?(k)
|
264
|
+
end
|
265
|
+
@@dependant_repos_cache[key] = dependant_repos
|
266
|
+
@@dependant_repos_cache[key]
|
267
|
+
end
|
268
|
+
|
269
|
+
# Gets repo-name from project_id.
|
270
|
+
# @return string
|
271
|
+
def self.get_project_repo_name(project_id)
|
272
|
+
project = get_project_by_id(project_id, true)
|
273
|
+
Blufin::Git::extract_repo_name(project[REPOSITORY][REMOTE])
|
274
|
+
end
|
275
|
+
|
276
|
+
# Shows a prompt and returns project Hash once selected.
|
277
|
+
# If only one project exists, prompt not displayed.
|
278
|
+
# @return Hash
|
279
|
+
def self.show_project_prompt(array_of_projects)
|
280
|
+
raise RuntimeError, "Expected Array, instead got: #{array_of_projects.class}" unless array_of_projects.is_a?(Array)
|
281
|
+
Blufin::Terminal::error('No projects found.') unless array_of_projects.any?
|
282
|
+
return array_of_projects[0] if array_of_projects.length == 1
|
283
|
+
projects = []
|
284
|
+
array_of_projects.each { |project| projects << { :text => project[PROJECT_ID], :value => project } }
|
285
|
+
Blufin::Terminal::prompt_select('Select project:', projects)
|
124
286
|
end
|
125
287
|
|
126
288
|
private
|
127
289
|
|
128
290
|
# Validate the Project YML.
|
129
291
|
# @return void
|
130
|
-
def
|
292
|
+
def process_source_file(source_file)
|
131
293
|
# Skip empty file.
|
132
294
|
return if Blufin::Files::is_empty(source_file)
|
133
295
|
# Otherwise, validate file.
|
@@ -170,8 +332,31 @@ module Blufin
|
|
170
332
|
end
|
171
333
|
end
|
172
334
|
|
335
|
+
# Buffer/validate project(s) stuff.
|
336
|
+
file_parsed['Projects'].each do |project|
|
337
|
+
project_id = project[PROJECT_ID]
|
338
|
+
project_type = project[TYPE]
|
339
|
+
if project_type == TYPE_MVN_LIB || TYPE_NPM_LIB
|
340
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Duplicate Library Project.", "A library with this ID (#{Blufin::Terminal::format_invalid(project_id)}) has already been registered.") if @@libs.keys.include?(project_id)
|
341
|
+
@@libs[project_id] = project
|
342
|
+
elsif project_type == TYPE_API
|
343
|
+
[ALIAS, PROJECT_NAME, PROJECT_NAME_PASCAL_CASE, TITLE].each do |x|
|
344
|
+
@@api_data[x] = [] unless @@api_data.has_key?(x) && @@api_data[x].is_a?(Array)
|
345
|
+
property_value = project[API][x].strip.downcase
|
346
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Duplicate #{x} API Property.", "An API Property with this value (#{Blufin::Terminal::format_invalid(property_value)}) has already been registered.") if @@api_data[x].include?(property_value)
|
347
|
+
@@api_data[x] << property_value
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
173
352
|
used_ports = {}
|
174
353
|
|
354
|
+
# Run through once quickly to populate critical objects (required for validation).
|
355
|
+
file_parsed['Projects'].each do |project|
|
356
|
+
@@project_names << project[PROJECT]
|
357
|
+
@@project_ids << project[PROJECT_ID]
|
358
|
+
end
|
359
|
+
|
175
360
|
# Loop (and validate) projects.
|
176
361
|
file_parsed['Projects'].each do |project|
|
177
362
|
# Validate keys are in specific order.
|
@@ -180,25 +365,26 @@ module Blufin
|
|
180
365
|
PROJECT => true,
|
181
366
|
TYPE => true,
|
182
367
|
REPOSITORY => true,
|
368
|
+
UPSTREAM => false,
|
369
|
+
DOWNSTREAM => false,
|
183
370
|
RUN => false,
|
184
371
|
TEST => false,
|
185
372
|
BUILD => false,
|
186
373
|
API => false,
|
187
374
|
LAMBDA => false,
|
188
|
-
|
375
|
+
UI => false,
|
376
|
+
DEPLOYMENT => false,
|
189
377
|
}
|
190
378
|
Blufin::Validate::assert_valid_keys(expected, project.keys, source_file)
|
191
379
|
project_id = project[PROJECT_ID]
|
192
380
|
project_name = project[PROJECT]
|
193
381
|
project_type = project[TYPE]
|
194
|
-
|
195
|
-
# Validate Type.
|
196
|
-
Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Invalid Project Type: #{Blufin::Terminal::format_invalid(project_type)}. Valid types are:", VALID_TYPES, true) unless VALID_TYPES.include?(project_type)
|
382
|
+
validate_type(project_type, project_id)
|
197
383
|
# Validate Script(s).
|
198
384
|
[RUN, TEST, BUILD].each do |script_type|
|
199
385
|
if project.has_key?(script_type)
|
200
386
|
# Validate the LAMBDA functions don't need build scripts.
|
201
|
-
Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Project type: #{Blufin::Terminal::format_highlight(TYPE_LAMBDA)} does not require #{Blufin::Terminal::format_invalid(script_type)} script(s).", 'This type of project does not support this.', true) if [BUILD].include?(script_type) && project_type == TYPE_LAMBDA
|
387
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Project type: #{Blufin::Terminal::format_highlight(TYPE_LAMBDA)} does not require #{Blufin::Terminal::format_invalid(script_type)} script(s).", 'This type of project does not support this.', true) if [BUILD].include?(script_type) && project_type == TYPE_LAMBDA
|
202
388
|
if project[script_type].is_a?(Hash)
|
203
389
|
script_key = script_key_mapper(script_type)
|
204
390
|
valid_scripts = []
|
@@ -207,12 +393,21 @@ module Blufin
|
|
207
393
|
script_name = script['Script']
|
208
394
|
unless valid_scripts.include?(script_name)
|
209
395
|
error = valid_scripts.any? ? 'Valid values are:' : "There currently are no #{script_key} script(s) defined."
|
210
|
-
Blufin::Terminal::error("#{project_id} \xe2\x80\x94 #{Blufin::Terminal::format_highlight(script_type)} \xe2\x80\x94 Invalid script reference: #{Blufin::Terminal::format_invalid(script_name)}. #{error}", valid_scripts)
|
396
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 #{Blufin::Terminal::format_highlight(script_type)} \xe2\x80\x94 Invalid script reference: #{Blufin::Terminal::format_invalid(script_name)}. #{error}", valid_scripts)
|
211
397
|
end
|
212
398
|
end
|
213
399
|
end
|
214
400
|
end
|
215
401
|
|
402
|
+
# Validate Repository property.
|
403
|
+
if project.has_key?(REPOSITORY)
|
404
|
+
if project[REPOSITORY].has_key?(LOCAL)
|
405
|
+
repo_path = project[REPOSITORY][LOCAL]
|
406
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Repository path not found: #{Blufin::Terminal::format_invalid(repo_path)}") unless Blufin::Files::path_exists(repo_path)
|
407
|
+
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
216
411
|
# Validate Deployment property.
|
217
412
|
if project.has_key?(DEPLOYMENT)
|
218
413
|
expected = {
|
@@ -225,7 +420,7 @@ module Blufin
|
|
225
420
|
# Validate API property.
|
226
421
|
if project_type == TYPE_API
|
227
422
|
# Make sure we have the API property.
|
228
|
-
Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Missing property: #{Blufin::Terminal::format_highlight(API)}", "This property is required for project(s) with type: #{API}", true) unless project.has_key?(API)
|
423
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Missing property: #{Blufin::Terminal::format_highlight(API)}", "This property is required for project(s) with type: #{API}", true) unless project.has_key?(API)
|
229
424
|
# Validate keys are in specific order.
|
230
425
|
expected = {
|
231
426
|
TITLE => true,
|
@@ -248,16 +443,16 @@ module Blufin
|
|
248
443
|
used_ports[project[API][PORTS][CRON]] = project_id
|
249
444
|
used_ports[project[API][PORTS][WORKER]] = project_id
|
250
445
|
@@apis = {} if @@apis.nil?
|
251
|
-
@@apis[project[PROJECT_ID]] = project
|
446
|
+
@@apis[project[PROJECT_ID]] = project
|
252
447
|
else
|
253
448
|
# Make sure we DON'T have the API key.
|
254
|
-
Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Property not supported: #{Blufin::Terminal::format_invalid(API)}", "This property is only allowed for project(s) with type: #{API}", true) if project.has_key?(API)
|
449
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Property not supported: #{Blufin::Terminal::format_invalid(API)}", "This property is only allowed for project(s) with type: #{API}", true) if project.has_key?(API)
|
255
450
|
end
|
256
451
|
|
257
452
|
# Validate Lambda property.
|
258
453
|
if project_type == TYPE_LAMBDA
|
259
|
-
# Make sure we have the Lambda
|
260
|
-
Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Missing property: #{Blufin::Terminal::format_highlight(LAMBDA)}", "This property is required for project(s) with type: #{
|
454
|
+
# Make sure we have the Lambda property.
|
455
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Missing property: #{Blufin::Terminal::format_highlight(LAMBDA)}", "This property is required for project(s) with type: #{TYPE_LAMBDA}", true) unless project.has_key?(LAMBDA)
|
261
456
|
# Validate keys are in specific order.
|
262
457
|
expected = {
|
263
458
|
TITLE => true,
|
@@ -274,12 +469,49 @@ module Blufin
|
|
274
469
|
@@lambdas[project[PROJECT_ID]] = project
|
275
470
|
else
|
276
471
|
# Make sure we DON'T have the Lambda key.
|
277
|
-
Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Property not supported: #{Blufin::Terminal::format_invalid(LAMBDA)}", "This property is only allowed for project(s) with type: #{
|
472
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Property not supported: #{Blufin::Terminal::format_invalid(LAMBDA)}", "This property is only allowed for project(s) with type: #{TYPE_LAMBDA}", true) if project.has_key?(LAMBDA)
|
473
|
+
end
|
474
|
+
|
475
|
+
# Validate UI property.
|
476
|
+
if project_type == TYPE_UI
|
477
|
+
# Make sure we have the UI property.
|
478
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Missing property: #{Blufin::Terminal::format_highlight(UI)}", "This property is required for project(s) with type: #{TYPE_UI}", true) unless project.has_key?(UI)
|
479
|
+
# Validate keys are in specific order.
|
480
|
+
expected = {
|
481
|
+
ROUTES_FILE => true
|
482
|
+
}
|
483
|
+
Blufin::Validate::assert_valid_keys(expected, project[UI].keys, source_file)
|
484
|
+
# Validate RoutesFile exists.
|
485
|
+
routes_file = "#{Blufin::Projects::get_project_path(project_id, true, project: project)}/#{project[UI][ROUTES_FILE]}"
|
486
|
+
Blufin::Terminal::error("Cannot find #{Blufin::Terminal::format_highlight(ROUTES_FILE)}: #{Blufin::Terminal::format_directory(routes_file)}") unless Blufin::Files::file_exists(routes_file)
|
487
|
+
@@uis = {} if @@uis.nil?
|
488
|
+
Blufin::Terminal::error("Duplicate UI project: #{Blufin::Terminal::format_invalid(project[PROJECT_ID])}") if @@uis.has_key?(project[PROJECT_ID])
|
489
|
+
@@uis[project[PROJECT_ID]] = project
|
490
|
+
else
|
491
|
+
# Make sure we DON'T have the UI key.
|
492
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Property not supported: #{Blufin::Terminal::format_invalid(UI)}", "This property is only allowed for project(s) with type: #{TYPE_UI}", true) if project.has_key?(UI)
|
493
|
+
end
|
494
|
+
|
495
|
+
# Validate upstream/downstream Libs(s).
|
496
|
+
[UPSTREAM, DOWNSTREAM].each do |stream|
|
497
|
+
if project.has_key?(stream)
|
498
|
+
project[stream].each do |library|
|
499
|
+
case stream
|
500
|
+
when UPSTREAM
|
501
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Unrecognized #{Blufin::Terminal::format_action(UPSTREAM)} library: #{Blufin::Terminal::format_invalid(library)}") unless @@libs.keys.include?(library)
|
502
|
+
when DOWNSTREAM
|
503
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Unrecognized #{Blufin::Terminal::format_action(DOWNSTREAM)} library: #{Blufin::Terminal::format_invalid(library)}") unless @@project_ids.include?(library)
|
504
|
+
else
|
505
|
+
raise RuntimeError, "Unrecognized stream: #{stream}"
|
506
|
+
end
|
507
|
+
end
|
508
|
+
end
|
278
509
|
end
|
279
510
|
|
280
511
|
@@projects[project_name] = {} unless @@projects.has_key?(project_name)
|
281
512
|
Blufin::Terminal::error("Duplicate project ID: #{Blufin::Terminal::format_invalid(project_id)}") if @@projects[project_name].has_key?(project_id)
|
282
513
|
@@projects[project_name][project_id] = project
|
514
|
+
@@projects_arr << project
|
283
515
|
|
284
516
|
end
|
285
517
|
@@project_names.uniq!
|
@@ -287,12 +519,33 @@ module Blufin
|
|
287
519
|
end
|
288
520
|
end
|
289
521
|
|
522
|
+
# Validate project type.
|
523
|
+
# @return void
|
524
|
+
def validate_type(project_type, project_id = nil)
|
525
|
+
project_id = project_id.nil? ? nil : "#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 "
|
526
|
+
Blufin::Terminal::error("#{project_id}Invalid Project Type: #{Blufin::Terminal::format_invalid(project_type)}. Valid types are:", VALID_TYPES, true) unless VALID_TYPES.include?(project_type)
|
527
|
+
end
|
528
|
+
|
529
|
+
# Maps root-level property to enum.
|
530
|
+
# @return string
|
531
|
+
def script_key_mapper(script_type)
|
532
|
+
if [RUN_SCRIPTS, RUN].include?(script_type)
|
533
|
+
return SCRIPT_RUN
|
534
|
+
elsif [TEST_SCRIPTS, TEST].include?(script_type)
|
535
|
+
return TEST_SCRIPTS
|
536
|
+
elsif [BUILD_SCRIPTS, BUILD].include?(script_type)
|
537
|
+
return BUILD_SCRIPTS
|
538
|
+
else
|
539
|
+
raise RuntimeError, "Unhandled script type: #{script_type}"
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
290
543
|
# Validate the ports. Make sure none of the ports conflict with other projects.
|
291
544
|
# @return void
|
292
|
-
def
|
545
|
+
def validate_ports(ports, project_id, used_ports)
|
293
546
|
ports.each do |port|
|
294
547
|
if used_ports.has_key?(port)
|
295
|
-
Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Duplicate port detected: #{Blufin::Terminal::format_invalid(port)} ", ["The conflicting project is: #{Blufin::Terminal::format_highlight(used_ports[port])}"])
|
548
|
+
Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 Duplicate port detected: #{Blufin::Terminal::format_invalid(port)} ", ["The conflicting project is: #{Blufin::Terminal::format_highlight(used_ports[port])}"])
|
296
549
|
end
|
297
550
|
|
298
551
|
end
|