diff scripts/release.groovy @ 216:b628d49d2891

DEP-11: change name of lock file for release branch. update release script to depend on new resolution and dependency locking
author smith@nwoca.org
date Wed, 29 Jun 2016 13:57:17 +0100
parents 5bebb590b30e
children 49a220a1bde0
line wrap: on
line diff
--- a/scripts/release.groovy	Tue Jun 28 23:01:21 2016 +0100
+++ b/scripts/release.groovy	Wed Jun 29 13:57:17 2016 +0100
@@ -1,33 +1,39 @@
 #!groovy
+import groovy.transform.Sortable
+import groovy.transform.ToString
+import groovy.transform.TupleConstructor
 
 /**
-This script implements the SSDT branching strategy based on hg flow.  
+This script implements the SSDT branching strategy based on hg flow
+ and dependency resolution locking.
 
-The intention is to reduce drudgery of creating release branches.  The
-script tries to do the right thing based on standard SSDT project structures, 
-but it is the user's responsibility to ensure it's correct.
+The intention is to automate of creation of correctly configured release branches.
+ The script tries to do the right thing based on standard SSDT project structures,
+ but it is the user's responsibility to ensure it's correct.
 
-The script does NOT "hg push --new-branch".  That step is left for you
+The script does NOT "hg push --new-branch".   That step is left for you
 if the branch was created correctly.
 
 */
-	def project = new Properties()
+
+def branch = new BranchInfo()
+
+println "Project:\n"
 
-	if (new File('gradle.properties').exists() ) {
-		project.load(new File('gradle.properties').newInputStream())
-	}	
-	
-	println "\nCurrent project:"
-	println "\tversion: " + project.version ?: "Unknown"
-	println "-" * 20
-	
-if (args.size() < 2) {
+println "\trepo\t${("hg path".execute().text.split('=') ?: ['', ''])[1].trim()}"
+println "\tbranch\t$branch"
+println "\tversion\t$branch.version"
+
+println "-" * 40
+println ""
+
+if (args.size() < 1) {
 	println """	
-	usage:  release.groovy {releaseVersion} {nextVersion}\n
-	  e.g:  release.groovy 1.6.0 1.7.0    (SNAPSHOT will be added automatically)
+	usage:  release.groovy {releaseVersion}\n
+	  e.g:  release.groovy 1.6.0
 	  
 	If release ends in ".0", then will create 'release' stream, otherwise 'hotfix'.
-	For hotfix, current working branch should be the release branch.
+	For hotfix, current working branch should be the release branch being hotfix'ed.
 	
 	Recommend that this script be executed in a fresh clone of the repo.
 	
@@ -40,11 +46,11 @@
 }
 
 def releaseVersion = args[0]
-def nextVersion = args[1]
+
 def hotfix = !releaseVersion.endsWith('.0')
 def stream = hotfix ? 'hotfix' : 'release'
 
-println "Creating ${hotfix ? 'hotfix' : 'release'} branch for $releaseVersion"
+println "Creating $stream branch for $releaseVersion"
 
 checkForSnapshots()
 
@@ -53,30 +59,18 @@
 println "Continue? Enter = Yes, ^C to cancel"
 System.in.newReader().readLine()
 
-updateVersion(releaseVersion)
-
-println 'hg com -m "release: set release version"'.execute().text
-
 println "hg flow ${stream} start v${releaseVersion} --dirty".execute().text
 
-println "hg update default".execute().text
-
-updateVersion(nextVersion + ".SNAPSHOT")
-
-println 'hg com -m "release: set next release version"'.execute().text
-
 println "hg update ${stream}/v${releaseVersion}".execute().text
 
-println "Done! Created $releaseVersion $stream branch."
-println "      Verify the branch created correctly then push the new branch."
-println "      If any problems, then delete repo and clone fresh repository."
+println "Starting dependency lock via gradle... (please wait)"
+println "cmd /c gradlew.bat deleteGLobalLock generateGlobalLock saveGlobalLock".execute().text
 
-def updateVersion(String newVersion) {
+println 'hg commit -A release.lock -m "lock dynamic dependencies for release"'.execute().text
 
-	new File('gradle.properties').write(
-		new File('gradle.properties').text.replaceAll(/version=(.*)/,"version=$newVersion")
-	)
-}
+println "Created $releaseVersion $stream branch with locked dynamic dependencies."
+println "   Verify the branch and release.lock file created correctly then push the new branch."
+println "   If any problems, then delete repo and clone a fresh copy repository."
 
 def checkForSnapshots() {
 		def lines = new File('gradle.properties').readLines() + new File('build.gradle').readLines()
@@ -88,6 +82,133 @@
 			println "project contains SNAPSHOT dependencies: \n\t" + snapshots.join('\n\t')
 			System.exit(1)
 		}
+}
+
+
+@TupleConstructor
+@Sortable
+class Version {
+
+	Integer major = 0
+	Integer minor = 0
+	Integer patch = 0
+	Boolean snapshot = true
+
+	Version nextVersion() {
+		new Version(major, minor + 1, 0)
+	}
+
+	String toString() {
+		"${major}.${minor}.${patch}${snapshot ? '.SNAPSHOT' : ''}"
+	}
 
 }
 
+
+@ToString(includes=['name','shortName','buildVersion','imageId','deployName'],includeNames= true)
+class BranchInfo {
+	def name
+	def stream = "none"
+	def buildNumber = ""
+	def changeset = ""
+	def version
+
+	BranchInfo(name = null) {
+		this.name = name
+		if (!name) {
+			this.name = determineName() ?: ''
+		}
+		this.name = this.name.replace('@', '-')
+		determineStream()
+		buildNumber = System.getenv('bamboo_buildNumber') ?: ""
+		changeset = System.getenv('bamboo_planRepository_revision') ?: ""
+	}
+
+	String getDefaultDependencyStatus() {
+		return isRelease() ? 'release' : 'integration'
+	}
+
+	private boolean isRelease() {
+		return stream in ['release', 'hotfix']
+	}
+
+	def getShortName() {
+		def result = name.contains('/') ? name.split('/')[1] : name
+	}
+
+	String getBuildVersion() {
+		def v = isRelease() ? shortName - "v": ""
+		return v
+	}
+
+	def Version getVersion() {
+		if (!version) {
+			if (isRelease()) {
+				version = new Version(*getBuildVersion().split('\\.')*.toInteger(), false)
+			} else {
+				version = findSnapshotVersion()
+			}
+		}
+		return version
+	}
+
+	def getImageId() {
+		(buildVersion ?:  shortName.take(25)) + (buildNumber ? "-${buildNumber}" : "-0")
+	}
+
+	def getDeployName() {
+		(buildVersion ?:  shortName.take(25)).toLowerCase().collectReplacements {
+			('a'..'z').contains(it) || ('0'..'9').contains(it) || it == "-" ? null : '-'
+		}
+	}
+
+	def getHash() {
+		generateMD5(name)
+	}
+	def generateMD5(String s) {
+		def digest = java.security.MessageDigest.getInstance("MD5")
+		digest.update(s.bytes);
+		new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
+	}
+
+	private findSnapshotVersion() {
+		def versions = "hg branches --closed".execute().text.split('\n').findAll {
+			it.startsWith( 'release') || it.startsWith( 'hotfix')
+		}.collect {
+			it.replaceAll('\\s+',' ').split(' ')[0].split('/')[1] - 'v'
+		}.collect {
+			new Version(*it.split('\\.')*.toInteger())
+		}.sort { v1, v2 -> v2 <=> v1 }
+
+		return versions ?  versions.first().nextVersion() : new Version().nextVersion()
+
+	}
+
+
+	def determineName()  {
+		try {
+			def branch = "hg branch".execute().text.trim()
+			def rawParents = 'hg parents'.execute().text
+			def parent = rawParents.split('\n').find { it.startsWith("branch") }?.split(":")?.getAt(1)?.trim()
+			return parent ?: branch
+		} catch (e) {
+			['.hg/branch', '../.hg/branch'].findResult {
+				new File(it).exists() ? new File(it).text : null
+			}
+		}
+	}
+
+	void determineStream() {
+		def flowConfig = new File('.hgflow').exists() ? new File('.hgflow') : new File('../.hgflow')
+		if (flowConfig.exists()) {
+			def flows = new Properties()
+			flows.load(flowConfig.newReader())
+			flows.stringPropertyNames().each {
+				if (!it.startsWith("[") && name.startsWith(flows.getProperty(it))) {
+					stream = it
+				}
+			}
+		}
+	}
+
+}
\ No newline at end of file