cartage-remote 1.0 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +23 -1
  3. data/README.rdoc +1 -1
  4. data/Rakefile +2 -5
  5. data/lib/cartage/remote.rb +102 -64
  6. metadata +102 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ec28919c46cca17afd22212d913af4b3292c7eb
4
- data.tar.gz: 50e8f6d1252e272526e4e8953f0a872107e0078d
3
+ metadata.gz: 8d8ac39718d7abe3c0091abb06c8d3ecb456626e
4
+ data.tar.gz: a143524b851528d44b9dde9f77a9946c76ca2b1e
5
5
  SHA512:
6
- metadata.gz: a8cb9fd3b201d4951452c98b107fe68b01a3d61d4a544bbe864404467e28fea84791cf13654085d1a6201c0ed6407355e7da1b627dd9fb1b7b865dc4d8c23bc8
7
- data.tar.gz: ec485dac5760aca2e8fa061050e72bdf3dd9c8a29a8ef71af6b5522b81f30345981ada21c9ee6ac47e71525aa79b6da746b8e593d37a3881db612ca4890fc6f3
6
+ metadata.gz: 7a36d402c39713f5e0c1d4337cc52e7a7d57ddf74db363add86ca1e0c8db08d876603b58c1e099f8782507dd3ee9fec0fcce42311ccab03502f73aed318d0814
7
+ data.tar.gz: 395e90926c44b60f527398084938f8755679110c2b404211975d74077068a5881598f8b504c54e7c2d50705c1af829561242a0c6f03e422010f10183412eb97d
data/History.rdoc CHANGED
@@ -1,4 +1,26 @@
1
- === 1.0 / 2015-03-20
1
+ === 1.1 / 2015-03-26
2
+
3
+ * 1 major bugfix
4
+
5
+ * When a remote script fails, the error would not result in a non-zero
6
+ exit code, meaning that scripts could not detect failures in cartage
7
+ remote. Fixes [#1]{https://github.com/KineticCafe/cartage/issues/1}.
8
+
9
+ * 1 minor enhancement
10
+
11
+ * When the build is interrupted and a postbuild script is to be run, it
12
+ will be passed the exception error message as well as the stage.
13
+
14
+ * 1 minor bugfix
15
+
16
+ * Ensured that the last stage is not +cleanup+; added a +finished+ stage.
17
+
18
+ * Internal changes:
19
+
20
+ * Using [micromachine]{https://github.com/soveran/micromachine} to
21
+ provide the remote builds state machine cleanly.
22
+
23
+ === 1.0 / 2015-03-24
2
24
 
3
25
  * 1 major enhancement
4
26
 
data/README.rdoc CHANGED
@@ -24,7 +24,7 @@ control rules and without requiring development tool access.
24
24
 
25
25
  Add cartage-remote to your Gemfile:
26
26
 
27
- gem 'cartage-remote', '~> 1.0'
27
+ gem 'cartage-remote', '~> 1.1'
28
28
 
29
29
  Or manually install:
30
30
 
data/Rakefile CHANGED
@@ -20,7 +20,8 @@ spec = Hoe.spec 'cartage-remote' do
20
20
 
21
21
  license 'MIT'
22
22
 
23
- self.extra_deps << ['cartage', '~> 1.0']
23
+ self.extra_deps << ['cartage', '~> 1.1']
24
+ self.extra_deps << ['micromachine', '~> 1.2']
24
25
  self.extra_deps << ['fog', '~> 1.27']
25
26
 
26
27
  self.extra_dev_deps << ['rake', '~> 10.0']
@@ -28,7 +29,6 @@ spec = Hoe.spec 'cartage-remote' do
28
29
  self.extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
29
30
  self.extra_dev_deps << ['hoe-git', '~> 1.5']
30
31
  self.extra_dev_deps << ['hoe-geminabox', '~> 0.3']
31
- =begin
32
32
  self.extra_dev_deps << ['minitest', '~> 5.4']
33
33
  self.extra_dev_deps << ['minitest-autotest', '~> 1.0']
34
34
  self.extra_dev_deps << ['minitest-bisect', '~> 1.2']
@@ -36,10 +36,8 @@ spec = Hoe.spec 'cartage-remote' do
36
36
  self.extra_dev_deps << ['minitest-moar', '~> 0.0']
37
37
  self.extra_dev_deps << ['minitest-pretty_diff', '~> 0.1']
38
38
  self.extra_dev_deps << ['simplecov', '~> 0.7']
39
- =end
40
39
  end
41
40
 
42
- =begin
43
41
  namespace :test do
44
42
  task :coverage do
45
43
  prelude = <<-EOS
@@ -51,6 +49,5 @@ gem 'minitest'
51
49
  Rake::Task['test'].execute
52
50
  end
53
51
  end
54
- =end
55
52
 
56
53
  # vim: syntax=ruby
@@ -5,6 +5,7 @@ end
5
5
  require 'tempfile'
6
6
  require 'yaml'
7
7
  require 'erb'
8
+ require 'micromachine'
8
9
  require 'cartage/plugin'
9
10
 
10
11
  class Cartage
@@ -102,8 +103,11 @@ class Cartage
102
103
  # #!/bin/bash
103
104
  # ssh-keyscan -H %<remote_host>s >> ~/.ssh/known_hosts
104
105
  # +postbuild+:: A multiline YAML string that is run as a script on the local
105
- # machine to finish the build process locally. If not provided,
106
- # nothing will run.
106
+ # machine to finish the build process locally. If not
107
+ # provided, nothing will run. The script will be passed the
108
+ # stage (+config+, +ssh_config+, +prebuild+, +remote_clone+,
109
+ # +remote_build+, +cleanup+, or +finished+) and, if the stage
110
+ # is not +finished+, the error message.
107
111
  #
108
112
  # == Script Substitution
109
113
  #
@@ -153,32 +157,70 @@ class Cartage
153
157
  # bundle exec cartage s3 --config-file %<config_file>s
154
158
  #
155
159
  class Remote < Cartage::Plugin
156
- VERSION = '1.0' #:nodoc:
160
+ VERSION = '1.1' #:nodoc:
157
161
 
158
162
  def initialize(*) #:nodoc:
159
163
  super
160
164
  @tmpfiles = []
165
+ @fsm = MicroMachine.new(:new).tap do |fsm|
166
+ fsm.when(:local_setup, new: :config)
167
+ fsm.when(:ssh_setup, config: :ssh_config)
168
+ fsm.when(:run_prebuild, ssh_config: :prebuild)
169
+ fsm.when(:clone_remote, prebuild: :remote_clone)
170
+ fsm.when(:build_remote, remote_clone: :remote_build)
171
+ fsm.when(:clean_remote, remote_build: :cleanup)
172
+ fsm.when(:complete, cleanup: :finished)
173
+ fsm.on(:any) { |event| dispatch(event, @fsm.state) }
174
+ end
161
175
  end
162
176
 
163
177
  # Build on the remote server.
164
178
  def build
179
+ @fsm.trigger!(:local_setup)
180
+ @fsm.trigger!(:ssh_setup)
181
+ @fsm.trigger!(:run_prebuild)
182
+ @fsm.trigger!(:clone_remote)
183
+ @fsm.trigger!(:build_remote)
184
+ @fsm.trigger!(:clean_remote)
185
+ @fsm.trigger!(:complete)
186
+ rescue Cartage::StatusError
187
+ raise
188
+ rescue Exception => e
189
+ error = e.exception("Remote error in stage #{@fsm.state}: #{e.message}")
190
+ error.set_backtrace(e.backtrace)
191
+ raise error
192
+ ensure
193
+ if @postbuild
194
+ @cartage.display 'Running postbuild script...'
195
+ system(make_tmpscript('postbuild', @postbuild, @subs).path,
196
+ @fsm.state.to_s, error.to_s)
197
+ end
198
+
199
+ @tmpfiles.each { |tmpfile|
200
+ tmpfile.close
201
+ tmpfile.unlink
202
+ }
203
+ @tmpfiles.clear
204
+ end
205
+
206
+ private
207
+
208
+ def local_setup
165
209
  @cartage.display 'Pre-build configuration...'
166
- stage = :config
167
-
168
- paths = OpenStruct.new(build_root: @build_root)
169
- paths.cartage_path = paths.build_root.join('cartage')
170
- paths.project_path = paths.cartage_path.join(@cartage.name)
171
- paths.isolation_path = paths.project_path.join(@cartage.timestamp)
172
- paths.build_path = paths.isolation_path.join(@cartage.name)
173
- paths.remote_bundle = paths.isolation_path.join('deps')
174
- paths.bundle_cache = paths.project_path
175
- paths.config_file = paths.isolation_path.join('cartage.yml')
176
- paths.build_script = paths.isolation_path.join('cartage-build-remote')
177
-
178
- config_file = make_config(paths).path
179
-
180
- subs = OpenStruct.new(
181
- paths.to_h.merge(repo_url: @cartage.repo_url,
210
+ @paths = OpenStruct.new(build_root: @build_root)
211
+ @paths.cartage_path = @paths.build_root.join('cartage')
212
+ @paths.project_path = @paths.cartage_path.join(@cartage.name)
213
+ @paths.isolation_path = @paths.project_path.join(@cartage.timestamp)
214
+ @paths.build_path = @paths.isolation_path.join(@cartage.name)
215
+ @paths.remote_bundle = @paths.isolation_path.join('deps')
216
+ @paths.bundle_cache = @paths.project_path
217
+ @paths.config_file = @paths.isolation_path.join('cartage.yml')
218
+ @paths.build_script = @paths.isolation_path.join('cartage-build-remote')
219
+
220
+ @config_file = make_config(@paths).path
221
+
222
+ @subs = OpenStruct.new(
223
+ @paths.to_h.merge(repo_url: @cartage.repo_url,
182
224
  name: @cartage.name,
183
225
  release_hashref: @cartage.release_hashref,
184
226
  timestamp: @cartage.timestamp,
@@ -187,51 +229,56 @@ class Cartage
187
229
  remote_user: @remote_user)
188
230
  )
189
231
 
190
- stage = :ssh_config
191
- configure_ssh
232
+ end
233
+
234
+ def ssh_setup
235
+ require 'fog'
236
+ options = {
237
+ paranoid: true,
238
+ keys: @keys,
239
+ key_data: @key_data
240
+ }
241
+
242
+ options[:port] = @remote_port if @remote_port
243
+
244
+ @ssh = Fog::SSH.new(@remote_host, @remote_user, options)
245
+ @scp = Fog::SCP.new(@remote_host, @remote_user, options)
246
+ end
192
247
 
248
+ def run_prebuild
193
249
  @cartage.display 'Running prebuild script...'
194
- stage = :prebuild
195
- system(make_tmpscript('prebuild', @prebuild, subs).path)
250
+ system(make_tmpscript('prebuild', @prebuild, @subs).path)
251
+ end
196
252
 
197
- stage = :remote_clone
253
+ def clone_remote
198
254
  @cartage.display <<-message
199
255
  Checking out #{@cartage.repo_url} at #{@cartage.release_hashref} remotely...
200
256
  message
201
257
 
202
- ssh %Q(mkdir -p #{paths.isolation_path})
203
- @scp.upload(config_file, user_path(paths.config_file))
204
- ssh %Q(git clone #{@cartage.repo_url} #{paths.build_path})
258
+ ssh %Q(mkdir -p #{@paths.isolation_path})
259
+ @scp.upload(@config_file, user_path(@paths.config_file))
260
+ ssh %Q(git clone #{@cartage.repo_url} #{@paths.build_path})
205
261
  ssh <<-command
206
- cd #{paths.build_path} && git checkout #{@cartage.release_hashref}
262
+ cd #{@paths.build_path} && git checkout #{@cartage.release_hashref}
207
263
  command
264
+ end
208
265
 
266
+ def build_remote
209
267
  @cartage.display 'Running build script...'
210
- stage = :remote_build
211
- script = make_tmpscript('build', @build, subs).path
212
- @scp.upload(script, user_path(paths.build_script))
213
- ssh %Q(cd #{paths.build_path} && #{paths.build_script})
268
+ script = make_tmpscript('build', @build, @subs).path
269
+ @scp.upload(script, user_path(@paths.build_script))
270
+ ssh %Q(cd #{@paths.build_path} && #{@paths.build_script})
271
+ end
214
272
 
215
- stage = :cleanup
273
+ def clean_remote
216
274
  @cartage.display 'Cleaning up after the build...'
217
- ssh %Q(rm -rf #{paths.isolation_path})
218
- rescue StandardError => e
219
- $stderr.puts "Remote error in stage #{stage}: #{e.message}"
220
- $stderr.puts e.backtrace.join("\n") if @cartage.verbose
221
- ensure
222
- if @postbuild
223
- @cartage.display 'Running postbuild script...'
224
- system(make_tmpscript('postbuild', @postbuild, subs).path, stage.to_s)
225
- end
226
-
227
- @tmpfiles.each { |tmpfile|
228
- tmpfile.close
229
- tmpfile.unlink
230
- }
231
- @tmpfiles.clear
275
+ ssh %Q(rm -rf #{@paths.isolation_path})
232
276
  end
233
277
 
234
- private
278
+ def dispatch(event, state)
279
+ send(event) if respond_to?(event, true)
280
+ send(state) if respond_to?(state, true)
281
+ end
235
282
 
236
283
  def resolve_config!(remote_config)
237
284
  unless remote_config
@@ -296,19 +343,6 @@ No build script to run on remote #{@remote_server}.
296
343
  @cartage
297
344
  end
298
345
 
299
- def configure_ssh
300
- require 'fog'
301
- options = {
302
- paranoid: true,
303
- keys: @keys,
304
- key_data: @key_data
305
- }
306
-
307
- options[:port] = @remote_port if @remote_port
308
-
309
- @ssh = Fog::SSH.new(@remote_host, @remote_user, options)
310
- @scp = Fog::SCP.new(@remote_host, @remote_user, options)
311
- end
312
346
 
313
347
  def ssh(*commands)
314
348
  results = @ssh.run(commands) do |stdout, stderr|
@@ -318,8 +352,12 @@ No build script to run on remote #{@remote_server}.
318
352
 
319
353
  results.each do |result|
320
354
  if result.status.nonzero?
321
- fail "SSH Command failed with status (#{result.status}): " +
322
- "#{result.status}"
355
+ message = <<-msg
356
+ Remote error in stage #{@fsm.state}:
357
+ SSH command failed with status (#{result.status}):
358
+ #{result.command}
359
+ msg
360
+ fail Cartage::StatusError.new(result.status, message)
323
361
  end
324
362
  end
325
363
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cartage-remote
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.0'
4
+ version: '1.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Austin Ziegler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-24 00:00:00.000000000 Z
11
+ date: 2015-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cartage
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '1.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: micromachine
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: fog
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +150,90 @@ dependencies:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
152
  version: '0.3'
153
+ - !ruby/object:Gem::Dependency
154
+ name: minitest-autotest
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: minitest-bisect
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '1.2'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '1.2'
181
+ - !ruby/object:Gem::Dependency
182
+ name: minitest-focus
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '1.1'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '1.1'
195
+ - !ruby/object:Gem::Dependency
196
+ name: minitest-moar
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '0.0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '0.0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: minitest-pretty_diff
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '0.1'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '0.1'
223
+ - !ruby/object:Gem::Dependency
224
+ name: simplecov
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: '0.7'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: '0.7'
139
237
  - !ruby/object:Gem::Dependency
140
238
  name: hoe
141
239
  requirement: !ruby/object:Gem::Requirement