cpflow 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,48 +15,14 @@ module Command
15
15
  - Maintenance mode is only supported for domains that use path based routing mode and have a route configured for the prefix '/' on either port 80 or 443
16
16
  DESC
17
17
 
18
- def call # rubocop:disable Metrics/MethodLength
19
- one_off_workload = config[:one_off_workload]
20
- maintenance_workload = config.current[:maintenance_workload] || "maintenance"
21
-
22
- domain_data = if config.domain
23
- cp.fetch_domain(config.domain)
24
- else
25
- cp.find_domain_for([one_off_workload, maintenance_workload])
26
- end
27
- unless domain_data
28
- raise "Can't find domain. " \
29
- "Maintenance mode is only supported for domains that use path based routing mode " \
30
- "and have a route configured for the prefix '/' on either port 80 or 443."
31
- end
32
-
33
- domain = domain_data["name"]
34
- if cp.domain_workload_matches?(domain_data, one_off_workload)
35
- progress.puts("Maintenance mode is already disabled for app '#{config.app}'.")
36
- return
37
- end
38
-
39
- cp.fetch_workload!(maintenance_workload)
40
-
41
- # Start all other workloads
42
- Cpflow::Cli.start(["ps:start", "-a", config.app, "--wait"])
43
-
44
- progress.puts
45
-
46
- # Switch domain workload
47
- step("Switching workload for domain '#{domain}' to '#{one_off_workload}'") do
48
- cp.set_domain_workload(domain_data, one_off_workload)
49
-
50
- # Give it a bit of time for the domain to update
51
- Kernel.sleep(30)
52
- end
53
-
54
- progress.puts
18
+ def call
19
+ maintenance_mode.disable!
20
+ end
55
21
 
56
- # Stop maintenance workload
57
- Cpflow::Cli.start(["ps:stop", "-a", config.app, "-w", maintenance_workload, "--wait"])
22
+ private
58
23
 
59
- progress.puts("\nMaintenance mode disabled for app '#{config.app}'.")
24
+ def maintenance_mode
25
+ @maintenance_mode ||= MaintenanceMode.new(self)
60
26
  end
61
27
  end
62
28
  end
@@ -15,48 +15,14 @@ module Command
15
15
  - Maintenance mode is only supported for domains that use path based routing mode and have a route configured for the prefix '/' on either port 80 or 443
16
16
  DESC
17
17
 
18
- def call # rubocop:disable Metrics/MethodLength
19
- one_off_workload = config[:one_off_workload]
20
- maintenance_workload = config.current[:maintenance_workload] || "maintenance"
21
-
22
- domain_data = if config.domain
23
- cp.fetch_domain(config.domain)
24
- else
25
- cp.find_domain_for([one_off_workload, maintenance_workload])
26
- end
27
- unless domain_data
28
- raise "Can't find domain. " \
29
- "Maintenance mode is only supported for domains that use path based routing mode " \
30
- "and have a route configured for the prefix '/' on either port 80 or 443."
31
- end
32
-
33
- domain = domain_data["name"]
34
- if cp.domain_workload_matches?(domain_data, maintenance_workload)
35
- progress.puts("Maintenance mode is already enabled for app '#{config.app}'.")
36
- return
37
- end
38
-
39
- cp.fetch_workload!(maintenance_workload)
40
-
41
- # Start maintenance workload
42
- Cpflow::Cli.start(["ps:start", "-a", config.app, "-w", maintenance_workload, "--wait"])
43
-
44
- progress.puts
45
-
46
- # Switch domain workload
47
- step("Switching workload for domain '#{domain}' to '#{maintenance_workload}'") do
48
- cp.set_domain_workload(domain_data, maintenance_workload)
49
-
50
- # Give it a bit of time for the domain to update
51
- Kernel.sleep(30)
52
- end
53
-
54
- progress.puts
18
+ def call
19
+ maintenance_mode.enable!
20
+ end
55
21
 
56
- # Stop all other workloads
57
- Cpflow::Cli.start(["ps:stop", "-a", config.app, "--wait"])
22
+ private
58
23
 
59
- progress.puts("\nMaintenance mode enabled for app '#{config.app}'.")
24
+ def maintenance_mode
25
+ @maintenance_mode ||= MaintenanceMode.new(self)
60
26
  end
61
27
  end
62
28
  end
@@ -14,9 +14,9 @@ module Command
14
14
 
15
15
  def call
16
16
  if config.options[:version]
17
- Cpflow::Cli.start(["version"])
17
+ run_cpflow_command("version")
18
18
  else
19
- Cpflow::Cli.start(["help"])
19
+ run_cpflow_command("help")
20
20
  end
21
21
  end
22
22
  end
@@ -25,14 +25,14 @@ module Command
25
25
  private
26
26
 
27
27
  def copy_image_from_upstream
28
- Cpflow::Cli.start(["copy-image-from-upstream", "-a", config.app, "-t", config.options[:upstream_token]])
28
+ run_cpflow_command("copy-image-from-upstream", "-a", config.app, "-t", config.options[:upstream_token])
29
29
  progress.puts
30
30
  end
31
31
 
32
32
  def deploy_image
33
33
  args = []
34
34
  args.push("--run-release-phase") if config.current[:release_script]
35
- Cpflow::Cli.start(["deploy-image", "-a", config.app, *args])
35
+ run_cpflow_command("deploy-image", "-a", config.app, *args)
36
36
  end
37
37
  end
38
38
  end
data/lib/command/run.rb CHANGED
@@ -243,7 +243,7 @@ module Command
243
243
 
244
244
  step("Updating runner workload '#{runner_workload}'") do
245
245
  # Update runner workload
246
- @expected_deployed_version = cp.cron_workload_deployed_version(runner_workload) + 1
246
+ @expected_deployed_version = (cp.cron_workload_deployed_version(runner_workload) || 0) + 1
247
247
  cp.apply_hash("kind" => "workload", "name" => runner_workload, "spec" => spec)
248
248
  end
249
249
  end
@@ -256,7 +256,7 @@ module Command
256
256
 
257
257
  def wait_for_runner_workload_update
258
258
  step("Waiting for runner workload '#{runner_workload}' to be updated", retry_on_failure: true) do
259
- cp.cron_workload_deployed_version(runner_workload) >= expected_deployed_version
259
+ (cp.cron_workload_deployed_version(runner_workload) || 0) >= expected_deployed_version
260
260
  end
261
261
  end
262
262
 
@@ -306,7 +306,7 @@ module Command
306
306
  exit(ExitCode::SUCCESS)
307
307
  end
308
308
 
309
- Cpflow::Cli.start(["logs", *app_workload_replica_args])
309
+ run_cpflow_command("logs", *app_workload_replica_args)
310
310
  end
311
311
  Process.detach(logs_pid)
312
312
 
@@ -42,7 +42,7 @@ module Command
42
42
 
43
43
  args = []
44
44
  args.push("--add-app-identity") unless skip_secrets_setup
45
- Cpflow::Cli.start(["apply-template", *templates, "-a", config.app, *args])
45
+ run_cpflow_command("apply-template", *templates, "-a", config.app, *args)
46
46
 
47
47
  bind_identity_to_policy unless skip_secrets_setup
48
48
  run_post_creation_hook unless config.options[:skip_post_creation_hook]
data/lib/command/test.rb CHANGED
@@ -16,8 +16,8 @@ module Command
16
16
  def call
17
17
  # Modify this method to trigger the code you want to test.
18
18
  # You can use `debugger` to debug.
19
- # You can use `Cpflow::Cli.start` to simulate a command
20
- # (e.g., `Cpflow::Cli.start(["deploy-image", "-a", "my-app-name"])`).
19
+ # You can use `run_cpflow_command` to simulate a command
20
+ # (e.g., `run_cpflow_command("deploy-image", "-a", "my-app-name")`).
21
21
  end
22
22
  end
23
23
  end
@@ -90,7 +90,7 @@ class Controlplane # rubocop:disable Metrics/ClassLength
90
90
  api.query_images(org: a_org, gvc: a_gvc, gvc_op_type: gvc_op)
91
91
  end
92
92
 
93
- def image_build(image, dockerfile:, docker_args: [], build_args: [], push: true)
93
+ def image_build(image, dockerfile:, docker_args: [], build_args: [])
94
94
  # https://docs.controlplane.com/guides/push-image#step-2
95
95
  # Might need to use `docker buildx build` if compatiblitity issues arise
96
96
  cmd = "docker build --platform=linux/amd64 -t #{image} -f #{dockerfile}"
@@ -99,9 +99,8 @@ class Controlplane # rubocop:disable Metrics/ClassLength
99
99
  cmd += " #{docker_args.join(' ')}" if docker_args.any?
100
100
  build_args.each { |build_arg| cmd += " --build-arg #{build_arg}" }
101
101
  cmd += " #{config.app_dir}"
102
- perform!(cmd)
103
102
 
104
- image_push(image) if push
103
+ perform!(cmd)
105
104
  end
106
105
 
107
106
  def fetch_image_details(image)
@@ -278,7 +277,7 @@ class Controlplane # rubocop:disable Metrics/ClassLength
278
277
  end
279
278
 
280
279
  def workload_exec(workload, replica, location:, container: nil, command: nil)
281
- cmd = "cpln workload exec #{workload} #{gvc_org} --replica #{replica} --location #{location}"
280
+ cmd = "cpln workload exec #{workload} #{gvc_org} --replica #{replica} --location #{location} -it"
282
281
  cmd += " --container #{container}" if container
283
282
  cmd += " -- #{command}"
284
283
  perform!(cmd, output_mode: :all)
@@ -3,10 +3,12 @@
3
3
  class ValidationError < StandardError; end
4
4
 
5
5
  class DoctorService
6
- attr_reader :config
6
+ extend Forwardable
7
7
 
8
- def initialize(config)
9
- @config = config
8
+ def_delegators :@command, :config, :progress
9
+
10
+ def initialize(command)
11
+ @command = command
10
12
  end
11
13
 
12
14
  def run_validations(validations, silent_if_passing: false) # rubocop:disable Metrics/MethodLength
@@ -37,7 +39,7 @@ class DoctorService
37
39
  end
38
40
 
39
41
  def validate_templates
40
- @template_parser = TemplateParser.new(config)
42
+ @template_parser = TemplateParser.new(@command)
41
43
  filenames = Dir.glob("#{@template_parser.template_dir}/*.yml")
42
44
  templates = @template_parser.parse(filenames)
43
45
 
@@ -97,8 +99,4 @@ class DoctorService
97
99
  .join("\n")
98
100
  progress.puts("\n#{Shell.color("DEPRECATED: #{message}", :yellow)}\n#{list}\n\n")
99
101
  end
100
-
101
- def progress
102
- $stderr
103
- end
104
102
  end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MaintenanceMode
4
+ extend Forwardable
5
+
6
+ def_delegators :@command, :config, :progress, :cp, :step, :run_cpflow_command
7
+
8
+ def initialize(command)
9
+ @command = command
10
+ end
11
+
12
+ def enabled?
13
+ validate_domain_exists!
14
+ cp.domain_workload_matches?(domain_data, maintenance_workload)
15
+ end
16
+
17
+ def disabled?
18
+ validate_domain_exists!
19
+ cp.domain_workload_matches?(domain_data, one_off_workload)
20
+ end
21
+
22
+ def enable!
23
+ if enabled?
24
+ progress.puts("Maintenance mode is already enabled for app '#{config.app}'.")
25
+ else
26
+ enable_maintenance_mode
27
+ end
28
+ end
29
+
30
+ def disable!
31
+ if disabled?
32
+ progress.puts("Maintenance mode is already disabled for app '#{config.app}'.")
33
+ else
34
+ disable_maintenance_mode
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def enable_maintenance_mode
41
+ validate_maintenance_workload_exists!
42
+
43
+ start_or_stop_maintenance_workload(:start)
44
+ switch_domain_workload(to: maintenance_workload)
45
+ start_or_stop_all_workloads(:stop)
46
+
47
+ progress.puts("\nMaintenance mode enabled for app '#{config.app}'.")
48
+ end
49
+
50
+ def disable_maintenance_mode
51
+ validate_maintenance_workload_exists!
52
+
53
+ start_or_stop_maintenance_workload(:start)
54
+ switch_domain_workload(to: one_off_workload)
55
+ start_or_stop_all_workloads(:stop)
56
+
57
+ progress.puts("\nMaintenance mode disabled for app '#{config.app}'.")
58
+ end
59
+
60
+ def validate_domain_exists!
61
+ return if domain_data
62
+
63
+ raise "Can't find domain. " \
64
+ "Maintenance mode is only supported for domains that use path based routing mode " \
65
+ "and have a route configured for the prefix '/' on either port 80 or 443."
66
+ end
67
+
68
+ def validate_maintenance_workload_exists!
69
+ cp.fetch_workload!(maintenance_workload)
70
+ end
71
+
72
+ def start_or_stop_all_workloads(action)
73
+ run_cpflow_command("ps:#{action}", "-a", config.app, "--wait")
74
+
75
+ progress.puts
76
+ end
77
+
78
+ def start_or_stop_maintenance_workload(action)
79
+ run_cpflow_command("ps:#{action}", "-a", config.app, "-w", maintenance_workload, "--wait")
80
+
81
+ progress.puts
82
+ end
83
+
84
+ def switch_domain_workload(to:)
85
+ step("Switching workload for domain '#{domain_data['name']}' to '#{to}'") do
86
+ cp.set_domain_workload(domain_data, to)
87
+
88
+ # Give it a bit of time for the domain to update
89
+ Kernel.sleep(30)
90
+ end
91
+
92
+ progress.puts
93
+ end
94
+
95
+ def domain_data
96
+ @domain_data ||=
97
+ if config.domain
98
+ cp.fetch_domain(config.domain)
99
+ else
100
+ cp.find_domain_for([one_off_workload, maintenance_workload])
101
+ end
102
+ end
103
+
104
+ def one_off_workload
105
+ @one_off_workload ||= config[:one_off_workload]
106
+ end
107
+
108
+ def maintenance_workload
109
+ @maintenance_workload ||= config.current[:maintenance_workload] || "maintenance"
110
+ end
111
+ end
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class TemplateParser
4
- attr_reader :config, :deprecated_variables
4
+ extend Forwardable
5
5
 
6
- def initialize(config)
7
- @config = config
6
+ def_delegators :@command, :config, :cp
7
+
8
+ attr_reader :deprecated_variables
9
+
10
+ def initialize(command)
11
+ @command = command
8
12
  end
9
13
 
10
14
  def template_dir
@@ -69,8 +73,4 @@ class TemplateParser
69
73
  "APP_IMAGE" => "{{APP_IMAGE}}"
70
74
  }
71
75
  end
72
-
73
- def cp
74
- @cp ||= Controlplane.new(config)
75
- end
76
76
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cpflow
4
- VERSION = "3.0.0"
5
- MIN_CPLN_VERSION = "2.0.1"
4
+ VERSION = "4.0.0"
5
+ MIN_CPLN_VERSION = "3.1.0"
6
6
  end
data/lib/cpflow.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "date"
4
+ require "forwardable"
4
5
  require "dotenv/load"
5
6
  require "cgi"
6
7
  require "json"
@@ -30,25 +31,7 @@ at_exit do
30
31
  end
31
32
  end
32
33
 
33
- # Fix for https://github.com/erikhuda/thor/issues/398
34
- # Copied from https://github.com/rails/thor/issues/398#issuecomment-622988390
35
- class Thor
36
- module Shell
37
- class Basic
38
- def print_wrapped(message, options = {})
39
- indent = (options[:indent] || 0).to_i
40
- if indent.zero?
41
- stdout.puts(message)
42
- else
43
- message.each_line do |message_line|
44
- stdout.print(" " * indent)
45
- stdout.puts(message_line.chomp)
46
- end
47
- end
48
- end
49
- end
50
- end
51
- end
34
+ require_relative "patches/thor"
52
35
 
53
36
  module Cpflow
54
37
  class Error < StandardError; end
@@ -64,7 +47,7 @@ module Cpflow
64
47
  check_cpflow_version
65
48
  fix_help_option
66
49
 
67
- super(*args)
50
+ super
68
51
  end
69
52
 
70
53
  def self.check_cpln_version # rubocop:disable Metrics/MethodLength
@@ -127,7 +110,7 @@ module Cpflow
127
110
  def self.is_thor_reserved_word?(word, type) # rubocop:disable Naming/PredicateName
128
111
  return false if word == "run"
129
112
 
130
- super(word, type)
113
+ super
131
114
  end
132
115
 
133
116
  def self.deprecated_commands
@@ -226,12 +209,14 @@ module Cpflow
226
209
 
227
210
  Cpflow::Cli.show_info_header(config) if with_info_header
228
211
 
212
+ command = command_class.new(config)
213
+
229
214
  if validations.any? && ENV.fetch("DISABLE_VALIDATIONS", nil) != "true"
230
- doctor = DoctorService.new(config)
215
+ doctor = DoctorService.new(command)
231
216
  doctor.run_validations(validations, silent_if_passing: true)
232
217
  end
233
218
 
234
- command_class.new(config).call
219
+ command.call
235
220
  rescue RuntimeError => e
236
221
  ::Shell.abort(e.message)
237
222
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Thor
4
+ # Fix for https://github.com/erikhuda/thor/issues/398
5
+ # Copied from https://github.com/rails/thor/issues/398#issuecomment-622988390
6
+ module Shell
7
+ class Basic
8
+ def print_wrapped(message, options = {})
9
+ indent = (options[:indent] || 0).to_i
10
+ if indent.zero?
11
+ stdout.puts(message)
12
+ else
13
+ message.each_line do |message_line|
14
+ stdout.print(" " * indent)
15
+ stdout.puts(message_line.chomp)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ # Fix for https://github.com/rails/thor/issues/742
23
+ def self.basename
24
+ @package_name || super
25
+ end
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
@@ -9,22 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-06-21 00:00:00.000000000 Z
12
+ date: 2024-08-22 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: debug
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: 1.7.1
21
- type: :runtime
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - "~>"
26
- - !ruby/object:Gem::Version
27
- version: 1.7.1
28
14
  - !ruby/object:Gem::Dependency
29
15
  name: dotenv
30
16
  requirement: !ruby/object:Gem::Requirement
@@ -81,132 +67,6 @@ dependencies:
81
67
  - - "~>"
82
68
  - !ruby/object:Gem::Version
83
69
  version: 1.2.1
84
- - !ruby/object:Gem::Dependency
85
- name: overcommit
86
- requirement: !ruby/object:Gem::Requirement
87
- requirements:
88
- - - "~>"
89
- - !ruby/object:Gem::Version
90
- version: 0.60.0
91
- type: :development
92
- prerelease: false
93
- version_requirements: !ruby/object:Gem::Requirement
94
- requirements:
95
- - - "~>"
96
- - !ruby/object:Gem::Version
97
- version: 0.60.0
98
- - !ruby/object:Gem::Dependency
99
- name: rspec
100
- requirement: !ruby/object:Gem::Requirement
101
- requirements:
102
- - - "~>"
103
- - !ruby/object:Gem::Version
104
- version: 3.12.0
105
- type: :development
106
- prerelease: false
107
- version_requirements: !ruby/object:Gem::Requirement
108
- requirements:
109
- - - "~>"
110
- - !ruby/object:Gem::Version
111
- version: 3.12.0
112
- - !ruby/object:Gem::Dependency
113
- name: rspec-retry
114
- requirement: !ruby/object:Gem::Requirement
115
- requirements:
116
- - - "~>"
117
- - !ruby/object:Gem::Version
118
- version: 0.6.2
119
- type: :development
120
- prerelease: false
121
- version_requirements: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - "~>"
124
- - !ruby/object:Gem::Version
125
- version: 0.6.2
126
- - !ruby/object:Gem::Dependency
127
- name: rubocop
128
- requirement: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - "~>"
131
- - !ruby/object:Gem::Version
132
- version: 1.45.0
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - "~>"
138
- - !ruby/object:Gem::Version
139
- version: 1.45.0
140
- - !ruby/object:Gem::Dependency
141
- name: rubocop-rake
142
- requirement: !ruby/object:Gem::Requirement
143
- requirements:
144
- - - "~>"
145
- - !ruby/object:Gem::Version
146
- version: 0.6.0
147
- type: :development
148
- prerelease: false
149
- version_requirements: !ruby/object:Gem::Requirement
150
- requirements:
151
- - - "~>"
152
- - !ruby/object:Gem::Version
153
- version: 0.6.0
154
- - !ruby/object:Gem::Dependency
155
- name: rubocop-rspec
156
- requirement: !ruby/object:Gem::Requirement
157
- requirements:
158
- - - "~>"
159
- - !ruby/object:Gem::Version
160
- version: 2.18.1
161
- type: :development
162
- prerelease: false
163
- version_requirements: !ruby/object:Gem::Requirement
164
- requirements:
165
- - - "~>"
166
- - !ruby/object:Gem::Version
167
- version: 2.18.1
168
- - !ruby/object:Gem::Dependency
169
- name: simplecov
170
- requirement: !ruby/object:Gem::Requirement
171
- requirements:
172
- - - "~>"
173
- - !ruby/object:Gem::Version
174
- version: 0.22.0
175
- type: :development
176
- prerelease: false
177
- version_requirements: !ruby/object:Gem::Requirement
178
- requirements:
179
- - - "~>"
180
- - !ruby/object:Gem::Version
181
- version: 0.22.0
182
- - !ruby/object:Gem::Dependency
183
- name: timecop
184
- requirement: !ruby/object:Gem::Requirement
185
- requirements:
186
- - - "~>"
187
- - !ruby/object:Gem::Version
188
- version: 0.9.6
189
- type: :development
190
- prerelease: false
191
- version_requirements: !ruby/object:Gem::Requirement
192
- requirements:
193
- - - "~>"
194
- - !ruby/object:Gem::Version
195
- version: 0.9.6
196
- - !ruby/object:Gem::Dependency
197
- name: webmock
198
- requirement: !ruby/object:Gem::Requirement
199
- requirements:
200
- - - "~>"
201
- - !ruby/object:Gem::Version
202
- version: 3.18.1
203
- type: :development
204
- prerelease: false
205
- version_requirements: !ruby/object:Gem::Requirement
206
- requirements:
207
- - - "~>"
208
- - !ruby/object:Gem::Version
209
- version: 3.18.1
210
70
  description: CLI for providing Heroku-like platform-as-a-service on Control Plane
211
71
  email:
212
72
  - justin@shakacode.com
@@ -219,6 +79,7 @@ files:
219
79
  - ".github/workflows/check_cpln_links.yml"
220
80
  - ".github/workflows/command_docs.yml"
221
81
  - ".github/workflows/rspec-shared.yml"
82
+ - ".github/workflows/rspec-specific.yml"
222
83
  - ".github/workflows/rspec.yml"
223
84
  - ".github/workflows/rubocop.yml"
224
85
  - ".gitignore"
@@ -288,6 +149,7 @@ files:
288
149
  - lib/core/controlplane_api_direct.rb
289
150
  - lib/core/doctor_service.rb
290
151
  - lib/core/helpers.rb
152
+ - lib/core/maintenance_mode.rb
291
153
  - lib/core/shell.rb
292
154
  - lib/core/template_parser.rb
293
155
  - lib/cpflow.rb
@@ -299,6 +161,7 @@ files:
299
161
  - lib/generator_templates/templates/app.yml
300
162
  - lib/generator_templates/templates/postgres.yml
301
163
  - lib/generator_templates/templates/rails.yml
164
+ - lib/patches/thor.rb
302
165
  - rakelib/create_release.rake
303
166
  - script/add_command
304
167
  - script/check_command_docs