jets 3.1.0 → 4.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.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/CHANGELOG.md +55 -0
  4. data/README.md +1 -5
  5. data/backers.md +0 -5
  6. data/jets.gemspec +4 -4
  7. data/lib/jets/application/defaults.rb +7 -2
  8. data/lib/jets/application.rb +6 -7
  9. data/lib/jets/aws_info.rb +2 -2
  10. data/lib/jets/aws_services.rb +8 -0
  11. data/lib/jets/booter.rb +64 -5
  12. data/lib/jets/builders/code_builder.rb +35 -21
  13. data/lib/jets/builders/gem_replacer.rb +2 -7
  14. data/lib/jets/builders/ruby_packager.rb +37 -4
  15. data/lib/jets/cfn/builders/api_deployment_builder.rb +1 -1
  16. data/lib/jets/cfn/builders/api_gateway_builder.rb +31 -27
  17. data/lib/jets/cfn/builders/api_resources_builder.rb +1 -1
  18. data/lib/jets/cfn/builders/authorizer_builder.rb +1 -1
  19. data/lib/jets/cfn/builders/base_child_builder.rb +20 -1
  20. data/lib/jets/cfn/builders/interface.rb +19 -0
  21. data/lib/jets/cfn/builders/page_builder.rb +80 -0
  22. data/lib/jets/cfn/builders/parent_builder.rb +22 -3
  23. data/lib/jets/cfn/builders/shared_builder.rb +1 -1
  24. data/lib/jets/cfn/built_template.rb +1 -1
  25. data/lib/jets/cfn/ship.rb +9 -2
  26. data/lib/jets/cfn/status.rb +1 -1
  27. data/lib/jets/cfn/upload.rb +2 -2
  28. data/lib/jets/cli.rb +12 -5
  29. data/lib/jets/commands/call/base_guesser.rb +1 -1
  30. data/lib/jets/commands/clean/log.rb +3 -3
  31. data/lib/jets/commands/configure.rb +1 -1
  32. data/lib/jets/commands/console.rb +7 -1
  33. data/lib/jets/commands/delete.rb +1 -1
  34. data/lib/jets/commands/deploy.rb +2 -2
  35. data/lib/jets/commands/main.rb +6 -3
  36. data/lib/jets/commands/stack_info.rb +1 -1
  37. data/lib/jets/commands/templates/skeleton/Gemfile.tt +1 -1
  38. data/lib/jets/commands/templates/skeleton/config/application.rb.tt +2 -1
  39. data/lib/jets/commands/url.rb +1 -1
  40. data/lib/jets/core.rb +14 -2
  41. data/lib/jets/core_ext/file.rb +9 -0
  42. data/lib/jets/dotenv.rb +2 -2
  43. data/lib/jets/erb.rb +1 -1
  44. data/lib/jets/inflections.rb +1 -1
  45. data/lib/jets/internal/app/controllers/jets/bare_controller.rb +1 -1
  46. data/lib/jets/internal/app/functions/jets/base_path.rb +93 -3
  47. data/lib/jets/internal/app/functions/jets/base_path_mapping.rb +79 -8
  48. data/lib/jets/internal/app/jobs/jets/preheat_job.rb +6 -2
  49. data/lib/jets/job/base.rb +2 -0
  50. data/lib/jets/job/helpers/sns_event_helper.rb +8 -0
  51. data/lib/jets/job/helpers/sqs_event_helper.rb +8 -0
  52. data/lib/jets/lambda/dsl.rb +7 -1
  53. data/lib/jets/{naming.rb → names.rb} +3 -3
  54. data/lib/jets/preheat.rb +9 -6
  55. data/lib/jets/resource/api_gateway/base_path/role.rb +1 -1
  56. data/lib/jets/resource/api_gateway/deployment.rb +2 -2
  57. data/lib/jets/resource/api_gateway/rest_api/logical_id/message.rb +13 -3
  58. data/lib/jets/resource/api_gateway/rest_api/logical_id.rb +1 -1
  59. data/lib/jets/resource/api_gateway/rest_api/routes/change/base.rb +11 -40
  60. data/lib/jets/resource/api_gateway/rest_api/routes/change/media_types.rb +1 -1
  61. data/lib/jets/resource/api_gateway/rest_api/routes/change/page.rb +2 -2
  62. data/lib/jets/resource/api_gateway/rest_api/routes/change.rb +1 -1
  63. data/lib/jets/resource/api_gateway/rest_api.rb +12 -2
  64. data/lib/jets/resource/child_stack/api_deployment.rb +1 -1
  65. data/lib/jets/resource/child_stack/api_resource/page.rb +1 -1
  66. data/lib/jets/resource/child_stack/api_resource.rb +1 -1
  67. data/lib/jets/resource/child_stack/app_class.rb +1 -1
  68. data/lib/jets/resource/child_stack/shared.rb +1 -1
  69. data/lib/jets/resource/iam/base_role_definition.rb +0 -5
  70. data/lib/jets/resource/iam/policy.rb +31 -0
  71. data/lib/jets/resource/lambda/function/environment.rb +6 -3
  72. data/lib/jets/resource/lambda/function.rb +3 -3
  73. data/lib/jets/router/route.rb +18 -2
  74. data/lib/jets/router/state.rb +47 -0
  75. data/lib/jets/router.rb +12 -0
  76. data/lib/jets/stack/main/dsl/lambda.rb +1 -0
  77. data/lib/jets/tmp_loader.rb +1 -1
  78. data/lib/jets/turbo/database_yaml.rb +1 -1
  79. data/lib/jets/util/yamler.rb +16 -0
  80. data/lib/jets/version.rb +1 -1
  81. data/lib/jets.rb +2 -0
  82. metadata +26 -20
  83. data/.python-version +0 -1
  84. data/.ruby-version +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2aa7cee0958dbdb8e631abc755587de924e101c25b5f64d2f1c4b31ec1abf3d9
4
- data.tar.gz: bd4aaa8264304a61a780140f1f0f33d0e68658d57c6be55487f27faa090fdf57
3
+ metadata.gz: 557e01dec1b92f8a04213ef4b7f5ee9d8a35f25dd20231c96ba24b0d9890b7cd
4
+ data.tar.gz: 5c8c12ae959d76dc9e5a681c8f18a40d5d60defcc4eead52ed9d9ad2571a3fe1
5
5
  SHA512:
6
- metadata.gz: 0a0b34e96bb206743a192297848e70f03ef07ed587633e81bd1731881dcca2fb2a9232c374194c795b1e48eb537b690b882650c9f9173e5c77faca4cb1a9a83d
7
- data.tar.gz: 2270fd363dc73f508e662ba4a115a71d54db9f298f5db17738328b88ec62284a544a41668a93b18bcbc094009d6bf178cc82c65e37a751f2af3036c8cb00a680
6
+ metadata.gz: 944a1d09ba4da26110e292cdf42d73a240d283d066dbe1ca677787c20b03ee925cf12e3d92555bc16e6327c7096ce59782cd271ff802f5d8554819674f040020
7
+ data.tar.gz: 987eac8ef96a9cc10b0ac071ff099c02245cf5143bb75d23622513aba73ba447414ab0c542f7a734c30ba6ce07f20cd479daecc030c02d9a5d3505c10c0a5c34
@@ -0,0 +1 @@
1
+ github: boltops-tools
data/CHANGELOG.md CHANGED
@@ -3,6 +3,61 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## [4.0.0] - 2023-05-27
7
+ - [#641](https://github.com/boltops-tools/jets/pull/641) bundle check and prevent error from getting to aws lambda
8
+ - [#642](https://github.com/boltops-tools/jets/pull/642) Fix rack mounted apps: update interface with removed meth
9
+ - [#643](https://github.com/boltops-tools/jets/pull/643) JETS_EXTRA support, deprecate JETS_ENV_EXTRA
10
+ - [#644](https://github.com/boltops-tools/jets/pull/644) remove docs to separate repo
11
+ - [#645](https://github.com/boltops-tools/jets/pull/645) PreheatJob: fix function lookups and iam function permission
12
+ - [#646](https://github.com/boltops-tools/jets/pull/646) log debug uploading and setting content type
13
+ - [#647](https://github.com/boltops-tools/jets/pull/647) fix Jets.logger call
14
+ - [#648](https://github.com/boltops-tools/jets/pull/648) make sure logger level info is default
15
+ - [#649](https://github.com/boltops-tools/jets/pull/649) Custom Domain: Hard fail on IAM permission error
16
+ - [#650](https://github.com/boltops-tools/jets/pull/650) Validate lambda function names
17
+ - [#651](https://github.com/boltops-tools/jets/pull/651) allow custom rake tasks with params to work with jets as well as rake command
18
+ - [#652](https://github.com/boltops-tools/jets/pull/652) Validate lambda function names: fix regexp
19
+ - [#653](https://github.com/boltops-tools/jets/pull/653) refactor cleanup: rename Jets::Naming to Jets::Names
20
+ - [#654](https://github.com/boltops-tools/jets/pull/654) Ruby 3.2 Support
21
+ - apigw routes state save: fix to_json infinite loop from Grape apps
22
+ - delete .python-version: more general approach. fixes specs when specific version of python is not installed
23
+
24
+ ## [3.2.2] - 2023-05-19
25
+ - [#640](https://github.com/boltops-tools/jets/pull/640) Base path mapping CloudFormation custom resource and lambda function hardening
26
+
27
+ ## [3.2.1] - 2023-05-03
28
+ - [#637](https://github.com/boltops-tools/jets/pull/637) Readme: Replace "splat out" with "had" a baby
29
+ - [#638](https://github.com/boltops-tools/jets/pull/638) feature: update an array of reserved variables in aws lambda
30
+ - [#639](https://github.com/boltops-tools/jets/pull/639) fix assets upload during deploy
31
+
32
+ ## [3.2.0] - 2022-12-03
33
+ - [#631](https://github.com/boltops-tools/jets/pull/631) Implement vpc_endpoint_ids configuration
34
+ - [#634](https://github.com/boltops-tools/jets/pull/634) Custom domain messaging
35
+ - [#635](https://github.com/boltops-tools/jets/pull/635) smarter apigw routes paging calculation
36
+ - Introduce the storage of APIGW routes state in the jets managed s3 bucket under path jets/state/apigw/pages.json and jets/state/apigw/routes.json
37
+ - This speeds up deployment for apps with a large number of routes. Depending on the internet connection this can be minutes faster.
38
+ - Update internationalization.md
39
+ - fix domain.name check when APIGW changes
40
+ - improve change apigw endpoint change messaging
41
+
42
+ ## [3.1.5] - 2022-08-08
43
+ - [#628](https://github.com/boltops-tools/jets/pull/628) Multiple Databases
44
+ - [#629](https://github.com/boltops-tools/jets/pull/629) loosen zeitwerk dependency in generated project Gemfile
45
+ - [#630](https://github.com/boltops-tools/jets/pull/630) compile assets with WEBPACKER_ASSET_HOST as s3 endpoint url
46
+
47
+ ## [3.1.4] - 2022-07-02
48
+ - [#627](https://github.com/boltops-tools/jets/pull/627) use >= for most gem dependencies
49
+
50
+ ## [3.1.3] - 2022-06-29
51
+ - [#626](https://github.com/boltops-tools/jets/pull/626) aws options to better handle rate limit for base path mapping
52
+
53
+ ## [3.1.2] - 2022-04-24
54
+ - [#618](https://github.com/boltops-tools/jets/pull/618) Jets Console accepts environment cli argument
55
+ - [#621](https://github.com/boltops-tools/jets/pull/621) Add SQS and SNS event helpers for jobs
56
+ - [#624](https://github.com/boltops-tools/jets/pull/624) Add lambda.function.ephemeral_storage function property support
57
+
58
+ ## [3.1.1] - 2022-01-18
59
+ - [#615](https://github.com/boltops-tools/jets/pull/615) adjust required_ruby_version
60
+
6
61
  ## [3.1.0] - 2022-01-08
7
62
  - [#614](https://github.com/boltops-tools/jets/pull/614) support zeitwerk 2.5
8
63
  - clean command alias -y for --yes option
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  <a href="http://rubyonjets.com"><img src="http://rubyonjets.com/img/logos/jets-logo-full.png" /></a>
3
3
  </div>
4
4
 
5
- Ruby and Lambda splat out a baby and that child's name is [Jets](http://rubyonjets.com/).
5
+ Ruby and Lambda had a baby and that child's name is [Jets](http://rubyonjets.com/).
6
6
 
7
7
  ![Build Status](https://codebuild.us-west-2.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoiZ08vK2hjOHczQUVoUDhSYnBNNUU4T0gxQWJuOTlLaXpwVGQ1NjJ3NnVDY1dSdFVXQ3d2VXVSQzRFcU1qd1JPMndFZlByRktIcTUrZm5GWlM5dHpjM1ZrPSIsIml2UGFyYW1ldGVyU3BlYyI6Imluc1Qrd25GanhUdHlidjUiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=master)
8
8
  [![CircleCI](https://circleci.com/gh/boltops-tools/jets.svg?style=svg)](https://circleci.com/gh/boltops-tools/jets)
@@ -16,10 +16,6 @@ Please **watch/star** this repo to help grow and support the project.
16
16
 
17
17
  **Upgrading**: If you are upgrading Jets, please check on the [Upgrading Notes](http://rubyonjets.com/docs/extras/upgrading/).
18
18
 
19
- ## Sponsors
20
-
21
- [![](https://img.boltops.com/boltops/tools/jets/sponsors/arist.png)](https://arist.co/)
22
-
23
19
  ## What is Ruby on Jets?
24
20
 
25
21
  Jets is a Ruby Serverless Framework. Jets allows you to create serverless applications with a beautiful language: Ruby. It includes everything required to build an application and deploy it to AWS Lambda.
data/backers.md CHANGED
@@ -11,10 +11,5 @@ Funds donated via Patreon go directly to support Tung Nguyen's full-time work on
11
11
  <h2 align="center">Backers via Patreon</h2>
12
12
 
13
13
  <!--10 start-->
14
- - Erlend Finvåg
15
- - Nate Clark
16
- - Hirokatsu Endo
17
- - Michael Choi
18
- - Phan Lam
19
14
  - Theron Welch
20
15
  <!--10 end-->
data/jets.gemspec CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://rubyonjets.com"
15
15
  spec.license = "MIT"
16
16
 
17
- spec.required_ruby_version = '~> 2.5'
17
+ spec.required_ruby_version = ['>= 2.5.0']
18
18
  spec.rdoc_options += Jets::Rdoc.options
19
19
 
20
20
  vendor_files = Dir.glob("vendor/**/*")
@@ -44,7 +44,7 @@ Gem::Specification.new do |spec|
44
44
  spec.add_dependency "aws-sdk-sqs"
45
45
  spec.add_dependency "aws-sdk-ssm"
46
46
  spec.add_dependency "cfn-status"
47
- spec.add_dependency "cfn_camelizer", "~> 0.4.6"
47
+ spec.add_dependency "cfn_camelizer", ">= 0.4.9"
48
48
  spec.add_dependency "cfn_response"
49
49
  spec.add_dependency "dotenv"
50
50
  spec.add_dependency "gems" # jets-gems dependency
@@ -57,11 +57,11 @@ Gem::Specification.new do |spec|
57
57
  spec.add_dependency "railties", "~> 6.1.0" # for ActiveRecord database_tasks.rb
58
58
  spec.add_dependency "rainbow"
59
59
  spec.add_dependency "recursive-open-struct"
60
- spec.add_dependency "serverlessgems", "~> 0.1.4"
60
+ spec.add_dependency "serverlessgems", ">= 0.2.0"
61
61
  spec.add_dependency "shotgun"
62
62
  spec.add_dependency "text-table"
63
63
  spec.add_dependency "thor"
64
- spec.add_dependency "zeitwerk", "~> 2.5.0"
64
+ spec.add_dependency "zeitwerk", ">= 2.6.0"
65
65
 
66
66
  spec.add_development_dependency "bundler"
67
67
  spec.add_development_dependency "byebug"
@@ -51,6 +51,7 @@ class Jets::Application
51
51
  config.autoload_paths = [] # allows for customization
52
52
  config.ignore_paths = [] # allows for customization
53
53
  config.logger = Jets::Logger.new($stderr)
54
+ config.logger.level = Logger::INFO
54
55
  config.time_zone = "UTC"
55
56
 
56
57
  # function properties defaults
@@ -59,6 +60,7 @@ class Jets::Application
59
60
  # default memory setting based on:
60
61
  # https://medium.com/epsagon/how-to-make-lambda-faster-memory-performance-benchmark-be6ebc41f0fc
61
62
  config.function.memory_size = 1536
63
+ config.function.ephemeral_storage = { size: 512 } # megabytes
62
64
 
63
65
  config.prewarm = ActiveSupport::OrderedOptions.new
64
66
  config.prewarm.enable = true
@@ -76,10 +78,11 @@ class Jets::Application
76
78
  config.inflections.irregular = {}
77
79
 
78
80
  config.assets = ActiveSupport::OrderedOptions.new
79
- config.assets.folders = %w[assets images packs]
80
81
  config.assets.base_url = nil # IE: https://cloudfront.com/my/base/path
81
- config.assets.max_age = 3600
82
82
  config.assets.cache_control = nil # IE: public, max-age=3600 , max_age is a shorter way to set cache_control.
83
+ config.assets.folders = %w[assets images packs]
84
+ config.assets.max_age = 3600
85
+ config.assets.webpacker_asset_host = "s3_endpoint" # true = use conventional by default
83
86
 
84
87
  config.ruby = ActiveSupport::OrderedOptions.new
85
88
 
@@ -97,6 +100,7 @@ class Jets::Application
97
100
  config.api.cors_authorization_type = nil # nil so ApiGateway::Cors#cors_authorization_type handles
98
101
  config.api.endpoint_policy = nil # required when endpoint_type is EDGE
99
102
  config.api.endpoint_type = 'EDGE' # PRIVATE, EDGE, REGIONAL
103
+ config.api.vpc_endpoint_ids = nil
100
104
 
101
105
  config.api.authorizers = ActiveSupport::OrderedOptions.new
102
106
  config.api.authorizers.default_token_source = "Auth" # method.request.header.Auth
@@ -159,6 +163,7 @@ class Jets::Application
159
163
 
160
164
  config.ruby = ActiveSupport::OrderedOptions.new
161
165
  config.ruby.check = true
166
+ config.ruby.supported_versions = %w[2.5 2.7 3.2] # supported by AWS Lambda
162
167
 
163
168
  config
164
169
  end
@@ -163,13 +163,12 @@ class Jets::Application
163
163
  staging: 'stag',
164
164
  }
165
165
  def set_computed_configs!
166
- # env_extra can be also be set with JETS_ENV_EXTRA.
167
- # JETS_ENV_EXTRA higher precedence than config.env_extra
168
- config.env_extra = ENV['JETS_ENV_EXTRA'] if ENV['JETS_ENV_EXTRA']
169
- # IE: With env_extra: project-dev-1
170
- # Without env_extra: project-dev
166
+ # env var JETS_EXTRA higher precedence than config.extra
167
+ config.extra = Jets.extra
168
+ # IE: With extra: project-dev-1
169
+ # Without extra: project-dev
171
170
  config.short_env = ENV_MAP[Jets.env.to_sym] || Jets.env
172
- # table_namespace does not have the env_extra, more common case desired.
171
+ # table_namespace does not have the extra, more common case desired.
173
172
  config.table_namespace = [config.project_name, config.short_env].compact.join('-')
174
173
 
175
174
  config.project_namespace = Jets.project_namespace
@@ -205,7 +204,7 @@ class Jets::Application
205
204
  if File.exist?(database_yml)
206
205
  require "active_record/database_configurations" # lazy require
207
206
  text = Jets::Erb.result(database_yml)
208
- db_configs = YAML.load(text)
207
+ db_configs = Jets::Util::Yamler.load(text)
209
208
  configurations = ActiveRecord::DatabaseConfigurations.new(db_configs)
210
209
  config.database = configurations
211
210
  end
data/lib/jets/aws_info.rb CHANGED
@@ -73,7 +73,7 @@ module Jets
73
73
  return "fake-test-s3-bucket" if Jets.env.test?
74
74
  return @@s3_bucket unless @@s3_bucket == BUCKET_DOES_NOT_YET_EXIST
75
75
 
76
- resp = cfn.describe_stacks(stack_name: Jets::Naming.parent_stack_name)
76
+ resp = cfn.describe_stacks(stack_name: Jets::Names.parent_stack_name)
77
77
  stack = resp.stacks.first
78
78
  output = stack["outputs"].find { |o| o["output_key"] == "S3Bucket" }
79
79
  @@s3_bucket = output["output_value"] # s3_bucket
@@ -83,7 +83,7 @@ module Jets
83
83
  # not been loaded in the config yet. We do some trickery with loading
84
84
  # the config twice in Application#load_app_config
85
85
  # The first load will result in a Aws::CloudFormation::Errors::ValidationError
86
- # since the Jets::Naming.parent_stack_name has not been properly set yet.
86
+ # since the Jets::Names.parent_stack_name has not been properly set yet.
87
87
  #
88
88
  # Rescuing all exceptions in case there are other exceptions dont know about yet
89
89
  # Here are the known ones: Aws::CloudFormation::Errors::ValidationError, Aws::CloudFormation::Errors::InvalidClientTokenId
@@ -86,10 +86,18 @@ module Jets::AwsServices
86
86
  retry_limit: 7, # default: 3
87
87
  retry_base_delay: 0.6, # default: 0.3
88
88
  }
89
+ # See debug logger. Noisy.
90
+ # Example:
91
+ # D, [2022-12-02T13:18:55.298788 #26182] DEBUG -- : [Aws::APIGateway::Client 200 0.030837 0 retries] get_method(rest_api_id:"mke40eh6l0",resource_id:"zf8w2m",http_method:"GET")
89
92
  options.merge!(
90
93
  log_level: :debug,
91
94
  logger: Logger.new($stdout),
92
95
  ) if ENV['JETS_DEBUG_AWS_SDK']
96
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/debugging.html to enable http_wire_trace
97
+ # See the HTTP headers and JSON responses. Super noisy.
98
+ options.merge!(
99
+ http_wire_trace: true,
100
+ ) if ENV['JETS_DEBUG_AWS_SDK_HTTP_WIRE_TRACE']
93
101
  options
94
102
  end
95
103
  end
data/lib/jets/booter.rb CHANGED
@@ -10,6 +10,7 @@ class Jets::Booter
10
10
  Jets::Bundle.require
11
11
 
12
12
  Jets.application.setup!
13
+ check_ruby_version!
13
14
 
14
15
  # Turbines are loaded after setup_autoload_paths in Jets.application.setup! Some Turbine options are defined
15
16
  # in the project so setup must happen before internal Turbines are loaded.
@@ -94,11 +95,23 @@ class Jets::Booter
94
95
  # `show processlist` until after a query. Have confirmed that the connection is reused and the connection count stays
95
96
  # the same.
96
97
  def connect_db
97
- primary_hash_config = ActiveRecord::Base.configurations.configs_for(env_name: Jets.env).find { |hash_config|
98
- hash_config.name == "primary"
99
- }
100
- primary_config = primary_hash_config.configuration_hash # configuration_hash is a normal Ruby Hash
101
- ActiveRecord::Base.establish_connection(primary_config)
98
+ if ActiveRecord::Base.legacy_connection_handling
99
+ primary_hash_config = ActiveRecord::Base.configurations.configs_for(env_name: Jets.env).find { |hash_config|
100
+ hash_config.name == "primary"
101
+ }
102
+
103
+ primary_config = primary_hash_config.configuration_hash # configuration_hash is a normal Ruby Hash
104
+
105
+ ActiveRecord::Base.establish_connection(primary_config)
106
+ else
107
+ configs = ActiveRecord::Base.configurations.configs_for(env_name: Jets.env, include_replicas: true)
108
+
109
+ databases = { }
110
+ databases[:writing] = :primary if configs.any? { |config| config.name == "primary" }
111
+ databases[:reading] = :primary_replica if configs.any? { |config| config.name == "primary_replica" }
112
+
113
+ ActiveRecord::Base.connects_to database: databases
114
+ end
102
115
  end
103
116
 
104
117
  def load_internal_turbines
@@ -162,5 +175,51 @@ class Jets::Booter
162
175
  exit 1
163
176
  end
164
177
  end
178
+
179
+ def check_ruby_version!
180
+ return if ENV['JETS_RUBY_CHECK'] == '0'
181
+ return if !Jets.config.ruby.check
182
+ return if ruby_version_supported?
183
+
184
+ puts <<~EOL.color(:red)
185
+ You are using Ruby #{RUBY_VERSION}
186
+ AWS Lambda does not support this version.
187
+ Please use one of the supported Ruby versions: #{supported_ruby_versions.join(' ')}
188
+ EOL
189
+
190
+ puts <<~EOL
191
+ If you would like to skip this check, you can set: JETS_RUBY_CHECK=0 or configure
192
+
193
+ config/application.rb
194
+
195
+ Jets.application.configure do
196
+ config.ruby.check = false
197
+ end
198
+
199
+ Or if you want to allow additional Ruby versions, then configure:
200
+
201
+ config/application.rb
202
+
203
+ Jets.application.configure do
204
+ config.ruby.supported_versions = ["2.5", "2.7", "3.2"]
205
+ end
206
+
207
+ Note: If AWS Lambda does not officially support the Ruby version,
208
+ you'll need to also provide the Ruby Custom Runtime Layer.
209
+ Related Docs: https://rubyonjets.com/docs/extras/custom-runtime/
210
+ EOL
211
+ exit 1
212
+ end
213
+
214
+ def ruby_version_supported?
215
+ md = RUBY_VERSION.match(/(\d+)\.(\d+)\.\d+/)
216
+ major, minor = md[1], md[2]
217
+ detected_ruby = [major, minor].join('.')
218
+ supported_ruby_versions.include?(detected_ruby)
219
+ end
220
+
221
+ def supported_ruby_versions
222
+ Jets.config.ruby.supported_versions
223
+ end
165
224
  end
166
225
  end
@@ -26,7 +26,6 @@ module Jets::Builders
26
26
  end
27
27
 
28
28
  def build
29
- check_ruby_version
30
29
  @version_purger.purge
31
30
  cache_check_message
32
31
 
@@ -80,6 +79,7 @@ module Jets::Builders
80
79
  return false if ENV['JETS_BUILD_NO_INTERNET']
81
80
  s3_key = "jets/code/#{filename}"
82
81
  begin
82
+ Jets.logger.debug "Checking s3://#{s3_bucket}/#{s3_key}"
83
83
  s3.head_object(bucket: s3_bucket, key: s3_key)
84
84
  true
85
85
  rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::Forbidden
@@ -205,12 +205,45 @@ module Jets::Builders
205
205
  return unless webpacker_included?
206
206
 
207
207
  sh("yarn install")
208
+
209
+ ENV['WEBPACKER_ASSET_HOST'] = webpacker_asset_host if Jets.config.assets.webpacker_asset_host
208
210
  webpack_command = File.exist?("#{Jets.root}/bin/webpack") ?
209
211
  "bin/webpack" :
210
212
  `which webpack`.strip
211
213
  sh "JETS_ENV=#{Jets.env} #{webpack_command}"
212
214
  end
213
215
 
216
+ # Different url for these. Examples:
217
+ #
218
+ # webpacker_asset_host https://demo-dev-s3bucket-lw5vq7ht8ip4.s3.us-west-2.amazonaws.com/jets/public/packs/media/images/boltops-0dd1c6bd.png
219
+ # s3_base_url https://s3-us-west-2.amazonaws.com/demo-dev-s3bucket-lw5vq7ht8ip4/jets/packs/media/images/boltops-0dd1c6bd.png
220
+ #
221
+ # Interesting: webpacker_asset_host works but s3_base_url does not for CORs. IE: reactjs or vuejs requests
222
+ # Thinking AWS configures the non-subdomain url endpoint to be more restrictive.
223
+ #
224
+ def webpacker_asset_host
225
+ # Allow user to set assets.webpacker_asset_host
226
+ #
227
+ # Jets.application.configure do
228
+ # config.assets.webpacker_asset_host = "https://cloudfront.com/my/base/path"
229
+ # end
230
+ #
231
+ assets = Jets.config.assets
232
+ return assets.webpacker_asset_host if assets.webpacker_asset_host && assets.webpacker_asset_host != "s3_endpoint"
233
+ return assets.base_url if assets.base_url
234
+
235
+ # By default, will use the s3 url endpoint directly by convention
236
+ return unless assets.webpacker_asset_host == "s3_endpoint"
237
+
238
+ region = Jets.aws.region
239
+
240
+ asset_base_url = region == 'us-east-1' ?
241
+ "https://#{s3_bucket}.s3.amazonaws.com" :
242
+ "https://#{s3_bucket}.s3.#{region}.amazonaws.com"
243
+
244
+ "#{asset_base_url}/jets/public" # s3_base_url
245
+ end
246
+
214
247
  def webpacker_included?
215
248
  # Old code, leaving around for now:
216
249
  # Thanks: https://stackoverflow.com/questions/4195735/get-list-of-gems-being-used-by-a-bundler-project
@@ -322,7 +355,7 @@ module Jets::Builders
322
355
  webpacker_yml = "#{"#{stage_area}/code"}/config/webpacker.yml"
323
356
  return unless File.exist?(webpacker_yml)
324
357
 
325
- config = YAML.load_file(webpacker_yml)
358
+ config = Jets::Util::Yamler.load_file(webpacker_yml)
326
359
  config["development"]["compile"] = false # force this to be false for deployment
327
360
  new_yaml = YAML.dump(config)
328
361
  IO.write(webpacker_yml, new_yaml)
@@ -379,25 +412,6 @@ module Jets::Builders
379
412
  FileUtils.cp_r(ruby_version_path, build_area)
380
413
  end
381
414
 
382
- SUPPORTED_RUBY_VERSIONS = %w[2.5 2.7]
383
- def check_ruby_version
384
- return unless ENV['JETS_RUBY_CHECK'] == '0' || Jets.config.ruby.check == false
385
- return if ruby_version_supported?
386
- puts <<~EOL.color(:red)
387
- You are using Ruby version #{RUBY_VERSION} which is not supported by Jets.
388
- Please use one of the Jets supported ruby versions: #{SUPPORTED_RUBY_VERSIONS.join(' ')}
389
- If you would like to skip this check you can set: JETS_RUBY_CHECK=0
390
- EOL
391
- exit 1
392
- end
393
-
394
- def ruby_version_supported?
395
- md = RUBY_VERSION.match(/(\d+)\.(\d+)\.\d+/)
396
- major, minor = md[1], md[2]
397
- detected_ruby = [major, minor].join('.')
398
- SUPPORTED_RUBY_VERSIONS.include?(detected_ruby)
399
- end
400
-
401
415
  # Group all the path settings together here
402
416
  def self.tmp_code
403
417
  Jets::Commands::Build.tmp_code
@@ -1,6 +1,8 @@
1
1
  module Jets::Builders
2
2
  class GemReplacer
3
3
  extend Memoist
4
+ include Util
5
+
4
6
  def initialize(options)
5
7
  @options = options
6
8
  end
@@ -37,13 +39,6 @@ module Jets::Builders
37
39
  FileUtils.mv(src, dest) unless File.exist?(dest) # looks like rename_gem actually runs twice
38
40
  end
39
41
 
40
- def sh(command)
41
- puts "=> #{command}".color(:green)
42
- success = system(command)
43
- abort("Command Failed: #{command}") unless success
44
- success
45
- end
46
-
47
42
  def ruby_folder
48
43
  Jets::Gems.ruby_folder
49
44
  end
@@ -3,9 +3,9 @@ require "bundler" # for clean_old_submodules only
3
3
  module Jets::Builders
4
4
  class RubyPackager
5
5
  include Util
6
-
7
- GEM_REGEXP = /-(arm|x)\d+.*-(darwin|linux)/
8
-
6
+
7
+ GEM_REGEXP = /-(arm|x)\d+.*-(darwin|linux)/
8
+
9
9
  attr_reader :full_app_root
10
10
  def initialize(relative_app_root)
11
11
  @full_app_root = "#{build_area}/#{relative_app_root}"
@@ -16,6 +16,7 @@ module Jets::Builders
16
16
 
17
17
  clean_old_submodules
18
18
  bundle_install
19
+ bundle_check
19
20
  copy_bundle_config
20
21
  copy_cache_gems
21
22
  end
@@ -75,7 +76,39 @@ module Jets::Builders
75
76
  # For example we add the jets-rails to the Gemfile.
76
77
  copy_back_gemfile_lock
77
78
 
78
- puts 'Bundle install success.'
79
+ puts 'Bundle install completed'
80
+ end
81
+
82
+ # Example `bundle check` error:
83
+ #
84
+ # The following gems are missing
85
+ # * date (3.3.3)
86
+ # * timeout (0.3.2)
87
+ # Install missing gems with `bundle install`
88
+ #
89
+ # Example success:
90
+ #
91
+ # The Gemfile's dependencies are satisfied
92
+ #
93
+ def bundle_check
94
+ out = ''
95
+ Bundler.with_unbundled_env do
96
+ out = `cd #{cache_area} && bundle check 2>&1`
97
+ end
98
+ if out.include?("missing")
99
+ puts "Failed: bundle check".color(:red)
100
+ puts <<~EOL
101
+ This means something went wrong with the bundle install.
102
+ Jets will prevent the deployment to AWS Lambda.
103
+ It's better to error now instead of finding out on AWS Lambda.
104
+ The bundle install can fail for different system-specific reasons.
105
+ It could be an outdated or incompatible version of RubyGems and Ruby.
106
+
107
+ Related: https://community.boltops.com/t/could-not-find-timeout-0-3-1-in-any-of-the-sources/996
108
+
109
+ EOL
110
+ exit 1
111
+ end
79
112
  end
80
113
 
81
114
  def copy_back_gemfile_lock
@@ -45,7 +45,7 @@ module Jets::Cfn::Builders
45
45
 
46
46
  # template_path is an interface method
47
47
  def template_path
48
- Jets::Naming.api_deployment_template_path
48
+ Jets::Names.api_deployment_template_path
49
49
  end
50
50
 
51
51
  # do not bother writing a template if routes are empty
@@ -18,7 +18,7 @@ module Jets::Cfn::Builders
18
18
 
19
19
  # template_path is an interface method
20
20
  def template_path
21
- Jets::Naming.api_gateway_template_path
21
+ Jets::Names.api_gateway_template_path
22
22
  end
23
23
 
24
24
  # do not bother writing a template if routes are empty
@@ -49,19 +49,19 @@ module Jets::Cfn::Builders
49
49
 
50
50
  def add_route53_dns
51
51
  dns = Jets::Resource::Route53::RecordSet.new
52
- if !existing_domain_name?(dns.domain_name) or existing_dns_record_on_stack?
52
+ if !existing_domain_name?(dns.domain_name) or existing_dns_record_on_stack?
53
53
  add_resource(dns)
54
54
  add_outputs(dns.outputs)
55
55
  end
56
56
  end
57
57
 
58
- def create_domain_name()
58
+ def create_domain_name
59
59
  resource = Jets::Resource::ApiGateway::DomainName.new
60
-
60
+
61
61
  return {
62
62
  "DomainName" => resource.domain_name
63
63
  } if (existing_domain_name?(resource) and !existing_domain_name_on_stack?)
64
-
64
+
65
65
  add_resource(resource)
66
66
  return resource.outputs
67
67
  end
@@ -70,41 +70,44 @@ module Jets::Cfn::Builders
70
70
  apigateway.get_domain_name({
71
71
  domain_name: resource.domain_name
72
72
  })
73
- return true
74
- rescue
75
- return false
73
+ true
74
+ # IE: Aws::APIGateway::Errors::NotFoundException Invalid domain name identifier specified
75
+ rescue Aws::APIGateway::Errors::NotFoundException
76
+ false
76
77
  end
77
78
  memoize :existing_domain_name?
78
79
 
79
80
  def existing_domain_name_on_stack?
80
- cfn.describe_stack_resource({
81
+ cfn.describe_stack_resource(
81
82
  stack_name: api_gateway_physical_resource_id,
82
83
  logical_resource_id: "DomainName"
83
- })
84
- return true
85
- rescue
86
- return false
84
+ )
85
+ true
86
+ # IE: Aws::CloudFormation::Errors::ValidationError (Resource DomainName does not exist for stack demo-dev)
87
+ rescue Aws::CloudFormation::Errors::ValidationError
88
+ false
87
89
  end
88
90
 
89
91
  def existing_dns_record_on_stack?
90
- cfn.describe_stack_resource({
92
+ cfn.describe_stack_resource(
91
93
  stack_name: api_gateway_physical_resource_id,
92
94
  logical_resource_id: "DnsRecord"
93
- })
94
- return true
95
- rescue
96
- return false
95
+ )
96
+ true
97
+ # IE: Aws::CloudFormation::Errors::ValidationError (Resource DnsRecord does not exist for stack demo-dev)
98
+ rescue Aws::CloudFormation::Errors::ValidationError
99
+ false
97
100
  end
98
101
 
99
102
  def api_gateway_physical_resource_id
100
- cfn.describe_stack_resource({
101
- stack_name: Jets::Naming.parent_stack_name,
103
+ resp = cfn.describe_stack_resource(
104
+ stack_name: Jets::Names.parent_stack_name,
102
105
  logical_resource_id: "ApiGateway"
103
- })
104
- .stack_resource_detail
105
- .physical_resource_id
106
- rescue
107
- return nil
106
+ )
107
+ resp&.stack_resource_detail&.physical_resource_id
108
+ # IE: Aws::CloudFormation::Errors::ValidationError (Resource ApiGateway does not exist for stack demo-dev)
109
+ rescue Aws::CloudFormation::Errors::ValidationError
110
+ nil
108
111
  end
109
112
  memoize :api_gateway_physical_resource_id
110
113
 
@@ -114,8 +117,9 @@ module Jets::Cfn::Builders
114
117
  def add_gateway_routes
115
118
  # Reject homepage. Otherwise we have 200 - 1 resources on the first page.
116
119
  # There's a next call in ApiResources.add_gateway_resources to skip the homepage.
117
- all_paths = Jets::Router.all_paths.reject { |p| p == '' }
118
- all_paths.each_slice(PAGE_LIMIT).each_with_index do |paths, i|
120
+ page_builder = Jets::Cfn::Builders::PageBuilder.new
121
+ pages = page_builder.build
122
+ pages.each_with_index do |paths, i|
119
123
  ApiResourcesBuilder.new(@options, paths, i+1).build
120
124
  end
121
125
  end
@@ -16,7 +16,7 @@ module Jets::Cfn::Builders
16
16
 
17
17
  # template_path is an interface method
18
18
  def template_path
19
- Jets::Naming.api_resources_template_path(@page)
19
+ Jets::Names.api_resources_template_path(@page)
20
20
  end
21
21
 
22
22
  def add_rest_api_parameter
@@ -61,7 +61,7 @@ module Jets::Cfn::Builders
61
61
  end
62
62
 
63
63
  def template_path
64
- Jets::Naming.authorizer_template_path(@path)
64
+ Jets::Names.authorizer_template_path(@path)
65
65
  end
66
66
  end
67
67
  end