Class: Foobara::AWS::Packager
- Inherits:
-
Object
- Object
- Foobara::AWS::Packager
- Defined in:
- lib/foobara/aws/packager.rb
Overview
Builds one deployable artifact per unit in a Plan.
BUILD time — neither runtime nor synth. It shells out to Docker, so it is required explicitly and never from a Lambda or a CDK app.
Foobara::AWS::Packager.new(plan:, root: ".", out: "build").build
Each artifact contains the application's sources, a generated handler.rb,
and a standalone gem bundle holding only that unit's dependencies. Units
whose gemfiles resolve identically share one bundle build.
It also writes the plan next to them. That is the contract with synthesis: the CDK app reads what was BUILT, so it cannot route to an artifact that does not exist, and it needs neither a running connector nor the app.
Constant Summary collapse
- DEFAULT_IMAGE =
A Lambda-like container, so native extensions are built against the runtime's own libraries rather than the host's.
"public.ecr.aws/sam/build-ruby4.0"- BUNDLE_COMMAND =
Bundler's standalone mode, NOT
bundle exec: Bundler's runtime costs several hundred milliseconds at Lambda's smaller memory sizes, on every cold start, for nothing a deployed artifact needs. "bundle install --standalone"
Instance Method Summary collapse
-
#build ⇒ Object
rubocop:enable Metrics/ParameterLists.
-
#initialize(plan:, root: Dir.pwd, out: "build", sources: %w[app config],, gemfiles: "units", image: DEFAULT_IMAGE, env: {}, mounts: [], handler_template: nil, authorizer: nil, docker: nil) ⇒ Packager
constructor
rubocop:disable Metrics/ParameterLists.
- #plan_path ⇒ Object
Constructor Details
#initialize(plan:, root: Dir.pwd, out: "build", sources: %w[app config],, gemfiles: "units", image: DEFAULT_IMAGE, env: {}, mounts: [], handler_template: nil, authorizer: nil, docker: nil) ⇒ Packager
rubocop:disable Metrics/ParameterLists
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/foobara/aws/packager.rb', line 38 def initialize(plan:, root: Dir.pwd, out: "build", sources: %w[app config], gemfiles: "units", image: DEFAULT_IMAGE, env: {}, mounts: [], handler_template: nil, authorizer: nil, docker: nil) @plan = plan @root = File.(root) @out = File.(out, @root) @sources = sources @gemfiles = gemfiles @image = image @env = env # Extra host paths to mount. A gemfile referencing a gem by path outside # the application root would otherwise fail inside the container, which # sees only the root. @mounts = mounts @handler_template = handler_template @authorizer = # Injectable so the layout can be tested without Docker, and so an # environment with a different container runtime can substitute one. @docker = docker || method(:run_docker) end |
Instance Method Details
#build ⇒ Object
rubocop:enable Metrics/ParameterLists
60 61 62 63 64 65 66 67 68 |
# File 'lib/foobara/aws/packager.rb', line 60 def build FileUtils.mkdir_p(@out) built = @plan.units.map { |unit| build_unit(unit) } built << if @authorizer File.write(plan_path, JSON.pretty_generate(@plan.to_h)) built end |
#plan_path ⇒ Object
70 |
# File 'lib/foobara/aws/packager.rb', line 70 def plan_path = File.join(@out, "plan.json") |