RPM and Yum Rake Tasks Sep 5, 2011
As part of our dev and release cycle for aeolus we build alot of rpms and yum repositories.
To help with this process, especially for the aeolus puppet configuration recipes, we whipped up a couple of rake tasks to create rpms and yum repositories.
The latest versions of the tasks can be found here and can simply be included in your Rakefile as such:
require 'rubygems'
require 'rake/rpmtask'
require 'rake/yumtask'
CURRENT_DIR = File.dirname(__FILE__)
YUM_REPO = "#{CURRENT_DIR}/repo"
RPM_SPEC = "my-package.spec"
# Build the rpm
rpm_task =
Rake::RpmTask.new(RPM_SPEC) do |rpm|
rpm.need_tar = true
rpm.package_files.include("bin/*", "recipes/**/*")
rpm.topdir = "#{RPMBUILD_DIR}"
end
# Construct yum repo
Rake::YumTask.new(YUM_REPO) do |repo|
repo.rpms << rpm_task.rpm_file
end
And without further ado, here is the rpm task
# Define a package task library to aid in the definition of RPM
# packages.
require 'rubygems'
require 'rake'
require 'rake/packagetask'
require 'rbconfig' # used to get system arch
module Rake
# Create a package based upon a RPM spec.
# RPM packages, can be produced by this task.
class RpmTask < PackageTask
# RPM spec containing the metadata for this package
attr_accessor :rpm_spec
# RPM build dir
attr_accessor :topdir
# Include extra_release information in the rpm
attr_accessor :include_extra_release
def initialize(rpm_spec)
init(rpm_spec)
yield self if block_given?
define if block_given?
end
def init(rpm_spec)
@include_extra_release = true
@rpm_spec = rpm_spec
# parse this out of the rpmbuild macros,
# not ideal but better than hardcoding this
File.open('/etc/rpm/macros.dist', "r") { |f|
f.read.scan(/%dist\s*\.(.*)\n/)
@distro = $1
}
# Parse rpm name / version out of spec
# hacky way to do this for now
# (would be nice to implement a full blown rpm spec parser for ruby)
File.open(rpm_spec, "r") { |f|
contents = f.read
@name = contents.scan(/\nName: .*\n/).first.split.last
@version = contents.scan(/\nVersion: .*\n/).first.split.last
@release = contents.scan(/\nRelease: .*\n/).first.split.last
@release.gsub!("%{?dist}", ".#{@distro}")
@arch = contents.scan(/\nBuildArch: .*\n/) # TODO grab local arch if not defined
if @arch.nil?
@arch = Config::CONFIG["target_cpu"] # hoping this will work for all cases,
# can just run the 'arch' cmd if we want
else
@arch = @arch.first.split.last
end
}
super(@name, @version)
@rpmbuild_cmd = 'rpmbuild'
end
def define
super
directory "#{@topdir}/SOURCES"
directory "#{@topdir}/SPECS"
desc "Build the rpms"
task :rpms, [:include_extra_release] => [rpm_file]
# FIXME properly determine :package build artifact(s) to copy to sources dir
file rpm_file, [:include_extra_release] => [:package, "#{@topdir}/SOURCES", "#{@topdir}/SPECS"] do |t,args|
@include_extra_release = args.include_extra_release != "false"
git_head = `git log -1 --pretty=format:%h`
extra_release = "." + Time.now.strftime("%Y%m%d%k%M%S").gsub(/\s/, '') + "git" + "#{git_head}"
cp "#{package_dir}/#{@name}-#{@version}.tgz", "#{@topdir}/SOURCES/"
cp @rpm_spec, "#{@topdir}/SPECS"
sh "#{@rpmbuild_cmd} " +
"--define '_topdir #{@topdir}' " +
"--define 'extra_release #{@include_extra_release ? extra_release : ''}' " +
"-ba #{@rpm_spec}"
end
end
def rpm_file
# at some point we should support all a spec's subpackages as well
"#{@topdir}/RPMS/#{@arch}/#{@name}-#{@version}-#{@release}.#{@arch}.rpm"
end
end
end
And here is the yum task
# Define a package task library to aid in the definition of YUM
# repos.
require 'rubygems'
require 'rake'
module Rake
# Create a yum repo with specified rpms
class YumTask < TaskLib
# Yum repository location which to build
attr_accessor :yum_repo
# RPMs to pull into yum repo
attr_accessor :rpms
def initialize(yum_repo)
init(yum_repo)
yield self if block_given?
define if block_given?
end
def init(yum_repo)
@yum_repo = yum_repo
@createrepo_cmd = 'createrepo'
@rpms = []
end
def define
desc "Build the yum repo"
task :create_repo => @rpms do
@rpms.each { |rpm|
rpmc = rpm.split('.')
arch = rpmc[rpmc.size-2]
arch_dir = @yum_repo + "/" + arch
FileUtils.mkdir_p arch_dir unless File.directory? arch_dir
cp_r rpm, "#{@yum_repo}/#{arch}"
}
sh "#{@createrepo_cmd} -v #{@yum_repo}"
end
end
end
end
Have at it!