Prototype mock builder and yum releaser.

Still with configuration hard coded, but demonstrates building via mock,
and then assembling built packages into a yum repository.
This commit is contained in:
Devan Goodwin 2011-10-12 12:14:41 -03:00 committed by Devan Goodwin
parent fd4af9ef85
commit 7b449a2d7b
3 changed files with 150 additions and 24 deletions

View file

@ -69,14 +69,14 @@ class Builder(object):
for options in pkg_config.options(section):
if not self.config.has_section(section):
self.config.add_section(section)
self.config.set(section, options,
self.config.set(section, options,
pkg_config.get(section, options))
if self.config.has_section("requirements"):
if self.config.has_option("requirements", "tito"):
if loose_version(self.config.get("requirements", "tito")) > \
loose_version(require('tito')[0].version):
print("Error: tito version %s or later is needed to build this project." %
print("Error: tito version %s or later is needed to build this project." %
self.config.get("requirements", "tito"))
print("Your version: %s" % require('tito')[0].version)
sys.exit(-1)
@ -112,7 +112,7 @@ class Builder(object):
# Set to true if we've already created a tgz:
self.ran_tgz = False
# Used to make sure we only modify the spec file for a test build
# Used to make sure we only modify the spec file for a test build
# once. The srpm method may be called multiple times during koji
# releases to create the proper disttags, but we only want to modify
# the spec file once.
@ -198,7 +198,7 @@ class Builder(object):
cmd = ('LC_ALL=C rpmbuild --define "_source_filedigest_algorithm md5" --define'
' "_binary_filedigest_algorithm md5" %s %s %s --nodeps -bs %s' % (
self.rpmbuild_options, self._get_rpmbuild_dir_options(),
self.rpmbuild_options, self._get_rpmbuild_dir_options(),
define_dist, self.spec_file))
output = run_command(cmd)
print(output)
@ -219,7 +219,7 @@ class Builder(object):
define_dist = "--define 'dist %s'" % self.dist
cmd = ('LC_ALL=C rpmbuild --define "_source_filedigest_algorithm md5" '
'--define "_binary_filedigest_algorithm md5" %s %s %s --clean '
'-ba %s' % (self.rpmbuild_options,
'-ba %s' % (self.rpmbuild_options,
self._get_rpmbuild_dir_options(), define_dist, self.spec_file))
try:
output = run_command(cmd)
@ -690,7 +690,7 @@ class UpstreamBuilder(NoTgzBuilder):
def patch_upstream(self):
"""
Generate patches for any differences between our tag and the
upstream tag, and apply them into an exported copy of the
upstream tag, and apply them into an exported copy of the
spec file.
"""
patch_filename = "%s-to-%s-%s.patch" % (self.upstream_tag,
@ -699,14 +699,14 @@ class UpstreamBuilder(NoTgzBuilder):
patch_filename)
patch_dir = self.git_root
if self.relative_project_dir != "/":
patch_dir = os.path.join(self.git_root,
patch_dir = os.path.join(self.git_root,
self.relative_project_dir)
os.chdir(patch_dir)
debug("patch dir = %s" % patch_dir)
print("Generating patch [%s]" % patch_filename)
debug("Patch: %s" % patch_file)
patch_command = "git diff --relative %s..%s > %s" % \
(self.upstream_tag, self.git_commit_id,
(self.upstream_tag, self.git_commit_id,
patch_file)
debug("Generating patch with: %s" % patch_command)
output = run_command(patch_command)
@ -772,3 +772,70 @@ class UpstreamBuilder(NoTgzBuilder):
class SatelliteBuilder(UpstreamBuilder):
pass
class MockBuilder(Builder):
"""
Uses the mock tool to create a chroot for building packages for a different
OS version than you may be currently using.
"""
def __init__(self, name=None, version=None, tag=None, build_dir=None,
pkg_config=None, global_config=None, user_config=None, options=None):
Builder.__init__(self, name=name, version=version, tag=tag,
build_dir=build_dir, pkg_config=pkg_config,
global_config=global_config, user_config=user_config,
options=options)
self.mock_tag = "fedora-15-x86_64"
#self.mock_tag = "epel-6-x86_64"
#self.mock_tag = "fedora-14-x86_64"
#self.mock_tag = "epel-5-x86_64"
# TODO: error out if mock package is not installed
def _rpm(self):
"""
Uses the SRPM
Override the base builder rpm method.
"""
print("Creating rpms for %s-%s in mock: %s" % (
self.project_name, self.display_version, self.mock_tag))
if not self.srpm_location:
self.srpm()
print("Using srpm: %s" % self.srpm_location)
self._build_in_mock()
def _build_in_mock(self):
print("Initializing mock:\n")
output = run_command("mock -r %s --init" % self.mock_tag)
print output
print("\nInstalling deps:\n")
output = run_command("mock -r %s --installdeps %s" % (
self.mock_tag, self.srpm_location))
print output
#print("\nCopying:\n")
#output = run_command("mock -r %s --copyin %s /tmp" % (
# self.mock_tag, self.srpm_location))
#print output
print("\nRebuilding:\n")
output = run_command('mock -r %s --rebuild %s' %
(self.mock_tag, self.srpm_location))
print output
print("\nCopying resulting rpms:\n")
mock_output_dir = os.path.join(self.rpmbuild_dir, "mockoutput")
output = run_command("mock -r %s --copyout /builddir/build/RPMS/ %s" %
(self.mock_tag, mock_output_dir))
print output
# Copy everything mock wrote out to /tmp/tito:
files = os.listdir(mock_output_dir)
run_command("cp %s/*.rpm %s" %
(mock_output_dir, self.rpmbuild_basedir))
print
print("Wrote:")
for rpm in files:
rpm_path = os.path.join(self.rpmbuild_basedir, rpm)
print(" %s" % rpm_path)
self.artifacts.append(rpm_path)

View file

@ -127,7 +127,7 @@ class BaseCliModule(object):
default=False)
default_output_dir = lookup_build_dir(self.user_config)
self.parser.add_option("-o", "--output", dest="output_dir",
self.parser.add_option("-o", "--output", dest="output_dir",
metavar="OUTPUTDIR", default=default_output_dir,
help="Path to write temp files, tarballs and rpms to. "
"(default %s)"
@ -154,7 +154,7 @@ class BaseCliModule(object):
# Check if global config defines a custom lib dir:
if self.global_config.has_option(GLOBALCONFIG_SECTION,
"lib_dir"):
lib_dir = self.global_config.get(GLOBALCONFIG_SECTION,
lib_dir = self.global_config.get(GLOBALCONFIG_SECTION,
"lib_dir")
if lib_dir[0] != '/':
# Looks like a relative path, assume from the git root:
@ -228,7 +228,7 @@ class BaseCliModule(object):
else:
# HACK: Check for legacy build.py.props naming, needed to support
# older tags:
current_props_file = os.path.join(os.getcwd(),
current_props_file = os.path.join(os.getcwd(),
"build.py.props")
if (os.path.exists(current_props_file)):
properties_file = current_props_file
@ -309,7 +309,7 @@ class BuildModule(BaseCliModule):
help="Build srpm")
self.parser.add_option("--rpm", dest="rpm", action="store_true",
help="Build rpm")
self.parser.add_option("-i", "--install", dest="auto_install",
self.parser.add_option("-i", "--install", dest="auto_install",
action="store_true", default=False,
help="Install any binary rpms being built. (WARNING: " + \
"uses sudo rpm -Uvh --force)")
@ -326,7 +326,7 @@ class BuildModule(BaseCliModule):
"(i.e. spacewalk-java-0.4.0-1)")
self.parser.add_option("--release", dest="release",
action="store_true", help="DEPRECATED: please use 'tito release' instead.")
action="store_true", help="DEPRECATED: please use 'tito release' instead.")
self.parser.add_option("--list-tags", dest="list_tags",
action="store_true",
@ -430,6 +430,7 @@ class ReleaseModule(BaseCliModule):
'cvs': 'tito.release.CvsReleaser',
'koji': 'tito.release.KojiReleaser',
'fedora-git': 'tito.release.FedoraGitReleaser',
'yum-mock': 'tito.release.YumRepoMockReleaser'
}
# Load all custom releasers configured:
@ -510,7 +511,7 @@ class TagModule(BaseCliModule):
help=("Automatically accept the generated changelog."))
self.parser.add_option("--auto-changelog-message",
dest="auto_changelog_msg", metavar="MESSAGE",
dest="auto_changelog_msg", metavar="MESSAGE",
help=("Use MESSAGE as the default changelog message for "
"new packages"))
@ -667,7 +668,7 @@ class ReportModule(BaseCliModule):
continue
f = open(os.path.join(package_metadata_dir, md_file))
(version, relative_dir) = f.readline().strip().split(" ")
# Hack for single project git repos:
if relative_dir == '/':
relative_dir = ""

View file

@ -22,6 +22,9 @@ import pyfedpkg
import tempfile
import subprocess
from tempfile import mkdtemp
from shutil import rmtree, copy
from tito.common import *
DEFAULT_KOJI_OPTS = "build --nowait"
@ -36,7 +39,7 @@ class Releaser(object):
def __init__(self, name=None, version=None, tag=None, build_dir=None,
pkg_config=None, global_config=None, user_config=None):
# While we create a builder here, we don't actually call run on it
# While we create a builder here, we don't actually call run on it
# unless the releaser needs to:
self.builder = create_builder(name, tag,
version, None, pkg_config,
@ -158,11 +161,71 @@ class Releaser(object):
return new_files, copied_files, old_files
class YumRepoMockReleaser(Releaser):
"""
A releaser which will rsync down a yum repo, build the desired packages,
plug them in, update the repodata, and push the yum repo back out.
Building of the packages is done via mock.
WARNING: This will not work in all
situations, depending on the current OS, and the mock target you
are attempting to use.
"""
def __init__(self, name=None, version=None, tag=None, build_dir=None,
pkg_config=None, global_config=None, user_config=None):
Releaser.__init__(self, name, version, tag, build_dir, pkg_config,
global_config, user_config)
self.build_dir = build_dir
# Override to use the mock builder:
from tito.builder import MockBuilder
self.builder = MockBuilder(name=name, tag=tag, version=version,
options=None,
pkg_config=pkg_config,
build_dir=build_dir,
global_config=global_config,
user_config=user_config)
def release(self, dry_run=False):
# Should this run?
self.builder.tgz()
self.builder.srpm()
self.builder._rpm()
self.builder.cleanup()
print "RPMS:"
print self.builder.artifacts
# TODO: username
rsync_location = "fedorapeople.org:/srv/repos/candlepin/subscription-manager/fedora-15/x86_64/"
# Make a temp directory to sync the existing repo contents into:
yum_temp_dir = mkdtemp(dir=self.build_dir, prefix="tito-yumrepo-")
debug("Copying existing yum repo to:: %s" % yum_temp_dir)
run_command("rsync -avtz %s %s" % (rsync_location, yum_temp_dir))
for artifact in self.builder.artifacts:
if artifact.endswith(".rpm") and not artifact.endswith(".src.rpm"):
copy(artifact, yum_temp_dir)
print("Copied %s to yum repo." % artifact)
os.chdir(yum_temp_dir)
output = run_command("createrepo ./")
print output
# TODO: Cleanup
#rmtree(yum_temp_dir)
class FedoraGitReleaser(Releaser):
def __init__(self, name=None, version=None, tag=None, build_dir=None,
pkg_config=None, global_config=None, user_config=None):
Releaser.__init__(self, name, version, tag, build_dir, pkg_config,
Releaser.__init__(self, name, version, tag, build_dir, pkg_config,
global_config, user_config)
self.git_branches = []
@ -209,8 +272,6 @@ class FedoraGitReleaser(Releaser):
main_branch = self.git_branches[0]
os.chdir(project_checkout)
(status, diff_output) = commands.getstatusoutput("git diff --cached")
@ -278,9 +339,6 @@ class FedoraGitReleaser(Releaser):
sys.stderr.write(" Output: %s" % output)
sys.exit(1)
def _can_build_in_git(self):
"""
Return True if this repo and branch is configured to build in
@ -356,7 +414,7 @@ class CvsReleaser(Releaser):
def __init__(self, name=None, version=None, tag=None, build_dir=None,
pkg_config=None, global_config=None, user_config=None):
Releaser.__init__(self, name, version, tag, build_dir, pkg_config,
Releaser.__init__(self, name, version, tag, build_dir, pkg_config,
global_config, user_config)
# Configure CVS variables if possible. Will check later that
@ -616,7 +674,7 @@ class KojiReleaser(Releaser):
def __init__(self, name=None, version=None, tag=None, build_dir=None,
pkg_config=None, global_config=None, user_config=None):
Releaser.__init__(self, name, version, tag, build_dir, pkg_config,
Releaser.__init__(self, name, version, tag, build_dir, pkg_config,
global_config, user_config)
self.only_tags = self.builder.only_tags