Repository navigation
Add pipeline script for create_release_notes and link to master instead of backport issue #229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
4d13e2b
Add groovy wrapper for generating release notes
smlambert 936ed5c
Add generate-release-notes Groovy pipeline wrapper
smlambert 1307340
fix #200
smlambert 5b31dd7
Assisted-by: IBM Bob v2.0.3
smlambert 8c54f31
Use backportedBy
smlambert 4282915
Keep backportOf for all objects
smlambert f73a8dc
Fix backportedBy value
smlambert 2a83f3e
Update as per review request
smlambert 0f15a07
Bump actions/setup-java from 5.7.0 to 6.0.0 (#230)
dependabot[bot] ca6e260
Bump js-yaml in /generate-release-notes/generate-release-notes (#231)
dependabot[bot] 91fa8dd
Fix Release Note Generation Rate Limiting (#234)
steelhead31 9dbcbe8
Bump actions/setup-java from 6.0.0 to 6.0.1 (#232)
dependabot[bot] b260ea9
fix #200
smlambert 865351c
Merge branch 'adoptium:master' into groovy
smlambert File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,256 @@ | ||
| #!groovy | ||
|
|
||
| // Created with the assistance of IBM Bob v2.0.3 | ||
| // Workaround to handle different versions of the Badge/Groovy Postbuild plugin. | ||
| def appendSummaryText(summary, text) { | ||
| try { | ||
| def currentText = summary.getText() ?: '' | ||
| summary.setText(currentText + text) | ||
| } catch (Exception e) { | ||
| echo "setText failed, trying deprecated appendText: ${e.message}" | ||
| summary.appendText(text, false) | ||
| } | ||
| } | ||
|
|
||
| // Returns true when the tag follows the pre-JEP-322 JDK 8 scheme (e.g. jdk8u502-ga, jdk8u492-b07). | ||
| def isJdk8Tag(String tag) { | ||
| return tag ==~ /^jdk8u.*/ | ||
| } | ||
|
|
||
| // Parses a JEP-322 tag (JDK 9+) and returns a map of its components. | ||
| // | ||
| // Supported formats: | ||
| // jdk-26-ga - Feature release (first introduction of a new JDK version) | ||
| // jdk-21.0.1+12 – CPU release (no PATCH) | ||
| // jdk-21.0.12.1+1 – CSPU release; jdk-21.0.12.1+1 and jdk-21.0.12.1-ga point to the same SHA | ||
| // jdk-21.0.12-ga – GA alias for a standard release (no PATCH, no BUILD) | ||
| // jdk-21.0.12.1-ga – GA alias for a patch release | ||
| // | ||
| // Returned map: | ||
| // feature – major version number (e.g. "21") | ||
| // version – full version string from the tag (e.g. "21.0.12.1" or "21.0.12") | ||
| // patch – PATCH segment, "0" when absent (e.g. "1" or "0") | ||
| // build – BUILD number after '+', "0" when absent (e.g. "1" or "0") | ||
| def parseJdkTag(String tag) { | ||
| // 1. Strip leading "jdk-" prefix | ||
| def withoutPrefix = tag.replaceFirst(/^jdk-/, '') | ||
|
|
||
| // 2. Strip optional qualifier (e.g. "-ga", "-ea"). A qualifier starts with '-' | ||
| // followed by a non-digit character and runs to the end of the string. | ||
| def withoutQualifier = withoutPrefix.replaceFirst(/-[a-zA-Z].*$/, '') | ||
|
|
||
| // 3. Split on '+' to separate version from optional build number | ||
| def parts = withoutQualifier.tokenize('+') | ||
| if (parts.size() < 1 || parts.size() > 2) { | ||
| error("JDK_TAG '${tag}' does not match an expected JEP-322 format (jdk-FEATURE.INTERIM.UPDATE[.PATCH][+BUILD][-QUALIFIER])") | ||
| } | ||
| def build = parts.size() == 2 ? parts[1] : '0' | ||
|
|
||
| // 4. Split version on '.' → [FEATURE, INTERIM, UPDATE] or [FEATURE, INTERIM, UPDATE, PATCH] | ||
| def versionParts = parts[0].tokenize('.') | ||
| if (versionParts.size() < 3) { | ||
| error("JDK_TAG '${tag}' version segment '${parts[0]}' must contain at least FEATURE.INTERIM.UPDATE") | ||
| } | ||
| def patch = versionParts.size() >= 4 ? versionParts[3] : '0' | ||
| // Preserve the full version string as it appears in the tag (3-part or 4-part) | ||
| def version = parts[0] | ||
|
|
||
| return [ | ||
| feature: versionParts[0], | ||
| version: version, | ||
| patch : patch, | ||
| build : build, | ||
| ] | ||
| } | ||
|
|
||
| pipeline { | ||
| agent { label 'worker' } | ||
| parameters { | ||
| string(name: 'JDK_TAG', defaultValue: '', description: 'Required. The JDK release tag, e.g. jdk-21.0.1+12 or jdk-21.0.12.1-ga. Needs to match the tag used for building and publishing binaries.') | ||
| string(name: 'BASE_JDK_TAG', defaultValue: '', description: 'Required. The base (previous) JDK tag to compare against, e.g. jdk-21.0.0+35 or jdk-21.0.12-ga') | ||
| string(name: 'GITHUB_REPOSITORY', defaultValue: '', description: 'Optional (JDK 9+, required for JDK 8). GitHub repository, e.g. adoptium/jdk21u or adoptium/jdk8u') | ||
| string(name: 'JDK_VERSION', defaultValue: '', description: 'Optional (JDK 9+, required for JDK 8). Version string for fetchReleaseNotes.js, e.g. 21.0.12.1 or openjdk8u462,8u501') | ||
| string(name: 'FILENAME', defaultValue: '', description: 'Optional (JDK 9+, required for JDK 8). Output filename, e.g. OpenJDK21-jdk-release-notes_21.0.12.1_1.json or OpenJDK8U-jdk-release-notes_8.0.502_07.json') | ||
| } | ||
| stages { | ||
| stage('Validate and Resolve Parameters') { | ||
| steps { | ||
| script { | ||
| if (!params.JDK_TAG) { | ||
| error('JDK_TAG parameter is required') | ||
| } | ||
| if (!params.BASE_JDK_TAG) { | ||
| error('BASE_JDK_TAG parameter is required') | ||
| } | ||
|
|
||
| if (isJdk8Tag(params.JDK_TAG)) { | ||
| // JDK 8 uses a pre-JEP-322 versioning scheme (e.g. jdk8u502-ga). | ||
| // The derived values for GITHUB_REPOSITORY, JDK_VERSION and FILENAME | ||
| // cannot be calculated reliably from the tag alone (the build number | ||
| // embedded in the filename requires a GitHub tag→SHA lookup), so all | ||
| // three must be provided explicitly. | ||
| if (!params.GITHUB_REPOSITORY) { | ||
| error('GITHUB_REPOSITORY is required for JDK 8 tags (e.g. adoptium/jdk8u)') | ||
| } | ||
| if (!params.JDK_VERSION) { | ||
| error('JDK_VERSION is required for JDK 8 tags (e.g. openjdk8u462,8u501)') | ||
| } | ||
| if (!params.FILENAME) { | ||
| error('FILENAME is required for JDK 8 tags (e.g. OpenJDK8U-jdk-release-notes_8.0.502_07.json)') | ||
| } | ||
| env.RESOLVED_GITHUB_REPOSITORY = params.GITHUB_REPOSITORY | ||
| env.RESOLVED_JDK_VERSION = params.JDK_VERSION | ||
| env.RESOLVED_FILENAME = params.FILENAME | ||
|
|
||
| echo "JDK_TAG: ${params.JDK_TAG} (JDK 8 — all parameters required)" | ||
| echo "BASE_JDK_TAG: ${params.BASE_JDK_TAG}" | ||
| echo "GITHUB_REPOSITORY: ${env.RESOLVED_GITHUB_REPOSITORY}" | ||
| echo "JDK_VERSION: ${env.RESOLVED_JDK_VERSION}" | ||
| echo "FILENAME: ${env.RESOLVED_FILENAME}" | ||
| } else { | ||
| def parsed = parseJdkTag(params.JDK_TAG) | ||
|
|
||
| // For +BUILD tags use build as the suffix. | ||
| // For -ga tags (build == '0') fall back to patch (e.g. jdk-21.0.12.1-ga → _1). | ||
| def filenameSuffix = (parsed.build != '0') ? parsed.build : parsed.patch | ||
|
|
||
| // Resolve optional parameters: use the supplied value when non-empty, | ||
| // otherwise derive from JDK_TAG. The ?: operator returns the left-hand | ||
| // side when it is truthy (non-null, non-empty), so an explicit param | ||
| // always wins over the calculated default. | ||
| env.RESOLVED_GITHUB_REPOSITORY = params.GITHUB_REPOSITORY ?: "adoptium/jdk${parsed.feature}u" | ||
| env.RESOLVED_JDK_VERSION = params.JDK_VERSION ?: parsed.version | ||
| env.RESOLVED_FILENAME = params.FILENAME ?: "OpenJDK${parsed.feature}-jdk-release-notes_${parsed.version}_${filenameSuffix}.json" | ||
|
|
||
| echo "JDK_TAG: ${params.JDK_TAG}" | ||
| echo "BASE_JDK_TAG: ${params.BASE_JDK_TAG}" | ||
| echo "GITHUB_REPOSITORY: ${env.RESOLVED_GITHUB_REPOSITORY}${params.GITHUB_REPOSITORY ? ' (provided)' : ' (derived)'}" | ||
| echo "JDK_VERSION: ${env.RESOLVED_JDK_VERSION}${params.JDK_VERSION ? ' (provided)' : ' (derived)'}" | ||
| echo "FILENAME: ${env.RESOLVED_FILENAME}${params.FILENAME ? ' (provided)' : ' (derived)'}" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| stage('Checkout') { | ||
| steps { | ||
| cleanWs() | ||
| checkout scm | ||
| } | ||
| } | ||
| stage('Install Dependencies') { | ||
| steps { | ||
| dir('generate-release-notes/generate-release-notes') { | ||
| nvm(version: 'v24.19.0', | ||
| nvmInstallURL: 'https://raw.githubusercontent.com/creationix/nvm/v0.40.7/install.sh', | ||
| nvmNodeJsOrgMirror: 'https://nodejs.org/dist', | ||
| nvmIoJsOrgMirror: 'https://iojs.org/dist', | ||
| nvmInstallDir: '$HOME/.nvm') { | ||
| sh 'node --version' | ||
| sh 'npm install' | ||
| } | ||
| } | ||
| } | ||
| } | ||
| stage('Fetch Commit List') { | ||
| steps { | ||
| dir('generate-release-notes/generate-release-notes') { | ||
| nvm(version: 'v24.19.0', | ||
| nvmInstallURL: 'https://raw.githubusercontent.com/creationix/nvm/v0.40.7/install.sh', | ||
| nvmNodeJsOrgMirror: 'https://nodejs.org/dist', | ||
| nvmIoJsOrgMirror: 'https://iojs.org/dist', | ||
| nvmInstallDir: '$HOME/.nvm') { | ||
| withEnv([ | ||
| "JDK_TAG=${params.JDK_TAG}", | ||
| "BASE_JDK_TAG=${params.BASE_JDK_TAG}", | ||
| "GITHUB_REPO=${env.RESOLVED_GITHUB_REPOSITORY}" | ||
| ]) { | ||
| sh ''' | ||
| echo "Generating release notes for $JDK_TAG" | ||
| node ./fetchCommitList.js \ | ||
| --repository "$GITHUB_REPO" \ | ||
| --baseTag "$BASE_JDK_TAG" \ | ||
| --tag "$JDK_TAG" \ | ||
| --filename "${JDK_TAG}-commits.json" | ||
| ''' | ||
| sh 'cat "${JDK_TAG}-commits.json"' | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| stage('Fetch Release Notes') { | ||
| steps { | ||
| dir('generate-release-notes/generate-release-notes') { | ||
| nvm(version: 'v24.19.0', | ||
| nvmInstallURL: 'https://raw.githubusercontent.com/creationix/nvm/v0.40.7/install.sh', | ||
| nvmNodeJsOrgMirror: 'https://nodejs.org/dist', | ||
| nvmIoJsOrgMirror: 'https://iojs.org/dist', | ||
| nvmInstallDir: '$HOME/.nvm') { | ||
| sh """ | ||
| node ./fetchReleaseNotes.js \ | ||
| --commitList ./${params.JDK_TAG}-commits.json \ | ||
| --filename ${env.RESOLVED_FILENAME} \ | ||
| --version ${env.RESOLVED_JDK_VERSION} | ||
| """ | ||
| } | ||
| } | ||
| } | ||
| } | ||
| stage('Archive Artifacts') { | ||
| steps { | ||
| dir('generate-release-notes/generate-release-notes') { | ||
| archiveArtifacts artifacts: "${params.JDK_TAG}-commits.json, ${env.RESOLVED_FILENAME}", | ||
| fingerprint: true | ||
| } | ||
| } | ||
| } | ||
| } | ||
| post { | ||
| failure { | ||
| echo "Release notes generation failed for ${params.JDK_TAG}" | ||
| } | ||
| success { | ||
| script { | ||
| echo "Release notes successfully generated: ${env.RESOLVED_FILENAME}" | ||
|
|
||
| // Build a pre-populated link to the release-tool publish job so the operator | ||
| // can publish the generated JSON with a single click. | ||
| // Mirrors the parambuild pattern used in ci-jenkins-pipelines/build_base_file.groovy. | ||
| def publishJobPath = 'build-scripts/release/refactor_openjdk_release_tool' | ||
| def releaseToolUrl = "${env.JENKINS_URL}job/${publishJobPath.replace('/', '/job/')}/parambuild?" | ||
|
|
||
| // Derive the JDK major version for the VERSION parameter (e.g. "jdk21"). | ||
| def versionParam | ||
| if (isJdk8Tag(params.JDK_TAG)) { | ||
| versionParam = 'jdk8' | ||
| } else { | ||
| def parsed = parseJdkTag(params.JDK_TAG) | ||
| versionParam = "jdk${parsed.feature}" | ||
| } | ||
|
|
||
| def encodedJobName = URLEncoder.encode(env.JOB_NAME, 'UTF-8') | ||
| def encodedArtifacts = URLEncoder.encode("**/${env.RESOLVED_FILENAME}", 'UTF-8') | ||
| def encodedTag = URLEncoder.encode(params.JDK_TAG, 'UTF-8') | ||
|
|
||
| releaseToolUrl += "VERSION=${versionParam}" | ||
| releaseToolUrl += "&TAG=${encodedTag}" | ||
| releaseToolUrl += "&UPSTREAM_JOB_NAME=${encodedJobName}" | ||
| releaseToolUrl += "&UPSTREAM_JOB_NUMBER=${currentBuild.number}" | ||
| releaseToolUrl += "&ARTIFACTS_TO_COPY=${encodedArtifacts}" | ||
| releaseToolUrl += "&RELEASE=true" | ||
| releaseToolUrl += "&DRY_RUN=false" | ||
|
|
||
| echo "Publish release notes — click to trigger: ${releaseToolUrl}" | ||
|
|
||
| // Add a clickable summary badge to the Jenkins build page, matching the | ||
| // pattern used in ci-jenkins-pipelines/build_base_file.groovy. | ||
| def summary = manager.createSummary('document.svg') | ||
| appendSummaryText(summary, "<b>Release notes generated: ${env.RESOLVED_FILENAME}</b><br/>") | ||
| appendSummaryText(summary, "<a href='${releaseToolUrl}'>Publish release notes for ${params.JDK_TAG}</a>") | ||
| } | ||
| } | ||
| cleanup { | ||
| cleanWs() | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment for function says
jdk-26-gais a supported format. However versionParts is size 1 (just 26) and this would error out on that input.Maybe a special case is needed for versionParts size 1?