Class: Jets::Commands::Build

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

Constant Summary

Constants included from Timing

Timing::RECORD_LOG_PATH

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

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

Methods included from AwsServices::StackStatus

#stack_exists?, #stack_in_progress?

Methods included from Timing

clear, #record_data, #record_log, report

Constructor Details

#initialize(options) ⇒ Build

Returns a new instance of Build.



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

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

Class Method Details

.app_file?(path) ⇒ Boolean

Returns:

  • (Boolean)


174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/jets/commands/build.rb', line 174

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.



112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/jets/commands/build.rb', line 112

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

.internal_app_filesObject

Add internal Jets controllers if they are being used



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

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

Returns:

  • (Boolean)


145
146
147
148
149
150
151
152
153
154
155
# File 'lib/jets/commands/build.rb', line 145

def self.poly_only?
  # Scans all the app code and look for any methods that are ruby.
  # If any method is written in ruby then we know the app is not a
  # solely polymorphic non-ruby app.
  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)
  end
  !has_ruby
end

.shared_filesObject



131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/jets/commands/build.rb', line 131

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

.tmp_code(full_build_path = false) ⇒ Object



195
196
197
# File 'lib/jets/commands/build.rb', line 195

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

Instance Method Details

#app_filesObject



104
105
106
# File 'lib/jets/commands/build.rb', line 104

def app_files
  self.class.app_files
end

#buildObject



22
23
24
25
# File 'lib/jets/commands/build.rb', line 22

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

#build_all_templatesObject



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/jets/commands/build.rb', line 45

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



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

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

#build_app_child_templatesObject



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

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



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/jets/commands/build.rb', line 80

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)
  builder.build
end

#build_codeObject



28
29
30
# File 'lib/jets/commands/build.rb', line 28

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

#build_minimal_templateObject



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

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

#build_parent_templateObject



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

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

#build_shared_resources_templatesObject



72
73
74
75
76
# File 'lib/jets/commands/build.rb', line 72

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

#build_templatesObject



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

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

#clean_templatesObject



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

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

#full?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/jets/commands/build.rb', line 41

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

#runObject



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

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



127
128
129
# File 'lib/jets/commands/build.rb', line 127

def shared_files
  self.class.shared_files
end