jets 3.1.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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