require "builder"
module Hudson
class JobConfigBuilder
attr_accessor :job_type, :matrix_project
attr_accessor :steps
attr_accessor :scm, :public_scm, :git_branches
attr_accessor :assigned_node
attr_accessor :envfile
InvalidTemplate = Class.new(StandardError)
VALID_JOB_TEMPLATES = %w[rails rails3 ruby rubygem]
# +job_type+ - template of default steps to create with the job
# +steps+ - array of [:method, cmd], e.g. [:build_shell_step, "bundle initial"]
# - Default is based on +job_type+.
# +scm+ - URL to the repository. Currently only support git URLs.
# +public_scm+ - convert the +scm+ URL to a publicly accessible URL for the Hudson job config.
# +git_branches+ - array of branches to run builds. Default: ['master']
# +assigned_node+ - restrict this job to running on slaves with these labels (space separated)
def initialize(job_type = :ruby, &block)
self.job_type = job_type.to_s if job_type
yield self
self.git_branches ||= ["master"]
raise InvalidTemplate unless VALID_JOB_TEMPLATES.include?(job_type.to_s)
end
def builder
b = Builder::XmlMarkup.new :indent => 2
b.instruct!
b.tag!(matrix_project? ? "matrix-project" : "project") do
b.actions
b.description
b.keepDependencies false
b.properties
build_scm b
b.assignedNode assigned_node if assigned_node
b.canRoam !assigned_node
b.disabled false
b.blockBuildWhenUpstreamBuilding false
# build_triggers b
b.concurrentBuild false
build_axes b if matrix_project?
build_steps b
b.publishers
build_wrappers b
b.runSequentially false if matrix_project?
end
end
def to_xml
builder.to_s
end
protected
def matrix_project?
matrix_project ||
%w[rubygem].include?(job_type)
end
# ...
def build_scm(b)
if scm && scm =~ /git/
scm_url = public_scm ? public_only_git_scm(scm) : scm
b.scm :class => "hudson.plugins.git.GitSCM" do
b.configVersion 1
b.remoteRepositories do
b.tag! "org.spearce.jgit.transport.RemoteConfig" do
b.string "origin"
b.int 5
b.string "fetch"
b.string "+refs/heads/*:refs/remotes/origin/*"
b.string "receivepack"
b.string "git-upload-pack"
b.string "uploadpack"
b.string "git-upload-pack"
b.string "url"
b.string scm_url
b.string "tagopt"
b.string
end
end
if git_branches
b.branches do
git_branches.each do |branch|
b.tag! "hudson.plugins.git.BranchSpec" do
b.name branch
end
end
end
end
b.localBranch
b.mergeOptions
b.recursiveSubmodules false
b.doGenerateSubmoduleConfigurations false
b.authorOrCommitter false
b.clean false
b.wipeOutWorkspace false
b.buildChooser :class => "hudson.plugins.git.util.DefaultBuildChooser"
b.gitTool "Default"
b.submoduleCfg :class => "list"
b.relativeTargetDir
b.excludedRegions
b.excludedUsers
end
end
end
# TODO
def build_axes(b)
b.axes
end
# Example:
#
#
# /path/to/env/file
#
#
def build_wrappers(b)
if envfile
b.buildWrappers do
self.envfile = [envfile] unless envfile.is_a?(Array)
b.tag! "hudson.plugins.envfile.EnvFileBuildWrapper" do
envfile.each do |file|
b.filePath file
end
end
end
else
b.buildWrappers
end
end
# The important sequence of steps that are run to process a job build.
# Can be defaulted by the +job_type+ using +default_steps(job_type)+,
# or customized via +steps+ array.
def build_steps(b)
b.builders do
self.steps ||= default_steps(job_type)
steps.each do |step|
method, cmd = step
send(method.to_sym, b, cmd) # e.g. build_shell_step(b, "bundle install")
end
end
end
def default_steps(job_type)
case job_type.to_sym
when :rails, :rails3
[
[:build_shell_step, "bundle install"],
[:build_ruby_step, <<-RUBY.gsub(/^ /, '')],
unless File.exist?("config/database.yml")
require 'fileutils'
example = Dir["config/database*"].first
puts "Using \#{example} for config/database.yml"
FileUtils.cp example, "config/database.yml"
end
RUBY
[:build_shell_step, "bundle exec rake db:create:all"],
[:build_shell_step, <<-RUBY.gsub(/^ /, '')],
if [ -f db/schema.rb ]; then
bundle exec rake db:migrate
else
bundle exec rake db:schema:load
fi
RUBY
[:build_shell_step, "bundle exec rake"]
]
else
[
[:build_shell_step, "bundle install"],
[:build_shell_step, "bundle exec rake"]
]
end
end
#
# bundle install
#
def build_shell_step(b, command)
b.tag! "hudson.tasks.Shell" do
b.command command.to_xs.gsub(%r{"}, '"').gsub(%r{'}, ''')
end
end
#
# unless File.exist?("config/database.yml")
# require 'fileutils'
# example = Dir["config/database*"].first
# puts "Using #{example} for config/database.yml"
# FileUtils.cp example, "config/database.yml"
# end
#
def build_ruby_step(b, command)
b.tag! "hudson.plugins.ruby.Ruby" do
b.command do
b << command.to_xs.gsub(%r{"}, '"').gsub(%r{'}, ''')
end
end
end
# Usage: build_ruby_step b, "db:schema:load"
#
#
# (Default)
#
#
#
# db:schema:load
# false
#
def build_rake_step(b, tasks)
b.tag! "hudson.plugins.rake.Rake" do
b.rakeInstallation "(Default)"
b.rakeFile
b.rakeLibDir
b.rakeWorkingDir
b.tasks tasks
b.silent false
end
end
# Converts git@github.com:drnic/newgem.git into git://github.com/drnic/newgem.git
def public_only_git_scm(scm_url)
if scm_url =~ /git@([\w\-_.]+):(.+)\.git/
"git://#{$1}/#{$2}.git"
else
scm_url
end
end
end
end