comparison 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
comparison
equal deleted inserted replaced
215:5bebb590b30e 216:b628d49d2891
1 #!groovy 1 #!groovy
2 import groovy.transform.Sortable
3 import groovy.transform.ToString
4 import groovy.transform.TupleConstructor
2 5
3 /** 6 /**
4 This script implements the SSDT branching strategy based on hg flow. 7 This script implements the SSDT branching strategy based on hg flow
5 8 and dependency resolution locking.
6 The intention is to reduce drudgery of creating release branches. The 9
7 script tries to do the right thing based on standard SSDT project structures, 10 The intention is to automate of creation of correctly configured release branches.
8 but it is the user's responsibility to ensure it's correct. 11 The script tries to do the right thing based on standard SSDT project structures,
9 12 but it is the user's responsibility to ensure it's correct.
10 The script does NOT "hg push --new-branch". That step is left for you 13
14 The script does NOT "hg push --new-branch". That step is left for you
11 if the branch was created correctly. 15 if the branch was created correctly.
12 16
13 */ 17 */
14 def project = new Properties() 18
15 19 def branch = new BranchInfo()
16 if (new File('gradle.properties').exists() ) { 20
17 project.load(new File('gradle.properties').newInputStream()) 21 println "Project:\n"
18 } 22
19 23 println "\trepo\t${("hg path".execute().text.split('=') ?: ['', ''])[1].trim()}"
20 println "\nCurrent project:" 24 println "\tbranch\t$branch"
21 println "\tversion: " + project.version ?: "Unknown" 25 println "\tversion\t$branch.version"
22 println "-" * 20 26
23 27 println "-" * 40
24 if (args.size() < 2) { 28 println ""
29
30 if (args.size() < 1) {
25 println """ 31 println """
26 usage: release.groovy {releaseVersion} {nextVersion}\n 32 usage: release.groovy {releaseVersion}\n
27 e.g: release.groovy 1.6.0 1.7.0 (SNAPSHOT will be added automatically) 33 e.g: release.groovy 1.6.0
28 34
29 If release ends in ".0", then will create 'release' stream, otherwise 'hotfix'. 35 If release ends in ".0", then will create 'release' stream, otherwise 'hotfix'.
30 For hotfix, current working branch should be the release branch. 36 For hotfix, current working branch should be the release branch being hotfix'ed.
31 37
32 Recommend that this script be executed in a fresh clone of the repo. 38 Recommend that this script be executed in a fresh clone of the repo.
33 39
34 ** Any uncommitted changes in the working directory will be committed with 40 ** Any uncommitted changes in the working directory will be committed with
35 the initial setting of the version. These are assumed to be 41 the initial setting of the version. These are assumed to be
38 44
39 System.exit(0) 45 System.exit(0)
40 } 46 }
41 47
42 def releaseVersion = args[0] 48 def releaseVersion = args[0]
43 def nextVersion = args[1] 49
44 def hotfix = !releaseVersion.endsWith('.0') 50 def hotfix = !releaseVersion.endsWith('.0')
45 def stream = hotfix ? 'hotfix' : 'release' 51 def stream = hotfix ? 'hotfix' : 'release'
46 52
47 println "Creating ${hotfix ? 'hotfix' : 'release'} branch for $releaseVersion" 53 println "Creating $stream branch for $releaseVersion"
48 54
49 checkForSnapshots() 55 checkForSnapshots()
50 56
51 println "hg flow $stream start v${releaseVersion} --dry-run".execute().text 57 println "hg flow $stream start v${releaseVersion} --dry-run".execute().text
52 58
53 println "Continue? Enter = Yes, ^C to cancel" 59 println "Continue? Enter = Yes, ^C to cancel"
54 System.in.newReader().readLine() 60 System.in.newReader().readLine()
55 61
56 updateVersion(releaseVersion)
57
58 println 'hg com -m "release: set release version"'.execute().text
59
60 println "hg flow ${stream} start v${releaseVersion} --dirty".execute().text 62 println "hg flow ${stream} start v${releaseVersion} --dirty".execute().text
61 63
62 println "hg update default".execute().text
63
64 updateVersion(nextVersion + ".SNAPSHOT")
65
66 println 'hg com -m "release: set next release version"'.execute().text
67
68 println "hg update ${stream}/v${releaseVersion}".execute().text 64 println "hg update ${stream}/v${releaseVersion}".execute().text
69 65
70 println "Done! Created $releaseVersion $stream branch." 66 println "Starting dependency lock via gradle... (please wait)"
71 println " Verify the branch created correctly then push the new branch." 67 println "cmd /c gradlew.bat deleteGLobalLock generateGlobalLock saveGlobalLock".execute().text
72 println " If any problems, then delete repo and clone fresh repository." 68
73 69 println 'hg commit -A release.lock -m "lock dynamic dependencies for release"'.execute().text
74 def updateVersion(String newVersion) { 70
75 71 println "Created $releaseVersion $stream branch with locked dynamic dependencies."
76 new File('gradle.properties').write( 72 println " Verify the branch and release.lock file created correctly then push the new branch."
77 new File('gradle.properties').text.replaceAll(/version=(.*)/,"version=$newVersion") 73 println " If any problems, then delete repo and clone a fresh copy repository."
78 )
79 }
80 74
81 def checkForSnapshots() { 75 def checkForSnapshots() {
82 def lines = new File('gradle.properties').readLines() + new File('build.gradle').readLines() 76 def lines = new File('gradle.properties').readLines() + new File('build.gradle').readLines()
83 def snapshots = lines.collect { it.trim() }.findAll{ 77 def snapshots = lines.collect { it.trim() }.findAll{
84 it.contains('.SNAPSHOT') && !it.startsWith('version=') || 78 it.contains('.SNAPSHOT') && !it.startsWith('version=') ||
86 } 80 }
87 if (snapshots) { 81 if (snapshots) {
88 println "project contains SNAPSHOT dependencies: \n\t" + snapshots.join('\n\t') 82 println "project contains SNAPSHOT dependencies: \n\t" + snapshots.join('\n\t')
89 System.exit(1) 83 System.exit(1)
90 } 84 }
91 85 }
92 } 86
93 87
88 @TupleConstructor
89 @Sortable
90 class Version {
91
92 Integer major = 0
93 Integer minor = 0
94 Integer patch = 0
95 Boolean snapshot = true
96
97 Version nextVersion() {
98 new Version(major, minor + 1, 0)
99 }
100
101 String toString() {
102 "${major}.${minor}.${patch}${snapshot ? '.SNAPSHOT' : ''}"
103 }
104
105 }
106
107
108 @ToString(includes=['name','shortName','buildVersion','imageId','deployName'],includeNames= true)
109 class BranchInfo {
110 def name
111 def stream = "none"
112 def buildNumber = ""
113 def changeset = ""
114 def version
115
116 BranchInfo(name = null) {
117 this.name = name
118 if (!name) {
119 this.name = determineName() ?: ''
120 }
121 this.name = this.name.replace('@', '-')
122 determineStream()
123 buildNumber = System.getenv('bamboo_buildNumber') ?: ""
124 changeset = System.getenv('bamboo_planRepository_revision') ?: ""
125 }
126
127 String getDefaultDependencyStatus() {
128 return isRelease() ? 'release' : 'integration'
129 }
130
131 private boolean isRelease() {
132 return stream in ['release', 'hotfix']
133 }
134
135 def getShortName() {
136 def result = name.contains('/') ? name.split('/')[1] : name
137 }
138
139 String getBuildVersion() {
140 def v = isRelease() ? shortName - "v": ""
141 return v
142 }
143
144 def Version getVersion() {
145 if (!version) {
146 if (isRelease()) {
147 version = new Version(*getBuildVersion().split('\\.')*.toInteger(), false)
148 } else {
149 version = findSnapshotVersion()
150 }
151 }
152 return version
153 }
154
155 def getImageId() {
156 (buildVersion ?: shortName.take(25)) + (buildNumber ? "-${buildNumber}" : "-0")
157 }
158
159 def getDeployName() {
160 (buildVersion ?: shortName.take(25)).toLowerCase().collectReplacements {
161 ('a'..'z').contains(it) || ('0'..'9').contains(it) || it == "-" ? null : '-'
162 }
163 }
164
165 def getHash() {
166 generateMD5(name)
167 }
168 def generateMD5(String s) {
169 def digest = java.security.MessageDigest.getInstance("MD5")
170 digest.update(s.bytes);
171 new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
172 }
173
174 private findSnapshotVersion() {
175 def versions = "hg branches --closed".execute().text.split('\n').findAll {
176 it.startsWith( 'release') || it.startsWith( 'hotfix')
177 }.collect {
178 it.replaceAll('\\s+',' ').split(' ')[0].split('/')[1] - 'v'
179 }.collect {
180 new Version(*it.split('\\.')*.toInteger())
181 }.sort { v1, v2 -> v2 <=> v1 }
182
183 return versions ? versions.first().nextVersion() : new Version().nextVersion()
184
185 }
186
187
188 def determineName() {
189 try {
190 def branch = "hg branch".execute().text.trim()
191 def rawParents = 'hg parents'.execute().text
192 def parent = rawParents.split('\n').find { it.startsWith("branch") }?.split(":")?.getAt(1)?.trim()
193 return parent ?: branch
194 } catch (e) {
195 ['.hg/branch', '../.hg/branch'].findResult {
196 new File(it).exists() ? new File(it).text : null
197 }
198 }
199 }
200
201 void determineStream() {
202 def flowConfig = new File('.hgflow').exists() ? new File('.hgflow') : new File('../.hgflow')
203 if (flowConfig.exists()) {
204 def flows = new Properties()
205 flows.load(flowConfig.newReader())
206 flows.stringPropertyNames().each {
207 if (!it.startsWith("[") && name.startsWith(flows.getProperty(it))) {
208 stream = it
209 }
210 }
211 }
212 }
213
214 }