示例#1
0
    def runCLI(self, configFile, askToCreateRelease=False, forceSvnAuth=False):
        logger.info('-' * 79)
        logger.info(self.pkg)
        logger.info('-' * 79)
        logger.info('Start releasing new version of ' + self.pkg)
        # 1. Read the configuration file.
        logger.info('Loading configuration file: ' + configFile)
        config = ConfigParser.RawConfigParser()
        config.read(configFile)
        # 1.1. Get package index info.
        self.packageIndexUrl = config.get(
            base.BUILD_SECTION, 'package-index')
        self.packageIndexUsername = config.get(
            base.BUILD_SECTION, 'package-index-username')
        self.packageIndexPassword = config.get(
            base.BUILD_SECTION, 'package-index-password')
        # 1.2. Get svn repository info.
        self.svnRepositoryUrl = config.get(
            base.BUILD_SECTION, 'svn-repos')

        if forceSvnAuth:
            svnRepositoryUsername = config.get(
                base.BUILD_SECTION, 'svn-repos-username')
            svnRepositoryPassword = config.get(
                base.BUILD_SECTION, 'svn-repos-password')

            self.svn = base.SVN(svnRepositoryUsername, svnRepositoryPassword,
                                forceAuth=True)
        else:
            self.svn = base.SVN()

        try:
            self.uploadType = config.get(
                base.BUILD_SECTION, 'upload-type')
        except ConfigParser.NoOptionError:
            self.uploadType = 'internal'

        try:
            self.tagLayout = config.get(
                base.BUILD_SECTION, 'tag-layout')
        except ConfigParser.NoOptionError:
            self.tagLayout = 'flat'

        # 1.3. Determine the possibly custom path.
        for pkg in config.get(base.BUILD_SECTION, 'packages').split():
            if pkg.startswith(self.pkg):
                if ':' in pkg:
                    self.customPath = pkg.split(':')[1]
                break

        # 2. Find all versions.
        versions = self.findVersions()
        logger.info('Existing %s versions: %s' % (
            self.pkg, ' | '.join(reversed(versions))))

        # 3. Determine the default version to suggest.
        defaultVersion = None

        # 3.1 Set default version based on forceVersion
        forceVersion = self.options.forceVersion
        if forceVersion:
            if forceVersion in versions:
                logger.error('Forced version %s already exists' % forceVersion)
            else:
                defaultVersion = forceVersion

        if versions and not defaultVersion:
            if self.options.nextVersion:
                # 3.2. If the branch was specified, check whether it changed
                # since the last release or if independent is set, if the last
                # release is based on the current branch
                changed = False
                if self.options.branch:
                    logger.info("Checking for changes since version %s; please "
                                "wait...", versions[-1])
                    changed = self.hasChangedSince(versions[-1],
                        self.options.branch)
                    if self.options.independent and not changed:
                        # only check if not already marked as changed
                        logger.info("Checking if last release is based on "
                                    "branch %s; please wait...",
                                    self.options.branch)
                        if not self.isLastReleaseFromBranch(versions[-1],
                            self.options.branch):
                            changed = True
                    if not changed:
                        logger.info("No changes detected.")
                else:
                    logger.info("Not checking for changes since version %s "
                                "because no -b or --use-branch was specified.",
                                versions[-1])
                # 3.3. If the branch changed and the next version should be
                # suggested, let's find the next version.
                if changed:
                    defaultVersion = base.guessNextVersion(versions[-1])
                else:
                    defaultVersion = versions[-1]
            else:
                logger.info("Not checking for changes because -n or "
                            "--next-version was not used")
                defaultVersion = versions[-1]
        else:
            logger.info(
                "Not checking for changes because --force-version was used")

        # If there's no version the package is probably non existent
        if defaultVersion is None and self.options.defaultPackageVersion:
            # avoid interactive questions (handy for automated builds)
            defaultVersion = self.options.defaultPackageVersion

        branch = self.options.branch
        while True:
            version = base.getInput(
                'Version for `%s`' %self.pkg, defaultVersion,
                self.options.useDefaults and defaultVersion is not None)
            if version not in versions and not self.options.offline:
                if askToCreateRelease:
                    print 'The release %s-%s does not exist.' %(pkg, version)
                    doRelease = base.getInput(
                        'Do you want to create it? yes/no', 'yes',
                        self.options.useDefaults)
                    if doRelease == 'no':
                        continue
                # 4. Now create a release for this version.
                if not self.options.offline:
                    # 4.1. Determine the branch from which to base the release
                    # on.
                    if branch is None:
                        print 'Available Branches:'
                        for branch in self.getBranches():
                            print '  * ' + branch
                        print '  * trunk'
                        branch = base.getInput(
                            'What branch do you want to use?', 'trunk',
                            self.options.useDefaults)
                    # 4.2. Create the release.
                    self.createRelease(version, branch)
            break
        # 5. Return the version number.
        logger.info('Chosen version: ' + version)

        # save the info for build.py
        if branch is None:
            branch = 'trunk'
        self.branchUrl = self.getBranchURL(branch)
        self.branchRevision = self.getRevision(self.branchUrl)

        return version
示例#2
0
文件: build.py 项目: jean/keas.build
def build(configFile, options):
    # save the time we started
    now = datetime.datetime.now()

    # Read the configuration file.
    logger.info('Loading configuration file: ' + configFile)
    config = base.NonDestructiveRawConfigParser()
    config.read(configFile)

    # Create the project config parser
    logger.info('Creating Project Configuration')
    projectParser = base.NonDestructiveRawConfigParser()
    template_path = None
    if config.has_option(base.BUILD_SECTION, 'template'):
        template = config.get(base.BUILD_SECTION, 'template')
        logger.info('Loading Project Configuration Template: ' + template)
        projectParser.read([template])
        template_path = os.path.abspath(template)

    if not projectParser.has_section('versions'):
        projectParser.add_section('versions')

    # Determine all versions of the important packages
    pkgversions = {}
    pkginfos = {}
    for pkg in config.get(base.BUILD_SECTION, 'packages').split():
        customPath = None
        if ':' in pkg:
            pkg, customPath = pkg.split(':')
        builder = package.PackageBuilder(pkg, options)

        version = builder.runCLI(configFile, askToCreateRelease=True,
                                 forceSvnAuth = options.forceSvnAuth)

        pkgversions[pkg] = version
        pkginfos[pkg] = (builder.branchUrl, builder.branchRevision)
        projectParser.set('versions', pkg, version)

    # Get upload type
    try:
        uploadType = config.get(base.BUILD_SECTION, 'buildout-upload-type')
    except ConfigParser.NoOptionError:
        uploadType = "webdav"

    # Stop if no buildout-server given
    try:
        config.get(base.BUILD_SECTION, 'buildout-server')
    except ConfigParser.NoOptionError:
        logger.info('No buildout-server specified in the cfg, STOPPING')
        logger.info('Selected package versions:\n%s' % (
            '\n'.join('%s = %s' % (pkg, version)
                      for pkg, version in pkgversions.items())) )
        return

    # Write the new configuration file to disk
    projectName = config.get(base.BUILD_SECTION, 'name')
    defaultVersion = configVersion = config.get(base.BUILD_SECTION, 'version')
    projectVersions = findProjectVersions(projectName, config,
                                          options, uploadType)

    # Determine new project version
    if projectVersions:
        defaultVersion = projectVersions[-1]
    if options.nextVersion or configVersion == '+':
        defaultVersion = base.guessNextVersion(defaultVersion)
    if options.forceVersion:
        if options.forceVersion in projectVersions:
            logger.error('Forced version %s already exists' % options.forceVersion)
        else:
            defaultVersion = options.forceVersion
    projectVersion = base.getInput(
        'Project Version', defaultVersion, options.useDefaults)

    # Write out the new project config -- the pinned versions
    projectConfigFilename = '%s-%s.cfg' % (projectName, projectVersion)
    logger.info('Writing project configuration file: ' + projectConfigFilename)
    projectParser.write(open(projectConfigFilename, 'w'))

    filesToUpload = [projectConfigFilename]

    try:
        hashConfigFiles = config.getboolean(base.BUILD_SECTION,
                                            'hash-config-files')
    except ConfigParser.NoOptionError:
        hashConfigFiles = False

    # Process config files, check for dependent config files
    # we should make sure that they are on the server
    # by design only the projectConfigFilename will have variable dependencies
    if template_path:
        if hashConfigFiles:
            hashes = {}
        else:
            hashes = None

        dependencies = getDependentConfigFiles(os.path.dirname(template_path),
                                               projectConfigFilename,
                                               addSelf=False,
                                               outfile=projectConfigFilename,
                                               hashes=hashes)

        if hashConfigFiles:
            dependencies = addHashes(dependencies, hashes)
            #fix main config too
            addHashes([projectConfigFilename], hashes, rename=False)

        filesToUpload.extend(dependencies)

    # Dump package repo infos
    # do it here, projectConfigFilename might be rewritten by
    # getDependentConfigFiles
    projectFile = open(projectConfigFilename, 'a')
    projectFile.write('\n')
    projectFile.write('# package SVN infos:\n')
    for pkg, pkginfo in pkginfos.items():
        projectFile.writelines(
            ('# %s\n' % pkg,
             '#   svn URL:%s\n' % pkginfo[0],
             '#   svn repo revision:%s\n' % pkginfo[1][0],
             '#   svn last change revision:%s\n' % pkginfo[1][1],
            ))
        logger.info('SVN info: %s: %s %s %s', pkg, pkginfo[0],
                    pkginfo[1][0], pkginfo[1][1])
    projectFile.close()

    # Create deployment configurations
    # first define a parser for load addition variable (vars) section somewhere
    # in your templates chain.
    varsParser = base.NonDestructiveRawConfigParser()
    # make sure we use the right (tempalte inheritation) order
    varsParser.read(reversed(filesToUpload))

    for section in config.sections():
        if section == base.BUILD_SECTION:
            continue
        logger.info('Building deployment configuration: %s', section)
        template_path = config.get(section, 'template')
        logger.info('Loading deploy template file: %s', template_path)
        template = file(template_path, 'r').read()
        vars = dict([(name, value)
                     for name, value in config.items(section)
                     if name != 'template'])

        # apply additional vars defined in release template section if a
        # section name is defined as vars argument
        # or keep the vars argument as is if there is no section. This is
        # usefull if someone uses the vars attribute as argument (BBB)
        vName = vars.get('vars')
        if varsParser.has_section(vName):
            # apply vars from given section as additional vars
            for name, value in varsParser.items(vName):
                if name not in vars:
                    # but only if not overriden in deployment config
                    vars[name] = value

        # apply defaults
        vars['project-name'] = projectName
        vars['project-version'] = projectVersion
        vars['instance-name'] = section

        # add current time
        vars['current-datetime'] = now.isoformat()
        vars['current-date'] = now.date().isoformat()
        vars['current-time'] = now.time().isoformat()

        #handle multi-line items, ConfigParser removes leading spaces
        #we need to add some back otherwise it will be a parsing error
        for k, v in vars.items():
            if '\n' in v:
                #add a 2 space indent
                vars[k] = v.replace('\n', '\n  ')

        try:
            deployConfigText = template % vars
        except KeyError, e:
            logger.error("The %s deployment configuration is missing the %r setting required by %s",
                         section, e.message, template_path)
            sys.exit(0)
        deployConfigFilename = '%s-%s-%s.cfg' %(
            config.get(base.BUILD_SECTION, 'name'), section, projectVersion)
        deployConfig = base.NonDestructiveRawConfigParser()
        deployConfig.readfp(StringIO.StringIO(deployConfigText))
        deployConfig.set('buildout', 'extends', projectConfigFilename)
        logger.info('Writing deployment file: ' + deployConfigFilename)
        deployConfig.write(open(deployConfigFilename, 'w'))

        filesToUpload.append(deployConfigFilename)
示例#3
0
    def runCLI(self):
        # 1. Get the project to be installed.
        project = self.options.project
        if project is None:
            projects = self.getProjects()
            print 'Projects'
            for name in projects:
                print '  * ' + name
            project = base.getInput('Project', projects[0], False)
        # 2. Get the variant of the project.
        variant = self.options.variant
        if variant is None:
            variants = self.getVariants(project)
            print 'Variants'
            for name in variants:
                print '  * ' + name
            if not variants:
                logger.error(
                    "No variants found, this script only works with variants.")
                sys.exit(0)
            variant = base.getInput('Variant', variants[0], False)
        # 3. Get the version of the project.
        version = self.options.version
        if version is None:
            versions = self.getVersions(project, variant)
            if len(versions) == 0:
                print "Sorry, but there have not been any", project, variant, "releases yet."
                sys.exit(0)
            if self.options.latest:
                version = versions[-1]
            else:
                print 'Versions'
                for name in versions:
                    print '  * ' + name
                version = base.getInput('Version', versions[-1], False)
        # 4. Install the package
        url = self.options.url

        if self.options.username:
            #add username and password if present so that buildout can access
            #the URL without prompting
            parts = urlparse.urlparse(url)
            url = '%s://%s:%s@%s' % (parts[0], self.options.username,
                                     self.options.password, ''.join(parts[1:]))

        options = []
        if self.options.verbose:
            options.append('-vv')

        if self.options.overrideDir:
            overrideDir = self.options.overrideDir
            #make it absolute if it's not
            #buildout does not like relative, buildbot cannot do absolute
            if is_win32:
                isAbs = overrideDir[0].lower().isalpha() and overrideDir[1]==':'
                if not isAbs:
                    overrideDir = os.path.abspath(overrideDir)
            else:
                isAbs = overrideDir.startswith('/')
                if not isAbs:
                    overrideDir = os.path.abspath(overrideDir)

            options.append('buildout:directory=%s' % overrideDir)

        cfgFile = '%s%s/%s-%s-%s.cfg' % (url, project, project, variant, version)

        base.do('%s -t %s %s -c %s' %(
                self.options.buildout,
                self.options.timeout,
                ' '.join(options),
                cfgFile),
                captureOutput=False)