From 316c886e2173a3e553796db6cbf50c32cc056836 Mon Sep 17 00:00:00 2001 From: Hannes Wellmann Date: Sun, 28 Sep 2025 15:03:19 +0200 Subject: [PATCH] [Build] Read parameters from Jenkins-files and create jobs dynamically When creating a pipeline-job the Jenkins JobDSL, by default, doesn't consider the parameters defined within the pipeline-job's Jenkinsfile. Therefore parameters defined only within the Jenkinsfile are only added to the job's definition after the pipeline was executed first (and updated on subsequent executions, if changes are applied). In order to make parameters available even on the first run, instead they have to be defined in the groovy-file that uses the Jenkins Job-DSL to define the pipeline-job. This is an long standing and known, yet unsolved issue in Jenkins: - https://issues.jenkins.io/browse/JENKINS-41929 The current solution to define parameters in the job-definition has the drawback that an important part of the pipeline is defined in another file, which makes maintenance more difficult. This implements an enhanced work-around, allowing to define the parameters within a pipeline's Jenkinsfile again: During the definition of a pipeline-job, it's Jenkinsfile file is parsed and its AST is searched for parameter definitions. All encountered parameters are translated dynamically into corresponding parameters of the job definition. With this new possibility all parameters have their definition moved into their pipeline's Jenkinsfile. Furthermore this adds a JenkinsFile for the seedJob of the RelEng JIPP, which was previously manually defined as a free-style job. That seedJob pipeline also creates jobs dynamically from all pipeline files in the corresponding folders. It's therefore sufficient to just add a JenkinsFile and not necessary anymore to explicitly add a corresponding pipeline job definition anywhere. This also ensures a unified naming schema of all jobs that corresponds to the name of the pipeline's Jenkinsfile. --- JenkinsJobs/AutomatedTests/FOLDER.groovy | 4 - .../AutomatedTests/I_unit_tests.groovy | 2 +- .../Builds/DockerImagesBuild.jenkinsfile | 6 + JenkinsJobs/Builds/FOLDER.groovy | 81 ------- JenkinsJobs/Builds/build.jenkinsfile | 2 +- JenkinsJobs/Builds/markBuild.jenkinsfile | 14 +- JenkinsJobs/Cleanup/FOLDER.groovy | 43 ---- JenkinsJobs/Cleanup/cleanupBuilds.jenkinsfile | 9 + .../cleanupReleaseArtifacts.jenkinsfile | 3 + JenkinsJobs/Releng/FOLDER.groovy | 185 --------------- .../Releng/collectTestResults.jenkinsfile | 12 +- JenkinsJobs/Releng/deployToMaven.jenkinsfile | 39 +++- .../modifyP2CompositeRepository.jenkinsfile | 13 ++ .../Releng/prepareNextDevCycle.jenkinsfile | 42 ++-- JenkinsJobs/Releng/promoteBuild.jenkinsfile | 46 ++-- .../Releng/publishPromotedBuild.jenkinsfile | 16 +- JenkinsJobs/Releng/updateIndex.jenkinsfile | 4 + JenkinsJobs/SmokeTests/FOLDER.groovy | 31 --- .../SmokeTests/StartSmokeTests.jenkinsfile | 10 +- JenkinsJobs/YBuilds/FOLDER.groovy | 38 ---- JenkinsJobs/YBuilds/Y_unit_tests.groovy | 2 +- JenkinsJobs/seedJob.jenkinsfile | 215 ++++++++++++++++++ 22 files changed, 384 insertions(+), 433 deletions(-) delete mode 100644 JenkinsJobs/AutomatedTests/FOLDER.groovy delete mode 100644 JenkinsJobs/Builds/FOLDER.groovy delete mode 100644 JenkinsJobs/Cleanup/FOLDER.groovy delete mode 100644 JenkinsJobs/Releng/FOLDER.groovy delete mode 100644 JenkinsJobs/SmokeTests/FOLDER.groovy delete mode 100644 JenkinsJobs/YBuilds/FOLDER.groovy create mode 100644 JenkinsJobs/seedJob.jenkinsfile diff --git a/JenkinsJobs/AutomatedTests/FOLDER.groovy b/JenkinsJobs/AutomatedTests/FOLDER.groovy deleted file mode 100644 index 65b19e3d367..00000000000 --- a/JenkinsJobs/AutomatedTests/FOLDER.groovy +++ /dev/null @@ -1,4 +0,0 @@ -folder('AutomatedTests') { - displayName('Automated Tests') - description('Folder for Unit Tests') -} \ No newline at end of file diff --git a/JenkinsJobs/AutomatedTests/I_unit_tests.groovy b/JenkinsJobs/AutomatedTests/I_unit_tests.groovy index a03e29a9b26..ad96e5a2558 100644 --- a/JenkinsJobs/AutomatedTests/I_unit_tests.groovy +++ b/JenkinsJobs/AutomatedTests/I_unit_tests.groovy @@ -1,4 +1,4 @@ -def config = new groovy.json.JsonSlurper().parseText(readFileFromWorkspace('JenkinsJobs/JobDSL.json')) +def config = new groovy.json.JsonSlurper().parseText(readFileFromWorkspace('JobDSL.json')) def TEST_CONFIGURATIONS = [ [os: 'linux' , ws:'gtk' , arch: 'x86_64' , javaVersion: 21, agentLabel: 'ubuntu-2404' , javaHome: "tool(type:'jdk', name:'temurin-jdk21-latest')" ], diff --git a/JenkinsJobs/Builds/DockerImagesBuild.jenkinsfile b/JenkinsJobs/Builds/DockerImagesBuild.jenkinsfile index e6816c4d926..297978aa615 100644 --- a/JenkinsJobs/Builds/DockerImagesBuild.jenkinsfile +++ b/JenkinsJobs/Builds/DockerImagesBuild.jenkinsfile @@ -1,3 +1,6 @@ +// Constants read by +private static final _JOB_DESCRIPTION = 'Build and publish custom Docker images' + pipeline { options { skipDefaultCheckout() @@ -6,6 +9,9 @@ pipeline { buildDiscarder(logRotator(numToKeepStr:'5')) disableConcurrentBuilds(abortPrevious: true) } + triggers { + cron '@weekly' + } agent { label 'docker-build' } diff --git a/JenkinsJobs/Builds/FOLDER.groovy b/JenkinsJobs/Builds/FOLDER.groovy deleted file mode 100644 index 2ef46fce678..00000000000 --- a/JenkinsJobs/Builds/FOLDER.groovy +++ /dev/null @@ -1,81 +0,0 @@ -def config = new groovy.json.JsonSlurper().parseText(readFileFromWorkspace('JenkinsJobs/JobDSL.json')) - -folder('Builds') { - description('Eclipse periodic build jobs.') -} - -config.I.streams.each{ STREAM, configuration -> - - pipelineJob('Builds/I-build-' + STREAM){ - description('Daily Eclipse Integration builds.') - properties { - pipelineTriggers { - triggers { - cron { - spec(configuration.schedule ? """TZ=America/Toronto -# Format: Minute Hour Day Month Day-of-week (1-7) -# - - - Integration Eclipse SDK builds - - - -# Schedule: 6 PM every day until end of RC2 -${configuration.schedule} -""" : '') - } - } - } - } - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', configuration.branch) - } - scriptPath('JenkinsJobs/Builds/build.jenkinsfile') - } - } - } - -} - -pipelineJob('Builds/Build-Docker-images'){ - description('Build and publish custom Docker images') - properties { - pipelineTriggers { - triggers { - cron { spec('@weekly') } - } - } - } - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Builds/DockerImagesBuild.jenkinsfile') - } - } -} - -pipelineJob('Builds/mark-build'){ - displayName("Mark build") - description("Mark a build as stable/unstable or to (not to) be kept indefinitely.") - parameters { - stringParam('buildId', null, "ID of the build to be marked.") - choiceParam('markAs', [ - 'STABLE', - 'UNSTABLE', - 'RETAINED_INDEFINITELY', - 'NOT_RETAINED', - ], 'The kind of marker to apply to (respectively remove from) the specified build.') - stringParam('issueURL', null, 'URL of the causing Github issue or PR (only relevant if the build is marked as unstable).') - } - - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Builds/markBuild.jenkinsfile') - } - } -} diff --git a/JenkinsJobs/Builds/build.jenkinsfile b/JenkinsJobs/Builds/build.jenkinsfile index 3eafc47b5e3..47af9a6a65d 100644 --- a/JenkinsJobs/Builds/build.jenkinsfile +++ b/JenkinsJobs/Builds/build.jenkinsfile @@ -303,7 +303,7 @@ spec: ] } } - build job: 'SmokeTests/Start-smoke-tests', wait: false, parameters: [string(name: 'buildId', value: "${BUILD_IID}")] + build job: 'SmokeTests/StartSmokeTests', wait: false, parameters: [string(name: 'buildId', value: "${BUILD_IID}")] } } stage('Trigger publication to Maven snapshots repo') { diff --git a/JenkinsJobs/Builds/markBuild.jenkinsfile b/JenkinsJobs/Builds/markBuild.jenkinsfile index c9fbed9746a..774f464c9e8 100644 --- a/JenkinsJobs/Builds/markBuild.jenkinsfile +++ b/JenkinsJobs/Builds/markBuild.jenkinsfile @@ -1,3 +1,6 @@ +// Constants read by +private static final _JOB_DESCRIPTION = 'Mark a build as stable/unstable or to (not to) be kept indefinitely.' + pipeline { options { skipDefaultCheckout() @@ -5,6 +8,13 @@ pipeline { timeout(time: 5, unit: 'MINUTES') buildDiscarder(logRotator(numToKeepStr:'5')) } + parameters { + string(name: 'buildId', trim: true, description: 'ID of the build to be marked.') + choice(name: 'markAs', choices: [ 'STABLE', 'UNSTABLE', 'RETAINED_INDEFINITELY', 'NOT_RETAINED' ], + description: 'The kind of marker to apply to (respectively remove from) the specified build.') + string(name: 'issueURL', trim: true, + description: 'URL of the causing Github issue or PR (only relevant if the build is marked as unstable).') + } agent { label 'basic' } @@ -18,10 +28,6 @@ pipeline { steps { sshagent(['projects-storage.eclipse.org-bot-ssh']) { sh '''#!/bin/bash -xe - # Strip spaces from the buildId and eclipseStream - buildId=$(echo $buildId|tr -d ' ') - issueURL=$(echo $issueURL|tr -d ' ') - if [ -z "$buildId" ]; then echo "BuildId is empty! Exiting." exit 1 diff --git a/JenkinsJobs/Cleanup/FOLDER.groovy b/JenkinsJobs/Cleanup/FOLDER.groovy deleted file mode 100644 index 4fa6e00b659..00000000000 --- a/JenkinsJobs/Cleanup/FOLDER.groovy +++ /dev/null @@ -1,43 +0,0 @@ -folder('Cleanup') { - description('Cleanup Scripts.') -} - -pipelineJob('Cleanup/cleanupBuilds'){ - displayName('Daily Cleanup of old Builds') - description('Remove old builds from the downloads servers.') - properties { - pipelineTriggers { - triggers { - cron { - spec('''TZ=America/Toronto -0 4 * * * -0 16 * * * -''') - } - } - } - } - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Cleanup/cleanupBuilds.jenkinsfile') - } - } -} - -pipelineJob('Cleanup/cleanupReleaseArtifacts'){ - displayName('Cleanup Release Artifacts') - description('Cleanup major artifacts from previous releases at the beginning of a new release.') - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Cleanup/cleanupReleaseArtifacts.jenkinsfile') - } - } -} diff --git a/JenkinsJobs/Cleanup/cleanupBuilds.jenkinsfile b/JenkinsJobs/Cleanup/cleanupBuilds.jenkinsfile index 30b4997bd66..9c317e5eae4 100644 --- a/JenkinsJobs/Cleanup/cleanupBuilds.jenkinsfile +++ b/JenkinsJobs/Cleanup/cleanupBuilds.jenkinsfile @@ -1,3 +1,6 @@ +// Constants read by job creation +private static final _JOB_DISPLAY_NAME = 'Daily Cleanup of old Builds' +private static final _JOB_DESCRIPTION = 'Remove old builds from the downloads servers.' def int EQUINOX_RETENTION_COUNT = 3 // Keep the three most recent builds def int ECLIPSE_I_BUILD_RETENTION_DAYS = 5 // Minimal number of days for which a drop should be retained @@ -11,6 +14,12 @@ pipeline { timeout(time: 15, unit: 'MINUTES') buildDiscarder(logRotator(numToKeepStr:'5')) } + triggers { + cron '''TZ=America/Toronto + 0 4 * * * + 0 16 * * * + ''' + } agent { label 'basic' } diff --git a/JenkinsJobs/Cleanup/cleanupReleaseArtifacts.jenkinsfile b/JenkinsJobs/Cleanup/cleanupReleaseArtifacts.jenkinsfile index 07a37f810c1..ea9c03f0768 100644 --- a/JenkinsJobs/Cleanup/cleanupReleaseArtifacts.jenkinsfile +++ b/JenkinsJobs/Cleanup/cleanupReleaseArtifacts.jenkinsfile @@ -1,3 +1,6 @@ +// Constants read by job creation +private static final _JOB_DESCRIPTION = 'Cleanup major artifacts from previous releases at the beginning of a new release.' + def int RELEASE_RETENTION_COUNT = 3 pipeline { diff --git a/JenkinsJobs/Releng/FOLDER.groovy b/JenkinsJobs/Releng/FOLDER.groovy deleted file mode 100644 index 87933d847b7..00000000000 --- a/JenkinsJobs/Releng/FOLDER.groovy +++ /dev/null @@ -1,185 +0,0 @@ -folder('Releng') { - description('Jobs related to routine releng tasks. Some are periodic, some are "manual" jobs ran only when needed.') -} - -pipelineJob('Releng/collectTestResults'){ - displayName('Collect Test Results') - description('Performs some summary analysis and writes unit test results to the download page.') - parameters { - stringParam('triggeringJob', null, 'Name of the job to collect results from: i.e. \'ep427I-unit-cen64-gtk3-java17\'.') - stringParam('buildURL', null, 'Build URL of the triggering job.') - stringParam('buildID', null, 'ID of the I-build being tested.') - } - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Releng/collectTestResults.jenkinsfile') - } - } -} - -pipelineJob('Releng/deployToMaven'){ - displayName('Deploy to Maven') - description('''\ -

-This job uses the CBI aggregator to produce a Maven-compatible repository -with contents as specified by the SDK4Mvn.aggr and -then deploys the artifacts for Eclipse-Platform, JDT, Equinox and PDE from the output: -

- -

-''') - parameters { // Define parameters in job configuration to make them available even for the very first build after this job was (re)created. - stringParam('sourceRepository', null, '''\ -The URL of the source P2 repository to be deployed.
-To deploy a snapshot, the 4.x-I-Builds child repository of the specific build should be specified, e.g. 'https://download.eclipse.org/eclipse/updates/4.37-I-builds/I20250710-1800/'
-To deploy a Release, the corresponding release repository should be specified, e.g. 'https://download.eclipse.org/eclipse/updates/4.36/R-4.36-202505281830/'
-If left blank (not recommended), the latest I-build is deployed. -

-''') - } - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Releng/deployToMaven.jenkinsfile') - } - } -} - -pipelineJob('Releng/modifyP2CompositeRepository'){ - displayName('Modify P2 Composite Repository') - description('Add or remove children from an Eclipse-P2 composite repository.') - parameters { - stringParam('repositoryPath', null, "Relative repository path from https://download.eclipse.org/. E.g. 'eclipse/updates/4.37-I-builds'") - stringParam('add', null, 'Comma separated list of children to add. May be empty') - stringParam('remove', null, 'Comma separated list of children to remove. May be empty') - stringParam('sizeLimit', null, ''' -The maximum number of childrem the modified composite should contain. -If the total number of children exceeds this limit (after adding new ones), a corresponding number of children is removed from the beginning of the list. -''') - stringParam('repositoryName', null, 'Optional name attribute of the composite repository to set (if blank the name is not changed)') - } - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Releng/modifyP2CompositeRepository.jenkinsfile') - } - } -} - -pipelineJob('Releng/prepareNextDevCycle'){ - displayName('Prepare Next Development Cycle') - description('Perform all steps to prepare the next development cycle of Eclipse.') - parameters { - booleanParam('DRY_RUN', true, '''\ -If enabled, the final publication of all changes is skipped respectivly all changes at the download-server happen in a 'try-out' area at https://download.eclipse.org/eclipse/try-outs/. -This area is cleaned on each dry-run and should be cleaned after a try-out session is completed. -Useful for debugging and to very that the pipeline behaves as intended. -''') - stringParam('NEXT_RELEASE_VERSION', null, 'Version of the release to prepare, for example: 4.37') - stringParam('PREVIOUS_RELEASE_CANDIDATE_ID', null, 'Id of the current release-candiate for the previous release, for example: S-4.36RC2-202505281830') - stringParam('NEXT_SIMREL_NAME', null, 'The name of the Simultanious Release that is targeted by the prepared release in the format yyyy-mm, for example: 2026-03') - stringParam('NEXT_JAVA_RELEASE_DATE', null, 'Release date of the next Java version, if it is released shortly after the Eclipse release (i.e. shortly after the GA_DATE specified above, usual for odd release versions), else left blank (usual for even releases). Value is in the format yyyy-mm-dd, for example: 2025-09-16') - } - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Releng/prepareNextDevCycle.jenkinsfile') - } - } -} - -pipelineJob('Releng/promoteBuild'){ - displayName('Promote Build') - description('''\ -This job does the "stage 1" or first part of a promotion. -It renames the files for Equinox and Eclipse, creates an appropriate repo on 'downloads', sync's everything to 'downloads', but leave everything "invisible" -- unless someone knows the exact URL. -This allows two things. First, allows artifacts some time to "mirror" when that is needed. -But also, allows the sites and repositories to be examined for correctness before making them visible to the world. -The second (deferred) step that makes things visible works, in part, based on some output of this first step. Hence, they must "share a workspace". -''') - parameters { - booleanParam('DRY_RUN', true, 'If enabled, the final publication of all changes is skipped. Useful for debugging and to very that the pipeline behaves as intended.') - stringParam('DROP_ID', null, '''\ -The name (or, build id) of the build to promote. Typically would be a value such as 'I20250714-1800'. -It must match the name of the build on the build machine. - ''') - stringParam('CHECKPOINT', null, 'M1, M3, RC1, RC2, RC3 etc (blank for final releases).') - stringParam('SIGNOFF_BUG', null, 'The issue that was used to "signoff" the checkpoint. If there are no unit test failures, this can be left blank. Otherwise a link is added to test page explaining that "failing unit tests have been investigated".') - } - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Releng/promoteBuild.jenkinsfile') - } - } -} - -pipelineJob('Releng/publishPromotedBuild'){ - displayName('Publish Promoted Build') - description('''\ -Make a 'release build', which was previously declared by running the 'Promote Build' job, visible. -The first part of a promotion -- the 'Promote Build' job -- puts the build at its final location, but keeps it hidden. -Therefore, both jobs have to share a 'workspace', and the output of the first job must remain in place until its time to "make visible". -''') - parameters { - stringParam('releaseBuildID', null, '''\ -The id of the 'milestone', 'release-candidate' or 'GA-release' build to make visible. -Typically would be a value such as 'S-4.26M1-202209281800' or 'R-4.36-202505281830'. -It must match the name of the build on the download server. -''') - } - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Releng/publishPromotedBuild.jenkinsfile') - } - } -} - -pipelineJob('Releng/updateIndex'){ - displayName('Update Download Index') - description('Recreates the Eclipse download page index.') - definition { - cpsScm { - lightweight(true) - scm { - github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') - } - scriptPath('JenkinsJobs/Releng/updateIndex.jenkinsfile') - } - } -} - diff --git a/JenkinsJobs/Releng/collectTestResults.jenkinsfile b/JenkinsJobs/Releng/collectTestResults.jenkinsfile index 6fd43149d03..2573a1acad6 100644 --- a/JenkinsJobs/Releng/collectTestResults.jenkinsfile +++ b/JenkinsJobs/Releng/collectTestResults.jenkinsfile @@ -1,3 +1,6 @@ +// Constants read by job creation +private static final _JOB_DESCRIPTION = 'Performs some summary analysis and writes unit test results to the download page.' + pipeline { options { skipDefaultCheckout() @@ -6,6 +9,11 @@ pipeline { buildDiscarder(logRotator(numToKeepStr:'15')) disableConcurrentBuilds() } + parameters { + string(name: 'triggeringJob', trim: true, description: 'Name of the job to collect results from: i.e. \'ep427I-unit-cen64-gtk3-java17\'.') + string(name: 'buildURL', trim: true, description: 'Build URL of the triggering job.') + string(name: 'buildID', trim: true, description: 'ID of the I-build being tested.') + } agent { label 'basic' } @@ -33,10 +41,6 @@ pipeline { steps { sshagent(['projects-storage.eclipse.org-bot-ssh']) { sh '''#!/bin/bash -xe - #trim inputs - buildID=$(echo $buildID|tr -d ' ') - buildURL=$(echo $buildURL|tr -d ' ') - triggeringJob=$(echo $triggeringJob|tr -d ' ') curl -L -o "${WORKSPACE}/buildproperties.shsource" http://download.eclipse.org/eclipse/downloads/drops4/${buildID}/buildproperties.shsource source "${WORKSPACE}/buildproperties.shsource" diff --git a/JenkinsJobs/Releng/deployToMaven.jenkinsfile b/JenkinsJobs/Releng/deployToMaven.jenkinsfile index af83f8472f6..1caa5aa05cb 100644 --- a/JenkinsJobs/Releng/deployToMaven.jenkinsfile +++ b/JenkinsJobs/Releng/deployToMaven.jenkinsfile @@ -1,3 +1,21 @@ +// Constants read by job creation +private static final _JOB_DESCRIPTION = '''\ +

+This job uses the CBI aggregator to produce a Maven-compatible repository +with contents as specified by the SDK4Mvn.aggr and +then deploys the artifacts for Eclipse-Platform, JDT, Equinox and PDE from the output: +

+ +

+''' + pipeline { options { timestamps() @@ -5,6 +23,22 @@ pipeline { buildDiscarder(logRotator(numToKeepStr:'10', artifactNumToKeepStr:'2')) checkoutToSubdirectory('git-repo') } + parameters { + string(name: 'sourceRepository', trim: true, description: '''\ + The URL of the source P2 repository to be deployed.
+ To deploy a snapshot, the 4.x-I-Builds child repository of the specific build should be specified, e.g. 'https://download.eclipse.org/eclipse/updates/4.37-I-builds/I20250710-1800/'
+ To deploy a Release, the corresponding release repository should be specified, e.g. 'https://download.eclipse.org/eclipse/updates/4.36/R-4.36-202505281830/'
+ If left blank (not recommended), the latest I-build is deployed. +

+ ''') + } agent { label 'basic' } @@ -21,7 +55,6 @@ pipeline { // prevent jline warning about inability to create a system terminal and increase keep-alive timeouts to increase stability in concurrent usage MVND = "mvnd -Dmvnd.daemonStorage=${WORKSPACE}/tools/mvnd -Dorg.jline.terminal.type=dumb -Dmvnd.keepAlive=1000 -Dmvnd.maxLostKeepAlive=600" } - // parameters declared in the definition of the invoking job stages { stage('Aggregate Maven repository') { steps { @@ -161,7 +194,7 @@ pipeline { ''' script { if ("${DEPLOYMENT_TYPE}" == 'release') { - def repoTag = "${sourceRepository}".trim() + def repoTag = "${sourceRepository}" if (repoTag.endsWith('/')) { repoTag = repoTag.substring(0, repoTag.length() - 1) } @@ -225,7 +258,7 @@ pipeline { } def determineDeploymentType() { - if ("${sourceRepository}".trim() =~ /\/(?\d+\.\d+)\/R-\k(\.\d+)?-\d{12}(\/)?$/) { + if ("${sourceRepository}" =~ /\/(?\d+\.\d+)\/R-\k(\.\d+)?-\d{12}(\/)?$/) { return 'release' } else { return 'snapshot' diff --git a/JenkinsJobs/Releng/modifyP2CompositeRepository.jenkinsfile b/JenkinsJobs/Releng/modifyP2CompositeRepository.jenkinsfile index 47d3c15a135..8201eedabb4 100644 --- a/JenkinsJobs/Releng/modifyP2CompositeRepository.jenkinsfile +++ b/JenkinsJobs/Releng/modifyP2CompositeRepository.jenkinsfile @@ -1,3 +1,6 @@ +// Constants read by job creation +private static final _JOB_DESCRIPTION = 'Add or remove children from an Eclipse-P2 composite repository.' + pipeline { options { disableConcurrentBuilds() // prevent concurrent updates of the same repository @@ -6,6 +9,16 @@ pipeline { timeout(time: 15, unit: 'MINUTES') buildDiscarder(logRotator(numToKeepStr:'5')) } + parameters { + string(name: 'repositoryPath', trim: true, description: 'Relative repository path from https://download.eclipse.org/. E.g.: eclipse/updates/4.37-I-builds') + string(name: 'add', trim: true, description: 'Comma separated list of children to add. May be empty') + string(name: 'remove', trim: true, description: 'Comma separated list of children to remove. May be empty') + string(name: 'sizeLimit', trim: true, description: '''\ + The maximum number of childrem the modified composite should contain. + If the total number of children exceeds this limit (after adding new ones), a corresponding number of children is removed from the beginning of the list. + ''') + string(name: 'repositoryName', trim: true, description: 'Optional name attribute of the composite repository to set (if blank the name is not changed)') + } agent { label 'basic' } diff --git a/JenkinsJobs/Releng/prepareNextDevCycle.jenkinsfile b/JenkinsJobs/Releng/prepareNextDevCycle.jenkinsfile index 27bcc7fa942..27f748e43ab 100644 --- a/JenkinsJobs/Releng/prepareNextDevCycle.jenkinsfile +++ b/JenkinsJobs/Releng/prepareNextDevCycle.jenkinsfile @@ -1,3 +1,6 @@ +// Constants read by job creation +private static final _JOB_DISPLAY_NAME = 'Prepare Next Development Cycle' +private static final _JOB_DESCRIPTION = 'Perform all steps to prepare the next development cycle of Eclipse.' def releaseEvents = [ M1: 'Milestone 1', M2: 'Milestone 2', M3: 'Milestone 3', RC1: 'Release Candidate 1', RC2: 'Release Candidate 2', GA: 'Release' ] @@ -8,6 +11,21 @@ pipeline { buildDiscarder(logRotator(numToKeepStr:'5')) skipDefaultCheckout() } + parameters { + booleanParam(name: 'DRY_RUN', defaultValue: true, description: '''\ + If enabled, the final publication of all changes is skipped respectivly all changes at the download-server happen in a 'try-out' area at https://download.eclipse.org/eclipse/try-outs/. + This area is cleaned on each dry-run and should be cleaned after a try-out session is completed. + Useful for debugging and to very that the pipeline behaves as intended. + ''') + string(name: 'NEXT_RELEASE_VERSION', trim: true, description: 'Version of the release to prepare, for example: 4.37') + string(name: 'PREVIOUS_RELEASE_CANDIDATE_ID', trim: true, description: 'Id of the current release-candiate for the previous release. For example: S-4.36RC2-202505281830') + string(name: 'NEXT_SIMREL_NAME', trim: true, description: 'The name of the Simultanious Release that is targeted by the prepared release. Value is in the format yyyy-mm, for example: 2026-03') + string(name: 'NEXT_JAVA_RELEASE_DATE', trim: true, description: '''\ + Release date of the next Java version, if it is released shortly after the Eclipse release + (i.e. shortly after the GA_DATE specified above, usual for odd release versions), else left blank (usual for even releases). + Value is in the format yyyy-mm-dd, for example: 2025-09-16 + ''') + } agent { label 'ubuntu-2404' } @@ -21,8 +39,8 @@ pipeline { steps { script { echo "DRY_RUN: ${DRY_RUN}" - env.NEXT_RELEASE_VERSION = readParameter('NEXT_RELEASE_VERSION') - def nextVersionMatcher = env.NEXT_RELEASE_VERSION =~ /(?\d+)\.(?\d+)/ + echo "NEXT_RELEASE_VERSION: ${NEXT_RELEASE_VERSION}" + def nextVersionMatcher = "${NEXT_RELEASE_VERSION}" =~ /(?\d+)\.(?\d+)/ if (!nextVersionMatcher.matches()) { error "Unexpected format for NEXT_RELEASE_VERSION: ${NEXT_RELEASE_VERSION}" } @@ -30,13 +48,13 @@ pipeline { assignEnvVariable('NEXT_RELEASE_VERSION_MINOR', nextVersionMatcher.group('minor')) nextVersionMatcher = null // release matcher as it's not serializable - env.PREVIOUS_RELEASE_CANDIDATE_ID = readParameter('PREVIOUS_RELEASE_CANDIDATE_ID') + echo "PREVIOUS_RELEASE_CANDIDATE_ID: ${PREVIOUS_RELEASE_CANDIDATE_ID}" def buildPropertiesTxt = sh(script: "curl --fail https://download.eclipse.org/eclipse/downloads/drops4/${PREVIOUS_RELEASE_CANDIDATE_ID}/buildproperties.txt", returnStdout: true) def buildProperties = readProperties(text: buildPropertiesTxt) assignEnvVariable('IS_JAVA_RELEASE_IMMINENT', !buildProperties.NEXT_JAVA_RELEASE_DATE.replace('"','').isEmpty()) // Remove surrounding quotes def previousIdMatcher = null - if ((previousIdMatcher = env.PREVIOUS_RELEASE_CANDIDATE_ID =~ /(?[SR])-(?\d+)\.(?\d+)(\.(?\d+))?(?(M|RC)\d+[a-z]?)?-(?\d{8})(?