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+ stages {
20+ stage('Clean up builds') {
21+ parallel {
22+ stage('Equinox') {
23+ steps {
24+ sshagent (['projects-storage.eclipse.org-bot-ssh']) {
25+ script {
26+ def retainedBuilds = 3 // Keep the three most recent builds
27+ for (buildType in ['I', 'Y']) {
28+ def builds = listSubDirectoriesOnRemote("${EP_EQUINOX_DROPS}", "-name '${buildType}*'") // sorted in ascending order
29+ if (retainedBuilds < builds.size()) {
30+ for (buildDir in builds.subList(0, builds.size() - retainedBuilds)) {
31+ sh "$SSH rm -rf ${EP_EQUINOX_DROPS}/${buildDir}"
32+ }
33+ } else {
34+ echo 'Nothing to clean.'
35+ }
36+ }
37+ }
38+ }
39+ }
40+ }
41+ stage('Eclipse') {
42+ steps {
43+ sshagent (['projects-storage.eclipse.org-bot-ssh']) {
44+ // Among all builds older than five days, keep only the first stable build of each week (starting Monday) and delete all others.
45+ // But keep at least the last four builds regardless of their age and all of those younger than five days.
46+ script {
47+ def BUILD_TYPE = 'I'
48+ def MINIMAL_RETENTION_DAYS = 5 // Keep builds for at least five days
49+ def MINIMAL_RETENTION_COUNT = 4 // Retain at least the four most recent builds
50+
51+ def oldIBuilds = listSubDirectoriesOnRemote("${EP_ECLIPSE_DROPS}", "-ctime +${MINIMAL_RETENTION_DAYS} -name '${BUILD_TYPE}*'") // sort ascending to start with Mondays
52+ echo "Old I-Builds: ${oldIBuilds}"
53+ def allIBuilds = listSubDirectoriesOnRemote("${EP_ECLIPSE_DROPS}", "-name '${BUILD_TYPE}*'").reverse() // sort descending to start with latest
54+ def toRetain = allIBuilds.subList(0, Math.min(allIBuilds.size(), MINIMAL_RETENTION_COUNT)).toSet().sort()
55+ echo "Number of I-builds before cleaning: ${allIBuilds.size()}"
56+ echo "Minimally retained I-Builds: ${toRetain}"
57+ def Set<Integer> retainedWeeks = []
58+ for (oldIBuild in oldIBuilds) {
59+ if (toRetain.contains(oldIBuild)) {
60+ echo "Not removed (since one of 4 newest, even though old): ${oldIBuild}"
61+ continue;
62+ }
63+ def weekOfYear = parseWeekOfYear(oldIBuild)
64+ if (!retainedWeeks.contains(weekOfYear)) {
65+ def isUnstable = sh(script: """$SSH "if [ -f '${EP_ECLIPSE_DROPS}/${oldIBuild}/buildUnstable' ]; then echo 'true'; fi" """, returnStdout: true).toBoolean()
66+ if (!isUnstable) {
67+ retainedWeeks.add(weekOfYear) // Retain the first stable build of a week
68+ echo "Retain stable build ${oldIBuild} for week ${weekOfYear}"
69+ continue;
70+ } else {
71+ echo "Ignore unstable build ${oldIBuild} to be retained for week ${weekOfYear}"
72+ }
73+ }
74+ sh "$SSH rm -rf ${EP_ECLIPSE_DROPS}/${oldIBuild}"
75+ }
76+ def nbuilds = listSubDirectoriesOnRemote("${EP_ECLIPSE_DROPS}", "-name '${BUILD_TYPE}*'").size()
77+ echo "Number of I-builds after cleaning: ${nbuilds}"
78+ }
79+ }
80+ build job: 'Releng/updateIndex', wait: false
81+ }
82+ }
83+ }
84+ }
85+ }
86+ }
87+
88+ private List<String> listSubDirectoriesOnRemote(String remoteDirectory, String pattern) {
89+ def result = sh(script: """$SSH "cd ${remoteDirectory} && find -maxdepth 1 -type d ${pattern}" """, returnStdout: true).trim()
90+ return result.isEmpty() ? [] : result.split('\\s+').collect{ d -> d.startsWith('./') ? d.substring(2) : d }.sort()
91+ }
92+
93+ @NonCPS
94+ private int parseWeekOfYear(String iBuildId) {
95+ def idMatcher = iBuildId =~ /I(?<date>\d{8})-(?<time>\d{4})/
96+ if (!idMatcher.matches()) {
97+ error "buildID: ${iBuildId}, does not match the expected pattern."
98+ }
99+ def date = idMatcher.group('date')
100+ def localDate = java.time.LocalDate.parse("${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}")
101+ // return localDate.get(java.time.temporal.IsoFields.WEEK_OF_WEEK_BASED_YEAR)
102+ int mondayDOY = localDate.getDayOfYear() - localDate.getDayOfWeek().ordinal();
103+ // This is actually not absolutly correct but as we only want to now if two dates are in the same week (i.e. have the same Monday), it's sufficient
104+ int weekOfYear = (7 + mondayDOY) / 7;
105+ return weekOfYear == 53 ? 0 : weekOfYear;
106+ }
0 commit comments