Newer
Older
#!/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
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 = os.path.basename(os.getcwd())
BUILDDIR = '../plugin_dbui_build'
CHANGELOG = 'static/plugin_dbui/CHANGELOG'
EXTJSSRC = 'static/plugin_extjs/src'
JSBASE = 'static/plugin_dbui/src/App.js'
JSDOC = 'static/plugin_dbui/docs/jsduck'
JSLIBDEBUG = 'static/plugin_dbui/dbui-debug.js'
JSLIBMIN = 'static/plugin_dbui/dbui-min.js'
JSLIBSRC = 'static/plugin_dbui/src'
SPHINXDOC = 'static/plugin_dbui/docs/sphinx'
SPHINXSRC = 'docs/api'
NOW = datetime.datetime.now()
PACK_PLUGIN_URL = 'http://localhost:8000/%s/default/pack_plugin' % APP
# basic commands
GIT = '/usr/bin/git'
JSDUCK = os.path.expandvars("$HOME/bin/jsduck")
SENCHA = os.path.expandvars("$HOME/bin/sencha")
SPHINX = '/usr/bin/sphinx-build'
MSG_VERSION = 'Enter the new release: '
def compile():
"""compile the javascript code and generate the debug version
as well as the minified version of the dbui library.
The compiler verify that the code complied with the class model
and order the file in the proper way.
The minified library can be build in several ways, including
the Ext JS class required by the applications. In the
current version, the library contains only the dbui classes and
the Ext JS ones have to be loaded separately. In that sense
this command is very similar to the yuicompressor one.
Several compressor can be used yui, closure compiler, ....
In the current version, the default yui compressor is used?
This operation relies on the Sencha Cmd:
http://www.sencha.com/products/sencha-cmd/download
The details documantation can be found:
http://docs.sencha.com/extjs/4.2.2/#!/guide/command
"""
if not os.path.exists(SENCHA):
print '\n\tThe application sencha is missing !'
print '\tSee: http://www.sencha.com/products/sencha-cmd/download'
print '\tSkip this step.\n'
return
# clean previous version
for el in (JSLIBDEBUG, JSLIBMIN):
os.remove(el)
print 'Remove javascript library', el
# debug version of the javascript library
print '\nDebug version of the javascript library', JSLIBDEBUG
cmd = ["sencha", "-sdk", os.path.join(cwd, EXTJSSRC),
"compile", "-class", os.path.join(cwd, JSLIBSRC),
"exclude", "--namespace", "Ext",
"and", "concat", os.path.join(cwd, JSLIBDEBUG)]
subprocess.call(cmd)
# Minified version of the javascript library
print '\nMinified version of the javascript library', JSLIBMIN
cmd = ["sencha", "-sdk", os.path.join(cwd, EXTJSSRC),
"compile", "-class", os.path.join(cwd, JSLIBSRC),
"exclude", "--namespace", "Ext",
"and", "concat", "--yui", os.path.join(cwd, JSLIBMIN)]
def get_version():
"""Get the current version identifier.
"""
s = open(JSBASE, 'rb').read()
m = re.match("(.+ version: ')([\w._-]*)('.+)", s, re.DOTALL)
return m.group(2)
def git():
"""Commit and tag the current release.
if not os.path.exists(GIT):
print '\n\tThe application git is missing !'
print '\tSkip this step.\n'
return
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)
# release message
m = "Release version %s" % version
# Commit the new release in git an tag it
print 'git add', JSBASE, CHANGELOG
cmd = ["git", "add", JSBASE, CHANGELOG]
subprocess.call(cmd)
print 'git commit'
cmd = ["git", "commit", "-m", m]
subprocess.call(cmd)
# annotated tag
print 'git tag', version
cmd = ["git", "tag", "-a", version, "-m", m]
subprocess.call(cmd)
def jsduck():
"""Generate the JavaScript documentation.
The HTML files are located in static/plugin_dbui/docs/jsduck
if not os.path.exists(JSDUCK):
print '\n\tThe application jsduck is missing !'
print '\tSkip this step.\n'
return
# create the directory
if not os.path.exists(JSDOC):
os.makedirs(JSDOC)
# clean the directory
cmd = ["rm", "-rf", JSDOC]
subprocess.call(cmd)
# run JsDuck
cmd = ["jsduck", EXTJSSRC, JSLIBSRC, \
"--output", JSDOC, \
"--title", "plugin_dbui %s" % get_version(), \
"--warnings=-all:" + EXTJSSRC]
subprocess.call(cmd)
print "JavaScript documentation in", JSDOC
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("(.+ 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])
fn = "%s~" % CHANGELOG
if os.path.exists(fn):
os.remove(fn)
def sphinx():
"""Generate the Sphinx documentation.
"""
if not os.path.exists(SPHINX):
print '\n\tThe application sphinx is missing !'
print '\tSkip this step.\n'
return
if not os.path.exists(SPHINXSRC):
print '\nNo sphinx source file !'
return
# clean the directory
cmd = ["rm", "-rf", SPHINXDOC]
subprocess.call(cmd)
# generate the HTML version
cmd = [SPHINX, "-b", "html", SPHINXSRC, SPHINXDOC]
subprocess.call(cmd)
print "\nSphinx HTML documentation in", SPHINXDOC, "\n"
def web2py():
"""Produce the binary file for the web2py plugin.
print '\nBuild the web2py plugin binary file'
rep = raw_input('Check that the web2py service is running ? Type CR to continue.')
if rep:
print '\n\tSkip this step.\n'
return
f = urllib.urlopen(PACK_PLUGIN_URL)
s = f.read()
fn = DBUI_W2P % get_version().replace('.', '')
fi = open(fn, 'wb')
fi.write(s)
fi.close()
# move the file to the build directory
fn_build = os.path.join(BUILDDIR, fn)
if os.path.exists(fn_build):
os.remove(fn_build)
print 'Binary file', fn, 'is created in ', BUILDDIR
if __name__ == '__main__':
ops = optparse.OptionParser()
ops.add_option("-a", "--all",
action="store_true",
dest="all",
help="run all steps.")
ops.add_option("-c", "--compile",
action="store_true",
dest="compile",
help="compile the javascript library using sencha command.")
ops.add_option("-g", "--git",
action="store_true",
dest="git",
help="commit and tag the current release.")
ops.add_option("-j", "--jsduck",
action="store_true",
dest="jsduck",
help="generate the JavaScript documentation.")
ops.add_option("-r", "--release",
action="store_true",
dest="get",
help="get the version of the current release and exit.")
ops.add_option("-s", "--sphinx",
action="store_true",
dest="sphinx",
help="generate sphinx documentation.")
ops.add_option("-v", "--set_version",
action="store_true",
dest="set",
help="set the version.")
ops.add_option("-w", "--web2py",
action="store_true",
dest="web2py",
help="pack the web2py plugin.")
git=False,
web2py=False)
(opt, args) = ops.parse_args()
version = get_version()
print "\nThe version of the current release is %s\n" % version
if opt.jsduck:
jsduck()
if opt.compile:
compile()
# run all steps
if opt.all:
version = get_version()
print "\nThe version of the current release is %s\n" % version
version = (args[0] if args else raw_input(MSG_VERSION))
set_version(version)
git()
jsduck()
print 'Exit buidVersion\n'