Class: Jets::Commands::Deploy

Inherits:
Object
  • Object
show all
Extended by:
Memoist
Includes:
StackInfo
Defined in:
lib/jets/commands/deploy.rb

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, #sqs, #sts

Methods included from AwsServices::StackStatus

#lookup, #stack_exists?, #stack_in_progress?

Constructor Details

#initialize(options) ⇒ Deploy

Returns a new instance of Deploy.



5
6
7
# File 'lib/jets/commands/deploy.rb', line 5

def initialize(options)
  @options = options
end

Instance Method Details

#build_codeObject



48
49
50
# File 'lib/jets/commands/deploy.rb', line 48

def build_code
  Jets::Commands::Build.new(@options).build_code
end

#check_dev_modeObject



41
42
43
44
45
46
# File 'lib/jets/commands/deploy.rb', line 41

def check_dev_mode
  if File.exist?("#{Jets.root}/dev.mode")
    puts "The dev.mode file exists. Please removed it and run bundle update before you deploy.".color(:red)
    exit 1
  end
end

#check_route_connected_functionsObject

Checks that all routes are validate and have corresponding lambda functions



57
58
59
60
61
62
63
64
65
66
# File 'lib/jets/commands/deploy.rb', line 57

def check_route_connected_functions
  return if Jets::Router.all_routes_valid

  puts "Deploy fail: The jets application contain invalid routes.".color(:red)
  puts "Please double check the routes below map to valid controllers:"
  Jets::Router.invalid_routes.each do |route|
    puts "  /#{route.path} => #{route.controller_name}##{route.action_name}"
  end
  exit 1
end

#delete_minimal_stackObject



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

def delete_minimal_stack
  puts "Existing stack is in ROLLBACK_COMPLETE state from a previous failed minimal deploy. Deleting stack and continuing."
  cfn.delete_stack(stack_name: stack_name)
  status.wait
  status.reset
end

#exit_unless_updateable!Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/jets/commands/deploy.rb', line 113

def exit_unless_updateable!
  stack_name = Jets::Naming.parent_stack_name
  exists = stack_exists?(stack_name)
  return unless exists # continue because stack could be updating

  stack = cfn.describe_stacks(stack_name: stack_name).stacks.first
  status = stack["stack_status"]
  if status =~ /^ROLLBACK_/ ||
     status =~ /_IN_PROGRESS$/
    region = `aws configure get region`.strip rescue "us-east-1"
    url = "https://console.aws.amazon.com/cloudformation/home?region=#{region}#/stacks"
    puts "The parent stack of the #{Jets.config.project_name.color(:green)} project is not in an updateable state."
    puts "Stack name #{stack_name.color(:yellow)} status #{stack["stack_status"].color(:yellow)}"
    puts "Here's the CloudFormation url to check for more details #{url}"
    exit 1
  end
end

#find_stack(stack_name) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/jets/commands/deploy.rb', line 100

def find_stack(stack_name)
  resp = cfn.describe_stacks(stack_name: stack_name)
  resp.stacks.first
rescue Aws::CloudFormation::Errors::ValidationError => e
  # example: Stack with id demo-dev does not exist
  if e.message =~ /Stack with/ && e.message =~ /does not exist/
    nil
  else
    raise
  end
end

#minimal_rollback_complete?Boolean

Checks for a few things before deciding to delete the parent stack

* Parent stack status status is ROLLBACK_COMPLETE
* Parent resources are in the DELETE_COMPLETE state

Returns:

  • (Boolean)


88
89
90
91
92
93
94
95
96
97
98
# File 'lib/jets/commands/deploy.rb', line 88

def minimal_rollback_complete?
  stack = find_stack(stack_name)
  return false unless stack

  return false unless stack.stack_status == 'ROLLBACK_COMPLETE'

  # Finally check if all the minimal resources in the parent template have been deleted
  resp = cfn.describe_stack_resources(stack_name: stack_name)
  resource_statuses = resp.stack_resources.map(&:resource_status).uniq
  resource_statuses == ['DELETE_COMPLETE']
end

#runObject



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/jets/commands/deploy.rb', line 9

def run
  deployment_env = Jets.config.project_namespace.color(:green)
  puts "Deploying to Lambda #{deployment_env} environment..."
  return if @options[:noop]

  check_dev_mode
  validate_routes!

  # deploy full nested stack when stack already exists
  # Delete existing rollback stack from previous bad minimal deploy
  delete_minimal_stack if minimal_rollback_complete?
  exit_unless_updateable! # Stack could be in a weird rollback state or in progress state

  if first_run?
    ship(stack_type: :minimal)
    Jets.application.reload_configs!
  end

  # Build code after the minimal stack because need s3 bucket for assets
  # on_aws? and s3_base_url logic
  build_code

  ship(stack_type: :full, s3_bucket: s3_bucket)
end

#ship(stack_options) ⇒ Object



68
69
70
71
72
# File 'lib/jets/commands/deploy.rb', line 68

def ship(stack_options)
  options = @options.merge(stack_options) # includes stack_type and s3_bucket
  Jets::Commands::Build.new(options).build_templates
  Jets::Cfn::Ship.new(options).run
end

#stack_nameObject



79
80
81
# File 'lib/jets/commands/deploy.rb', line 79

def stack_name
  Jets::Naming.parent_stack_name
end

#statusObject



74
75
76
# File 'lib/jets/commands/deploy.rb', line 74

def status
  Jets::Cfn::Status.new(stack_name)
end

#validate_routes!Object



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

def validate_routes!
  check_route_connected_functions
end