revup 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2012 Eloy Duran <eloy@fngtps.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,150 @@
1
+ require 'rake/tasklib'
2
+ require 'net/ssh'
3
+ require 'net/scp'
4
+ require 'logger'
5
+
6
+ require 'revup/version'
7
+
8
+ module Revup
9
+ class DeployTask < Rake::TaskLib
10
+ DEFAULT_TO_CLASS_ATTRS = [:host, :app_dir, :remote_setup, :files_root, :logger, :local_tmp_dir, :remote_tmp_dir]
11
+ class << self
12
+ attr_accessor *DEFAULT_TO_CLASS_ATTRS
13
+ end
14
+
15
+ self.local_tmp_dir = self.remote_tmp_dir = '/tmp'
16
+
17
+ self.logger = Logger.new(STDOUT)
18
+ logger.level = Logger::INFO
19
+ logger.progname = "revup (#{VERSION})"
20
+
21
+ attr_accessor :component_name
22
+
23
+ attr_accessor :component_name_and_prerequisites
24
+
25
+ attr_accessor :files_root, :files
26
+
27
+ attr_accessor :host
28
+
29
+ attr_accessor :app_dir
30
+
31
+ attr_accessor :revision
32
+
33
+ attr_accessor :local_tmp_dir, :remote_tmp_dir
34
+
35
+ attr_accessor :remote_setup
36
+
37
+ attr_accessor :logger
38
+
39
+ def initialize(component_name_and_prerequisites)
40
+ DEFAULT_TO_CLASS_ATTRS.each do |attr|
41
+ send("#{attr}=", self.class.send(attr))
42
+ end
43
+
44
+ @component_name_and_prerequisites = component_name_and_prerequisites
45
+ @component_name = @component_name_and_prerequisites.is_a?(Hash) ?
46
+ @component_name_and_prerequisites.keys.first : @component_name_and_prerequisites
47
+
48
+ yield self if block_given?
49
+ define
50
+ end
51
+
52
+ def revision
53
+ @revision ||= begin
54
+ result = sh("git rev-parse --short HEAD 2>&1")
55
+ result unless result.empty?
56
+ end
57
+ end
58
+
59
+ def archive_basename
60
+ "#{@component_name}-#{@revision}"
61
+ end
62
+
63
+ def local_archive_path
64
+ File.join(@local_tmp_dir, "#{archive_basename}.tgz")
65
+ end
66
+
67
+ def remote_archive_path
68
+ File.join(@remote_tmp_dir, "#{archive_basename}.tgz")
69
+ end
70
+
71
+ def remote_archive_dir
72
+ File.join(@remote_tmp_dir, archive_basename)
73
+ end
74
+
75
+ # Actual task definition
76
+
77
+ def define
78
+ desc "Deploy build of the `#{@component_name}' component"
79
+ task(@component_name_and_prerequisites) do
80
+ deploy
81
+ end
82
+ end
83
+
84
+ def deploy
85
+ validate files_root, "Please specify the location of the root of the files that should be deployed."
86
+ validate files, "Please specify a list of files that should be deployed."
87
+ validate host, "Please specify the host of the machine to deploy to."
88
+ validate app_dir, "Please specify the path to the application."
89
+ validate revision, "Please specify the Git revision hash."
90
+
91
+ create_archive
92
+ upload_and_register
93
+
94
+ rescue Object => e
95
+ @logger.error("#{e.message}\n\t#{e.backtrace.join("\n\t")}")
96
+ raise e
97
+ end
98
+
99
+ def create_archive
100
+ sh "mkdir -p '#{@local_tmp_dir}'"
101
+ sh "tar -C '#{@files_root}' -zcf '#{local_archive_path}' '#{@files.sort.join("' '")}'"
102
+ end
103
+
104
+ def upload_and_register
105
+ Net::SSH.start(@host, ENV['USER']) do |connection|
106
+ @ssh = connection
107
+
108
+ ssh "mkdir -p '#{remote_archive_dir}'"
109
+ # Upload archive
110
+ @logger.info("Transferring `#{local_archive_path}' to `#{@host}:#{remote_archive_path}'")
111
+ @ssh.scp.upload!(local_archive_path, remote_archive_path)
112
+ # Unpack archive
113
+ ssh "tar -C '#{remote_archive_dir}' -zxf '#{remote_archive_path}'"
114
+ # Register revision
115
+ ssh "cd '#{@app_dir}' && bundle exec ./script/register_component_revision '#{remote_archive_dir}' '#{component_name}' '#{revision}'"
116
+
117
+ cleanup!
118
+ end
119
+ @ssh = nil
120
+ end
121
+
122
+ def cleanup!
123
+ sh "rm -f '#{local_archive_path}'"
124
+ ssh "rm -f '#{remote_archive_path}'"
125
+ ssh "rm -rf '#{remote_archive_dir}'"
126
+ end
127
+
128
+ private
129
+
130
+ def validate(value, message)
131
+ raise message if value.nil? || value.empty?
132
+ end
133
+
134
+ def sh(cmd)
135
+ @logger.info("[local] executing: #{cmd}")
136
+ result = `#{cmd} 2>&1`.strip
137
+ raise "Failed to execute: #{result}" unless $?.success?
138
+ @logger.info("[local] output: #{result}") unless result.empty?
139
+ result
140
+ end
141
+
142
+ def ssh(cmd)
143
+ cmd = "#{remote_setup}; #{cmd}" if remote_setup
144
+ @logger.info("[remote] executing: #{cmd}")
145
+ if result = @ssh.exec!(cmd)
146
+ @logger.info("[remote] output: #{result}")
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,3 @@
1
+ module Revup
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: revup
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Eloy Duran
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-01-12 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: net-ssh
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 3
30
+ - 0
31
+ version: 2.3.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: net-scp
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 0
44
+ - 4
45
+ version: 1.0.4
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 2
57
+ - 8
58
+ - 0
59
+ version: 2.8.0
60
+ type: :development
61
+ version_requirements: *id003
62
+ description:
63
+ email:
64
+ - eloy@fngtps.com
65
+ - martin@sauspiel.de
66
+ executables: []
67
+
68
+ extensions: []
69
+
70
+ extra_rdoc_files: []
71
+
72
+ files:
73
+ - lib/revup/deploy_task.rb
74
+ - lib/revup/version.rb
75
+ - LICENSE
76
+ has_rdoc: true
77
+ homepage:
78
+ licenses:
79
+ - MIT
80
+ post_install_message:
81
+ rdoc_options: []
82
+
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.3.6
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: A simple deploy tool, packaged as a rake task. Currently targeted for sauspiel.de
106
+ test_files: []
107
+