statistrano 1.2.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.
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