pushwagner 0.0.1.8 → 0.0.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1aded808749a511c913730aa48a8fe9c30bbdd6d
4
- data.tar.gz: 580c4d0976ddb634d044670855ed34a13feca64c
3
+ metadata.gz: 868b3ca9f8ea0c6060b4201bea0c4e23d6bb7925
4
+ data.tar.gz: 49f53b278d4c0e4a18ed8772b164ccfa5778be13
5
5
  SHA512:
6
- metadata.gz: 87ba43bea04f1d3c118f399c7f755f3716094b04b1d75fe99ecd34caaaab7e3684d36be7c822d85e60c80f007c21fa841395a198b2cd2b41b0c5cbf6c6f42cdc
7
- data.tar.gz: 7a300f0cc0ccf072a451bce9b7080e6d7cdf342ceab2c8aaa53766534920d23567e7ee1ffd806c0e32877e2e58ff473e95be479199d17d17caf0448b67db0aaa
6
+ metadata.gz: 0a66c0ddff6c4e93fb1b0891f2fefb45e9a33023c7657d7bd9a40d316a8fcc68fbc5d05c1d517a127fe8acbfe68bc24b5c97bdfd51870d36c45674fe3cfd2876
7
+ data.tar.gz: acf003c5a5355239a88202f015ca53abfe40b6a709f88d0858cb4d73d0a4297f448abc1a6aba6768b0cae57018a2151bad103750893449f98d38575457d73afe
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ pw
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.1.0
data/.travis.yml CHANGED
@@ -1,6 +1,3 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - jruby-18mode # JRuby in 1.8 mode
5
- - jruby-19mode # JRuby in 1.9 mode
6
- - 1.8.7
3
+ - 2.1.0
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
data/Gemfile.lock CHANGED
@@ -1,15 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pushwagner (0.0.1.7)
5
- net-scp
6
- net-ssh
7
- nokogiri (~> 1.6.4.1)
4
+ pushwagner (0.0.1.9)
5
+ colorize (~> 0.7)
6
+ net-scp (~> 1.2, >= 1.2.1)
7
+ net-ssh (~> 2.9, >= 2.9.1)
8
+ nokogiri (~> 1.6)
8
9
 
9
10
  GEM
10
- remote: http://rubygems.org/
11
+ remote: https://rubygems.org/
11
12
  specs:
12
13
  coderay (1.0.9)
14
+ colorize (0.7.3)
13
15
  diff-lcs (1.2.4)
14
16
  method_source (0.8.1)
15
17
  mini_portile (0.6.1)
@@ -37,8 +39,8 @@ PLATFORMS
37
39
  ruby
38
40
 
39
41
  DEPENDENCIES
40
- bundler (~> 1.7.6)
42
+ bundler (~> 1.7)
41
43
  pry
42
44
  pushwagner!
43
- rake (~> 10.1.0)
45
+ rake (~> 10.1)
44
46
  rspec
data/bin/pw CHANGED
@@ -3,7 +3,7 @@
3
3
  require 'pushwagner'
4
4
 
5
5
  def get_version
6
- puts "You must specify which version you wish to deploy: "
6
+ Pushwagner.info "You must specify which version you wish to deploy"
7
7
  STDIN.gets.strip
8
8
  end
9
9
 
@@ -18,11 +18,6 @@ main = Pushwagner::Main.new(:config_file => 'config/deploy.yml', :version => ver
18
18
  case ARGV[0]
19
19
  when "deploy"
20
20
  main.deploy
21
- main.restart
22
-
23
- when "restart"
24
- main.restart
25
-
26
21
  else
27
- puts "Usage: pw <deploy|restart> [environment]"
22
+ Pushwagner.warning "Usage: pw <deploy|todo> [environment]"
28
23
  end
@@ -14,7 +14,7 @@ module Pushwagner
14
14
  config_file = look_for_config_file(opts[:config_file])
15
15
 
16
16
  @version = opts[:version] && opts[:version].to_s
17
- @current = opts[:environment] || 'development'
17
+ @current = opts[:environment] || 'default'
18
18
 
19
19
  @config = HashWithIndifferentAccess.new(YAML::load_file(config_file) || {})
20
20
  end
@@ -43,6 +43,10 @@ module Pushwagner
43
43
  config['environments'] || {}
44
44
  end
45
45
 
46
+ def hooks
47
+ config['hooks'] || {}
48
+ end
49
+
46
50
  def environment
47
51
  environments[current] || {}
48
52
  end
@@ -1,5 +1,8 @@
1
- # Use colorize gem to color/fmt output
2
- require 'colorize'
1
+ class String
2
+ def trunc(sz)
3
+ self[0, sz]
4
+ end
5
+ end
3
6
 
4
7
  module Pushwagner
5
8
  # Shamefully copied from ActiveSupport
@@ -0,0 +1,133 @@
1
+ require 'net/https'
2
+ require 'net/ssh'
3
+ require 'net/scp'
4
+ require 'open-uri'
5
+ require 'nokogiri'
6
+
7
+ module Pushwagner
8
+
9
+ #
10
+ # Deployer strategy for maven repos (wip).
11
+ #
12
+ class Hooks
13
+
14
+ attr_reader :remote, :local
15
+
16
+ def initialize(env)
17
+ raise "Invalid environment" unless env
18
+ default_cfg = { before: [], after: [] }
19
+ @local = Hooks::Local.new(env, env.hooks['local'] || default_cfg)
20
+ @remote = Hooks::Remote.new(env, env.hooks['remote'] || default_cfg)
21
+ end
22
+
23
+ def run(target)
24
+ if target == :before
25
+ local.run(target)
26
+ remote.run(target)
27
+ elsif target == :after
28
+ local.run(target)
29
+ remote.run(target)
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ class Hooks::Remote
36
+
37
+ attr_reader :environment, :before, :after
38
+
39
+ def initialize(env, remote)
40
+ @environment = env
41
+
42
+ @before = remote['before'] || []
43
+ @after = remote['after'] || []
44
+ end
45
+
46
+ def run(target)
47
+ ssh_exec(method(target).call)
48
+ end
49
+
50
+ def gets_sudo_passwd
51
+ if ENV['PUSHWAGNER_SUDO']
52
+ @sudo = ENV['PUSHWAGNER_SUDO']
53
+ elsif @sudo.nil?
54
+ puts
55
+ Pushwagner.severe "<<< WARNING: this operation requires privileges >>>"
56
+ Pushwagner.warning "Enter Ctrl+C to abort."
57
+ print "Enter sudo-passwd: "
58
+
59
+ begin
60
+ system 'stty -echo'
61
+ rescue
62
+ # windoz
63
+ end
64
+ @sudo = STDIN.gets.chomp
65
+ puts
66
+ begin
67
+ system 'stty echo'
68
+ rescue
69
+ # windoz
70
+ end
71
+ end
72
+ @sudo
73
+ end
74
+
75
+ def ssh_exec(cmds)
76
+ environment.hosts.each do |host|
77
+ cmds.each do |cmd|
78
+ # Run each cmd in a separate 'transaction'
79
+ Pushwagner.begin_info "Executing `#{cmd}` on #{host}"
80
+
81
+ Net::SSH.start(host, environment.user) do |ssh|
82
+ ssh.open_channel do |ch|
83
+
84
+ ch.request_pty do |pty_ch, success|
85
+ raise "could not execute #{cmd}" unless success
86
+
87
+ ch.exec("#{cmd}")
88
+
89
+ ch.on_data do |data_ch, data|
90
+ if data =~ /\[sudo\] password/i
91
+ ch.send_data("#{gets_sudo_passwd}\n")
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ ssh.loop
98
+ end
99
+
100
+ Pushwagner.ok
101
+ end
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+
108
+ class Hooks::Local
109
+
110
+ attr_reader :environment, :before, :after
111
+
112
+ def initialize(env, local)
113
+ @environment = env
114
+ @before = local['before'] || []
115
+ @after = local['after'] || []
116
+ end
117
+
118
+ def run(target)
119
+ local_exec(method(target).call)
120
+ end
121
+
122
+ private
123
+ def local_exec(cmds)
124
+ cmds.each do |cmd|
125
+ Pushwagner.info "Executing `#{cmd}` locally..."
126
+
127
+ system("#{cmd}")
128
+
129
+ end
130
+ end
131
+
132
+ end
133
+ end
@@ -14,15 +14,18 @@ module Pushwagner
14
14
  end
15
15
 
16
16
  def deploy(opts = {})
17
- puts "Deploying to #{@environment.current} environment:"
18
- @environment.hosts.each { |h| puts " - #{@environment.user}@#{h}"}
17
+ Pushwagner.info "Starting deployment to environment: #{@environment.current}"
18
+ @environment.hosts.each { |h| Pushwagner.info " - #{@environment.user}@#{h}" }
19
+
20
+ pw_hooks = Hooks.new(@environment)
21
+ pw_hooks.run(:before)
19
22
 
20
23
  Maven::Deployer.new(@environment, opts).deploy if @environment.maven?
21
24
  Static::Deployer.new(@environment, opts).deploy if @environment.static?
22
- end
23
25
 
24
- def restart(opts = {})
25
- Supervisord::Restarter.new(@environment, opts).restart
26
+ pw_hooks.run(:after)
26
27
  end
28
+
27
29
  end
30
+
28
31
  end
@@ -57,6 +57,10 @@ module Pushwagner
57
57
  version.downcase =~ /snapshot/
58
58
  end
59
59
 
60
+ def to_s
61
+ "#{group_id}:#{artifact_id}:#{version}"
62
+ end
63
+
60
64
  end
61
65
 
62
66
  class Maven::Repository
@@ -116,10 +120,12 @@ module Pushwagner
116
120
  def deploy
117
121
  artifacts.each do |name, artifact|
118
122
  environment.hosts.each do |host|
123
+ Pushwagner.info "Deploying #{name}, #{artifact} to #{host}"
124
+
119
125
  mark_previous(name, host)
120
126
  pull_artifact(name, artifact, host)
121
127
  mark_new(name, artifact, host)
122
- puts "Deployed to #{name}, #{artifact} to #{host}: [ " + "OK".colorize(:green) + " ]"
128
+
123
129
  end
124
130
  end
125
131
  true # false if failed
@@ -129,22 +135,25 @@ module Pushwagner
129
135
 
130
136
  def pull_artifact(name, artifact, host)
131
137
  Net::SSH.start(host, environment.user) do |ssh|
132
- puts "Pulling #{repository.absolute_url(artifact)} to #{host}:#{environment.path_prefix}/#{artifact.jar_name}..."
138
+ Pushwagner.begin_info "Pulling #{repository.absolute_url(artifact)} to #{host}:#{environment.path_prefix}/#{artifact.jar_name}"
133
139
  ssh.exec("curl --user '#{repository.authentication(artifact.snapshot?)}' #{repository.absolute_url(artifact)} > #{environment.path_prefix}/#{name}/#{artifact.jar_name}")
140
+ Pushwagner.ok
134
141
  end
135
142
  end
136
143
 
137
144
  def mark_previous(name, host)
138
145
  Net::SSH.start(host, environment.user) do |ssh|
139
- puts "Marking previous release on #{host}..."
146
+ Pushwagner.begin_info "Marking previous release on #{host}"
140
147
  ssh.exec("cp -P #{environment.path_prefix}/#{name}/#{name}.jar #{environment.path_prefix}/#{name}/#{name}.previous.jar")
148
+ Pushwagner.ok
141
149
  end
142
150
  end
143
151
 
144
152
  def mark_new(name, artifact, host)
145
153
  Net::SSH.start(host, environment.user) do |ssh|
146
- puts "Marking #{artifact.jar_name} as current on #{host}..."
154
+ Pushwagner.begin_info "Marking #{artifact.jar_name} as current on #{host}"
147
155
  ssh.exec("ln -sf #{environment.path_prefix}/#{name}/#{artifact.jar_name} #{environment.path_prefix}/#{name}/#{name}.jar")
156
+ Pushwagner.ok
148
157
  end
149
158
  end
150
159
 
@@ -15,14 +15,19 @@ module Pushwagner
15
15
  environment.hosts.each do |host|
16
16
  Net::SCP.start(host, environment.user) do |scp|
17
17
  dest = name.start_with?('/') ? name : "#{environment.path_prefix}/#{name}/"
18
- puts "Uploading files to #{host}:#{dest}/"
18
+ Pushwagner.begin_info "Uploading files to #{host}:#{dest}"
19
+
19
20
  files.each do |f|
20
21
  if File.exists?(f)
21
22
  scp.upload!(f, dest, :recursive => File.directory?(f))
22
23
  else
23
- puts "Warning: File #{f} does not exist"
24
+ puts
25
+ Pushwagner.warning "Local file #{f} does not exist"
26
+ puts
24
27
  end
25
28
  end
29
+
30
+ Pushwagner.ok
26
31
  end
27
32
  end
28
33
  end
@@ -0,0 +1,25 @@
1
+ # Use colorize gem to color/fmt output
2
+ require 'colorize'
3
+
4
+ module Pushwagner
5
+ def self.ok
6
+ puts '[ ' + 'OK'.colorize(:green) + ' ]'
7
+ end
8
+
9
+ def self.severe(str)
10
+ puts str.trunc(99).colorize(color: :red, mode: :bold)
11
+ end
12
+
13
+ def self.begin_info(str)
14
+ print str.trunc(99).ljust(101, ".").colorize(mode: :bold)
15
+ end
16
+
17
+ def self.info(str)
18
+ puts str.trunc(99).colorize(mode: :bold)
19
+ end
20
+
21
+ def self.warning(str)
22
+ puts str.trunc(99).colorize(color: :yellow)
23
+ end
24
+
25
+ end
@@ -1,3 +1,3 @@
1
1
  module Pushwagner
2
- VERSION = "0.0.1.8"
2
+ VERSION = "0.0.1.10"
3
3
  end
data/lib/pushwagner.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'pushwagner/ext'
2
+ require 'pushwagner/util'
2
3
  require 'pushwagner/environment'
3
4
  require 'pushwagner/maven'
4
5
  require 'pushwagner/static'
5
- require 'pushwagner/supervisord'
6
+ require 'pushwagner/hooks'
6
7
  require 'pushwagner/main'
@@ -0,0 +1,18 @@
1
+ path_prefix: /static/path
2
+
3
+ hooks:
4
+ remote:
5
+ before:
6
+ - ls
7
+ - echo "foo"
8
+ local:
9
+ before:
10
+ - echo "one"
11
+ after:
12
+ - echo "two"
13
+ - echo "three"
14
+
15
+ environments:
16
+ default:
17
+ hosts: [www.uppercase.no, www2.uppercase.no]
18
+ user: www-data
@@ -0,0 +1,145 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'pushwagner/environment'
3
+
4
+ describe Pushwagner::Hooks do
5
+ #let(:cfg) {YAML::load_file(File.join(config_root, 'hooks.yml'))}
6
+
7
+ let(:env) { Pushwagner::Environment.new(config_file: File.join(config_root, 'hooks.yml')) }
8
+
9
+ describe "#initialize" do
10
+ it "raises error if invalid environment" do
11
+ expect { Pushwagner::Hooks.new(nil) }.to raise_exception
12
+ end
13
+
14
+ it "returns an empty config with an empty environment" do
15
+ sut = Pushwagner::Hooks.new(Pushwagner::Environment.new(config_file: File.join(config_root, 'empty.yml')))
16
+ expect(sut.local.before).to eq([])
17
+ expect(sut.local.after).to eq([])
18
+ expect(sut.remote.before).to eq([])
19
+ expect(sut.remote.after).to eq([])
20
+ end
21
+
22
+ it "returns a full working config" do
23
+ sut = Pushwagner::Hooks.new(env)
24
+ expect(sut.remote.before).to eq(['ls', 'echo "foo"'])
25
+ expect(sut.remote.after).to eq([])
26
+ expect(sut.local.before).to eq(['echo "one"'])
27
+ expect(sut.local.after).to eq(['echo "two"', 'echo "three"'])
28
+ end
29
+ end
30
+ describe "#run" do
31
+ it "requires an argument" do
32
+ sut = Pushwagner::Hooks.new(env)
33
+ expect { sut.run() }.to raise_exception
34
+ end
35
+
36
+ it "accepts run :after target" do
37
+ sut = Pushwagner::Hooks.new(env)
38
+
39
+ sut.stub_chain("local.run").with(:after).once
40
+ sut.stub_chain("remote.run").with(:after).once
41
+
42
+ sut.run(:after)
43
+ end
44
+
45
+ it "accepts run :before target" do
46
+ sut = Pushwagner::Hooks.new(env)
47
+
48
+ sut.stub_chain("local.run").with(:before).once
49
+ sut.stub_chain("remote.run").with(:before).once
50
+
51
+ sut.run(:before)
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ describe Pushwagner::Hooks::Local do
58
+ let(:env) { Pushwagner::Environment.new(config_file: File.join(config_root, 'hooks.yml')) }
59
+
60
+ describe "#initialize" do
61
+ it "returns an empty config without a config" do
62
+ sut = Pushwagner::Hooks::Local.new(env, env.hooks['local'])
63
+ expect(sut.before).to eq(['echo "one"'])
64
+ expect(sut.after).to eq(['echo "two"', 'echo "three"'])
65
+ end
66
+ end
67
+
68
+ describe "#run" do
69
+ it "requires an argument" do
70
+ sut = Pushwagner::Hooks::Local.new(env, env.hooks['local'])
71
+
72
+ expect { sut.run() }.to raise_exception
73
+ end
74
+ it "supports :before hooks" do
75
+ sut = Pushwagner::Hooks::Local.new(env, env.hooks['local'])
76
+
77
+ Pushwagner.stub(:info)
78
+ Pushwagner.stub(:begin_info)
79
+ Pushwagner.stub(:ok)
80
+
81
+ sut.should_receive(:system).with('echo "one"').once
82
+ sut.run(:before)
83
+ end
84
+ it "supports :after hooks" do
85
+ sut = Pushwagner::Hooks::Local.new(env, env.hooks['local'])
86
+
87
+ Pushwagner.stub(:info)
88
+ Pushwagner.stub(:begin_info)
89
+ Pushwagner.stub(:ok)
90
+
91
+ sut.should_receive(:system).with('echo "two"').once
92
+ sut.should_receive(:system).with('echo "three"').once
93
+ sut.run(:after)
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+ describe Pushwagner::Hooks::Remote do
100
+ let(:env) { Pushwagner::Environment.new(config_file: File.join(config_root, 'hooks.yml')) }
101
+
102
+ describe "#initialize" do
103
+ it "returns an empty config without a config" do
104
+ sut = Pushwagner::Hooks::Remote.new(env, env.hooks['remote'])
105
+ expect(sut.before).to eq(['ls', 'echo "foo"'])
106
+ expect(sut.after).to eq([])
107
+ end
108
+ end
109
+
110
+ describe "#run" do
111
+ it "requires an argument" do
112
+ sut = Pushwagner::Hooks::Remote.new(env, env.hooks['remote'])
113
+
114
+ expect { sut.run() }.to raise_exception
115
+ end
116
+
117
+ it "supports :before hooks" do
118
+ sut = Pushwagner::Hooks::Remote.new(env, env.hooks['remote'])
119
+
120
+ Pushwagner.stub(:info)
121
+ Pushwagner.stub(:begin_info)
122
+ Pushwagner.stub(:ok)
123
+
124
+ # Mock Net::SSH inner interaction smoke test
125
+ ssh = mock
126
+ ssh.should_receive(:open_channel).exactly(4).times
127
+ ssh.should_receive(:loop).exactly(4).times
128
+ Net::SSH.should_receive(:start).and_yield(ssh).exactly(4).times
129
+
130
+ sut.run(:before)
131
+ end
132
+
133
+ it "supports :after hooks" do
134
+ sut = Pushwagner::Hooks::Remote.new(env, env.hooks['remote'])
135
+
136
+ # Mock Net::SSH inner interaction smoke
137
+ ssh = mock
138
+ ssh.should_receive(:open_channel).never
139
+ Net::SSH.should_receive(:start).and_yield(ssh).never
140
+
141
+ sut.run(:after)
142
+ end
143
+ end
144
+
145
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pushwagner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.8
4
+ version: 0.0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ole Christian Rynning
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-20 00:00:00.000000000 Z
11
+ date: 2014-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-ssh
@@ -128,7 +128,8 @@ extensions: []
128
128
  extra_rdoc_files: []
129
129
  files:
130
130
  - ".gitignore"
131
- - ".rvmrc"
131
+ - ".ruby-gemset"
132
+ - ".ruby-version"
132
133
  - ".travis.yml"
133
134
  - Gemfile
134
135
  - Gemfile.lock
@@ -139,19 +140,22 @@ files:
139
140
  - lib/pushwagner.rb
140
141
  - lib/pushwagner/environment.rb
141
142
  - lib/pushwagner/ext.rb
143
+ - lib/pushwagner/hooks.rb
142
144
  - lib/pushwagner/main.rb
143
145
  - lib/pushwagner/maven.rb
144
146
  - lib/pushwagner/static.rb
145
- - lib/pushwagner/supervisord.rb
147
+ - lib/pushwagner/util.rb
146
148
  - lib/pushwagner/version.rb
147
149
  - pushwagner.gemspec
148
150
  - spec/configs/empty.yml
149
151
  - spec/configs/full.yml
152
+ - spec/configs/hooks.yml
150
153
  - spec/configs/maven-metadata.xml
151
154
  - spec/configs/maven.yml
152
155
  - spec/configs/settings.xml
153
156
  - spec/configs/static.yml
154
157
  - spec/environment_spec.rb
158
+ - spec/hooks_spec.rb
155
159
  - spec/maven_spec.rb
156
160
  - spec/spec_helper.rb
157
161
  homepage: http://rubygems.org/gems/pushwagner
@@ -181,10 +185,12 @@ summary: Simple remote automation wrapper (wip).
181
185
  test_files:
182
186
  - spec/configs/empty.yml
183
187
  - spec/configs/full.yml
188
+ - spec/configs/hooks.yml
184
189
  - spec/configs/maven-metadata.xml
185
190
  - spec/configs/maven.yml
186
191
  - spec/configs/settings.xml
187
192
  - spec/configs/static.yml
188
193
  - spec/environment_spec.rb
194
+ - spec/hooks_spec.rb
189
195
  - spec/maven_spec.rb
190
196
  - spec/spec_helper.rb
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm use 1.9.3@pw --create
@@ -1,14 +0,0 @@
1
- require 'net/ssh'
2
-
3
- module Pushwagner
4
- module Supervisord
5
- class Restarter
6
- def initialize(environment, opts = {})
7
- end
8
-
9
- def restart
10
- puts "..."
11
- end
12
- end
13
- end
14
- end