pushwagner 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .idea
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@pw --create
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'pry'
7
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ pushwagner (0.0.1)
5
+ net-scp
6
+ net-ssh
7
+ nokogiri (~> 1.5)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ coderay (1.0.8)
13
+ diff-lcs (1.1.3)
14
+ method_source (0.8.1)
15
+ net-scp (1.0.4)
16
+ net-ssh (>= 1.99.1)
17
+ net-ssh (2.6.1)
18
+ nokogiri (1.5.5)
19
+ pry (0.9.10)
20
+ coderay (~> 1.0.5)
21
+ method_source (~> 0.8)
22
+ slop (~> 3.3.1)
23
+ rake (0.9.5)
24
+ rspec (2.12.0)
25
+ rspec-core (~> 2.12.0)
26
+ rspec-expectations (~> 2.12.0)
27
+ rspec-mocks (~> 2.12.0)
28
+ rspec-core (2.12.0)
29
+ rspec-expectations (2.12.0)
30
+ diff-lcs (~> 1.1.3)
31
+ rspec-mocks (2.12.0)
32
+ slop (3.3.3)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ bundler (~> 1.0)
39
+ pry
40
+ pushwagner!
41
+ rake (~> 0.9)
42
+ rspec (~> 2.11)
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ task :spec do
4
+ exec "rspec --color --format=documentation spec"
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :spec
data/bin/pw ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pushwagner'
4
+
5
+ def get_version
6
+ puts "You must specify which version you wish to deploy: "
7
+ STDIN.gets.strip
8
+ end
9
+
10
+ # TODO: detect version requirement from config
11
+ version = 1 # ENV["VERSION"] || get_version
12
+
13
+ main = Pushwagner::Main.new(:config_file => 'config/deploy.yml', :version => version, :environment => 'staging')
14
+
15
+ # TODO: detect cli from config
16
+ case ARGV[0]
17
+ when "deploy"
18
+ main.deploy
19
+ main.restart
20
+
21
+ when "restart"
22
+ main.restart
23
+
24
+ else
25
+ puts "Usage: pw <deploy|restart>"
26
+ end
@@ -0,0 +1,56 @@
1
+ require 'pushwagner/ext'
2
+ require 'pushwagner/maven'
3
+
4
+ module Pushwagner
5
+
6
+ class Environment
7
+ attr_reader :config
8
+ attr_accessor :current, :version
9
+
10
+ def initialize(opts = {})
11
+ opts = HashWithIndifferentAccess.new(opts)
12
+
13
+ config_file = opts[:config_file] || File.join(File.dirname(__FILE__), '/config/deploy.yml')
14
+ @version = opts[:version]
15
+ @current = opts[:environment] || 'development'
16
+
17
+ @config = HashWithIndifferentAccess.new(YAML::load_file(config_file) || {})
18
+ end
19
+
20
+ def path_prefix
21
+ config['path_prefix'] || '/srv/www'
22
+ end
23
+
24
+ def maven
25
+ @maven = config['maven'] ? Maven.new(config['maven'], version) : {}
26
+ end
27
+
28
+ def maven?
29
+ maven.any?
30
+ end
31
+
32
+ def static
33
+ config['static'] || {}
34
+ end
35
+
36
+ def static?
37
+ static.any?
38
+ end
39
+
40
+ def environments
41
+ config['environments'] || {}
42
+ end
43
+
44
+ def environment
45
+ environments[current] || {}
46
+ end
47
+
48
+ def hosts
49
+ environment['hosts'] || []
50
+ end
51
+
52
+ def user
53
+ environment['user'] || "nobody"
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,59 @@
1
+ module Pushwagner
2
+ class HashWithIndifferentAccess < ::Hash
3
+ def initialize(hash={})
4
+ super()
5
+ hash.each do |key, value|
6
+ self[convert_key(key)] = value
7
+ end
8
+ end
9
+
10
+ def [](key)
11
+ super(convert_key(key))
12
+ end
13
+
14
+ def []=(key, value)
15
+ super(convert_key(key), value)
16
+ end
17
+
18
+ def delete(key)
19
+ super(convert_key(key))
20
+ end
21
+
22
+ def values_at(*indices)
23
+ indices.collect { |key| self[convert_key(key)] }
24
+ end
25
+
26
+ def merge(other)
27
+ dup.merge!(other)
28
+ end
29
+
30
+ def merge!(other)
31
+ other.each do |key, value|
32
+ self[convert_key(key)] = value
33
+ end
34
+ self
35
+ end
36
+
37
+ def to_hash
38
+ Hash.new(default).merge!(self)
39
+ end
40
+
41
+ protected
42
+ def convert_key(key)
43
+ key.is_a?(Symbol) ? key.to_s : key
44
+ end
45
+
46
+ def method_missing(method, *args, &block)
47
+ method = method.to_s
48
+ if method =~ /^(\w+)\?$/
49
+ if args.empty?
50
+ !!self[$1]
51
+ else
52
+ self[$1] == args.first
53
+ end
54
+ else
55
+ self[method]
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,25 @@
1
+ module Pushwagner
2
+
3
+ class Main
4
+ def initialize(opts = {})
5
+ @environment = Pushwagner::Environment.new(opts)
6
+ end
7
+
8
+ def set_environment(env)
9
+ @environment.current = env.to_s
10
+ end
11
+
12
+ def set_version(version)
13
+ @environment.version = version
14
+ end
15
+
16
+ def deploy(opts = {})
17
+ Maven::Deployer.new(@environment, opts).deploy
18
+ Static::Deployer.new(@environment, opts).deploy
19
+ end
20
+
21
+ def restart(opts = {})
22
+ Supervisord::Restarter.new(@environment, opts).restart
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,142 @@
1
+ require 'net/https'
2
+ require 'net/ssh'
3
+ require 'net/scp'
4
+ require 'open-uri'
5
+ require 'nokogiri'
6
+
7
+ module Pushwagner
8
+ class Maven
9
+
10
+ attr_reader :repository, :artifacts
11
+ def initialize(maven, version)
12
+ return if !maven or maven.empty?
13
+
14
+ @version = version || required("Deployment version for artifacts is required")
15
+ @repository = Repository.new(maven['repositories'])
16
+ @artifacts = Hash[(maven['artifacts'] || {}).map { |k,h| [k, Artifact.new(h['artifact_id'], h['group_id'], h['version'] || version)] }]
17
+ end
18
+
19
+ def required(msg)
20
+ raise StandardError.new(msg)
21
+ end
22
+ end
23
+
24
+ class Maven::Artifact
25
+ attr_reader :artifact_id, :group_id, :version
26
+
27
+ def initialize(artifact_id, group_id, version)
28
+ @artifact_id = artifact_id
29
+ @group_id = group_id
30
+ @version = version
31
+ end
32
+
33
+ def base_path
34
+ "#{group_id.gsub('.', '/')}/#{artifact_id.gsub('.', '/')}/#{version}"
35
+ end
36
+
37
+ def jar_name
38
+ "#{artifact_id}-#{version}.jar"
39
+ end
40
+
41
+ def jar_path
42
+ "#{base_path}/#{jar_name}"
43
+ end
44
+
45
+ def snapshot?
46
+ version.downcase =~ /snapshot/
47
+ end
48
+
49
+ end
50
+
51
+ class Maven::Repository
52
+ attr_reader :snapshots_url
53
+ attr_reader :releases_url
54
+
55
+ def initialize(repositories)
56
+ required(repositories, "repositories configuration required")
57
+ required(repositories['snapshots'], "snapshots repository required")
58
+ required(repositories['releases'], "releases repository required")
59
+
60
+ @snapshots_url = repositories['snapshots']
61
+ @releases_url = repositories['releases']
62
+ end
63
+
64
+ def absolute_url(artifact)
65
+ if artifact.snapshot?
66
+ doc = Nokogiri::XML(open(URI.parse("#{snapshots_url}/#{artifact.base_path}/maven-metadata.xml"), :http_basic_authentication => authentication(false)))
67
+ snapshot_version = doc.xpath("//metadata/versioning/snapshotVersions/snapshotVersion/value/text()").first.content
68
+ return "#{snapshots_url}/#{artifact.base_path}/#{artifact.artifact_id}-#{snapshot_version}.jar"
69
+ end
70
+
71
+ "#{releases_url}/#{artifact.jar_path}"
72
+ end
73
+
74
+ def authentication(snapshots = false)
75
+ @settings_file ||= ENV['M2_HOME'] ? "#{ENV['M2_HOME']}/conf/settings.xml" : "#{ENV['HOME']}/.m2/settings.xml"
76
+
77
+ if File.exists?(@settings_file)
78
+ Nokogiri::XML(open(@settings_file)).css("settings servers server").each do |n|
79
+ return "#{n.css("username").text}:#{n.css("password").text}" if n.css("id").text == (snapshots ? 'snapshots' : 'releases')
80
+ end
81
+ end
82
+ ""
83
+ end
84
+
85
+ def required(exp, message)
86
+ raise StandardError.new(message) unless exp
87
+ end
88
+
89
+ end
90
+
91
+ #
92
+ # Deployer strategy for maven repos (wip).
93
+ #
94
+ class Maven::Deployer
95
+
96
+ attr_reader :environment, :artifacts, :repository
97
+
98
+ def initialize(env, opts = {})
99
+ @environment = env
100
+ # TODO: nil-object instead?
101
+ @artifacts = env.maven? ? env.maven.artifacts : {}
102
+ @repository = env.maven? ? env.maven.repository : nil
103
+ end
104
+
105
+ def deploy
106
+ artifacts.each do |name, artifact|
107
+ environment.hosts.each do |host|
108
+ mark_previous(name, host)
109
+ pull_artifact(name, artifact, host)
110
+ mark_new(name, artifact, host)
111
+ end
112
+ end
113
+ true # false if failed
114
+ end
115
+
116
+ protected
117
+
118
+ def pull_artifact(name, artifact, host)
119
+ Net::SSH.start(host, environment.user) do |ssh|
120
+ puts "Pulling #{repository.absolute_url(artifact)} to #{host}:#{environment.path_prefix}/#{artifact.jar_name}..."
121
+ ssh.exec("curl --user '#{repository.authentication(artifact.snapshot?)}' #{repository.absolute_url(artifact)} > #{environment.path_prefix}/#{artifact.jar_name}")
122
+ end
123
+ end
124
+
125
+ def mark_previous(name, host)
126
+ Net::SSH.start(host, user) do |ssh|
127
+ puts "Marking previous release on #{host}..."
128
+ ssh.exec("cp -P #{environment.path_prefix}/#{name}.jar #{environment.path_prefix}/#{name}.previous.jar")
129
+ end
130
+ end
131
+
132
+ def mark_new(name, artifact, host)
133
+ Net::SSH.start(host, user) do |ssh|
134
+ cwd = deploy_path(app_name)
135
+ puts "Marking #{artifact.jar_name} as current on #{host}..."
136
+ ssh.exec("ln -sf #{environment.path_prefix}/#{artifact.jar_name} #{environment.path_prefix}/#{name}.jar")
137
+ end
138
+ end
139
+
140
+ end
141
+ ##
142
+ end
@@ -0,0 +1,33 @@
1
+ require 'net/ssh'
2
+ require 'net/scp'
3
+
4
+ module Pushwagner
5
+ module Static
6
+ class Deployer
7
+ attr_reader :environment
8
+
9
+ def initialize(environment, opts = {})
10
+ @environment = environment
11
+ end
12
+
13
+ def deploy
14
+ environment.static.each do |name, files|
15
+ environment.hosts.each do |host|
16
+ Net::SCP.start(host, environment.user) do |scp|
17
+ puts "Uploading files to #{host}:#{environment.path_prefix}/#{name}/"
18
+ files.each do |f|
19
+ if File.exists?(f)
20
+ scp.upload!(f, "#{environment.path_prefix}/#{name}/", :recursive => File.directory?(f))
21
+ else
22
+ puts "Warning: File #{f} does not exist"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ # EOC
30
+ end
31
+ # EOM
32
+ end
33
+ end
@@ -0,0 +1,14 @@
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
@@ -0,0 +1,3 @@
1
+ module Pushwagner
2
+ VERSION = "0.0.1"
3
+ end
data/lib/pushwagner.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'pushwagner/ext'
2
+ require 'pushwagner/environment'
3
+ require 'pushwagner/maven'
4
+ require 'pushwagner/static'
5
+ require 'pushwagner/supervisord'
6
+ require 'pushwagner/main'
@@ -0,0 +1,32 @@
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
+ require 'pushwagner/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'pushwagner'
6
+ s.version = Pushwagner::VERSION
7
+ s.date = Time.now.strftime("%Y-%m-%d")
8
+
9
+ s.description = "Simple remote automation wrapper."
10
+ s.summary = "Simple remote automation wrapper (wip)."
11
+
12
+ s.authors = ["Ole Christian Rynning"]
13
+ s.email = 'oc@rynning.no'
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files spec`.split("\n")
17
+ s.licenses = ['MIT']
18
+ s.homepage = 'http://rubygems.org/gems/pushwagner'
19
+ s.executables = ['pw']
20
+ s.require_paths = ['lib']
21
+
22
+ s.required_rubygems_version = Gem::Requirement.new('>= 1.3.6')
23
+
24
+ s.add_runtime_dependency 'net-ssh'
25
+ s.add_runtime_dependency 'net-scp'
26
+ s.add_runtime_dependency 'nokogiri', '~> 1.5'
27
+
28
+ s.add_development_dependency 'bundler', '~> 1.0'
29
+ s.add_development_dependency 'rake', '~> 0.9'
30
+ s.add_development_dependency 'rspec', '~> 2.11'
31
+
32
+ end
@@ -0,0 +1 @@
1
+ # empty.
@@ -0,0 +1,26 @@
1
+ path_prefix: /full/path
2
+
3
+ maven:
4
+ repositories:
5
+ releases: http://foo.mu/nexus/content/repositories/releases
6
+ snapshots: http://foo.mu/nexus/content/repositories/snapshots
7
+ artifacts:
8
+ bubble-api:
9
+ group_id: double
10
+ artifact_id: trouble-api
11
+ bubble-notifier:
12
+ group_id: double
13
+ artifact_id: trouble-notifier
14
+
15
+ static:
16
+ diakonhjemmet.uppercase.no:
17
+ - index.htm
18
+ - static
19
+
20
+ environments:
21
+ staging:
22
+ hosts: [staging.uppercase.no]
23
+ user: www-data
24
+ production:
25
+ hosts: [prod1.uppercase.no]
26
+ user: www-data
@@ -0,0 +1,24 @@
1
+ <metadata modelVersion="1.1.0">
2
+ <groupId>bar</groupId>
3
+ <artifactId>foo</artifactId>
4
+ <version>1.0-SNAPSHOT</version>
5
+ <versioning>
6
+ <snapshot>
7
+ <timestamp>20121114.152717</timestamp>
8
+ <buildNumber>3</buildNumber>
9
+ </snapshot>
10
+ <lastUpdated>20121114152717</lastUpdated>
11
+ <snapshotVersions>
12
+ <snapshotVersion>
13
+ <extension>jar</extension>
14
+ <value>1.0-20121114.152717-3</value>
15
+ <updated>20121114152717</updated>
16
+ </snapshotVersion>
17
+ <snapshotVersion>
18
+ <extension>pom</extension>
19
+ <value>1.0-20121114.152717-3</value>
20
+ <updated>20121114152717</updated>
21
+ </snapshotVersion>
22
+ </snapshotVersions>
23
+ </versioning>
24
+ </metadata>
@@ -0,0 +1,19 @@
1
+ path_prefix: /var/www
2
+
3
+ maven:
4
+ repositories:
5
+ releases: http://w00t.uppercase.no/nexus/content/repositories/releases
6
+ snapshots: http://w00t.uppercase.no/nexus/content/repositories/snapshots
7
+ artifacts:
8
+ some-api:
9
+ group_id: uppercase
10
+ artifact_id: uc-api
11
+ some-notifier:
12
+ group_id: uppercase
13
+ artifact_id: uc-notifier
14
+ version: 1.0final
15
+
16
+ environments:
17
+ simple:
18
+ hosts: [simple.uppercase.no]
19
+ user: www-data
@@ -0,0 +1,14 @@
1
+ <settings>
2
+ <servers>
3
+ <server>
4
+ <id>releases</id>
5
+ <username>foo</username>
6
+ <password>bar</password>
7
+ </server>
8
+ <server>
9
+ <id>snapshots</id>
10
+ <username>bar</username>
11
+ <password>baz</password>
12
+ </server>
13
+ </servers>
14
+ </settings>
@@ -0,0 +1,11 @@
1
+ path_prefix: /static/path
2
+
3
+ static:
4
+ diakonhjemmet.uppercase.no:
5
+ - index.htm
6
+ - static
7
+
8
+ environments:
9
+ www:
10
+ hosts: [www.uppercase.no, www2.uppercase.no]
11
+ user: www-data
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'pushwagner/environment'
3
+
4
+ describe Pushwagner::Environment do
5
+ describe "#initialize" do
6
+ it "requires config_file" do
7
+ expect { Pushwagner::Environment.new('config_file' => File.join(config_root, 'nonexisting.yml'))}.to raise_error
8
+ end
9
+
10
+ it "supports config_file" do
11
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'full.yml'))
12
+ expect(env.path_prefix).to eq("/full/path")
13
+ end
14
+
15
+ it "supports :config_file" do
16
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'static.yml'))
17
+ expect(env.path_prefix).to eq("/static/path")
18
+ end
19
+
20
+ it "supports :version" do
21
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'full.yml'), :version => "1.3.3.7")
22
+ expect(env.version).to eq("1.3.3.7")
23
+ end
24
+ end
25
+ describe "#maven" do
26
+ it "requires a version" do
27
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'maven.yml'))
28
+ expect { env.maven }.to raise_error(StandardError, "Deployment version for artifacts is required")
29
+ end
30
+
31
+ it "returns empty hash when not configured" do
32
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'static.yml'), :version => "1foo" )
33
+ expect(env.maven?).to be_false
34
+ expect(env.maven).to eq({})
35
+ end
36
+ end
37
+ describe "#static" do
38
+ it "returns empty hash when not configured" do
39
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'maven.yml'), :version => "1foo" )
40
+ expect(env.static?).to be_false
41
+ expect(env.static).to eq({})
42
+ end
43
+ it "is a hash with files" do
44
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'static.yml'))
45
+ expect(env.static).to eq({'diakonhjemmet.uppercase.no' => ['index.htm', 'static']})
46
+ end
47
+ end
48
+ describe "#environments" do
49
+ it "returns all environments" do
50
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'full.yml'), :version => "1foo" )
51
+ expect(env.environments.size).to eq(2)
52
+ end
53
+ end
54
+ describe "#environment" do
55
+ it "returns empty environment if it doesn't exist" do
56
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'full.yml'), :version => "1foo" )
57
+ expect(env.environment).to eq({})
58
+ end
59
+ it "returns environment if it exists" do
60
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'full.yml'), :version => "1foo", :environment => "staging")
61
+ expect(env.environment).to eq({'hosts' => ["staging.uppercase.no"], 'user' => "www-data"})
62
+ end
63
+ end
64
+ describe "#hosts" do
65
+ it "returns empty list if it doesn't exist" do
66
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'empty.yml'), :version => "1foo" )
67
+ expect(env.hosts).to eq([])
68
+ end
69
+ it "returns environment if it exists" do
70
+ env = Pushwagner::Environment.new(:config_file => File.join(config_root, 'full.yml'), :version => "1foo", :environment => "staging")
71
+ expect(env.environment).to eq({'hosts' => ["staging.uppercase.no"], 'user' => "www-data"})
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,104 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'pushwagner/environment'
3
+
4
+ describe Pushwagner::Maven do
5
+ let(:cfg) {YAML::load_file(File.join(config_root, 'maven.yml'))['maven']}
6
+
7
+ describe "#initialize" do
8
+ it "requires a version" do
9
+ expect { Pushwagner::Maven.new(cfg, nil) }.to raise_error(StandardError, "Deployment version for artifacts is required")
10
+ end
11
+
12
+ it "trickles the version down to artifacts" do
13
+ m = Pushwagner::Maven.new(cfg, "1foo")
14
+ expect(m.artifacts["some-api"].version).to eq("1foo")
15
+ end
16
+
17
+ it "allows stable versions on artifacts" do
18
+ m = Pushwagner::Maven.new(cfg, "1bar")
19
+ expect(m.artifacts["some-notifier"].version).to eq("1.0final")
20
+ end
21
+
22
+ it "returns nil-object maven when not configured" do
23
+ m = Pushwagner::Maven.new({}, "1baz")
24
+ expect(m.artifacts).to be_nil
25
+ expect(m).to_not be_nil
26
+ end
27
+
28
+ describe "initialization of artifacts" do
29
+ it "handles no artifacts" do
30
+ cfg.delete('artifacts')
31
+ m = Pushwagner::Maven.new(cfg, "1bar")
32
+ expect(m.artifacts.size).to eq(0)
33
+ end
34
+ it "parses two artifacts" do
35
+ m = Pushwagner::Maven.new(cfg, "1bar")
36
+ expect(m.artifacts.size).to eq(2)
37
+ expect(m.artifacts.keys.first).to eq("some-api")
38
+ expect(m.artifacts.keys.last).to eq("some-notifier")
39
+ end
40
+ end
41
+
42
+ describe "initialization of repositories" do
43
+ it "requires snapshots repository" do
44
+ cfg.delete('repositories')
45
+ expect {Pushwagner::Maven.new(cfg, "1")}.to raise_error(StandardError)
46
+ end
47
+ it "requires snapshots repository" do
48
+ cfg['repositories'].delete('snapshots')
49
+ expect {Pushwagner::Maven.new(cfg, "1")}.to raise_error(StandardError)
50
+ end
51
+ it "requires releases repository" do
52
+ cfg['repositories'].delete('releases')
53
+ expect {Pushwagner::Maven.new(cfg, "1")}.to raise_error(StandardError)
54
+ end
55
+ it "parses repository" do
56
+ m = Pushwagner::Maven.new(cfg, "1")
57
+ expect(m.repository.snapshots_url).to eq("http://w00t.uppercase.no/nexus/content/repositories/snapshots")
58
+ expect(m.repository.releases_url).to eq("http://w00t.uppercase.no/nexus/content/repositories/releases")
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "repositories" do
64
+ let(:settings) {IO.read(File.join(config_root, 'settings.xml'))}
65
+
66
+ it "reads releases authentication from maven settings.xml" do
67
+ m = Pushwagner::Maven.new(cfg, "1")
68
+ m.repository.should_receive(:open).
69
+ with(/.*settings.xml$/).
70
+ and_return(settings)
71
+
72
+ expect(m.repository.authentication).to eq("foo:bar")
73
+ end
74
+
75
+ it "reads snapshots authentication from maven settings.xml" do
76
+ m = Pushwagner::Maven.new(cfg, "1")
77
+ m.repository.should_receive(:open).
78
+ with(/.*settings.xml$/).
79
+ and_return(settings)
80
+
81
+ expect(m.repository.authentication(true)).to eq("bar:baz")
82
+ end
83
+
84
+ let(:metadata) {IO.read(File.join(config_root, 'maven-metadata.xml'))}
85
+
86
+ it "builds maven2-repo-style urls and retrieves metadata" do
87
+ m = Pushwagner::Maven.new(cfg, "1")
88
+
89
+ m.repository.should_receive(:authentication).and_return("")
90
+ m.repository.should_receive(:open).and_return(metadata)
91
+
92
+ snapshot = Pushwagner::Maven::Artifact.new("foo", "bar", "1.0-SNAPSHOT")
93
+ expect(m.repository.absolute_url(snapshot)).to eq("http://w00t.uppercase.no/nexus/content/repositories/snapshots/bar/foo/1.0-SNAPSHOT/foo-1.0-20121114.152717-3.jar")
94
+ end
95
+
96
+ it "builds maven2-repo-style urls for release artifacts" do
97
+ m = Pushwagner::Maven.new(cfg, "1")
98
+ release = Pushwagner::Maven::Artifact.new("foo", "bar", "1.0")
99
+ expect(m.repository.absolute_url(release)).to eq("http://w00t.uppercase.no/nexus/content/repositories/releases/bar/foo/1.0/foo-1.0.jar")
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,19 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
+ require 'pushwagner'
3
+ require 'stringio'
4
+
5
+ require 'rspec'
6
+ require 'diff/lcs'
7
+
8
+ RSpec.configure do |config|
9
+ config.before do
10
+ ARGV.replace []
11
+ end
12
+
13
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
14
+
15
+ def config_root
16
+ File.join(File.dirname(__FILE__), 'configs')
17
+ end
18
+
19
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pushwagner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ole Christian Rynning
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: net-ssh
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: net-scp
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: nokogiri
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.5'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.5'
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '0.9'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '0.9'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '2.11'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '2.11'
110
+ description: Simple remote automation wrapper.
111
+ email: oc@rynning.no
112
+ executables:
113
+ - pw
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - .gitignore
118
+ - .rvmrc
119
+ - Gemfile
120
+ - Gemfile.lock
121
+ - Rakefile
122
+ - bin/pw
123
+ - lib/pushwagner.rb
124
+ - lib/pushwagner/environment.rb
125
+ - lib/pushwagner/ext.rb
126
+ - lib/pushwagner/main.rb
127
+ - lib/pushwagner/maven.rb
128
+ - lib/pushwagner/static.rb
129
+ - lib/pushwagner/supervisord.rb
130
+ - lib/pushwagner/version.rb
131
+ - pushwagner.gemspec
132
+ - spec/configs/empty.yml
133
+ - spec/configs/full.yml
134
+ - spec/configs/maven-metadata.xml
135
+ - spec/configs/maven.yml
136
+ - spec/configs/settings.xml
137
+ - spec/configs/static.yml
138
+ - spec/environment_spec.rb
139
+ - spec/maven_spec.rb
140
+ - spec/spec_helper.rb
141
+ homepage: http://rubygems.org/gems/pushwagner
142
+ licenses:
143
+ - MIT
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ none: false
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: 1.3.6
160
+ requirements: []
161
+ rubyforge_project:
162
+ rubygems_version: 1.8.24
163
+ signing_key:
164
+ specification_version: 3
165
+ summary: Simple remote automation wrapper (wip).
166
+ test_files:
167
+ - spec/configs/empty.yml
168
+ - spec/configs/full.yml
169
+ - spec/configs/maven-metadata.xml
170
+ - spec/configs/maven.yml
171
+ - spec/configs/settings.xml
172
+ - spec/configs/static.yml
173
+ - spec/environment_spec.rb
174
+ - spec/maven_spec.rb
175
+ - spec/spec_helper.rb