#!/usr/bin/env python # vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 # -*- coding: utf-8 -*- import sys import os import argparse import json import build_functions import logging import re import subprocess import commands import shutil import git import distutils.dir_util print os.environ.get("USER") ####################################################### parser = argparse.ArgumentParser( description='Automate NSS builds using mock.', add_help=True, conflict_handler='resolve', epilog='Program designed to be used both on the command line or by cron') parser.add_argument("-ver", "--version", action='version', default= "0.9 beta", help="set version number") parser.add_argument("-d", "--debug", action="store_true", default=True, help="show debug output") parser.add_argument("-t", "--test", action="store_true", default=False, help="test mode (for debugging)") parser.add_argument('-f', '--flavor', action="store", dest="flavor", default='nss', help='specify the flavor of the build. [default=nss]') #parser.add_argument('-p', # '--platform', # action="store", # dest="platform", # default=None, # help='specify a platform to use for mock config. [default=None] NOT IMPLEMENTED') parser.add_argument('-r', '--rel', action="store", dest="rel", default=None, choices=("rawhide", "f25" ), help='specify a release to use for mock config. [default=None]') parser.add_argument('-a', '--arch', action="store", dest="arch", default=None, choices=("i386", "x86_64"), help='specify an arch to use for mock config. [default=None]') parser.add_argument('-l', '--local', action="store_true", dest="localBuild", default=True, help='perform a build in the current working diretory. [default=False]') parser.add_argument('-mm', '--mailme', action="store_true", dest="mailMe", default=False, help='send email to emaldona@redhat.com. [default=False]') parser.add_argument('-sb', '--skipbuild', action="store_true", dest="skipBuild", default=False, help='skip the build portion of the program. [default=False] ') parser.add_argument('-sc', '--skipcopy', action="store_true", dest="skipCopy", default=True, help='skip the copy portion of the program. [default=True] ') parser.add_argument('-sw', '--skipwget', action="store_true", dest="skipWget", default=True, help='skip the wget portion of the program. [default=True] ') parser.add_argument('-b', '--build', action='store', dest='nssPackageList', nargs='+', default=['nspr', 'nss-util', 'nss-softokn', 'nss' ], help='specify a list of one of more builds to perform. ', choices=('nspr', 'nss-util', 'nss-softokn', 'nss')) parser.add_argument('-c', '--clients', action='store', dest='clientPackageList', nargs='+', default=[ '' ], help='specify a list of one of more builds to perform. ', choices=('mod_nss', 'mod_revocator', 'curl', 'evolution-data-server', 'libreswan', 'xulrunner')) parser.add_argument('-m', '--mock_cfg', action="store", dest="mockCfgList", nargs='+', default=["fedora-rawhide-i386", "fedora-rawhide-x86_64"], help='specify a list of one or more mock configs to use. [default = fedora-rawhide-i386", "fedora-rawhide-x86_64]', choices=("fedora-rawhide-i386", "fedora-rawhide-x86_64")) parser.add_argument("-nc", "--no-cleanup-after", action='store_true', dest="noCleanupAfter", default= "True", help="don't cleanup the buildroot first") options = parser.parse_args() #if args.servername is None and not args.dry_run: def print_debug(msg): if options.debug: print "DEBUG: %s" % (msg) #TODO: figure out some logic about which parameters can be used together ####################################################### workbase = os.environ['HOME'] scriptsDir = workbase + "/scripts" pythonDir=scriptsDir + "/build" sys.path.append(pythonDir) from build_functions import * ####################################################### if options.test: options.debug = True options.mailMe = True if options.skipCopy: options.skipWget = True if options.skipBuild and options.nssPackageList: print "INFO: --skipBuild and --build cannot be used together" print_debug("test = %s " % options.test) print_debug("debug = %s " % options.debug) #print_debug("platform = %s " % options.platform) print_debug("release = %s " % options.rel) print_debug("arch = %s " % options.arch) print_debug("flavor = %s " % options.flavor) print_debug("mailMe = %s " % options.mailMe) print_debug("localBuild = %s " % options.localBuild) print_debug("skipBuild = %s " % options.skipBuild) print_debug("skipCopy = %s " % options.skipCopy) print_debug("skipWget = %s " % options.skipWget) print_debug("nssPackageList = %s " % options.nssPackageList) print_debug("clientPackageList = %s " % options.clientPackageList) print_debug("mockCfgList = %s " % options.mockCfgList) print_debug("noCleanupAfter = %s " % options.noCleanupAfter) ####################################################### mockCfgList=[] for mock_cfg in options.mockCfgList: [platform, rel, arch] = mock_cfg.split("-") if options.rel is not None: print_debug("Release = %s" % options.rel) mockCfgList.append("-".join([platform, options.rel, arch])) else: print_debug("Release not defined") mockCfgList = options.mockCfgList print_debug("mockCfgList = %s" % mockCfgList) for mock_cfg in options.mockCfgList: [platform, rel, arch] = mock_cfg.split("-") if options.arch is not None: print_debug("arch = %s" % options.arch) mockCfgList = [("-".join([platform, rel, options.arch]))] else: print_debug("arch not defined") mockCfgList = options.mockCfgList print_debug("mockCfgList = %s" % mockCfgList) ####################################################### #TODO use MAILTO or mailTo or receiver to pass as a arg #test to see if a variable is defined #try: #thevariable #except NameError: #print "well, it WASN'T defined after all!" #else: #print "sure, it was defined." ####################################################### #TODO use MAILTO or mailTo or receiver to pass as a arg if options.mailMe: mailTo="emaldona@redhat.com" else: mailTo="nss-nspr-devel@redhat.com" ####################################################### if options.localBuild is False: import datetime now = datetime.datetime.now() DT=now.strftime('%Y%m%d-%H%M%S') str(DT) buildDir = workbase + "/" + DT print_debug("DT = %s" % DT) else: buildDir = os.getcwd() DT=os.path.basename(buildDir) #need the DT for later when copying files. print_debug("DT = %s" % DT) print_debug("buildDir = %s" % buildDir) nssPackageList = options.nssPackageList clientPackageList = options.clientPackageList flavor = options.flavor ####################################################### progname = os.path.basename(__file__) message = "Subject: INFO: starting a build of from %s\n\nThe build directory is %s " % (progname, buildDir) #TODO. figure out how to send this email only to me. (ugh!) #email(message, mailTo) ####################################################### print_debug("Verifying the existence of the mock config file") mockDir = '/etc/mock' fileNameExt = '.cfg' for mock_cfg in mockCfgList: if os.path.isfile(os.path.join(mockDir, mock_cfg + fileNameExt)): print_debug("%s" % os.path.join(mockDir, mock_cfg + fileNameExt)) else: print "ERROR: %s doesn't exist." % os.path.join(mockDir, mock_cfg + fileNameExt) message = "Subject: ERROR: %s missing from /etc/mock\n\nERROR: %s missing from /etc/mock. Killing the build." % (mock_cfg + fileNameExt, mock_cfg) email(message, mailTo) sys.exit() ####################################################### buildStatusDict={} if options.skipBuild is False: for mock_cfg in mockCfgList: [platform, rel, arch] = mock_cfg.split("-") package = "nss" status = build_nss_pkgs(package, buildDir, mock_cfg, flavor, scriptsDir, options.debug, mailTo) buildStatusDict[('nss',mock_cfg)]=status print_debug("%s" % json.dumps(str(buildStatusDict), sort_keys=True, indent=4)) print_debug("package %s completed with status %s for %s" % ('nss', status, mock_cfg)) # TODO fix issue with failed build not stopping creating the repo # NOTE the problem appears to be if the x86_64 bit builds all complete # successfully, then the dict only shows those builds then it thinks the # build is okay. also, dogtag uses build_pki, whereas nss # uses build_generic_pkg -- this may not apply to nss #print_debug("%s" % buildStatusDict) print_debug("%s" % json.dumps(str(buildStatusDict), sort_keys=True, indent=4)) #TODO write the output of buildStatusDict to a file in the home directory. #This way, I can easily tell if anything failed. ################################################################################ # NOTE: handle whether or not to copy the files over and create the rpm repo. # The logic is as follows: # if any package fails to build, skipCopy gets enabled, don't copy # if the command line option skipCopy is enabled, don't copy # else if either skipCopy is disabled and the files get copied then the # yum repos are created. ################################################################################ skipCopy=False for mock_cfg in mockCfgList: for (package, status) in buildStatusDict: print_debug("%s" % buildStatusDict[package,mock_cfg]) if buildStatusDict[package,mock_cfg]=="FAILED": skipCopy=True print "ERROR: skipCopy is %s (enabled) due to a failure of package %s on %s. The repo will NOT be created)" % (skipCopy, package, mock_cfg) #TODO Add the code here to copy the build logs over possibly only for the packages the failed? if options.skipCopy is True: message = "Subject: INFO: skipCopy was enabled from the commandline. Skipping copying to and/or creating the repo.\n\nThe build directory is %s." % (buildDir) print message email(message, mailTo) elif skipCopy is True: status_message="" for (package, status) in buildStatusDict: status_message += "build status of package: %s on %s: %s\n" % (package, status, buildStatusDict[package,mock_cfg]) message = "Subject: ERROR: %s skipping copying to and/or creating the repo.\n\nERROR: The repo was not created due to a failure of one or more packages.\n\nHere's the list of builds and their status:\n\n%s\n" % (flavor, status_message) #TODO add code to copy the log files over somewhere when the build fails. createRepoDirs(mock_cfg, flavor, DT, buildDir, options.test, options.debug, mailTo) print_debug("%s" % message) email(message, mailTo) elif skipCopy is False: #for mock_cfg in mockCfgList: print_debug("copy the files to the repo for %s" % mock_cfg) copyToRepo(mock_cfg, flavor, DT, buildDir, options.test, options.debug, options.skipWget, mailTo) sys.exit() if __name__ == '__main__': import sys try: main(sys.argv[1]) except IndexError: main()