jets 0.2.0 → 0.5.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.
Files changed (292) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/bin/commit_docs.sh +26 -0
  3. data/.circleci/config.yml +126 -0
  4. data/.codebuild/README.md +57 -0
  5. data/.codebuild/bin/jets +3 -0
  6. data/.codebuild/buildspec-base.yml +14 -0
  7. data/.codebuild/integration.sh +54 -0
  8. data/.codebuild/jets.postman_collection.json +323 -0
  9. data/.codebuild/scripts/install-docker.sh +12 -0
  10. data/.codebuild/scripts/install-dynamodb-local.sh +22 -0
  11. data/.codebuild/scripts/install-java.sh +20 -0
  12. data/.codebuild/scripts/install-node.sh +4 -0
  13. data/.gitignore +3 -0
  14. data/.gitmodules +9 -0
  15. data/.python-version +1 -0
  16. data/.rspec +2 -0
  17. data/.ruby-version +1 -1
  18. data/CHANGELOG.md +3 -0
  19. data/Dockerfile +16 -0
  20. data/Dockerfile.base +53 -0
  21. data/Gemfile +8 -1
  22. data/Gemfile.lock +132 -28
  23. data/LICENSE.txt +1 -1
  24. data/Procfile +2 -0
  25. data/README.md +116 -17
  26. data/Rakefile +6 -0
  27. data/buildspec.yml +18 -0
  28. data/exe/jets +14 -0
  29. data/jets.gemspec +31 -3
  30. data/lib/jets.rb +56 -8
  31. data/lib/jets/application.rb +121 -0
  32. data/lib/jets/application/middleware.rb +23 -0
  33. data/lib/jets/aws_services.rb +71 -0
  34. data/lib/jets/booter.rb +95 -0
  35. data/lib/jets/builders.rb +6 -0
  36. data/lib/jets/builders/code_builder.rb +431 -0
  37. data/lib/jets/builders/deducer.rb +73 -0
  38. data/lib/jets/builders/gem_replacer.rb +154 -0
  39. data/lib/jets/builders/handler_generator.rb +76 -0
  40. data/lib/jets/builders/node-hello.js +73 -0
  41. data/lib/jets/builders/node-shim.js +151 -0
  42. data/lib/jets/cfn.rb +5 -4
  43. data/lib/jets/cfn/ship.rb +178 -0
  44. data/lib/jets/cfn/status.rb +208 -0
  45. data/lib/jets/cfn/template_builders.rb +21 -0
  46. data/lib/jets/cfn/template_builders/api_gateway_builder.rb +73 -0
  47. data/lib/jets/cfn/template_builders/api_gateway_deployment_builder.rb +38 -0
  48. data/lib/jets/cfn/template_builders/base_child_builder.rb +38 -0
  49. data/lib/jets/cfn/template_builders/controller_builder.rb +107 -0
  50. data/lib/jets/cfn/template_builders/function_builder.rb +20 -0
  51. data/lib/jets/cfn/template_builders/function_properties.rb +6 -0
  52. data/lib/jets/cfn/template_builders/function_properties/base_builder.rb +106 -0
  53. data/lib/jets/cfn/template_builders/function_properties/node_builder.rb +12 -0
  54. data/lib/jets/cfn/template_builders/function_properties/python_builder.rb +12 -0
  55. data/lib/jets/cfn/template_builders/function_properties/ruby_builder.rb +13 -0
  56. data/lib/jets/cfn/template_builders/interface.rb +91 -0
  57. data/lib/jets/cfn/template_builders/job_builder.rb +63 -0
  58. data/lib/jets/cfn/template_builders/parent_builder.rb +97 -0
  59. data/lib/jets/cfn/template_builders/rule_builder.rb +55 -0
  60. data/lib/jets/cfn/template_builders/templates/minimal-stack.yml +45 -0
  61. data/lib/jets/cfn/template_mappers.rb +23 -0
  62. data/lib/jets/cfn/template_mappers/api_gateway_deployment_mapper.rb +48 -0
  63. data/lib/jets/cfn/template_mappers/api_gateway_mapper.rb +4 -0
  64. data/lib/jets/cfn/template_mappers/child_mapper.rb +41 -0
  65. data/lib/jets/cfn/template_mappers/config_rule_mapper.rb +34 -0
  66. data/lib/jets/cfn/template_mappers/controller_mapper.rb +36 -0
  67. data/lib/jets/cfn/template_mappers/events_rule_mapper.rb +40 -0
  68. data/lib/jets/cfn/template_mappers/function_mapper.rb +4 -0
  69. data/lib/jets/cfn/template_mappers/gateway_method_mapper.rb +56 -0
  70. data/lib/jets/cfn/template_mappers/gateway_resource_mapper.rb +62 -0
  71. data/lib/jets/cfn/template_mappers/job_mapper.rb +4 -0
  72. data/lib/jets/cfn/template_mappers/lambda_function_mapper.rb +50 -0
  73. data/lib/jets/cfn/template_mappers/rule_mapper.rb +5 -0
  74. data/lib/jets/cli.rb +180 -15
  75. data/lib/jets/commands.rb +22 -0
  76. data/lib/jets/commands/base.rb +151 -0
  77. data/lib/jets/commands/build.rb +186 -0
  78. data/lib/jets/commands/call.rb +175 -0
  79. data/lib/jets/commands/call/anonymous_guesser.rb +96 -0
  80. data/lib/jets/commands/call/autoload_guesser.rb +112 -0
  81. data/lib/jets/commands/call/base_guesser.rb +33 -0
  82. data/lib/jets/commands/call/guesser.rb +51 -0
  83. data/lib/jets/commands/console.rb +12 -0
  84. data/lib/jets/commands/db.rb +15 -0
  85. data/lib/jets/commands/db/environment-task.rake +3 -0
  86. data/lib/jets/commands/db/tasks.rb +30 -0
  87. data/lib/jets/commands/dbconsole.rb +131 -0
  88. data/lib/jets/commands/delete.rb +119 -0
  89. data/lib/jets/commands/deploy.rb +53 -0
  90. data/lib/jets/commands/dynamodb.rb +22 -0
  91. data/lib/jets/commands/dynamodb/migrate.rb +9 -0
  92. data/lib/jets/commands/dynamodb/migrator.rb +36 -0
  93. data/lib/jets/commands/help.rb +9 -0
  94. data/lib/jets/commands/help/build.md +1 -0
  95. data/lib/jets/commands/help/call.md +55 -0
  96. data/lib/jets/commands/help/console.md +4 -0
  97. data/lib/jets/commands/help/db/generate.md +8 -0
  98. data/lib/jets/commands/help/dbconsole.md +5 -0
  99. data/lib/jets/commands/help/delete.md +9 -0
  100. data/lib/jets/commands/help/deploy.md +5 -0
  101. data/lib/jets/commands/help/dynamodb/generate.md +50 -0
  102. data/lib/jets/commands/help/dynamodb/migrate.md +4 -0
  103. data/lib/jets/commands/help/generate.md +5 -0
  104. data/lib/jets/commands/help/new.md +9 -0
  105. data/lib/jets/commands/help/process/controller.md +6 -0
  106. data/lib/jets/commands/help/process/function.md +5 -0
  107. data/lib/jets/commands/help/process/job.md +5 -0
  108. data/lib/jets/commands/help/process/rule.md +5 -0
  109. data/lib/jets/commands/help/routes.md +3 -0
  110. data/lib/jets/commands/help/server.md +6 -0
  111. data/lib/jets/commands/help/status.md +1 -0
  112. data/lib/jets/commands/help/url.md +5 -0
  113. data/lib/jets/commands/main.rb +111 -0
  114. data/lib/jets/commands/markdown.rb +8 -0
  115. data/lib/jets/commands/markdown/creator.rb +58 -0
  116. data/lib/jets/commands/markdown/index.rb +27 -0
  117. data/lib/jets/commands/markdown/page.rb +125 -0
  118. data/lib/jets/commands/markdown/shell.rb +11 -0
  119. data/lib/jets/commands/new.rb +110 -0
  120. data/lib/jets/commands/rake_command.rb +61 -0
  121. data/lib/jets/commands/rake_tasks.rb +45 -0
  122. data/lib/jets/commands/sequence.rb +44 -0
  123. data/lib/jets/commands/stack_info.rb +30 -0
  124. data/lib/jets/commands/templates/skeleton/.env +2 -0
  125. data/lib/jets/commands/templates/skeleton/.env.development.tt +3 -0
  126. data/lib/jets/commands/templates/skeleton/.env.test +3 -0
  127. data/lib/jets/commands/templates/skeleton/.gitignore +14 -0
  128. data/lib/jets/commands/templates/skeleton/.jetskeep +1 -0
  129. data/lib/jets/commands/templates/skeleton/Gemfile.tt +27 -0
  130. data/lib/jets/commands/templates/skeleton/Procfile +7 -0
  131. data/lib/jets/commands/templates/skeleton/README.md +4 -0
  132. data/lib/jets/commands/templates/skeleton/Rakefile +2 -0
  133. data/lib/jets/commands/templates/skeleton/app/controllers/application_controller.rb +2 -0
  134. data/lib/jets/commands/templates/skeleton/app/helpers/application_helper.rb +2 -0
  135. data/lib/jets/commands/templates/skeleton/app/jobs/application_job.rb +2 -0
  136. data/lib/jets/commands/templates/skeleton/app/models/application_item.rb +2 -0
  137. data/lib/jets/commands/templates/skeleton/app/models/application_record.rb +3 -0
  138. data/lib/jets/commands/templates/skeleton/app/views/layouts/application.html.erb.tt +24 -0
  139. data/lib/jets/commands/templates/skeleton/bin/ruby_server +18 -0
  140. data/lib/jets/commands/templates/skeleton/bin/ruby_server.rb +2 -0
  141. data/lib/jets/commands/templates/skeleton/config.ru +4 -0
  142. data/lib/jets/commands/templates/skeleton/config/application.rb.tt +26 -0
  143. data/lib/jets/commands/templates/skeleton/config/database.yml.tt +27 -0
  144. data/lib/jets/commands/templates/skeleton/config/dynamodb.yml +25 -0
  145. data/lib/jets/commands/templates/skeleton/config/routes.rb +8 -0
  146. data/lib/jets/commands/templates/skeleton/db/.gitkeep +0 -0
  147. data/lib/jets/commands/templates/skeleton/public/404.html +67 -0
  148. data/lib/jets/commands/templates/skeleton/public/422.html +67 -0
  149. data/lib/jets/commands/templates/skeleton/public/500.html +66 -0
  150. data/lib/jets/commands/templates/skeleton/public/favicon.ico +0 -0
  151. data/lib/jets/commands/templates/skeleton/public/index.html.tt +79 -0
  152. data/lib/jets/commands/templates/skeleton/spec/controllers/posts_controller_spec.rb +18 -0
  153. data/lib/jets/commands/templates/skeleton/spec/fixtures/payloads/posts-index.json +51 -0
  154. data/lib/jets/commands/templates/skeleton/spec/fixtures/payloads/posts-show.json +53 -0
  155. data/lib/jets/commands/templates/skeleton/spec/spec_helper.rb.tt +27 -0
  156. data/lib/jets/commands/templates/webpacker/app/javascript/packs/application.js.tt +14 -0
  157. data/lib/jets/commands/templates/webpacker/app/javascript/packs/theme.scss.tt +24 -0
  158. data/lib/jets/commands/templates/webpacker/app/javascript/src/jets/crud.js +87 -0
  159. data/lib/jets/commands/url.rb +45 -0
  160. data/lib/jets/commands/webpacker_template.rb +19 -0
  161. data/lib/jets/controller.rb +9 -0
  162. data/lib/jets/controller/base.rb +50 -0
  163. data/lib/jets/controller/callbacks.rb +43 -0
  164. data/lib/jets/controller/layout.rb +17 -0
  165. data/lib/jets/controller/params.rb +53 -0
  166. data/lib/jets/controller/redirection.rb +55 -0
  167. data/lib/jets/controller/renderers.rb +5 -0
  168. data/lib/jets/controller/renderers/aws_proxy_renderer.rb +69 -0
  169. data/lib/jets/controller/renderers/base_renderer.rb +16 -0
  170. data/lib/jets/controller/renderers/template_renderer.rb +107 -0
  171. data/lib/jets/controller/rendering.rb +80 -0
  172. data/lib/jets/controller/request.rb +55 -0
  173. data/lib/jets/core.rb +81 -0
  174. data/lib/jets/default/application.rb +20 -0
  175. data/lib/jets/dotenv.rb +37 -0
  176. data/lib/jets/erb.rb +51 -0
  177. data/lib/jets/generator.rb +40 -0
  178. data/lib/jets/generator/templates/erb/controller/view.html.erb +2 -0
  179. data/lib/jets/generator/templates/erb/scaffold/_form.html.erb +39 -0
  180. data/lib/jets/generator/templates/erb/scaffold/edit.html.erb +6 -0
  181. data/lib/jets/generator/templates/erb/scaffold/index.html.erb +29 -0
  182. data/lib/jets/generator/templates/erb/scaffold/new.html.erb +5 -0
  183. data/lib/jets/generator/templates/erb/scaffold/show.html.erb +9 -0
  184. data/lib/jets/generator/templates/rails/assets/javascript.js +2 -0
  185. data/lib/jets/generator/templates/rails/assets/stylesheet.css +4 -0
  186. data/lib/jets/generator/templates/rails/controller/controller.rb +13 -0
  187. data/lib/jets/generator/templates/rails/helper/helper.rb +4 -0
  188. data/lib/jets/generator/templates/rails/scaffold/scaffold.css +80 -0
  189. data/lib/jets/generator/templates/rails/scaffold_controller/api_controller.rb +62 -0
  190. data/lib/jets/generator/templates/rails/scaffold_controller/controller.rb +71 -0
  191. data/lib/jets/internal/app/controllers/jets/public_controller.rb +30 -0
  192. data/lib/jets/internal/app/controllers/jets/public_controller/python/show.py +47 -0
  193. data/lib/jets/internal/app/controllers/jets/public_controller/python/show.pyc +0 -0
  194. data/lib/jets/internal/app/controllers/jets/welcome_controller.rb +22 -0
  195. data/lib/jets/internal/app/controllers/jets/welcome_controller/python/index.py +24 -0
  196. data/lib/jets/internal/app/jobs/jets/preheat_job.rb +52 -0
  197. data/lib/jets/job.rb +5 -0
  198. data/lib/jets/job/base.rb +29 -0
  199. data/lib/jets/job/dsl.rb +58 -0
  200. data/lib/jets/job/task.rb +17 -0
  201. data/lib/jets/klass.rb +71 -0
  202. data/lib/jets/lambda.rb +18 -0
  203. data/lib/jets/lambda/dsl.rb +153 -0
  204. data/lib/jets/lambda/function.rb +29 -0
  205. data/lib/jets/lambda/function_constructor.rb +60 -0
  206. data/lib/jets/lambda/functions.rb +22 -0
  207. data/lib/jets/lambda/task.rb +77 -0
  208. data/lib/jets/naming.rb +61 -0
  209. data/lib/jets/pascalize.rb +30 -0
  210. data/lib/jets/poly_fun.rb +61 -0
  211. data/lib/jets/poly_fun/base_executor.rb +129 -0
  212. data/lib/jets/poly_fun/lambda_executor.rb +16 -0
  213. data/lib/jets/poly_fun/node_error.rb +8 -0
  214. data/lib/jets/poly_fun/node_executor.rb +54 -0
  215. data/lib/jets/poly_fun/python_error.rb +8 -0
  216. data/lib/jets/poly_fun/python_executor.rb +23 -0
  217. data/lib/jets/preheat.rb +72 -0
  218. data/lib/jets/processors.rb +4 -0
  219. data/lib/jets/processors/deducer.rb +54 -0
  220. data/lib/jets/processors/main_processor.rb +57 -0
  221. data/lib/jets/rails_overrides.rb +4 -0
  222. data/lib/jets/rails_overrides/asset_tag_helper.rb +41 -0
  223. data/lib/jets/rails_overrides/common_methods.rb +13 -0
  224. data/lib/jets/rails_overrides/rendering_helper.rb +26 -0
  225. data/lib/jets/rails_overrides/url_helper.rb +26 -0
  226. data/lib/jets/route.rb +145 -0
  227. data/lib/jets/router.rb +115 -0
  228. data/lib/jets/ruby_server.rb +91 -0
  229. data/lib/jets/rule.rb +5 -0
  230. data/lib/jets/rule/base.rb +19 -0
  231. data/lib/jets/rule/dsl.rb +64 -0
  232. data/lib/jets/rule/task.rb +44 -0
  233. data/lib/jets/server.rb +16 -0
  234. data/lib/jets/server/api_gateway.rb +39 -0
  235. data/lib/jets/server/lambda_aws_proxy.rb +122 -0
  236. data/lib/jets/server/route_matcher.rb +96 -0
  237. data/lib/jets/server/timing_middleware.rb +16 -0
  238. data/lib/jets/server/webpacker_setup.rb +7 -0
  239. data/lib/jets/timing.rb +65 -0
  240. data/lib/jets/timing/report.rb +82 -0
  241. data/lib/jets/util.rb +7 -12
  242. data/lib/jets/version.rb +1 -1
  243. data/support/clean +3 -0
  244. data/support/console +3 -0
  245. metadata +473 -76
  246. data/bin/jets +0 -14
  247. data/lib/jets/base_controller.rb +0 -54
  248. data/lib/jets/build.rb +0 -46
  249. data/lib/jets/build/handler_generator.rb +0 -46
  250. data/lib/jets/build/lambda_deducer.rb +0 -23
  251. data/lib/jets/build/templates/handler.js +0 -149
  252. data/lib/jets/build/traveling_ruby.rb +0 -133
  253. data/lib/jets/cfn/base.rb +0 -17
  254. data/lib/jets/cfn/builder.rb +0 -53
  255. data/lib/jets/cfn/namer.rb +0 -30
  256. data/lib/jets/cli/help.rb +0 -19
  257. data/lib/jets/command.rb +0 -25
  258. data/lib/jets/process.rb +0 -18
  259. data/lib/jets/process/base_processor.rb +0 -23
  260. data/lib/jets/process/controller_processor.rb +0 -36
  261. data/lib/jets/process/help.rb +0 -11
  262. data/lib/jets/process/processor_deducer.rb +0 -51
  263. data/lib/jets/project.rb +0 -23
  264. data/notes/design.md +0 -107
  265. data/notes/faq.md +0 -3
  266. data/notes/lambda_ruby_info.md +0 -34
  267. data/notes/traveling-ruby-packaging-jets.md +0 -26
  268. data/notes/traveling-ruby-packaging.md +0 -103
  269. data/notes/traveling-ruby-structure.md +0 -6
  270. data/notes/traveling-ruby.md +0 -82
  271. data/spec/fixtures/classes.rb +0 -5
  272. data/spec/fixtures/project/.gitignore +0 -3
  273. data/spec/fixtures/project/.ruby-version +0 -1
  274. data/spec/fixtures/project/Gemfile +0 -4
  275. data/spec/fixtures/project/Gemfile.lock +0 -23
  276. data/spec/fixtures/project/app/controllers/application_controller.rb +0 -2
  277. data/spec/fixtures/project/app/controllers/posts_controller.rb +0 -12
  278. data/spec/fixtures/project/bin/jets +0 -22
  279. data/spec/fixtures/project/config/routes.rb +0 -6
  280. data/spec/fixtures/project/handlers/controllers/posts.js +0 -212
  281. data/spec/lib/cli_spec.rb +0 -20
  282. data/spec/lib/jets/base_controller_spec.rb +0 -18
  283. data/spec/lib/jets/build/handler_generator_spec.rb +0 -20
  284. data/spec/lib/jets/build/lambda_deducer_spec.rb +0 -15
  285. data/spec/lib/jets/build_spec.rb +0 -34
  286. data/spec/lib/jets/cfn/builder_spec.rb +0 -18
  287. data/spec/lib/jets/cfn/namer_spec.rb +0 -16
  288. data/spec/lib/jets/process/controller_processor_spec.rb +0 -22
  289. data/spec/lib/jets/process/infer_spec.rb +0 -24
  290. data/spec/lib/jets/process_spec.rb +0 -18
  291. data/spec/lib/jets/project_spec.rb +0 -14
  292. data/spec/spec_helper.rb +0 -28
@@ -0,0 +1,6 @@
1
+ class Jets::Builders
2
+ autoload :Deducer, "jets/builders/deducer"
3
+ autoload :HandlerGenerator, "jets/builders/handler_generator"
4
+ autoload :CodeBuilder, "jets/builders/code_builder"
5
+ autoload :GemReplacer, "jets/builders/gem_replacer"
6
+ end
@@ -0,0 +1,431 @@
1
+ require "fileutils"
2
+ require "open-uri"
3
+ require "colorize"
4
+ require "socket"
5
+ require "net/http"
6
+ require "action_view"
7
+
8
+ # Some important folders to help understand how jets builds a project:
9
+ #
10
+ # /tmp/jets: build root where different jets projects get built.
11
+ # /tmp/jets/project: each jets project gets built in a different subdirectory.
12
+ #
13
+ # The rest of the folders are subfolders under /tmp/jets/project:
14
+ #
15
+ # cache: Gemfile is here, this is where we run bundle install.
16
+ # cache/bundled/gems: Vendored gems that get created as part of bundled install.
17
+ # Initially, macosx gems but then get replaced by linux gems where appropriate.
18
+ # cache/downloads/rubies: ruby tarballs.
19
+ # cache/downloads/gems: gem tarballs.
20
+ # app_root: Where project gets copied into in order for us to configure it.
21
+ # app_root/bundled/gems: Where vendored gems finally end up at. The compiled
22
+ # gems at this point are only linux gems.
23
+ # artifacts/code/code-md5sha.zip: code artifact that gets uploaded to lambda.
24
+ #
25
+ # Building Steps:
26
+ #
27
+ ### Before copy
28
+ # * compile assets: easier to do this before the copy
29
+ #
30
+ ### copy project
31
+ # * copy project: to app_root
32
+ #
33
+ ### setup app_root project
34
+ # * clean project: remove log and ignored files to reduce size
35
+ # * reconfigure webpacker: config/webpacker.yml
36
+ # * generate node shims: handlers
37
+ #
38
+ ### build bundled in cache area
39
+ # * bundle install: cache/bundled/gems
40
+ #
41
+ ### setup bundled on app root from cache
42
+ # * copy bundled to app_root: app_root/bundled
43
+ # * extract linux ruby: cache/downloads/rubies:
44
+ # cache/bundled/rbenv, cache/bundled/linuxbrew
45
+ # * extract linux gems: cache/downloads/gems:
46
+ # cache/bundled/gems, cache/bundled/linuxbrew
47
+ # * setup bundled config: app_root/.bundle/config
48
+ #
49
+ ### zip
50
+ # * create zip file
51
+ class Jets::Builders
52
+ class CodeBuilder
53
+ include Jets::Timing
54
+ # When we update JETS_RUBY_VERSION, need to update `def jets_ruby_version` in
55
+ # vendor/lambdagem/lib/lambdagem/base.rb also.
56
+ JETS_RUBY_VERSION = "2.5.0"
57
+
58
+ include ActionView::Helpers::NumberHelper # number_to_human_size
59
+ attr_reader :full_project_path
60
+ def initialize
61
+ # Expanding to the full path and capture now.
62
+ # Dir.chdir gets called later and we'll lose this info.
63
+ @full_project_path = File.expand_path(Jets.root) + "/"
64
+ end
65
+
66
+ def build
67
+ return create_zip_file(fake=true) if ENV['TEST_CODE'] # early return
68
+
69
+ cache_check_message
70
+ check_ruby_version
71
+
72
+ clean_start
73
+ compile_assets # easier to do before we copy the project
74
+ copy_project
75
+ Dir.chdir(full(tmp_app_root)) do
76
+ # These commands run from project root
77
+ start_app_root_setup
78
+ bundle_install
79
+ finish_app_root_setup
80
+ create_zip_file
81
+ end
82
+ end
83
+ time :build
84
+
85
+ # Finds out of the app has polymorphic functions only and zero ruby functions.
86
+ # In this case, we can skip a lot of the ruby related building and speed up the
87
+ # deploy process.
88
+ def poly_only?
89
+ return true if ENV['POLY_ONLY'] # bypass to allow rapid development of handlers
90
+ Jets::Commands::Build.poly_only?
91
+ end
92
+
93
+ def start_app_root_setup
94
+ tidy_project
95
+ reconfigure_development_webpacker
96
+ reconfigure_ruby_version
97
+ generate_node_shims
98
+ end
99
+ time :start_app_root_setup
100
+
101
+ def finish_app_root_setup
102
+ return if poly_only?
103
+
104
+ copy_bundled_to_app_root
105
+ setup_bundle_config
106
+ extract_ruby
107
+ extract_gems
108
+ end
109
+ time :finish_app_root_setup
110
+
111
+ def lambdagem_options
112
+ {
113
+ s3: "lambdagems",
114
+ build_root: cache_area, # used in lambdagem
115
+ project_root: full(tmp_app_root), # used in gem_replacer and lambdagem
116
+ }
117
+ end
118
+
119
+ def extract_ruby
120
+ headline "Setting up a vendored copy of ruby."
121
+ Lambdagem::Extract::Ruby.new(JETS_RUBY_VERSION, lambdagem_options).run
122
+ end
123
+
124
+ def extract_gems
125
+ headline "Replacing compiled gems with AWS Lambda Linux compiled versions."
126
+ GemReplacer.new(JETS_RUBY_VERSION, lambdagem_options).run
127
+ end
128
+
129
+ # This happens in the current app directory not the tmp app_root for simplicity
130
+ def compile_assets
131
+ headline "Compling assets in current project directory"
132
+ # Thanks: https://stackoverflow.com/questions/4195735/get-list-of-gems-being-used-by-a-bundler-project
133
+ webpacker_loaded = Gem.loaded_specs.keys.include?("webpacker")
134
+ return unless webpacker_loaded
135
+
136
+ sh("yarn install")
137
+ webpack_bin = File.exist?("#{Jets.root}bin/webpack") ?
138
+ "bin/webpack" :
139
+ `which webpack`.strip
140
+ sh("JETS_ENV=#{Jets.env} #{webpack_bin}")
141
+ end
142
+ time :compile_assets
143
+
144
+ # Cleans out non-cached files like code-*.zip in Jets.build_root
145
+ # for a clean start. Also ensure that the /tmp/jets/project build root exists.
146
+ #
147
+ # Most files are kept around after the build process for inspection and
148
+ # debugging. So we have to clean out the files. But we only want to clean out
149
+ # some of the files.
150
+ def clean_start
151
+ Dir.glob("#{Jets.build_root}/code/code-*.zip").each { |f| FileUtils.rm_f(f) }
152
+ FileUtils.mkdir_p(Jets.build_root) # /tmp/jets/demo
153
+ end
154
+
155
+ # Copy project into temporary directory. Do this so we can keep the project
156
+ # directory untouched and we can also remove a bunch of unnecessary files like
157
+ # logs before zipping it up.
158
+ def copy_project
159
+ headline "Copying current project directory to temporary build area: #{full(tmp_app_root)}"
160
+ FileUtils.rm_rf(full(tmp_app_root)) # remove current app_root folder
161
+ move_node_modules(Jets.root, Jets.build_root)
162
+ begin
163
+ FileUtils.cp_r(@full_project_path, full(tmp_app_root))
164
+ ensure
165
+ move_node_modules(Jets.build_root, Jets.root) # move node_modules directory back
166
+ end
167
+ end
168
+ time :copy_project
169
+
170
+ # Move the node modules to the tmp build folder to speed up project copying.
171
+ # A little bit risky because a ctrl-c in the middle of the project copying
172
+ # results in a missing node_modules but user can easily rebuild that.
173
+ #
174
+ # Tesing shows 6.623413 vs 0.027754 speed improvement.
175
+ def move_node_modules(source_folder, dest_folder)
176
+ source = "#{source_folder}/node_modules"
177
+ dest = "#{dest_folder}/node_modules"
178
+ if File.exist?(source)
179
+ FileUtils.mv(source, dest)
180
+ end
181
+ end
182
+
183
+ # Because we're removing files (something dangerous) use full paths.
184
+ def tidy_project
185
+ headline "Tidying project: removing ignored files to reduce package size."
186
+ excludes.each do |exclude|
187
+ exclude = exclude.sub(%r{^/},'') # remove leading slash
188
+ remove_path = "#{full(tmp_app_root)}/#{exclude}"
189
+ FileUtils.rm_rf(remove_path)
190
+ # puts " rm -rf #{remove_path}" # uncomment to debug
191
+ end
192
+ end
193
+
194
+ def generate_node_shims
195
+ headline "Generating node shims in the handlers folder."
196
+ # Crucial that the Dir.pwd is in the tmp_app_root because for
197
+ # Jets::Builders::app_files because Jets.boot set ups
198
+ # autoload_paths and this is how project classes are loaded.
199
+ Jets::Commands::Build.app_files.each do |path|
200
+ handler = Jets::Builders::HandlerGenerator.new(path)
201
+ handler.generate
202
+ end
203
+ end
204
+
205
+ # Bit hacky but this saves the user from accidentally forgetting to change this
206
+ # when they deploy a jets project in development mode
207
+ def reconfigure_development_webpacker
208
+ return unless Jets.env.development?
209
+ headline "Reconfiguring webpacker development settings for AWS Lambda."
210
+
211
+ webpacker_yml = "#{full(tmp_app_root)}/config/webpacker.yml"
212
+ return unless File.exist?(webpacker_yml)
213
+
214
+ config = YAML.load_file(webpacker_yml)
215
+ config["development"]["compile"] = false # force this to be false for deployment
216
+ new_yaml = YAML.dump(config)
217
+ IO.write(webpacker_yml, new_yaml)
218
+ end
219
+
220
+ # This is in case the user has a 2.5.x variant.
221
+ # Force usage of ruby version that jets supports
222
+ # The lambda server only has ruby 2.5.0 installed.
223
+ def reconfigure_ruby_version
224
+ ruby_version = "#{full(tmp_app_root)}/.ruby-version"
225
+ IO.write(ruby_version, JETS_RUBY_VERSION)
226
+ end
227
+
228
+ def copy_bundled_to_app_root
229
+ app_root_bundled = "#{full(tmp_app_root)}/bundled"
230
+ if File.exist?(app_root_bundled)
231
+ puts "Removing current bundled from project"
232
+ FileUtils.rm_rf(app_root_bundled)
233
+ end
234
+ # Leave #{Jets.build_root}/bundled behind to act as cache
235
+ FileUtils.cp_r("#{cache_area}/bundled", app_root_bundled)
236
+ end
237
+
238
+ def setup_bundle_config
239
+ ensure_build_cache_bundle_config_exists!
240
+
241
+ # Override project's .bundle/config and ensure that .bundle/config matches
242
+ # at these 2 spots:
243
+ # app_root/.bundle/config
244
+ # bundled/gems/.bundle/config
245
+ cache_bundle_config = "#{cache_area}/.bundle/config"
246
+ app_bundle_config = "#{full(tmp_app_root)}/.bundle/config"
247
+ FileUtils.mkdir_p(File.dirname(app_bundle_config))
248
+ FileUtils.cp(cache_bundle_config, app_bundle_config)
249
+ end
250
+
251
+ # On circleci the "#{Jets.build_root}/.bundle/config" doesnt exist
252
+ # this only happens with ssh debugging, not when the ci.sh script gets ran.
253
+ # But on macosx it exists.
254
+ # Dont know why this is the case.
255
+ def ensure_build_cache_bundle_config_exists!
256
+ text =<<-EOL
257
+ ---
258
+ BUNDLE_PATH: "bundled/gems"
259
+ BUNDLE_WITHOUT: "development:test"
260
+ EOL
261
+ bundle_config = "#{cache_area}/.bundle/config"
262
+ FileUtils.mkdir_p(File.dirname(bundle_config))
263
+ IO.write(bundle_config, text)
264
+ end
265
+
266
+ def create_zip_file(fake=nil)
267
+ puts "Creating zip file."
268
+ temp_code_zipfile = "#{Jets.build_root}/code/code-temp.zip"
269
+ FileUtils.mkdir_p(File.dirname(temp_code_zipfile))
270
+
271
+ # Use fake if testing CloudFormation only
272
+ if fake
273
+ hello_world = "/tmp/hello.js"
274
+ puts "Uploading tiny #{hello_world} file to S3 for quick testing.".colorize(:red)
275
+ code = IO.read(File.expand_path("../node-hello.js", __FILE__))
276
+ IO.write(hello_world, code)
277
+ command = "zip --symlinks -rq #{temp_code_zipfile} #{hello_world}"
278
+ else
279
+ # https://serverfault.com/questions/265675/how-can-i-zip-compress-a-symlink
280
+ command = "cd #{full(tmp_app_root)} && zip --symlinks -rq #{temp_code_zipfile} ."
281
+ end
282
+
283
+ sh(command)
284
+
285
+ # we can get the md5 only after the file has been created
286
+ md5 = Digest::MD5.file(temp_code_zipfile).to_s[0..7]
287
+ md5_zip_dest = "#{Jets.build_root}/code/code-#{md5}.zip"
288
+ FileUtils.mkdir_p(File.dirname(md5_zip_dest))
289
+ FileUtils.mv(temp_code_zipfile, md5_zip_dest)
290
+ # mv /tmp/jets/demo/code/code-temp.zip /tmp/jets/demo/code/code-a8a604aa.zip
291
+
292
+ file_size = number_to_human_size(File.size(md5_zip_dest))
293
+ puts "Zip file with code and bundled linux ruby created at: #{md5_zip_dest.colorize(:green)} (#{file_size})"
294
+
295
+ # Save state
296
+ IO.write("#{Jets.build_root}/code/current-md5-filename.txt", md5_zip_dest)
297
+ # Much later: ship, base_child_builder need set an s3_key which requires
298
+ # the md5_zip_dest.
299
+ # It is a pain to pass this all the way up from the
300
+ # CodeBuilder class.
301
+ # Let's store the "/tmp/jets/demo/code/code-a8a604aa.zip" into a
302
+ # file that can be read from any places where this is needed.
303
+ # Can also just generate a "fake file" for specs
304
+ end
305
+ time :create_zip_file
306
+
307
+ # Installs gems on the current target system: both compiled and non-compiled.
308
+ # If user is on a macosx machine, macosx gems will be installed.
309
+ # If user is on a linux machine, linux gems will be installed.
310
+ #
311
+ # Copies Gemfile* to /tmp/jetss/demo/bundled folder and installs
312
+ # gems with bundle install from there.
313
+ #
314
+ # We take the time to copy Gemfile and bundle into a separate directory
315
+ # because it gets left around to act as a 'cache'. So, when the builds the
316
+ # project gets built again not all the gems from get installed from the
317
+ # beginning.
318
+ def bundle_install
319
+ return if poly_only?
320
+
321
+ headline "Bundling: running bundle install in cache area: #{cache_area}."
322
+
323
+ copy_gemfiles
324
+
325
+ require "bundler" # dynamically require bundler so user can use any bundler
326
+ Bundler.with_clean_env do
327
+ # cd /tmp/jets/demo
328
+ sh(
329
+ "cd #{cache_area} && " \
330
+ "env BUNDLE_IGNORE_CONFIG=1 bundle install --path bundled/gems --without development test"
331
+ )
332
+ end
333
+
334
+ puts 'Bundle install success.'
335
+ end
336
+ time :bundle_install
337
+
338
+ def copy_gemfiles
339
+ FileUtils.mkdir_p(cache_area)
340
+ FileUtils.cp("#{@full_project_path}Gemfile", "#{cache_area}/Gemfile")
341
+ FileUtils.cp("#{@full_project_path}Gemfile.lock", "#{cache_area}/Gemfile.lock")
342
+ end
343
+
344
+ def excludes
345
+ excludes = %w[.git tmp log spec]
346
+ excludes += get_excludes("#{full(tmp_app_root)}/.gitignore")
347
+ excludes += get_excludes("#{full(tmp_app_root)}/.dockerignore")
348
+ excludes = excludes.reject do |p|
349
+ jetskeep.find do |keep|
350
+ p.include?(keep)
351
+ end
352
+ end
353
+ excludes
354
+ end
355
+
356
+ def get_excludes(file)
357
+ path = file
358
+ return [] unless File.exist?(path)
359
+
360
+ exclude = File.read(path).split("\n")
361
+ exclude.map {|i| i.strip}.reject {|i| i =~ /^#/ || i.empty?}
362
+ # IE: ["/handlers", "/bundled*", "/vendor/jets]
363
+ end
364
+
365
+ # We clean out ignored files pretty aggressively. So provide
366
+ # a way for users to keep files from being cleaned ou.
367
+ def jetskeep
368
+ defaults = %w[pack handlers]
369
+ path = Jets.root + ".jetskeep"
370
+ return defaults unless path.exist?
371
+
372
+ keep = path.read.split("\n")
373
+ keep = keep.map {|i| i.strip}.reject {|i| i =~ /^#/ || i.empty?}
374
+ (defaults + keep).uniq
375
+ end
376
+
377
+ def cache_check_message
378
+ if File.exist?("#{Jets.build_root}/cache")
379
+ puts "The #{Jets.build_root}/cache folder exists. Incrementally re-building the jets using the cache. To clear the cache: rm -rf #{Jets.build_root}/cache"
380
+ end
381
+ end
382
+
383
+ def check_ruby_version
384
+ unless ruby_version_supported?
385
+ puts "You are using ruby version #{RUBY_VERSION} which is not supported by Jets."
386
+ ruby_variant = JETS_RUBY_VERSION.split('.')[0..1].join('.') + '.x'
387
+ abort("Jets uses ruby #{JETS_RUBY_VERSION}. You should use a variant of ruby #{ruby_variant}".colorize(:red))
388
+ end
389
+ end
390
+
391
+ def ruby_version_supported?
392
+ pattern = /(\d+)\.(\d+)\.(\d+)/
393
+ md = RUBY_VERSION.match(pattern)
394
+ ruby = {major: md[1], minor: md[2]}
395
+ md = JETS_RUBY_VERSION.match(pattern)
396
+ jets = {major: md[1], minor: md[2]}
397
+
398
+ ruby[:major] == jets[:major] && ruby[:minor] == jets[:minor]
399
+ end
400
+
401
+ def cache_area
402
+ "#{Jets.build_root}/cache" # cleaner to use full path for this setting
403
+ end
404
+
405
+ # Provide pretty clear way to desinate full path.
406
+ # full("bundled") => /tmp/jets/demo/bundled
407
+ def full(relative_path)
408
+ "#{Jets.build_root}/#{relative_path}"
409
+ end
410
+
411
+ # Group all the path settings together here
412
+ def self.tmp_app_root
413
+ Jets::Commands::Build.tmp_app_root
414
+ end
415
+
416
+ def tmp_app_root
417
+ self.class.tmp_app_root
418
+ end
419
+
420
+ def sh(command)
421
+ puts "=> #{command}".colorize(:green)
422
+ success = system(command)
423
+ abort("#{command} failed to run") unless success
424
+ success
425
+ end
426
+
427
+ def headline(message)
428
+ puts "=> #{message}".colorize(:cyan)
429
+ end
430
+ end
431
+ end
@@ -0,0 +1,73 @@
1
+ # Build::Deducers figure out required values to create the node shim
2
+ class Jets::Builders
3
+ class Deducer
4
+ # Allow user to specify relative or full path. The right path gets used
5
+ # internally. Example paths:
6
+ # app/controllers/posts_controller.rb
7
+ # app/jobs/hard_job.rb
8
+ # /tmp/jets/build/app_root/app/jobs/hard_job.rb
9
+ # /tmp/jets/build/app_root/app/functions/hello.rb
10
+ def initialize(path)
11
+ @full_path = full(path)
12
+ @relative_path = relative(path)
13
+ end
14
+
15
+ def full(path)
16
+ path = "#{Jets.root}#{path}" unless path.starts_with?("/")
17
+ path
18
+ end
19
+
20
+ def relative(path)
21
+ full_path = full(path)
22
+ full_path.sub(Jets.root.to_s, "")
23
+ .sub(/.*internal\/app/, "app")
24
+
25
+ end
26
+
27
+ # process_type is key, it will either "controller" or "job".
28
+ # It is used to deduce klass, etc.
29
+ # We get the process_type from the path.
30
+ # Example paths:
31
+ # app/controllers/posts_controller.rb
32
+ # app/jobs/hard_job.rb
33
+ def process_type
34
+ @relative_path.split('/')[1].singularize # controller or job
35
+ end
36
+
37
+ # Returns the public methods of the child_class.
38
+ # Example: [:create, :update]
39
+ def functions
40
+ # Example: require: /tmp/jets/demo/app_root/app/controllers/admin/posts_controller.rb
41
+ class_name = @full_path.sub(/.*\/app\/\w+\//,'').sub(/\.rb/,'') # admin/posts_controller
42
+ class_name = class_name.classify # Admin::PostsController
43
+ # Autoload instead of require to avoid accidentallly double requiring and
44
+ # it resulting WARNINGs when there are constants already defined
45
+ klass = class_name.constantize # autoload
46
+
47
+ klass.lambda_functions
48
+ end
49
+
50
+ # Examples: PostsController, HardJob, Hello, HelloFunction
51
+ def klass
52
+ @klass ||= Jets::Klass.from_path(@relative_path)
53
+ end
54
+
55
+ def lang(meth)
56
+ klass.tasks.find
57
+ end
58
+
59
+ # This gets called in the node shim js template
60
+ def handler_for(meth)
61
+ # possibly not include _function
62
+ underscored_name = @relative_path.sub(%r{app/(\w+)/},'').sub('.rb','')
63
+ "handlers/#{process_type.pluralize}/#{underscored_name}.#{meth}"
64
+ end
65
+
66
+ # Example return: "handlers/controllers/posts.js"
67
+ def js_path
68
+ @relative_path
69
+ .sub("app", "handlers")
70
+ .sub(/\.rb$/, ".js")
71
+ end
72
+ end
73
+ end