cartage-remote 1.0 → 1.1

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 (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