deplomat 0.1.13 → 0.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.
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