import os
import shlex
import string
import subprocess
from ConfigParser import ConfigParser
from datetime import date
DEBUG=1
CP = ConfigParser()
def main():
CP.read(os.path.join(os.environ['HOME'], '.forgepushrc'))
engineer = option('re', 'engineer', 'Name of engineer pushing: ')
text, tag = make_ticket_text(engineer)
print '*** Create a ticket on SourceForge (https://sourceforge.net/p/allura/tickets/new/) with the following contents:'
print '*** Summary: Production Push (R:%s, D:%s)' % (
tag, date.today().strftime('%Y%m%d'))
print '---BEGIN---'
print text
print '---END---'
raw_input("Verify that there are no new dependencies, or RPM's are build for all deps...")
raw_input("Verify that a new sandbox builds starts without engr help...")
raw_input('When this is done, create a JIRA ticket (https://engr.geek.net/jira/secure/CreateIssue!default.jspa) with the same contents...')
raw_input('Now link the two tickets...')
newforge_num = raw_input('What is the newforge ticket number? ')
command('git', 'tag', '-a', '-m', '[#%s] - Push to RE' % newforge_num, tag, 'master')
command('git', 'push', 'origin', 'master')
command('git', 'push', 'live', 'master')
command('git', 'push', '--tags', 'origin')
command('git', 'push', '--tags', 'live')
raw_input('Now go to the sog-engr channel and let them know that %s is ready'
' for pushing (include the JIRA ticket #' % tag)
raw_input('Make sure SOG restarted reactors and web services.')
CP.write(open(os.path.join(os.environ['HOME'], '.forgepushrc'), 'w'))
print "You're done!"
def make_ticket_text(engineer):
tag_prefix = date.today().strftime('release_%Y%m%d')
# get release tag
existing_tags_today = command('git tag -l %s*' % tag_prefix)
if existing_tags_today:
tag = '%s.%.2d' % (tag_prefix, len(existing_tags_today))
else:
tag = tag_prefix
last_release = command('git tag -l release_*')
if last_release: last_release = last_release[-1]
else: last_release = ''
changes = command(
'git', 'log', "--format=* %h %s", last_release.strip() + '..')
changes = ''.join(changes)
prelaunch = []
postlaunch = ['* allurapaste ensure_index /var/local/config/production.ini']
needs_reactor_setup = raw_input('Does this release require a reactor_setup? [n]')
needs_flyway = raw_input('Does this release require a migration? [y]')
if needs_reactor_setup[:1].lower() in ('y', '1'):
postlaunch.append('* service reactor stop')
postlaunch.append('* allurapaste reactor_setup /var/local/config/production.ini')
postlaunch.append('* service reactor start')
if needs_flyway[:1].lower() in ('', 'y', '1'):
prelaunch.append('* dump the database in case we need to roll back')
postlaunch.append('* allurapaste flyway --url mongo://sfn-mongo-1:27017/')
if postlaunch:
postlaunch = [ 'From sfu-scmprocess-1 do the following:\n' ] + postlaunch
postlaunch = '\n'.join(postlaunch)
else:
postlaunch = '-none-'
if prelaunch:
prelaunch = [ 'From sfn-mongo-1 do the following:\n' ] + prelaunch
prelaunch = '\n'.join(prelaunch)
else:
prelaunch = '-none-'
return TICKET_TEMPLATE.substitute(locals()), tag
def command(*args):
if len(args) == 1 and isinstance(args[0], basestring):
argv = shlex.split(args[0])
else:
argv = list(args)
if DEBUG:
print ' '.join(argv)
raw_input('Press enter to run this command...')
p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
rc = p.wait()
if rc != 0:
print 'Error running %s' % ' '.join(argv)
import pdb; pdb.set_trace()
return p.stdout.readlines()
def option(section, key, prompt=None):
if not CP.has_section(section):
CP.add_section(section)
if CP.has_option(section, key):
value = CP.get(section, key)
else:
value = raw_input(prompt or ('%s: ' % key))
CP.set(section, key, value)
return value
TICKET_TEMPLATE=string.Template('''
(engr) Name of Engineer pushing: $engineer
(engr) Which code tree(s): allura
(engr) Is configtree to be pushed?: no
(engr) Which release/revision is going to be synced?: $tag
(engr) Itemized list of changes to be launched with sync:
$changes
Pre-launch dependencies:
$prelaunch
Post-launch dependencies:
$postlaunch
(engr) Approved for release (Dean/Dave/John): None
(sog) Approval for sync provided by (Jacob/Jay/David/Wayne): None
(sog) Outcome of sync:
''')
if __name__ == '__main__':
main()