volley 0.1.0.alpha1

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.
@@ -0,0 +1,94 @@
1
+
2
+ module Volley
3
+ module Dsl
4
+ class Project
5
+ class << self
6
+ attr_reader :projects
7
+ def project(name, o={}, &block)
8
+ n = name.to_sym
9
+ @projects ||= {}
10
+ if @projects[n]
11
+ #raise "defining project #{name} more than once"
12
+ else
13
+ @projects[n] = new(n)
14
+ @projects[n].instance_eval &block if block_given?
15
+ end
16
+ @projects[n]
17
+ end
18
+
19
+ def get(name)
20
+ @projects[name.to_sym]
21
+ end
22
+
23
+ def config
24
+ Volley.config
25
+ end
26
+
27
+ def exists?(name)
28
+ n = name.to_sym
29
+ @projects.keys.include?(n)
30
+ end
31
+ end
32
+
33
+ attr_reader :plans
34
+ attr_reader :name
35
+ attr_reader :source
36
+
37
+ def initialize(name)
38
+ @name = name
39
+ @plans = {}
40
+ end
41
+
42
+ def config
43
+ @config ||= OpenStruct.new
44
+ end
45
+
46
+ def plan(name, o={}, &block)
47
+ n = name.to_sym
48
+ options = {
49
+ :project => self
50
+ }.merge(o)
51
+ if block_given?
52
+ @plans[n] ||= Volley::Dsl::Plan.new(name, options, &block)
53
+ end
54
+ @plans[n]
55
+ end
56
+
57
+ def plan?(name)
58
+ n = name.to_sym
59
+ @plans.keys.include?(n)
60
+ end
61
+
62
+ def scm(name, o={}, &block)
63
+ n = name.to_s
64
+ require "volley/scm/#{n}"
65
+ klass = "Volley::Scm::#{n.camelize}".constantize
66
+ @source = klass.new(o)
67
+ end
68
+
69
+ #def encrypt(tf, o={})
70
+ # options = {
71
+ # :enabled => tf,
72
+ # :overwrite => false,
73
+ # :key => "",
74
+ # }.merge(o)
75
+ # config.encrypt = OpenStruct.new(options)
76
+ #
77
+ # key = config.encrypt.key
78
+ # if File.file?(key)
79
+ # key = File.read(key).chomp
80
+ # end
81
+ #
82
+ # config.encrypt.key = key
83
+ #end
84
+ #
85
+ #def pack(tf, o={})
86
+ # options = {
87
+ # :enabled => tf,
88
+ # :type => "tgz",
89
+ # }.merge(o)
90
+ # config.pack = OpenStruct.new(options)
91
+ #end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,25 @@
1
+
2
+ module Volley
3
+ module Dsl
4
+ class Publisher
5
+ class << self
6
+ def publisher(name, o={}, &block)
7
+ n = name.to_sym
8
+
9
+ if @publisher
10
+ raise "only one publisher can be defined at a time"
11
+ else
12
+ klass = "Volley::Publisher::#{name.to_s.camelize}"
13
+ Volley::Log.info "loading publisher: #{name} (#{klass})" if Volley.config.debug
14
+ require "volley/publisher/#{name}"
15
+ @publisher = klass.constantize.new(o)
16
+ end
17
+ end
18
+
19
+ def get
20
+ @publisher
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
data/lib/volley/dsl.rb ADDED
@@ -0,0 +1,27 @@
1
+ d = "#{File.dirname(__FILE__)}/dsl/*"
2
+ Dir[d].select{|e| e =~ /\.rb$/}.each do |file|
3
+ f = file.gsub(/\.rb$/, '')
4
+ require f
5
+ end
6
+
7
+ module Volley
8
+ module Dsl
9
+ class << self
10
+ def publisher
11
+ Volley::Dsl::Publisher.get
12
+ end
13
+
14
+ def project(name)
15
+ Volley::Dsl::Project.get(name)
16
+ end
17
+
18
+ def project?(name)
19
+ Volley::Dsl::Project.exists?(name)
20
+ end
21
+
22
+ def projects
23
+ Volley::Dsl::Project.projects
24
+ end
25
+ end
26
+ end
27
+ end
data/lib/volley/log.rb ADDED
@@ -0,0 +1,31 @@
1
+ require "yell"
2
+
3
+ module Volley
4
+ class Log
5
+ class << self
6
+ def init
7
+ @loggers = []
8
+ @loggers << Yell.new(STDOUT, :level => [:info,:warn], :format => Yell::NoFormat)
9
+ @loggers << Yell.new(STDERR, :level => [:error,:fatal], :format => Yell::NoFormat)
10
+ end
11
+
12
+ def add(level, dest, format=Yell::DefaultFormat)
13
+ if [STDOUT,STDERR].include?(dest)
14
+ @loggers << Yell.new(dest, :level => level, :format => format)
15
+ else
16
+ @loggers << Yell.new(:datefile, dest, :level => level, :format => format,
17
+ :keep => 7, :symlink_original_filename => true)
18
+ end
19
+ end
20
+
21
+ %w{debug info warn error fatal}.each do |method_name|
22
+ class_eval(<<-METHOD_DEFN, __FILE__, __LINE__)
23
+ def #{method_name}(msg=nil, &block)
24
+ @loggers.each {|l| l.#{method_name}(msg, &block) }
25
+ end
26
+ METHOD_DEFN
27
+ end
28
+ end
29
+ end
30
+ end
31
+ Volley::Log.init
@@ -0,0 +1,123 @@
1
+ require 'fog'
2
+
3
+ module Volley
4
+ module Publisher
5
+ class Amazons3 < Base
6
+ attr_accessor :key, :secret
7
+
8
+ def files
9
+ hash = {:desc => {}, :all => {}, :latest => {}}
10
+ @connection.directories.get(@bucket).files.collect{|e| e.key}.each do |e|
11
+ (pr, br, vr) = e.split(/\//)
12
+ hash[:desc][pr] ||= {}
13
+ hash[:desc][pr][br] ||= {}
14
+ hash[:desc][pr][br][vr] ||= []
15
+ hash[:desc][pr][br][vr] << e
16
+ hash[:all] ||= {}
17
+ hash[:latest] ||= {}
18
+ v = "#{pr}/#{br}/#{vr}"
19
+ hash[:latest]["#{pr}/#{br}"] ||= latest(pr, br)
20
+ hash[:all][v] = hash["latest"] == v
21
+ end
22
+ #ap hash
23
+ hash
24
+ end
25
+
26
+ def all
27
+ files[:all]
28
+ end
29
+
30
+ def projects
31
+ data = files
32
+ data[:desc].keys
33
+ #files.collect{|e| e.split(/\//).first }.uniq
34
+ rescue => e
35
+ Volley::Log.warn "error getting project list from publisher: #{e.message} at #{e.backtrace.first}"
36
+ []
37
+ end
38
+
39
+ def branches(pr)
40
+ puts "branches for #{pr}"
41
+ files[:desc][pr].keys
42
+ #files.select{|e| e.split(/\//).first == pr}.collect{|e| e.split(/\//)[1]}
43
+ rescue => e
44
+ Volley::Log.warn "error getting branch list from publisher: #{e.message}"
45
+ []
46
+ end
47
+
48
+ def versions(pr,br)
49
+ files[:desc][pr][br].keys
50
+ #raise "not implemented"
51
+ rescue => e
52
+ Volley::Log.warn "error getting version list from publisher: #{e.message}"
53
+ []
54
+ end
55
+
56
+ def contents(pr, br, vr)
57
+ files[:desc][pr][br][vr]
58
+ end
59
+
60
+ def latest(pr, br)
61
+ @project = pr
62
+ @branch = br
63
+ f = @connection.directories.get(@bucket).files.get("#{branch}/latest")
64
+ f.body
65
+ end
66
+
67
+ private
68
+
69
+ def load_configuration
70
+ @key = requires(:aws_access_key_id)
71
+ @secret = requires(:aws_secret_access_key)
72
+ @bucket = requires(:bucket)
73
+ @local = requires(:local)
74
+ @debug = optional(:debug, false)
75
+ @encrypted = optional(:encrypted, false)
76
+ connect
77
+ end
78
+
79
+ def remote_file
80
+ "#@branch-#@version.tgz#{".cpt" if @encrypted}"
81
+ end
82
+
83
+ def push_file(name, dir, contents)
84
+ Volley::Log.info ".. #{name}"
85
+ file = File.basename(name)
86
+ path = "#{dir}/#{file}"
87
+ Volley::Log.info ".. -> s3:#@bucket/#{path}"
88
+ @dir ||= @connection.directories.create({ :key => @bucket })
89
+ s3f = @dir.files.create(
90
+ :key => "#{path}",
91
+ :body => contents,
92
+ :public => true
93
+ )
94
+ Volley::Log.info ".. => #{s3f.public_url.gsub("%2F", "/")}"
95
+ "#{path}"
96
+ end
97
+
98
+ def pull_file(name, dir, ldir=nil)
99
+ Volley::Log.info ".. <- s3:#@bucket/#{dir}/#{name}"
100
+ if ldir
101
+ FileUtils.mkdir_p(ldir)
102
+ end
103
+ f = @connection.directories.get(@bucket).files.get("#{dir}/#{name}")
104
+ contents = f.body
105
+ if ldir
106
+ lfile = "#{ldir}/#{name}"
107
+ File.open(lfile, "w") { |lf| lf.write(contents) }
108
+ Volley::Log.info ".. <= #{lfile}"
109
+ else
110
+ contents
111
+ end
112
+ end
113
+
114
+ def connect
115
+ @connection ||= Fog::Storage.new(
116
+ :provider => "AWS",
117
+ :aws_access_key_id => @key,
118
+ :aws_secret_access_key => @secret,
119
+ )
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,102 @@
1
+ module Volley
2
+ module Publisher
3
+ class Base
4
+ def initialize(options={ })
5
+ @options = {
6
+ :overwrite => false,
7
+ }.merge(options)
8
+ load_configuration
9
+ end
10
+
11
+ def projects
12
+ raise "not implemented"
13
+ end
14
+
15
+ def volleyfile(desc={ })
16
+ @project = desc[:project]
17
+ @branch = desc[:branch]
18
+ @version = desc[:version] && desc[:version] != 'latest' ? desc[:version] : get_latest(@project, @branch)
19
+ contents = pull_file("Volleyfile", version)
20
+ dest = @options[:destination] || "/tmp/Volleyfile-#{Time.now.to_i}-#{$$}"
21
+ raise "File #{dest} already exists" if File.exists?(dest)
22
+ Volley::Log.debug("saving Volleyfile: #{dest}")
23
+ File.open(dest, "w") { |f| f.write(contents) }
24
+ dest
25
+ end
26
+
27
+ def push(project, br, ver, localfiles)
28
+ @project = project
29
+ @branch = br
30
+ @version = ver
31
+
32
+ localfiles = [*localfiles].flatten
33
+ Volley::Log.info ".. pushing:" if @debug
34
+
35
+ localfiles.each do |localfile|
36
+ Volley::Log.info ".. .. #{localfile}" if @debug
37
+ push_file(localfile, version, File.open(localfile))
38
+ end
39
+ push_file("latest", branch, version)
40
+ push_file("Volleyfile", version, File.open(Volley.config.volleyfile))
41
+ end
42
+
43
+ def pull(project, branch, ver="latest")
44
+ @project = project
45
+ @branch = branch
46
+ @version = ver
47
+
48
+ if @version == "latest"
49
+ @version = get_latest(@project, @branch)
50
+ end
51
+
52
+ Volley::Log.info "remote: #{version}" if @debug
53
+ Volley::Log.info "remote_file: #{remote_file}" if @debug
54
+ pull_file(remote_file, version, "#@local/#{version}")
55
+
56
+ "#@local/#{version}/#{remote_file}"
57
+ end
58
+
59
+ def get_latest(project, branch)
60
+ cur = pull_file("latest", "#{project}/#{branch}")
61
+ (p, n, v) = cur.split(/\//)
62
+ v
63
+ end
64
+
65
+ private
66
+ def me
67
+ self.class.name.split("::").last
68
+ end
69
+
70
+ def branch
71
+ "#@project/#@branch"
72
+ end
73
+
74
+ def version
75
+ "#{branch}/#@version"
76
+ end
77
+
78
+ def requires(name)
79
+ v = get_option(name)
80
+ if v.nil?
81
+ #ap @options
82
+ raise "Publisher #{me} requires option #{name}"
83
+ end
84
+ v
85
+ end
86
+
87
+ def optional(name, default)
88
+ get_option(name) || default
89
+ end
90
+
91
+ def get_option(name)
92
+ n = name.to_sym
93
+ @options[n]
94
+ end
95
+
96
+ def get_config(name)
97
+ n = name.to_sym
98
+ Volley.config.send(n)
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,61 @@
1
+ module Volley
2
+ module Publisher
3
+ class Local < Base
4
+
5
+ def projects
6
+ puts "#@directory"
7
+ Dir["#@directory/*"].map {|e| e.gsub(/#@directory\//,"")}
8
+ end
9
+
10
+ def branches(pr)
11
+ Dir["#@directory/#{pr}/*"].map {|e| e.gsub(/#@directory\/#{pr}\//,"")}
12
+ end
13
+
14
+ def versions(pr, br)
15
+ Dir["#@directory/#{pr}/#{br}/*"].map {|e| e.gsub(/#@directory\/#{pr}\/#{br}\//,"")}
16
+ end
17
+
18
+ private
19
+
20
+ def load_configuration
21
+ @directory = requires(:directory)
22
+ @local = requires(:local)
23
+ @debug = optional(:debug, false)
24
+ end
25
+
26
+ def remote_file
27
+ "#@branch-#@version.tgz#{".cpt" if @encrypted}"
28
+ end
29
+
30
+ def push_file(local, path, content = nil)
31
+ Volley::Log.debug "content=#{content.inspect}"
32
+ local = File.basename(local) if local =~ /^\//
33
+ dest = "#@directory/#{path}"
34
+ file = "#{dest}/#{local}"
35
+ Volley::Log.info".. -> #{dest}"
36
+ FileUtils.mkdir_p(File.dirname(file))
37
+ content = content.read if content.is_a?(File)
38
+ if content
39
+ File.open(file, "w") { |f| f.write(content) }
40
+ else
41
+ FileUtils.copy(local, file)
42
+ end
43
+ Volley::Log.info".. => #{file}"
44
+ end
45
+
46
+ def pull_file(file, path, ldir=nil)
47
+ remote = "#@directory/#{path}"
48
+ Volley::Log.info".. <- #{remote}/#{file}"
49
+ if ldir
50
+ FileUtils.mkdir_p(ldir)
51
+ end
52
+ if ldir
53
+ Volley::Log.info".. <= #@local/#{path}/#{file}"
54
+ FileUtils.copy("#{remote}/#{file}", "#@local/#{path}")
55
+ else
56
+ File.open("#{remote}/#{file}") { |f| f.read }
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,8 @@
1
+
2
+ module Volley
3
+ module Scm
4
+ class Base
5
+
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,31 @@
1
+ require 'volley/scm/base'
2
+
3
+ module Volley
4
+ module Scm
5
+ class Git < Base
6
+ def initialize(opt={ })
7
+ @options = {
8
+ :update => false
9
+ }.merge(opt)
10
+ end
11
+
12
+ def branch
13
+ @branch ||= `git branch`.lines.select {|e| e =~ /^\*/}.first.chomp.split[1]
14
+ rescue => e
15
+ Volley::Log.error "git: could not get branch: #{e.message}"
16
+ Volley::Log.debug e
17
+ end
18
+
19
+ def revision
20
+ @revision ||= `git log --format='%h' --max-count=1`.chomp
21
+ end
22
+
23
+ def update
24
+ @options.delete(:update)
25
+ up = %x{git pull --rebase}
26
+ @branch = nil
27
+ @revision = nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ require 'volley/scm/base'
2
+
3
+ module Volley
4
+ module Scm
5
+ class Subversion < Base
6
+ def initialize(opt={ })
7
+ @options = {
8
+ :update => false
9
+ }.merge(opt)
10
+ end
11
+
12
+ def data
13
+ @data ||= begin
14
+ update if @options[:update]
15
+ YAML::load(%x{svn info})
16
+ end
17
+ end
18
+
19
+ def branch
20
+ @branch ||= begin
21
+ if data["URL"] =~ /\/trunk/
22
+ "trunk"
23
+ elsif data["URL"] =~ /\/branches\//
24
+ m = data["URL"].match(/\/branches\/([^\/]+)\/*/)
25
+ m[1]
26
+ else
27
+ nil
28
+ end
29
+ end
30
+ end
31
+
32
+ def revision
33
+ @revision ||= begin
34
+ data["Revision"]
35
+ end
36
+ end
37
+
38
+ def update
39
+ @options.delete(:update)
40
+ up = %x{svn update}
41
+ @data = nil
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,10 @@
1
+ unless defined?(Volley::Version)
2
+ module Volley
3
+ module Version
4
+ MAJOR = 0
5
+ MINOR = 1
6
+ TINY = 0
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,45 @@
1
+ module Volley
2
+ module VolleyFile
3
+ class << self
4
+ def init
5
+ @loaded = {}
6
+ ["~/.Volleyfile", "/etc/Volleyfile", "../../../conf/common.volleyfile"].each do |f|
7
+ file = File.expand_path(f, __FILE__)
8
+ @loaded[file] ||= load(file, :optional => true)
9
+ end
10
+ end
11
+
12
+ def load(filename, options={ })
13
+ Volley::Log.debug "LOAD: #{filename} #{options.inspect}"
14
+ @projects ||= { }
15
+ file = File.expand_path(filename)
16
+ config.volleyfile = file if options[:primary]
17
+
18
+ if File.file?(file)
19
+ @loaded[file] ||= instance_eval(File.read(file), file)
20
+ else
21
+ raise "cannot read file" unless options[:optional]
22
+ end
23
+ end
24
+
25
+ def config
26
+ Volley.config
27
+ end
28
+
29
+ # TOP LEVEL DSL METHODS
30
+
31
+ def project(name, o={}, &block)
32
+ Volley::Log.debug "project: #{name}"
33
+ Volley::Dsl::Project.project(name, o, &block)
34
+ end
35
+
36
+ def publisher(name, o={}, &block)
37
+ Volley::Dsl::Publisher.publisher(name, o, &block)
38
+ end
39
+
40
+ def log(level, dest)
41
+ Volley::Log.add(level, dest)
42
+ end
43
+ end
44
+ end
45
+ end
data/lib/volley.rb ADDED
@@ -0,0 +1,58 @@
1
+ require "awesome_print"
2
+ require "ostruct"
3
+ require "active_support/all"
4
+
5
+ require "volley/version"
6
+ require "volley/config"
7
+ require "volley/log"
8
+ require "volley/volley_file"
9
+ require "volley/publisher/base"
10
+
11
+ require "volley/dsl"
12
+
13
+ module Volley
14
+ class << self
15
+ def process(opts)
16
+ project = opts[:project]
17
+ plan = opts[:plan]
18
+ branch = opts[:branch]
19
+ version = opts[:version]
20
+ args = opts[:args]
21
+
22
+ begin
23
+ if Volley::Dsl.project?(project)
24
+ # we have the project locally
25
+ pr = Volley::Dsl.project(project)
26
+ if pr.plan?(plan)
27
+ # plan is defined
28
+ pl = pr.plan(plan)
29
+ pl.call(:rawargs => args)
30
+ else
31
+ # plan is not defined
32
+ raise "could not find plan #{plan} in project #{project}"
33
+ end
34
+ else
35
+ # we dont have the project locally, search the publisher
36
+ pub = Volley::Dsl.publisher
37
+ if pub
38
+ if pub.projects.include?(project)
39
+ vf = pub.volleyfile(opts)
40
+ puts "VF:#{vf}"
41
+ else
42
+ raise "project #{project} does not exist in configured publisher #{pub.class}"
43
+ end
44
+ else
45
+ raise "project #{project} does not exist locally, and no publisher is configured."
46
+ end
47
+ end
48
+ rescue => e
49
+ Volley::Log.error "error while processing: #{e.message}"
50
+ Volley::Log.debug e
51
+ end
52
+
53
+ #if Volley.config.debug
54
+ # ap Volley::Dsl::Project.projects
55
+ #end
56
+ end
57
+ end
58
+ end
data/volley.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/volley/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Shawn Catanzarite"]
6
+ gem.email = ["scatanzarite@gmail.com"]
7
+ gem.description = %q{PubSub Deployment tool}
8
+ gem.summary = %q{PubSub Deployment tool}
9
+ gem.homepage = "http://github.com/shawncatz/volley"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "volley"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = "#{Volley::Version::STRING}.alpha1"
17
+
18
+ gem.add_dependency "clamp"
19
+ gem.add_dependency "fog"
20
+ gem.add_dependency "activesupport"
21
+ gem.add_dependency "mixlib-shellout"
22
+ gem.add_dependency "yell"
23
+ end