blufin-lib 1.7.6 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|