jets 0.10.4 → 1.0.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/CHANGELOG.md +16 -0
- data/Gemfile.lock +12 -12
- data/README.md +4 -2
- data/exe/jets +2 -2
- data/lib/jets/application.rb +41 -5
- data/lib/jets/aws_info.rb +20 -0
- data/lib/jets/builders/code_builder.rb +201 -296
- data/lib/jets/builders/gem_replacer.rb +1 -1
- data/lib/jets/builders/handler_generator.rb +62 -43
- data/lib/jets/builders/md5.rb +55 -0
- data/lib/jets/builders/md5_zip.rb +60 -0
- data/lib/jets/builders/rack_packager.rb +29 -0
- data/lib/jets/builders/rackup_wrappers/rackup +23 -0
- data/lib/jets/builders/rackup_wrappers/rackup.rb +7 -0
- data/lib/jets/builders/reconfigure_rails/config/initializers/jets.rb +14 -0
- data/lib/jets/builders/reconfigure_rails.rb +99 -0
- data/lib/jets/builders/ruby_packager.rb +198 -0
- data/lib/jets/builders/{deducer.rb → shim_vars/app.rb} +14 -10
- data/lib/jets/builders/shim_vars/base.rb +24 -0
- data/lib/jets/builders/{shared_deducer.rb → shim_vars/shared.rb} +4 -3
- data/lib/jets/builders/shim_vars.rb +5 -0
- data/lib/jets/builders/templates/handler.js +9 -0
- data/lib/jets/builders/templates/shim.js +271 -0
- data/lib/jets/builders/tidy.rb +80 -0
- data/lib/jets/builders/util.rb +28 -0
- data/lib/jets/builders.rb +8 -2
- data/lib/jets/cfn/builders/function_builder.rb +0 -10
- data/lib/jets/cfn/builders/parent_builder.rb +7 -6
- data/lib/jets/cfn/ship.rb +9 -103
- data/lib/jets/cfn/upload.rb +139 -0
- data/lib/jets/cfn.rb +1 -0
- data/lib/jets/commands/build.rb +17 -19
- data/lib/jets/commands/deploy.rb +2 -0
- data/lib/jets/commands/help/deploy.md +2 -2
- data/lib/jets/commands/help/import/rack.md +13 -0
- data/lib/jets/commands/help/import/rails.md +11 -0
- data/lib/jets/commands/import/base.rb +39 -0
- data/lib/jets/commands/import/rack.rb +16 -0
- data/lib/jets/commands/import/rail.rb +68 -0
- data/lib/jets/commands/import/sequence.rb +68 -0
- data/lib/jets/commands/import.rb +14 -0
- data/lib/jets/commands/main.rb +2 -1
- data/lib/jets/commands/new.rb +1 -1
- data/lib/jets/commands/sequence.rb +26 -22
- data/lib/jets/commands/templates/skeleton/Gemfile.tt +5 -2
- data/lib/jets/commands/templates/skeleton/README.md +11 -2
- data/lib/jets/commands/templates/skeleton/app/jobs/application_job.rb +1 -1
- data/lib/jets/commands/templates/skeleton/app/views/layouts/application.html.erb.tt +1 -1
- data/lib/jets/commands/templates/skeleton/config/application.rb.tt +12 -5
- data/lib/jets/commands/templates/skeleton/config/database.yml.tt +5 -1
- data/lib/jets/commands/templates/skeleton/config/environments/development.rb +3 -0
- data/lib/jets/commands/templates/skeleton/config/environments/production.rb +5 -0
- data/lib/jets/commands/templates/skeleton/public/{images/favicon.ico → favicon.ico} +0 -0
- data/lib/jets/commands/templates/skeleton/spec/controllers/posts_controller_spec.rb +1 -3
- data/lib/jets/commands.rb +1 -0
- data/lib/jets/controller/base.rb +1 -1
- data/lib/jets/controller/layout.rb +3 -0
- data/lib/jets/controller/params.rb +3 -2
- data/lib/jets/controller/request.rb +4 -0
- data/lib/jets/core.rb +20 -18
- data/lib/jets/core_ext/kernel.rb +9 -5
- data/lib/jets/default/application.rb +1 -1
- data/lib/jets/inflections.rb +16 -8
- data/lib/jets/internal/app/controllers/jets/public_controller.rb +17 -22
- data/lib/jets/internal/app/controllers/jets/rack_controller.rb +15 -0
- data/lib/jets/naming.rb +0 -23
- data/lib/jets/rack/hash_converter.rb +25 -0
- data/lib/jets/rack/request.rb +71 -0
- data/lib/jets/rack/server.rb +47 -0
- data/lib/jets/rack.rb +7 -0
- data/lib/jets/rails_overrides/asset_tag_helper.rb +12 -11
- data/lib/jets/resource/function.rb +13 -5
- data/lib/jets/router.rb +1 -1
- data/lib/jets/ruby_server.rb +63 -18
- data/lib/jets/server/api_gateway.rb +1 -1
- data/lib/jets/stack/resource.rb +3 -1
- data/lib/jets/version.rb +1 -1
- data/lib/jets.rb +3 -5
- metadata +34 -9
- data/lib/jets/builders/node-hello.js +0 -73
- data/lib/jets/builders/node-shim.js +0 -182
- data/lib/jets/internal/app/controllers/jets/public_controller/python/show.py +0 -47
- data/lib/jets/internal/app/controllers/jets/public_controller/python/show.pyc +0 -0
|
@@ -4,7 +4,6 @@ require "colorize"
|
|
|
4
4
|
require "socket"
|
|
5
5
|
require "net/http"
|
|
6
6
|
require "action_view"
|
|
7
|
-
require "bundler" # for clean_old_submodules only
|
|
8
7
|
|
|
9
8
|
# Some important folders to help understand how jets builds a project:
|
|
10
9
|
#
|
|
@@ -18,7 +17,7 @@ require "bundler" # for clean_old_submodules only
|
|
|
18
17
|
# Initially, macosx gems but then get replaced by linux gems where appropriate.
|
|
19
18
|
# cache/downloads/rubies: ruby tarballs.
|
|
20
19
|
# cache/downloads/gems: gem tarballs.
|
|
21
|
-
#
|
|
20
|
+
# code: Where project gets copied into in order for us to configure it.
|
|
22
21
|
# app_root/bundled/gems: Where vendored gems finally end up at. The compiled
|
|
23
22
|
# gems at this point are only linux gems.
|
|
24
23
|
# artifacts/code/code-md5sha.zip: code artifact that gets uploaded to lambda.
|
|
@@ -40,20 +39,24 @@ require "bundler" # for clean_old_submodules only
|
|
|
40
39
|
# * bundle install: cache/bundled/gems
|
|
41
40
|
#
|
|
42
41
|
### setup bundled on app root from cache
|
|
43
|
-
# * copy bundled to
|
|
42
|
+
# * copy bundled to code: code/bundled
|
|
44
43
|
# * extract linux ruby: cache/downloads/rubies:
|
|
45
44
|
# cache/bundled/rbenv, cache/bundled/linuxbrew
|
|
46
45
|
# * extract linux gems: cache/downloads/gems:
|
|
47
46
|
# cache/bundled/gems, cache/bundled/linuxbrew
|
|
48
|
-
# * setup bundled config:
|
|
47
|
+
# * setup bundled config: code/.bundle/config
|
|
49
48
|
#
|
|
50
49
|
### zip
|
|
51
50
|
# * create zip file
|
|
52
51
|
class Jets::Builders
|
|
53
52
|
class CodeBuilder
|
|
53
|
+
# https://docs.aws.amazon.com/lambda/latest/dg/limits.html
|
|
54
|
+
AWS_CODE_SIZE_LIMIT = 250 * 1024 * 1024 # 250MB
|
|
55
|
+
|
|
54
56
|
include Jets::Timing
|
|
55
|
-
include ActionView::Helpers::NumberHelper # number_to_human_size
|
|
56
57
|
include Jets::AwsServices
|
|
58
|
+
include Util
|
|
59
|
+
extend Memoist
|
|
57
60
|
|
|
58
61
|
attr_reader :full_project_path
|
|
59
62
|
def initialize
|
|
@@ -63,54 +66,148 @@ class Jets::Builders
|
|
|
63
66
|
end
|
|
64
67
|
|
|
65
68
|
def build
|
|
66
|
-
return create_zip_file(fake=true) if ENV['TEST_CODE'] # early return
|
|
67
|
-
|
|
68
69
|
cache_check_message
|
|
69
70
|
check_ruby_version
|
|
70
71
|
|
|
71
72
|
clean_start
|
|
72
|
-
compile_assets # easier to do before we copy the project
|
|
73
|
+
compile_assets # easier to do before we copy the project because node and yarn has been likely setup in the that dir
|
|
74
|
+
compile_rails_assets
|
|
73
75
|
copy_project
|
|
74
|
-
Dir.chdir(full(
|
|
76
|
+
Dir.chdir(full(tmp_code)) do
|
|
75
77
|
# These commands run from project root
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
create_zip_file
|
|
78
|
+
code_setup
|
|
79
|
+
package_ruby
|
|
80
|
+
code_finish
|
|
80
81
|
end
|
|
81
82
|
end
|
|
82
83
|
time :build
|
|
83
84
|
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
# Resolves the chicken-and-egg problem with md5 checksums. The handlers need
|
|
86
|
+
# to reference files with the md5 checksum. The files are the:
|
|
87
|
+
#
|
|
88
|
+
# jets/code/rack-checksum.zip
|
|
89
|
+
# jets/code/bundled-checksum.zip
|
|
90
|
+
#
|
|
91
|
+
# We compute the checksums before we generate the node shim handlers.
|
|
92
|
+
def calculate_md5s
|
|
93
|
+
Md5.compute! # populates Md5.checksums hash
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def generate_node_shims
|
|
97
|
+
headline "Generating shims in the handlers folder."
|
|
98
|
+
# Crucial that the Dir.pwd is in the tmp_code because for
|
|
99
|
+
# Jets::Builders::app_files because Jets.boot set ups
|
|
100
|
+
# autoload_paths and this is how project classes are loaded.
|
|
101
|
+
Jets::Builders::HandlerGenerator.build!
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def create_zip_files
|
|
105
|
+
folders = Md5.stage_folders
|
|
106
|
+
folders.each do |folder|
|
|
107
|
+
zip = Md5Zip.new(folder)
|
|
108
|
+
if exist_on_s3?(zip.md5_name)
|
|
109
|
+
puts "Already exists: s3://#{s3_bucket}/jets/code/#{zip.md5_name}"
|
|
110
|
+
else
|
|
111
|
+
zip = Md5Zip.new(folder)
|
|
112
|
+
zip.create
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
time :create_zip_files
|
|
117
|
+
|
|
118
|
+
def exist_on_s3?(filename)
|
|
119
|
+
s3_key = "jets/code/#{filename}"
|
|
120
|
+
begin
|
|
121
|
+
s3.head_object(bucket: s3_bucket, key: s3_key)
|
|
122
|
+
true
|
|
123
|
+
rescue Aws::S3::Errors::NotFound
|
|
124
|
+
false
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Moves code/bundled and code/rack to build_root.
|
|
129
|
+
# These files will be packaged separated and lazy loaded as part of the
|
|
130
|
+
# node shim. This keeps the code zipfile smaller in size and helps
|
|
131
|
+
# with the 250MB extract limited. /tmp permits up to 512MB.
|
|
132
|
+
# AWS Lambda Limits: https://amzn.to/2A7y6v6
|
|
133
|
+
#
|
|
134
|
+
# > Each Lambda function receives an additional 512MB of non-persistent disk space in its own /tmp directory. The /tmp directory can be used for loading additional resources like dependency libraries or data sets during function initialization.
|
|
135
|
+
#
|
|
136
|
+
def setup_tmp
|
|
137
|
+
tmp_symlink("bundled") if Jets.lazy_load?
|
|
138
|
+
tmp_symlink("rack")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def stage_area
|
|
142
|
+
"#{Jets.build_root}/stage"
|
|
90
143
|
end
|
|
91
144
|
|
|
92
|
-
|
|
93
|
-
|
|
145
|
+
# Moves folder to a stage folder and create a symlink its place
|
|
146
|
+
# that links from /var/task to /tmp. Example:
|
|
147
|
+
#
|
|
148
|
+
# /var/task/bundled => /tmp/bundled
|
|
149
|
+
#
|
|
150
|
+
def tmp_symlink(folder)
|
|
151
|
+
src = "#{full(tmp_code)}/#{folder}"
|
|
152
|
+
return unless File.exist?(src)
|
|
153
|
+
|
|
154
|
+
dest = "#{stage_area}/#{folder}"
|
|
155
|
+
dir = File.dirname(dest)
|
|
156
|
+
FileUtils.mkdir_p(dir) unless File.exist?(dir)
|
|
157
|
+
FileUtils.mv(src, dest)
|
|
158
|
+
|
|
159
|
+
# Create symlink
|
|
160
|
+
FileUtils.ln_sf("/tmp/#{folder}", "/#{full(tmp_code)}/#{folder}")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def code_setup
|
|
94
164
|
reconfigure_development_webpacker
|
|
95
|
-
|
|
165
|
+
end
|
|
166
|
+
time :code_setup
|
|
167
|
+
|
|
168
|
+
def code_finish
|
|
169
|
+
update_lazy_load_config # at the top, must be called before Jets.lazy_load? is used
|
|
170
|
+
store_s3_base_url
|
|
171
|
+
setup_tmp
|
|
172
|
+
calculate_md5s # must be called before generate_node_shims and create_zip_files
|
|
96
173
|
generate_node_shims
|
|
174
|
+
create_zip_files
|
|
97
175
|
end
|
|
98
|
-
time :
|
|
176
|
+
time :code_finish
|
|
99
177
|
|
|
100
|
-
def
|
|
101
|
-
|
|
178
|
+
def update_lazy_load_config
|
|
179
|
+
size_limit = AWS_CODE_SIZE_LIMIT
|
|
180
|
+
code_size = dir_size(full(tmp_code))
|
|
181
|
+
if code_size > size_limit
|
|
182
|
+
# override the setting because we dont have to a choice but to lazy load
|
|
183
|
+
Jets.config.ruby.lazy_load = true
|
|
184
|
+
end
|
|
185
|
+
end
|
|
102
186
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
187
|
+
# Thanks https://stackoverflow.com/questions/9354595/recursively-getting-the-size-of-a-directory
|
|
188
|
+
# Seems to overestimate a little bit but close enough.
|
|
189
|
+
def dir_size(folder)
|
|
190
|
+
Dir.glob(File.join(folder, '**', '*'))
|
|
191
|
+
.select { |f| File.file?(f) }
|
|
192
|
+
.map{ |f| File.size(f) }
|
|
193
|
+
.inject(:+)
|
|
108
194
|
end
|
|
109
|
-
time :finish_app_root_setup
|
|
110
195
|
|
|
111
|
-
#
|
|
196
|
+
# Store s3 base url is needed for asset serving from s3 later. Need to package this
|
|
197
|
+
# as part of the code so we have a reference to it.
|
|
198
|
+
# At this point the minimal stack exists, so we can grab it with the AWS API.
|
|
199
|
+
# We do not want to grab this as part of the live request because it is slow.
|
|
112
200
|
def store_s3_base_url
|
|
113
|
-
|
|
201
|
+
return if poly_only?
|
|
202
|
+
|
|
203
|
+
write_s3_base_url("config/s3_base_url.txt")
|
|
204
|
+
write_s3_base_url("rack/config/s3_base_url.txt") if Jets.rack?
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def write_s3_base_url(relative_path)
|
|
208
|
+
full_path = "#{full(tmp_code)}/#{relative_path}"
|
|
209
|
+
FileUtils.mkdir_p(File.dirname(full_path))
|
|
210
|
+
IO.write(full_path, s3_base_url)
|
|
114
211
|
end
|
|
115
212
|
|
|
116
213
|
def s3_base_url
|
|
@@ -122,50 +219,69 @@ class Jets::Builders
|
|
|
122
219
|
#
|
|
123
220
|
return Jets.config.assets.base_url if Jets.config.assets.base_url
|
|
124
221
|
|
|
125
|
-
resp = cfn.describe_stacks(stack_name: Jets::Naming.parent_stack_name)
|
|
126
|
-
stack = resp.stacks.first
|
|
127
|
-
output = stack["outputs"].find { |o| o["output_key"] == "S3Bucket" }
|
|
128
|
-
bucket_name = output["output_value"] # s3_bucket
|
|
129
222
|
region = Jets.aws.region
|
|
130
223
|
|
|
131
224
|
asset_base_url = "https://s3-#{region}.amazonaws.com"
|
|
132
|
-
"#{asset_base_url}/#{
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def lambdagem_options
|
|
136
|
-
{
|
|
137
|
-
s3: "lambdagems",
|
|
138
|
-
build_root: cache_area, # used in lambdagem
|
|
139
|
-
project_root: full(tmp_app_root), # used in gem_replacer and lambdagem
|
|
140
|
-
}
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def extract_ruby
|
|
144
|
-
headline "Setting up a vendored copy of ruby."
|
|
145
|
-
Lambdagem.log_level = :info
|
|
146
|
-
Lambdagem::Extract::Ruby.new(Jets::RUBY_VERSION, lambdagem_options).run
|
|
225
|
+
"#{asset_base_url}/#{s3_bucket}/jets" # s3_base_url
|
|
147
226
|
end
|
|
148
227
|
|
|
149
|
-
def
|
|
150
|
-
|
|
151
|
-
GemReplacer.new(Jets::RUBY_VERSION, lambdagem_options).run
|
|
228
|
+
def s3_bucket
|
|
229
|
+
Jets.aws.s3_bucket
|
|
152
230
|
end
|
|
153
231
|
|
|
154
|
-
# This happens in the current app directory not the tmp
|
|
232
|
+
# This happens in the current app directory not the tmp code for simplicity.
|
|
233
|
+
# This is because the node and yarn has likely been set up correctly there.
|
|
155
234
|
def compile_assets
|
|
235
|
+
if ENV['JETS_SKIP_ASSETS']
|
|
236
|
+
puts "Skip compiling assets".colorize(:yellow) # useful for debugging
|
|
237
|
+
return
|
|
238
|
+
end
|
|
239
|
+
|
|
156
240
|
headline "Compling assets in current project directory"
|
|
157
241
|
# Thanks: https://stackoverflow.com/questions/4195735/get-list-of-gems-being-used-by-a-bundler-project
|
|
158
242
|
webpacker_loaded = Gem.loaded_specs.keys.include?("webpacker")
|
|
159
243
|
return unless webpacker_loaded
|
|
160
244
|
|
|
161
245
|
sh("yarn install")
|
|
162
|
-
|
|
246
|
+
webpack_command = File.exist?("#{Jets.root}bin/webpack") ?
|
|
163
247
|
"bin/webpack" :
|
|
164
248
|
`which webpack`.strip
|
|
165
|
-
sh("JETS_ENV=#{Jets.env} #{
|
|
249
|
+
sh("JETS_ENV=#{Jets.env} #{webpack_command}")
|
|
166
250
|
end
|
|
167
251
|
time :compile_assets
|
|
168
252
|
|
|
253
|
+
# This happens in the current app directory not the tmp code for simplicity
|
|
254
|
+
# This is because the node likely been set up correctly there.
|
|
255
|
+
def compile_rails_assets
|
|
256
|
+
return unless rails?
|
|
257
|
+
|
|
258
|
+
if ENV['JETS_SKIP_ASSETS']
|
|
259
|
+
puts "Skip compiling rack assets".colorize(:yellow) # useful for debugging
|
|
260
|
+
return
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
return unless Jets.rack?
|
|
264
|
+
|
|
265
|
+
Bundler.with_clean_env do
|
|
266
|
+
rails_assets(:clobber)
|
|
267
|
+
rails_assets(:precompile)
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def rails_assets(cmd)
|
|
272
|
+
# rake is available in both rails 4 and 5. rails command only in 5
|
|
273
|
+
command = "rake assets:#{cmd} --trace"
|
|
274
|
+
command = "RAILS_ENV=#{Jets.env} #{fulL_cmd}" unless Jets.env.development?
|
|
275
|
+
sh("cd rack && #{command}")
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Rudimentary rails detection
|
|
279
|
+
def rails?
|
|
280
|
+
config_ru = "#{Jets.root}rack/config.ru"
|
|
281
|
+
return false unless File.exist?(config_ru)
|
|
282
|
+
!IO.readlines(config_ru).grep(/Rails.application/).empty?
|
|
283
|
+
end
|
|
284
|
+
|
|
169
285
|
# Cleans out non-cached files like code-*.zip in Jets.build_root
|
|
170
286
|
# for a clean start. Also ensure that the /tmp/jets/project build root exists.
|
|
171
287
|
#
|
|
@@ -181,11 +297,14 @@ class Jets::Builders
|
|
|
181
297
|
# directory untouched and we can also remove a bunch of unnecessary files like
|
|
182
298
|
# logs before zipping it up.
|
|
183
299
|
def copy_project
|
|
184
|
-
headline "Copying current project directory to temporary build area: #{full(
|
|
185
|
-
FileUtils.rm_rf(
|
|
300
|
+
headline "Copying current project directory to temporary build area: #{full(tmp_code)}"
|
|
301
|
+
FileUtils.rm_rf(stage_area) # clear out from previous build
|
|
302
|
+
FileUtils.mkdir_p(stage_area)
|
|
303
|
+
FileUtils.rm_rf(full(tmp_code)) # remove current code folder
|
|
186
304
|
move_node_modules(Jets.root, Jets.build_root)
|
|
187
305
|
begin
|
|
188
|
-
|
|
306
|
+
# puts "cp -r #{@full_project_path} #{full(tmp_code)}".colorize(:yellow) # uncomment to debug
|
|
307
|
+
FileUtils.cp_r(@full_project_path, full(tmp_code))
|
|
189
308
|
ensure
|
|
190
309
|
move_node_modules(Jets.build_root, Jets.root) # move node_modules directory back
|
|
191
310
|
end
|
|
@@ -205,35 +324,13 @@ class Jets::Builders
|
|
|
205
324
|
end
|
|
206
325
|
end
|
|
207
326
|
|
|
208
|
-
# Because we're removing files (something dangerous) use full paths.
|
|
209
|
-
def tidy_project
|
|
210
|
-
headline "Tidying project: removing ignored files to reduce package size."
|
|
211
|
-
excludes.each do |exclude|
|
|
212
|
-
exclude = exclude.sub(%r{^/},'') # remove leading slash
|
|
213
|
-
remove_path = "#{full(tmp_app_root)}/#{exclude}"
|
|
214
|
-
FileUtils.rm_rf(remove_path)
|
|
215
|
-
# puts " rm -rf #{remove_path}" # uncomment to debug
|
|
216
|
-
end
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
def generate_node_shims
|
|
220
|
-
headline "Generating node shims in the handlers folder."
|
|
221
|
-
# Crucial that the Dir.pwd is in the tmp_app_root because for
|
|
222
|
-
# Jets::Builders::app_files because Jets.boot set ups
|
|
223
|
-
# autoload_paths and this is how project classes are loaded.
|
|
224
|
-
Jets::Commands::Build.app_files.each do |path|
|
|
225
|
-
handler = Jets::Builders::HandlerGenerator.new(path)
|
|
226
|
-
handler.generate
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
|
|
230
327
|
# Bit hacky but this saves the user from accidentally forgetting to change this
|
|
231
328
|
# when they deploy a jets project in development mode
|
|
232
329
|
def reconfigure_development_webpacker
|
|
233
330
|
return unless Jets.env.development?
|
|
234
331
|
headline "Reconfiguring webpacker development settings for AWS Lambda."
|
|
235
332
|
|
|
236
|
-
webpacker_yml = "#{full(
|
|
333
|
+
webpacker_yml = "#{full(tmp_code)}/config/webpacker.yml"
|
|
237
334
|
return unless File.exist?(webpacker_yml)
|
|
238
335
|
|
|
239
336
|
config = YAML.load_file(webpacker_yml)
|
|
@@ -242,199 +339,28 @@ class Jets::Builders
|
|
|
242
339
|
IO.write(webpacker_yml, new_yaml)
|
|
243
340
|
end
|
|
244
341
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
# The lambda server only has ruby 2.5.0 installed.
|
|
248
|
-
def reconfigure_ruby_version
|
|
249
|
-
ruby_version = "#{full(tmp_app_root)}/.ruby-version"
|
|
250
|
-
IO.write(ruby_version, Jets::RUBY_VERSION)
|
|
342
|
+
def ruby_packager
|
|
343
|
+
RubyPackager.new(tmp_code)
|
|
251
344
|
end
|
|
345
|
+
memoize :ruby_packager
|
|
252
346
|
|
|
253
|
-
def
|
|
254
|
-
|
|
255
|
-
if File.exist?(app_root_bundled)
|
|
256
|
-
puts "Removing current bundled from project"
|
|
257
|
-
FileUtils.rm_rf(app_root_bundled)
|
|
258
|
-
end
|
|
259
|
-
# Leave #{Jets.build_root}/bundled behind to act as cache
|
|
260
|
-
FileUtils.cp_r("#{cache_area}/bundled", app_root_bundled)
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
def setup_bundle_config
|
|
264
|
-
ensure_build_cache_bundle_config_exists!
|
|
265
|
-
|
|
266
|
-
# Override project's .bundle/config and ensure that .bundle/config matches
|
|
267
|
-
# at these 2 spots:
|
|
268
|
-
# app_root/.bundle/config
|
|
269
|
-
# bundled/gems/.bundle/config
|
|
270
|
-
cache_bundle_config = "#{cache_area}/.bundle/config"
|
|
271
|
-
app_bundle_config = "#{full(tmp_app_root)}/.bundle/config"
|
|
272
|
-
FileUtils.mkdir_p(File.dirname(app_bundle_config))
|
|
273
|
-
FileUtils.cp(cache_bundle_config, app_bundle_config)
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
# On circleci the "#{Jets.build_root}/.bundle/config" doesnt exist
|
|
277
|
-
# this only happens with ssh debugging, not when the ci.sh script gets ran.
|
|
278
|
-
# But on macosx it exists.
|
|
279
|
-
# Dont know why this is the case.
|
|
280
|
-
def ensure_build_cache_bundle_config_exists!
|
|
281
|
-
text =<<-EOL
|
|
282
|
-
---
|
|
283
|
-
BUNDLE_PATH: "bundled/gems"
|
|
284
|
-
BUNDLE_WITHOUT: "development:test"
|
|
285
|
-
EOL
|
|
286
|
-
bundle_config = "#{cache_area}/.bundle/config"
|
|
287
|
-
FileUtils.mkdir_p(File.dirname(bundle_config))
|
|
288
|
-
IO.write(bundle_config, text)
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
def create_zip_file(fake=nil)
|
|
292
|
-
headline "Creating zip file."
|
|
293
|
-
temp_code_zipfile = "#{Jets.build_root}/code/code-temp.zip"
|
|
294
|
-
FileUtils.mkdir_p(File.dirname(temp_code_zipfile))
|
|
295
|
-
|
|
296
|
-
# Use fake if testing CloudFormation only
|
|
297
|
-
if fake
|
|
298
|
-
hello_world = "/tmp/hello.js"
|
|
299
|
-
puts "Uploading tiny #{hello_world} file to S3 for quick testing.".colorize(:red)
|
|
300
|
-
code = IO.read(File.expand_path("../node-hello.js", __FILE__))
|
|
301
|
-
IO.write(hello_world, code)
|
|
302
|
-
command = "zip --symlinks -rq #{temp_code_zipfile} #{hello_world}"
|
|
303
|
-
else
|
|
304
|
-
# https://serverfault.com/questions/265675/how-can-i-zip-compress-a-symlink
|
|
305
|
-
command = "cd #{full(tmp_app_root)} && zip --symlinks -rq #{temp_code_zipfile} ."
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
sh(command)
|
|
309
|
-
|
|
310
|
-
# we can get the md5 only after the file has been created
|
|
311
|
-
md5 = Digest::MD5.file(temp_code_zipfile).to_s[0..7]
|
|
312
|
-
md5_zip_dest = "#{Jets.build_root}/code/code-#{md5}.zip"
|
|
313
|
-
FileUtils.mkdir_p(File.dirname(md5_zip_dest))
|
|
314
|
-
FileUtils.mv(temp_code_zipfile, md5_zip_dest)
|
|
315
|
-
# mv /tmp/jets/demo/code/code-temp.zip /tmp/jets/demo/code/code-a8a604aa.zip
|
|
316
|
-
|
|
317
|
-
file_size = number_to_human_size(File.size(md5_zip_dest))
|
|
318
|
-
puts "Zip file with code and bundled linux ruby created at: #{md5_zip_dest.colorize(:green)} (#{file_size})"
|
|
319
|
-
|
|
320
|
-
# Save state
|
|
321
|
-
IO.write("#{Jets.build_root}/code/current-md5-filename.txt", md5_zip_dest)
|
|
322
|
-
# Much later: ship, base_child_builder need set an s3_key which requires
|
|
323
|
-
# the md5_zip_dest.
|
|
324
|
-
# It is a pain to pass this all the way up from the
|
|
325
|
-
# CodeBuilder class.
|
|
326
|
-
# Let's store the "/tmp/jets/demo/code/code-a8a604aa.zip" into a
|
|
327
|
-
# file that can be read from any places where this is needed.
|
|
328
|
-
# Can also just generate a "fake file" for specs
|
|
347
|
+
def rack_packager
|
|
348
|
+
RackPackager.new("#{tmp_code}/rack")
|
|
329
349
|
end
|
|
330
|
-
|
|
350
|
+
memoize :rack_packager
|
|
331
351
|
|
|
332
|
-
def
|
|
333
|
-
|
|
334
|
-
|
|
352
|
+
def package_ruby
|
|
353
|
+
ruby_packager.install
|
|
354
|
+
reconfigure_rails
|
|
355
|
+
rack_packager.install
|
|
356
|
+
ruby_packager.finish
|
|
357
|
+
rack_packager.finish
|
|
335
358
|
end
|
|
336
|
-
time :
|
|
337
|
-
|
|
338
|
-
# Installs gems on the current target system: both compiled and non-compiled.
|
|
339
|
-
# If user is on a macosx machine, macosx gems will be installed.
|
|
340
|
-
# If user is on a linux machine, linux gems will be installed.
|
|
341
|
-
#
|
|
342
|
-
# Copies Gemfile* to /tmp/jetss/demo/bundled folder and installs
|
|
343
|
-
# gems with bundle install from there.
|
|
344
|
-
#
|
|
345
|
-
# We take the time to copy Gemfile and bundle into a separate directory
|
|
346
|
-
# because it gets left around to act as a 'cache'. So, when the builds the
|
|
347
|
-
# project gets built again not all the gems from get installed from the
|
|
348
|
-
# beginning.
|
|
349
|
-
def bundle_install
|
|
350
|
-
return if poly_only?
|
|
351
|
-
|
|
352
|
-
headline "Bundling: running bundle install in cache area: #{cache_area}."
|
|
359
|
+
time :package_ruby
|
|
353
360
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
Bundler.with_clean_env do
|
|
358
|
-
# cd /tmp/jets/demo
|
|
359
|
-
sh(
|
|
360
|
-
"cd #{cache_area} && " \
|
|
361
|
-
"env BUNDLE_IGNORE_CONFIG=1 bundle install --path bundled/gems --without development test"
|
|
362
|
-
)
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
puts 'Bundle install success.'
|
|
366
|
-
end
|
|
367
|
-
|
|
368
|
-
# When using submodules, bundler leaves old submodules behind. Over time this inflates
|
|
369
|
-
# the size of the the bundled gems. So we'll clean it up.
|
|
370
|
-
def clean_old_submodules
|
|
371
|
-
# https://stackoverflow.com/questions/38800129/parsing-a-gemfile-lock-with-bundler
|
|
372
|
-
lockfile = "#{cache_area}/Gemfile.lock"
|
|
373
|
-
return unless File.exist?(lockfile)
|
|
374
|
-
|
|
375
|
-
parser = Bundler::LockfileParser.new(Bundler.read_file(lockfile))
|
|
376
|
-
specs = parser.specs
|
|
377
|
-
|
|
378
|
-
# specs = Bundler.load.specs
|
|
379
|
-
# IE: spec.source.to_s: "https://github.com/tongueroo/webpacker.git (at jets@a8c4661)"
|
|
380
|
-
submoduled_specs = specs.select do |spec|
|
|
381
|
-
spec.source.to_s =~ /@\w+\)/
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
# find git shas to keep
|
|
385
|
-
# IE: ["a8c4661", "abc4661"]
|
|
386
|
-
git_shas = submoduled_specs.map do |spec|
|
|
387
|
-
md = spec.source.to_s.match(/@(\w+)\)/)
|
|
388
|
-
git_sha = md[1]
|
|
389
|
-
end
|
|
390
|
-
|
|
391
|
-
# IE: /tmp/jets/demo/cache/bundled/gems/ruby/2.5.0/bundler/gems/webpacker-a8c46614c675
|
|
392
|
-
Dir.glob("#{cache_area}/bundled/gems/ruby/2.5.0/bundler/gems/*").each do |path|
|
|
393
|
-
sha = path.split('-').last[0..6] # only first 7 chars of the git sha
|
|
394
|
-
unless git_shas.include?(sha)
|
|
395
|
-
puts "Removing old submoduled gem: #{path}"
|
|
396
|
-
FileUtils.rm_rf(path) # REMOVE old submodule directory
|
|
397
|
-
end
|
|
398
|
-
end
|
|
399
|
-
end
|
|
400
|
-
|
|
401
|
-
def copy_gemfiles
|
|
402
|
-
FileUtils.mkdir_p(cache_area)
|
|
403
|
-
FileUtils.cp("#{@full_project_path}Gemfile", "#{cache_area}/Gemfile")
|
|
404
|
-
FileUtils.cp("#{@full_project_path}Gemfile.lock", "#{cache_area}/Gemfile.lock")
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
def excludes
|
|
408
|
-
excludes = %w[.git tmp log spec]
|
|
409
|
-
excludes += get_excludes("#{full(tmp_app_root)}/.gitignore")
|
|
410
|
-
excludes += get_excludes("#{full(tmp_app_root)}/.dockerignore")
|
|
411
|
-
excludes = excludes.reject do |p|
|
|
412
|
-
jetskeep.find do |keep|
|
|
413
|
-
p.include?(keep)
|
|
414
|
-
end
|
|
415
|
-
end
|
|
416
|
-
excludes
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
def get_excludes(file)
|
|
420
|
-
path = file
|
|
421
|
-
return [] unless File.exist?(path)
|
|
422
|
-
|
|
423
|
-
exclude = File.read(path).split("\n")
|
|
424
|
-
exclude.map {|i| i.strip}.reject {|i| i =~ /^#/ || i.empty?}
|
|
425
|
-
# IE: ["/handlers", "/bundled*", "/vendor/jets]
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
# We clean out ignored files pretty aggressively. So provide
|
|
429
|
-
# a way for users to keep files from being cleaned ou.
|
|
430
|
-
def jetskeep
|
|
431
|
-
defaults = %w[pack handlers]
|
|
432
|
-
path = Jets.root + ".jetskeep"
|
|
433
|
-
return defaults unless path.exist?
|
|
434
|
-
|
|
435
|
-
keep = path.read.split("\n")
|
|
436
|
-
keep = keep.map {|i| i.strip}.reject {|i| i =~ /^#/ || i.empty?}
|
|
437
|
-
(defaults + keep).uniq
|
|
361
|
+
# TODO: Move logic into plugin instead
|
|
362
|
+
def reconfigure_rails
|
|
363
|
+
ReconfigureRails.new("#{full(tmp_code)}/rack").run
|
|
438
364
|
end
|
|
439
365
|
|
|
440
366
|
def cache_check_message
|
|
@@ -461,34 +387,13 @@ EOL
|
|
|
461
387
|
ruby[:major] == jets[:major] && ruby[:minor] == jets[:minor]
|
|
462
388
|
end
|
|
463
389
|
|
|
464
|
-
def cache_area
|
|
465
|
-
"#{Jets.build_root}/cache" # cleaner to use full path for this setting
|
|
466
|
-
end
|
|
467
|
-
|
|
468
|
-
# Provide pretty clear way to desinate full path.
|
|
469
|
-
# full("bundled") => /tmp/jets/demo/bundled
|
|
470
|
-
def full(relative_path)
|
|
471
|
-
"#{Jets.build_root}/#{relative_path}"
|
|
472
|
-
end
|
|
473
|
-
|
|
474
390
|
# Group all the path settings together here
|
|
475
|
-
def self.
|
|
476
|
-
Jets::Commands::Build.
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
def tmp_app_root
|
|
480
|
-
self.class.tmp_app_root
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
def sh(command)
|
|
484
|
-
puts "=> #{command}".colorize(:green)
|
|
485
|
-
success = system(command)
|
|
486
|
-
abort("#{command} failed to run") unless success
|
|
487
|
-
success
|
|
391
|
+
def self.tmp_code
|
|
392
|
+
Jets::Commands::Build.tmp_code
|
|
488
393
|
end
|
|
489
394
|
|
|
490
|
-
def
|
|
491
|
-
|
|
395
|
+
def tmp_code
|
|
396
|
+
self.class.tmp_code
|
|
492
397
|
end
|
|
493
398
|
end
|
|
494
399
|
end
|
|
@@ -79,7 +79,7 @@ Jets is unable to build a deployment package that will work on AWS Lambda withou
|
|
|
79
79
|
* Wait until it added to lambdagems.com. No need to report this to us, as we've already been notified.
|
|
80
80
|
* Use another gem that does not require compilation.
|
|
81
81
|
|
|
82
|
-
Compiled gems usually take some time to figure out how to build as they each depend on different libraries and packages. We make an effort add new gems as soon as we can.
|
|
82
|
+
Compiled gems usually take some time to figure out how to build as they each depend on different libraries and packages. We make an effort add new gems as soon as we can.
|
|
83
83
|
EOL
|
|
84
84
|
erb = ERB.new(template, nil, '-') # trim mode https://stackoverflow.com/questions/4632879/erb-template-removing-the-trailing-line
|
|
85
85
|
erb.result(binding)
|