jjb: lava: rename lttng-baremetal-tests to system-tests
[lttng-ci.git] / scripts / system-tests / system-trigger.groovy
1 /**
2 * Copyright (C) 2017 - Francis Deslauriers <francis.deslauriers@efficios.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 import hudson.console.HyperlinkNote
19 import hudson.model.*
20 import java.io.File
21 import org.eclipse.jgit.api.Git
22 import org.eclipse.jgit.lib.Ref
23
24 class InvalidKVersionException extends Exception {
25 public InvalidKVersionException(String message) {
26 super(message)
27 }
28 }
29
30 class EmptyKVersionException extends Exception {
31 public EmptyKVersionException(String message) {
32 super(message)
33 }
34 }
35
36 class VanillaKVersion implements Comparable<VanillaKVersion> {
37
38 Integer major = 0
39 Integer majorB = 0
40 Integer minor = 0
41 Integer patch = 0
42 Integer rc = Integer.MAX_VALUE
43 Boolean inStable = false;
44
45 VanillaKVersion() {}
46
47 VanillaKVersion(version) {
48 this.parse(version)
49 }
50
51 static VanillaKVersion minKVersion() {
52 return new VanillaKVersion("v0.0.0")
53 }
54
55 static VanillaKVersion maxKVersion() {
56 return new VanillaKVersion("v" + Integer.MAX_VALUE + ".0.0")
57 }
58
59 static VanillaKVersion factory(version) {
60 return new VanillaKVersion(version)
61 }
62
63 def parse(version) {
64 this.major = 0
65 this.majorB = 0
66 this.minor = 0
67 this.patch = 0
68 this.rc = Integer.MAX_VALUE
69
70 if (!version) {
71 throw new EmptyKVersionException("Empty kernel version")
72 }
73
74 def match = version =~ /^v(\d+)\.(\d+)(\.(\d+))?(\.(\d+))?(-rc(\d+))?$/
75 if (!match) {
76 throw new InvalidKVersionException("Invalid kernel version: ${version}")
77 }
78
79 Integer offset = 0;
80
81 // Major
82 this.major = Integer.parseInt(match.group(1))
83 if (this.major <= 2) {
84 offset = 2
85 this.majorB = Integer.parseInt(match.group(2))
86 }
87
88 // Minor
89 if (match.group(2 + offset) != null) {
90 this.minor = Integer.parseInt(match.group(2 + offset))
91 }
92
93 // Patch level
94 if (match.group(4 + offset) != null) {
95 this.patch = Integer.parseInt(match.group(4 + offset))
96 this.inStable = true
97 }
98
99 // RC
100 if (match.group(8) != null) {
101 this.rc = Integer.parseInt(match.group(8))
102 }
103 }
104
105 Boolean isInStableBranch() {
106 return this.inStable
107 }
108
109 // Return true if both version are of the same stable branch
110 Boolean isSameStable(VanillaKVersion o) {
111 if (this.major != o.major) {
112 return false
113 }
114 if (this.majorB != o.majorB) {
115 return false
116 }
117 if (this.minor != o.minor) {
118 return false
119 }
120
121 return true
122 }
123
124 @Override int compareTo(VanillaKVersion o) {
125 if (this.major != o.major) {
126 return Integer.compare(this.major, o.major)
127 }
128 if (this.majorB != o.majorB) {
129 return Integer.compare(this.majorB, o.majorB)
130 }
131 if (this.minor != o.minor) {
132 return Integer.compare(this.minor, o.minor)
133 }
134 if (this.patch != o.patch) {
135 return Integer.compare(this.patch, o.patch)
136 }
137 if (this.rc != o.rc) {
138 return Integer.compare(this.rc, o.rc)
139 }
140
141 // Same version
142 return 0;
143 }
144
145 String toString() {
146 String vString = "v${this.major}"
147
148 if (this.majorB > 0) {
149 vString = vString.concat(".${this.majorB}")
150 }
151
152 vString = vString.concat(".${this.minor}")
153
154 if (this.patch > 0) {
155 vString = vString.concat(".${this.patch}")
156 }
157
158 if (this.rc > 0 && this.rc < Integer.MAX_VALUE) {
159 vString = vString.concat("-rc${this.rc}")
160 }
161 return vString
162 }
163 }
164
165 class RunConfiguration {
166 def linuxBranch
167 def linuxTagId
168 def lttngBranch
169 def lttngModulesCommitId
170 def lttngToolsCommitId
171 def lttngUstCommitId
172 RunConfiguration(linuxBranch, linuxTagId, lttngBranch, lttngToolsCommitId,
173 lttngModulesCommitId, lttngUstCommitId) {
174 this.linuxBranch = linuxBranch
175 this.linuxTagId = linuxTagId
176 this.lttngBranch = lttngBranch
177 this.lttngModulesCommitId = lttngModulesCommitId
178 this.lttngToolsCommitId = lttngToolsCommitId
179 this.lttngUstCommitId = lttngUstCommitId
180 }
181
182 String toString() {
183 return "${this.linuxBranch}:{${this.linuxTagId}}, ${this.lttngBranch}:{${this.lttngModulesCommitId}, ${this.lttngToolsCommitId}, ${this.lttngUstCommitId}}"
184 }
185 }
186
187 def LoadPreviousIdsFromWorkspace = { ondiskpath ->
188 def previousIds = []
189 try {
190 File myFile = new File(ondiskpath);
191 def input = new ObjectInputStream(new FileInputStream(ondiskpath))
192 previousIds = input.readObject()
193 input.close()
194 } catch (all) {
195 println("Failed to load previous ids from disk.")
196 }
197 return previousIds
198 }
199
200 def saveCurrentIdsToWorkspace = { currentIds, ondiskpath ->
201 try {
202 File myFile = new File(ondiskpath);
203 myFile.createNewFile();
204 def out = new ObjectOutputStream(new FileOutputStream(ondiskpath))
205 out.writeObject(currentIds)
206 out.close()
207 } catch (all) {
208 println("Failed to save previous ids from disk.")
209 }
210 }
211
212 def GetHeadCommits = { remoteRepo, branchesOfInterest ->
213 def remoteHeads = [:]
214 def remoteHeadRefs = Git.lsRemoteRepository()
215 .setTags(false)
216 .setHeads(true)
217 .setRemote(remoteRepo).call()
218
219 remoteHeadRefs.each {
220 def branch = it.getName().replaceAll('refs/heads/', '')
221 if (branchesOfInterest.contains(branch))
222 remoteHeads[branch] = it.getObjectId().name()
223 }
224
225 return remoteHeads
226 }
227
228 def GetTagIds = { remoteRepo ->
229 def remoteTags = [:]
230 def remoteTagRefs = Git.lsRemoteRepository()
231 .setTags(true)
232 .setHeads(false)
233 .setRemote(remoteRepo).call()
234
235 remoteTagRefs.each {
236 // Exclude release candidate tags
237 if (!it.getName().contains('-rc')) {
238 remoteTags[it.getName().replaceAll('refs/tags/', '')] = it.getObjectId().name()
239 }
240 }
241
242 return remoteTags
243 }
244
245 def GetLastTagOfBranch = { tagRefs, branch ->
246 def tagVersions = tagRefs.collect {new VanillaKVersion(it.key)}
247 def currMax = new VanillaKVersion('v0.0.0');
248 if (!branch.contains('master')){
249 def targetVersion = new VanillaKVersion(branch.replaceAll('linux-', 'v').replaceAll('.y', ''))
250 tagVersions.each {
251 if (it.isSameStable(targetVersion)) {
252 if (currMax < it) {
253 currMax = it;
254 }
255 }
256 }
257 } else {
258 tagVersions.each {
259 if (!it.isInStableBranch() && currMax < it) {
260 currMax = it;
261 }
262 }
263 }
264 return currMax.toString()
265 }
266
267 // Returns the latest tags of each of the branches passed in the argument
268 def GetLastTagIds = { remoteRepo, branchesOfInterest ->
269 def remoteHeads = GetHeadCommits(remoteRepo, branchesOfInterest)
270 def remoteTagRefs = GetTagIds(remoteRepo)
271 def remoteLastTagCommit = [:]
272
273 remoteTagRefs = remoteTagRefs.findAll { !it.key.contains("v2.") }
274 branchesOfInterest.each {
275 remoteLastTagCommit[it] = remoteTagRefs[GetLastTagOfBranch(remoteTagRefs, it)]
276 }
277
278 return remoteLastTagCommit
279 }
280
281 def CraftJobName = { jobType, runConfig ->
282 return "${jobType}_k${runConfig.linuxBranch}_l${runConfig.lttngBranch}"
283 }
284
285 def LaunchJob = { jobName, runConfig ->
286 def job = Hudson.instance.getJob(jobName)
287 def params = []
288 for (paramdef in job.getProperty(ParametersDefinitionProperty.class).getParameterDefinitions()) {
289 params += paramdef.getDefaultParameterValue();
290 }
291
292 params.add(new StringParameterValue('tools_commit_id', runConfig.lttngToolsCommitId))
293 params.add(new StringParameterValue('modules_commit_id', runConfig.lttngModulesCommitId))
294 params.add(new StringParameterValue('ust_commit_id', runConfig.lttngUstCommitId))
295 params.add(new StringParameterValue('kernel_tag_id', runConfig.linuxTagId))
296 job.scheduleBuild2(0, new Cause.UpstreamCause(build), new ParametersAction(params))
297 println "Launching job: ${HyperlinkNote.encodeTo('/' + job.url, job.fullDisplayName)}"
298 }
299
300 def jobTypes = ['baremetal_tests', 'vm_tests', 'baremetal_benchmarks']
301 final String toolsRepo = "https://github.com/lttng/lttng-tools.git"
302 final String modulesRepo = "https://github.com/lttng/lttng-modules.git"
303 final String ustRepo = "https://github.com/lttng/lttng-ust.git"
304 final String linuxRepo = "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git"
305
306 final String toolsOnDiskPath = build.getEnvironment(listener).get('WORKSPACE') + "/on-disk-tools-ref"
307 final String modulesOnDiskPath = build.getEnvironment(listener).get('WORKSPACE') + "/on-disk-modules-ref"
308 final String ustOnDiskPath = build.getEnvironment(listener).get('WORKSPACE') + "/on-disk-ust-ref"
309 final String linuxOnDiskPath = build.getEnvironment(listener).get('WORKSPACE') + "/on-disk-linux-ref"
310
311 def recentLttngBranchesOfInterest = ['master', 'stable-2.10', 'stable-2.9']
312 def recentLinuxBranchesOfInterest = ['master', 'linux-4.9.y', 'linux-4.4.y']
313
314 def legacyLttngBranchesOfInterest = ['stable-2.7']
315 def legacyLinuxBranchesOfInterest = ['linux-3.18.y', 'linux-4.4.y']
316
317 // Generate configurations of interest
318 def configurationOfInterest = [] as Set
319
320 recentLttngBranchesOfInterest.each { lttngBranch ->
321 recentLinuxBranchesOfInterest.each { linuxBranch ->
322 configurationOfInterest.add([lttngBranch, linuxBranch])
323 }
324 }
325
326 legacyLttngBranchesOfInterest.each { lttngBranch ->
327 legacyLinuxBranchesOfInterest.each { linuxBranch ->
328 configurationOfInterest.add([lttngBranch, linuxBranch])
329 }
330 }
331
332 def lttngBranchesOfInterest = recentLttngBranchesOfInterest + legacyLttngBranchesOfInterest
333 def linuxBranchesOfInterest = recentLinuxBranchesOfInterest + legacyLinuxBranchesOfInterest
334
335 // For Linux branches, we look for new non-RC tags
336 def toolsHeadCommits = GetHeadCommits(toolsRepo, lttngBranchesOfInterest)
337 def modulesHeadCommits = GetHeadCommits(modulesRepo, lttngBranchesOfInterest)
338 def ustHeadCommits = GetHeadCommits(ustRepo, lttngBranchesOfInterest)
339
340 // For LTTng branches, we look for new commits
341 def linuxLastTagIds = GetLastTagIds(linuxRepo, linuxBranchesOfInterest)
342
343 // Load previously build Linux tag ids
344 def oldLinuxTags = LoadPreviousIdsFromWorkspace(linuxOnDiskPath) as Set
345
346 // Load previously built LTTng commit ids
347 def oldToolsHeadCommits = LoadPreviousIdsFromWorkspace(toolsOnDiskPath) as Set
348 def oldModulesHeadCommits = LoadPreviousIdsFromWorkspace(modulesOnDiskPath) as Set
349 def oldUstHeadCommits = LoadPreviousIdsFromWorkspace(ustOnDiskPath) as Set
350
351 def newOldLinuxTags = oldLinuxTags
352 def newOldToolsHeadCommits = oldToolsHeadCommits
353 def newOldModulesHeadCommits = oldModulesHeadCommits
354 def newOldUstHeadCommits = oldUstHeadCommits
355
356 def canaryRunConfigs = [] as Set
357 canaryRunConfigs.add(
358 ['v4.4.9', '1a1a512b983108015ced1e7a7c7775cfeec42d8c', 'v2.8.1','d11e0db', '7fd9215', '514a87f'] as RunConfiguration)
359
360 def runConfigs = [] as Set
361
362 // For each top of branch kernel tags that were not seen before, schedule one
363 // job for each lttng/linux tracked configurations
364 linuxLastTagIds.each { linuxTag ->
365 if (!oldLinuxTags.contains(linuxTag.value)) {
366 lttngBranchesOfInterest.each { lttngBranch ->
367 if (configurationOfInterest.contains([lttngBranch, linuxTag.key])) {
368 runConfigs.add([linuxTag.key, linuxTag.value,
369 lttngBranch, toolsHeadCommits[lttngBranch],
370 modulesHeadCommits[lttngBranch], ustHeadCommits[lttngBranch]]
371 as RunConfiguration)
372
373 newOldLinuxTags.add(linuxTag.value)
374 }
375 }
376 }
377 }
378
379 // For each top of branch commits that were not seen before, schedule one job
380 // for each lttng/linux tracked configurations
381 toolsHeadCommits.each { toolsHead ->
382 if (!oldToolsHeadCommits.contains(toolsHead.value)) {
383 linuxLastTagIds.each { linuxTag ->
384 def lttngBranch = toolsHead.key
385 if (configurationOfInterest.contains([lttngBranch, linuxTag.key])) {
386 runConfigs.add([linuxTag.key, linuxTag.value,
387 lttngBranch, toolsHeadCommits[lttngBranch],
388 modulesHeadCommits[lttngBranch], ustHeadCommits[lttngBranch]]
389 as RunConfiguration)
390
391 newOldToolsHeadCommits.add(toolsHead.value)
392 }
393 }
394 }
395 }
396
397 // For each top of branch commits that were not seen before, schedule one job
398 // for each lttng/linux tracked configurations
399 modulesHeadCommits.each { modulesHead ->
400 if (!oldModulesHeadCommits.contains(modulesHead.value)) {
401 linuxLastTagIds.each { linuxTag ->
402 def lttngBranch = modulesHead.key
403 if (configurationOfInterest.contains([lttngBranch, linuxTag.key])) {
404 runConfigs.add([linuxTag.key, linuxTag.value,
405 lttngBranch, toolsHeadCommits[lttngBranch],
406 modulesHeadCommits[lttngBranch], ustHeadCommits[lttngBranch]]
407 as RunConfiguration)
408
409 newOldModulesHeadCommits.add(modulesHead.value)
410 }
411 }
412 }
413 }
414
415 // For each top of branch commits that were not seen before, schedule one job
416 // for each lttng/linux tracked configurations
417 ustHeadCommits.each { ustHead ->
418 if (!oldUstHeadCommits.contains(ustHead.value)) {
419 linuxLastTagIds.each { linuxTag ->
420 def lttngBranch = ustHead.key
421 if (configurationOfInterest.contains([lttngBranch, linuxTag.key])) {
422 runConfigs.add([linuxTag.key, linuxTag.value,
423 lttngBranch, toolsHeadCommits[lttngBranch],
424 modulesHeadCommits[lttngBranch], ustHeadCommits[lttngBranch]]
425 as RunConfiguration)
426
427 newOldUstHeadCommits.add(ustHead.value)
428 }
429 }
430 }
431 }
432
433 // Save the tag and commit IDs scheduled in the past and during this run to the workspace
434 saveCurrentIdsToWorkspace(newOldLinuxTags, linuxOnDiskPath)
435 saveCurrentIdsToWorkspace(newOldToolsHeadCommits, toolsOnDiskPath)
436 saveCurrentIdsToWorkspace(newOldModulesHeadCommits, modulesOnDiskPath)
437 saveCurrentIdsToWorkspace(newOldUstHeadCommits, ustOnDiskPath)
438
439 // Launch jobs
440 println("Schedule canary jobs once a day")
441 canaryRunConfigs.each { config ->
442 jobTypes.each { type ->
443 LaunchJob(type + '_canary', config)
444 }
445 }
446
447 if (runConfigs.size() > 0) {
448 println("Schedule jobs because of code changes.")
449 runConfigs.each { config ->
450 jobTypes.each { type ->
451 LaunchJob(CraftJobName(type, config), config);
452 }
453
454 // Jobs to run only on master branchs of both linux and lttng
455 if (config.linuxBranch.contains('master') &&
456 config.lttngBranch.contains('master')) {
457 LaunchJob(CraftJobName('vm_tests_fuzzing', config), config)
458 }
459 }
460 } else {
461 println("No new commit or tags, nothing more to do.")
462 }
This page took 0.047945 seconds and 5 git commands to generate.