pushwagner 0.0.1.8 → 0.0.1.10

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