Class: Jets::Commands::Build

Inherits:
Object
  • Object
show all
Includes:
StackInfo
Defined in:
lib/jets/commands/build.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from StackInfo

#first_run?, #parent_stack_name, #s3_bucket, #stack_type

Methods included from AwsServices

#apigateway, #cfn, #lambda, #logs, #s3, #s3_resource, #sns, #sts

Methods included from AwsServices::StackStatus

#lookup, #stack_exists?, #stack_in_progress?

Constructor Details

#initialize(options) ⇒ Build

Returns a new instance of Build.



7
8
9
# File 'lib/jets/commands/build.rb', line 7

def initialize(options)
  @options = options.dup
end

Class Method Details

.app_file?(path) ⇒ Boolean

Returns:

  • (Boolean)


188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/jets/commands/build.rb', line 188

def self.app_file?(path)
  return false unless File.extname(path) == ".rb"
  # Do not define lamda functions for the application_controller.rb or
  # application_job.rb
  excludes = %w[
    application_controller.rb
    application_job.rb
  ]
  return false if excludes.detect { |p| path.include?(p) }

  includes = %w[
    app/controllers
    app/jobs
    app/functions
    app/rules
  ]
  return true if includes.detect { |p| path.include?(p) }

  false
end

.app_filesObject

Crucial that the Dir.pwd is in the tmp_code because for because Jets.boot set ups autoload_paths and this is how project classes are loaded. TODO: rework code so that Dir.pwd does not have to be in tmp_code for build to work.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/jets/commands/build.rb', line 109

def self.app_files
  paths = []
  expression = "#{Jets.root}app/**/**/*.rb"
  Dir.glob(expression).each do |path|
    return false unless File.file?(path)
    next unless app_file?(path)

    relative_path = path.sub(Jets.root.to_s, '')
    # Rids of the Jets.root at beginning
    paths << relative_path
  end
  paths += internal_app_files
  paths
end

.app_has_ruby?Boolean

Returns:

  • (Boolean)


149
150
151
152
153
154
155
156
# File 'lib/jets/commands/build.rb', line 149

def self.app_has_ruby?
  has_ruby = app_files.detect do |path|
    app_class = Jets::Klass.from_path(path)  # IE: PostsController, Jets::PublicController
    langs = app_class.tasks.map(&:lang)
    langs.include?(:ruby) && app_class != Jets::PreheatJob
  end
  !!has_ruby
end

.internal_app_filesObject

Add internal Jets controllers if they are being used



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/jets/commands/build.rb', line 172

def self.internal_app_files
  paths = []
  controllers = File.expand_path("../../internal/app/controllers/jets", __FILE__)

  public_catchall = Jets::Router.has_controller?("Jets::PublicController")
  paths << "#{controllers}/public_controller.rb" if public_catchall

  rack_catchall = Jets::Router.has_controller?("Jets::RackController")
  paths << "#{controllers}/rack_controller.rb" if rack_catchall

  jobs = File.expand_path("../../internal/app/jobs/jets", __FILE__)
  paths << "#{jobs}/preheat_job.rb"

  paths
end

.poly_only?Boolean

Finds out of the app has polymorphic functions only and zero ruby functions. In this case, we can skip a lot of the ruby related building and speed up the deploy process.

Returns:

  • (Boolean)


145
146
147
# File 'lib/jets/commands/build.rb', line 145

def self.poly_only?
  !app_has_ruby? && !shared_has_ruby?
end

.shared_filesObject



128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/jets/commands/build.rb', line 128

def self.shared_files
  paths = []
  expression = "#{Jets.root}app/**/**/*.rb"
  Dir.glob(expression).each do |path|
    return false unless File.file?(path)
    next unless path.include?("app/shared/resources")

    relative_path = path.sub(Jets.root.to_s, '')
    # Rids of the Jets.root at beginning
    paths << relative_path
  end
  paths
end

.shared_has_ruby?Boolean

Returns:

  • (Boolean)


158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/jets/commands/build.rb', line 158

def self.shared_has_ruby?
  has_ruby = false
  Jets::Stack.subclasses.each do |klass|
    klass.functions.each do |fun|
      if fun.lang == :ruby
        has_ruby = true
        break
      end
    end
  end
  has_ruby
end

.tmp_code(full_build_path = false) ⇒ Object



209
210
211
# File 'lib/jets/commands/build.rb', line 209

def self.tmp_code(full_build_path=false)
  full_build_path ? "#{Jets.build_root}/stage/code" : "stage/code"
end

Instance Method Details

#app_filesObject



101
102
103
# File 'lib/jets/commands/build.rb', line 101

def app_files
  self.class.app_files
end

#buildObject



20
21
22
23
# File 'lib/jets/commands/build.rb', line 20

def build
  build_code unless @options[:templates]
  build_templates
end

#build_all_templatesObject



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/jets/commands/build.rb', line 40

def build_all_templates
  # CloudFormation templates
  # 1. Shared templates - child templates needs them
  build_api_gateway_templates
  # 2. Child templates - parent template needs them
  build_app_child_templates
  # 2. Child templates - parent template needs them
  build_shared_resources_templates
  # 4. Finally parent template
  build_parent_template # must be called at the end
end

#build_api_gateway_templatesObject



56
57
58
59
# File 'lib/jets/commands/build.rb', line 56

def build_api_gateway_templates
  Jets::Cfn::Builders::ApiGatewayBuilder.new(@options).build
  Jets::Cfn::Builders::ApiDeploymentBuilder.new(@options).build
end

#build_app_child_templatesObject



61
62
63
64
65
# File 'lib/jets/commands/build.rb', line 61

def build_app_child_templates
  app_files.each do |path|
    build_child_template(path)
  end
end

#build_child_template(path) ⇒ Object

path: app/controllers/comments_controller.rb path: app/jobs/easy_job.rb



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/jets/commands/build.rb', line 75

def build_child_template(path)
  md = path.match(%r{app/(.*?)/}) # extract: controller, job or function
  process_class = md[1].classify
  builder_class = "Jets::Cfn::Builders::#{process_class}Builder".constantize

  # Examples:
  #   Jets::Cfn::Builders::ControllerBuilder.new(PostsController)
  #   Jets::Cfn::Builders::JobBuilder.new(EasyJob)
  #   Jets::Cfn::Builders::RuleBuilder.new(CheckRule)
  #   Jets::Cfn::Builders::FunctionBuilder.new(Hello)
  #   Jets::Cfn::Builders::FunctionBuilder.new(HelloFunction)
  app_class = Jets::Klass.from_path(path)
  builder = builder_class.new(app_class)
  unless Jets.poly_only? && app_class == Jets::PreheatJob
    builder.build
  end
end

#build_codeObject



25
26
27
# File 'lib/jets/commands/build.rb', line 25

def build_code
  Jets::Builders::CodeBuilder.new.build unless @options[:noop]
end

#build_minimal_templateObject



52
53
54
# File 'lib/jets/commands/build.rb', line 52

def build_minimal_template
  Jets::Cfn::Builders::ParentBuilder.new(@options).build
end

#build_parent_templateObject



93
94
95
# File 'lib/jets/commands/build.rb', line 93

def build_parent_template
  Jets::Cfn::Builders::ParentBuilder.new(@options).build
end

#build_shared_resources_templatesObject



67
68
69
70
71
# File 'lib/jets/commands/build.rb', line 67

def build_shared_resources_templates
  Jets::Stack.subclasses.each do |subclass|
    Jets::Cfn::Builders::SharedBuilder.new(subclass).build
  end
end

#build_templatesObject



29
30
31
32
33
34
# File 'lib/jets/commands/build.rb', line 29

def build_templates
  puts "Building CloudFormation templates."
  clean_templates
  build_minimal_template
  build_all_templates if full?
end

#clean_templatesObject



97
98
99
# File 'lib/jets/commands/build.rb', line 97

def clean_templates
  FileUtils.rm_rf("#{Jets.build_root}/templates")
end

#full?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/jets/commands/build.rb', line 36

def full?
  @options[:templates] || @options[:stack_type] == :full
end

#runObject



11
12
13
14
15
16
17
18
# File 'lib/jets/commands/build.rb', line 11

def run
  puts "Building project for Lambda..."
  return if @options[:noop]
  # run gets called from the CLI and does not have all the stack_options yet.
  # We compute it and change the options early here.
  @options.merge!(stack_type: stack_type, s3_bucket: s3_bucket)
  build
end

#shared_filesObject



124
125
126
# File 'lib/jets/commands/build.rb', line 124

def shared_files
  self.class.shared_files
end