Skip to content
Snippets Groups Projects
buildVersion.py 7.45 KiB
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" 
   NAME
          buildVersion -- helper script to build and tag a plugin_dbui version

    SYNOPSIS
          buildVersion [options] version

    DESCRIPTION
          Helper script to build a version of the plugin_dbui.
          
          The version identifier should contains alphanumeric characters 
          including ".", "-" and "_".
          
          Push version identifier in the javascript library.
          Push version number in the CHANGELOG.
          Build debug and minified version of the javascript library.
          Commit the new version in git and tag it
          Build the web2py plugin file
              
    EXAMPLES

            > buildVersion -h
            > buildVersion 0.4.3

    AUTHOR
          R. Le Gac, renaud.legac@free.fr

    Copyright (c) 2012 R. Le Gac
    
"""

import datetime
import optparse
import os
import re
import subprocess
import sys
import tempfile
import urllib


# constants
APP = 'mygit_dbui_04x'
CHANGELOG = 'static/plugin_dbui/CHANGELOG'
DBUI_W2P = 'web2py.plugin.dbui.%s.w2p'
JSBASE = 'static/plugin_dbui/src/appbase.js'
JSLIBDEBUG = 'static/plugin_dbui/dbui-debug.js'
JSLIBMIN = 'static/plugin_dbui/dbui-min.js'
JSLIBSRC = 'static/plugin_dbui/src'
NOW = datetime.datetime.now()
PACK_PLUGIN_URL = 'http://localhost:8000/%s/default/pack_plugin' % APP

# basic commands
GIT = '/usr/bin/git'
YUICOMPRESSOR = os.path.expandvars("$HOME/lib/yuicompressor-2.4.6/build/yuicompressor-2.4.6.jar")
WEB2PY = os.path.expandvars('$HOME/myweb/web2py/web2py.py')


def clean():
    """Clean the previous build.
    
    """
    fn = DBUI_W2P % get_version().replace('.', '')
        
    for el in (fn , JSLIBDEBUG, JSLIBMIN):
        if os.path.exists(el): 
            os.remove(el)
            print 'file', el, 'is removed.'


def get_version():
    """Get the current version identifier.
    
    """
    s = open(JSBASE, 'rb').read()
    m = re.match("(.+App.version = ')([\w._-]*)(';.*)", s, re.DOTALL)
    return m.group(2)


def git():
    """Commit and tag the current release.
    
    """
    version = get_version()
    
    # check tag in git
    fi = tempfile.TemporaryFile()
    subprocess.call(["git", "tag"], stdout=fi)
    fi.seek(0)
    if version in fi.read():
        print "\n\ttag %s already exit in git" % version
        sys.exit(1)
        
    # Commit the new release in git an tag it
    print 'git add', JSBASE, CHANGELOG, JSLIBDEBUG, JSLIBMIN
    cmd = ["git", "add", JSBASE, CHANGELOG, JSLIBDEBUG, JSLIBMIN]
    subprocess.call(cmd)
    
    print 'git commit'
    cmd = ["git", "commit", "-m", "Release version %s" % version]
    subprocess.call(cmd)
    
    print 'git tag', version
    cmd = ["git", "tag", version]
    subprocess.call(cmd)


def set_version(version):
    """Set version identifier in CHANGELOG and appbase.js
    
    """
    print 'Set version in', JSBASE
    s = open(JSBASE, 'rb').read()
    
    # look for a pattern App.version = '0.8.3'; in appbase.js
    # split the the string in 3 parts (pre, version, post)
    m = re.match("(.+App.version = ')([\w._-]*)(';.*)", s, re.DOTALL)
    
    if m.group(2) == version:
        print '\n\tVersion "%s" already exists in the appbase.js file !' % version
        rep = raw_input('\tDo you want to continue [n]?')
        if rep not in ('y', 'yes'):
            sys.exit(1)

    # update the version and write a new file    
    s = m.group(1) + version + m.group(3)
    fi = open(JSBASE, 'wb')
    fi.write(s)
    fi.close()
    
    # look for a pattern HEAD in the CHANGELOG
    # split the the string in 2 parts (pre HEAD, post HEAD)
    print 'Set version in', CHANGELOG
    s = open(CHANGELOG, 'rb').read()
    
    m = re.match("(.+HEAD\n)(.*)", s, re.DOTALL)
    
    if m == None:
        print '\n\tNo HEAD tag in the CHANGELOG!\n'
        rep = raw_input('\tDo you want to continue [n]?')
        if rep not in ('y', 'yes'):
            sys.exit(1)

    # update the version and edit the CHANGELOG    
    s = '%s\n%s (%s)\n%s' % (m.group(1), version, NOW.strftime('%b %Y'), m.group(2))
    fi = open(CHANGELOG, 'wb')
    fi.write(s)
    fi.close()
    subprocess.call(["vim", CHANGELOG])


def web2py():
    """Produce the binary file for the web2py plugin.
    
    """
    print 'Build the web2py plugin binary file'
    raw_input('Check that the web2py service is running ? Type CR to continue.')
    f = urllib.urlopen(PACK_PLUGIN_URL)
    s = f.read()
    
    fn = DBUI_W2P % get_version().replace('.', '')
    fi = open(fn, 'wb')
    fi.write(s)
    fi.close()
    print 'Binary file', fn, 'is created.'


def yuicompressor():
    """Compresssed and minified the javascript library.
    
    """
    # debug version of the javascript library
    print 'Debug version of the javascript library', JSLIBDEBUG
    subprocess.call('cat %s/*.js > %s' % (JSLIBSRC, JSLIBDEBUG), shell=True)

    # Minified version of the javascript library
    print 'Minified version of the javascript library', JSLIBMIN
    cmd = ["java", "-jar", YUICOMPRESSOR, "-o", JSLIBMIN, JSLIBDEBUG]
    subprocess.call(cmd)


if __name__ == '__main__':
    
    # check that basic commands are there
    for cmd in (GIT, YUICOMPRESSOR, WEB2PY):
        if not os.path.exists(cmd):
            print '\n\t%s application is missing !' % cmd
            sys.exit(1)
        
    # define script options 
    ops = optparse.OptionParser()
    
    ops.add_option("-c", "--clean",
                   action="store_true",
                   dest= "clean",
                   help= "clean build files and exit.")
    
    ops.add_option("-g", "--git",
                   action="store_true",
                   dest= "git",
                   help= "run the git steps.")

    ops.add_option("-r", "--release",
                   action="store_true",
                   dest= "get",
                   help= "run the version of the current release and exit.")
        
    ops.add_option("-s", "--set_version",
                   action="store_true",
                   dest= "set",
                   help= "run the update version step.")
    
    ops.add_option("-y", "--yuicompressor",
                   action="store_true",
                   dest= "yuicompressor",
                   help= "run the yuicompressor step.")
    
    ops.add_option("-w", "--web2py",
                   action="store_true",
                   dest= "web2py",
                   help= "run the web2py step.")
    
    ops.set_defaults(clean=False,
                     get=False,
                     git=False,
                     set=False,
                     yuicompressor=False,
                     web2py=False)
    
    (opt, args) = ops.parse_args()
    
    # the version of the current release
    if opt.get:
        version = get_version()
        print "\nThe version of the current release is %s\n" % version
        sys.exit(0)
        
    # by default run all steps: update, git, YUIcompressor and web2py
    if not (opt.set or opt.git or opt.yuicompressor or opt.web2py):
        opt.set = True
        opt.git = True
        opt.yuicompressor = True
        opt.web2py = True

    # process
    print '\nStart buildVersion'
        
    if opt.clean:
        clean()
        sys.exit(0)
    
    if opt.set:
        if args:
            version = args[0]
            
        else:
            version = raw_input('Enter the version identifier: ')
    
        set_version(version)
        
    if opt.yuicompressor: yuicompressor()
    if opt.git: git()
    if opt.web2py: web2py()
    
    print 'Exit buidVersion\n'
    sys.exit(0)