diff --git a/linux/jdk/debian/src/main/packaging/temurin/21/debian/control b/linux/jdk/debian/src/main/packaging/temurin/21/debian/control index d7b4f4f82..eef45d010 100644 --- a/linux/jdk/debian/src/main/packaging/temurin/21/debian/control +++ b/linux/jdk/debian/src/main/packaging/temurin/21/debian/control @@ -32,7 +32,10 @@ Provides: java-compiler, java16-sdk, java17-sdk, java18-sdk, + java19-sdk, java2-sdk, + java20-sdk, + java21-sdk, java5-sdk, java6-sdk, java7-sdk, diff --git a/linux/jdk/debian/src/main/packaging/temurin/22/debian/control b/linux/jdk/debian/src/main/packaging/temurin/22/debian/control index 8f402b115..b627a83ec 100644 --- a/linux/jdk/debian/src/main/packaging/temurin/22/debian/control +++ b/linux/jdk/debian/src/main/packaging/temurin/22/debian/control @@ -32,7 +32,11 @@ Provides: java-compiler, java16-sdk, java17-sdk, java18-sdk, + java19-sdk, java2-sdk, + java20-sdk, + java21-sdk, + java22-sdk, java5-sdk, java6-sdk, java7-sdk, diff --git a/linux/jdk/debian/src/main/packaging/temurin/23/debian/control b/linux/jdk/debian/src/main/packaging/temurin/23/debian/control index 369b24f61..90b5a3a9d 100644 --- a/linux/jdk/debian/src/main/packaging/temurin/23/debian/control +++ b/linux/jdk/debian/src/main/packaging/temurin/23/debian/control @@ -32,7 +32,12 @@ Provides: java-compiler, java16-sdk, java17-sdk, java18-sdk, + java19-sdk, java2-sdk, + java20-sdk, + java21-sdk, + java22-sdk, + java23-sdk, java5-sdk, java6-sdk, java7-sdk, diff --git a/linux_new/Jenkinsfile b/linux_new/Jenkinsfile new file mode 100644 index 000000000..2629bd342 --- /dev/null +++ b/linux_new/Jenkinsfile @@ -0,0 +1,887 @@ +/* Used By Jenkins Job create_installer_linux */ +/* https://ci.adoptium.net/job/build-scripts/job/release/job/create_installer_linux/ */ + +/* Constant Declarations */ + +def NODE_LABEL = 'build&&linux&&x64&&dockerBuild&&dynamicAzure' // Default node +def PRODUCT = 'temurin' +def JVM = 'hotspot' + +// Artifactory Global Variables +def baseURL = "https://github.com/adoptium/" +def ArchiveFileName = "" + +// Github Artifact Repos +def binaryRepo = "${params.VERSION.replace('jdk', 'temurin')}-binaries/releases/tag/${params.TAG}" +def binaryDLRepo = "${params.VERSION.replace('jdk', 'temurin')}-binaries/releases/download/${params.TAG}" +def fullURL = "${baseURL}/${binaryRepo}" +def dlURL = "${baseURL}/${binaryDLRepo}" + +/* Supported Distro Arrays */ +// Remember If Adding An Deb Distro to update the cacerts package // +def deb_distros = [ +"trixie", // Debian/13 +"bookworm", // Debian/12 +"bullseye", // Debian/11 +"buster", // Debian/10 +"oracular", // Ubuntu/24.10 (STS) +"noble", // Ubuntu/24.04 (LTS) +"jammy", // Ubuntu/22.04 (LTS) +"focal", // Ubuntu/20.04 (LTS) +"bionic" // Ubuntu/18.04 (LTS) +] + +def rhel_distros = [ + 'rpm/centos/7', + 'rpm/rocky/8', + 'rpm/rhel/7', + 'rpm/rhel/8', + 'rpm/rhel/9', + 'rpm/fedora/35', + 'rpm/fedora/36', + 'rpm/fedora/37', + 'rpm/fedora/38', + 'rpm/fedora/39', + 'rpm/fedora/40', + 'rpm/fedora/41', + 'rpm/fedora/42', + 'rpm/fedora/rawhide', + 'rpm/oraclelinux/7', + 'rpm/oraclelinux/8', + 'rpm/amazonlinux/2' + ] + +def suse_distros = [ + 'rpm/opensuse/15.3', + 'rpm/opensuse/15.4', + 'rpm/opensuse/15.5', + 'rpm/sles/12', + 'rpm/sles/15' + ] +/* End Of Distro Definitions*/ + +// Global Variables +def DLfilenames = [] +def JDKArray = [] +def ModifiedJDKArray = [] +def DISTS_TO_BUILD = [] +def distro = "" +def distro_list = '' +def arch = "" +def ReleaseVersion = "" +def Release = "" +def Version = "" +def Build = "" +def packagearch = "" +def AlpArch = "" +def packagearchDeb = "" +def packagearchRhel = "" +def PackageReleaseVersion = "0" +def upstreamversion = "" +def upstreamversionARM32 = "" +def RHELkey = "" +def SUSEkey = "" +def TemurinVersion = "${params.TEMURIN_VERSION_INCREMENT}" + +/* Have Some Default Node Labels */ +/* Specified Here To Simplify Updates Later */ + +def PKGBUILDLABELAPK = 'build&&linux&&x64&&dockerBuild&&dynamicAzure' +def PKGBUILDLABELDEB = 'build&&linux&&x64&&dockerBuild&&dynamicAzure' +def PKGBUILDLABELRHEL = 'build&&linux&&x64&&dockerBuild&&dynamicAzure' + +// Function Definitions Begin + +// Helper function to download and validate files +def downloadArtifact(url) { + echo "Downloading: ${url}" + def result = sh(script: "curl -sSL -O ${url}", returnStatus: true) + if (result != 0) { + error("Failed to download ${url}. File not found or an error occurred. Download result := ${result}") + } + echo "Downloaded: ${url}" +} + +// Helper function to validate checksum +def validateChecksum(file, checksumFile) { + def expectedChecksum = sh(script: "awk '{print \$1}' ${checksumFile}", returnStdout: true).trim() + def calculatedChecksum = sh(script: "sha256sum ${file} | awk '{print \$1}'", returnStdout: true).trim() + if (expectedChecksum != calculatedChecksum) { + error("Checksum mismatch for ${file}. Expected: ${expectedChecksum}, but found: ${calculatedChecksum}.") + } + echo "Checksum validation successful for ${file}." + return calculatedChecksum +} + +// Helper function to extract upstream version from tar file +def extractUpstreamVersionFromTar(file) { + // def version = sh(script: "tar xvfz \"${file}\" | head -n 1 | cut -d/ -f1", returnStdout: true).trim() + def version = sh(script: "tar tvfz \"${file}\" | head -n 1 | awk '{print \$NF}' | cut -d/ -f1", returnStdout: true).trim() + sh "rm -rf \"${version}\"" + echo "Extracted upstream version: ${version}" + return version +} + +// Helper function to cleanup files +def cleanupFiles(files) { + files.each { file -> + sh "rm -rf ${file}" +} +} + +// Helper function to Set Node Labels +def getPackageBuildLabel(String arch, String distro) { + switch (distro) { + case 'APK': + if (arch == 'x64') { + return 'build&&linux&&x64&&dockerBuild&&dynamicAzure' + } else if (arch == 'aarch64') { + // return 'docker&&linux&&aarch64&&alpineInstaller' + return 'build&&docker&&linux&&aarch64' + } else { + error("Unsupported architecture '${arch}' for distro 'APK'") + } + case 'DEB': + return (arch == 'x64') ? 'build&&linux&&x64&&dockerBuild&&dynamicAzure' : + (arch == 'arm') ? 'docker&&linux&&aarch64' : + (arch == 'aarch64') ? 'docker&&linux&&aarch64' : + (arch == 'ppc64le') ? 'build&&docker&&ppc64le' : + (arch == 's390x') ? 'docker&&s390x&&dockerBuild' : + (arch == 'riscv64') ? 'dockerBuild&&linux&&riscv64&&dockerInstaller' : + error("Unsupported architecture '${arch}' for distro 'DEB'") + case 'RHEL': + return 'build&&linux&&x64&&dockerBuild&&dynamicAzure' + default: + error("Unsupported distro: ${distro}") + } +} + +// Helper function to check and upload files +def CheckAndUpload(String Target, String Distro, String BuildArch, String RelVersion, String DistroList, String Value, String PackageDir, String Key, String FileName) { + echo "Entering : CheckAndUpload()" + // Define A Context Appropriate Release Number + def RelNumber = params.VERSION.replaceAll(/[^\d]/, '') + + env.TARGET = Target + env.DISTRO = Distro + env.BUILDARCH = BuildArch + env.VERSION = RelVersion + env.RELNUM = RelNumber + env.DISTROLIST = DistroList + env.VALUE = Value + env.PACKAGEDIR = PackageDir + env.KEY = Key + env.FILENAME = FileName + def artBaseURL = "https://adoptium.jfrog.io/artifactory/" + + try { + switch(Distro) { // Distro Values ( Alpine / RPMS / Debian ) + case "Debian": + echo "Uploading Debian Target : ${Target} For Filename {$Filename}" + def ResponseCode = sh(script: "curl -o /dev/null --silent --head --write-out '%{http_code}' ${artBaseURL}${Target}/${Key}", returnStdout: true).trim() + echo "File Existence Check Result = = ${ResponseCode}" + if ( ResponseCode == '200') { + echo "Target Exists - Skipping" + break + } else { + echo "Target Doesnt Exist - Upload Files" + // This Upload Works + jf 'rt u ${FILENAME} deb/pool/main/t/temurin-${RELNUM}/ --target-props=${DISTROLIST}deb.component=main;deb.architecture=${BUILDARCH} --flat=true' + break + } + case "Alpine": + echo "Uploading Debian Target : ${Target} For Filename {$Filename}" + def ResponseCode = sh(script: "curl -o /dev/null --silent --head --write-out '%{http_code}' ${artBaseURL}${Target}/${FileName}", returnStdout: true).trim() + echo "File Existence Check Result = = ${ResponseCode}" + if ( ResponseCode == '200') { + echo "Target Exists - Skipping" + break + } else { + // This Upload Works + jf 'rt u **/build/ospackage/${FILENAME} apk/alpine/main/${BUILDARCH}/ --flat=true' + break + } + case "RPMS": + echo "Uploading RPM Target : ${Target} For Filename {$Filename}" + def ResponseCode = sh(script: "curl -o /dev/null --silent --head --write-out '%{http_code}' ${artBaseURL}${Target}/${DistroList}/${Value}", returnStdout: true).trim() + echo "File Existence Check Result = = ${ResponseCode}" + if ( ResponseCode == '200') { + echo "Target Exists - Skipping" + break + } else { + jf 'rt u ${FILENAME} ${PACKAGEDIR}/ --flat=true' + break + } + default: + echo "Default Case" + echo "I've reached an unsupported Distro This Shouldnt Occur - Have Some Debugging" + echo "Target = ${Target}/${FileName}" + echo "Distro = ${Distro}" + echo "Arch = ${BuildArch}" + echo "Version = ${Version}" + echo "DistroList = ${DistroList}" + echo "Value = ${Value}" + echo "PackageDir = ${PackageDir}" + echo "Key = ${Key}" + echo "Filename = ${FileName}" + break + } + } catch (Exception e) { + error "Error While Checking URL ${Target}: ${e.message}" + } +} +// Function Definitions End + +/* Pipeline Declaration */ +pipeline { + agent none // No Default Agent + options { + timeout(time: 2, unit: 'HOURS') + } + + parameters { + string(name: 'TAG', defaultValue: 'jdk-23+37', description: 'Release Tag') + string(name: 'VERSION', defaultValue: 'jdk23', description: 'Release Version') + string(name: 'ARTIFACTS_TO_COPY', defaultValue: '**/alpine-linux/aarch64/temurin/*.tar.gz,**/alpine-linux/aarch64/temurin/*.zip,**/alpine-linux/aarch64/temurin/*.sha256.txt,**/alpine-linux/aarch64/temurin/*.msi,**/alpine-linux/aarch64/temurin/*.pkg,**/alpine-linux/aarch64/temurin/*.json,**/alpine-linux/aarch64/temurin/*.sig', description: 'Artifacts String') + booleanParam(name: 'RELEASE', defaultValue: false, description: 'Release Flag' ) + booleanParam(name: 'DRY_RUN', defaultValue: false, description: 'Release Dry Run') + booleanParam(name: 'ENABLEGPGSIGNING', defaultValue: true, description: 'Require GPG Signing') + booleanParam(name: 'ENABLEDEBUG', defaultValue: false, description: 'Tick to enable --stacktrace for gradle build') + booleanParam(name: 'REPACKAGE', defaultValue: false, description: 'Tick if this is a republish of an existing package, ie xx.xxx.2 , rather than the base release of a package (1)') + string(name: 'PACKAGE_INCREMENT', defaultValue: '1', description: 'This is the incremental number used for re-releases of package versions - Should be set appropriately if RePackage is True') + string(name: 'TEMURIN_VERSION_INCREMENT', defaultValue: '0', description: 'Final Element Of The Version Number - Used For Temurin Specific Patches - NEARLY ALWAYS ZERO') + } + // Stage Definition - Start + stages { + // Print Parameters Stage - Start + stage('Print Parameters') { + agent { label NODE_LABEL } + steps { + script { + echo "Entering Stage : Print Parameters" + echo "Tag : ${params.TAG}" + echo "Version : ${params.VERSION}" + echo "Artifacts : ${params.ARTIFACTS_TO_COPY}" + echo "Release : ${params.RELEASE}" + echo "Dry Run : ${params.DRY_RUN}" + + if (params.DRY_RUN) { + echo "This Is A Dry Run - And As No Packages Are Potentially On Github - No Further Stages Will Run" + } else { + echo "Not A Dry Run - About To Build And Publish Packages" + } + } + } + } + // Print Parameters Stage - End + // Process Parameters Stage - Start + stage('Process Parameters') { + agent { label NODE_LABEL } + when { + expression { return params.DRY_RUN == false } + } + steps { + script{ + echo "Entering Stage : Process Parameters" + // Figure Out Which Dist This Run Is For + if (params.ARTIFACTS_TO_COPY.contains('alpine-linux')) { + distro = "alpine-linux" + } else if (params.ARTIFACTS_TO_COPY.contains('linux')) { + distro = "linux" + } else { + printlin "WARNING: The Artifacts Are For Neither Linux OR Alpine" + currentBuild.result = 'UNSTABLE' // Also Consider NOT_BUILT + error("Pipeline Skipped Due To Triggered For Neither Alpine Or Linux") + } + + // Valid architectures + def validArchs = ['aarch64', 'x64', 's390x', 'arm', 'ppc64le', 'riscv64'] + + // Extract architectures from the parameter + def specifiedPaths = params.ARTIFACTS_TO_COPY.tokenize(',') // Split by commas + def extractedArchs = specifiedPaths.collect { path -> + validArchs.find { validArch -> path.contains("/${validArch}/") }}.unique() // Get unique architectures + + // Validate architectures + if (extractedArchs.size() == 1) { + def check_arch = extractedArchs[0] + println "Valid architecture identified: ${check_arch}" + arch = extractedArchs[0] + } else if (extractedArchs.isEmpty()) { + println "WARNING: No valid architecture found in the specified paths: ${params.ARTIFACTS_TO_COPY}" + error("No valid architecture found in the specified paths.") + } else { + println "WARNING: Multiple architectures found: ${extractedArchs}" + error("The Artifacts contain multiple architectures: ${extractedArchs}") + } + + // Derive Node To Build Packages On + + PKGBUILDLABELAPK = getPackageBuildLabel(arch, 'APK') + PKGBUILDLABELDEB = getPackageBuildLabel(arch, 'DEB') + PKGBUILDLABELRHEL = getPackageBuildLabel(arch, 'RHEL') + + // Map Architectures From Source To Dist Suitable Values + + packagearchDeb = (arch == 'x64') ? 'amd64' : + (arch == 'arm') ? 'armhf' : + (arch == 'aarch64') ? 'arm64' : + (arch == 'ppc64le') ? 'ppc64el' : + (arch == 's390x') ? 's390x' : + (arch == 'riscv64') ? 'riscv64' : + 'unknown' + + packagearchRhel = (arch == 'x64') ? 'x86_64' : + (arch == 'arm') ? 'armv7hl' : + (arch == 'aarch64') ? 'aarch64' : + (arch == 'ppc64le') ? 'ppc64le' : + (arch == 's390x') ? 's390x' : + (arch == 'riscv64') ? 'riscv64' : + 'unknown' + + // Version Number Parsing + + def vername = '' + def verversion = '' + def verbuild = '' + + // Add Special Handling For JDK8 Version Number + // jdk8u432-b06 + + if (params.TAG?.startsWith("jdk8")) { + echo "JDK 8" + def split = (params.TAG =~ /(jdk)(\d+u\d+)-(b\d+)/) + if (split.find()) { + // println("Full Match: ${split[0][0]}") + vername = split[0][1] // "jdk" + verversion = split[0][2] // "8u432" + verbuild = split[0][3] // "06" + } else { + error("The version string format does not match the expected pattern.") + } + } else { + echo "Not JDK8" + // Parse the version tag into usable components. + def split = (params.TAG =~ /(jdk)-(\d[\d.]*)([+_]\d+)?/) + if (split.find()) { + vername = split.group(1) + verversion = split.group(2) + verbuild = split.group(3)?.replaceAll("[+_]", "") + } else { + error("The version string format does not match the expected pattern.") + } + } + + // Construct the Filename + def filennameFinal ="" + def filenamePrefix = "Open" + def filenameSuffix = "tar.gz" + def filenameVersion = params.VERSION.toUpperCase() + "U" + def packageTypes = ['jdk', 'jre'] + + packageTypes.each { packageType -> + if (params.TAG?.startsWith("jdk8")) { + filenameFinal = "${filenamePrefix}${filenameVersion}-${packageType}_${arch}_${distro}_${JVM}_${verversion}${verbuild ?: 'N/A'}" + ReleaseVersion = "${verversion}${verbuild ?: 'N/A'}" + } else { + filenameFinal = "${filenamePrefix}${filenameVersion}-${packageType}_${arch}_${distro}_${JVM}_${verversion}_${verbuild ?: 'N/A'}" + ReleaseVersion = "${verversion}_${verbuild ?: 'N/A'}" + } + + def JDKFinal = "${filenameFinal}.${filenameSuffix}" + def SHAFinal = "${JDKFinal}.sha256.txt" + + DLfilenames << JDKFinal + DLfilenames << SHAFinal + + JDKArray << [ "${packageType}" , "${JDKFinal}", "${SHAFinal}" , "${distro}" , "${arch}" , "${ReleaseVersion}" ] + } + + // Set Package Release Version If Repackage + if (params.REPACKAGE) { + PackageReleaseVersion = params.PACKAGE_INCREMENT + } + } + } + } + // Process Parameters Stage - End + // Validate Artifacts Stage - Start + stage('Validate Artifacts') { + agent { label NODE_LABEL } + when { + expression { return params.DRY_RUN == false } + } + steps { + script { + echo "Entering Stage : Validate Artifacts" + + JDKArray.each { ArrayElement -> + def (PTYPE, PFILE, PSIGN, PDIST, PARCH, PVERS) = ArrayElement + def Binurl = "${dlURL}/${PFILE}" + def SHAurl = "${dlURL}/${PSIGN}" + + // Download binary and checksum + downloadArtifact(Binurl) + downloadArtifact(SHAurl) + + // Validate checksum + def calculatedChecksum = validateChecksum(PFILE, PSIGN) + + // Special Case : Arm 32 has a different tag format as its built from a seperate repo + // It does require a different tag for the specfiles, which can be extracted from the tarball. + if (PARCH == "arm") { + upstreamversionARM32 = extractUpstreamVersionFromTar(PFILE) + } + + // Cleanup temporary files + cleanupFiles([PFILE, PSIGN]) + + // Update array with the validated information + ModifiedJDKArray << [PTYPE, PFILE, PSIGN, PDIST, PARCH, PVERS, calculatedChecksum, Binurl] + } + + JDKArray = ModifiedJDKArray + } + } +} +// Generate Spec File Stage - Start +stage('Generate Spec File') { + agent { label NODE_LABEL } + when { + expression { return params.DRY_RUN == false } + } + steps { + script { + echo "Entering Stage : Generate Spec File" + JDKArray.each { ArrayElement -> + // echo "${ArrayElement}" + // Assign Tuple Values To Vars + def PTYPE = ArrayElement[0] + def PFILE = ArrayElement[1] + def PSIGN = ArrayElement[2] + def PDIST = ArrayElement[3] + def PARCH = ArrayElement[4] + def PVERS = ArrayElement[5] + def PCSUM = ArrayElement[6] + def PKURL = ArrayElement[7] + + // Generate Date For Use In Various Places + def getDate = new Date(currentBuild.startTimeInMillis) + // Format The Date + def currentDate = getDate.format("EEE, dd MMM yyyy HH:mm:ss Z", TimeZone.getTimeZone('UTC')) + def currentDateRHEL = getDate.format("EEE MMM d yyyy", TimeZone.getTimeZone('UTC')) + echo "Current Date: ${currentDate}" + echo "Current Date RHEL: ${currentDateRHEL}" + + // Setup List Of Packages To Build + if (PDIST == 'alpine-linux') { + DISTS_TO_BUILD = ['alpine'] + } else if (PDIST == 'linux') { + DISTS_TO_BUILD = ['rhel', 'suse', 'debian'] + } else { + error("Unsupported dist: ${PDIST}") + } + DISTS_TO_BUILD.each { DistArrayElement -> + + if (params.TAG?.startsWith("jdk8")) { + def versionPattern = /(\d+)(u\d+)(b\d+)/ + def versparser = (PVERS =~ versionPattern) + // println("Full Match: ${versparser[0][0]}") + if (versparser.matches()) { + // println("Full Match: ${versparser[0][0]}") + Release = versparser[0][1] + Version = versparser[0][2] + Build = versparser[0][3] + } else { + error("The version string format does not match the expected pattern.") + } + } else { + def versionPattern = /^(\d+)(?:\.(.*))?_(.+)$/ + def versparser = (PVERS =~ versionPattern) + if (versparser.matches()) { + Release = versparser[0][1].toInteger() + Version = versparser[0][2] ? versparser[0][2] : "null" + Build = versparser[0][3] + } else { + error("Version string format is invalid: ${PVERS}") + } + } + + def TemplateType = ArrayElement[0] + def packagever + packagearch = PARCH + def templatebase + def outputfile + def changelogversion + + // Reformat Any Variables For Distribution Specific Oddities + + if (DistArrayElement == 'alpine') { + + if (Version == "null") { + packagever = "${Release}_p${Build}" + } else { + packagever = "${Release}.${Version}_p${Build}" + } + + // Upstream Version Is Not Required For Alpine + upstreamversion = "" + + if (Release == "8" ) { + // Regular expression to split around 'u' and 'b' + def versionPattern = /(\d+)(u)(\d+)(b)(\d+)/ + def versparser = (PVERS =~ versionPattern) + if (versparser.matches()) { + Release = versparser[0][1] // Capture before 'u', e.g., "8" + Version = versparser[0][3] // Capture between 'u' and 'b', e.g., "432" + Build = versparser[0][5] // Capture after 'b', e.g., "06" + } else { + error("The version string format does not match the expected pattern.") + } + packagever = "${Release}.${Version}.${Build}" + } + // Reformat x64 For Alpine + if (PARCH == 'x64') { + packagearch = "x86_64" + } + outputfile = "APKBUILD" + + // Figure Out Template name + templatebase = "./linux_new/${PTYPE}/${DistArrayElement}/src/main/packaging/${PRODUCT}/${Release}/${DistArrayElement}.${PTYPE}${Release}.template.j2" + + // Check If Template Exists + if (!fileExists(templatebase)) { + error("Template File Not Found At : ${templatebase}") + } + + def speccmd = "python3 linux_new/generate_spec.py \"${templatebase}\" \"${packagever}\" \"${packagearch}\" \"${PKURL}\" \"${PCSUM}\" \"${PFILE}\" \"${outputfile}\" \"${currentDate}\" \"${PackageReleaseVersion}\" \"${upstreamversion}\" \"${packagever}\" \"${upstreamversion}\"" + echo "Spec Command : ${speccmd}" + def genresult = sh(script: speccmd, returnStatus: true) + echo "Result : ${genresult}" + } + + if (DistArrayElement == 'debian') { + + echo "Processing Debian Files" + + // Debian Requires 3 Files To Be Generated + def debianFiles = ['changelog', 'control', 'rules'] + + if (Release == "8" ) { + // Extract components from original format + def major = PVERS[0] // Extract major version '8' + def versparser = (PVERS =~ /(\d+)u(\d+)b(\d+)/) + def minor = versparser[0][2] // Extract '432' + def build = versparser[0][3].replaceAll(/^0+/, '') // Extract '6' + // Construct the new format + packagever = "${major}.0.${minor}.0.${TemurinVersion}+${build}" + } else { + if (Version == "null") { + packagever = "${Release}.0.0.0.${TemurinVersion}+${Build}" + } else { + def debverparts = Version.tokenize('.') + if (debverparts.size() == 2) { + Version = "${debverparts[0]}.${debverparts[1]}.${TemurinVersion}" + } + packagever = "${Release}.${Version}.${TemurinVersion}+${Build}" + } + } + + debianFiles.each { debianFilesArrayElement -> + + echo "Processing Debian ${debianFilesArrayElement} File" + outputfile = debianFilesArrayElement + + // Figure Out Template name + templatebase = "./linux_new/${PTYPE}/${DistArrayElement}/src/main/packaging/${PRODUCT}/${Release}/${DistArrayElement}/${debianFilesArrayElement}.template.j2" + + // Check If Template Exists + if (!fileExists(templatebase)) { + error("Template File Not Found At : ${templatebase}") + } + + def speccmd = "python3 linux_new/generate_spec.py \"${templatebase}\" \"${packagever}\" \"${packagearchDeb}\" \"${PKURL}\" \"${PCSUM}\" \"${PFILE}\" \"${outputfile}\" \"${currentDate}\" \"${PackageReleaseVersion}\" \"${upstreamversion}\" \"${packagever}\" \"${upstreamversion}\"" + // echo "Spec Command : ${speccmd}" + def genresult = sh(script: speccmd, returnStatus: true) + // echo "Result : ${genresult}" + } + } + + if (DistArrayElement == "rhel" || DistArrayElement == "suse") { + + def verparts = Version.tokenize('.') + if (verparts.size() == 2) { + Version = "${verparts[0]}.${verparts[1]}.${TemurinVersion}" + echo "Formatted Version: ${Version}" + } + + if (Release == "8" ) { + upstreamversion = params.TAG.replaceFirst("^jdk", "") + // Extract components from original format + def major = PVERS[0] // Extract major version '8' + def versparser = (PVERS =~ /(\d+)u(\d+)b(\d+)/) + def minor = versparser[0][2] // Extract '432' + def build = versparser[0][3].replaceAll(/^0+/, '') // Extract '6' + def formattedBuild = build.toString()padLeft(2, '0') + // Construct the new format + packagever = "${major}.0.${minor}.0.${TemurinVersion}.${build}" + changelogversion = "${major}.0.${minor}-b${formattedBuild}" + } else { + upstreamversion = params.TAG.replaceFirst("^jdk-", "") + + if (Version == "null") { + packagever = "${Release}.0.0.0.${TemurinVersion}.${Build}" + changelogversion = "${Release}.0.${TemurinVersion}+${Build}" + } else { + packagever = "${Release}.${Version}.${TemurinVersion}.${Build}" + changelogversion = "${Release}.${Version}.${TemurinVersion}+${Build}" + } + } + + if (PARCH == 'arm') { + // If JDK8 ARM32, Then Need To Deduce Correct Upstream + upstreamversionARM32 = upstreamversionARM32.replaceFirst("^jdk", "").replaceAll(/-(jre|jdk)$/, "") + // DONE + } + + // Figure Out Template name + templatebase = "./linux_new/${PTYPE}/${DistArrayElement}/src/main/packaging/${PRODUCT}/${Release}/${PRODUCT}-${Release}-${PTYPE}.template.j2" + // Output File Name Only ( defaults to outputting in same location as template ) + outputfile = "${PRODUCT}-${Release}-${PTYPE}.spec" + + // Check If Template Exists + if (!fileExists(templatebase)) { + error("Template File Not Found At : ${templatebase}") + } + + def speccmd = "python3 linux_new/generate_spec.py \"${templatebase}\" \"${packagever}\" \"${packagearchRhel}\" \"${PKURL}\" \"${PCSUM}\" \"${PFILE}\" \"${outputfile}\" \"${currentDateRHEL}\" \"${PackageReleaseVersion}\" \"${upstreamversion}\" \"${changelogversion}\" \"${upstreamversionARM32}\"" + def genresult = sh(script: speccmd, returnStatus: true) + // End Of RHEL SUSE CODE + } + } +} + +// Archive & store the generated files, for future reference + +ArchiveFileName = "Package_Bld_Src_${distro}_${params.TAG}_${arch}_${env.BUILD_NUMBER}.tar.gz" +echo "ArchiveFileName = ${ArchiveFileName}" +sh "find ./linux_new -type f \\( -name '*.spec' -o -name 'control' -o -name 'changelog' -o -name 'rules' -o -name 'APKBUILD' \\) | tar -czf ./${ArchiveFileName} -T -" + +// Publish the tarball +archiveArtifacts artifacts: "${ArchiveFileName}", allowEmptyArchive: false + +// Stash the generated build files for use throughout the rest of the process +dir('linux_new') { + stash name: 'installercode', includes: '**' + } + } + } +} +// Generate Spec File Stage - End +// Build And Archive Packages Stage - Start +stage('Build & Archive Package') { + when { + expression { return params.DRY_RUN == false } + } + steps { + script { + echo "Entering Stage : Build & Archive Package" + DISTS_TO_BUILD.each { DistArrayElement -> + def nodeLabel = '' + if (DistArrayElement == 'alpine') { + nodeLabel = PKGBUILDLABELAPK + } else if (DistArrayElement == 'debian') { + nodeLabel = PKGBUILDLABELDEB + } else if (DistArrayElement in ['rhel', 'suse']) { + nodeLabel = PKGBUILDLABELRHEL + } else { + error "Unknown DistArrayElement: ${DistArrayElement}" + } + + node(label: nodeLabel) { // Assign node dynamically based on distribution type + + // Docker --mount option requires BuildKit + env.DOCKER_BUILDKIT = 1 + env.COMPOSE_DOCKER_CLI_BUILD = 1 + + // Prepare Workspace + cleanWs() + unstash 'installercode' + + try { + def PackagesToBuild = ['jdk', 'jre'] + def buildCli + PackagesToBuild.each { PackageArrayElement -> + echo "Building Package: ${PackageArrayElement} for ${DistArrayElement}" + def gBuildTask = (packagearch in ['x86_64', 'amd64']) ? + "package${PackageArrayElement}${DistArrayElement} check${PackageArrayElement}${DistArrayElement}" : + "package${PackageArrayElement}${DistArrayElement}" + + // Override Package Arch To Be Dist Specific + + if (DistArrayElement == "rhel" || DistArrayElement == "suse") { + buildCli = "./gradlew ${gBuildTask} --parallel -PPRODUCT=${PRODUCT} -PPRODUCT_VERSION=${Release} -PARCH=${packagearchRhel}" + } else if (DistArrayElement == "debian") { + buildCli = "./gradlew ${gBuildTask} --parallel -PPRODUCT=${PRODUCT} -PPRODUCT_VERSION=${Release} -PARCH=${packagearchDeb}" + } else { + buildCli = "./gradlew ${gBuildTask} --parallel -PPRODUCT=${PRODUCT} -PPRODUCT_VERSION=${Release} -PARCH=${packagearch}" + } + + if (params.ENABLEGPGSIGNING) { + def privateKey = 'adoptium-artifactory-rsa-key' + withCredentials([file(credentialsId: privateKey, variable: 'GPG_KEY')]) { + buildCli += " -PGPG_KEY_PATH=${GPG_KEY}" + } + } + + buildCli = params.ENABLEDEBUG.toBoolean() ? buildCli + ' --stacktrace' : buildCli + // echo "Build CLI : ${buildCli}" + sh("$buildCli") + } + } catch (Exception ex) { + echo "Exception in build for ${DistArrayElement}: ${ex}" + currentBuild.result = 'FAILURE' + } finally { + archiveArtifacts artifacts: '**/build/ospackage/*,**/build/reports/**,**/packageTest/dependencies/deb/*', + onlyIfSuccessful: false, allowEmptyArchive: false + } + } + } + } + } + } +// Build And Archive Packages Stage - End +// Publish Packages Stage - Start +stage('Publish Packages') { + agent { label NODE_LABEL } + tools { + jfrog 'jfrog-cli' + } + when { + expression { return params.DRY_RUN == false } + } + steps { + script { + echo "Entering Stage : Publish Packages" + copyArtifacts projectName: "${env.JOB_NAME}", + selector: specific("${env.BUILD_NUMBER}"), + filter: '**/build/ospackage/*,**/build/reports/**,**/packageTest/dependencies/deb/*' + + echo "Done Retrieving Files" + + // Distro Specific Uploads + if (distro == 'alpine-linux') { + echo "ALPINE UPLOAD" + AlpArch = arch + if (arch == 'x64') { + echo "Fixing Arch For Alpine" + AlpArch = "x86_64" + } + def AlpDistro = "Alpine" + def PackFiles = findFiles(glob: '**/build/ospackage/temurin-*j*.apk') // List All Packages To Upload + def SrcFiles = findFiles(glob: '**/build/ospackage/temurin-*src*.apk') // List All Sources To Upload + def AllFiles = PackFiles + SrcFiles + for (AlpPackFile in AllFiles) { + def AlpFileName = AlpPackFile.name + def AlpFilePath = AlpPackFile.path + def Target = "apk/alpine/main/${AlpArch}" + CheckAndUpload(Target, AlpDistro, AlpArch, '', '', '', '', '' , AlpFileName) + } + } + if (distro == 'linux') { + echo "Linux Upload" + echo "Preparing For Debian Upload" + def DebFileName = '' + def DebTarget = '' + // Creates list like deb.distribution=stretch;deb.distribution=buster; + deb_distros.each { deb_version -> + distro_list += "deb.distribution=${deb_version};" + } + def DebDistro = "Debian" + def DebPackFiles = findFiles(glob: "**/build/ospackage/temurin-*.deb") // List All Packages To Upload + for (DebPackFile in DebPackFiles) { + DebFileName = DebPackFile.name + def DebFilePath = DebPackFile.path + DebTarget = "deb/pool/main/t/temurin-${Release}" + def DebArchEx = (DebFileName =~ /_(\w+)\.deb$/) + def DebArch = DebArchEx[0][1] + CheckAndUpload(DebTarget, DebDistro, DebArch,, '', distro_list, '', '', DebFileName, DebPackFile.path) + } + echo "Preapring For RHEL Upload" + def RHELFileName = '' + def RHELFilePath = '' + def RHELTarget = '' + def RHELarchitecture = '' + def RHELDistro = "RPMS" + def RHELPackFiles = findFiles(glob: "**/rhel/build/ospackage/t*.rpm") // List All Packages To Upload For Temurin + for (RHELPackFile in RHELPackFiles) { + RHELFileName = RHELPackFile.name + RHELFilePath = RHELPackFile.path + // We Need To Extract The Architecture From The Built Filename + def RHELarchex = RHELFileName =~ /(?:\d+\.\d+-\d+)\.(\w+)\.(?:src\.)?rpm/ + RHELarchitecture = RHELarchex ? RHELarchex[0][1] : null + // OverRide Architecture For SRC RPMS + if (RHELFileName.contains(".src.rpm")) { + RHELarchitecture = "source" + } + + rhel_distros.each { rhel_distro -> + RHELkey = "${rhel_distro}/${RHELarchitecture}" + RHELTarget = "${RHELkey}/Packages" + CheckAndUpload(RHELTarget, RHELDistro, RHELarchitecture, '', '', RHELFileName, RHELTarget, RHELkey, RHELFilePath) + } + } + echo "Preapring For SUSE Upload" + def SUSEFileName = '' + def SUSEFilePath = '' + def SUSETarget = '' + def SUSEarchitecture = '' + def SUSEDistro = "RPMS" + def SUSEPackFiles = findFiles(glob: "**/suse/build/ospackage/t*.rpm") // List All Packages To Upload For Temurin + for (SUSEPackFile in SUSEPackFiles) { + SUSEFileName = SUSEPackFile.name + SUSEFilePath = SUSEPackFile.path + // We Need To Extract The Architecture From The Built Filename + def SUSEarchex = SUSEFileName =~ /(?:\d+\.\d+-\d+)\.(\w+)\.(?:src\.)?rpm/ + SUSEarchitecture = SUSEarchex ? SUSEarchex[0][1] : null + // OverRide Architecture For SRC RPMS + if (SUSEFileName.contains(".src.rpm")) { + SUSEarchitecture = "source" + // echo "Overriden Architecture : ${SUSEarchitecture}" + } + // Calculate Key + suse_distros.each { suse_distro -> + SUSEkey = "${suse_distro}/${SUSEarchitecture}" + SUSETarget = "${SUSEkey}/Packages" + CheckAndUpload(SUSETarget, SUSEDistro, SUSEarchitecture, '', '', SUSEFileName, SUSETarget, SUSEkey, SUSEFilePath) + } + } + } // End Of Linux Distro + } +// End OF Script + } +// Publish Packages Stage - End + } +// Stage Definition - End +} +post { + success { + script { + if (!params.DRY_RUN) { + echo 'Build succeeded. Triggering downstream job...' + echo "Release : ${params.TAG}" + echo "FileName : ${ArchiveFileName}" + + build job: 'publish_linux_pkg_src', parameters: [ + string(name: 'TAG', value: "${params.TAG}"), + string(name: 'FILENAME', value: "${ArchiveFileName}") + ] + } else { + echo 'Dry Run is enabled. Skipping downstream job trigger.' + } + } + } +} +// End Of Post Build Trigger Stage +} +// Pipeline Definition - End \ No newline at end of file diff --git a/linux_new/LICENSE.txt b/linux_new/LICENSE.txt new file mode 100644 index 000000000..ff7737963 --- /dev/null +++ b/linux_new/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/linux_new/NOTES.txt b/linux_new/NOTES.txt new file mode 100644 index 000000000..7e3332adc --- /dev/null +++ b/linux_new/NOTES.txt @@ -0,0 +1,160 @@ +x64 +=== + +Job adoptium-ca-certificates/Debian: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean :ca-certificates:package --parallel + +Job Temurin JDK 11/Debian: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkDebian checkJdkDebian --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=11 + +Job Temurin JDK 11/RedHat: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=11 + +Job Temurin JDK 11/SUSE: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkSuse checkJdkSuse --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=11 + +Job Dragonwell JDK 11/Debian: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkDebian checkJdkDebian --parallel -PPRODUCT=dragonwell -PPRODUCT_VERSION=11 + +Job Dragonwell JDK 11/RedHat: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT=dragonwell -PPRODUCT_VERSION=11 + +Job Dragonwell JDK 11/SUSE: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkSuse checkJdkSuse --parallel -PPRODUCT=dragonwell -PPRODUCT_VERSION=11 + +Job Temurin JDK 16/Debian: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkDebian checkJdkDebian --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=16 + +Job Temurin JDK 16/RedHat: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=16 + +Job Temurin JDK 16/SUSE: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkSuse checkJdkSuse --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=16 + +Job Temurin JDK 17/Debian: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkDebian checkJdkDebian --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=17 + +Job Temurin JDK 17/RedHat: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=17 + +Job Temurin JDK 17/SUSE: + +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkSuse checkJdkSuse --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=17 + +aarch64 +======= + +Job Temurin JDK 11/Debian: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkDebian checkJdkDebian --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=11 + +Job Temurin JDK 11/RedHat: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=11 + +Job Temurin JDK 11/SUSE: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkSuse checkJdkSuse --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=11 + +Job Dragonwell JDK 11/Debian: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkDebian checkJdkDebian --parallel -PPRODUCT=dragonwell -PPRODUCT_VERSION=11 + +Job Dragonwell JDK 11/RedHat: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT=dragonwell -PPRODUCT_VERSION=11 + +Job Dragonwell JDK 11/SUSE: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkSuse checkJdkSuse --parallel -PPRODUCT=dragonwell -PPRODUCT_VERSION=11 + +Job Temurin JDK 16/Debian: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkDebian checkJdkDebian --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=16 + +Job Temurin JDK 16/RedHat: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=16 + +Job Temurin JDK 16/SUSE: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkSuse checkJdkSuse --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=16 + +Job Temurin JDK 17/Debian: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkDebian checkJdkDebian --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=17 + +Job Temurin JDK 17/RedHat: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=17 + +Job Temurin JDK 17/SUSE: + +export _JAVA_OPTIONS="-Xmx4g" +export TESTCONTAINERS_RYUK_DISABLED=true +export TESTCONTAINERS_CHECKS_DISABLE=true +./gradlew clean packageJdkSuse checkJdkSuse --parallel -PPRODUCT=temurin -PPRODUCT_VERSION=17 + +Notes: + +* For regular testing `./gradlew clean package checkPackage -PPRODUCT=temurin -PPRODUCT_VERSION=11` and `./gradlew clean package checkPackage -PPRODUCT=temurin -PPRODUCT_VERSION=16` do all we need. Each command can replace 3 of the jobs listed above. +* Collect */*/build/ospackage/* (that's we have to upload somewhere later), and ideally */*/build/reports/** (test reports to investigate if something goes wrong). +* Expect dozens of additional jobs (additional platforms like arm32, s390x), JREs (not all versions), additional JDKs like Dragonwell (not all versions or platforms), more products (JMC, jtreg, ...). diff --git a/linux_new/README.md b/linux_new/README.md new file mode 100644 index 000000000..1797e31ff --- /dev/null +++ b/linux_new/README.md @@ -0,0 +1,245 @@ +# Linux Packages of Eclipse Adoptium + +We package for Debian, Red Hat, SUSE (e.g. DEB and RPM based) Linux distributions. + +The current implementation to build the packages involves using Gradle to call a small Java program. +That Java program spins up a Docker container, installing the base O/S and its packaging tools, +and then looping over configuration to create the various packages and signing them as appropriate +with the (Eclipse Foundation as a default) signing service. + +TODO You can then optionally upload those packages to a package repository of your choice. +The default Adoptium package repository is https://packages.adoptium.net/ui/packages. The packages are built and uploaded by Jenkins pipeline job defined by [Jenkinsfile](https://github.com/adoptium/installer/blob/master/linux/Jenkinsfile) + +## Prerequisites + +To run this locally + +* You will need to have Docker 20.10+ installed and running. +* You will need to have Java 8+ installed. +* You will need to have a minimum of 8GB of RAM on your system (the build required 4GB). + +## Building the Packages + +Builds take at least ~5-15 minutes to complete on a modern machine. Please ensure that you have Docker installed and running. + +You'll want to make sure you've set the exact versions of the binaries you want package in the: + +* **Alpine Based** - _{jdk,jre}/alpine/src/main/packaging/\\/\\/AKKBUILD_ files. +* **Debian Based** - _{jdk,jre,ca-certificates}/debian/src/main/packaging/\\/\\/debian/rules_ files. +* **Red Hat Based** - _{jdk,jre}/redhat/src/main/packaging/\/\/\/\-\-jdk.spec_ files. +* **SUSE Based** - _{jdk,jre}/suse/src/main/packaging/\/\/\/\-\-jdk.spec_ files. + +In all the examples below you'll need to replace the following variables: + +* Replace `` with `8|11|17|19` +* Replace `` with `temurin|dragonwell` +* Replace `` with `Alpine|Debian|RedHat|Suse` +* Replace `` with `Jdk|Jre` (or `CaCertificates` for the `Debian` platform) + +**Notes:** +* Not all combinations are possible, i.e., for some vendors we might only provide certain versions, or types. +* For `Debian` we provide a separate package with _Certification Authority_ certificates. + +### Build all packages for a version + +```shell +export DOCKER_BUILDKIT=1 +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean package checkPackage -PPRODUCT= -PPRODUCT_VERSION= +``` + +The scripts roughly work as follows: + +* **Gradle Kickoff** - The various `package` tasks in subdirectories under the _jdk_ (or _jre_) directory all have a dependency on the `packageJDK` (`packageJRE`) task, +which in turn has a dependency on the `package` task (this is how Gradle knows to trigger each of those in turn). +* **package<platform> Tasks** - These tasks are responsible for building the various packages for the given platform. They fire up the Docker container +(A _Dockerfile_ is included in each subdirectory), mount some file locations (so you can get to the output) and then run packaging commands in that container. +* **check<platform> Tasks** - Test containers are used to install the package and run the tests in +_src/packageTest/java/packaging_ on them. + +- [task package](build.gradle) --> [task package\](/build.gradle) --> [task package\\](/\/build.gradle ) +- [task checkPackage](build.gradle) --> [task check\Package](/build.gradle) --> [task check\\](/\/build.gradle ) + +### Build a Debian specific package for a version + +- replace `` with `8|11|17|19` +- replace `` with `temurin|dragonwell` +- Replace `` with `Jdk|Jre` + +```shell +export DOCKER_BUILDKIT=1 +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageDebian checkDebian --parallel -PPRODUCT= -PPRODUCT_VERSION= +``` + +### Build a Red Hat specific package for a version + +- replace `` with `8|11|17|19` +- replace `` with `temurin|dragonwell` + +```shell +export DOCKER_BUILDKIT=1 +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT= -PPRODUCT_VERSION= +``` + +### Build a SUSE specific package for a version + +- replace `` with `8|11|17|19` +- replace `` with `temurin|dragonwell` + +```shell +export DOCKER_BUILDKIT=1 +export _JAVA_OPTIONS="-Xmx4g" +./gradlew clean packageJdkSuse checkJdkSuse --parallel -PPRODUCT= -PPRODUCT_VERSION= +``` + +## GPG Signing RPMs/APKs + +In order to GPG sign the generated RPMs/APKs you must add the following argument to the gradlew command: +- replace `` with `Alpine|RedHat|Suse` +- replace `` with `8|11|17|19` +- replace `` with `temurin|dragonwell` + +```shell +./gradlew packageJdk --parallel -PPRODUCT= -PPRODUCT_VERSION= -PGPG_KEY= +``` + +## Building from local files + +In order to build a jdk/jre package for RPM or DEB from local `tar.gz` file(s), put both the `tar.gz` and the `sha256.txt` files in an empty input directory. If the vendor supports building locally, then one can specify this directory when running `./gradlew clean` using the `-PINPUT_DIR` flag + +Example: +```shell +./gradlew clean packageJdkRedHat checkJdkRedHat --parallel -PPRODUCT= -PPRODUCT_VERSION= -PARCH= -PINPUT_DIR= +``` + +**NOTE if building an RPM**: +Make sure to update global variables `upstream_version` and `spec_version` in the corresponding spec-file to match the version number of the jdk/jre RPM that you are building. (This is how RPM determines the version number of the resulting package) + +**Note if building an DEB**: +Make sure to update the `changelog` file in the corresponding vendor's debian folder so the most recent entry is about the version number of the jdk/jre DEB that you are building. (This is how DEB determines the version number of the resulting package) + +## Building SRPMs and RPMs Directly + +If you do not require testing or advanced build support, it is perfectly fine to eschew the Gradle-based build and to +directly build SRPMs and RPMs using the spec files in the repository. + +In this example, we are using the existing spec files for the Temurin 11 JDK to create an SRPM and then rebuild that +SRPM into a binary RPM. It supports building it for the current target architecture or for a different one than the host +system by specifying `vers_arch`. + +Prerequisites: `rpm-build` and `rpmdevtools` packages are installed. For example: + +``` +$ rpm -q rpmdevtools rpm-build +rpmdevtools-9.3-3.fc33.noarch +rpm-build-4.16.1.3-1.fc33.x86_64 +``` + +### Produce a Source/Binary RPM for x86_64 + +Consider this RPM build where x86_64 is the build hosts' architecture. +Download the release blobs and associated sources. +Suppose build rpm for jdk11 for target architecture `x86_64` + +```shell +cd linux/jdk/redhat/src/main/packaging/temurin/11 +mkdir temurin_x86_64 +pushd temurin_x86_64 +spec=$(pwd)/temurin-11-jdk.spec +spectool --gf ${spec} +sha256sum -c *.sha256.txt +``` + +Create a SRPM: + +```shell +rpmbuild --define "_sourcedir $(pwd)" --define "_specdir $(pwd)" \ + --define "_builddir $(pwd)" --define "_srcrpmdir $(pwd)" \ + --define "_rpmdir $(pwd)" --nodeps -bs ${spec} +``` + +Build the binary from the SRPM: + +```shell +rpmbuild --define "_sourcedir $(pwd)" --define "_specdir $(pwd)" \ + --define "_builddir $(pwd)" --define "_srcrpmdir $(pwd)" \ + --define "_rpmdir $(pwd)" --rebuild *.src.rpm +``` + +### Building for a different architecture + +In order to produce RPMs on an x86_64 build host for the s390x target architecture, use the `--target` switch to `rpm-build` to build for a different +architecture. Suppose the host architecture is `x86_64` and we want to build for target architecture `s390x`: + +```shell +rpmbuild --define "_sourcedir $(pwd)" --define "_specdir $(pwd)" \ + --define "_builddir $(pwd)" --define "_srcrpmdir $(pwd)" \ + --define "_rpmdir $(pwd)" --target s390x --rebuild *.src.rpm +``` + +## Supported packages + +### APK (Alpine) +- Supported JDK version 8,11,17,19 +- Supported JRE version 8,11,17,19 + +Supported platform amd64 + +| Distro | Test enabled platforms | Note | +|--------------|:----------------------:|:----:| +| alpine/3.x.x | x86_64 | | + +### DEB +- Supported JDK version 8,11,17,19 +- Supported JRE version 8,11,17,19 + +Supported platform amd64, arm64, armhf, ppc64le, s390x (s390x is only available for jdk > 8) + +| Distro | Test enabled platforms | Note | +|------------------------------|:----------------------:|:----:| +| debian/13 (trixie/testing) | x86_64 | | +| debian/12 (bookworm/testing) | x86_64 | | +| debian/11 (bullseye/stable) | x86_64 | | +| debian/10 (buster/oldstable) | x86_64 | | +| ubuntu/24.10 (oracular) | x86_64 | | +| ubuntu/24.04 (noble) | x86_64 | | +| ubuntu/22.04 (jammy) | x86_64 | | +| ubuntu/20.04 (focal) | x86_64 | | +| ubuntu/18.04 (bionic) | x86_64 | | + +- Debian Releases: https://www.debian.org/releases/index.en.html +- Ubuntu Releases: https://ubuntu.com/about/release-cycle + +### RPM (RedHat and Suse) +- Supported JDK version 8,11,17,19 +- Supported JRE version 8,11,17,19 + +Supported platform x86_64, aarch64, armv7hl, ppc64le, s390x (s390x is only available for jdk > 8) +SRPM also available. + +| Distro | Test enabled platforms | Note | +|---------------|:----------------------:|:-------------------------------------------:| +| amazonlinux/2 | x86_64 | | +| centos/7 | x86_64 | | +| rpm/fedora/35 | x86_64 | | +| rpm/fedora/36 | x86_64 | | +| rpm/fedora/37 | x86_64 | | +| rpm/fedora/38 | x86_64 | | +| rpm/fedora/39 | x86_64 | | +| oraclelinux/7 | x86_64 | | +| oraclelinux/8 | x86_64 | | +| opensuse/15.3 | x86_64 | | +| opensuse/15.4 | x86_64 | | +| opensuse/15.5 | x86_64 | | +| rocky/8 | x86_64 | | +| rpm/rhel/7 | x86_64 | | +| rpm/rhel/8 | x86_64 | | +| rpm/rhel/9 | x86_64 | | +| sles/12 | Null | Need subscription to even run zypper update | +| sles/15 | x86_64 | | + +## Install the packages + +See [Eclipse Temurin Linux (RPM/DEB) installer packages](https://adoptium.net/installation/linux/) diff --git a/linux_new/azure-pipelines.yml b/linux_new/azure-pipelines.yml new file mode 100644 index 000000000..0926f1349 --- /dev/null +++ b/linux_new/azure-pipelines.yml @@ -0,0 +1,71 @@ +trigger: + branches: + include: + - "*" + tags: + include: + - "v*" # Only consider tags like v1.0.0. + +pr: + branches: + include: + - "*" + +schedules: + - cron: "2 4 * * Tue" # Every Tuesday on 04:02 UTC + displayName: "Weekly Build" + branches: + include: + - main + +pool: + vmImage: "ubuntu-latest" + +variables: + isTag: $[startsWith(variables['Build.SourceBranch'], 'refs/tags/')] + +steps: + - task: CmdLine@2 + displayName: 'Lint Bash scripts' + inputs: + script: | + shellcheck *.sh + shellcheck packaging/debian/adoptium-cacerts.sh + shellcheck packaging/debian/postinst + shellcheck packaging/debian/prerm + + - task: Gradle@2 + displayName: "Build and run tests" + inputs: + workingDirectory: "" + gradleWrapperFile: "gradlew" + gradleOptions: "-Xmx3072m" + javaHomeOption: "JDKVersion" + jdkVersionOption: "1.8" + jdkArchitectureOption: "x64" + publishJUnitResults: true + testResultsFiles: "**/TEST-*.xml" + tasks: "check packageTest" + + - task: CopyFiles@2 + displayName: "Collect debian packages" + inputs: + sourceFolder: "$(Build.SourcesDirectory)/build/deb" + contents: "*.deb" + targetFolder: "$(Build.ArtifactStagingDirectory)" + + - task: PublishBuildArtifacts@1 + displayName: "Publish artifacts" + inputs: + pathToPublish: '$(Build.ArtifactStagingDirectory)' + artifactName: artifacts + + - task: GitHubRelease@0 + displayName: "Push to GitHub Releases" + condition: and(succeeded(), eq(variables.isTag, true)) + inputs: + gitHubConnection: github/aahlenst + repositoryName: "$(Build.Repository.Name)" + action: "create" + target: "$(Build.SourceVersion)" + tagSource: "auto" diff --git a/linux_new/build.gradle b/linux_new/build.gradle new file mode 100644 index 000000000..fd6b68930 --- /dev/null +++ b/linux_new/build.gradle @@ -0,0 +1,61 @@ +plugins { + id "java" +} + +ext { + junitVersion = "5.7.0" + testcontainersVersion = "1.15.1" + assertjCoreVersion = "3.18.1" +} + +repositories { + mavenCentral() +} + +group "org.adoptium" +version "1.0.0-SNAPSHOT" + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +tasks.register("package") { + group = "packaging" + description = "Creates Linux packages." +} + +tasks.register("checkPackage") { + description = "Tests the generated packages." + group = "verification" +} + +check.dependsOn(checkPackage) + +def getProduct() { + return hasProperty("PRODUCT") ? PRODUCT.toString().toLowerCase(Locale.US) : null +} + +def getProductVersion() { + return hasProperty("PRODUCT_VERSION") ? Integer.parseInt(PRODUCT_VERSION) : null +} + +def getGPGKey() { + return hasProperty("GPG_KEY") ? GPG_KEY.toString() : null +} + +def getArch() { + return hasProperty("ARCH") ? ARCH.toString() : "all" +} + +def getInputDir() { + return hasProperty("INPUT_DIR") ? INPUT_DIR.toString() : null +} + +def getLocalBuildStatus() { + return hasProperty("INPUT_DIR") ? "true" : "false" +} + +def getContainerRegistry() { + return hasProperty("CONTAINER_REGISTRY") ? CONTAINER_REGISTRY.toString() : "" +} \ No newline at end of file diff --git a/linux_new/generate_spec.py b/linux_new/generate_spec.py new file mode 100644 index 000000000..f3915442a --- /dev/null +++ b/linux_new/generate_spec.py @@ -0,0 +1,114 @@ +import sys +import os +from jinja2 import Environment, FileSystemLoader + +def print_parameters(template_path, package_version, hardware_architecture, package_url, package_checksum, package_name, output_file_name, current_date, package_release_version, upstream_version, changelog_version, upstreamarm32_version): + """ + Print the received parameters in a formatted manner. + """ + print("Parameters received:") + print(f" Template Path : {template_path}") + print(f" Package Version : {package_version}") + print(f" Hardware Architecture : {hardware_architecture}") + print(f" Package URL : {package_url}") + print(f" Package Checksum : {package_checksum}") + print(f" Package Name : {package_name}") + print(f" Output File Name : {output_file_name}") + print(f" Current Date : {current_date}") + print(f" Pack Rel Version : {package_release_version}") + print(f" Upstream Version : {upstream_version}") + print(f" Changelog Version : {changelog_version}") + print(f" Upstream ARM32 Version : {upstreamarm32_version}") + +def render_template(template_path, package_version, hardware_architecture, package_url, package_checksum, package_name, output_file_name, current_date, package_release_version, upstream_version, changelog_version, upstreamarm32_version): + """ + Render a Jinja2 template file using provided parameters and save the result to an output file specified by the user. + + Args: + template_path (str): Path to the J2 template file. + package_version (str): The JDK version for the package being built. + hardware_architecture (str): The hardware architecture for the package. + package_url (str): The URL of the GitHub binary file for this release. + package_checksum (str): The validated SHA256 checksum of the binary specified in the URL. + package_name (str): The filename of the package binary. + output_file_name (str): The name of the output file to save the rendered content. + current_date (str): The date to be used for changelogs etc. + package_release_version (str): The package release version. + upstream_version (str): The upstream release version. + changelog_version (str): The version to be used in the changelog version + upstreamarm32_version (str): The upstream version to be used for ARM32 on JDK8 + """ + # Get the directory of the template file and set the output file path in the same directory + template_dir = os.path.dirname(template_path) + output_path = os.path.join(template_dir, output_file_name) + + # Load the template environment and template file + env = Environment(loader=FileSystemLoader(template_dir)) + template = env.get_template(os.path.basename(template_path)) + + # Render the template with provided parameters + rendered_content = template.render( + package_version=package_version, + hardware_architecture=hardware_architecture, + package_url=package_url, + package_checksum=package_checksum, + package_name=package_name, + current_date=current_date, + package_release_version=package_release_version, + upstream_version=upstream_version, + changelog_version=changelog_version, + upstreamarm32_version=upstreamarm32_version + ) + + # Write the rendered content to the output file + with open(output_path, "w") as output_file: + output_file.write(rendered_content) + + print(f"Template rendered and saved to {output_path}") + +def main(): + # Define the expected parameter count (9 parameters + script name) + expected_params = 12 + + # Check if the correct number of arguments was provided ( add 1 for script name/system param) + if len(sys.argv) != expected_params + 1: + print("Error: Eleven parameters are required.") + print("\nUsage:") + print(" python3 script.py