# HG changeset patch # User Bernhard Herzog # Date 1175609375 -7200 # Node ID e1028211d34b41c3d3de83b1ef2e5141fc3373ec # Parent 3e610233ccfece86e9d8dee1448c2e0d89b18cdd# Parent 225206553bba1fed9868513b5bea14c85c7fd6ce merge diff -r 3e610233ccfe -r e1028211d34b README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Tue Apr 03 16:09:35 2007 +0200 @@ -0,0 +1,101 @@ +README for TreePackager +======================= +2007-03-19, Bernhard Herzog + + +TreePackager is a tool to automatically build debian packages from SVN. + + +Prerequisites +------------- + +You need the following software to run TreePackager. In the list below, +parentheses contain the name of the corresponding package in Debian Etch +if its not the same as the software. The version required is usually +the one from debian etch. + + Python 2.4 (python2.4-minimal) + Debian devscripts (devscripts) + subversion + pbuilder + sudo + bzip2 + +For the web front-end you also need the following software: + + Genshi (python-genshi) + CherryPy (python-cherrypy) + +Some of the packagers require additional software. The KDEPIM +enterprise branch packagers require the following additional software: + + autoconf2.13 + automake1.9 + + +Installation +------------ + +You can run the tree packager itself directly from the source tree. +However, you need to configure it first and setup pbuilder. + + +Configuration +------------- + +To understand the configuration, first a few notes about the +architecture of TreePackager. The TreePackager consist of one program +that periodically updates svn working directories and if something has +changed, builds a new debian package from the working directory. The +program should run as a normal user. The sample configuration assumes +that it's the user "builder" with a home directory "/home/builder". The +default configuration manages a directory tree under +"/home/builder/enterprise". + +The binary packages are built with pbuilder. Because pbuilder uses a +chroot environment to build the packages, it must be run as root. The +tree packager therefore needs a way to run pbuilder as root even though +itself runs as a non-root user. By default the tree packager uses sudo, +so you have to setup sudo to allow the tree packager user to invoke +pbuilder without a password. This can be accomplished with the +following line in /etc/sudoers (using the default user name): + + builder ALL = NOPASSWD: /usr/sbin/pbuilder + + +Configure TreePackager +~~~~~~~~~~~~~~~~~~~~~~ + +The file demo.cfg contains example configuration that contains most of +what is needed to package KDEPIM and kde-i18n from the KDEPIM enterprise +branch. Copy this file to treepkg.cfg and adapt it to your needs. The +comments in the file should provide enough hints to get you started. + + +Configure pbuilder +~~~~~~~~~~~~~~~~~~ + +It's best to give the tree packager its own pbuilder configuration and +directories. The default configuration uses a "pbuilder" subdirectory +in /home/builder/enterprise. If you have created the treepkg.cfg file +with at least one packager and the correct root_cmd and pbuilderrc +options (the defaults for both should be OK if you use sudo as described +above), you can create the directories, the pbuilder configuration and +the chroot environment with the script initpbuilder.py like this: + + ./initpbuilder.py --mirrorsite= + +You can specify some more mirrors with the --othermirror option. For +more information run "./initpbuilder.py --help" and consult the pbuilder +documentation. + + +Configure the web front-end +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The default configuration should be OK in most cases. If you want you +can customize it in cherrypy.cfg. Start the web front-end with + + ./starttreepkgweb.py + +starttreepkgweb has some options to specify which configuration files to use. diff -r 3e610233ccfe -r e1028211d34b demo.cfg --- a/demo.cfg Tue Mar 20 17:27:46 2007 +0100 +++ b/demo.cfg Tue Apr 03 16:09:35 2007 +0200 @@ -23,6 +23,14 @@ # specific values root_cmd: sudo +# The pbuilder config file to use. It should be an absolute filename. +# The script initpbuilder.py can create it and the rest of the pbuilder +# files and directories. You can override this in the pkg_ sections for +# individual packagers if necessaary. You will have to adapt pbuilder +# yourself, then, though. +pbuilderrc: %(treepkg_dir)s/pbuilder/pbuilderrc + + # Email address and name to use as the packager in the debian packages. # You can override this in the pkg_ sections if you need package # specific values diff -r 3e610233ccfe -r e1028211d34b initpbuilder.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/initpbuilder.py Tue Apr 03 16:09:35 2007 +0200 @@ -0,0 +1,128 @@ +#! /usr/bin/python2.4 +# Copyright (C) 2007 by Intevation GmbH +# Authors: +# Bernhard Herzog +# +# This program is free software under the GPL (>=v2) +# Read the file COPYING coming with the software for details. + +"""Script to initialize the pbuilder environment for the tree packager + +The script assumes that the config file for the tree packager already +contains the pbuilder settings. Also, this script assumes that there is +only one pbuilder setting for all packagers. +""" + +import sys +import os +from optparse import OptionParser + +from treepkg.packager import create_package_line, PackagerGroup +from treepkg.readconfig import read_config +from treepkg.util import ensure_directory, writefile +from treepkg.run import call + + +pbuilderrc_template = '''\ +# This file was automatically generated by initpbuilder.py. +# for the possible settings see "man pbuilderrc" + +BASETGZ=%(basedir)s/base.tgz +BUILDPLACE=%(builddir)s +USEPROC=yes +USEDEVPTS=yes +BUILDRESULT=%(resultdir)s +DISTRIBUTION=%(distribution)s +APTCACHE=%(basedir)s/aptcache +APTCACHEHARDLINK=yes +REMOVEPACKAGES=lilo +MIRRORSITE="%(mirrorsite)s" +OTHERMIRROR="%(othermirror)s" +BINDMOUNTS="%(extra-pkgdir)s" +PKGNAME_LOGFILE=yes +''' + + +def init_pbuilder(pbuilderrc, distribution, mirrorsite, extramirrors, root_cmd): + if not os.path.isabs(pbuilderrc): + print >>sys.stderr, "pbuilderrc must be an absolute filename" + sys.exit(1) + + if os.path.exists(pbuilderrc): + print >>sys.stderr, "pbuilderrc %r already exists." % pbuilderrc + sys.exit(1) + + basedir = os.path.dirname(pbuilderrc) + replacements = dict(basedir=basedir, + distribution=distribution, + mirrorsite=mirrorsite) + + # create the pbuilder directories. basedir is created implicitly by + # creating its subdirectories. + for subdir in ["base", "build", "result", "aptcache", "extra-pkg"]: + directory = os.path.join(basedir, subdir) + replacements[subdir + "dir"] = directory + print "creating directory:", repr(directory) + ensure_directory(directory) + + # build OTHERMIRROR value. We always include the extra-pkg dir. + othermirror = "deb file://%(extra-pkgdir)s ./" % replacements + if extramirrors: + othermirror += " | " + extramirrors + replacements["othermirror"] = othermirror + + # create the pbuilderrcfile + print "creating pbuilderrc:", repr(pbuilderrc) + writefile(pbuilderrc, pbuilderrc_template % replacements) + + # turn the extra-pkg directory into a property deb archive + print "turn the extra-pkg dir into a debian archive" + extra_pkgdir = replacements["extra-pkgdir"] + call(["apt-ftparchive", "packages", "."], + stdout=open(os.path.join(extra_pkgdir, "Packages"), "w"), + cwd=extra_pkgdir) + + # create the base.tgz chroot + print "Run pbuilder create" + call(root_cmd + ["pbuilder", "create", "--configfile", pbuilderrc]) + + +def parse_commandline(): + parser = OptionParser() + parser.set_defaults(config_file=os.path.join(os.path.dirname(__file__), + "treepkg.cfg"), + distribution="etch") + parser.add_option("--config-file", + help=("The tree packager config file." + " Default is treepkg.cfg")) + parser.add_option("--mirrorsite", + help=("The debian mirror site" + " (pbuilder MIRRORSITE setting). Required.")) + parser.add_option("--othermirror", + help=("Extra contents of the OTHERMIRROR setting." + " See the pbuilder documentation for the format.")) + parser.add_option("--distribution", + help=("The debian distribution for the pbuilder chroot." + " Default is etch.")) + return parser.parse_args() + + +def main(): + options, args = parse_commandline() + + if options.mirrorsite is None: + print >>sys.stderr, "Missing required option --mirrorsite" + sys.exit(1) + + treepkg_opts, packager_opts = read_config(options.config_file) + group = PackagerGroup([create_package_line(**opts) + for opts in packager_opts], + **treepkg_opts) + pkg_line = group.get_package_lines()[0] + init_pbuilder(pkg_line.pbuilderrc, + distribution=options.distribution, + mirrorsite=options.mirrorsite, + extramirrors=options.othermirror, + root_cmd=pkg_line.root_cmd) + +main() diff -r 3e610233ccfe -r e1028211d34b treepkg/packager.py --- a/treepkg/packager.py Tue Mar 20 17:27:46 2007 +0100 +++ b/treepkg/packager.py Tue Apr 03 16:09:35 2007 +0200 @@ -188,9 +188,12 @@ util.ensure_directory(self.binary_dir) logging.info("Building binary package; loging to %r", self.logfile) run.call(cmdexpand("@rootcmd /usr/sbin/pbuilder build" + " --configfile $pbuilderrc" " --logfile $logfile --buildresult $bindir $dsc", - rootcmd=self.pkg_line.root_cmd, logfile=self.logfile, - bindir=self.binary_dir, dsc=self.dsc_file), + rootcmd=self.pkg_line.root_cmd, + pbuilderrc=self.pkg_line.pbuilderrc, + logfile=self.logfile, bindir=self.binary_dir, + dsc=self.dsc_file), suppress_output=True) self.status.binary_package_created() @@ -257,12 +260,13 @@ extra_config_desc = [] - def __init__(self, name, base_dir, svn_url, root_cmd, deb_email, + def __init__(self, name, base_dir, svn_url, root_cmd, pbuilderrc, deb_email, deb_fullname, packager_class="treepkg.packager"): self.name = name self.base_dir = base_dir self.svn_url = svn_url self.root_cmd = root_cmd + self.pbuilderrc = pbuilderrc self.deb_email = deb_email self.deb_fullname = deb_fullname self.pkg_dir_template = "%(revision)d-%(increment)d" diff -r 3e610233ccfe -r e1028211d34b treepkg/readconfig.py --- a/treepkg/readconfig.py Tue Mar 20 17:27:46 2007 +0100 +++ b/treepkg/readconfig.py Tue Apr 03 16:09:35 2007 +0200 @@ -17,7 +17,7 @@ packager_desc = [ "name", "base_dir", "svn_url", "packager_class", - ("root_cmd", shlex.split), + ("root_cmd", shlex.split), "pbuilderrc", "deb_email", "deb_fullname", ]