Skip to content

Commit f8f47fc

Browse files
Merge pull request #1258 from Shopify/evan/obey-bare-shipit-file
Configurable respect bare shipit file behavior
2 parents c4b2f02 + d742b24 commit f8f47fc

File tree

5 files changed

+102
-28
lines changed

5 files changed

+102
-28
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,19 @@ Lastly, if you override the `app_name` configuration in your Shipit deployment,
134134

135135
* * *
136136

137+
<h3 id="respecting-bare-files">Respecting bare <code>shipit.yml</code> files</h3>
138+
139+
Shipit will, by default, respect the "bare" <code>shipit.yml</code> file as a fallback option if no more specifically-named file exists (such as <code>shipit.staging.yml</code>).
140+
141+
You can configure this behavior via the attribute <code>Shipit.respect_bare_shipit_file</code>.
142+
143+
- The value <code>false</code> will disable this behavior and instead cause Shipit to emit an error upon deploy if Shipit cannot find a more specifically-named file.
144+
- Setting this attribute to any other value (**including <code>nil</code>**), or not setting this attribute, will cause Shipit to use the default behavior of respecting bare <code>shipit.yml</code> files.
145+
146+
You can determine if Shipit is configured to respect bare files using <code>Shipit.respect_bare_shipit_file?</code>.
147+
148+
* * *
149+
137150
<h3 id="installing-dependencies">Installing dependencies</h3>
138151

139152
The **<code>dependencies</code>** step allows you to install all the packages your deploy script needs.

app/models/shipit/deploy_spec/file_system.rb

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,31 @@ def config(*)
9191
end
9292

9393
def load_config
94-
read_config(file("#{app_name}.#{@env}.yml", root: true)) ||
95-
read_config(file("#{app_name}.yml", root: true)) ||
96-
read_config(file("shipit.#{@env}.yml", root: true)) ||
97-
read_config(file('shipit.yml', root: true))
94+
return if config_file_path.nil?
95+
loaded_config = read_config(config_file_path)
96+
return if loaded_config&.empty?
97+
98+
if !Shipit.respect_bare_shipit_file? && config_file_path.to_s.end_with?(*bare_shipit_filenames)
99+
loaded_config["deploy"]["pre"] = [shipit_not_obeying_bare_file_echo_command, "exit 1"]
100+
end
101+
loaded_config
102+
end
103+
104+
def shipit_file_names_in_priority_order
105+
["#{app_name}.#{@env}.yml", "#{app_name}.yml", "shipit.#{@env}.yml", "shipit.yml"].uniq
106+
end
107+
108+
def bare_shipit_filenames
109+
["#{app_name}.yml", "shipit.yml"].uniq
110+
end
111+
112+
def config_file_path
113+
shipit_file_names_in_priority_order.each do |filename|
114+
path = file(filename, root: true)
115+
return path if path.exist?
116+
end
117+
118+
nil
98119
end
99120

100121
def app_name
@@ -104,6 +125,14 @@ def app_name
104125
def read_config(path)
105126
SafeYAML.load(path.read) if path.exist?
106127
end
128+
129+
def shipit_not_obeying_bare_file_echo_command
130+
<<~EOM
131+
echo \"\e[1;31mShipit is configured to ignore the bare '#{app_name}.yml' file.
132+
Please rename this file to more specifically include the environment name.
133+
Deployments will fail until a valid '#{app_name}.#{@env}.yml' file is found.\e[0m\"
134+
EOM
135+
end
107136
end
108137
end
109138
end

lib/shipit.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ module Shipit
6363

6464
delegate :table_name_prefix, to: :secrets
6565

66-
attr_accessor :disable_api_authentication, :timeout_exit_codes, :deployment_checks
66+
attr_accessor :disable_api_authentication, :timeout_exit_codes, :deployment_checks, :respect_bare_shipit_file
6767
attr_writer(
6868
:internal_hook_receivers,
6969
:preferred_org_emails,
@@ -76,6 +76,9 @@ def task_execution_strategy
7676
end
7777

7878
self.timeout_exit_codes = [].freeze
79+
self.respect_bare_shipit_file = true
80+
81+
alias_method :respect_bare_shipit_file?, :respect_bare_shipit_file
7982

8083
def authentication_disabled?
8184
ENV['SHIPIT_DISABLE_AUTH'].present?

test/models/deploy_spec_test.rb

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -286,29 +286,6 @@ class DeploySpecTest < ActiveSupport::TestCase
286286
assert_equal({ 'GLOBAL' => '1' }, @spec.machine_env)
287287
end
288288

289-
test '#load_config can grab the env-specific shipit.yml file' do
290-
config = {}
291-
config.expects(:exist?).returns(true)
292-
config.expects(:read).returns({ 'dependencies' => { 'override' => %w(foo bar baz) } }.to_yaml)
293-
spec = DeploySpec::FileSystem.new('.', 'staging')
294-
spec.expects(:file).with('shipit.staging.yml', root: true).returns(config)
295-
assert_equal %w(foo bar baz), spec.dependencies_steps
296-
end
297-
298-
test '#load_config grabs the global shipit.yml file if there is no env-specific file' do
299-
not_config = {}
300-
not_config.expects(:exist?).returns(false)
301-
302-
config = {}
303-
config.expects(:exist?).returns(true)
304-
config.expects(:read).returns({ 'dependencies' => { 'override' => %w(foo bar baz) } }.to_yaml)
305-
306-
spec = DeploySpec::FileSystem.new('.', 'staging')
307-
spec.expects(:file).with('shipit.staging.yml', root: true).returns(not_config)
308-
spec.expects(:file).with('shipit.yml', root: true).returns(config)
309-
assert_equal %w(foo bar baz), spec.dependencies_steps
310-
end
311-
312289
test '#gemspec gives the path of the repo gemspec if present' do
313290
spec = DeploySpec::FileSystem.new('foobar/', 'production')
314291
Dir.expects(:[]).with('foobar/*.gemspec').returns(['foobar/foobar.gemspec'])
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# frozen_string_literal: true
2+
require 'test_helper'
3+
require 'tmpdir'
4+
5+
module Shipit
6+
class DeploySpec
7+
class FileSystemTest < ActiveSupport::TestCase
8+
test 'deploy.pre calls "exit 1" if there is a bare shipit file and Shipit is configured to ignore' do
9+
Shipit.expects(:respect_bare_shipit_file?).returns(false).at_least_once
10+
deploy_spec = Shipit::DeploySpec::FileSystem.new(Dir.tmpdir, 'env')
11+
deploy_spec.expects(:config_file_path).returns(Pathname.new(Dir.tmpdir) + '/shipit.yml').at_least_once
12+
deploy_spec.expects(:read_config).returns(SafeYAML.load(deploy_spec_yaml))
13+
pre_commands = deploy_spec.send(:config, 'deploy', 'pre')
14+
assert pre_commands.include?('exit 1')
15+
assert pre_commands.first.include?('configured to ignore')
16+
refute pre_commands.include?('test 2')
17+
end
18+
19+
test 'deploy.pre does not call "exit 1" if Shipit is not configured to do so' do
20+
Shipit.expects(:respect_bare_shipit_file?).returns(true).at_least_once
21+
deploy_spec = Shipit::DeploySpec::FileSystem.new(Dir.tmpdir, 'env')
22+
deploy_spec.expects(:config_file_path).returns(Pathname.new(Dir.tmpdir) + '/shipit.yml').at_least_once
23+
deploy_spec.expects(:read_config).returns(SafeYAML.load(deploy_spec_yaml))
24+
pre_commands = deploy_spec.send(:config, 'deploy', 'pre')
25+
refute pre_commands.include?('exit 1')
26+
assert pre_commands.include?('test 2')
27+
end
28+
29+
test 'Shipit.respect_bare_shipit_file? has no effect if the file is not a bare file' do
30+
[true, false].each do |obey_val|
31+
Shipit.expects(:respect_bare_shipit_file?).returns(obey_val).at_least_once
32+
deploy_spec = Shipit::DeploySpec::FileSystem.new(Dir.tmpdir, 'env')
33+
deploy_spec.expects(:config_file_path).returns(Pathname.new(Dir.tmpdir) + '/shipit.env.yml').at_least_once
34+
deploy_spec.expects(:read_config).returns(SafeYAML.load(deploy_spec_yaml))
35+
pre_commands = deploy_spec.send(:config, 'deploy', 'pre')
36+
refute pre_commands.include?('exit 1')
37+
assert pre_commands.include?('test 2')
38+
end
39+
end
40+
41+
def deploy_spec_yaml
42+
<<~EOYAML
43+
deploy:
44+
pre:
45+
- test 2
46+
override:
47+
- test 1
48+
EOYAML
49+
end
50+
end
51+
end
52+
end

0 commit comments

Comments
 (0)