summaryrefslogtreecommitdiffstats
path: root/tasks/rake
diff options
context:
space:
mode:
authorJames Turnbull <james@lovedthanlost.net>2009-02-10 02:14:55 +1100
committerJames Turnbull <james@lovedthanlost.net>2009-02-10 02:14:55 +1100
commite52f962f44e98719212d788699ebaa6eb4d61904 (patch)
tree7a9e661d02778055493982264b8dfa06761c513e /tasks/rake
parent072643736fcfd37d3c2c42d6d9841f05ff391319 (diff)
downloadfacter-e52f962f44e98719212d788699ebaa6eb4d61904.tar.gz
facter-e52f962f44e98719212d788699ebaa6eb4d61904.tar.xz
facter-e52f962f44e98719212d788699ebaa6eb4d61904.zip
Added Reductive Labs build library
Diffstat (limited to 'tasks/rake')
-rw-r--r--tasks/rake/redlabpackage.rb265
-rw-r--r--tasks/rake/reductive.rb538
2 files changed, 803 insertions, 0 deletions
diff --git a/tasks/rake/redlabpackage.rb b/tasks/rake/redlabpackage.rb
new file mode 100644
index 0000000..2de8005
--- /dev/null
+++ b/tasks/rake/redlabpackage.rb
@@ -0,0 +1,265 @@
+#!/usr/bin/env ruby
+
+# A raw platform for creating packages.
+
+require 'rbconfig'
+require 'rake'
+require 'rake/tasklib'
+
+# The PackageTask will create the following targets:
+#
+# [<b>:clobber_package</b>]
+# Delete all the package files. This target is automatically
+# added to the main clobber target.
+#
+# [<b>:repackage</b>]
+# Rebuild the package files from scratch, even if they are not out
+# of date.
+#
+# [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tgz"</b>]
+# Create a gzipped tar package (if <em>need_tar</em> is true).
+#
+# [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.gz"</b>]
+# Create a gzipped tar package (if <em>need_tar_gz</em> is true).
+#
+# [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.bz2"</b>]
+# Create a bzip2'd tar package (if <em>need_tar_bz2</em> is true).
+#
+# [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.zip"</b>]
+# Create a zip package archive (if <em>need_zip</em> is true).
+#
+# Example:
+#
+# Rake::PackageTask.new("rake", "1.2.3") do |p|
+# p.need_tar = true
+# p.package_files.include("lib/**/*.rb")
+# end
+#
+class Rake::RedLabPackageTask < Rake::TaskLib
+ # The different directory types we can manage.
+ DIRTYPES = {
+ :bindir => :bins,
+ :sbindir => :sbins,
+ :sitelibdir => :rubylibs
+ }
+
+ # Name of the package (from the GEM Spec).
+ attr_accessor :name
+
+ # Version of the package (e.g. '1.3.2').
+ attr_accessor :version
+
+ # Directory used to store the package files (default is 'pkg').
+ attr_accessor :package_dir
+
+ # The directory to which to publish packages and html and such.
+ attr_accessor :publishdir
+
+ # The package-specific publishing directory
+ attr_accessor :pkgpublishdir
+
+ # The Product name. Defaults to a capitalized version of the
+ # package name
+ attr_accessor :product
+
+ # The copyright message.
+ attr_accessor :copyright
+
+ # The vendor.
+ attr_accessor :vendor
+
+ # The license file. Defaults to COPYING.
+ attr_accessor :license
+
+ # The readme file. Defaults to README.
+ attr_accessor :readme
+
+ # The description.
+ attr_accessor :description
+
+ # The summary.
+ attr_accessor :summary
+
+ # The directory in which to put the binaries. Defaults to the system
+ # default.
+ attr_accessor :bindir
+
+ # The executables.
+ attr_accessor :bins
+
+ # The directory in which to put the system binaries. Defaults to the
+ # system default.
+ attr_accessor :sbindir
+
+ # The system binaries.
+ attr_accessor :sbins
+
+ # The libraries.
+ attr_accessor :rubylibs
+
+ # The directory in which to put Ruby libraries. Defaults to the
+ # system site_dir.
+ attr_accessor :sitelibdir
+
+ # The URL for the package.
+ attr_accessor :url
+
+ # The source for the package.
+ attr_accessor :source
+
+ # Our operating system.
+ attr_reader :os
+
+ # Add a required package.
+ def add_dependency(name, version = nil)
+ @requires[name] = version
+ end
+
+ # Create the tasks defined by this task library.
+ def define
+ fail "Version required (or :noversion)" if @version.nil?
+ @version = nil if :noversion == @version
+
+ directory pkgdest
+ file pkgdest => self.package_dir
+
+ directory self.package_dir
+
+ self.mkcopytasks
+
+ self
+ end
+
+ # Return the list of files associated with a dirname.
+ def files(dirname)
+ if @dirtypes.include?(dirname)
+ return self.send(@dirtypes[dirname])
+ else
+ raise "Could not find directory type %s" % dirname
+ end
+ end
+
+ # Create a Package Task with the given name and version.
+ def initialize(name=nil, version=nil)
+ # Theoretically, one could eventually add directory types here.
+ @dirtypes = DIRTYPES.dup
+
+ @requires = {}
+
+ @name = name
+ @version = version
+ @package_dir = 'pkg'
+ @product = name.capitalize
+
+ @bindir = Config::CONFIG["bindir"]
+ @sbindir = Config::CONFIG["sbindir"]
+ @sitelibdir = Config::CONFIG["sitelibdir"]
+
+ @license = "COPYING"
+ @readme = "README"
+
+ yield self if block_given?
+
+ define unless name.nil?
+
+ # Make sure they've provided everything necessary.
+ %w{copyright vendor description}.each do |attr|
+ unless self.send(attr)
+ raise "You must provide the attribute %s" % attr
+ end
+ end
+ end
+
+ # Make tasks for copying/linking all of the necessary files.
+ def mkcopytasks
+ basedir = pkgdest()
+
+ tasks = []
+
+ # Iterate across all of the file locations...
+ @dirtypes.each do |dirname, filemethod|
+ tname = ("copy" + dirname.to_s).intern
+
+ dir = self.send(dirname)
+
+ reqs = []
+
+ # This is where we're putting the files.
+ targetdir = self.targetdir(dirname)
+
+ # Make sure our target directories exist
+ directory targetdir
+ file targetdir => basedir
+
+ # Get the file list and remove the leading directory.
+ files = self.files(dirname) or next
+
+ reqs = []
+ files.each do |sourcefile|
+ # The file without the basedir. This is necessary because
+ # files are created with the path from ".", but they often
+ # have 'lib' changed to 'site_ruby' or something similar.
+ destfile = File.join(targetdir, sourcefile.sub(/^\w+\//, ''))
+ reqs << destfile
+
+ # Make sure the base directory is listed as a prereq
+ sourcedir = File.dirname(sourcefile)
+ destdir = nil
+ unless sourcedir == "."
+ destdir = File.dirname(destfile)
+ reqs << destdir
+ directory(destdir)
+ end
+
+ # Now make the task associated with creating the object in
+ # question.
+ if FileTest.directory?(sourcefile)
+ directory(destfile)
+ else
+ file(destfile => sourcefile) do
+ if FileTest.exists?(destfile)
+ if File.stat(sourcefile) > File.stat(destfile)
+ rm_f destfile
+ safe_ln(sourcefile, destfile)
+ end
+ else
+ safe_ln(sourcefile, destfile)
+ end
+ end
+
+ # If we've set the destdir, then list it as a prereq.
+ if destdir
+ file destfile => destdir
+ end
+ end
+ end
+
+ # And create a task for each one
+ task tname => reqs
+
+ # And then mark our task as a prereq
+ tasks << tname
+ end
+
+ task :copycode => [self.package_dir, pkgdest]
+
+ task :copycode => tasks do
+ puts "Finished copying"
+ end
+ end
+
+ # Where we're copying a given type of file.
+ def targetdir(dirname)
+ File.join(pkgdest(), self.send(dirname)).sub("//", "/")
+ end
+
+ private
+
+ def package_name
+ @version ? "#{@name}-#{@version}" : @name
+ end
+
+ def package_dir_path
+ "#{package_dir}/#{package_name}"
+ end
+end
diff --git a/tasks/rake/reductive.rb b/tasks/rake/reductive.rb
new file mode 100644
index 0000000..2fbd2b4
--- /dev/null
+++ b/tasks/rake/reductive.rb
@@ -0,0 +1,538 @@
+#!/usr/bin/env ruby
+
+# The tasks associated with building Reductive Labs projects
+
+require 'rbconfig'
+require 'rake'
+require 'rake/tasklib'
+
+require 'rake/clean'
+require 'rake/testtask'
+
+$features = {}
+
+begin
+ require 'rubygems'
+ require 'rake/gempackagetask'
+ $features[:gem] = true
+rescue Exception
+ $features[:gem] = false
+ $stderr.puts "No Gems; skipping"
+ nil
+end
+
+begin
+ require 'rdoc/rdoc'
+ $features[:rdoc] = true
+rescue => detail
+ $features[:rdoc] = false
+ puts "No rdoc: %s" % detail
+end
+
+if $features[:rdoc]
+ require 'rake/rdoctask'
+end
+
+# Create all of the standard targets for a Reductive Labs project.
+# NOTE: The reason so many of the rake tasks are generated, rather than being
+# declared directly, is that they need information from the project instance.
+# Any rake task with an instance variable (e.g., @name or @version) needs
+# to have that variable assigned *before* the task is defined. Suckage.
+class Rake::RedLabProject < Rake::TaskLib
+ # The project name.
+ attr_accessor :name
+
+ # The project version.
+ attr_accessor :version
+
+ # The directory to which to publish packages and html and such.
+ attr_accessor :publishdir
+
+ # The package-specific publishing directory
+ attr_accessor :pkgpublishdir
+
+ # Create a Gem file.
+ attr_accessor :mkgem
+
+ # The hosts to run all of our tests on.
+ attr_accessor :testhosts
+
+ # The summary of this project.
+ attr_accessor :summary
+
+ # The description of this project.
+ attr_accessor :description
+
+ # The author of this project.
+ attr_accessor :author
+
+ # A Contact email address.
+ attr_accessor :email
+
+ # The URL for the project.
+ attr_accessor :url
+
+ # Where to get the source code.
+ attr_accessor :source
+
+ # Who the vendor is.
+ attr_accessor :vendor
+
+ # The copyright for this project
+ attr_accessor :copyright
+
+ # The RubyForge project.
+ attr_accessor :rfproject
+
+ # The list of files. Only used for gem tasks.
+ attr_writer :filelist
+
+ # The directory in which to store packages. Defaults to "pkg".
+ attr_accessor :package_dir
+
+ # The default task. Defaults to the 'alltests' task.
+ attr_accessor :defaulttask
+
+ # The defined requirements
+ attr_reader :requires
+
+ # The file containing the version string.
+ attr_accessor :versionfile
+
+ # Print messages on stdout
+ def announce(msg = nil)
+ puts msg
+ end
+
+ # Print messages on stderr
+ def warn(msg = nil)
+ $stderr.puts msg
+ end
+
+ def add_dependency(name, version)
+ @requires[name] = version
+ end
+
+ # Where we'll be putting the code.
+ def codedir
+ unless defined? @codedir
+ @codedir = File.join(self.package_dir, "#{@name}-#{@version}")
+ end
+
+ return @codedir
+ end
+
+ # Retrieve the current version from the code.
+ def currentversion
+ unless defined? @currentversion
+ ver = %x{ruby -Ilib ./bin/#{@name} --version}.chomp
+ if $? == 0 and ver != ""
+ @currentversion = ver
+ else
+ warn "Could not retrieve current version; using 0.0.0"
+ @currentversion = "0.0.0"
+ end
+ end
+
+ return @currentversion
+ end
+
+ # Define all of our package tasks. We just search through all of our
+ # defined methods and call anything that's listed as making tasks.
+ def define
+ self.methods.find_all { |method| method.to_s =~ /^mktask/ }.each { |method|
+ self.send(method)
+ }
+ end
+
+ def egrep(pattern)
+ Dir['**/*.rb'].each do |fn|
+ count = 0
+ open(fn) do |f|
+ while line = f.gets
+ count += 1
+ if line =~ pattern
+ puts "#{fn}:#{count}:#{line}"
+ end
+ end
+ end
+ end
+ end
+
+ # List all of the files.
+ def filelist
+ unless defined? @createdfilelist
+ # If they passed in a file list as an array, then create a FileList
+ # object out of it.
+ if defined? @filelist
+ unless @filelist.is_a? FileList
+ @filelist = FileList[@filelist]
+ end
+ else
+ # Use a default file list.
+ @filelist = FileList[
+ 'install.rb',
+ '[A-Z]*',
+ 'lib/**/*.rb',
+ 'test/**/*.rb',
+ 'bin/**/*',
+ 'ext/**/*',
+ 'examples/**/*',
+ 'conf/**/*'
+ ]
+ end
+ @filelist.delete_if {|item| item.include?(".git")}
+
+ @createdfilelist = true
+ end
+
+ @filelist
+ end
+
+ def has?(feature)
+ feature = feature.intern if feature.is_a? String
+ if $features.include?(feature)
+ return $features[feature]
+ else
+ return true
+ end
+ end
+
+ def initialize(name, version = nil)
+ @name = name
+
+ if ENV['REL']
+ @version = ENV['REL']
+ else
+ @version = version || self.currentversion
+ end
+
+ @defaulttask = :alltests
+ @publishdir = "/opt/rl/docroots/reductivelabs.com/htdocs/downloads"
+ @pkgpublishdir = "#{@publishdir}/#{@name}"
+
+ @email = "dev@reductivelabs.com"
+ @url = "http://reductivelabs.com/projects/#{@name}"
+ @source = "http://reductivelabs.com/downloads/#{@name}/#{@name}-#{@version}.tgz"
+ @vendor = "Reductive Labs, LLC"
+ @copyright = "Copyright 2003-2008, Reductive Labs, LLC. Some Rights Reserved."
+ @rfproject = @name
+
+ @defaulttask = :package
+
+ @package_dir = "pkg"
+
+ @requires = {}
+
+ @versionfile = "lib/#{@name}.rb"
+
+ CLOBBER.include('doc/*')
+
+ yield self if block_given?
+ define if block_given?
+ end
+
+ def mktaskhtml
+ if $features[:rdoc]
+ Rake::RDocTask.new(:html) { |rdoc|
+ rdoc.rdoc_dir = 'html'
+ rdoc.template = 'html'
+ rdoc.title = @name.capitalize
+ rdoc.options << '--line-numbers' << '--inline-source' <<
+ '--main' << 'README'
+ rdoc.rdoc_files.include('README', 'COPYING', 'CHANGELOG')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+ CLEAN.include("html")
+ }
+
+ # Publish the html.
+ task :publish => [:package, :html] do
+ puts Dir.getwd
+ sh %{cp -r html #{self.pkgpublishdir}/apidocs}
+ end
+ else
+ warn "No rdoc; skipping html"
+ end
+ end
+
+ # Create a release task.
+ def mktaskrelease
+ desc "Make a new release"
+ task :release => [
+ :prerelease,
+ :clobber,
+ :update_version,
+ :commit_newversion,
+ :trac_version,
+ :tag, # tag everything before we make a bunch of extra dirs
+ :html,
+ :package,
+ :publish
+ ] do
+
+ announce
+ announce "**************************************************************"
+ announce "* Release #{@version} Complete."
+ announce "* Packages ready to upload."
+ announce "**************************************************************"
+ announce
+ end
+ end
+
+ # Do any prerelease work.
+ def mktaskprerelease
+ # Validate that everything is ready to go for a release.
+ task :prerelease do
+ announce
+ announce "**************************************************************"
+ announce "* Making Release #{@version}"
+ announce "* (current version #{self.currentversion})"
+ announce "**************************************************************"
+ announce
+
+ # Is a release number supplied?
+ unless ENV['REL']
+ warn "You must provide a release number when releasing"
+ fail "Usage: rake release REL=x.y.z [REUSE=tag_suffix]"
+ end
+
+ # Is the release different than the current release.
+ # (or is REUSE set?)
+ if @version == self.currentversion && ! ENV['REUSE']
+ fail "Current version is #{@version}, must specify REUSE=tag_suffix to reuse version"
+ end
+
+ # Are all source files checked in?
+ if ENV['RELTEST']
+ announce "Release Task Testing, skipping checked-in file test"
+ else
+ announce "Checking for unchecked-in files..."
+ data = %x{git status}
+ unless data.include?("nothing to commit")
+ fail "git status is not clean ... do you have unchecked-in files?"
+ end
+ announce "No outstanding checkins found ... OK"
+ end
+ end
+ end
+
+ # Create the task to update versions.
+ def mktaskupdateversion
+ task :update_version => [:prerelease] do
+ if @version == self.currentversion
+ announce "No version change ... skipping version update"
+ else
+ announce "Updating #{@versionfile} version to #{@version}"
+ open(@versionfile) do |rakein|
+ open("#{@versionfile}.new", "w") do |rakeout|
+ rakein.each do |line|
+ if line =~ /^(\s*)#{@name.upcase}VERSION\s*=\s*/
+ rakeout.puts "#{$1}#{@name.upcase}VERSION = '#{@version}'"
+ else
+ rakeout.puts line
+ end
+ end
+ end
+ end
+ mv "#{@versionfile}.new", @versionfile
+
+ end
+ end
+
+ desc "Commit the new versions to SVN."
+ task :commit_newversion => [:update_version] do
+ if ENV['RELTEST']
+ announce "Release Task Testing, skipping commiting of new version"
+ else
+ sh %{git commit -m "Updated to version #{@version}" #{@versionfile}}
+ end
+ end
+ end
+
+ def mktasktrac_version
+ task :trac_version => [:update_version] do
+ tracpath = "/opt/rl/trac/#{@name}"
+
+ unless FileTest.exists?(tracpath)
+ announce "No Trac instance at %s" % tracpath
+ else
+ output = %x{sudo trac-admin #{tracpath} version list}.chomp.split("\n")
+ versions = {}
+ output[3..-1].each do |line|
+ name, time = line.chomp.split(/\s+/)
+ versions[name] = time
+ end
+
+ if versions.include?(@version)
+ announce "Version #{@version} already in Trac"
+ else
+ announce "Adding #{@name} version #{@version} to Trac"
+ date = [Time.now.year.to_s,
+ Time.now.month.to_s,
+ Time.now.day.to_s].join("-")
+ system("sudo trac-admin #{tracpath} version add #{@version} #{date}")
+ end
+ end
+ end
+ end
+
+ # Create the tag task.
+ def mktasktag
+ desc "Tag all the files with the latest release number (REL=x.y.z)"
+ task :tag => [:prerelease] do
+ reltag = @version
+ announce "Tagging with [#{reltag}]"
+
+ if ENV['RELTEST']
+ announce "Release Task Testing, skipping tagging"
+ else
+ sh %{git tag #{reltag}}
+ end
+ end
+ end
+
+ # Create the task for testing across all hosts.
+ def mktaskhosttest
+ desc "Test Puppet on each test host"
+ task :hosttest do
+ out = ""
+ TESTHOSTS.each { |host|
+ puts "testing %s" % host
+ cwd = Dir.getwd
+ file = "/tmp/#{@name}-#{host}test.out"
+ system("ssh #{host} 'cd git/#{@name}/test; sudo rake' 2>&1 >#{file}")
+
+ if $? != 0
+ puts "%s failed; output is in %s" % [host, file]
+ end
+ }
+ end
+ end
+
+ def mktaskri
+ # Create a task to build the RDOC documentation tree.
+
+ #Rake::RDocTask.new("ri") { |rdoc|
+ # #rdoc.rdoc_dir = 'html'
+ # #rdoc.template = 'html'
+ # rdoc.title = "Puppet"
+ # rdoc.options << '--ri' << '--line-numbers' << '--inline-source' << '--main' << 'README'
+ # rdoc.rdoc_files.include('README', 'COPYING', 'CHANGELOG')
+ # rdoc.rdoc_files.include('lib/**/*.rb', 'doc/**/*.rdoc')
+ #}
+
+ if $features[:rdoc]
+ task :ri do |ri|
+ files = ['README', 'COPYING', 'CHANGELOG'] + Dir.glob('lib/**/*.rb')
+ puts "files are \n%s" % files.join("\n")
+ begin
+ ri = RDoc::RDoc.new
+ ri.document(["--ri-site"] + files)
+ rescue RDoc::RDocError => detail
+ puts "Failed to build docs: %s" % detail
+ return nil
+ rescue LoadError
+ puts "Missing rdoc; cannot build documentation"
+ return nil
+ end
+ end
+ else
+ warn "No rdoc; skipping ri."
+ end
+ end
+
+ desc "Install the application using the standard install.rb script"
+ task :install do
+ ruby "install.rb"
+ end
+
+ def mktaskdefault
+ if dtask = self.defaulttask
+ desc "Default task"
+ task :default => dtask
+ end
+ end
+
+ desc "Run all unit tests."
+ task :alltests do
+ if FileTest.exists?("test/Rakefile")
+ sh %{cd test; rake}
+ else
+ Dir.chdir("test") do
+ Dir.entries(".").find_all { |f| f =~ /\.rb/ }.each do |f|
+ sh %{ruby #{f}}
+ end
+ end
+ end
+ end
+
+ desc "List all ruby files"
+ task :rubyfiles do
+ puts Dir['**/*.rb'].reject { |fn| fn =~ /^pkg/ }
+ puts Dir['**/bin/*'].reject { |fn| fn =~ /svn|(~$)|(\.rb$)/ }
+ end
+
+ desc "Look for TODO and FIXME tags in the code"
+ task :todo do
+ egrep "/#.*(FIXME|TODO|TBD)/"
+ end
+
+ # This task requires extra information from the Rake file.
+ def mkgemtask
+ # ====================================================================
+ # Create a task that will package the Rake software into distributable
+ # tar, zip and gem files.
+ if ! defined?(Gem)
+ puts "Package Target requires RubyGEMs"
+ else
+ spec = Gem::Specification.new { |s|
+
+ #### Basic information.
+
+ s.name = self.name
+ s.version = self.version
+ s.summary = self.summary
+ s.description = self.description
+ s.platform = Gem::Platform::RUBY
+
+ #### Dependencies and requirements.
+
+ # I'd love to explicitly list all of the libraries that I need,
+ # but gems seem to only be able to handle dependencies on other
+ # gems, which is, um, stupid.
+ self.requires.each do |name, version|
+ s.add_dependency(name, ">= #{version}")
+ end
+
+ s.files = filelist.to_a
+
+ #### Signing key and cert chain
+ #s.signing_key = '/..../gem-private_key.pem'
+ #s.cert_chain = ['gem-public_cert.pem']
+
+ #### Author and project details.
+
+ s.author = [self.author]
+ s.email = self.email
+ s.homepage = self.url
+ s.rubyforge_project = self.rfproject
+
+ yield s
+ }
+
+ Rake::GemPackageTask.new(spec) { |pkg|
+ pkg.need_tar = true
+ }
+
+ desc "Copy the newly created package into the downloads directory"
+ task :publish => [:package] do
+ puts Dir.getwd
+ sh %{cp pkg/#{@name}-#{@version}.gem #{self.publishdir}/gems}
+ sh %{gem generate_index -d #{self.publishdir}}
+ sh %{cp pkg/#{@name}-#{@version}.tgz #{self.pkgpublishdir}}
+ sh %{ln -sf #{@name}-#{@version}.tgz #{self.pkgpublishdir}/#{@name}-latest.tgz}
+ end
+ CLEAN.include("pkg")
+ end
+ end
+end