cartage-remote 1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8ec28919c46cca17afd22212d913af4b3292c7eb
4
+ data.tar.gz: 50e8f6d1252e272526e4e8953f0a872107e0078d
5
+ SHA512:
6
+ metadata.gz: a8cb9fd3b201d4951452c98b107fe68b01a3d61d4a544bbe864404467e28fea84791cf13654085d1a6201c0ed6407355e7da1b627dd9fb1b7b865dc4d8c23bc8
7
+ data.tar.gz: ec485dac5760aca2e8fa061050e72bdf3dd9c8a29a8ef71af6b5522b81f30345981ada21c9ee6ac47e71525aa79b6da746b8e593d37a3881db612ca4890fc6f3
data/.autotest ADDED
@@ -0,0 +1,27 @@
1
+ # -*- ruby -*-
2
+
3
+ require "autotest/restart"
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+ # .minitest.rb ensures that the gem version of minitest is used.
7
+ at.testlib = ".minitest.rb"
8
+ # at.testlib = "minitest/unit"
9
+ #
10
+ # at.extra_files << "../some/external/dependency.rb"
11
+ #
12
+ # at.libs << ":../some/external"
13
+ #
14
+ # at.add_exception "vendor"
15
+ #
16
+ # at.add_mapping(/dependency.rb/) do |f, _|
17
+ # at.files_matching(/test_.*rb$/)
18
+ # end
19
+ #
20
+ # %w(TestA TestB).each do |klass|
21
+ # at.extra_class_map[klass] = "test/test_misc.rb"
22
+ # end
23
+ end
24
+
25
+ # Autotest.add_hook :run_command do |at|
26
+ # system "rake build"
27
+ # end
data/.gemtest ADDED
@@ -0,0 +1 @@
1
+
data/.minitest.rb ADDED
@@ -0,0 +1,2 @@
1
+ gem "minitest"
2
+ require "minitest/autorun"
data/Contributing.rdoc ADDED
@@ -0,0 +1,63 @@
1
+ == Contributing
2
+
3
+ We value any contribution to cartage-remote you can provide: a bug report, a
4
+ feature request, or code contributions.
5
+
6
+ cartage-remote has a few contribution guidelines:
7
+
8
+ * Changes *will* *not* be accepted without tests. The test suite is written
9
+ with {Minitest}[https://github.com/seattlerb/minitest].
10
+ * Match our coding style.
11
+ * Use a thoughtfully-named topic branch that contains your change. Rebase your
12
+ commits into logical chunks as necessary.
13
+ * Use {quality commit messages}[http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html].
14
+ * Do not change the version number; when your patch is accepted and a release
15
+ is made, the version will be updated at that point.
16
+ * Submit a GitHub pull request with your changes.
17
+
18
+ === Test Dependencies
19
+
20
+ cartage-remote uses Ryan Davis’s {Hoe}[https://github.com/seattlerb/hoe] to manage
21
+ the release process, and it adds a number of rake tasks. You will mostly be
22
+ interested in:
23
+
24
+ $ rake
25
+
26
+ which runs the tests the same way that:
27
+
28
+ $ rake test
29
+ $ rake travis
30
+
31
+ will do.
32
+
33
+ To assist with the installation of the development dependencies for cartage-remote,
34
+ I have provided the simplest possible Gemfile pointing to the (generated)
35
+ +cartage-remote.gemspec+ file. This will permit you to do:
36
+
37
+ $ bundle install
38
+
39
+ to get the development dependencies. If you aleady have +hoe+ installed, you
40
+ can accomplish the same thing with:
41
+
42
+ $ rake newb
43
+
44
+ This task will install any missing dependencies, run the tests/specs, and
45
+ generate the RDoc.
46
+
47
+ === Workflow
48
+
49
+ Here's the most direct way to get your work merged into the project:
50
+
51
+ * Fork the project.
52
+ * Clone down your fork (<tt>git clone git://github.com/KineticCafe/cartage-remote.git</tt>).
53
+ * Create a topic branch to contain your change (<tt>git checkout -b my\_awesome\_feature</tt>).
54
+ * Hack away, add tests. Not necessarily in that order.
55
+ * Make sure everything still passes by running +rake+.
56
+ * If necessary, rebase your commits into logical chunks, without errors.
57
+ * Push the branch up (<tt>git push origin my\_awesome\_feature</tt>).
58
+ * Create a pull request against KineticCafe/cartage-remote and describe
59
+ what your change does and the why you think it should be merged.
60
+
61
+ === Contributors
62
+
63
+ * Austin Ziegler created cartage-remote.
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # -*- ruby -*-
2
+
3
+ # NOTE: This file is not the canonical source of dependencies. Edit the
4
+ # Rakefile, instead.
5
+
6
+ source "https://rubygems.org/"
7
+ gemspec
8
+
9
+ # vim: syntax=ruby
data/History.rdoc ADDED
@@ -0,0 +1,5 @@
1
+ === 1.0 / 2015-03-20
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
data/Licence.rdoc ADDED
@@ -0,0 +1,27 @@
1
+ == Licence
2
+
3
+ This software is available under an MIT-style licence.
4
+
5
+ * Copyright 2015 Kinetic Cafe
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
8
+ this software and associated documentation files (the "Software"), to deal in
9
+ the Software without restriction, including without limitation the rights to
10
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11
+ of the Software, and to permit persons to whom the Software is furnished to do
12
+ so, subject to the following conditions:
13
+
14
+ * The names of its contributors may not be used to endorse or promote
15
+ products derived from this software without specific prior written
16
+ permission.
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,12 @@
1
+ .autotest
2
+ .gemtest
3
+ .minitest.rb
4
+ Contributing.rdoc
5
+ Gemfile
6
+ History.rdoc
7
+ Licence.rdoc
8
+ Manifest.txt
9
+ README.rdoc
10
+ Rakefile
11
+ lib/cartage/remote.rb
12
+ lib/cartage/remote/command.rb
data/README.rdoc ADDED
@@ -0,0 +1,45 @@
1
+ = cartage-remote by Kinetic Cafe
2
+
3
+ code :: https://github.com/KineticCafe/cartage-remote/
4
+ issues :: https://github.com/KineticCafe/cartage-remote/issues
5
+ continuous integration :: {<img src="https://travis-ci.org/KineticCafe/cartage-remote.png" />}[https://travis-ci.org/KineticCafe/cartage-remote]
6
+
7
+ == Description
8
+
9
+ cartage-remote is a plug-in for {cartage}[https://github.com/KineticCafe/cartage]
10
+ to build a package on a remote machine with cartage.
11
+
12
+ Cartage provides a repeatable means to create a package for a Rails application
13
+ that can be used in deployment with a configuration tool like Ansible, Chef,
14
+ Puppet, or Salt. The package is created with its dependencies bundled in
15
+ `vendor/bundle`, so it can be deployed in environments with strict access
16
+ control rules and without requiring development tool access.
17
+
18
+ == Synopsis
19
+
20
+ # Build a package on a remote machine via SSH.
21
+ cartage remote
22
+
23
+ == Install
24
+
25
+ Add cartage-remote to your Gemfile:
26
+
27
+ gem 'cartage-remote', '~> 1.0'
28
+
29
+ Or manually install:
30
+
31
+ % gem install cartage-remote
32
+
33
+ == cartage-remote Semantic Versioning
34
+
35
+ cartage-remote uses a {Semantic Versioning}[http://semver.org/] scheme with one
36
+ change:
37
+
38
+ * When PATCH is zero (+0+), it will be omitted from version references.
39
+
40
+ cartage-remote will generally track cartage for major versions to ensure plugin API
41
+ compatibility.
42
+
43
+ :include: Contributing.rdoc
44
+
45
+ :include: Licence.rdoc
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require 'pathname'
6
+
7
+ Hoe.plugin :doofus
8
+ Hoe.plugin :email unless ENV['CI'] or ENV['TRAVIS']
9
+ Hoe.plugin :gemspec2
10
+ Hoe.plugin :git
11
+ Hoe.plugin :minitest
12
+ Hoe.plugin :rubygems
13
+
14
+ spec = Hoe.spec 'cartage-remote' do
15
+ developer('Austin Ziegler', 'aziegler@kineticcafe.com')
16
+
17
+ self.history_file = 'History.rdoc'
18
+ self.readme_file = 'README.rdoc'
19
+ self.extra_rdoc_files = FileList['*.rdoc'].to_a
20
+
21
+ license 'MIT'
22
+
23
+ self.extra_deps << ['cartage', '~> 1.0']
24
+ self.extra_deps << ['fog', '~> 1.27']
25
+
26
+ self.extra_dev_deps << ['rake', '~> 10.0']
27
+ self.extra_dev_deps << ['hoe-doofus', '~> 1.0']
28
+ self.extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
29
+ self.extra_dev_deps << ['hoe-git', '~> 1.5']
30
+ self.extra_dev_deps << ['hoe-geminabox', '~> 0.3']
31
+ =begin
32
+ self.extra_dev_deps << ['minitest', '~> 5.4']
33
+ self.extra_dev_deps << ['minitest-autotest', '~> 1.0']
34
+ self.extra_dev_deps << ['minitest-bisect', '~> 1.2']
35
+ self.extra_dev_deps << ['minitest-focus', '~> 1.1']
36
+ self.extra_dev_deps << ['minitest-moar', '~> 0.0']
37
+ self.extra_dev_deps << ['minitest-pretty_diff', '~> 0.1']
38
+ self.extra_dev_deps << ['simplecov', '~> 0.7']
39
+ =end
40
+ end
41
+
42
+ =begin
43
+ namespace :test do
44
+ task :coverage do
45
+ prelude = <<-EOS
46
+ require 'simplecov'
47
+ SimpleCov.start('test_frameworks') { command_name 'Minitest' }
48
+ gem 'minitest'
49
+ EOS
50
+ spec.test_prelude = prelude.split($/).join('; ')
51
+ Rake::Task['test'].execute
52
+ end
53
+ end
54
+ =end
55
+
56
+ # vim: syntax=ruby
@@ -0,0 +1,381 @@
1
+ begin
2
+ require 'psych'
3
+ rescue LoadError
4
+ end
5
+ require 'tempfile'
6
+ require 'yaml'
7
+ require 'erb'
8
+ require 'cartage/plugin'
9
+
10
+ class Cartage
11
+ # Connect to a remote machine and build a package remotely. Cartage::Remote
12
+ # uses Fog::SSH with key-based, not password-based authentication to connect
13
+ # to a remote server.
14
+ #
15
+ # Cartage::Remote assumes a relatively stable build server, but does not
16
+ # require one (custom +prebuild+ and +postbuild+ scripts could be used to
17
+ # manage that).
18
+ #
19
+ # == Remote Build Isolation
20
+ #
21
+ # Cartage::Remote allows for safe builds across multiple projects and
22
+ # branches with path-based isolation. The pattern for the build path is shown
23
+ # below, where the last part of the path is where the code will be cloned to.
24
+ #
25
+ # ~<remote_user>/cartage/<project-name>/<timestamp>/<project-name>
26
+ # | | | | |
27
+ # v | | | |
28
+ # build root v | | |
29
+ # cartage | | |
30
+ # path v | |
31
+ # project v |
32
+ # path isolation |
33
+ # path v
34
+ # build
35
+ # path
36
+ #
37
+ # So that if I am deploying on a project called +calliope+ and my remote user
38
+ # is +build+, my isolated build path might be:
39
+ #
40
+ # ~build/cartage/calliope/20150321091432/calliope
41
+ #
42
+ # == Remote Build Steps
43
+ #
44
+ # The steps for a remote build are:
45
+ #
46
+ # 1. Configure Cartage and save the active Cartage configuration as a
47
+ # temporary file that will be copied to the remote server.
48
+ # 2. Configure the Fog::SSH adapters with the keys to connect to the remote
49
+ # system.
50
+ # 3. Create the +prebuild+ script and run it locally.
51
+ # 4. Connect to the remote server, put the Cartage configuration file in the
52
+ # isolation path, and clone the repository. Check the repo out to the
53
+ # appropriate +release_hashref+.
54
+ # 5. Create the +build+ script, copy it remotely, and run it from the build
55
+ # isolation path (+build_path+). This is effectively:
56
+ # cd "$build_path" && $build_script
57
+ # 6. Clean up the remote server
58
+ #
59
+ # == Configuration
60
+ #
61
+ # Cartage::Remote is configured in the +plugins.remote+ section of the
62
+ # Cartage configuration file. The following keys are *required*:
63
+ #
64
+ # +server+:: A server string in the form <tt>[user@]host[:port]</tt> *or* a
65
+ # dictionary with +user+, +host+, and +port+. In either form, this
66
+ # will set @remote_user, @remote_host, and @remote_port. If
67
+ # @remote_user is not provided, it will be set from
68
+ # <tt>$USER</tt>.
69
+ #
70
+ # The following keys are optional:
71
+ #
72
+ # +keys+:: The SSH key(s) used to connect to the server. There are two basic
73
+ # ways that keys can be provided:
74
+ #
75
+ # * If provided as a string or an array of strings, the value(s)
76
+ # will be applied as glob patterns to find key files on disk.
77
+ # * If provided as a dictionary, the keys are irrelevant but the
78
+ # values are the key data.
79
+ #
80
+ # If keys are not provided, a default pattern of
81
+ # <tt>~/.ssh/*id_[rd]sa</tt> will be used to find keys on the local
82
+ # machine.
83
+ # +build+:: A multiline YAML string that is copied to the remote machine and
84
+ # executed as a script there. If not provided, the following script
85
+ # will be run:
86
+ #
87
+ # #!/bin/bash
88
+ # set -e
89
+ # if [ -f Gemfile ]; then
90
+ # bundle install --path %<remote_bundle>s
91
+ # bundle exec cartage build \
92
+ # --config-file %<config_file>s \
93
+ # --target %<project_path>s
94
+ # else
95
+ # cartage build --config-file %<config_file>s \
96
+ # --target %<project_path>s
97
+ # fi
98
+ # +prebuild+:: A multiline YAML string that is run as a script on the local
99
+ # machine to prepare for running remotely. If not provided, the
100
+ # following script will be run:
101
+ #
102
+ # #!/bin/bash
103
+ # ssh-keyscan -H %<remote_host>s >> ~/.ssh/known_hosts
104
+ # +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.
107
+ #
108
+ # == Script Substitution
109
+ #
110
+ # The +build+, +prebuild+, and +postbuild+ scripts require information from
111
+ # the Cartage and Cartage::Remote instances. When these scripts are rendered
112
+ # to disk, they will be run through Kernel#sprintf with the following
113
+ # substitution parameters specified as strings
114
+ # (<tt>%<<em>parameter-name</em>>s</tt>). All of these values are computed
115
+ # from the local Cartage configuration.
116
+ #
117
+ # +repo_url+:: The repository URL.
118
+ # +name+:: The package name.
119
+ # +release_hashref+:: The release hashref to build.
120
+ # +timestamp+:: The build timestamp.
121
+ # +remote_host+:: The remote build host.
122
+ # +remote_port+:: The remote build host SSH port (may be empty).
123
+ # +remote_user+:: The remote build user.
124
+ # +build_root+:: The remote build root, (usually
125
+ # <tt>~<em>remote_user</em></tt>).
126
+ # +cartage_path+:: <tt><em>build_root</em>/cartage</tt>.
127
+ # +project_path+:: <tt><em>cartage_path</em>/<em>name</em></tt>.
128
+ # +isolation_path+:: <tt><em>project_path</em>/<em>timestamp</em></tt>.
129
+ # +build_path+:: The remote build path (contains the code to package).
130
+ # <tt><em>isolation_path</em>/<em>name</em></tt>
131
+ # +remote_bundle+:: A place where dependencies for the build can be installed
132
+ # locally. <tt><em>isolation_path</em>/deps</tt>. Typically
133
+ # used in the +build+ script.
134
+ # bundle install --path %<remote_bundle>s
135
+ # +bundle_cache+:: The +bundle_cache+ for the remote server. Set the same as
136
+ # +project_path+.
137
+ # +config_file+:: The remote filename of the computed Cartage configuration.
138
+ # Must be provided to the remote run of +cartage+.
139
+ # bundle exec cartage build --config-file %<config_file>s
140
+ # +build_script+:: The full path to the remote build script.
141
+ # <tt><em>isolation_path</em>/cartage-build-remote</tt>.
142
+ #
143
+ # == Configuration Example
144
+ #
145
+ # ---
146
+ # plugins:
147
+ # remote:
148
+ # server:
149
+ # host: build-server
150
+ # script: |
151
+ # #! /bin/bash
152
+ # bundle install --path %<remote_bundle>s
153
+ # bundle exec cartage s3 --config-file %<config_file>s
154
+ #
155
+ class Remote < Cartage::Plugin
156
+ VERSION = '1.0' #:nodoc:
157
+
158
+ def initialize(*) #:nodoc:
159
+ super
160
+ @tmpfiles = []
161
+ end
162
+
163
+ # Build on the remote server.
164
+ def build
165
+ @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,
182
+ name: @cartage.name,
183
+ release_hashref: @cartage.release_hashref,
184
+ timestamp: @cartage.timestamp,
185
+ remote_host: @remote_host,
186
+ remote_port: @remote_port,
187
+ remote_user: @remote_user)
188
+ )
189
+
190
+ stage = :ssh_config
191
+ configure_ssh
192
+
193
+ @cartage.display 'Running prebuild script...'
194
+ stage = :prebuild
195
+ system(make_tmpscript('prebuild', @prebuild, subs).path)
196
+
197
+ stage = :remote_clone
198
+ @cartage.display <<-message
199
+ Checking out #{@cartage.repo_url} at #{@cartage.release_hashref} remotely...
200
+ message
201
+
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})
205
+ ssh <<-command
206
+ cd #{paths.build_path} && git checkout #{@cartage.release_hashref}
207
+ command
208
+
209
+ @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})
214
+
215
+ stage = :cleanup
216
+ @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
232
+ end
233
+
234
+ private
235
+
236
+ def resolve_config!(remote_config)
237
+ unless remote_config
238
+ raise ArgumentError, 'Cartage remote has no configuration.'
239
+ end
240
+
241
+ @remote_user = @remote_host = @remote_port = nil
242
+
243
+ case server = remote_config.server
244
+ when OpenStruct
245
+ @remote_user = server.user
246
+ @remote_host = server.host
247
+ @remote_port = server.port
248
+ when %r{\A(?:(?<user>[^@]+)@)?(?<host>[^@:]+)(?::(?<port>[^:]+))?\z}
249
+ @remote_user = $~[:user]
250
+ @remote_host = $~[:host]
251
+ @remote_port = $~[:port]
252
+ end
253
+
254
+ @remote_user ||= ENV['USER']
255
+
256
+ if @remote_host.nil? or @remote_host.empty?
257
+ raise ArgumentError, 'Cannot connect to remote; no server specified.'
258
+ end
259
+
260
+ @remote_server = @remote_host
261
+ @remote_server = "#{@remote_user}@#{@remote_server}" if @remote_user
262
+ @remote_server = "#{@remote_server}:#{@remote_port}" if @remote_port
263
+
264
+ @build_root = Pathname(remote_config.build_root || '~')
265
+
266
+ @build = remote_config.build
267
+ raise ArgumentError, <<-exception if @build.nil? or @build.empty?
268
+ No build script to run on remote #{@remote_server}.
269
+ exception
270
+
271
+ @key_data = @keys = nil
272
+
273
+ case keys = remote_config.keys
274
+ when OpenStruct
275
+ @key_data = keys.to_h.values
276
+ when Array
277
+ @keys = keys
278
+ when String
279
+ @keys = [ keys ]
280
+ when nil
281
+ @keys = %w(~/.ssh/*id_[rd]sa)
282
+ end
283
+
284
+ @keys &&= @keys.map { |key|
285
+ Pathname.glob(Pathname(key).expand_path)
286
+ }.flatten
287
+
288
+ @prebuild = remote_config.prebuild || DEFAULT_PREBUILD_SCRIPT
289
+ @postbuild = remote_config.postbuild
290
+
291
+ # Force lazy values to be present during execution.
292
+ @cartage.repo_url
293
+ @cartage.root_path
294
+ @cartage.release_hashref
295
+ @cartage.timestamp
296
+ @cartage
297
+ end
298
+
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
+
313
+ def ssh(*commands)
314
+ results = @ssh.run(commands) do |stdout, stderr|
315
+ $stdout.print stdout unless stdout.nil?
316
+ $stderr.print stderr unless stderr.nil?
317
+ end
318
+
319
+ results.each do |result|
320
+ if result.status.nonzero?
321
+ fail "SSH Command failed with status (#{result.status}): " +
322
+ "#{result.status}"
323
+ end
324
+ end
325
+ end
326
+
327
+ def make_tmpfile(basename, content = nil)
328
+ Tempfile.new("#{basename}.").tap { |f|
329
+ f.write content || yield
330
+ f.close
331
+ @tmpfiles << f
332
+ }
333
+ end
334
+
335
+ def make_tmpscript(basename, content, subs)
336
+ make_tmpfile(basename, content % subs.to_h).tap { |f|
337
+ File.chmod(0700, f.path)
338
+ }
339
+ end
340
+
341
+ def make_config(paths)
342
+ make_tmpfile('config.yml') do
343
+ config = Cartage::Config.new(@cartage.config)
344
+ config.name = @cartage.name
345
+ config.release_hashref = @cartage.release_hashref
346
+ config.timestamp = @cartage.timestamp
347
+ config.root_path = paths.build_path.to_s
348
+ config.bundle_cache = paths.bundle_cache.to_s
349
+ config.to_yaml
350
+ end
351
+ end
352
+
353
+ def user_path(path)
354
+ path.to_s.sub(%r{\A~/}, '')
355
+ end
356
+
357
+ def self.commands #:nodoc:
358
+ require_relative 'remote/command'
359
+ [ Cartage::Remote::Command ]
360
+ end
361
+
362
+ DEFAULT_PREBUILD_SCRIPT = <<-script #:nodoc:
363
+ #!/bin/bash
364
+
365
+ ssh-keyscan -H %<remote_host>s >> ~/.ssh/known_hosts
366
+ script
367
+
368
+ DEFAULT_BUILD_SCRIPT = <<-script #:nodoc:
369
+ #!/bin/bash
370
+
371
+ set -e
372
+
373
+ if [ -f Gemfile ]; then
374
+ bundle install --path %<remote_bundle>s
375
+ bundle exec cartage build --config-file %<config_file>s --target %<project_path>s
376
+ else
377
+ cartage build --config-file %<config_file>s --target %<project_path>s
378
+ fi
379
+ script
380
+ end
381
+ end
@@ -0,0 +1,22 @@
1
+ require 'cartage/command'
2
+
3
+ class Cartage::Remote::Command < Cartage::Command #:nodoc:
4
+ def initialize(cartage)
5
+ super(cartage, 'remote')
6
+ takes_commands(false)
7
+ short_desc('Build a release package and upload to cloud storage.')
8
+
9
+ @cartage = cartage
10
+ @remote = cartage.remote
11
+
12
+ Cartage.common_build_options(options, cartage)
13
+ end
14
+
15
+ def perform(*)
16
+ @remote.build
17
+ end
18
+
19
+ def with_plugins
20
+ %w(remote)
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,212 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cartage-remote
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Austin Ziegler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cartage
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: fog
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.27'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.27'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rdoc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: hoe-doofus
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: hoe-gemspec2
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.1'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: hoe-git
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.5'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: hoe-geminabox
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.3'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.3'
139
+ - !ruby/object:Gem::Dependency
140
+ name: hoe
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '3.13'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '3.13'
153
+ description: |-
154
+ cartage-remote is a plug-in for {cartage}[https://github.com/KineticCafe/cartage]
155
+ to build a package on a remote machine with cartage.
156
+
157
+ Cartage provides a repeatable means to create a package for a Rails application
158
+ that can be used in deployment with a configuration tool like Ansible, Chef,
159
+ Puppet, or Salt. The package is created with its dependencies bundled in
160
+ `vendor/bundle`, so it can be deployed in environments with strict access
161
+ control rules and without requiring development tool access.
162
+ email:
163
+ - aziegler@kineticcafe.com
164
+ executables: []
165
+ extensions: []
166
+ extra_rdoc_files:
167
+ - Contributing.rdoc
168
+ - History.rdoc
169
+ - Licence.rdoc
170
+ - Manifest.txt
171
+ - README.rdoc
172
+ files:
173
+ - ".autotest"
174
+ - ".gemtest"
175
+ - ".minitest.rb"
176
+ - Contributing.rdoc
177
+ - Gemfile
178
+ - History.rdoc
179
+ - Licence.rdoc
180
+ - Manifest.txt
181
+ - README.rdoc
182
+ - Rakefile
183
+ - lib/cartage/remote.rb
184
+ - lib/cartage/remote/command.rb
185
+ homepage: https://github.com/KineticCafe/cartage-remote/
186
+ licenses:
187
+ - MIT
188
+ metadata: {}
189
+ post_install_message:
190
+ rdoc_options:
191
+ - "--main"
192
+ - README.rdoc
193
+ require_paths:
194
+ - lib
195
+ required_ruby_version: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ required_rubygems_version: !ruby/object:Gem::Requirement
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ version: '0'
205
+ requirements: []
206
+ rubyforge_project:
207
+ rubygems_version: 2.2.2
208
+ signing_key:
209
+ specification_version: 4
210
+ summary: cartage-remote is a plug-in for {cartage}[https://github.com/KineticCafe/cartage]
211
+ to build a package on a remote machine with cartage
212
+ test_files: []