jets_gem_layer 0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 796fe39c52a3459efb7585c20543607952c5760fbde14cd348172e50d1521fe3
4
+ data.tar.gz: e9895777617ab674521b57a5d1f43477d9f05aeb3c276fc723b1595b4e8b0fbb
5
+ SHA512:
6
+ metadata.gz: 82457f5266038a4b08424fe518a89aa67f71f15541d6db06435d1e6ae14bc202027fe95044ed70c4d4dc6e6c072c055298464baf8e8257f0eaa23a5c7999fd7c
7
+ data.tar.gz: 308673cfb04e7ed74bea54fa2dcc4ebbc2773adb5ea2be3dac64b2182d98a3a7a7b9bda9dd74f543a8cb136bac9d8d201a340834f85c273b7e211f48173f8fe3
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ .rakeTasks
13
+
14
+ /.idea/
15
+ tags
data/.rubocop.yml ADDED
@@ -0,0 +1,3 @@
1
+ inherit_from: .rubocop_todo.yml
2
+ AllCops:
3
+ NewCops: enable
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,36 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2023-12-28 16:04:34 UTC using RuboCop version 1.59.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ Lint/MixedRegexpCaptureTypes:
11
+ Exclude:
12
+ - 'lib/jets_gem_layer/build_env/build_layer.rb'
13
+
14
+ Metrics/AbcSize:
15
+ Exclude:
16
+ - 'lib/jets_gem_layer/build_env/build_layer.rb'
17
+
18
+ Metrics/CyclomaticComplexity:
19
+ Exclude:
20
+ - 'lib/jets_gem_layer/build_env/build_layer.rb'
21
+
22
+ Metrics/MethodLength:
23
+ Exclude:
24
+ - 'lib/jets_gem_layer/build_env/build_layer.rb'
25
+
26
+ Metrics/PerceivedComplexity:
27
+ Exclude:
28
+ - 'lib/jets_gem_layer/build_env/build_layer.rb'
29
+
30
+ # Offense count: 2
31
+ # Configuration parameters: AllowedConstants.
32
+ Style/Documentation:
33
+ Enabled: false
34
+
35
+ Metrics/ClassLength:
36
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in s3_gem_host.gemspec
6
+ gemspec
7
+
8
+ group :development, :test do
9
+ gem 'rspec'
10
+ gem 'rubocop', require: false
11
+ gem 'rubocop-rspec', require: false
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,291 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jets_gem_layer (0.1)
5
+ jets (~> 5.0)
6
+ rake
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionmailer (7.0.8)
12
+ actionpack (= 7.0.8)
13
+ actionview (= 7.0.8)
14
+ activejob (= 7.0.8)
15
+ activesupport (= 7.0.8)
16
+ mail (~> 2.5, >= 2.5.4)
17
+ net-imap
18
+ net-pop
19
+ net-smtp
20
+ rails-dom-testing (~> 2.0)
21
+ actionpack (7.0.8)
22
+ actionview (= 7.0.8)
23
+ activesupport (= 7.0.8)
24
+ rack (~> 2.0, >= 2.2.4)
25
+ rack-test (>= 0.6.3)
26
+ rails-dom-testing (~> 2.0)
27
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
28
+ actionview (7.0.8)
29
+ activesupport (= 7.0.8)
30
+ builder (~> 3.1)
31
+ erubi (~> 1.4)
32
+ rails-dom-testing (~> 2.0)
33
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
34
+ activejob (7.0.8)
35
+ activesupport (= 7.0.8)
36
+ globalid (>= 0.3.6)
37
+ activemodel (7.0.8)
38
+ activesupport (= 7.0.8)
39
+ activerecord (7.0.8)
40
+ activemodel (= 7.0.8)
41
+ activesupport (= 7.0.8)
42
+ activesupport (7.0.8)
43
+ concurrent-ruby (~> 1.0, >= 1.0.2)
44
+ i18n (>= 1.6, < 2)
45
+ minitest (>= 5.1)
46
+ tzinfo (~> 2.0)
47
+ ast (2.4.2)
48
+ aws-eventstream (1.3.0)
49
+ aws-logs (0.5.1)
50
+ activesupport
51
+ aws-mfa-secure
52
+ aws-sdk-cloudwatchlogs
53
+ rainbow
54
+ thor
55
+ zeitwerk
56
+ aws-mfa-secure (0.4.4)
57
+ activesupport
58
+ aws-sdk-core
59
+ aws_config
60
+ memoist
61
+ rainbow
62
+ thor
63
+ zeitwerk
64
+ aws-partitions (1.875.0)
65
+ aws-sdk-apigateway (1.90.0)
66
+ aws-sdk-core (~> 3, >= 3.188.0)
67
+ aws-sigv4 (~> 1.1)
68
+ aws-sdk-cloudformation (1.97.0)
69
+ aws-sdk-core (~> 3, >= 3.188.0)
70
+ aws-sigv4 (~> 1.1)
71
+ aws-sdk-cloudwatchlogs (1.76.0)
72
+ aws-sdk-core (~> 3, >= 3.188.0)
73
+ aws-sigv4 (~> 1.1)
74
+ aws-sdk-core (3.190.1)
75
+ aws-eventstream (~> 1, >= 1.3.0)
76
+ aws-partitions (~> 1, >= 1.651.0)
77
+ aws-sigv4 (~> 1.8)
78
+ jmespath (~> 1, >= 1.6.1)
79
+ aws-sdk-dynamodb (1.98.0)
80
+ aws-sdk-core (~> 3, >= 3.188.0)
81
+ aws-sigv4 (~> 1.1)
82
+ aws-sdk-kinesis (1.54.0)
83
+ aws-sdk-core (~> 3, >= 3.188.0)
84
+ aws-sigv4 (~> 1.1)
85
+ aws-sdk-kms (1.75.0)
86
+ aws-sdk-core (~> 3, >= 3.188.0)
87
+ aws-sigv4 (~> 1.1)
88
+ aws-sdk-lambda (1.113.0)
89
+ aws-sdk-core (~> 3, >= 3.188.0)
90
+ aws-sigv4 (~> 1.1)
91
+ aws-sdk-s3 (1.142.0)
92
+ aws-sdk-core (~> 3, >= 3.189.0)
93
+ aws-sdk-kms (~> 1)
94
+ aws-sigv4 (~> 1.8)
95
+ aws-sdk-sns (1.70.0)
96
+ aws-sdk-core (~> 3, >= 3.188.0)
97
+ aws-sigv4 (~> 1.1)
98
+ aws-sdk-sqs (1.69.0)
99
+ aws-sdk-core (~> 3, >= 3.188.0)
100
+ aws-sigv4 (~> 1.1)
101
+ aws-sdk-ssm (1.162.0)
102
+ aws-sdk-core (~> 3, >= 3.188.0)
103
+ aws-sigv4 (~> 1.1)
104
+ aws-sigv4 (1.8.0)
105
+ aws-eventstream (~> 1, >= 1.0.2)
106
+ aws_config (0.1.1)
107
+ builder (3.2.4)
108
+ cfn-status (0.5.0)
109
+ aws-sdk-cloudformation
110
+ cfn_camelizer (0.5.0)
111
+ activesupport
112
+ memoist
113
+ rainbow
114
+ cfn_response (0.2.0)
115
+ cli-format (0.5.0)
116
+ activesupport
117
+ text-table
118
+ zeitwerk
119
+ concurrent-ruby (1.2.2)
120
+ crass (1.0.6)
121
+ date (3.3.4)
122
+ diff-lcs (1.5.0)
123
+ dotenv (2.8.1)
124
+ dsl_evaluator (0.3.1)
125
+ activesupport
126
+ memoist
127
+ rainbow
128
+ zeitwerk
129
+ erubi (1.12.0)
130
+ gems (1.2.0)
131
+ globalid (1.2.1)
132
+ activesupport (>= 6.1)
133
+ hashie (5.0.0)
134
+ i18n (1.14.1)
135
+ concurrent-ruby (~> 1.0)
136
+ jets (5.0.8)
137
+ actionmailer (~> 7.0.8)
138
+ actionpack (~> 7.0.8)
139
+ actionview (~> 7.0.8)
140
+ activerecord (~> 7.0.8)
141
+ activesupport (~> 7.0.8)
142
+ aws-logs
143
+ aws-mfa-secure (~> 0.4.0)
144
+ aws-sdk-apigateway
145
+ aws-sdk-cloudformation
146
+ aws-sdk-cloudwatchlogs
147
+ aws-sdk-dynamodb
148
+ aws-sdk-kinesis
149
+ aws-sdk-lambda
150
+ aws-sdk-s3
151
+ aws-sdk-sns
152
+ aws-sdk-sqs
153
+ aws-sdk-ssm
154
+ cfn-status (>= 0.5.0)
155
+ cfn_camelizer (>= 0.4.9)
156
+ cfn_response
157
+ cli-format (>= 0.4.0)
158
+ dotenv
159
+ dsl_evaluator (>= 0.3.0)
160
+ gems
161
+ hashie
162
+ jets-api (>= 0.1.4)
163
+ jets-git
164
+ jets-html-sanitizer
165
+ kramdown
166
+ memoist
167
+ mini_mime
168
+ rack
169
+ railties (~> 7.0.8)
170
+ rainbow
171
+ recursive-open-struct
172
+ text-table
173
+ thor
174
+ zeitwerk (>= 2.6.0)
175
+ jets-api (0.1.5)
176
+ jets-git (0.2.1)
177
+ activesupport
178
+ memoist
179
+ rainbow
180
+ zeitwerk
181
+ jets-html-sanitizer (1.0.4)
182
+ loofah (~> 2.2, >= 2.2.2)
183
+ jmespath (1.6.2)
184
+ json (2.7.1)
185
+ kramdown (2.4.0)
186
+ rexml
187
+ language_server-protocol (3.17.0.3)
188
+ loofah (2.22.0)
189
+ crass (~> 1.0.2)
190
+ nokogiri (>= 1.12.0)
191
+ mail (2.8.1)
192
+ mini_mime (>= 0.1.1)
193
+ net-imap
194
+ net-pop
195
+ net-smtp
196
+ memoist (0.16.2)
197
+ method_source (1.0.0)
198
+ mini_mime (1.1.5)
199
+ minitest (5.20.0)
200
+ net-imap (0.4.9)
201
+ date
202
+ net-protocol
203
+ net-pop (0.1.2)
204
+ net-protocol
205
+ net-protocol (0.2.2)
206
+ timeout
207
+ net-smtp (0.4.0)
208
+ net-protocol
209
+ nokogiri (1.16.0-arm64-darwin)
210
+ racc (~> 1.4)
211
+ parallel (1.24.0)
212
+ parser (3.2.2.4)
213
+ ast (~> 2.4.1)
214
+ racc
215
+ racc (1.7.3)
216
+ rack (2.2.8)
217
+ rack-test (2.1.0)
218
+ rack (>= 1.3)
219
+ rails-dom-testing (2.2.0)
220
+ activesupport (>= 5.0.0)
221
+ minitest
222
+ nokogiri (>= 1.6)
223
+ rails-html-sanitizer (1.6.0)
224
+ loofah (~> 2.21)
225
+ nokogiri (~> 1.14)
226
+ railties (7.0.8)
227
+ actionpack (= 7.0.8)
228
+ activesupport (= 7.0.8)
229
+ method_source
230
+ rake (>= 12.2)
231
+ thor (~> 1.0)
232
+ zeitwerk (~> 2.5)
233
+ rainbow (3.1.1)
234
+ rake (13.1.0)
235
+ recursive-open-struct (1.1.3)
236
+ regexp_parser (2.8.3)
237
+ rexml (3.2.6)
238
+ rspec (3.12.0)
239
+ rspec-core (~> 3.12.0)
240
+ rspec-expectations (~> 3.12.0)
241
+ rspec-mocks (~> 3.12.0)
242
+ rspec-core (3.12.2)
243
+ rspec-support (~> 3.12.0)
244
+ rspec-expectations (3.12.3)
245
+ diff-lcs (>= 1.2.0, < 2.0)
246
+ rspec-support (~> 3.12.0)
247
+ rspec-mocks (3.12.6)
248
+ diff-lcs (>= 1.2.0, < 2.0)
249
+ rspec-support (~> 3.12.0)
250
+ rspec-support (3.12.1)
251
+ rubocop (1.59.0)
252
+ json (~> 2.3)
253
+ language_server-protocol (>= 3.17.0)
254
+ parallel (~> 1.10)
255
+ parser (>= 3.2.2.4)
256
+ rainbow (>= 2.2.2, < 4.0)
257
+ regexp_parser (>= 1.8, < 3.0)
258
+ rexml (>= 3.2.5, < 4.0)
259
+ rubocop-ast (>= 1.30.0, < 2.0)
260
+ ruby-progressbar (~> 1.7)
261
+ unicode-display_width (>= 2.4.0, < 3.0)
262
+ rubocop-ast (1.30.0)
263
+ parser (>= 3.2.1.0)
264
+ rubocop-capybara (2.19.0)
265
+ rubocop (~> 1.41)
266
+ rubocop-factory_bot (2.24.0)
267
+ rubocop (~> 1.33)
268
+ rubocop-rspec (2.25.0)
269
+ rubocop (~> 1.40)
270
+ rubocop-capybara (~> 2.17)
271
+ rubocop-factory_bot (~> 2.22)
272
+ ruby-progressbar (1.13.0)
273
+ text-table (1.2.4)
274
+ thor (1.3.0)
275
+ timeout (0.4.1)
276
+ tzinfo (2.0.6)
277
+ concurrent-ruby (~> 1.0)
278
+ unicode-display_width (2.5.0)
279
+ zeitwerk (2.6.12)
280
+
281
+ PLATFORMS
282
+ arm64-darwin-23
283
+
284
+ DEPENDENCIES
285
+ jets_gem_layer!
286
+ rspec
287
+ rubocop
288
+ rubocop-rspec
289
+
290
+ BUNDLED WITH
291
+ 2.5.3
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+
2
+ Copyright (c) Dara Technologies, LLC
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # Jets Gem Layer
2
+ This gem provides a framework for automatically creating and publish an AWS Lambda Layer from project gems and
3
+ their linked libraries for use with [Ruby on Jets](https://github.com/rubyonjets/jets).
4
+
5
+ This gem creates a Lambda Layer based on your Jets project namespace and ruby version. I.e. for the app `demo` in `production` environment,
6
+ the Lambda Layer `demo-prod-ruby-3_2_2-gem_layer` will be created or its version incremented as needed. A new version is published whenever your
7
+ Gemfile.lock and/or Gemfile is changed (this is tracked based on a hash value stored in the Lambda Layer version description).
8
+
9
+ * The gem's build task runs in a docker container, i.e. `public.ecr.aws/sam/build-ruby:3.2`. The container version
10
+ is based on the current minor ruby version (i.e. 3.2 for ruby 3.2.2, so ensure your build environment's ruby version
11
+ is correctly set for your project.
12
+ * Docker is a prerequisite and must be installed to use this gem.
13
+ * This gem has not been tested to work on windows machines.
14
+
15
+ ## Installation
16
+
17
+ 1. Jets Pro would typically be disabled when using this gem so as to not generate multiple Lambda Layers.
18
+
19
+ ```ruby
20
+ # config/application.rb
21
+
22
+ config.pro.disable = true
23
+ ```
24
+
25
+ 2. The layer ARN created by this gem must be inserted so it is referenced on app deployment. The easiest way to do this
26
+ is to add the included helper to your environment configuration.
27
+
28
+ ```ruby
29
+ # config/production.rb
30
+
31
+ # JetsGemLayer.arn will resolve to the latest version of the published Layer, also looking for a correct hash in the
32
+ # layer description indicating the current Gemfile.lock and Gemfile are supported.
33
+ # If a suitable layer is not found, the gem will log an error and resolve to 'error-fetching-gem-layer-arn' which will allow your
34
+ # application to run locally but hopefully prevent an invalid deployment
35
+ config.lambda.layers = [JetsGemLayer.arn]
36
+ ```
37
+
38
+ 3. Add this gem to your Gemfile:
39
+ ```ruby
40
+ # Gemfile
41
+ gem 'jets_gem_layer'
42
+ ```
43
+
44
+ 4. Add the gem's initializer to your Rakefile
45
+ ```ruby
46
+ # Rakefile
47
+
48
+ require 'jets'
49
+ require_relative 'config/application'
50
+
51
+ Jets.application.load_tasks
52
+ JetsGemLayer.load_tasks
53
+ ```
54
+
55
+ 3. After running `bundle install`, run `rake -T` and you should see this Gem's tasks available for use.
56
+ ```
57
+ ➜ rake -T
58
+ rake gem_layer:build_and_publish # Build, publish, and clean
59
+ rake gem_layer:build # Build the gem layer zip file
60
+ rake gem_layer:publish # Publish the built gem laye zip to AWS
61
+ rake gem_layer:clean # Clean up the gem's tmp files
62
+ ```
63
+
64
+ ## Configuration
65
+
66
+ The following environmental variables may be used:
67
+ * `GEM_LAYER_ENV`: Comma-separated `key=value` pairs which will be added to the docker build environment.
68
+ For example, to pass a Gemfury token for Bundler, you could use `GEM_LAYER_ENV="BUNDLE_GEM__FURY__IO=xxyyzz"`
69
+ and `BUNDLE_GEM__FURY__IO` will be set correctly within the build container.
70
+ * `GEM_LAYER_PACKAGE_DEPENDENCIES`: use this to identify comma separated dependencies required for bundle install
71
+ specific to your Gemfile. For example, to build the `mysql2` gem you will need to set `GEM_LAYER_PACKAGE_DEPENDENCIES=mysql-devel`.
72
+ Dependencies will be installed within the build container and copied into the published Lambda Layer.
73
+
74
+ ## Deployment
75
+ Within your project directory (example for development environment):
76
+ 1. run `JETS_ENV=development rake gem_layer:build_and_publish`
77
+ 2. run `JETS_ENV=development jets deploy`
78
+
79
+ ## Acknowledgements
80
+ A big thank you to the authors of [Lambda Layer Cake](https://github.com/loganb/lambda-layer-cake), which served as a reference.
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'jets_gem_layer/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'jets_gem_layer'
9
+ spec.version = JetsGemLayer::VERSION
10
+ spec.authors = ['DocGo Engineering']
11
+ spec.license = 'MIT'
12
+ spec.required_ruby_version = '~> 3.2'
13
+
14
+ spec.summary = 'Rake tasks to automate building a Lambda Layer for Ruby on Jets projects'
15
+ spec.description = 'This gem provides Rake tasks to create and publish an AWS Lambda Layer from project gems ' \
16
+ 'and their linked libraries. Designed for use with Ruby on Jets 5.'
17
+ spec.homepage = 'https://github.com/ambulnzllc/jets_gem_layer'
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+
22
+ spec.add_dependency 'jets', '~> 5.0'
23
+ spec.add_dependency 'rake'
24
+ spec.metadata['rubygems_mfa_required'] = 'true'
25
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Substantial portions of this file attributed to lambda_layer_cake (c) 2019 Logan Bowers
4
+
5
+ require 'English'
6
+ require 'open3'
7
+ require 'fileutils'
8
+
9
+ def main
10
+ warn('Installing yum package manager...')
11
+ unless system('yum', 'install', '-y', 'yum-utils')
12
+ warn("Could not install yum-utils, exit code #{$CHILD_STATUS}, aborting...")
13
+ exit 1
14
+ end
15
+
16
+ Dir.chdir('/tmp/inputs')
17
+
18
+ if ENV['GEM_LAYER_PACKAGE_DEPENDENCIES']
19
+ warn("Installing package dependencies: #{ENV.fetch('GEM_LAYER_PACKAGE_DEPENDENCIES')}...")
20
+ gem_deps = ENV.fetch('GEM_LAYER_PACKAGE_DEPENDENCIES').split(',')
21
+ unless system('yum', 'install', '-y', *gem_deps)
22
+ warn('Could not install build dependency packages, aborting...')
23
+ exit 2
24
+ end
25
+ end
26
+
27
+ warn('Building gems...')
28
+ FileUtils.mkdir_p('/tmp/build/bundle')
29
+ system('bundle', 'lock', '--add-platform', 'x86_64-linux')
30
+ system('bundle', 'config', 'set', '--local', 'deployment', 'true')
31
+ system('bundle', 'config', 'set', '--local', 'path', '/tmp/build/bundle')
32
+ unless system('bundle', 'install')
33
+ warn('Error while building gems, aborting...')
34
+ exit 3
35
+ end
36
+
37
+ warn('Copying libs...')
38
+ required_libs = Set.new
39
+ yum_cache = Hash.new do |h, k|
40
+ pkgs_str, = Open3.capture2('repoquery', '-f', k)
41
+ h[k] = pkgs_str
42
+ end
43
+
44
+ Dir['/tmp/build/**/*.so*'].each do |lib|
45
+ deps_str, status = Open3.capture2('ldd', lib)
46
+ unless status.exitstatus.zero?
47
+ warn("Couldn't run ldd! Status code: #{status}, ignoring…")
48
+ # exit 3
49
+ end
50
+ deps = deps_str.split("\n").collect { |d_str| d_str[%r{(?<==>\s)(/\S+)}] }.compact
51
+ next unless deps.length.positive?
52
+
53
+ deps.each do |dep|
54
+ pkgs = yum_cache[dep].split("\n")
55
+ required_libs << dep if pkgs.length.positive?
56
+ end
57
+ end
58
+
59
+ FileUtils.mkdir_p('/tmp/outputs/lib')
60
+ FileUtils.cp(required_libs.to_a, '/tmp/outputs/lib')
61
+
62
+ # These files are not needed at runtime
63
+ FileUtils.rm_rf(Dir['/tmp/build/bundle/ruby/*/cache'])
64
+ FileUtils.rm_rf(Dir['/tmp/build/bundle/ruby/*/gems/*/test'])
65
+
66
+ # Move outputs into place for zipping up
67
+ FileUtils.mkdir_p('/tmp/outputs/ruby')
68
+ FileUtils.cp_r('/tmp/build/bundle/ruby', '/tmp/outputs/ruby')
69
+ FileUtils.mv('/tmp/outputs/ruby/ruby', '/tmp/outputs/ruby/gems')
70
+ FileUtils.chmod_R(0o755, '/tmp/outputs')
71
+
72
+ warn('Successfully generated gems and dependencies...')
73
+ end
74
+
75
+ main
76
+ true
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JetsGemLayer
4
+ class TaskHelper
5
+ include Rake::DSL
6
+ include Jets::AwsServices
7
+
8
+ # Files used to generate the gem layer
9
+ INPUT_FILES = Rake::FileList.new(
10
+ ['Gemfile', 'Gemfile.lock'].collect { |f| File.join(Jets.root, f) }
11
+ )
12
+ LOCAL_TMP_DIR = 'tmp/jets_gem_layer'
13
+ OUTPUT_DIR = File.expand_path(File.join(Jets.root, "#{LOCAL_TMP_DIR}/"))
14
+
15
+ def self.install
16
+ new.install
17
+ end
18
+
19
+ def self.arn
20
+ @arn ||= new.arn
21
+ end
22
+
23
+ def arn
24
+ # We do not want to do any of this when running in the lambda environment
25
+ # as it is only required for deployment.
26
+ @arn ||= if ENV['LAMBDA_TASK_ROOT']
27
+ 'no-op-while-running-in-lambda'
28
+ else
29
+ published_arn
30
+ end
31
+
32
+ @arn ||= 'no-matching-gem-layer-found'
33
+ end
34
+
35
+ def install
36
+ namespace :gem_layer do
37
+ install_build_and_publish
38
+ install_build
39
+ install_publish
40
+ install_clean
41
+ end
42
+ end
43
+
44
+ def install_build_and_publish
45
+ desc 'Build and publish a gem layer version'
46
+ task :build_and_publish do
47
+ Rake::Task['gem_layer:build'].invoke
48
+ Rake::Task['gem_layer:publish'].invoke
49
+ Rake::Task['gem_layer:clean'].invoke
50
+ end
51
+ end
52
+
53
+ def install_build
54
+ desc 'Build the gem layer zip file'
55
+ task :build do
56
+ Rake::Task['gem_layer:clean'].invoke
57
+ build_layer
58
+ zip_layer
59
+ end
60
+ end
61
+
62
+ def install_publish
63
+ desc 'Publish a built layer zip file'
64
+ task :publish do
65
+ publish_layer
66
+ end
67
+ end
68
+
69
+ def install_clean
70
+ desc 'Clean tmp files'
71
+ task :clean do
72
+ FileUtils.rm_r(working_dir) if File.exist?(working_dir)
73
+ end
74
+ end
75
+
76
+ def build_layer
77
+ FileUtils.mkdir_p(inputs_dir)
78
+ FileUtils.cp(INPUT_FILES.existing, inputs_dir)
79
+ system(*docker_run_cmd) or raise
80
+ end
81
+
82
+ def zip_layer
83
+ pwd = Dir.pwd
84
+ begin
85
+ Dir.chdir(outputs_dir)
86
+ system(*%W[zip -r #{File.join(working_dir, "#{layer_name}.zip")} lib ruby], out: File::NULL) or raise
87
+ puts 'Layer zipped successfully...'
88
+ ensure
89
+ Dir.chdir(pwd)
90
+ end
91
+ end
92
+
93
+ def publish_layer
94
+ aws_lambda.publish_layer_version(
95
+ layer_name:, # required
96
+ description: layer_version_description,
97
+ content: { zip_file: File.read(zip_file_path) }
98
+ )
99
+ puts "#{layer_name} published for #{layer_version_description}..."
100
+ end
101
+
102
+ private
103
+
104
+ def input_hash
105
+ @input_hash ||= begin
106
+ hash = Digest::SHA1.hexdigest(INPUT_FILES.existing.collect do |f|
107
+ File.read(f)
108
+ end.join("\x1C"))
109
+ hash[0..7]
110
+ end
111
+ end
112
+
113
+ def inputs_dir
114
+ working_dir('gem_layer_cache')
115
+ end
116
+
117
+ def layer_name
118
+ "#{Jets.project_namespace}-ruby-#{RUBY_VERSION.gsub('.', '_')}-gem_layer"
119
+ end
120
+
121
+ def layer_version_description
122
+ @layer_version_description ||= "Dependency Hash: #{input_hash}"
123
+ end
124
+
125
+ def zip_file_path
126
+ File.join(working_dir, "#{layer_name}.zip")
127
+ end
128
+
129
+ def outputs_dir
130
+ working_dir(layer_name.to_s)
131
+ end
132
+
133
+ def working_dir(path_suffix = '')
134
+ File.expand_path(
135
+ File.join(
136
+ OUTPUT_DIR,
137
+ path_suffix
138
+ )
139
+ )
140
+ end
141
+
142
+ def docker_tag
143
+ (/^\d+\.\d+/.match(RUBY_VERSION)[0]).to_s
144
+ end
145
+
146
+ def docker_run_cmd
147
+ cmd = %W[docker run --rm
148
+ --platform linux/amd64
149
+ -v #{inputs_dir}:/tmp/inputs
150
+ -v #{outputs_dir}:/tmp/outputs
151
+ -v #{File.expand_path("#{__dir__}/build_env")}:/var/task]
152
+
153
+ ENV.fetch('GEM_LAYER_ENV').split(',').each { |env| cmd.push "-e#{env}" } if ENV['GEM_LAYER_ENV']
154
+
155
+ if ENV['GEM_LAYER_PACKAGE_DEPENDENCIES']
156
+ cmd.push "-eGEM_LAYER_PACKAGE_DEPENDENCIES=#{ENV.fetch('GEM_LAYER_PACKAGE_DEPENDENCIES')}"
157
+ end
158
+
159
+ cmd.push(*%W[public.ecr.aws/sam/build-ruby#{docker_tag} ruby build_layer.rb])
160
+ end
161
+
162
+ def published_arn
163
+ return nil unless published?
164
+
165
+ published_layer_version.layer_version_arn
166
+ rescue StandardError
167
+ Jets.logger.error('Could not resolve lambda layer arn')
168
+ 'error-fetching-gem-layer-arn'
169
+ end
170
+
171
+ def published?
172
+ published_layer_version&.description == layer_version_description
173
+ end
174
+
175
+ def published_layer_version
176
+ @published_layer_version ||= aws_lambda.list_layer_versions({ layer_name: }).layer_versions&.first
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JetsGemLayer
4
+ VERSION = '0.1'
5
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jets'
4
+ require 'digest'
5
+ require 'fileutils'
6
+ require 'rake'
7
+
8
+ require 'jets_gem_layer/task_helper'
9
+
10
+ module JetsGemLayer
11
+ def self.load_tasks
12
+ JetsGemLayer::TaskHelper.install
13
+ end
14
+
15
+ def self.arn
16
+ JetsGemLayer::TaskHelper.arn
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jets_gem_layer
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - DocGo Engineering
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-12-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jets
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: This gem provides Rake tasks to create and publish an AWS Lambda Layer
42
+ from project gems and their linked libraries. Designed for use with Ruby on Jets
43
+ 5.
44
+ email:
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".rubocop.yml"
51
+ - ".rubocop_todo.yml"
52
+ - Gemfile
53
+ - Gemfile.lock
54
+ - LICENSE.txt
55
+ - README.md
56
+ - jets_gem_layer.gemspec
57
+ - lib/jets_gem_layer.rb
58
+ - lib/jets_gem_layer/build_env/build_layer.rb
59
+ - lib/jets_gem_layer/task_helper.rb
60
+ - lib/jets_gem_layer/version.rb
61
+ homepage: https://github.com/ambulnzllc/jets_gem_layer
62
+ licenses:
63
+ - MIT
64
+ metadata:
65
+ rubygems_mfa_required: 'true'
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.2'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubygems_version: 3.5.3
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Rake tasks to automate building a Lambda Layer for Ruby on Jets projects
85
+ test_files: []