Skip to content

Commit b81ccea

Browse files
committed
[Build] Unify clean-ups jobs as Jenkins pipelines and inline scripts
Migrate all clean-up jobs to pure Jenkinsfile/pipeline based jobs. Unify the daily clean-up builds into one job that handles Eclispe and Equinox builds in parallel - Try to move the clean-up of old releases into the daily clean-up so that it just runs on the day after the release? - Move remaining two jobs to the 'Releng' folder as it already contains the manually maintained variant of it. FIXUP] More. TODO: what is currently clean-ing up Y-build drops?! TODO: Delete https://download.eclipse.org/eclipse/workingDir/
1 parent 17ac0d2 commit b81ccea

12 files changed

+341
-383
lines changed

JenkinsJobs/Cleanup/FOLDER.groovy

Lines changed: 0 additions & 3 deletions
This file was deleted.

JenkinsJobs/Cleanup/cleanupDLsite.groovy

Lines changed: 0 additions & 33 deletions
This file was deleted.

JenkinsJobs/Cleanup/cleanupReleaseArtifacts.groovy

Lines changed: 0 additions & 102 deletions
This file was deleted.

JenkinsJobs/Cleanup/dailyCleanOldBuilds.groovy

Lines changed: 0 additions & 68 deletions
This file was deleted.

JenkinsJobs/Releng/FOLDER.groovy

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,51 @@ folder('Releng') {
22
description('Jobs related to routine releng tasks. Some are periodic, some are "manual" jobs ran only when needed.')
33
}
44

5+
pipelineJob('Releng/cleanupBuilds'){
6+
displayName('Daily Cleanup of old Builds')
7+
description('Remove old builds from the downloads servers.')
8+
properties {
9+
pipelineTriggers {
10+
triggers {
11+
cron {
12+
spec('''TZ=America/Toronto
13+
0 4 * * *
14+
0 16 * * *
15+
''')
16+
}
17+
}
18+
}
19+
}
20+
definition {
21+
cpsScm {
22+
lightweight(true)
23+
scm {
24+
github('eclipse-platform/eclipse.platform.releng.aggregator', 'master')
25+
}
26+
scriptPath('JenkinsJobs/Releng/cleanupBuilds.jenkinsfile')
27+
}
28+
}
29+
}
30+
31+
pipelineJob('Releng/cleanupReleaseArtifacts'){
32+
parameters {
33+
booleanParam('REMOVE_Y_BUILDS', false, '''Typically only true in even releases.
34+
True: Remove Y-build directories and move P-build directory to P-builds-old for safekeeping.
35+
False: Remove P-builds-old directory.
36+
''' )
37+
}
38+
definition {
39+
cpsScm {
40+
lightweight(true)
41+
scm {
42+
github('eclipse-platform/eclipse.platform.releng.aggregator', 'master')
43+
}
44+
scriptPath('JenkinsJobs/Releng/cleanupReleaseArtifacts.jenkinsfile')
45+
}
46+
}
47+
}
48+
49+
550
pipelineJob('Releng/deployToMaven'){
651
displayName('Deploy to Maven')
752
description('''\
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
pipeline {
2+
options {
3+
skipDefaultCheckout()
4+
timestamps()
5+
timeout(time: 15, unit: 'MINUTES')
6+
buildDiscarder(logRotator(numToKeepStr:'5'))
7+
}
8+
agent {
9+
label 'basic'
10+
}
11+
environment {
12+
// Download Server locations (would very seldom change)
13+
EP_ROOT = '/home/data/httpd/download.eclipse.org'
14+
EP_ECLIPSE_DROPS = "${EP_ROOT}/eclipse/downloads/drops4"
15+
EP_EQUINOX_DROPS = "${EP_ROOT}/equinox/drops"
16+
17+
SSH = 'ssh [email protected]'
18+
19+
EQUINOX_RETENTION_COUNT = '3' // Keep the three most recent builds
20+
ECLIPSE_MINIMAL_RETENTION_DAYS = '5' // Minimal number of days for which a drop should be retained
21+
ECLIPSE_MINIMAL_RETENTION_COUNT = '4' // Minimal number of drops to retain regardless of their age
22+
}
23+
stages {
24+
stage('Checkout SCM') {
25+
steps {
26+
checkout scm
27+
script {
28+
utilities = load "JenkinsJobs/shared/utilities.groovy"
29+
def buildProperties = readProperties(file: 'cje-production/buildproperties.txt')
30+
devVersionMajor = buildProperties.STREAMMajor.replace('"','').toInteger() // Remove surrounding quotes
31+
devVersionMinor = buildProperties.STREAMMinor.replace('"','').toInteger() // Remove surrounding quotes
32+
devVersionService = buildProperties.STREAMService.replace('"','').toInteger() // Remove surrounding quotes
33+
}
34+
}
35+
}
36+
stage('Clean up builds') {
37+
parallel {
38+
stage('Equinox') {
39+
steps {
40+
sshagent (['projects-storage.eclipse.org-bot-ssh']) {
41+
script {
42+
for (buildType in ['I', 'Y']) {
43+
def builds = utilities.listSubDirectoriesOnRemote("${EP_EQUINOX_DROPS}", "-name '${buildType}*'") // sorted in ascending order
44+
if (env.EQUINOX_RETENTION_COUNT.toInteger() < builds.size()) {
45+
for (buildDir in builds.subList(0, builds.size() - env.EQUINOX_RETENTION_COUNT.toInteger())) {
46+
sh "$SSH rm -rf ${EP_EQUINOX_DROPS}/${buildDir}"
47+
}
48+
} else {
49+
echo 'Nothing to clean.'
50+
}
51+
}
52+
}
53+
}
54+
}
55+
}
56+
stage('Eclipse I-builds') {
57+
steps {
58+
sshagent (['projects-storage.eclipse.org-bot-ssh']) {
59+
cleanUpBuildDropsOfCurrentStream('I')
60+
}
61+
build job: 'Releng/updateIndex', wait: false
62+
}
63+
}
64+
stage('Eclipse Y-builds') {
65+
steps {
66+
sshagent (['projects-storage.eclipse.org-bot-ssh']) {
67+
cleanUpBuildDropsOfCurrentStream('Y')
68+
//TODO: or just keep the last 5? Y-build drops regardless of their version.
69+
// If there is a new Java release soon after the Eclipse release the Y-build remains on the old Y-build any ways and produces new builds until the release
70+
// If there is no new Java release soon (usually on even Eclipse versions), there won't be Y-builds on the maintanance branch anyways.
71+
// In release clean-ups the Y-build drops should then not be touched at all.
72+
}
73+
}
74+
}
75+
}
76+
post {
77+
success {
78+
build job: 'Releng/updateIndex', wait: false
79+
}
80+
}
81+
}
82+
}
83+
}
84+
85+
@groovy.transform.Field
86+
def utilities = null
87+
@groovy.transform.Field
88+
def int devVersionMajor = null
89+
@groovy.transform.Field
90+
def int devVersionMinor = null
91+
@groovy.transform.Field
92+
def int devVersionService = null
93+
94+
def cleanUpBuildDropsOfCurrentStream(String buildType) {
95+
// Among all builds older than minimal retention time, keep only the first stable build of each week (starting Monday) and delete all others.
96+
// But keep at least the minimal retention count of builds regardless of their age and all of those younger than the minimal retention time.
97+
98+
def oldBuilds = utilities.listSubDirectoriesOnRemote("${EP_ECLIPSE_DROPS}", "-ctime +${ECLIPSE_MINIMAL_RETENTION_DAYS} -name '${buildType}*'", devVersionMajor, devVersionMinor, devVersionService) // sort ascending to start with Mondays
99+
echo "Old ${buildType}-Builds: ${oldBuilds}"
100+
def allBuilds = utilities.listSubDirectoriesOnRemote("${EP_ECLIPSE_DROPS}", "-name '${buildType}*'", devVersionMajor, devVersionMinor, devVersionService).reverse() // sort descending to start with latest
101+
echo "Number of ${buildType}-builds before cleaning: ${allBuilds.size()}"
102+
def toRetain = allBuilds.subList(0, Math.min(allBuilds.size(), env.ECLIPSE_MINIMAL_RETENTION_COUNT.toInteger())).toSet().sort()
103+
echo "Minimally retained ${buildType}-Builds: ${toRetain}"
104+
def Set<Integer> retainedWeeks = []
105+
for (oldBuild in oldBuilds) {
106+
if (toRetain.contains(oldBuild)) {
107+
echo "Not removed (since one of 4 newest, even though old): ${oldBuild}"
108+
continue;
109+
}
110+
def weekOfYear = parseWeekOfYear(oldBuild)
111+
if (!retainedWeeks.contains(weekOfYear)) {
112+
def isUnstable = sh(script: """$SSH "if [ -f '${EP_ECLIPSE_DROPS}/${oldBuild}/buildUnstable' ]; then echo 'true'; fi" """, returnStdout: true).toBoolean()
113+
if (!isUnstable) {
114+
retainedWeeks.add(weekOfYear) // Retain the first stable build of a week
115+
echo "Retain stable build ${oldBuild} for week ${weekOfYear}"
116+
continue;
117+
} else {
118+
echo "Ignore unstable build ${oldBuild} to be retained for week ${weekOfYear}"
119+
}
120+
}
121+
sh "$SSH rm -rf ${EP_ECLIPSE_DROPS}/${oldBuild}"
122+
}
123+
def nbuilds = utilities.listSubDirectoriesOnRemote("${EP_ECLIPSE_DROPS}", "-name '${buildType}*'", devVersionMajor, devVersionMinor, devVersionService).size()
124+
echo "Number of ${buildType}-builds after cleaning: ${nbuilds}"
125+
}
126+
127+
@NonCPS
128+
private int parseWeekOfYear(String iBuildId) {
129+
def idMatcher = iBuildId =~ /I(?<date>\d{8})-(?<time>\d{4})/
130+
if (!idMatcher.matches()) {
131+
error "buildID: ${iBuildId}, does not match the expected pattern."
132+
}
133+
def date = idMatcher.group('date')
134+
def localDate = java.time.LocalDate.parse("${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}")
135+
return localDate.get(java.time.temporal.IsoFields.WEEK_OF_WEEK_BASED_YEAR)
136+
}

0 commit comments

Comments
 (0)