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+ 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