diff --git a/.github/workflows/README.MD b/.github/workflows/README.MD index caf011b4ce8..c57efe8aa28 100644 --- a/.github/workflows/README.MD +++ b/.github/workflows/README.MD @@ -6,10 +6,6 @@ This repository contains some workflows that can be shared across all platform r Check if there is currently a freeze period in place. -## updateRelease.yml - -Workflow that can be used to trigger an automatic update to the next release when a new milestone is created - ## checkMergeCommits.yml Check if a PR contains unwanted merge commits. diff --git a/.github/workflows/prepareRelease.yml b/.github/workflows/prepareRelease.yml deleted file mode 100644 index 2310a4a8bd4..00000000000 --- a/.github/workflows/prepareRelease.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Prepare Next Release -on: - milestone: - types: [created] - -permissions: - contents: read - -jobs: - prepare: - runs-on: ubuntu-latest - if: contains(github.event.milestone.description, 'Release') - permissions: - pull-requests: write - contents: write - steps: - - name: Set up Maven - uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 - with: - maven-version: 3.9.9 - - id: get-release-name - run: | - name=$(echo ${{ github.event.milestone.due_on }} | cut -d- -f-2) - year=$(echo $name|cut -d- -f 1) - month=$(echo $name|cut -d- -f 2) - echo "year=$year" >> $GITHUB_OUTPUT - echo "month=$month" >> $GITHUB_OUTPUT - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - ref: master - - name: Set up JDK - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 - with: - java-version: '21' - distribution: 'temurin' - cache: maven - - name: Update Main Versions - run: mvn -U -ntp -f eclipse-platform-parent org.eclipse.tycho:tycho-versions-plugin:set-version -DnewVersion=${{ github.event.milestone.title }}.0-SNAPSHOT -Dmodules=../eclipse.platform.releng.prereqs.sdk,../eclipse.platform.releng.tychoeclipsebuilder - - name: Update Release Versions - run: mvn -ntp -f eclipse-platform-parent/pom.xml --non-recursive org.eclipse.tycho:tycho-versions-plugin:set-property -Dproperties=releaseVersion,releaseYear,releaseMonth -DnewReleaseYear=${{ steps.get-release-name.outputs.year }} -DnewReleaseMonth=${{ steps.get-release-name.outputs.month }} -DnewReleaseVersion=${{ github.event.milestone.title }} - - name: Create Pull Request for Release ${{ github.event.milestone.title }} - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 - with: - commit-message: Prepare Release ${{ github.event.milestone.title }} - branch: prepare_R${{ github.event.milestone.title }} - title: Prepare Release ${{ github.event.milestone.title }} - body: A new Release Milstone was created, please review the changes and merge if appropriate. - delete-branch: true - milestone: ${{ github.event.milestone.number }} - add-paths: | - eclipse-platform-parent/pom.xml - eclipse.platform.releng.prereqs.sdk/pom.xml - eclipse.platform.releng.tychoeclipsebuilder/**/pom.xml - eclipse.platform.releng.tychoeclipsebuilder/**/*.product - diff --git a/.github/workflows/updateRelease.yml b/.github/workflows/updateRelease.yml deleted file mode 100644 index dfcefee6603..00000000000 --- a/.github/workflows/updateRelease.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Update For Next Release - -on: - workflow_call: -jobs: - update: - runs-on: ubuntu-latest - if: contains(github.event.milestone.description, 'Release') - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 0 - ref: master - - name: Set up Maven - uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 - with: - maven-version: 3.9.9 - - name: Set up JDK - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 - with: - java-version: '21' - distribution: 'temurin' - cache: maven - - name: Update Versions - run: >- - mvn -U -B -ntp - org.eclipse.tycho:tycho-versions-plugin:set-version -DnewVersion=${{ github.event.milestone.title }}.0-SNAPSHOT - org.eclipse.tycho:tycho-versions-plugin:set-parent-version -DnewParentVersion=${{ github.event.milestone.title }}.0-SNAPSHOT - - name: Create Pull Request for Release ${{ github.event.milestone.title }} - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 - with: - commit-message: Update for release ${{ github.event.milestone.title }} - branch: update_R${{ github.event.milestone.title }} - title: Update for release ${{ github.event.milestone.title }} - body: A new release milstone was created, please review the changes and merge if appropriate. - delete-branch: true - milestone: ${{ github.event.milestone.number }} - add-paths: | - pom.xml - **/pom.xml diff --git a/JenkinsJobs/Releng/FOLDER.groovy b/JenkinsJobs/Releng/FOLDER.groovy index 63310735db0..652686d90e0 100644 --- a/JenkinsJobs/Releng/FOLDER.groovy +++ b/JenkinsJobs/Releng/FOLDER.groovy @@ -59,4 +59,30 @@ Releases are published to scriptPath('JenkinsJobs/Releng/publishToMaven.jenkinsfile') } } -} \ No newline at end of file +} + +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. 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('M1_DATE', null, 'Milestone 1 end date in the format yyyy-mm-dd, for example: 2025-07-04') + stringParam('M2_DATE', null, 'Milestone 2 end date in the format yyyy-mm-dd, for example: 2025-07-25') + stringParam('M3_DATE', null, 'Milestone 3 end date in the format yyyy-mm-dd, for example: 2025-08-15') + stringParam('RC1_DATE', null, 'Release-Candidate 1 end date in the format yyyy-mm-dd, for example: 2025-08-22') + stringParam('RC2_DATE', null, 'Release-Candidate 2 end date in the format yyyy-mm-dd, for example: 2025-08-29') + stringParam('GA_DATE', null, 'Final general availability release date in the format yyyy-mm-dd, for example: 2025-09-10') + } + definition { + cpsScm { + lightweight(true) + scm { + github('eclipse-platform/eclipse.platform.releng.aggregator', 'master') + } + scriptPath('JenkinsJobs/Releng/prepareNextDevCycle.jenkinsfile') + } + } +} + diff --git a/JenkinsJobs/Releng/prepareNextDevCycle.jenkinsfile b/JenkinsJobs/Releng/prepareNextDevCycle.jenkinsfile new file mode 100644 index 00000000000..3d8f98a455f --- /dev/null +++ b/JenkinsJobs/Releng/prepareNextDevCycle.jenkinsfile @@ -0,0 +1,352 @@ + +pipeline { + options { + timestamps() + timeout(time: 60, unit: 'MINUTES') + buildDiscarder(logRotator(numToKeepStr:'5')) + skipDefaultCheckout() + } + agent { + label 'ubuntu-2404' + } + tools { + jdk 'temurin-jdk21-latest' + maven 'apache-maven-latest' + } + //Parameters are defined in the job definition + stages { + stage('Process Input') { + steps { + script { + def nextVersionMatcher = params.NEXT_RELEASE_VERSION =~ /(?\d+)\.(?\d+)/ + if (!nextVersionMatcher.matches()) { + error "Unexpected format for NEXT_RELEASE_VERSION: ${params.NEXT_RELEASE_VERSION}" + } + env.NEXT_RELEASE_VERSION_MAJOR = nextVersionMatcher.group('major') + env.NEXT_RELEASE_VERSION_MINOR = nextVersionMatcher.group('minor') + nextVersionMatcher = null // release matcher as it's not serializable + + def previousVersionMatcher = params.PREVIOUS_RELEASE_CANDIDATE_ID =~ /(S|R)-(?\d+)\.(?\d+)(?M1|M2|M3|RC1|RC2)?-(?\d{12})/ + if (!previousVersionMatcher.matches()) { + error "Unexpected format for PREVIOUS_RELEASE_CANDIDATE_ID: ${params.PREVIOUS_RELEASE_CANDIDATE_ID}" + } + env.PREVIOUS_RELEASE_VERSION_MAJOR = previousVersionMatcher.group('major') + env.PREVIOUS_RELEASE_VERSION_MINOR = previousVersionMatcher.group('minor') + env.PREVIOUS_RELEASE_VERSION = "${PREVIOUS_RELEASE_VERSION_MAJOR}.${PREVIOUS_RELEASE_VERSION_MINOR}" + env.PREVIOUS_RELEASE_CANDIDATE_TAG = "${PREVIOUS_RELEASE_VERSION}" + previousVersionMatcher.group('kind') + def previousReleaseTimestamp = previousVersionMatcher.group('timestamp') + env.PREVIOUS_RELEASE_CANDIDATE_I_BUILD = "I${previousReleaseTimestamp.substring(0,8)}-${previousReleaseTimestamp.substring(8,12)}" + previousVersionMatcher = null // release matcher as it's not serializable + + //TODO: Read the dates from the calender instead of provide a structured document somewhere? + // E.g. next to: https://github.com/eclipse-simrel/.github/blob/main/wiki/SimRel/2025-09.md + def m1Date = parseDate(params.M1_DATE) + def m2Date = parseDate(params.M2_DATE) + def m3Date = parseDate(params.M3_DATE) + def rc1Date = parseDate(params.RC1_DATE) + def rc2Date = parseDate(params.RC2_DATE) + def gaDate = parseDate(params.GA_DATE) + if (!(m1Date < m2Date && m2Date < m3Date && m3Date < rc1Date && rc1Date < rc2Date && rc1Date < gaDate)) { + error "Dates are not in strictly ascending order: ${params.M1_DATE}, ${params.M2_DATE}, ${params.M3_DATE}, ${params.RC1_DATE}, ${params.RC2_DATE}, ${params.GA_DATE}" + } + env.NEXT_RELEASE_YEAR = gaDate.year + env.NEXT_RELEASE_MONTH = String.format("%02d", gaDate.monthValue) + sh '''#!/bin/sh +x + echo 'Input parameters read successfully' + echo "DRY_RUN='$DRY_RUN'" + echo '' + echo "NEXT_RELEASE_VERSION='$NEXT_RELEASE_VERSION'" + echo "NEXT_RELEASE_VERSION_MAJOR='$NEXT_RELEASE_VERSION_MAJOR'" + echo "NEXT_RELEASE_VERSION_MINOR='$NEXT_RELEASE_VERSION_MINOR'" + echo '' + echo "PREVIOUS_RELEASE_CANDIDATE_ID='$PREVIOUS_RELEASE_CANDIDATE_ID'" + echo "PREVIOUS_RELEASE_VERSION='$PREVIOUS_RELEASE_VERSION'" + echo "PREVIOUS_RELEASE_VERSION_MAJOR='$PREVIOUS_RELEASE_VERSION_MAJOR'" + echo "PREVIOUS_RELEASE_VERSION_MINOR='$PREVIOUS_RELEASE_VERSION_MINOR'" + echo "PREVIOUS_RELEASE_CANDIDATE_TAG='$PREVIOUS_RELEASE_CANDIDATE_TAG'" + echo "PREVIOUS_RELEASE_CANDIDATE_I_BUILD='$PREVIOUS_RELEASE_CANDIDATE_I_BUILD'" + echo '' + echo "M1_DATE='$M1_DATE'" + echo "M2_DATE='$M2_DATE'" + echo "M3_DATE='$M3_DATE'" + echo "RC1_DATE='$RC1_DATE'" + echo "RC2_DATE='$RC2_DATE'" + echo "GA_DATE='$GA_DATE'" + echo "NEXT_RELEASE_YEAR='$NEXT_RELEASE_YEAR'" + echo "NEXT_RELEASE_MONTH='$NEXT_RELEASE_MONTH'" + ''' + } + } + } + stage('Checkout SCM') { + steps { + checkout scm + sh ''' + git submodule update --init --recursive + git config --global user.email 'eclipse-releng-bot@eclipse.org' + git config --global user.name 'Eclipse Releng Bot' + ''' + } + } + /*TODO: Test: + - If deploying the parent POM works + - If pushing works to aggr and submodules (e.g. pde) + - if creation of milestones works in aggr-repo and submodules (e.g. PDE) + - if PR createion works in aggr-repo and submodules (e.g. PDE) + */ + stage('Update Maven Version') { + environment { + MAVEN_ARGS = '-U -B -ntp' + } + steps { + sh ''' + mvn org.eclipse.tycho:tycho-versions-plugin:set-version \ + -DnewVersion=${NEXT_RELEASE_VERSION}.0-SNAPSHOT + mvn -f eclipse-platform-parent/pom.xml --non-recursive org.eclipse.tycho:tycho-versions-plugin:set-property \ + -Dproperties=releaseVersion,releaseYear,releaseMonth \ + -DnewReleaseVersion=${NEXT_RELEASE_VERSION} \ + -DnewReleaseYear=${NEXT_RELEASE_YEAR} \ + -DnewReleaseMonth=${NEXT_RELEASE_MONTH} + + git commit --all --message "Prepare Release ${NEXT_RELEASE_VERSION}" + git submodule foreach 'git commit --all --message "Update release version for ${NEXT_RELEASE_VERSION}" & echo done' + ''' + } + } + stage('Update build scripts') { + steps { + replaceInFile('cje-production/buildproperties.txt', [ + "RELEASE_VER=\"${PREVIOUS_RELEASE_VERSION}\"" : "RELEASE_VER=\"${NEXT_RELEASE_VERSION}\"", + "STREAM=\"${PREVIOUS_RELEASE_VERSION}.0\"" : "STREAM=\"${NEXT_RELEASE_VERSION}.0\"", + "STREAMMajor=\"${PREVIOUS_RELEASE_VERSION_MAJOR}\"" : "STREAMMajor=\"${NEXT_RELEASE_VERSION_MAJOR}\"", + "STREAMMinor=\"${PREVIOUS_RELEASE_VERSION_MINOR}\"" : "STREAMMinor=\"${NEXT_RELEASE_VERSION_MINOR}\"", + ]) + replaceInFile('eclipse.platform.releng.tychoeclipsebuilder/eclipse.platform.repository/platform.p2.inf', [ + "${PREVIOUS_RELEASE_VERSION} Release" : "${NEXT_RELEASE_VERSION} Release", + ]) + replaceInFile('eclipse.platform.releng.tychoeclipsebuilder/eclipse.platform.repository/sdk.p2.inf', [ + "${PREVIOUS_RELEASE_VERSION} Release" : "${NEXT_RELEASE_VERSION} Release", + ]) + replaceInFile('production/testScripts/configuration/streamSpecific.properties', [ + "for ${PREVIOUS_RELEASE_VERSION}.0 builds" : "for ${NEXT_RELEASE_VERSION}.0 builds", + ]) + replaceAllInFile('scripts/updateProductVersion.sh', [ + 's/\\d+.\\d+.0/\\d+.\\d+.0/g' : "g|s/${PREVIOUS_RELEASE_VERSION}.0/${NEXT_RELEASE_VERSION}.0/g", + ]) + + commitAllChangesExcludingSubmodules("Update versions to ${NEXT_RELEASE_VERSION} in build scripts") + } + } + stage('Move previous version to current RC') { + steps { + sh ''' + mvn -f eclipse-platform-parent/pom.xml --non-recursive org.eclipse.tycho:tycho-versions-plugin:set-property \ + -Dproperties=previous-release.baseline \ + "-DnewPrevious-release.baseline=https://download.eclipse.org/eclipse/updates/${PREVIOUS_RELEASE_VERSION}-I-builds/${PREVIOUS_RELEASE_CANDIDATE_I_BUILD}/" + ''' + replaceAllInFile('cje-production/buildproperties.txt', [ + 'PREVIOUS_RELEASE_VER=".*"' : "PREVIOUS_RELEASE_VER=\"${PREVIOUS_RELEASE_CANDIDATE_TAG}\"", + 'PREVIOUS_RELEASE_REPO_ID=".*"' : "PREVIOUS_RELEASE_REPO_ID=\"${PREVIOUS_RELEASE_VERSION}-I-builds\"", + 'BASEBUILD_ID=".*"' : "BASEBUILD_ID=\"${PREVIOUS_RELEASE_CANDIDATE_I_BUILD}\"", + 'PREVIOUS_RELEASE_ID=".*"' : "PREVIOUS_RELEASE_ID=\"${PREVIOUS_RELEASE_CANDIDATE_ID}\"", + ]) + replaceAllInFile('eclipse.platform.releng.tychoeclipsebuilder/eclipse-junit-tests/src/main/resources/equinoxp2tests.properties', [ + 'eclipse-platform-\\d+.\\d+-' : "eclipse-platform-${PREVIOUS_RELEASE_CANDIDATE_TAG}-", + 'org.eclipse.equinox.p2.tests.last.release.build.repo=.*' : "org.eclipse.equinox.p2.tests.last.release.build.repo=https://download.eclipse.org/equinox/drops/${PREVIOUS_RELEASE_CANDIDATE_ID}/", + ]) + replaceAllInFile('eclipse.platform.releng.tychoeclipsebuilder/eclipse-junit-tests/src/main/resources/label.properties', [ + 'previousReleaseVersion=.*' : "previousReleaseVersion=${PREVIOUS_RELEASE_CANDIDATE_TAG}", + ]) + replaceAllInFile('production/testScripts/configuration/streamSpecific.properties', [ + 'previousReleaseLocation=.*' : 'previousReleaseLocation=https://\\${DOWNLOAD_HOST}/eclipse/downloads/drops4/' + PREVIOUS_RELEASE_CANDIDATE_ID + '/', + 'previousReleaseVersion=.*' : "previousReleaseVersion=${PREVIOUS_RELEASE_CANDIDATE_TAG}", + 'previousReleaseVersionRepo=.*' : "previousReleaseVersionRepo=${PREVIOUS_RELEASE_VERSION}-I-builds", + ]) + commitAllChangesExcludingSubmodules("Move previous version to ${PREVIOUS_RELEASE_CANDIDATE_TAG} in build scripts") + } + } + stage('Deploy parent-pom and SDK-target') { + // Deploy new parent first to ensure it's available when PRs for submodule updates are created. + environment { + GOAL ="${ params.DRY_RUN ? 'install' : 'deploy' }" + } + steps { + sh ''' + mvn clean ${GOAL} -f eclipse-platform-parent/pom.xml + mvn clean ${GOAL} -f eclipse.platform.releng.prereqs.sdk/pom.xml + ''' + } + } + stage('Push preparation branches') { + steps { + sshagent (['github-bot-ssh']) { + sh ''' + function pushNewCommitsToPreparationBranch() { + pushURL=$(git config remote.origin.url) + # Switch to SSH, if the configured URL uses HTTPS (we can only push with SSH) + if [[ "$pushURL" == http* ]]; then + pushURL=$(echo $pushURL|sed --expression 's|https://github.com/|git@github.com:|') + fi + if [[ ${DRY_RUN} == 'true' ]]; then + dryRunFlag='--dry-run' + fi + git push ${dryRunFlag} ${pushURL} HEAD:refs/heads/prepare_R${NEXT_RELEASE_VERSION} + } + pushNewCommitsToPreparationBranch + export -f pushNewCommitsToPreparationBranch + git submodule foreach 'pushNewCommitsToPreparationBranch' + ''' + } + } + } + stage('Create preparation Pull-Requests') { + environment { + GITHUB_BOT_TOKEN = credentials('github-bot-token') + } + steps { + script { + def prHeadline = "Prepare ${NEXT_RELEASE_VERSION} development" + def prBranch = "prepare_R${NEXT_RELEASE_VERSION}" + def aggregatorPreparationPR = createPullRequest('eclipse-platform/eclipse.platform.releng.aggregator', prHeadline, """\ + Prepare development of Eclipse ${NEXT_RELEASE_VERSION}. + This includes: + - Updating the version of the Maven parent, all references to it and the Eclipse products to `${NEXT_RELEASE_VERSION}` + - Updating the release version to `${NEXT_RELEASE_VERSION}` across build scripts + - Updating the previous release version to the current Release-Candidate: `${PREVIOUS_RELEASE_CANDIDATE_ID}` + """.stripIndent(), prBranch) + + def submoduleURLs = sh(script: "git submodule foreach --quiet 'git config remote.origin.url'", returnStdout: true).trim().split('\\s') + for (submoduleURL in submoduleURLs) { + // Extract repository path from e.g.: https://github.com/eclipse-platform/eclipse.platform.git + def expectedPrefix = 'https://github.com/' + def expectedSuffix = '.git' + if (!submoduleURL.startsWith(expectedPrefix) || !submoduleURL.endsWith(expectedSuffix)) { + error "Unexpected of submodule URL: ${submoduleURL}" + } + def repoName = submoduleURL.substring(expectedPrefix.length(), submoduleURL.length() - expectedSuffix.length()) + createPullRequest(repoName, prHeadline, """\ + Prepare development of Eclipse ${NEXT_RELEASE_VERSION}. + This complements: + - ${aggregatorPreparationPR} + """.stripIndent(), prBranch) + } + } + } + } + stage('Create Github milestones') { + environment { + GITHUB_BOT_TOKEN = credentials('github-bot-token') + } + steps { + script { + def organisations = [ 'eclipse-platform', 'eclipse-jdt', 'eclipse-pde', 'eclipse-equinox' ] + for (organisation in organisations) { + def repositories = listReposOfOrganization(organisation) + echo "${organisation} repositories: ${repositories}" + for (repository in repositories) { + createMilestone(organisation, repository, "${NEXT_RELEASE_VERSION} M1", "${NEXT_RELEASE_VERSION} Milestone 1", "${M1_DATE}") + createMilestone(organisation, repository, "${NEXT_RELEASE_VERSION} M2", "${NEXT_RELEASE_VERSION} Milestone 2", "${M2_DATE}") + createMilestone(organisation, repository, "${NEXT_RELEASE_VERSION} M3", "${NEXT_RELEASE_VERSION} Milestone 3", "${M3_DATE}") + createMilestone(organisation, repository, "${NEXT_RELEASE_VERSION} RC1", "${NEXT_RELEASE_VERSION} Release Candidate 1", "${RC1_DATE}") + createMilestone(organisation, repository, "${NEXT_RELEASE_VERSION} RC2", "${NEXT_RELEASE_VERSION} Release Candidate 2", "${RC2_DATE}") + createMilestone(organisation, repository, "${NEXT_RELEASE_VERSION}", "${NEXT_RELEASE_VERSION} Release", "${GA_DATE}") + } + } + } + } + } + } +} + +@NonCPS +def parseDate(String dateString) { + return java.time.LocalDate.parse(dateString.trim()) // expects format 'yyyy-MM-dd' +} + +def replaceInFile(String filePath, Map replacements) { + replaceAllInFile(filePath, replacements.collectEntries{ k, v -> [java.util.regex.Pattern.quote(k), v] }); +} + +def replaceAllInFile(String filePath, Map replacements) { + def content = readFile(filePath) + for (entry in replacements) { + content = content.replaceAll(entry.key, entry.value) + } + writeFile(file:filePath, text: content) +} + +def commitAllChangesExcludingSubmodules(String commitMessage) { + withEnv(["COMMIT_MESSAGE=${commitMessage}"]) { + sh ''' + #Commit all changes, except for the updated sub-modules here + git add --all + git restore --staged $(git submodule foreach --quiet 'echo $sm_path') + git commit --message "${COMMIT_MESSAGE}" + ''' + } +} + +def listReposOfOrganization(String orga) { + def response = queryGithubAPI('', "orgs/${orga}/repos", null) + if (!(response instanceof List) && (response.errors || (response.status && response.status != 201))) { + error "Response contains errors:\n${response}" + } + return response.name +} + +/** + * Create a new milestone. + * @param msDueDay the milestone's due-date, format: YYYY-MM-DD + */ +def createMilestone(String orga, String repo, String msTitle, String msDescription, String msDueDay) { + echo "In ${orga}/${repo} create milestone: ${msTitle} due on ${msDueDay}" + def params = [title: msTitle, description: msDescription, due_on: "${msDueDay}T23:59:59Z"] + def response = queryGithubAPI('-X POST', "repos/${orga}/${repo}/milestones", params) + if (response?.errors || (response?.status && response.status != 201)) { + if (response.errors && response.errors[0]?.code == 'already_exists') { + echo 'Milestone already exists and is not modified' + // TODO: update milestone in this case: https://docs.github.com/en/rest/issues/milestones?apiVersion=2022-11-28#update-a-milestone + // Usefull if e.g. the dates are wrongly read from the calendar + } else { + error "Response contains errors:\n${response}" + } + } else { + echo 'Created successfully' + } +} + +/** + * Create a PR in the specified repo, from a branch that is expected to reside in the same repository. + */ +def createPullRequest(String orgaSlashRepo, String prTitle, String prBody, String headBranch, String baseBranch = 'master') { + echo "In ${orgaSlashRepo} create PR: '${prTitle}' on branch ${headBranch}" + def params = [title: prTitle, body: prBody, head: headBranch, base: baseBranch] + def response = queryGithubAPI('-X POST',"repos/${orgaSlashRepo}/pulls", params) + if (response?.errors || (response?.status && response.status != 201)) { + error "Response contains errors:\n${response}" + } + return response?.html_url +} + +def queryGithubAPI(String method, String endpoint, Map queryParameters) { + def query = """\ + curl -L ${method} \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer \${GITHUB_BOT_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/${endpoint} \ + """.stripIndent() + if (queryParameters != null) { + def params = writeJSON(json: queryParameters, returnText: true) + query += "-d '" + params + "'" + } + if (params.DRY_RUN && !method.isEmpty()) { + echo "Query (not send): ${query}" + return null + } + def response = sh(script: query, returnStdout: true) + if (response == null || response.isEmpty()) { + error 'Response is null or empty. This commonly indicates: HTTP/1.1 500 Internal Server Error' + } + return readJSON(text: response) +} diff --git a/Jenkinsfile b/Jenkinsfile index b4d9dffb25c..9d216714d9e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -21,7 +21,6 @@ pipeline { anyOf { branch 'master' branch 'R*_maintenance' - branch 'prepare_R*' } } steps { @@ -79,7 +78,6 @@ pipeline { } } stage('Build') { - when { not { branch pattern: "prepare_R.*", comparator: "REGEXP" } } steps { sh ''' mvn clean install -pl :eclipse-sdk-prereqs,:org.eclipse.jdt.core.compiler.batch -DlocalEcjVersion=99.99 -Dmaven.repo.local=$WORKSPACE/.m2/repository -U diff --git a/RELEASE.md b/RELEASE.md index a4ccd00001f..d4eeae86c23 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -191,10 +191,13 @@ The release is scheduled for 10AM EST. Typically the jobs are scheduled beforeha - Run the [Create New Stream Repos](https://ci.eclipse.org/releng/job/Releng/job/newStreamRepos/) job to make an I-builds repo for the next release. #### **Create Git Milestones for the next Release:** + +Milestones are already created by running [`Prepare Next Development Cycle`](https://ci.eclipse.org/releng/job/Releng/job/prepareNextDevCycle/) job. +Previously they were created in ther own job: - Milestones in git are created by running the create-milestones job in jenkins, usually after RC1 or RC2. Only specific users can access this job for security reasons. If milestones need to be created and have not please contact @sdawley @sravanlakkimsetti or @laeubi to run it. #### **Version Updates:** - - Once the milestones are created (see above) the [Prepare Next Release](https://github.com/eclipse-platform/eclipse.platform.releng.aggregator/actions/workflows/prepareRelease.yml) workflow will run, which will update pom and product versions for the Eclipse repositories and submit pull requests for the changes. + - Running the [`Prepare Next Development Cycle`](https://ci.eclipse.org/releng/job/Releng/job/prepareNextDevCycle/) job will update pom and product versions for the Eclipse repositories and submit pull requests for the changes. This is still a work in progress so if there are any issues or a repo gets missed you can fall back to the old process below: If you cloned eclipse.platform.releng.aggregator's submodules you can fix the set version and run [updateProductVersion.sh](scripts/updateProductVersion.sh) to update most of the versions. Once that's done it's easiest to just grep for the previous release version or stream number to find the remaining instances that need to be updated, then commit the changes in a new branch for each repo. diff --git a/scripts/newReleasePrep.sh b/scripts/newReleasePrep.sh index da01d1166fc..0f0461bd8e7 100755 --- a/scripts/newReleasePrep.sh +++ b/scripts/newReleasePrep.sh @@ -34,9 +34,7 @@ BODY="This preparation work involves the following tasks. For previous bug pleas - [ ] Configure SWT build scripts for ${NEXT_STREAM} - [ ] Splash Screen for ${NEXT_STREAM} (${NEXT_TRAIN}) - [ ] Create ${NEXT_STREAM}-I-builds repo -- [ ] POM and product version changes for ${NEXT_STREAM} release -- [ ] Update product version number to ${NEXT_STREAM} across build scripts -- [ ] Move previous version to ${PREV_MAJOR}.${PREV_MINOR}RC2 across build scripts +- [ ] Run [`Prepare Next Development Cycle`](https://ci.eclipse.org/releng/job/Releng/job/prepareNextDevCycle/) job and submit the created changes - [ ] Update version number in Mac's Eclipse.app for ${NEXT_STREAM} - [ ] Clean forceQualifierUpdate files for doc bundles - [ ] Update builds and repo cleanup scripts for ${NEXT_STREAM}