polisher 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +84 -14
- data/Rakefile +21 -19
- data/TODO +5 -4
- data/bin/server +1 -0
- data/config/polisher.yml +0 -15
- data/db/connection.rb +13 -10
- data/db/migrations/{002_create_managed_gems.rb → 001_create_projects.rb} +4 -5
- data/db/migrations/{001_create_sources.rb → 002_create_sources.rb} +1 -3
- data/db/migrations/003_create_project_source_versions.rb +28 -0
- data/db/migrations/{003_create_events.rb → 004_create_events.rb} +2 -2
- data/db/migrations/005_create_project_dependencies.rb +28 -0
- data/db/models/event.rb +47 -21
- data/db/models/project.rb +110 -0
- data/db/models/project_dependency.rb +27 -0
- data/db/models/project_source_version.rb +31 -0
- data/db/models/source.rb +82 -16
- data/lib/common.rb +37 -5
- data/lib/dsl.rb +292 -0
- data/lib/event_handlers.rb +139 -73
- data/lib/gem_adapter.rb +94 -0
- data/polisher.rb +302 -50
- data/public/stylesheets/style.css +15 -31
- data/spec/common_spec.rb +28 -0
- data/spec/dsl_spec.rb +357 -0
- data/spec/event_handlers_spec.rb +166 -30
- data/spec/gem_adapter_spec.rb +89 -0
- data/spec/models_spec.rb +635 -107
- data/spec/polisher_spec.rb +496 -56
- data/views/layout.haml +3 -5
- data/views/projects/index.haml +42 -0
- data/views/projects/index.html.haml +38 -0
- data/views/result.haml +9 -0
- data/views/sources/index.haml +24 -41
- data/views/sources/index.html.haml +26 -0
- metadata +131 -12
- data/db/models/managed_gem.rb +0 -111
- data/public/javascripts/jquery-1.2.6.min.js +0 -32
- data/public/javascripts/polisher.js +0 -15
- data/views/gems/index.haml +0 -106
@@ -0,0 +1,110 @@
|
|
1
|
+
# Copyright (C) 2010 Red Hat, Inc.
|
2
|
+
# Written by Mohammed Morsi <mmorsi@redhat.com>
|
3
|
+
#
|
4
|
+
# This program is free software, you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU Affero General Public License
|
6
|
+
# as published by the Free Software Foundation, either version 3
|
7
|
+
# of the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# You should have received a copy of the the GNU Affero
|
10
|
+
# General Public License, along with Polisher. If not, see
|
11
|
+
# <http://www.gnu.org/licenses/>
|
12
|
+
|
13
|
+
class Project < ActiveRecord::Base
|
14
|
+
# TODO on delete, destroy these
|
15
|
+
has_many :project_source_versions
|
16
|
+
has_many :sources, :through => :project_source_versions
|
17
|
+
has_many :events
|
18
|
+
|
19
|
+
has_many :project_dependencies
|
20
|
+
has_many :project_dependents, :class_name => "ProjectDependency", :foreign_key => "depends_on_project_id"
|
21
|
+
|
22
|
+
alias :dependencies :project_dependencies
|
23
|
+
alias :dependents :project_dependents
|
24
|
+
|
25
|
+
validates_presence_of :name
|
26
|
+
validates_uniqueness_of :name
|
27
|
+
|
28
|
+
# Download all project sources to specified :dir
|
29
|
+
def download_to(args = {})
|
30
|
+
# If a version isn't specified we can't lookup project_source_versions entry for uri substitutions
|
31
|
+
# FIXME the latter case in this ternary operator should be something along the lines of sources_for_all_versions returning those only associated w/ project_version = nil (also being sure to do uri_params substition) (?)
|
32
|
+
srcs = args.has_key?(:version) ? sources_for_version(args[:version]) : sources
|
33
|
+
srcs.each { |source| source.download_to args }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return all events associated w/ particular version of the project
|
37
|
+
def events_for_version(version)
|
38
|
+
evnts = events
|
39
|
+
evnts.find_all { |event| event.applies_to_version?(version) }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return all dependencies associated w/ particular version of the project
|
43
|
+
def dependencies_for_version(version)
|
44
|
+
deps = project_dependencies
|
45
|
+
deps.find_all { |dep| dep.project_version == version || dep.project_version.nil? }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return all project_source_versions associated w/ particular version of the project
|
49
|
+
def project_source_versions_for_version(version)
|
50
|
+
psa = project_source_versions
|
51
|
+
psa.find_all { |ps| ps.project_version == version || ps.project_version.nil? }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Return all sources associated w/ particular version of the project, each w/ uri formatted
|
55
|
+
# using project_source_versions source_uri_params
|
56
|
+
def sources_for_version(version)
|
57
|
+
project_source_versions_for_version(version).collect { |ps|
|
58
|
+
ps.source.format_uri!(ps.source_uri_params)
|
59
|
+
ps.source
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get the project primary source
|
64
|
+
def primary_source
|
65
|
+
ps = project_source_versions.all.find { |ps| ps.primary_source }
|
66
|
+
# TODO special case if no sources are marked as primary, grab the first ? (also in primary_source_for_version below)
|
67
|
+
return ps.nil? ? nil : ps.source
|
68
|
+
end
|
69
|
+
|
70
|
+
# Set the project primary source
|
71
|
+
def primary_source=(source)
|
72
|
+
project_source_versions << ProjectSourceVersion.new(:project => self, :source => source, :primary_source => true)
|
73
|
+
#source.save! ; save!
|
74
|
+
end
|
75
|
+
|
76
|
+
# Return the primary source for the specified version
|
77
|
+
def primary_source_for_version(version)
|
78
|
+
ps = project_source_versions_for_version(version).find { |ps| ps.primary_source }
|
79
|
+
ps.source.format_uri!(ps.source_uri_params) unless ps.nil?
|
80
|
+
return ps.nil? ? nil : ps.source
|
81
|
+
end
|
82
|
+
|
83
|
+
# Return all versions which we have configured this project for
|
84
|
+
def versions
|
85
|
+
# TODO should we return configured project_depents.depends_on_project_version as well ?
|
86
|
+
(project_source_versions.collect { |ps| ps.project_version } +
|
87
|
+
events.collect { |e| e.version } +
|
88
|
+
project_dependencies.collect { |d| d.project_version }).uniq - [nil]
|
89
|
+
end
|
90
|
+
|
91
|
+
# Release specified project version
|
92
|
+
def released_version(version, args = {})
|
93
|
+
# process dependencies
|
94
|
+
dependencies_for_version(version).each { |dep|
|
95
|
+
dargs = {}
|
96
|
+
dargs = dep.depends_on_project_params.to_h.merge!(args) unless dep.depends_on_project_params.nil?
|
97
|
+
|
98
|
+
# if dep_version.nil? grab all configured depends_on_project versions
|
99
|
+
dep_versions = dep.depends_on_project_version
|
100
|
+
dep_versions = dep_versions.nil? ? dep.depends_on_project.versions : [dep_versions]
|
101
|
+
|
102
|
+
dep_versions.each { |dv| dep.depends_on_project.released_version(dv, dargs) }
|
103
|
+
}
|
104
|
+
|
105
|
+
# process events
|
106
|
+
args[:version] = version
|
107
|
+
events_for_version(version).each { |event| event.run(args) }
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Copyright (C) 2010 Red Hat, Inc.
|
2
|
+
# Written by Mohammed Morsi <mmorsi@redhat.com>
|
3
|
+
#
|
4
|
+
# This program is free software, you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU Affero General Public License
|
6
|
+
# as published by the Free Software Foundation, either version 3
|
7
|
+
# of the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# You should have received a copy of the the GNU Affero
|
10
|
+
# General Public License, along with Polisher. If not, see
|
11
|
+
# <http://www.gnu.org/licenses/>
|
12
|
+
|
13
|
+
class ProjectDependency < ActiveRecord::Base
|
14
|
+
belongs_to :project
|
15
|
+
belongs_to :depends_on_project, :class_name => "Project", :foreign_key => "depends_on_project_id"
|
16
|
+
|
17
|
+
validates_presence_of :project_id
|
18
|
+
validates_presence_of :depends_on_project_id
|
19
|
+
|
20
|
+
validates_uniqueness_of :depends_on_project_version, :scope => [:project_id, :depends_on_project_id, :depends_on_project_version]
|
21
|
+
|
22
|
+
before_save :normalize_versions
|
23
|
+
def normalize_versions
|
24
|
+
self.project_version = nil if project_version == ""
|
25
|
+
self.depends_on_project_version = nil if depends_on_project_version == ""
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Copyright (C) 2010 Red Hat, Inc.
|
2
|
+
# Written by Mohammed Morsi <mmorsi@redhat.com>
|
3
|
+
#
|
4
|
+
# This program is free software, you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU Affero General Public License
|
6
|
+
# as published by the Free Software Foundation, either version 3
|
7
|
+
# of the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# You should have received a copy of the the GNU Affero
|
10
|
+
# General Public License, along with Polisher. If not, see
|
11
|
+
# <http://www.gnu.org/licenses/>
|
12
|
+
|
13
|
+
class ProjectSourceVersion < ActiveRecord::Base
|
14
|
+
belongs_to :project
|
15
|
+
belongs_to :source
|
16
|
+
|
17
|
+
# FIXME destroy source on deletion only if no other project_source_versions sharing the source exist
|
18
|
+
|
19
|
+
validates_uniqueness_of :source_id, :scope => [:project_id, :project_version]
|
20
|
+
|
21
|
+
# validate only one primary_source set to 'true' in scope of (project_id, project_version)
|
22
|
+
validates_uniqueness_of :primary_source,
|
23
|
+
:scope => [:project_id, :project_version],
|
24
|
+
:if => Proc.new { |ps| ps.primary_source }
|
25
|
+
|
26
|
+
before_save :normalize_versions
|
27
|
+
def normalize_versions
|
28
|
+
self.project_version = nil if project_version == ""
|
29
|
+
self.source_version = nil if source_version == ""
|
30
|
+
end
|
31
|
+
end
|
data/db/models/source.rb
CHANGED
@@ -10,26 +10,92 @@
|
|
10
10
|
# General Public License, along with Polisher. If not, see
|
11
11
|
# <http://www.gnu.org/licenses/>
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
require 'curl' # requires 'curb' package
|
14
|
+
|
15
15
|
class Source < ActiveRecord::Base
|
16
|
-
|
16
|
+
# TODO on delete, destroy these
|
17
|
+
has_many :project_source_versions
|
18
|
+
has_many :projects, :through => :project_source_versions
|
19
|
+
|
20
|
+
validates_presence_of :name
|
21
|
+
validates_uniqueness_of :name
|
22
|
+
validates_presence_of :source_type
|
23
|
+
validates_presence_of :uri
|
24
|
+
validates_uniqueness_of :uri
|
25
|
+
|
26
|
+
# TODO additional source types
|
27
|
+
|
28
|
+
SOURCE_TYPES = ['archive', 'patch', 'spec', 'gem', 'file', 'git_repo']
|
29
|
+
|
30
|
+
validates_inclusion_of :source_type, :in => SOURCE_TYPES
|
31
|
+
|
32
|
+
# Extract filename of this source from path
|
33
|
+
def filename
|
34
|
+
URI::parse(uri).path.split('/').last
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return all project_source_versions associated w/ particular version of the source
|
38
|
+
def project_source_versions_for_version(version)
|
39
|
+
psa = project_source_versions
|
40
|
+
psa.find_all { |ps| ps.source_version == version || ps.source_version.nil? }
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return all projects associated w/ particular version of the source
|
44
|
+
def projects_for_version(version)
|
45
|
+
project_source_versions_for_version(version).collect { |ps| ps.project }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return all versions which we have configured this project for
|
49
|
+
def versions
|
50
|
+
(project_source_versions.collect { |ps| ps.source_version }).uniq - [nil]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Swap any occurence of the specified hash
|
54
|
+
# keys w/ their cooresponding values in the local source uri
|
55
|
+
def format_uri!(variables)
|
56
|
+
params = {}
|
57
|
+
if variables.class == String
|
58
|
+
params = variables.to_h
|
59
|
+
elsif variables.class == Hash
|
60
|
+
params = variables
|
61
|
+
else
|
62
|
+
return
|
63
|
+
end
|
64
|
+
|
65
|
+
turi = uri
|
66
|
+
params.each { |k,v| turi.gsub!("%{#{k}}", v.to_s) }
|
67
|
+
uri = turi
|
68
|
+
end
|
69
|
+
|
70
|
+
# Download source, args may contain any of the following
|
71
|
+
# * :path path to download source to
|
72
|
+
# * :dir directory to download source to, filename will be generated from the last part of the uri
|
73
|
+
def download_to(args = {})
|
74
|
+
# TODO handle source_type == git_repo
|
75
|
+
|
76
|
+
path = args.has_key?(:path) ? args[:path] : nil
|
77
|
+
dir = args.has_key?(:dir) ? args[:dir] : nil
|
78
|
+
|
79
|
+
# format the uri w/ any additional params
|
80
|
+
format_uri! args
|
17
81
|
|
18
|
-
|
82
|
+
begin
|
83
|
+
# generate path which to d/l the file to
|
84
|
+
fn = filename
|
85
|
+
path = "#{dir}/#{fn}" if path.nil?
|
86
|
+
dir = File.dirname(path)
|
87
|
+
raise ArgumentError unless File.writable?(dir)
|
19
88
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
89
|
+
# d/l the file
|
90
|
+
curl = Curl::Easy.new(uri)
|
91
|
+
curl.follow_location = true # follow redirects
|
92
|
+
curl.perform
|
93
|
+
File.write path, curl.body_str
|
24
94
|
|
25
|
-
|
95
|
+
rescue Exception => e
|
96
|
+
raise RuntimeError, "could not download project source from #{uri} to #{path}"
|
97
|
+
end
|
26
98
|
|
27
|
-
|
28
|
-
# makes sure it satisfiest gem API requests
|
29
|
-
|
30
|
-
# remove trailing slash in uri if present
|
31
|
-
before_save :clean_uri!
|
32
|
-
def clean_uri!
|
33
|
-
self.uri = self.uri[0...self.uri.size-1] if self.uri[-1].chr == '/'
|
99
|
+
return path
|
34
100
|
end
|
35
101
|
end
|
data/lib/common.rb
CHANGED
@@ -12,24 +12,23 @@
|
|
12
12
|
# General Public License, along with Polisher. If not, see
|
13
13
|
# <http://www.gnu.org/licenses/>
|
14
14
|
|
15
|
-
#
|
15
|
+
# Read entire file into string
|
16
16
|
def File.read_all(path)
|
17
17
|
File.open(path, 'rb') {|file| return file.read }
|
18
18
|
end
|
19
19
|
|
20
|
-
#
|
20
|
+
# Write contents of file from string
|
21
21
|
def File.write(path, str)
|
22
22
|
File.open(path, 'wb') {|file| file.write str }
|
23
23
|
end
|
24
24
|
|
25
|
-
#
|
25
|
+
# Create any missing directories
|
26
26
|
def create_missing_polisher_dirs(args = {})
|
27
27
|
artifacts_dir = args[:artifacts_dir]
|
28
28
|
db_data_dir = args[:db_data_dir]
|
29
29
|
log_dir = args[:log_dir]
|
30
30
|
|
31
|
-
[artifacts_dir + '/
|
32
|
-
artifacts_dir + '/repos',
|
31
|
+
[artifacts_dir + '/repos',
|
33
32
|
artifacts_dir + '/SOURCES',
|
34
33
|
artifacts_dir + '/SPECS',
|
35
34
|
artifacts_dir + '/templates',
|
@@ -37,3 +36,36 @@ def create_missing_polisher_dirs(args = {})
|
|
37
36
|
FileUtils.mkdir_p(dir) unless File.directory? dir
|
38
37
|
}
|
39
38
|
end
|
39
|
+
|
40
|
+
# Set up and return polisher config from application
|
41
|
+
def load_polisher_config(app)
|
42
|
+
config = {}
|
43
|
+
loaded_config = YAML::load(File.open(app.polisher_config))[app.environment.to_s]
|
44
|
+
config.merge!(loaded_config) unless loaded_config.nil?
|
45
|
+
|
46
|
+
# Attempt to parse gem api key from ~/.gem/credentials if missing
|
47
|
+
if config["gem_api_key"].nil?
|
48
|
+
gcfile = File.expand_path("~/.gem/credentials")
|
49
|
+
if File.exists?(gcfile)
|
50
|
+
config["gem_api_key"] = File.read_all(gcfile).scan(/:rubygems_api_key:\s(.*)/).to_s
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return config
|
54
|
+
end
|
55
|
+
|
56
|
+
class String
|
57
|
+
|
58
|
+
# Parse/split string around element delimiters (;) and
|
59
|
+
# key/value delimiters (=) and convert to hash.
|
60
|
+
def to_h
|
61
|
+
ret = {}
|
62
|
+
split(';').each { |p| u = p.split('='); ret[u[0]] = u[1] }
|
63
|
+
ret
|
64
|
+
end
|
65
|
+
|
66
|
+
# Convert hash into string
|
67
|
+
def self.from_h(hash)
|
68
|
+
hash.keys.collect { |k| k.to_s + "=" + hash[k].to_s }.join(";")
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
data/lib/dsl.rb
ADDED
@@ -0,0 +1,292 @@
|
|
1
|
+
# Polisher dsl
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Red Hat, Inc.
|
4
|
+
# Written by Mohammed Morsi <mmorsi@redhat.com>
|
5
|
+
#
|
6
|
+
# This program is free software, you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation, either version 3
|
9
|
+
# of the License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# You should have received a copy of the the GNU Affero
|
12
|
+
# General Public License, along with Polisher. If not, see
|
13
|
+
# <http://www.gnu.org/licenses/>
|
14
|
+
|
15
|
+
require 'libxml'
|
16
|
+
require 'rest_client'
|
17
|
+
|
18
|
+
module Polisher
|
19
|
+
|
20
|
+
# Helper method to handle (print) xml status response
|
21
|
+
def handle_response(operation, response, exception_on_fail = false)
|
22
|
+
rr = LibXML::XML::Document.string(response.body).root
|
23
|
+
success = rr.children.find { |c| c.name == "success" }.content.strip == "true"
|
24
|
+
msg = rr.children.find { |c| c.name == "message" }.content.strip
|
25
|
+
puts "#{operation} returned w/ success = #{success} and the message: #{msg}"
|
26
|
+
raise RuntimeError, "#{operation} returned w/ failed status: #{msg}" if exception_on_fail && !success
|
27
|
+
end
|
28
|
+
module_function :handle_response
|
29
|
+
|
30
|
+
# DSL representations of model classes (so as to not require db connection on client side)
|
31
|
+
|
32
|
+
# DSL project
|
33
|
+
class Project
|
34
|
+
# Project attributes
|
35
|
+
attr_accessor :id, :name
|
36
|
+
|
37
|
+
# Means to store project version and dependency params to be used when setting up project_source_versions and deps
|
38
|
+
attr_accessor :project_version, :dependency_params
|
39
|
+
|
40
|
+
def initialize(args = {})
|
41
|
+
args = {:id => nil, :name => nil}.merge(args)
|
42
|
+
@id = args[:id] ; @name = args[:name]
|
43
|
+
@dependency_params = {}
|
44
|
+
end
|
45
|
+
|
46
|
+
# Add a method to project for each source type, eg add_archive, add_path, add_repo, etc.
|
47
|
+
# TODO maintain as source_types are added (or put this this in a seperate module)
|
48
|
+
# XXX ran into this when doing it metaprogramatically http://coderrr.wordpress.com/2008/10/29/using-define_method-with-blocks-in-ruby-18/
|
49
|
+
def add_archive args = {}, █ add_source('archive', args, &block); end
|
50
|
+
def add_patch args = {}, █ add_source('patch', args, &block); end
|
51
|
+
def add_gem args = {}, █ add_source('gem', args, &block); end
|
52
|
+
def add_file args = {}, █ add_source('file', args, &block); end
|
53
|
+
|
54
|
+
def add_source type, args = {}, &block
|
55
|
+
args[:source_type] = type # automatically set the source type
|
56
|
+
src = source(args)
|
57
|
+
|
58
|
+
# Dispatch source to caller blocker to register specific project/source versions.
|
59
|
+
if !block.nil?
|
60
|
+
block.call src
|
61
|
+
|
62
|
+
# If no block is given register default */* project/source version
|
63
|
+
# TODO should this execute regardless of whether there is a block or not, eg only if no project/source versions were created/exist (need to perform a new query to get that info)
|
64
|
+
else
|
65
|
+
version nil, :corresponds_to => src
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Create Project from xml and return
|
70
|
+
def self.from_xml(xml_str)
|
71
|
+
project = Polisher::Project.new
|
72
|
+
|
73
|
+
xml = LibXML::XML::Document.string(xml_str).root
|
74
|
+
project.id = xml.children.find { |c| c.name == "id" }.content.to_i
|
75
|
+
project.name = xml.children.find { |c| c.name == "name" }.content.strip
|
76
|
+
# TODO associated versions, sources, events
|
77
|
+
#xml.children.find { |c| c.name == "version" }.children.each { |c|
|
78
|
+
#uri = c.children.find { |c| c.name == "uri"}
|
79
|
+
#project.sources << uri.content.strip unless uri.nil?
|
80
|
+
#}
|
81
|
+
|
82
|
+
return project
|
83
|
+
end
|
84
|
+
|
85
|
+
# Retrieve and return all projects
|
86
|
+
def self.all
|
87
|
+
projects = []
|
88
|
+
RestClient.get("#{$polisher_uri}/projects") { |response|
|
89
|
+
xml = LibXML::XML::Document.string(response.body).root
|
90
|
+
xml.children.find_all { |c| c.name == "project" }.each { |s|
|
91
|
+
projects << Polisher::Project.from_xml(s.to_s)
|
92
|
+
}
|
93
|
+
}
|
94
|
+
return projects
|
95
|
+
end
|
96
|
+
|
97
|
+
# Create project
|
98
|
+
def create
|
99
|
+
RestClient.post("#{$polisher_uri}/projects/create", :name => name) { |response| Polisher.handle_response('create project', response, true) }
|
100
|
+
end
|
101
|
+
|
102
|
+
# Delete project
|
103
|
+
def delete
|
104
|
+
RestClient.delete("#{$polisher_uri}/projects/destroy/#{id}") { |response| Polisher.handle_response('delete project', response, true) }
|
105
|
+
end
|
106
|
+
|
107
|
+
# Create new Event w/ the specified version qualifier, version, process, and process options
|
108
|
+
def on_version(*args)
|
109
|
+
args.unshift nil unless ['', '=', '>', '<', '>=', '<='].include?(args[0]) # XXX don't like having to replicate entire event version qualifiers, but don't want the activerecord dependency
|
110
|
+
version_qualifier = args[0]
|
111
|
+
version = args[1]
|
112
|
+
process = args[2]
|
113
|
+
process_options = args[3]
|
114
|
+
process_options = "" if process_options.nil?
|
115
|
+
process_options += ";" + String.from_h(args[4]) if args.size == 5
|
116
|
+
|
117
|
+
process.gsub!(/\s/, '_')
|
118
|
+
|
119
|
+
RestClient.post("#{$polisher_uri}/events/create",
|
120
|
+
:project_id => id, :process => process, :version => version,
|
121
|
+
:version_qualifier => version_qualifier, :process_options => process_options) { |response| Polisher.handle_response('create event', response) }
|
122
|
+
end
|
123
|
+
|
124
|
+
# Associate specified project version w/ corresponding source version if specified,
|
125
|
+
# else if not just return self
|
126
|
+
def version(version, args = {})
|
127
|
+
version = nil if version == "*"
|
128
|
+
@project_version = version
|
129
|
+
@dependency_params = args unless args.empty?
|
130
|
+
|
131
|
+
if args.has_key?(:corresponds_to)
|
132
|
+
# dispatch to source.version so we don't have to implement twice
|
133
|
+
source = args[:corresponds_to]
|
134
|
+
source.version source.source_version, :corresponds_to => self
|
135
|
+
|
136
|
+
elsif args.has_key?(:depends_on)
|
137
|
+
project = args.delete(:depends_on)
|
138
|
+
args = project.dependency_params.merge(args) unless project.dependency_params.empty?
|
139
|
+
depends_on_args = String.from_h(args) unless args.empty?
|
140
|
+
args = {:project_id => id, :project_version => version,
|
141
|
+
:depends_on_project_id => project.id, :depends_on_project_version => project.project_version,
|
142
|
+
:depends_on_project_params => depends_on_args}
|
143
|
+
RestClient.post("#{$polisher_uri}/project_dependencies/create", args) { |response| Polisher.handle_response('created project dependency', response) }
|
144
|
+
|
145
|
+
else
|
146
|
+
return self
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Test fire project released event for specified version
|
151
|
+
def released(version, params = {})
|
152
|
+
resource = RestClient::Resource.new("#{$polisher_uri}/projects/released", :timeout => 1000) # give event handlers plenty of time to run
|
153
|
+
|
154
|
+
sparams = "name=#{name}&version=#{version}"
|
155
|
+
params.each { |k,v| sparams += "&#{k}=#{v}" }
|
156
|
+
resource.post sparams do |response|
|
157
|
+
Polisher.handle_response('released project', response)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# DSL Source
|
163
|
+
class Source
|
164
|
+
# Source attributes
|
165
|
+
attr_accessor :id, :name, :uri, :source_type
|
166
|
+
|
167
|
+
# Means to store source version and optional uri params to be used when setting up project sources
|
168
|
+
attr_accessor :source_version, :uri_args
|
169
|
+
|
170
|
+
# Means to store primary_source value when creating projects sources
|
171
|
+
attr_accessor :primary_source
|
172
|
+
|
173
|
+
def initialize(args = {})
|
174
|
+
args = { :id => nil, :name => nil, :uri => nil, :source_type => nil, :primary_source => false}.merge(args)
|
175
|
+
@id = args[:id] ; @name = args[:name] ; @uri = args[:uri] ; @source_type = args[:source_type] ; @primary_sources = args[:primary_source]
|
176
|
+
@uri_args = '' ; @primary_source = false
|
177
|
+
end
|
178
|
+
|
179
|
+
# Create Source from xml and return
|
180
|
+
def self.from_xml(xml_str)
|
181
|
+
source = Polisher::Source.new
|
182
|
+
|
183
|
+
xml = LibXML::XML::Document.string(xml_str).root
|
184
|
+
source.id = xml.children.find { |c| c.name == "id" }.content.to_i
|
185
|
+
source.name = xml.children.find { |c| c.name == "name" }.content.strip
|
186
|
+
source.uri = xml.children.find { |c| c.name == "uri" }.content.strip
|
187
|
+
source.source_type = xml.children.find { |c| c.name == "source_type" }.content.strip
|
188
|
+
# TODO associated versions, projects, events
|
189
|
+
|
190
|
+
return source
|
191
|
+
end
|
192
|
+
|
193
|
+
# Retrieve and return all sources
|
194
|
+
def self.all
|
195
|
+
sources = []
|
196
|
+
RestClient.get("#{$polisher_uri}/sources") { |response|
|
197
|
+
xml = LibXML::XML::Document.string(response.body).root
|
198
|
+
xml.children.find_all { |c| c.name == "source" }.each { |s|
|
199
|
+
sources << Polisher::Source.from_xml(s.to_s)
|
200
|
+
}
|
201
|
+
}
|
202
|
+
return sources
|
203
|
+
end
|
204
|
+
|
205
|
+
# Create source
|
206
|
+
def create
|
207
|
+
RestClient.post("#{$polisher_uri}/sources/create", :name => name, :uri => uri, :source_type => source_type) { |response| Polisher.handle_response('create project', response, true) }
|
208
|
+
end
|
209
|
+
|
210
|
+
# Associate specified project source w/ corresponding source version if specified,
|
211
|
+
# else if not just return self
|
212
|
+
def version(version, args = {})
|
213
|
+
version = nil if version == "*"
|
214
|
+
project = args.delete(:corresponds_to)
|
215
|
+
|
216
|
+
@uri_args = String.from_h(args) unless args.empty?
|
217
|
+
|
218
|
+
if project.nil?
|
219
|
+
@source_version = version
|
220
|
+
return self
|
221
|
+
end
|
222
|
+
|
223
|
+
args = {:project_id => project.id, :project_version => project.project_version,
|
224
|
+
:source_id => id, :source_version => version, :source_uri_params => @uri_args,
|
225
|
+
:primary_source => @primary_source }
|
226
|
+
RestClient.post("#{$polisher_uri}/project_source_versions/create", args) { |response| Polisher.handle_response('created project source', response) }
|
227
|
+
end
|
228
|
+
|
229
|
+
# Set source as primary in project/source associations
|
230
|
+
def is_the_primary_source
|
231
|
+
@primary_source = true
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
end # module Polisher
|
236
|
+
|
237
|
+
# Set polisher uri for all connections
|
238
|
+
def polisher(uri)
|
239
|
+
# XXX do this better
|
240
|
+
$polisher_uri = uri
|
241
|
+
end
|
242
|
+
|
243
|
+
# Retrieve list of all projects, invoking yield w/ each, before returning the list
|
244
|
+
def projects
|
245
|
+
projects = Polisher::Project.all
|
246
|
+
projects.each { |project| yield project if block_given? }
|
247
|
+
return projects
|
248
|
+
end
|
249
|
+
|
250
|
+
# Find or create new project w/ specified args
|
251
|
+
def project(args = {})
|
252
|
+
projects { |project|
|
253
|
+
project = nil if (args.has_key?(:name) && args[:name] != project.name) ||
|
254
|
+
(args.has_key?(:id) && args[:id] != project.id)
|
255
|
+
unless project.nil?
|
256
|
+
yield project if block_given?
|
257
|
+
return project
|
258
|
+
end
|
259
|
+
}
|
260
|
+
proj = Polisher::Project.new args
|
261
|
+
proj.create
|
262
|
+
proj = project(args)
|
263
|
+
yield proj if block_given?
|
264
|
+
return proj
|
265
|
+
end
|
266
|
+
|
267
|
+
# Retrieve list of all sources, invoking yield w/ each, before returning the list
|
268
|
+
def sources
|
269
|
+
sources = Polisher::Source.all
|
270
|
+
sources.each { |source| yield source if block_given? }
|
271
|
+
return sources
|
272
|
+
end
|
273
|
+
|
274
|
+
# Find or create new source w/ specified args
|
275
|
+
def source(args = {})
|
276
|
+
sources { |src|
|
277
|
+
src = nil if (args.has_key?(:name) && args[:name] != src.name) ||
|
278
|
+
(args.has_key?(:id) && args[:id] != src.id) ||
|
279
|
+
(args.has_key?(:source_type) && args[:source_type] != src.source_type) ||
|
280
|
+
(args.has_key?(:uri) && args[:uri] != src.uri)
|
281
|
+
unless src.nil?
|
282
|
+
yield src if block_given?
|
283
|
+
return src
|
284
|
+
end
|
285
|
+
}
|
286
|
+
src = Polisher::Source.new args
|
287
|
+
src.create
|
288
|
+
src = source(args)
|
289
|
+
src.primary_source = args[:primary_source] if args.has_key?(:primary_source) # XXX ugly hack
|
290
|
+
yield src if block_given?
|
291
|
+
return src
|
292
|
+
end
|