statistrano 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/changelog.md +161 -0
  3. data/doc/config/file-permissions.md +33 -0
  4. data/doc/config/log-files.md +32 -0
  5. data/doc/config/task-definitions.md +88 -0
  6. data/doc/getting-started.md +96 -0
  7. data/doc/strategies/base.md +38 -0
  8. data/doc/strategies/branches.md +82 -0
  9. data/doc/strategies/releases.md +110 -0
  10. data/doc/strategies.md +17 -0
  11. data/lib/statistrano/config/configurable.rb +53 -0
  12. data/lib/statistrano/config/rake_task_with_context_creation.rb +43 -0
  13. data/lib/statistrano/config.rb +52 -0
  14. data/lib/statistrano/deployment/log_file.rb +44 -0
  15. data/lib/statistrano/deployment/manifest.rb +88 -0
  16. data/lib/statistrano/deployment/rake_tasks.rb +74 -0
  17. data/lib/statistrano/deployment/registerable.rb +11 -0
  18. data/lib/statistrano/deployment/releaser/revisions.rb +163 -0
  19. data/lib/statistrano/deployment/releaser/single.rb +48 -0
  20. data/lib/statistrano/deployment/releaser.rb +2 -0
  21. data/lib/statistrano/deployment/strategy/base.rb +132 -0
  22. data/lib/statistrano/deployment/strategy/branches/index/template.html.erb +78 -0
  23. data/lib/statistrano/deployment/strategy/branches/index.rb +40 -0
  24. data/lib/statistrano/deployment/strategy/branches/release.rb +73 -0
  25. data/lib/statistrano/deployment/strategy/branches.rb +198 -0
  26. data/lib/statistrano/deployment/strategy/check_git.rb +43 -0
  27. data/lib/statistrano/deployment/strategy/invoke_tasks.rb +58 -0
  28. data/lib/statistrano/deployment/strategy/releases.rb +76 -0
  29. data/lib/statistrano/deployment/strategy.rb +37 -0
  30. data/lib/statistrano/deployment.rb +10 -0
  31. data/lib/statistrano/log/default_logger.rb +105 -0
  32. data/lib/statistrano/log.rb +33 -0
  33. data/lib/statistrano/remote/file.rb +79 -0
  34. data/lib/statistrano/remote.rb +111 -0
  35. data/lib/statistrano/shell.rb +17 -0
  36. data/lib/statistrano/util/file_permissions.rb +34 -0
  37. data/lib/statistrano/util.rb +27 -0
  38. data/lib/statistrano/version.rb +3 -0
  39. data/lib/statistrano.rb +55 -0
  40. data/readme.md +247 -0
  41. data/spec/integration_tests/base_integration_spec.rb +103 -0
  42. data/spec/integration_tests/branches_integration_spec.rb +189 -0
  43. data/spec/integration_tests/releases/deploy_integration_spec.rb +116 -0
  44. data/spec/integration_tests/releases/list_releases_integration_spec.rb +38 -0
  45. data/spec/integration_tests/releases/prune_releases_integration_spec.rb +86 -0
  46. data/spec/integration_tests/releases/rollback_release_integration_spec.rb +46 -0
  47. data/spec/lib/statistrano/config/configurable_spec.rb +88 -0
  48. data/spec/lib/statistrano/config/rake_task_with_context_creation_spec.rb +73 -0
  49. data/spec/lib/statistrano/config_spec.rb +34 -0
  50. data/spec/lib/statistrano/deployment/log_file_spec.rb +75 -0
  51. data/spec/lib/statistrano/deployment/manifest_spec.rb +171 -0
  52. data/spec/lib/statistrano/deployment/rake_tasks_spec.rb +107 -0
  53. data/spec/lib/statistrano/deployment/registerable_spec.rb +19 -0
  54. data/spec/lib/statistrano/deployment/releaser/revisions_spec.rb +486 -0
  55. data/spec/lib/statistrano/deployment/releaser/single_spec.rb +59 -0
  56. data/spec/lib/statistrano/deployment/strategy/base_spec.rb +158 -0
  57. data/spec/lib/statistrano/deployment/strategy/branches_spec.rb +19 -0
  58. data/spec/lib/statistrano/deployment/strategy/check_git_spec.rb +39 -0
  59. data/spec/lib/statistrano/deployment/strategy/invoke_tasks_spec.rb +66 -0
  60. data/spec/lib/statistrano/deployment/strategy/releases_spec.rb +257 -0
  61. data/spec/lib/statistrano/deployment/strategy_spec.rb +76 -0
  62. data/spec/lib/statistrano/deployment_spec.rb +4 -0
  63. data/spec/lib/statistrano/log/default_logger_spec.rb +172 -0
  64. data/spec/lib/statistrano/log_spec.rb +36 -0
  65. data/spec/lib/statistrano/remote/file_spec.rb +166 -0
  66. data/spec/lib/statistrano/remote_spec.rb +226 -0
  67. data/spec/lib/statistrano/util/file_permissions_spec.rb +25 -0
  68. data/spec/lib/statistrano/util_spec.rb +23 -0
  69. data/spec/lib/statistrano_spec.rb +52 -0
  70. data/spec/spec_helper.rb +86 -0
  71. data/spec/support/given.rb +39 -0
  72. metadata +223 -0
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Statistrano::Deployment::Strategy::Releases#prune_releases integration", :integration do
4
+
5
+ context "with multiple_targets target" do
6
+
7
+ before :each do
8
+ Given.fixture "releases-deployed"
9
+ @subject = define_deployment "releases", :releases do
10
+ build_task "remote:copy"
11
+ local_dir "build"
12
+ hostname "localhost"
13
+ remote_dir File.join( Dir.pwd, "deployment" )
14
+
15
+ release_count 1
16
+ remotes [
17
+ { remote_dir: File.join( Dir.pwd, "deployment", "target01" ) },
18
+ { remote_dir: File.join( Dir.pwd, "deployment", "target02" ) },
19
+ { remote_dir: File.join( Dir.pwd, "deployment", "target03" ) }
20
+ ]
21
+ end
22
+ end
23
+
24
+ after :each do
25
+ Given.cleanup!
26
+ end
27
+
28
+ it "removes older releases beyond release count" do
29
+ @subject.prune_releases
30
+ expect( multi_release_folder_contents )
31
+ .to match_array [ "target01/releases/1372040000",
32
+ "target02/releases/1372040000",
33
+ "target03/releases/1372040000" ]
34
+ end
35
+
36
+ it "removes stray/untracked releases" do
37
+ Given.file "deployment/target01/releases/foo_bar/index.html", ''
38
+ Given.file "deployment/target02/releases/foo_bar/index.html", ''
39
+ Given.file "deployment/target03/releases/foo_bar/index.html", ''
40
+ @subject.prune_releases
41
+ expect( multi_release_folder_contents )
42
+ .to match_array [ "target01/releases/1372040000",
43
+ "target02/releases/1372040000",
44
+ "target03/releases/1372040000" ]
45
+ end
46
+
47
+ it "won't remove the currently symlinked release" do
48
+ Given.symlink "deployment/target01/releases/1372030000", "deployment/target01/current"
49
+ Given.symlink "deployment/target02/releases/1372030000", "deployment/target02/current"
50
+ Given.symlink "deployment/target03/releases/1372030000", "deployment/target03/current"
51
+
52
+ @subject.prune_releases
53
+
54
+ expect( multi_release_folder_contents )
55
+ .to match_array [ "target01/releases/1372030000",
56
+ "target01/releases/1372040000",
57
+
58
+ "target02/releases/1372030000",
59
+ "target02/releases/1372040000",
60
+
61
+ "target03/releases/1372030000",
62
+ "target03/releases/1372040000" ]
63
+ end
64
+
65
+ it "won't remove the currently symlinked release even if untracked" do
66
+ Given.file "deployment/target01/releases/foo_bar/index.html", ''
67
+ Given.file "deployment/target02/releases/foo_bar/index.html", ''
68
+ Given.file "deployment/target03/releases/foo_bar/index.html", ''
69
+ Given.symlink "deployment/target01/releases/foo_bar", "deployment/target01/current"
70
+ Given.symlink "deployment/target02/releases/foo_bar", "deployment/target02/current"
71
+ Given.symlink "deployment/target03/releases/foo_bar", "deployment/target03/current"
72
+
73
+ @subject.prune_releases
74
+
75
+ expect( multi_release_folder_contents )
76
+ .to match_array [ "target01/releases/foo_bar",
77
+ "target01/releases/1372040000",
78
+
79
+ "target02/releases/foo_bar",
80
+ "target02/releases/1372040000",
81
+
82
+ "target03/releases/foo_bar",
83
+ "target03/releases/1372040000" ]
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Statistrano::Deployment::Strategy::Releases#rollback_release integration", :integration do
4
+
5
+ context "with multiple_targets target" do
6
+
7
+ before :each do
8
+ Given.fixture "releases-deployed"
9
+ @subject = define_deployment "releases", :releases do
10
+ build_task "remote:copy"
11
+ local_dir "build"
12
+ hostname "localhost"
13
+ remote_dir File.join( Dir.pwd, "deployment" )
14
+
15
+ release_count 2
16
+ remotes [
17
+ { remote_dir: File.join( Dir.pwd, "deployment", "target01" ) },
18
+ { remote_dir: File.join( Dir.pwd, "deployment", "target02" ) },
19
+ { remote_dir: File.join( Dir.pwd, "deployment", "target03" ) }
20
+ ]
21
+ end
22
+ end
23
+
24
+ after :each do
25
+ Given.cleanup!
26
+ end
27
+
28
+ it "reverts to the previous release" do
29
+ # just to verify that 137204000 is the current release
30
+ # on all targets
31
+ ["target01","target02","target03"].each do |target|
32
+ ls_before = HereOrThere::Local.new.run("ls -la deployment/#{target}")
33
+ expect( ls_before.stdout ).to match /current ->(.+)tmp\/deployment\/#{target}\/releases\/1372040000/
34
+ end
35
+
36
+ @subject.rollback_release
37
+
38
+ ["target01","target02","target03"].each do |target|
39
+ ls_after = HereOrThere::Local.new.run("ls -la deployment/#{target}")
40
+ expect( ls_after.stdout ).to match /current ->(.+)tmp\/deployment\/#{target}\/releases\/1372030000/
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Config::Configurable do
4
+
5
+ before :each do
6
+ class Subject
7
+ extend ::Statistrano::Config::Configurable
8
+
9
+ option :foo, "bar"
10
+ option :wu
11
+ option :proc, -> { "hello" }
12
+
13
+ options :one, :two
14
+ end
15
+ end
16
+
17
+ let(:subject) { Subject.new }
18
+
19
+ describe "#option" do
20
+
21
+ it "sets the given default value" do
22
+ expect( subject.config.foo ).to eq("bar")
23
+ end
24
+
25
+ it "defaults to setting nil" do
26
+ expect( subject.config.wu ).to be_nil
27
+ end
28
+
29
+ end
30
+
31
+
32
+ describe "#options" do
33
+ it "creates an accessor for each given option" do
34
+ names = [:one,:two]
35
+
36
+ names.each do |meth|
37
+ expect( subject.config.respond_to? meth ).to be_truthy
38
+ end
39
+ end
40
+
41
+ it "defaults those values to nil" do
42
+ names = [:one,:two]
43
+
44
+ names.each do |meth|
45
+ expect( subject.config.public_send meth ).to be_nil
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "option accessor" do
51
+ let(:config) { subject.config }
52
+
53
+ it "returns the value if given no arguments" do
54
+ expect( config.foo ).to eq("bar")
55
+ end
56
+
57
+ it "sets the value if given one argument" do
58
+ config.foo "baz"
59
+ expect( config.foo ).to eq("baz")
60
+ end
61
+
62
+ it "sets the value if given an #=" do
63
+ config.foo = "badazz"
64
+ expect( config.foo ).to eq("badazz")
65
+ end
66
+
67
+ it "sets the value to a block if given one" do
68
+ config.foo do
69
+ "badazz"
70
+ end
71
+ expect( config.foo.call ).to eq "badazz"
72
+ end
73
+
74
+ it "calls a block if `:call` is passed" do
75
+ config.foo :call do
76
+ "badazz"
77
+ end
78
+ expect( config.foo ).to eq "badazz"
79
+ end
80
+
81
+ it "raises and ArgumentError if given more than 1 argument" do
82
+ expect{ config.foo "bar", "baz" }.to raise_error ArgumentError
83
+ end
84
+
85
+ end
86
+
87
+
88
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Config::RakeTaskWithContextCreation do
4
+
5
+ before :each do
6
+ Subject = Class.new
7
+ Subject.send(:include, described_class)
8
+ end
9
+
10
+ describe "::included" do
11
+ it "creates user_task_namespaces method defaulting to []" do
12
+ expect( Subject.new.methods ).to include :user_task_namespaces
13
+ expect( Subject.new.user_task_namespaces ).to eq []
14
+ end
15
+
16
+ it "creates user_tasks method defaulting to []" do
17
+ expect( Subject.new.methods ).to include :user_tasks
18
+ expect( Subject.new.user_tasks ).to eq []
19
+ end
20
+ end
21
+
22
+ describe "#task" do
23
+ it "adds a task to the user_tasks store with name and namespaces" do
24
+ subject = Subject.new
25
+ block = lambda { }
26
+ subject.task 'hello', &block
27
+
28
+ expect( subject.user_tasks ).to include name: 'hello',
29
+ namespaces: [],
30
+ block: block
31
+ end
32
+
33
+ it "adds optional desc to task" do
34
+ subject = Subject.new
35
+ block = lambda { }
36
+ subject.task 'hello', 'I a method', &block
37
+
38
+ expect( subject.user_tasks ).to include name: 'hello',
39
+ desc: 'I a method',
40
+ namespaces: [],
41
+ block: block
42
+ end
43
+ end
44
+
45
+ describe "#namespace" do
46
+ it "evaluates given block appending the namespaces" do
47
+ subject = Subject.new
48
+ block = lambda { }
49
+
50
+ subject.namespace 'hello' do
51
+ task 'world', &block
52
+
53
+ namespace 'foo' do
54
+ task 'bar', &block
55
+ task 'bang', &block
56
+ end
57
+ end
58
+
59
+ expect( subject.user_tasks ).to include name: 'world',
60
+ namespaces: ['hello'],
61
+ block: block
62
+
63
+ expect( subject.user_tasks ).to include name: 'bar',
64
+ namespaces: ['hello', 'foo'],
65
+ block: block
66
+
67
+ expect( subject.user_tasks ).to include name: 'bang',
68
+ namespaces: ['hello', 'foo'],
69
+ block: block
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Config do
4
+
5
+ describe "#initialize" do
6
+ it "defaults options & tasks to a blank hash" do
7
+ subject = described_class.new
8
+
9
+ expect( subject.options ).to eq({})
10
+ expect( subject.tasks ).to eq({})
11
+ end
12
+
13
+ it "defines an accessor for each given option" do
14
+ subject = described_class.new foo: 'bar'
15
+ expect( subject.foo ).to eq 'bar'
16
+ end
17
+
18
+ it "uses given options & tasks, but clones so the originals don't get modified" do
19
+ options = { foo: 'bar' }
20
+ tasks = { foo: 'bar' }
21
+ subject = described_class.new options, tasks
22
+
23
+ subject.foo = 'baz'
24
+ subject.tasks[:foo] = 'baz'
25
+
26
+ expect( subject.foo ).to eq 'baz'
27
+ expect( options ).to eq foo: 'bar'
28
+
29
+ expect( subject.tasks ).to eq foo: 'baz'
30
+ expect( tasks ).to eq foo: 'bar'
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Deployment::LogFile do
4
+
5
+ before :each do
6
+ config = double("Statistrano::Config", remote_dir: '/remote_dir')
7
+ @remote = instance_double("Statistrano::Remote", config: config)
8
+ end
9
+
10
+ describe "#initialize" do
11
+
12
+ it "sets :remote to the given remote" do
13
+ subject = described_class.new 'foo/bar', @remote
14
+ expect( subject.remote ).to eq @remote
15
+ end
16
+ it "sets resolved_path to given path if absolute" do
17
+ subject = described_class.new '/var/log', @remote
18
+ expect( subject.resolved_path ).to eq '/var/log'
19
+ end
20
+ it "sets resolved_path relative to remote.config.remote_dir if relative" do
21
+ subject = described_class.new 'var/log', @remote
22
+ expect( subject.resolved_path ).to eq '/remote_dir/var/log'
23
+ end
24
+ it "sets file to Remote::File created with resolved_path and remote" do
25
+ expect( Statistrano::Remote::File ).to receive(:new)
26
+ .with( '/var/log', @remote )
27
+
28
+ described_class.new '/var/log', @remote
29
+ end
30
+ end
31
+
32
+ describe "#append!" do
33
+ it "calls #append_content! on Remote::File with entry converted to json" do
34
+ remote_file_double = instance_double("Statistrano::Remote::File")
35
+ allow( Statistrano::Remote::File ).to receive(:new)
36
+ .with( '/var/log', @remote )
37
+ .and_return(remote_file_double)
38
+ subject = described_class.new '/var/log', @remote
39
+
40
+ expect( remote_file_double ).to receive(:append_content!)
41
+ .with('{"log":"entry"}')
42
+
43
+ subject.append! log: 'entry'
44
+ end
45
+ end
46
+
47
+ describe "#last_entry" do
48
+
49
+ before :each do
50
+ @remote_file_double = instance_double("Statistrano::Remote::File")
51
+ allow( Statistrano::Remote::File ).to receive(:new)
52
+ .with( '/var/log', @remote )
53
+ .and_return(@remote_file_double)
54
+ @subject = described_class.new '/var/log', @remote
55
+ end
56
+
57
+ it "returns hash of last entry data" do
58
+ allow( @remote_file_double ).to receive(:content)
59
+ .and_return "{\"log\":1}\n{\"log\":2}"
60
+
61
+ expect( @subject.last_entry ).to eq log: 2
62
+ end
63
+
64
+ it "returns empty hash if no entries" do
65
+ allow( @remote_file_double ).to receive(:content)
66
+ .and_return ""
67
+
68
+ expect( @subject.last_entry ).to eq({})
69
+ end
70
+ end
71
+
72
+ describe "#tail" do
73
+ end
74
+
75
+ end
@@ -0,0 +1,171 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Deployment::Manifest do
4
+
5
+ describe "#initialize" do
6
+ it "stores the provided remote_dir & remote" do
7
+ subject = described_class.new( "remote_dir", "remote" )
8
+
9
+ expect( subject.remote_dir ).to eq "remote_dir"
10
+ expect( subject.remote ).to eq "remote"
11
+ end
12
+ end
13
+
14
+ describe "#data" do
15
+ it "returns serialized data from remote" do
16
+ remote = instance_double("Statistrano::Remote")
17
+ file = instance_double("Statistrano::Remote::File")
18
+ expect( Statistrano::Remote::File ).to receive(:new)
19
+ .and_return(file)
20
+ subject = described_class.new '/var/www/proj', remote
21
+ expect( file ).to receive(:content)
22
+ .and_return('[{"key":"val"}]')
23
+
24
+ expect( subject.data ).to match_array [{ key: 'val' }]
25
+ end
26
+
27
+ it "returns empty array if manifest file is missing" do
28
+ remote = instance_double("Statistrano::Remote")
29
+ file = instance_double("Statistrano::Remote::File")
30
+ expect( Statistrano::Remote::File ).to receive(:new)
31
+ .and_return(file)
32
+ expect( file ).to receive(:content)
33
+ .and_return('')
34
+ subject = described_class.new '/var/www/proj', remote
35
+
36
+ expect( subject.data ).to match_array []
37
+ end
38
+
39
+ it "logs error when manifest contains invalid JSON" do
40
+ config = double("Statistrano::Config", hostname: 'web01')
41
+ remote = instance_double("Statistrano::Remote", config: config )
42
+ file = instance_double("Statistrano::Remote::File")
43
+ expect( Statistrano::Remote::File ).to receive(:new)
44
+ .and_return(file)
45
+ subject = described_class.new '/var/www/proj', remote
46
+ expect( file ).to receive(:content)
47
+ .and_return('invalid')
48
+ expect( Statistrano::Log ).to receive(:error)
49
+ subject.data
50
+ end
51
+
52
+ it "returns @_data if set" do
53
+ remote = instance_double("Statistrano::Remote")
54
+ subject = described_class.new '/var/www/proj', remote
55
+
56
+ subject.instance_variable_set(:@_data, 'data')
57
+ expect( subject.data ).to eq 'data'
58
+ end
59
+
60
+ it "sets @_data with return" do
61
+ remote = instance_double("Statistrano::Remote")
62
+ subject = described_class.new '/var/www/proj', remote
63
+ allow( remote ).to receive(:run).and_return( HereOrThere::Response.new('[{"key":"val"}]','',true) )
64
+
65
+ data = subject.data
66
+ expect( subject.instance_variable_get(:@_data) ).to eq data
67
+ end
68
+ end
69
+
70
+ describe "#push" do
71
+ it "adds data to the data array" do
72
+ remote = instance_double("Statistrano::Remote")
73
+ allow( remote ).to receive(:run).and_return( HereOrThere::Response.new('[{"key":"val"}]','',true) )
74
+ subject = described_class.new '/var/www/proj', remote
75
+
76
+ new_data = {foo: 'bar'}
77
+ subject.push new_data
78
+ expect( subject.data ).to include new_data
79
+ end
80
+
81
+ it "symbolizes keys in passed data" do
82
+ remote = instance_double("Statistrano::Remote")
83
+ allow( remote ).to receive(:run).and_return( HereOrThere::Response.new('[{"key":"val"}]','',true) )
84
+ subject = described_class.new '/var/www/proj', remote
85
+
86
+ new_data = {"foo" => 'bar'}
87
+ subject.push new_data
88
+ expect( subject.data ).to include foo: 'bar'
89
+ end
90
+
91
+ it "raises error if provided data cannot be converted to JSON" do
92
+ remote = instance_double("Statistrano::Remote")
93
+ allow( remote ).to receive(:run).and_return( HereOrThere::Response.new('[{"key":"val"}]','',true) )
94
+ subject = described_class.new '/var/www/proj', remote
95
+
96
+ data = double
97
+ expect( data ).to receive(:respond_to?)
98
+ .with(:to_json).and_return(false)
99
+
100
+ expect{
101
+ subject.push data
102
+ }.to raise_error ArgumentError, "data must be serializable as JSON"
103
+ end
104
+ end
105
+
106
+ describe "#put" do
107
+ # a "safer" version of `push`, will update a
108
+ # data_glob in place matched on key
109
+ let(:remote) { instance_double("Statistrano::Remote") }
110
+
111
+ context "when item doesn't exist" do
112
+ it "adds the item w/o disturbing existing data" do
113
+ subject = described_class.new "remote_dir", remote
114
+ allow( remote ).to receive(:run)
115
+ .and_return( HereOrThere::Response.new('[{"key":"val"}]','',true) )
116
+
117
+ subject.put( { foo: "bar" }, :foo )
118
+ expect( subject.data ).to match_array [{key: "val"},{foo: "bar"}]
119
+ end
120
+ end
121
+
122
+ context "when item does exist" do
123
+ it "updates the item w/o distrubing existing data" do
124
+ subject = described_class.new "remote_dir", remote
125
+ allow( remote ).to receive(:run)
126
+ .and_return( HereOrThere::Response.new('[{"key":"val"},{"key":"foo","marker":"orig"}]','',true) )
127
+
128
+ subject.put( {key:"foo",marker:"new"}, :key )
129
+ expect( subject.data ).to match_array [{key: "val"},{key:"foo",marker:"new"}]
130
+ end
131
+ end
132
+ end
133
+
134
+ describe "#remove_if" do
135
+ it "removes data that matches the condition" do
136
+ remote = instance_double("Statistrano::Remote")
137
+ allow( remote ).to receive(:run).and_return( HereOrThere::Response.new('[{"key":"val"}]','',true) )
138
+ subject = described_class.new '/var/www/proj', remote
139
+
140
+ subject.remove_if { |item| item.has_key?(:key) }
141
+ expect( subject.data ).to match_array []
142
+ end
143
+ it "retains data that doesn't match condition" do
144
+ remote = instance_double("Statistrano::Remote")
145
+ allow( remote ).to receive(:run).and_return( HereOrThere::Response.new('[{"key":"val"}]','',true) )
146
+ subject = described_class.new '/var/www/proj', remote
147
+
148
+ subject.remove_if { |item| !item.has_key?(:key) }
149
+ expect( subject.data ).to match_array [{key:"val"}]
150
+ end
151
+ end
152
+
153
+ describe "#save!" do
154
+ it "calls update_content! for the remote_file" do
155
+ remote = instance_double("Statistrano::Remote")
156
+ file = instance_double("Statistrano::Remote::File")
157
+
158
+ expect( Statistrano::Remote::File ).to receive(:new)
159
+ .with("/path/manifest.json", remote)
160
+ .and_return(file)
161
+ expect( file ).to receive(:update_content!)
162
+ .with('[{"key":"val"}]')
163
+
164
+ subject = described_class.new "/path", remote
165
+ subject.instance_variable_set(:@_data, [{key: "val"}])
166
+
167
+ subject.save!
168
+ end
169
+ end
170
+
171
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Deployment::RakeTasks do
4
+
5
+ describe "::register" do
6
+
7
+ context "config tasks" do
8
+ before :each do
9
+ class RakeTasksSubject
10
+ extend Statistrano::Config::Configurable
11
+ include Statistrano::Deployment::Strategy::InvokeTasks
12
+
13
+ attr_reader :name
14
+
15
+ task :foo, :bar, "baz"
16
+
17
+ def initialize name
18
+ @name = name
19
+ end
20
+
21
+ def bar
22
+ "baz"
23
+ end
24
+ end
25
+ end
26
+
27
+ after :each do
28
+ Rake::Task.clear
29
+ end
30
+
31
+ it "registers tasks using deployment's name as namespace" do
32
+ described_class.register RakeTasksSubject.new "woo"
33
+ expect( Rake::Task.tasks.map(&:to_s) ).to include 'woo:foo'
34
+ end
35
+
36
+ it "calls the tasks matching method on the deployment" do
37
+ subject = RakeTasksSubject.new "woo"
38
+ described_class.register subject
39
+
40
+ expect( subject ).to receive(:bar)
41
+
42
+ Rake::Task['woo:foo'].invoke
43
+ end
44
+ end
45
+
46
+ context "user_tasks" do
47
+
48
+ after :each do
49
+ Rake::Task.clear
50
+ end
51
+
52
+ it "adds the task in the correct namespace" do
53
+ config = Statistrano::Config.new
54
+ deployment_double = instance_double("Statistrano::Deployment::Strategy::Base", name: 'name', config: config)
55
+ config.user_tasks.push name: 'start',
56
+ namespaces: ['puma'],
57
+ block: lambda { }
58
+
59
+ described_class.register deployment_double
60
+
61
+ expect( Rake::Task.tasks.map(&:to_s) ).to include 'name:puma:start'
62
+ end
63
+
64
+ it "registers the task at top level if no namespaces" do
65
+ config = Statistrano::Config.new
66
+ deployment_double = instance_double("Statistrano::Deployment::Strategy::Base", name: 'name', config: config)
67
+ config.user_tasks.push name: 'start',
68
+ namespaces: [],
69
+ block: lambda { }
70
+
71
+ described_class.register deployment_double
72
+
73
+ expect( Rake::Task.tasks.map(&:to_s) ).to include 'name:start'
74
+ end
75
+
76
+ it "adds description if given" do
77
+ config = Statistrano::Config.new
78
+ deployment_double = instance_double("Statistrano::Deployment::Strategy::Base", name: 'name', config: config)
79
+ config.user_tasks.push name: 'start',
80
+ desc: 'start something',
81
+ namespaces: [],
82
+ block: lambda { }
83
+
84
+ described_class.register deployment_double
85
+
86
+ expect( Rake::Task.tasks.map(&:to_s) ).to include 'name:start'
87
+ expect( Rake::Task.tasks.select { |t| t.full_comment == 'start something' } ).not_to be_empty
88
+ end
89
+
90
+ it "yields the deployment if arity is given" do
91
+ config = Statistrano::Config.new
92
+ deployment_double = instance_double("Statistrano::Deployment::Strategy::Base", name: 'name', config: config)
93
+ config.user_tasks.push name: 'start',
94
+ namespaces: ['puma'],
95
+ block: lambda { |dep| dep.remotes }
96
+ described_class.register deployment_double
97
+
98
+ expect( deployment_double ).to receive(:remotes)
99
+
100
+ Rake::Task['name:puma:start'].invoke
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+ end