├── README └── release-script └── scripts ├── pre-commit.conf ├── repo.conf ├── pre-commit.py └── repomgmt.py /README: -------------------------------------------------------------------------------- 1 | Index card for all the folders inside this repo 2 | 3 | release-script - python based scripts to tag & branch svn 4 | -------------------------------------------------------------------------------- /release-script/scripts/pre-commit.conf: -------------------------------------------------------------------------------- 1 | [Log] 2 | # Path to apply validation rules, you can provide more than one path 3 | # with comma seperated value. Its usually your top level project root 4 | # name 5 | path="project1","project2","project3" 6 | 7 | # Perl regular expression syntax for log message prefix 8 | # Prefix and message is seperated by a character ':' hard-coded in code 9 | # Always enclose regex in double qotes, you can supply multiple values 10 | # each seperated with comma; this should match exactly with number of 11 | # values in path. 12 | prefix="MANTIS[0-9]+","b","c", 13 | 14 | # Change to yes if you like to allow empty log messages 15 | # NB: Default value of project is not to allow empty comment body 16 | # if your project needs to allow empty comment body set it to 'yes' 17 | # this values should match number of projects 18 | empty_body="no", 19 | -------------------------------------------------------------------------------- /release-script/scripts/repo.conf: -------------------------------------------------------------------------------- 1 | [Project] 2 | # Static string name of your project nice to have not mandatory 3 | name=Healthlogistics 4 | 5 | # Root of your reposiotry without trailing slash 6 | # examples: svn://localhost/myproject, http://localhost/project 7 | root=svn://www.example.com/client/repo 8 | 9 | [Release] 10 | # Trunk if you are releasing from trunk, else give the branch name 11 | # assuming you have followed svn convention when creating repository 12 | # having trunk, tags and branches as way of organising your code 13 | # example - trunk, branch-3.0 14 | from=trunk 15 | 16 | # Name for the tag you would like to create follow your project 17 | # convention 18 | # example - 2.7.0, 10.8.1, xmas 19 | name=lpp-beta-4.0 20 | 21 | # Name of the tag used in build process, this will be a copy of 22 | # tag created above. This tag is used by your build server. 23 | # It should be empty if not used or will always have one 24 | # constant value 25 | build=current 26 | 27 | [Branch] 28 | # If you are branching from trunk or if you are branching from 29 | # branch give the branch name 30 | # example - trunk, branch-xms 31 | from= 32 | 33 | # Name for the branch you would like to create follow your project 34 | # convention 35 | name= 36 | -------------------------------------------------------------------------------- /release-script/scripts/pre-commit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # This scipt is used for as an pre commit checker for svn commits 3 | # it identifies the log message and rejects the transaction if it 4 | # doen't meet the required criteria defined in a configration file 5 | # 6 | # Author: Nataraj M Basappa (nataraj.basappa@sceneric.com) 7 | # Creation Date: 12th Feburary 2011 8 | # Modified Date: 14th March 2011 9 | 10 | import sys, getopt 11 | import pysvn, re 12 | from configobj import ConfigObj as confobj 13 | 14 | # Script variables 15 | cobj = confobj('pre-commit.conf') 16 | 17 | def main(path_to_repo, transaction_name): 18 | transaction = pysvn.Transaction(path_to_repo, transaction_name) 19 | log_msg = transaction.revpropget('svn:log') 20 | log_conf = cobj['Log'] 21 | paths = log_conf['path'] 22 | prefixs = log_conf['prefix'] 23 | empty_body = log_conf['empty_body'] 24 | 25 | # NOT NEEDED 26 | # Clubing project with root path 27 | # path_to_project = [] 28 | # for temp in project_paths: 29 | # path_to_project.append(repo_root+"/"+temp) 30 | 31 | # Creating map with project and code prefix 32 | projects_prefix = dict(zip(paths,prefixs)) 33 | 34 | # Creating map with project and empty comment allowed 35 | projects_empty_comment = dict(zip(paths,empty_body)) 36 | 37 | #sys.stderr.write("Prefix : %s\n" % (projects_prefix)) 38 | #sys.stderr.write("Empty : %s\n" % (projects_empty_comment)) 39 | 40 | changes = transaction.changed() 41 | for path in changes: 42 | project = path[:path.index("/")] 43 | prefix = projects_prefix[project] 44 | empty_allowed = projects_empty_comment[project] 45 | if prefix != None: 46 | pattern = re.compile(prefix,re.IGNORECASE) 47 | #sys.stderr.write("\nSource - %s ; Prefix - %s" %(log_msg.split(':',1)[0],prefix)) 48 | match = pattern.match(log_msg.split(':',1)[0]) 49 | if match == None: 50 | sys.stderr.write("Commit message should match the prefix %s\n" %(prefix)) 51 | sys.exit(1) 52 | 53 | if empty_allowed == None or empty_allowed.lower() == "no": 54 | #sys.stderr.write("\nSource - %s ; Empty - %s" %(log_msg.split(':',1)[1],empty_allowed)) 55 | pattern = re.compile("\s*(\w+)",re.IGNORECASE) 56 | if prefix == None: 57 | match = pattern.match(log_msg) 58 | else: 59 | match = pattern.match(log_msg.split(':',1)[1]) 60 | 61 | if match == None: 62 | sys.stderr.write("Commit message can't be emtpy\n") 63 | sys.exit(1) 64 | sys.exit(0) 65 | 66 | if __name__ == '__main__': 67 | # This script is called by svn with two arguments 68 | # 1. path to repository 69 | # 2. transction name 70 | opts, args = getopt.getopt(sys.argv[1:], '') 71 | main(args[0],args[1]) 72 | -------------------------------------------------------------------------------- /release-script/scripts/repomgmt.py: -------------------------------------------------------------------------------- 1 | # This scipt is used to help release manager to automate the 2 | # the release process by aiding in creation of tags or branches 3 | # and release notes all read from the properties configuration 4 | # file (repo.conf). 5 | # 6 | # Author: Nataraj M Basappa (nataraj.basappa@sceneric.com) 7 | # Creation Date: 24th December 2010 8 | # Modified Date: 05th January 2011 9 | 10 | import sys, os 11 | import getopt, getpass 12 | import pysvn 13 | from pysvn import opt_revision_kind 14 | from configobj import ConfigObj as confobj 15 | 16 | class RepoMgmt: 17 | 18 | def __init__(self, cfile, branch, username): 19 | # Constants 20 | self.username = username 21 | self.password = None 22 | self.log = None 23 | self.is_branch = branch 24 | self.client = pysvn.Client() 25 | 26 | self.cobj = confobj(cfile) 27 | self.project = self.cobj['Project'] 28 | self.release = self.cobj['Release'] 29 | self.branch = self.cobj['Branch'] 30 | 31 | def main(self): 32 | if self.is_branch: 33 | self.create_branch() 34 | else: 35 | self.create_tag() 36 | 37 | def svn_setup(self): 38 | self.client.set_default_username(self.username) 39 | self.client.set_default_password(self.password) 40 | self.client.callback_get_log_message = self.svn_log_message 41 | 42 | def svn_create(self, src, dest): 43 | self.client.copy(src, dest, src_revision=pysvn.Revision(opt_revision_kind.head)) 44 | 45 | def svn_delete(self, src): 46 | try: 47 | self.client.remove(src) 48 | except pysvn.ClientError, e: 49 | if str(e) == "URL '"+ src +"' does not exist": 50 | return 51 | else: 52 | print str(e) 53 | print "Failed to delete build tag\n" 54 | 55 | def svn_log_message(self): 56 | return True, self.log 57 | 58 | def svn_notify(self, event_dict): 59 | return 60 | 61 | def create_tag(self): 62 | if self.release['from'].lower() == 'trunk': 63 | src = self.project['root']+'/'+self.release['from'].lower() 64 | else: 65 | src = self.project['root']+'/branches/'+self.release['from'].lower() 66 | 67 | self.log = 'Creating tag '+self.release['name'] 68 | dest = self.project['root']+'/tags/'+self.release['name'] 69 | 70 | #print src+'\n'+dest+'\n'+self.log 71 | self.create('tag', src, dest) 72 | 73 | def create_branch(self): 74 | if self.branch['from'].lower() == 'trunk': 75 | src = self.project['root']+'/'+self.branch['from'] 76 | else: 77 | src = self.project['root']+'/branches/'+self.branch['from'] 78 | 79 | self.log = 'Creating branch '+self.branch['name'] 80 | dest = self.project['root']+'/branches/'+self.branch['name'] 81 | 82 | #print src+'\n'+dest+'\n'+self.log 83 | self.create('branch', src, dest) 84 | 85 | def create(self, action, src, dest): 86 | 87 | is_buildTag = False 88 | if not self.is_branch: 89 | if len(self.release['build']) > 0: 90 | build_dest = self.project['root']+'/tags/'+self.release['build'] 91 | is_buildTag = True 92 | 93 | output = sys.stdout 94 | output.write( 95 | "**************************************************************************\n" 96 | "Project: %s\n" 97 | "**************************************************************************\n" 98 | "Please verify following details before continuing\n" 99 | "\n" 100 | "Creating %s: %s\n" 101 | "From: %s\n" 102 | "Log: %s\n" 103 | "SVN user: %s\n" 104 | % (self.project['name'], action, dest, src, self.log, self.username)) 105 | if is_buildTag: 106 | output.write("Build tag: %s\n" 107 | "\n" %(build_dest)) 108 | else: 109 | print # print empty line 110 | choice = raw_input("Press 'y' to proceed anything else to exit: ") 111 | 112 | if choice!='y': 113 | sys.exit(0) 114 | 115 | counter = 0 116 | while True: 117 | self.password = getpass.getpass("SVN password for "+self.username+": ") 118 | print"\nplease wait..." 119 | try: 120 | self.svn_setup() 121 | self.svn_create(src,dest) 122 | if is_buildTag: 123 | # Resetting log 124 | self.log = 'Removing old build tag' 125 | self.svn_setup() 126 | self.svn_delete(build_dest) 127 | self.log = 'Creating build tag '+self.release['name'] 128 | self.svn_setup() 129 | self.svn_create(src,build_dest) 130 | 131 | output.write( 132 | "Done creating %s.\n" %(action)) 133 | break 134 | except pysvn.ClientError, e: 135 | if counter < 2 and str(e) == 'callback_get_login required': 136 | print '\nIncorrect SVN password' 137 | counter = counter + 1 138 | elif str(e).find('already exists') != -1: 139 | print '\n%s %s already exists update your conf file before running again' % (action, self.branch['name'] if self.is_branch else self.release['name']) 140 | break 141 | else: 142 | print '\nToo many attempts quitting!\n' 143 | break 144 | def usage(exit): 145 | if exit: 146 | output = sys.stderr 147 | else: 148 | output = sys.stdout 149 | 150 | output.write( 151 | "Usage: %s [OPTION]... username...\n" 152 | "Creates a tag or branch using the username supplied, reads the configuration from\n" 153 | "default configuration (repo.conf) file under current folder.\n" 154 | "\n" 155 | "-c, --conf Path to configuration file.\n" 156 | "-b, --branch Create a branch.\n" 157 | "-h, --help Displays this help and exit.\n" 158 | "\n" 159 | % (sys.argv[0])) 160 | 161 | sys.exit(exit) 162 | 163 | if __name__ == '__main__': 164 | 165 | # Config file 166 | cfile = 'repo.conf' 167 | branch = False 168 | 169 | # Check command options 170 | try: 171 | opts, args = getopt.getopt(sys.argv[1:], 'hcb', ['help','conf','branch']) 172 | except getopt.GetoptError, err: 173 | print str(err) # will print something like "option -z not recognized" 174 | usage(2) 175 | 176 | for opt, value in opts: 177 | if opt in ('-h', '--help'): 178 | usage(0) 179 | elif opt in ('-c','--conf'): 180 | cfile = value 181 | elif opt in ('-b','--branch'): 182 | branch = True 183 | else: 184 | assert False, "unhandled option" 185 | 186 | # Check command arguments 187 | if len(args) < 1: 188 | usage(2) 189 | else: 190 | repoMgmt = RepoMgmt(cfile, branch, args[0]) 191 | repoMgmt.main() 192 | --------------------------------------------------------------------------------