deplomat 0.1.13 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85c420483a9680a16bcffb390c89a1e65ff92734ec191844ddeb93103cfc24c1
4
- data.tar.gz: 47632dd964956da6aeb1bfaf7a2ecf953f5254f43a34143f20c4623159661c66
3
+ metadata.gz: c91e9845ccf8392c7fff51614f56677df22aa87f00d29a1147fcf510c54ef88a
4
+ data.tar.gz: 4a35bfdfa7ae33d72234e4ef46d6b612b0bc5743285d3055662c44efb5ba62e2
5
5
  SHA512:
6
- metadata.gz: 11c1ccfc9525ed5bc32a064c88a52c9a861c0186a130271dc165933b0efa1e3faa7f868b83f42104c23d74fda21b2693e96ee3a5050a21fd98f3773451c5e6bd
7
- data.tar.gz: 2ceb5111bc322aaab57d84e499eb99e8c6f4856bff2ace60a89151c7fc6ef7374090409f96c9ee7031b5ac2ff396ea99968e4edee41f3bb24ef3e3f2cc24e4c0
6
+ metadata.gz: 4192a3789c9f630cb1640830ec417d3e05c4331a37c371ab265d6691ec788812a9606bd1a950d2971611a682f43344a88e060c9e27c163daca4cf73cbe033196
7
+ data.tar.gz: 0e1044ee65039255401f375057b61cea4d55f121c3d851f789bab155f90e0f70a4cc80e109e70da0f1f46566298305636b5a24ffed2766f1c16bb2b96239745a
data/README.rdoc CHANGED
@@ -1,3 +1,262 @@
1
- = deplomat
1
+ # Deplomat - a stack agnostic deployment system
2
+ Deplomat is a stack agnostic deployment system that uses bash and ssh commands.
3
+ The purpose of Deplomat is to be a suitable deployment system for all and easily scale from
4
+ a one-man operation to big teams and multiple servers.
2
5
 
3
- Stack agnostic deployment system that uses bash and ssh commands.
6
+ How does it work?
7
+ -----------------
8
+ * It uses SSH to send commands to remote servers and can also execute scripts on a local machine.
9
+ * The SSH connection is opened in such a way that it is persistent, so it's fast to execute multiple commands over it;
10
+ * The deployment script is a simple ruby script. You just create your own methods and then call them.
11
+
12
+ Let's take a look at an example script, step by step. For the purposes of this tutorial, we'll simplify things.
13
+ The process will resemble a typical web-app deployment, but won't be too specific or complicated.
14
+
15
+ #!/usr/bin/env ruby
16
+ require 'rubygems'
17
+ require 'deplomat'
18
+
19
+ $env = ARGV[0] || "staging"
20
+ $local = Deplomat::LocalNode.new(path: "/home/user/myproject")
21
+ $server = Deplomat::RemoteNode.new host: "myproject.com", port: 22, user: "deploy"
22
+ $branch = ARGV[1] || $env
23
+ $app_name = "myproject"
24
+ $project_dir = "/var/www/#{$app_name}"
25
+ $release_dir = Time.now.to_i
26
+
27
+ We've defined a bunch of global variables here. They're global to easily distinguish them from unimportant things, but they might as well
28
+ have been regular local variables. We have also created a `LocalNode` object - it is used to run commands on the local machine; and a `RemoteNode`
29
+ object, which, you guessed it, is used to run commands on a remote machine. You can theoretically have as many different remote nodes
30
+ as you want, but in our example we'll just have one.
31
+
32
+ Ok, now let's write the actual deployment code.
33
+
34
+ # Create the release dir
35
+ $server.create_dir("#{$project_dir}/#$env/releases/#{$release_dir}")
36
+
37
+ # Upload to the remote dir
38
+ $server.upload("#{$local.current_path}/*", "#{$project_dir}/#$env/releases/#{$release_dir}/")
39
+
40
+ # cd to the release dir we've just created and uploaded, we'll do things inside it.
41
+ $server.cd("#{$project_dir}/#$env/releases/#{$release_dir}")
42
+
43
+ Here, we used standard `Deplomat::RemoteNode` methods. First, we used `Deplomat::RemoteNode#create_dir` which
44
+ ran a `"mkdir -p /home/user/myproject/staging/releases/[timestamp]"` command on the server for us. Then we used the
45
+ `Deplomat::RemoteNode#upload` which uploaded all the files from our project directory to the server. And, finally,
46
+ we've changed current directory on the server to the one we've just created. So far so good, but we now need
47
+ to do a few things on the server before we can restart our webapp:
48
+
49
+ $server.create_symlink("#{$project_dir}/#$env/shared/config/database.yml", "config/")
50
+ $server.create_symlink("#{$project_dir}/#$env/shared/config/secrets.yml", "config/")
51
+ $server.create_symlink("#{$project_dir}/#$env/shared/config/cable.yml", "config/")
52
+ $server.create_symlink("#{$project_dir}/#$env/shared/config/redis.yml", "config/")
53
+ $server.create_symlink("#{$project_dir}/#$env/shared/log", "./")
54
+ $server.create_symlink("#{$project_dir}/#$env/shared/public/uploads", "public/")
55
+
56
+ Here, we created symlinks to the files and directories that persist across deployments. For example, the files users
57
+ upload should not evaporate with each new release and so we put them in the `/var/www/myproject/staging/shared/public/uploads`
58
+ directory and then symlink them to the release directory.
59
+
60
+ For the final steps, we need to migrate the database, instruct the server to restart and symlink the release directory:
61
+
62
+ # Migrate DB. Our migration script requires a login shell to work properly,
63
+ # so we instruct deplomat to run it using a login shell.
64
+ $server.execute("bin/migrate_db #{$env}", login_shell: true)
65
+
66
+ # Restart the server
67
+ $server.execute("mkdir -p tmp")
68
+ $server.touch("tmp/restart.txt")
69
+
70
+ if $server.file_exists?("#{$project_dir}/#$env/current")
71
+ $server.mv("#{$project_dir}/#$env/current", "#{$project_dir}/#$env/previous")
72
+ end
73
+ $server.create_symlink("#{$project_dir}/#$env/releases/#{$release_dir}", "#{$project_dir}/#$env/current")
74
+
75
+ You can see how we used `#file_exists?`, `#touch`, `#mv` methods here. Those are also standard methods of `Deplomat::Node`.
76
+ Notice how we checked if `"#{$project_dir}/#$env/current"` exists first, because it might not exist on our first deployment.
77
+ However if it does exist, it's wise to rename this symlink into `previous` so we can later undo the deployment easily by renaming that
78
+ symlink back to `current`.
79
+
80
+ Our script is ready, now you can run `./deploy` (assuming it's in the root dir of your project and you've made it executable).
81
+
82
+
83
+ Adding more structure with methods
84
+ ----------------------------------
85
+ Our script above is ok, however as your project grows you'll discover you'd want to add more structure to it. It
86
+ makes sense to group some actions into methods, so you can have something like this:
87
+
88
+ #!/usr/bin/env ruby
89
+ require 'rubygems'
90
+ require 'deplomat'
91
+ require 'deployment_steps' # << THIS IS WHERE WE PUT OUR METHODS THAT WE USE BELOW
92
+
93
+ $env = ARGV[0] || "staging"
94
+ $local = Deplomat::LocalNode.new(path: "/home/user/myproject")
95
+ $server = Deplomat::RemoteNode.new host: "myproject.com", port: 22, user: "deploy"
96
+ $branch = ARGV[1] || $env
97
+ $app_name = "myproject"
98
+ $project_dir = "/var/www/#{$app_name}"
99
+ $release_dir = Time.now.to_i
100
+
101
+ create_release_dir_and_upload!
102
+ create_symlinks!
103
+ migrate_db!
104
+ restart_server!
105
+
106
+ This script looks much nicer. We moved deployment code into separate methods into a file we called
107
+ `deployment_steps.rb` and it looks like this:
108
+
109
+ def create_release_dir_and_upload!
110
+ # Create the release dir
111
+ $server.create_dir("#{$project_dir}/#$env/releases/#{$release_dir}")
112
+ # Upload to the remote dir
113
+ $server.upload("#{$local.current_path}/*", "#{$project_dir}/#$env/releases/#{$release_dir}/")
114
+ # cd to the release dir we've just created and uploaded, we'll do things inside it.
115
+ $server.cd("#{$project_dir}/#$env/releases/#{$release_dir}")
116
+ end
117
+
118
+ def create_symlinks!
119
+ $server.create_symlink("#{$project_dir}/#$env/shared/config/database.yml", "config/")
120
+ $server.create_symlink("#{$project_dir}/#$env/shared/config/secrets.yml", "config/")
121
+ $server.create_symlink("#{$project_dir}/#$env/shared/config/cable.yml", "config/")
122
+ $server.create_symlink("#{$project_dir}/#$env/shared/config/redis.yml", "config/")
123
+ $server.create_symlink("#{$project_dir}/#$env/shared/log", "./")
124
+ $server.create_symlink("#{$project_dir}/#$env/shared/public/uploads", "public/")
125
+ end
126
+
127
+ def migrate_db!
128
+ # Migrate DB. Our migration script requires a login shell to work properly,
129
+ # so we instruct deplomat to run it using a login shell.
130
+ $server.execute("bin/migrate_db #{$env}", login_shell: true)
131
+ end
132
+
133
+ def restart_server!
134
+ # Restart the server
135
+ $server.execute("mkdir -p tmp")
136
+ $server.touch("tmp/restart.txt")
137
+
138
+ if $server.file_exists?("#{$project_dir}/#$env/current")
139
+ $server.mv("#{$project_dir}/#$env/current", "#{$project_dir}/#$env/previous")
140
+ end
141
+ $server.create_symlink("#{$project_dir}/#$env/releases/#{$release_dir}", "#{$project_dir}/#$env/current")
142
+ end
143
+
144
+ Notice, we were able to use the same `$server`, `$release_dir`, `$env` and some other variables inside that file precisely
145
+ because we made them global. While global vars are not great for large systems, deployment scripts such as this
146
+ one can take advantage of them without complicating things too much.
147
+
148
+ Deployment requisites
149
+ ---------------------
150
+ Sometimes you need to run a piece of code while deploying the project, but you only need to run it once - that is,
151
+ on one deployment after which it will never be run again. Much like Ruby On Rails runs migrations once and then only runs
152
+ new migrations when necessary.
153
+
154
+ An example would be when you need to add something to the config file. While you can do it manually by logging into your server
155
+ and editing the config file, it's much more desirable to automate that process, because then you won't forget to do it.
156
+
157
+ Deplomat has a special feature called Deployment requisites, which allow you to
158
+
159
+ * Write special ruby scripts called "requisites", which have access to all the variables and features your script has access to;
160
+ * Enumarate the tasks that are being run on each deployment and keep track of them by using a special requisite counter (a file created on the server);
161
+ * Assign each task to be run before or after a particular deployment method in your script;
162
+
163
+ Let's see how we do that. The first step would be to replace method calls with a call to `#add_task` in your deployment script:
164
+
165
+ #!/usr/bin/env ruby
166
+ require 'rubygems'
167
+ require 'deplomat'
168
+ require 'deployment_steps' # << THIS IS WHERE WE PUT OUR METHODS THAT WE USE BELOW
169
+
170
+ $env = ARGV[0] || "staging"
171
+ $local = Deplomat::LocalNode.new(path: "/home/user/myproject")
172
+ $server = Deplomat::RemoteNode.new host: "myproject.com", port: 22, user: "deploy"
173
+ $branch = ARGV[1] || $env
174
+ $app_name = "myproject"
175
+ $project_dir = "/var/www/#{$app_name}"
176
+ $release_dir = Time.now.to_i
177
+
178
+ add_task :create_release_dir_and_upload!
179
+ add_task :create_symlinks!
180
+ add_task :migrate_db!
181
+ add_task :restart_server!
182
+
183
+ execute_tasks!
184
+
185
+ This script's behavior is equivalent to the one we had previously. We can make it shorter though by writing:
186
+
187
+ # --- top part with requires and global var settings ommited ---
188
+
189
+ add_task :create_release_dir_and_upload!, :create_symlinks!, :migrate_db!, :restart_server!
190
+ execute_tasks!
191
+
192
+
193
+ We'll add two lines of code that will read the current requisite number from the server and then load the requisites from
194
+ a local directory called `./deployment_requisites/`. You can change the defaults by passing an additional `path:` argument
195
+ to the `load_requisites!` method, but we're not going to do it here.
196
+
197
+ # --- top part with requires and global var settings ommited ---
198
+
199
+ # This method is kind of a callback, it's called automatically after every #before_task
200
+ # or #after_task call. We need to define it manually here,
201
+ # otherwise requisite number will be stuck on the same number
202
+ # and never updated.
203
+ def update_requisite_number!(n)
204
+ $server.update_requisite_number!(n)
205
+ end
206
+
207
+ # read current requisite number from the server
208
+ req_n = $server.current_requisite_number
209
+
210
+ # load requisites
211
+ load_requisites!(req_n)
212
+
213
+ add_task :create_release_dir_and_upload!, :create_symlinks!, :migrate_db!, :restart_server!
214
+ execute_tasks!
215
+
216
+ The `#execute_tasks!` method will now not only run your methods, but also run the requisites associated with each task. Now
217
+ you might ask, where's the actual code for the requisites? Let's create two files in the `./deployment_requisites/` dir on
218
+ your local machine:
219
+
220
+ # ./deployment_requisites/1_add_var1_to_config_file.rb
221
+ before_task(:migrate_db, 1) do
222
+ $server.execute("cat 'var1: true' >> config/secrets.yml")
223
+ end
224
+
225
+ # ./deployment_requisites/2_add_var2_to_config_file.rb
226
+ after_task(:create_release_dir_and_upload!, 2) do
227
+ $server.execute("cat 'var2: true' >> config/secrets.yml")
228
+ end
229
+
230
+ Notice two things here:
231
+
232
+ * Filenames start with a number. That's very important: each new requisite file should get a number that's larger than the previous number;
233
+ * When calling `before_task` or `after_task` the second argument should always be the number that equals that
234
+ consecutive number in the file name;
235
+ * You can have only one call to `before_task` or `after_task` per requisite file.
236
+
237
+ When you deploy, that's what's going to happen:
238
+
239
+ * Deplomat will check for the requisite number in the counter file at `"#{@current_path}/.deployment_requisites_counter"` (that's
240
+ the default location, can be changed by passing an additional argument to `Deplomat::Node#current_requisite_number` and
241
+ `Deplomat::Node#update_requisite_number`, see sources);
242
+
243
+ * Use that fetched counter number to run only requisites with the numbers that are higher;
244
+
245
+ * Update that number upon each requisite script completion (so if there's an error somehwere, we're still left at the exact requisite number
246
+ that ran successfully). The update is done by calling the `#update_requisite_number!` we defined in our deployment script.
247
+
248
+
249
+ Where can I find the list of all methods?
250
+ ----------------------------------------
251
+ For now, because this is a relatively small library, you're better off browsing the sources, specifically:
252
+
253
+ * [Deplomat::Node](lib/deplomat/node.rb)
254
+ * [Deplomat::LocalNode](lib/deplomat/local_node.rb)
255
+ * [Deplomat::RemoteNode](lib/deplomat/remotenode.rb)
256
+
257
+ TODO
258
+ -----
259
+
260
+ * `Deplomat::Node` methods to read and update .yml files easily (usecase: update config files in requisite scripts).
261
+ * Include `git-archive-all` script
262
+ * Include scripts for default Ruby On Rails deployments (perhaps as a separate repo)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.13
1
+ 0.2.0
data/deplomat.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: deplomat 0.1.13 ruby lib
5
+ # stub: deplomat 0.2.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "deplomat".freeze
9
- s.version = "0.1.13"
9
+ s.version = "0.2.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Roman Snitko".freeze]
14
- s.date = "2018-11-17"
14
+ s.date = "2018-12-17"
15
15
  s.description = "Stack agnostic deployment system that uses bash and ssh commands".freeze
16
16
  s.email = "roman.snitko@gmail.com".freeze
17
17
  s.extra_rdoc_files = [
@@ -35,7 +35,11 @@ Gem::Specification.new do |s|
35
35
  "lib/deplomat/local_node.rb",
36
36
  "lib/deplomat/node.rb",
37
37
  "lib/deplomat/remote_node.rb",
38
+ "spec/deployment_requisites/1_req.rb",
39
+ "spec/deployment_requisites/2_req.rb",
40
+ "spec/deployment_requisites/not_a_task.rb",
38
41
  "spec/directives_spec.rb",
42
+ "spec/fixtures/.deployment_requisites_counter",
39
43
  "spec/fixtures/cleaning/.keep",
40
44
  "spec/fixtures/dir1/file1",
41
45
  "spec/fixtures/dir1/file2",
@@ -1,4 +1,6 @@
1
- $partials = {}
1
+ $partials = {}
2
+ $deplomat_tasks = []
3
+ $deplomat_tasks_callbacks = {}
2
4
 
3
5
  def execute_in(env:)
4
6
  yield if $env == env
@@ -23,3 +25,58 @@ def print_to_terminal(message, color: nil, newline: true)
23
25
  message = message.send(color) if color
24
26
  $stdout.print message
25
27
  end
28
+
29
+ # This wrapper allows us to insert external before/after
30
+ # tasks into every method executed by deplomat.
31
+ # Very useful for the one-time-tasks implementation.
32
+ def add_task(*tasks)
33
+ $deplomat_tasks += tasks
34
+ end
35
+ alias :add_tasks :add_task
36
+
37
+ def before_task(task_name, requisite_number, &block)
38
+ $deplomat_tasks_callbacks[task_name] ||= {}
39
+ $deplomat_tasks_callbacks[task_name][:before] ||= []
40
+ $deplomat_tasks_callbacks[task_name][:before] << lambda { block.call; update_requisite_number!(requisite_number) }
41
+ end
42
+
43
+ def after_task(task_name, requisite_number, &block)
44
+ $deplomat_tasks_callbacks[task_name] ||= {}
45
+ $deplomat_tasks_callbacks[task_name][:after] ||= []
46
+ $deplomat_tasks_callbacks[task_name][:after] << lambda { block.call; update_requisite_number!(requisite_number) }
47
+ end
48
+
49
+ def execute_tasks!
50
+ $deplomat_tasks.each do |t|
51
+ $deplomat_tasks_callbacks[t][:before].each { |block| block.call } if $deplomat_tasks_callbacks[t] && $deplomat_tasks_callbacks[t][:before]
52
+ self.send(t)
53
+ $deplomat_tasks_callbacks[t][:after].each { |block| block.call } if $deplomat_tasks_callbacks[t] && $deplomat_tasks_callbacks[t][:after]
54
+ end
55
+ end
56
+
57
+ # This should be redefined in the deployment script.
58
+ def update_requisite_number!(n)
59
+ # call Node#update_requisite_number! here
60
+ # or do something else, more complicated.
61
+ end
62
+
63
+ def load_requisites!(counter, requisites_path: "./deployment_requisites")
64
+
65
+ files = Dir["#{requisites_path}/*.rb"].map do |fn|
66
+ number = fn.split("/").last.match(/\A\d+_/).to_a.first&.chomp("_")
67
+ number ? [number, fn] : nil
68
+ end
69
+ .compact # ignore files that don't start with a number
70
+ .sort { |x,y| x.first <=> y.first } # Sort files according to the number in front of their names
71
+ .map { |fn| fn.last } # lose the folded Array we used to store the consecutive requisite number
72
+ .slice(counter..-1) # lose files whose consecutive requisite number is below or equals the counter
73
+
74
+ log = []
75
+ files.each do |fn|
76
+ log << "Loading requisite: #{fn.split("/").last }"
77
+ require fn
78
+ end
79
+
80
+ return { counter: counter + files.length, log: log }
81
+
82
+ end
@@ -1,4 +1,5 @@
1
1
  module Deplomat
2
2
  class ExecutionError < Exception;end
3
3
  class NoSuchPathError < Exception;end
4
+ class RequisitesNumberError < Exception; end
4
5
  end
data/lib/deplomat/node.rb CHANGED
@@ -125,6 +125,25 @@ module Deplomat
125
125
  execute("git checkout #{target}")
126
126
  end
127
127
 
128
+ def update_requisite_number!(n, counter_file_path: "#{@current_path}/.deployment_requisites_counter")
129
+ current_number = current_requisite_number(counter_file_path)
130
+ if n <= current_number
131
+ raise Deplomat::RequisitesNumberError, message: "New requisite number (#{n}) is below or equals the current one (#{current_number}). " +
132
+ "Something must have gone wrong."
133
+ else
134
+ File.open(counter_file_path, "w") { |f| f.puts n }
135
+ end
136
+ end
137
+
138
+ def current_requisite_number(fn="#{@current_path}/.deployment_requisites_counter")
139
+ if file_exists?(fn)
140
+ return File.readlines(fn).first.to_i
141
+ else
142
+ raise Deplomat::RequisitesNumberError, message: "Requisite counter file `#{@current_path}/.deployment_requisites_counter` doesn't exist. " +
143
+ "Please create it manually and symlink it in the deployment script if necessary."
144
+ end
145
+ end
146
+
128
147
  def clean(path: @current_path, except: [], leave: [0, :last])
129
148
  # Gets us all entries sorted by date, most recent ones first
130
149
  entries_by_date = execute("ls -t", path, log_command: false)[:out].split("\n")
@@ -0,0 +1,3 @@
1
+ before_task(:task1, 1) do
2
+ $deployment_requisites_test_file1 = true
3
+ end
@@ -0,0 +1,3 @@
1
+ before_task(:task2, 2) do
2
+ $deployment_requisites_test_file2 = true
3
+ end
File without changes
@@ -2,6 +2,10 @@ require 'spec_helper'
2
2
 
3
3
  describe "directives" do
4
4
 
5
+ before(:each) do
6
+ $deplomat_tasks = []
7
+ end
8
+
5
9
  it "executes arbitrary ruby code in a particular environment" do
6
10
  $env = 'staging'
7
11
  expect(self).to receive(:hello).exactly(1).times
@@ -20,6 +24,41 @@ describe "directives" do
20
24
  execute_partial "hello_partial", x: 'hello'
21
25
  end
22
26
 
23
- it "passes before and after messages"
27
+ it "executes tasks consecutively, running before and after callbacks" do
28
+
29
+ $out = ""
30
+ def task1; $out += "task1"; end
31
+ def task2; $out += "task2"; end
32
+ def task3; $out += ",task3"; end
33
+
34
+ before_task(:task1, 1) { $out += "before_task1:" }
35
+ after_task(:task1, 2) { $out += ":after_task1," }
36
+ before_task(:task2, 3) { $out += "before_task2:" }
37
+ after_task(:task2, 4) { $out += ":after_task2" }
38
+ before_task(:task4, 5) { $out += "before_task4:" }
39
+ after_task(:task4, 6) { $out += ":after_task4" }
40
+
41
+ add_task :task1, :task2, :task3
42
+
43
+ execute_tasks!
44
+ expect($out).to eq("before_task1:task1:after_task1,before_task2:task2:after_task2,task3")
45
+
46
+ end
47
+
48
+ it "loads and runs requisites" do
49
+
50
+ def task1;end
51
+ def task2;end
52
+
53
+ add_task :task1, :task2
54
+
55
+ result = load_requisites!(1, requisites_path: "#{File.expand_path(File.dirname(__FILE__))}/deployment_requisites")
56
+ expect(result[:counter]).to eq(2)
57
+ expect(result[:log]).to eq(["Loading requisite: 2_req.rb"])
58
+ execute_tasks!
59
+ expect($deployment_requisites_test_file1).to be_nil
60
+ expect($deployment_requisites_test_file2).to be_truthy
61
+
62
+ end
24
63
 
25
64
  end
data/spec/node_spec.rb CHANGED
@@ -44,6 +44,21 @@ describe Deplomat::Node do
44
44
  @node.execute("ls #{@fixtures_dir}/dir1", message: ["hello", "bye"])
45
45
  end
46
46
 
47
+ it "updates requisite counter" do
48
+
49
+ requisites_counter_fn = "#{Dir.pwd}/spec/.deployment_requisites_counter"
50
+ @node.cd Dir.pwd + "/spec"
51
+
52
+ File.open(requisites_counter_fn, "w") { |f| f.puts 1 }
53
+ @node.update_requisite_number!(2)
54
+ expect(File.readlines(requisites_counter_fn).first.to_i).to eq(2)
55
+
56
+ expect(-> { @node.update_requisite_number!(1) }).to raise_exception(Deplomat::RequisitesNumberError)
57
+
58
+ File.unlink(requisites_counter_fn)
59
+ expect(-> { @node.update_requisite_number!(3) }).to raise_exception(Deplomat::RequisitesNumberError)
60
+ end
61
+
47
62
  end
48
63
 
49
64
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deplomat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Snitko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-17 00:00:00.000000000 Z
11
+ date: 2018-12-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sys-proctable
@@ -104,7 +104,11 @@ files:
104
104
  - lib/deplomat/local_node.rb
105
105
  - lib/deplomat/node.rb
106
106
  - lib/deplomat/remote_node.rb
107
+ - spec/deployment_requisites/1_req.rb
108
+ - spec/deployment_requisites/2_req.rb
109
+ - spec/deployment_requisites/not_a_task.rb
107
110
  - spec/directives_spec.rb
111
+ - spec/fixtures/.deployment_requisites_counter
108
112
  - spec/fixtures/cleaning/.keep
109
113
  - spec/fixtures/dir1/file1
110
114
  - spec/fixtures/dir1/file2