cartage-remote 1.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 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: []