From e5dcce7ac0d13470e9d3d291e79e1996cce8ecf7 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Tue, 30 Jun 2026 16:00:14 +0800 Subject: [PATCH] Move UbuntuAmd64 CI to Ubuntu 24.04 EC2 agents. Match the new gradle-bt-ci AMI while preserving the glibc 2.23 floor for released native libraries by publishing JNI artifacts from an Ubuntu 16.04 container on the Ubuntu 24 host agent. --- .teamcity/Agent.kt | 8 ++++-- .teamcity/NativePlatformBuild.kt | 23 ++++++++++++++-- .teamcity/NativePlatformPublishing.kt | 9 +++++++ .teamcity/Os.kt | 7 +++++ .../docker/native-publish-ubuntu16/Dockerfile | 25 ++++++++++++++++++ .teamcity/extensions.kt | 26 +++++++++++++++++++ 6 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 .teamcity/docker/native-publish-ubuntu16/Dockerfile diff --git a/.teamcity/Agent.kt b/.teamcity/Agent.kt index 211e986d..3dadb0c1 100644 --- a/.teamcity/Agent.kt +++ b/.teamcity/Agent.kt @@ -14,8 +14,12 @@ * limitations under the License. */ -enum class Agent(val os: Os, val architecture: Architecture) { - UbuntuAmd64(os = Os.Ubuntu16, architecture = Architecture.Amd64), +enum class Agent(val os: Os, val architecture: Architecture, val nativePublishContainer: String? = null) { + UbuntuAmd64( + os = Os.Ubuntu24, + architecture = Architecture.Amd64, + nativePublishContainer = "native-platform/ubuntu16-publish:local", + ), UbuntuAarch64(os = Os.Ubuntu16, architecture = Architecture.Aarch64), AmazonLinuxAmd64(os = Os.AmazonLinux, architecture = Architecture.Amd64), AmazonLinuxAarch64(os = Os.AmazonLinux, architecture = Architecture.Aarch64), diff --git a/.teamcity/NativePlatformBuild.kt b/.teamcity/NativePlatformBuild.kt index 46019fb4..4f609e7e 100644 --- a/.teamcity/NativePlatformBuild.kt +++ b/.teamcity/NativePlatformBuild.kt @@ -32,14 +32,33 @@ open class NativePlatformBuild(agent: Agent, buildReceiptSource: Boolean = false } steps { + val publishOnHost = agent.nativePublishContainer.isNullOrBlank() || agent.allPublishTasks.isBlank() + if (!publishOnHost) { + buildNativePublishContainerImage(agent) + } + gradle { - tasks = - "clean build -PagentName=${agent.name}${agent.allPublishTasks} ${javaInstallationLocations()}" + tasks = buildString { + append("clean build -PagentName=${agent.name}") + if (publishOnHost) { + append(agent.allPublishTasks) + } + append(" ${javaInstallationLocations()}") + } if (buildReceiptSource) { gradleParams = "-PignoreIncomingBuildReceipt" } buildFile = "" } + + if (!publishOnHost) { + gradle { + name = "Publish (glibc 2.23 container)" + tasks = "${agent.allPublishTasks.trim()} ${javaInstallationLocations()}" + useNativePublishContainer(agent) + buildFile = "" + } + } } features { diff --git a/.teamcity/NativePlatformPublishing.kt b/.teamcity/NativePlatformPublishing.kt index 4dc931c6..0df2dbca 100644 --- a/.teamcity/NativePlatformPublishing.kt +++ b/.teamcity/NativePlatformPublishing.kt @@ -91,11 +91,20 @@ open class NativePlatformPublishSnapshot( } steps { + val usesNativePublishContainer = !agent.nativePublishContainer.isNullOrBlank() && + uploadTasks.any { it.isNativePublishTask() } + if (usesNativePublishContainer) { + buildNativePublishContainerImage(agent) + } + uploadTasks.forEach { task -> gradle { name = "Gradle $task" tasks = "clean $task -P${releaseType.gradleProperty}${if (releaseType.userProvidedVersion) "=%versionPostfix%" else ""} ${javaInstallationLocations()}" + if (usesNativePublishContainer && task.isNativePublishTask()) { + useNativePublishContainer(agent) + } buildFile = "" } } diff --git a/.teamcity/Os.kt b/.teamcity/Os.kt index 8582d79e..1b46b6c0 100644 --- a/.teamcity/Os.kt +++ b/.teamcity/Os.kt @@ -27,6 +27,13 @@ interface Os { } } + object Ubuntu24 : Linux(Ncurses.Ncurses6) { + override fun Requirements.additionalRequirements() { + contains(osDistributionNameParameter, "ubuntu") + contains(osDistributionVersionParameter, "24") + } + } + object AmazonLinux : Linux(Ncurses.Ncurses6) { override fun Requirements.additionalRequirements() { contains(osDistributionNameParameter, "amazon") diff --git a/.teamcity/docker/native-publish-ubuntu16/Dockerfile b/.teamcity/docker/native-publish-ubuntu16/Dockerfile new file mode 100644 index 00000000..d2dab537 --- /dev/null +++ b/.teamcity/docker/native-publish-ubuntu16/Dockerfile @@ -0,0 +1,25 @@ +# Released native-platform Linux libraries must stay on glibc 2.23 (Ubuntu 16.04). +FROM ubuntu:16.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + ca-certificates \ + curl \ + g++ \ + git \ + libncurses5-dev \ + openjdk-8-jdk \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +ARG JDK21_VERSION=jdk-21.0.11+10 +RUN mkdir -p /opt/jdk \ + && curl -fsSL "https://api.adoptium.net/v3/binary/version/${JDK21_VERSION}/linux/x64/jdk/hotspot/normal/adoptium" -o /tmp/jdk21.tar.gz \ + && tar xf /tmp/jdk21.tar.gz -C /opt/jdk \ + && ln -s "/opt/jdk/${JDK21_VERSION}" /opt/jdk/open-jdk-21 \ + && rm /tmp/jdk21.tar.gz + +ENV JDK8=/usr/lib/jvm/java-8-openjdk-amd64 +ENV JDK21=/opt/jdk/open-jdk-21 +ENV JAVA_HOME=/opt/jdk/open-jdk-21 diff --git a/.teamcity/extensions.kt b/.teamcity/extensions.kt index 9d862733..1bbd027a 100644 --- a/.teamcity/extensions.kt +++ b/.teamcity/extensions.kt @@ -16,10 +16,13 @@ import jetbrains.buildServer.configs.kotlin.BuildFeatures import jetbrains.buildServer.configs.kotlin.BuildType +import jetbrains.buildServer.configs.kotlin.BuildSteps import jetbrains.buildServer.configs.kotlin.DslContext import jetbrains.buildServer.configs.kotlin.Requirements import jetbrains.buildServer.configs.kotlin.buildFeatures.commitStatusPublisher import jetbrains.buildServer.configs.kotlin.buildFeatures.freeDiskSpace +import jetbrains.buildServer.configs.kotlin.buildSteps.GradleBuildStep +import jetbrains.buildServer.configs.kotlin.buildSteps.script fun Requirements.requireAgent(agent: Agent) { agent.os.addAgentRequirements(this) @@ -97,3 +100,26 @@ fun BuildFeatures.lowerRequiredFreeDiskSpace() { failBuild = false } } + +private const val nativePublishContainerDockerfile = ".teamcity/docker/native-publish-ubuntu16" + +fun BuildSteps.buildNativePublishContainerImage(agent: Agent) { + val containerImage = agent.nativePublishContainer ?: return + script { + name = "Build native publish container image" + scriptContent = """ + #!/bin/bash + set -euo pipefail + docker build -t $containerImage $nativePublishContainerDockerfile + """.trimIndent() + } +} + +fun GradleBuildStep.useNativePublishContainer(agent: Agent) { + val containerImage = agent.nativePublishContainer ?: return + dockerImage = containerImage + dockerPull = false +} + +fun String.isNativePublishTask(): Boolean = + contains("uploadJni") || contains("uploadNcurses")