cpflow 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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