Commit | Line | Data |
---|---|---|
017c762b JR |
1 | enum KernelVersioning { |
2 | MAJOR,MINOR,REVISION,BUILD | |
3 | } | |
4 | ||
81470b33 | 5 | class BasicVersion implements Comparable<BasicVersion> { |
017c762b JR |
6 | int major = -1 |
7 | int minor = -1 | |
8 | int revision = -1 | |
9 | int build = -1 | |
10 | int rc = -1 | |
5a67a345 | 11 | String gitRefs |
017c762b JR |
12 | |
13 | // Default Constructor | |
81470b33 | 14 | BasicVersion() {} |
017c762b | 15 | |
81470b33 JR |
16 | // Parse a version string of format X.Y.Z.W-A |
17 | BasicVersion(String version, String ref) { | |
5a67a345 | 18 | gitRefs = ref |
d11d0665 | 19 | def tokenVersion |
017c762b JR |
20 | def token |
21 | if (version.contains('-')) { | |
22 | // Release canditate | |
23 | token = version.tokenize('-') | |
24 | tokenVersion = token[0] | |
81470b33 | 25 | if (token[1]?.isInteger()) { |
017c762b JR |
26 | rc = token[1].toInteger() |
27 | } | |
28 | } else { | |
29 | tokenVersion = version | |
30 | } | |
31 | ||
32 | tokenVersion = tokenVersion.tokenize('.') | |
33 | ||
34 | def tagEnum = KernelVersioning.MAJOR | |
35 | tokenVersion.each { | |
81470b33 | 36 | if (it?.isInteger()) { |
017c762b JR |
37 | switch (tagEnum) { |
38 | case KernelVersioning.MAJOR: | |
39 | major = it.toInteger() | |
40 | tagEnum = KernelVersioning.MINOR | |
41 | break | |
42 | case KernelVersioning.MINOR: | |
43 | minor = it.toInteger() | |
44 | tagEnum = KernelVersioning.REVISION | |
45 | break | |
46 | case KernelVersioning.REVISION: | |
47 | revision = it.toInteger() | |
48 | tagEnum = KernelVersioning.BUILD | |
49 | break | |
50 | case KernelVersioning.BUILD: | |
51 | build = it.toInteger() | |
52 | tagEnum = -1 | |
53 | break | |
54 | default: | |
55 | println("Unsupported version extension") | |
56 | println("Trying to parse: ${version}") | |
57 | println("Invalid sub version value: ${it}") | |
d11d0665 | 58 | //TODO: throw exception for jenkins |
017c762b JR |
59 | } |
60 | } | |
61 | } | |
62 | } | |
63 | ||
017c762b JR |
64 | String print() { |
65 | String ret = "" | |
66 | if (major != -1) { | |
67 | ret += major | |
68 | if (minor != -1) { | |
69 | ret += "." + minor | |
70 | if (revision != -1) { | |
71 | ret += "." + revision | |
72 | if (build != -1) { | |
73 | ret += "." + build | |
74 | } | |
75 | } | |
76 | } | |
77 | if (rc != -1) { | |
5a67a345 | 78 | ret += "-rc" + rc |
017c762b JR |
79 | } |
80 | } | |
81 | return ret | |
82 | } | |
83 | ||
84 | @Override | |
81470b33 | 85 | int compareTo(BasicVersion kernelVersion) { |
017c762b JR |
86 | return major <=> kernelVersion.major ?: minor <=> kernelVersion.minor ?: revision <=> kernelVersion.revision ?: build <=> kernelVersion.build ?: rc <=> kernelVersion.rc |
87 | } | |
88 | } | |
89 | ||
6f47f2cd | 90 | def kernelTagCutOff = new BasicVersion("4.0", "") |
d11d0665 JR |
91 | def modulesBranches = ["master","stable-2.5.0","stable-2.6.0", "stable-2.4.0"] |
92 | ||
93 | ||
017c762b JR |
94 | def linuxURL = "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git" |
95 | def modulesURL = "git://git.lttng.org/lttng-modules.git" | |
96 | ||
97 | // Linux specific variable | |
98 | String linuxCheckoutTo = "linux-source" | |
99 | String recipeCheckoutTo = "recipe" | |
100 | String modulesCheckoutTo = "lttng-modules" | |
101 | ||
102 | def linuxGitReference = "/home/jenkins/gitcache/linux-stable.git" | |
017c762b | 103 | |
d11d0665 | 104 | // Check if we are on jenkins |
81f87da0 JR |
105 | // Useful for outside jenkins devellopment related to groovy only scripting |
106 | def isJenkinsInstance = binding.variables.containsKey('JENKINS_HOME') | |
107 | ||
132cba4a | 108 | // Fetch tags and format |
017c762b JR |
109 | // Split the string into sections based on | |
110 | // And pipe the results together | |
132cba4a | 111 | String process = "git ls-remote -t $linuxURL | cut -c42- | sort -V" |
017c762b JR |
112 | def out = new StringBuilder() |
113 | def err = new StringBuilder() | |
114 | Process result = process.tokenize( '|' ).inject( null ) { p, c -> | |
115 | if( p ) | |
116 | p | c.execute() | |
117 | else | |
118 | c.execute() | |
119 | } | |
120 | ||
121 | result.waitForProcessOutput(out,err) | |
122 | ||
123 | if ( result.exitValue() == 0 ) { | |
124 | def branches = out.readLines().collect { | |
d11d0665 | 125 | // Scrap special string tag |
5a67a345 | 126 | it.replaceAll("\\^\\{\\}", '') |
017c762b JR |
127 | } |
128 | ||
129 | branches = branches.unique() | |
017c762b | 130 | |
81f87da0 | 131 | List versions = [] |
017c762b | 132 | branches.each { branch -> |
d11d0665 JR |
133 | def stripBranch = branch.replaceAll("rc", '').replaceAll(/refs\/tags\/v/,'') |
134 | BasicVersion kVersion = new BasicVersion(stripBranch, branch) | |
017c762b JR |
135 | versions.add(kVersion) |
136 | } | |
137 | ||
81f87da0 | 138 | // Sort the version via Comparable implementation of KernelVersion |
017c762b JR |
139 | versions = versions.sort() |
140 | ||
132cba4a | 141 | // Find the version cutoff |
d11d0665 | 142 | def cutoffPos = versions.findIndexOf{(it.major >= kernelTagCutOff.major) && (it.minor >= kernelTagCutOff.minor) && (it.revision >= kernelTagCutOff.revision) && (it.build >= kernelTagCutOff.build) && (it.rc >= kernelTagCutOff.rc)} |
017c762b | 143 | |
017c762b JR |
144 | // Get last version and include only last rc |
145 | def last | |
146 | def lastNoRcPos | |
147 | last = versions.last() | |
148 | if (last.rc != -1) { | |
149 | int i = versions.size()-1 | |
150 | while (i > -1 && versions[i].rc != -1 ) { | |
151 | i-- | |
152 | } | |
153 | lastNoRcPos = i + 1 | |
154 | } else { | |
155 | lastNoRcPos = versions.size() | |
156 | } | |
157 | ||
d11d0665 | 158 | String modulesPrefix = "lttng-modules" |
162a2360 | 159 | String kernelPrefix = "dsl-kernel" |
d11d0665 JR |
160 | String separator = "-" |
161 | // Actual job creation | |
017c762b | 162 | for (int i = cutoffPos; i < versions.size() ; i++) { |
81f87da0 | 163 | |
d11d0665 | 164 | // Only create for valid build |
017c762b JR |
165 | if ( (i < lastNoRcPos && versions[i].rc == -1) || (i >= lastNoRcPos)) { |
166 | println ("Preparing job for") | |
d11d0665 JR |
167 | |
168 | String jobName = kernelPrefix + separator + versions[i].print() | |
169 | ||
170 | // Generate modules job based on supported modules jobs | |
171 | def modulesJob = [:] | |
172 | modulesBranches.each { branch -> | |
173 | modulesJob[branch] = modulesPrefix + separator + branch + separator + jobName | |
174 | } | |
175 | ||
176 | // Jenkins only dsl | |
017c762b | 177 | println(jobName) |
d11d0665 JR |
178 | if (isJenkinsInstance) { |
179 | matrixJob("${jobName}") { | |
180 | using("linux-master") | |
181 | scm { | |
182 | git { | |
183 | remote { | |
184 | url("${linuxURL}") | |
185 | } | |
186 | branch(versions[i].gitRefs) | |
187 | shallowClone(true) | |
188 | relativeTargetDir(linuxCheckoutTo) | |
189 | reference(linuxGitReference) | |
190 | } | |
191 | } | |
192 | publishers { | |
193 | modulesJob.each { | |
194 | downstream(it.value, 'SUCCESS') | |
195 | } | |
196 | } | |
197 | } | |
198 | } | |
199 | // Corresponding Module job | |
ef0e4e86 JR |
200 | modulesJob.each { job -> |
201 | println("\t" + job.key + " " + job.value) | |
d11d0665 | 202 | if (isJenkinsInstance) { |
ef0e4e86 | 203 | matrixJob(job.value) { |
d11d0665 JR |
204 | using("modules") |
205 | multiscm { | |
206 | git { | |
207 | remote { | |
208 | name(kernelPrefix) | |
209 | url("${linuxURL}") | |
210 | } | |
211 | branch(versions[i].gitRefs) | |
212 | shallowClone(true) | |
213 | relativeTargetDir(linuxCheckoutTo) | |
214 | reference(linuxGitReference) | |
215 | } | |
216 | git { | |
217 | remote { | |
218 | name(modulesPrefix) | |
219 | url(modulesURL) | |
220 | } | |
ef0e4e86 | 221 | branch(job.key) |
d11d0665 JR |
222 | relativeTargetDir(modulesCheckoutTo) |
223 | } | |
224 | } | |
225 | steps { | |
226 | copyArtifacts("${jobName}/arch=\$arch", "linux-artifact/**", '', false, false) { | |
227 | latestSuccessful(true) // Latest successful build | |
228 | } | |
229 | shell(readFileFromWorkspace('lttng-modules/lttng-modules-dsl-master.sh')) | |
230 | } | |
231 | } | |
232 | } | |
233 | } | |
234 | } | |
235 | } | |
162a2360 JR |
236 | |
237 | // Trigger generations | |
238 | def dslTriggerKernel = """\ | |
239 | ||
240 | import hudson.model.* | |
241 | import hudson.AbortException | |
242 | import hudson.console.HyperlinkNote | |
243 | import java.util.concurrent.CancellationException | |
244 | ||
245 | ||
246 | def jobs = hudson.model.Hudson.instance.items | |
247 | def fail = false | |
b46e797c | 248 | def jobStartWith = "${kernelPrefix}" |
162a2360 JR |
249 | |
250 | def anotherBuild | |
251 | jobs.each { job -> | |
252 | def jobName = job.getName() | |
253 | if (jobName.startsWith(jobStartWith)) { | |
254 | def lastBuild = job.getLastBuild() | |
255 | if (lastBuild == null) { | |
256 | try { | |
257 | def future = job.scheduleBuild2(0, new Cause.UpstreamCause(build)) | |
258 | println "\\tWaiting for the completion of " + HyperlinkNote.encodeTo('/' + job.url, job.fullDisplayName) | |
259 | anotherBuild = future.get() | |
260 | } catch (CancellationException x) { | |
261 | throw new AbortException("\${job.fullDisplayName} aborted.") | |
262 | } | |
263 | println HyperlinkNote.encodeTo('/' + anotherBuild.url, anotherBuild.fullDisplayName) + " completed. Result was " + anotherBuild.result | |
264 | ||
265 | build.result = anotherBuild.result | |
266 | if (anotherBuild.result != Result.SUCCESS && anotherBuild.result != Result.UNSTABLE) { | |
267 | // We abort this build right here and now. | |
268 | fail = true | |
269 | println("Build Failed") | |
270 | } | |
271 | } else { | |
272 | println("\\tAlready built") | |
273 | } | |
274 | } | |
275 | } | |
276 | ||
c76d8fe2 JR |
277 | if (fail){ |
278 | throw new AbortException("Some job failed") | |
279 | } | |
280 | """ | |
281 | def dslTriggerModule = """\ | |
282 | import hudson.model.* | |
283 | import hudson.AbortException | |
284 | import hudson.console.HyperlinkNote | |
285 | import java.util.concurrent.CancellationException | |
286 | ||
287 | ||
288 | def jobs = hudson.model.Hudson.instance.items | |
289 | def fail = false | |
6a7fce90 | 290 | def jobStartWith = "JOBPREFIX" |
c76d8fe2 JR |
291 | |
292 | def anotherBuild | |
293 | jobs.each { job -> | |
294 | def jobName = job.getName() | |
295 | if (jobName.startsWith(jobStartWith)) { | |
296 | def lastBuild = job.getLastBuild() | |
297 | if (lastBuild == null) { | |
298 | try { | |
299 | def future = job.scheduleBuild2(0, new Cause.UpstreamCause(build)) | |
300 | println "\\tWaiting for the completion of " + HyperlinkNote.encodeTo('/' + job.url, job.fullDisplayName) | |
301 | anotherBuild = future.get() | |
302 | } catch (CancellationException x) { | |
303 | throw new AbortException("\${job.fullDisplayName} aborted.") | |
304 | } | |
305 | println HyperlinkNote.encodeTo('/' + anotherBuild.url, anotherBuild.fullDisplayName) + " completed. Result was " + anotherBuild.result | |
306 | ||
307 | build.result = anotherBuild.result | |
308 | if (anotherBuild.result != Result.SUCCESS && anotherBuild.result != Result.UNSTABLE) { | |
309 | // We abort this build right here and now. | |
310 | fail = true | |
311 | println("Build Failed") | |
312 | } | |
313 | } else { | |
314 | println("\\tAlready built") | |
315 | } | |
316 | } | |
317 | } | |
318 | ||
162a2360 JR |
319 | if (fail){ |
320 | throw new AbortException("Some job failed") | |
321 | } | |
322 | """ | |
323 | if (isJenkinsInstance) { | |
324 | freeStyleJob("dsl-trigger-kernel") { | |
325 | steps { | |
6f47f2cd | 326 | systemGroovyCommand(dslTriggerKernel) |
162a2360 | 327 | } |
c76d8fe2 JR |
328 | } |
329 | ||
330 | modulesBranches.each { branch -> | |
331 | freeStyleJob("dsl-trigger-module-${branch}") { | |
332 | steps { | |
6a7fce90 | 333 | systemGroovyCommand(dslTriggerModule.replaceAll("JOBPREFIX",modulesPrefix + separator + branch + separator)) |
c76d8fe2 JR |
334 | } |
335 | } | |
336 | } | |
162a2360 | 337 | } |
017c762b | 338 | } |