From 75b4c6e4679c06e706d2af0c4f57aaf4a7213864 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Wed, 23 Apr 2025 16:31:23 -0700 Subject: [PATCH 1/8] Add native build to CI --- .github/workflows/build-native-image.yml | 99 ++++++++++++++++++++++++ .github/workflows/ci.yml | 6 ++ .github/workflows/prepare-release.yml | 67 +--------------- docker/native-image-musl/dockerfile | 18 +++++ docker/native-image-musl/install-musl.sh | 28 +++++++ docker/native-image/dockerfile | 8 +- temporal-test-server/build.gradle | 7 +- 7 files changed, 166 insertions(+), 67 deletions(-) create mode 100644 .github/workflows/build-native-image.yml create mode 100644 docker/native-image-musl/dockerfile create mode 100644 docker/native-image-musl/install-musl.sh diff --git a/.github/workflows/build-native-image.yml b/.github/workflows/build-native-image.yml new file mode 100644 index 000000000..88ca5c998 --- /dev/null +++ b/.github/workflows/build-native-image.yml @@ -0,0 +1,99 @@ +name: Build native image +defaults: + run: + shell: bash -euo pipefail -O nullglob {0} +on: + workflow_dispatch: + inputs: + ref: + type: string + description: "Git ref from which to release" + required: true + default: "master" + workflow_call: + inputs: + ref: + type: string + description: "Git ref from which to release" + required: true + default: "master" +env: + INPUT_REF: ${{ github.event.inputs.ref }} + +jobs: + build_native_images: + name: Build native test server + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-latest + os_family: linux + arch: amd64 + musl: true + - runner: ubuntu-latest + os_family: linux + arch: amd64 + musl: false + - runner: macos-13 + os_family: macOS + arch: amd64 + - runner: macos-latest + os_family: macOS + arch: arm64 + - runner: ubuntu-24.04-arm + os_family: linux + arch: arm64 + - runner: windows-latest + os_family: windows + arch: amd64 + runs-on: ${{ matrix.runner }} + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + ref: ${{ env.INPUT_REF }} + + - name: Set up Java + if: matrix.os_family != 'Linux' + uses: actions/setup-java@v4 + with: + java-version: "21" + distribution: "graalvm" + + - name: Set up Gradle + if: matrix.os_family != 'Linux' + uses: gradle/actions/setup-gradle@v4 + + - name: Build native test server (non-Docker) + if: matrix.os_family != 'Linux' + run: | + ./gradlew -PnativeBuild :temporal-test-server:nativeCompile + + - name: Build native test server (Docker non-musl) + if: matrix.os_family == 'Linux' && matrix.musl == false + run: | + docker run \ + --rm -w /github/workspace -v "$(pwd):/github/workspace" \ + $(docker build -q ./docker/native-image) \ + sh -c "./gradlew -PnativeBuild :temporal-test-server:nativeCompile" + + - name: Build native test server (Docker musl) + if: matrix.os_family == 'Linux' && matrix.musl == true + run: | + docker run \ + --rm -w /github/workspace -v "$(pwd):/github/workspace" \ + $(docker build -q ./docker/native-image-musl) \ + sh -c "./gradlew -PnativeBuild -PnativeBuildMusl :temporal-test-server:nativeCompile" + # path ends in a wildcard because on windows the file ends in '.exe' + - name: Upload executable to workflow + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.musl && format('{0}_{1}_musl', matrix.os_family, matrix.arch) || format('{0}_{1}', matrix.os_family, matrix.arch)}} + path: | + temporal-test-server/build/native/nativeCompile/temporal-test-server* + if-no-files-found: error + retention-days: 1 + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54f03c912..ccd0af8b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -188,3 +188,9 @@ jobs: - name: Run copyright and code format checks run: ./gradlew --no-daemon checkLicenseMain checkLicenses spotlessCheck + + build_native_images: + name: Build native test server + uses: ./.github/workflows/build-native-image.yml + with: + ref: ${{ github.event.pull_request.head.sha }} \ No newline at end of file diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index e077e72f9..fba735306 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -124,70 +124,9 @@ jobs: name: Build native test server needs: create_draft_release if: github.event.inputs.do_build_native_images == 'true' - strategy: - fail-fast: false - matrix: - include: - - runner: ubuntu-latest - os_family: linux - arch: amd64 - - runner: macos-13 - os_family: macOS - arch: amd64 - - runner: macos-latest - os_family: macOS - arch: arm64 - - runner: ubuntu-24.04-arm - os_family: linux - arch: arm64 - - runner: windows-2019 - os_family: windows - arch: amd64 - runs-on: ${{ matrix.runner }} - steps: - - name: Checkout repo - uses: actions/checkout@v4 - with: - submodules: recursive - ref: ${{ env.INPUT_REF }} - - # See comment on temporary tag above. tldr: this is a local tag; never - # gets pushed - - name: Temporary tag - run: git tag "$INPUT_TAG" - - - name: Set up Java - if: matrix.os_family != 'Linux' - uses: actions/setup-java@v4 - with: - java-version: "21" - distribution: "graalvm" - - - name: Set up Gradle - if: matrix.os_family != 'Linux' - uses: gradle/actions/setup-gradle@v4 - - - name: Build native test server (non-Docker) - if: matrix.os_family != 'Linux' - run: | - ./gradlew -PnativeBuild :temporal-test-server:nativeBuild - - - name: Build native test server (Docker) - if: matrix.os_family == 'Linux' - run: | - docker run \ - --rm -w /github/workspace -v "$(pwd):/github/workspace" \ - $(docker build -q ./docker/native-image) \ - sh -c "./gradlew -PnativeBuild :temporal-test-server:nativeBuild" - # path ends in a wildcard because on windows the file ends in '.exe' - - name: Upload executable to workflow - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.os_family }}_${{ matrix.arch }} - path: | - temporal-test-server/build/native/nativeCompile/temporal-test-server* - if-no-files-found: error - retention-days: 1 + uses: ./.github/workflows/build-native-image.yml + with: + ref: ${{ github.event.inputs.ref }} attach_to_release: name: Attach native executables to release diff --git a/docker/native-image-musl/dockerfile b/docker/native-image-musl/dockerfile new file mode 100644 index 000000000..483746241 --- /dev/null +++ b/docker/native-image-musl/dockerfile @@ -0,0 +1,18 @@ +# Use an old version of Ubuntu to build the test server to maintain compatibility with +# older versions of glibc, specifically glib 2.17. +FROM ubuntu:18.04 +ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java21 +COPY --from=ghcr.io/graalvm/native-image-community:21 $JAVA_HOME $JAVA_HOME +ENV PATH="${JAVA_HOME}/bin:${PATH}" +RUN apt-get update +RUN apt-get install -y git build-essential curl +COPY install-musl.sh /opt/install-musl.sh +RUN chmod +x /opt/install-musl.sh +WORKDIR /opt +# We need to build musl and zlibc with musl to for a static build +# See https://www.graalvm.org/21.3/reference-manual/native-image/StaticImages/index.html +RUN ./install-musl.sh +ENV MUSL_HOME=/opt/musl-toolchain +ENV PATH="$MUSL_HOME/bin:$PATH" +# Avoid errors like: "fatal: detected dubious ownership in repository" +RUN git config --global --add safe.directory '*' \ No newline at end of file diff --git a/docker/native-image-musl/install-musl.sh b/docker/native-image-musl/install-musl.sh new file mode 100644 index 000000000..9000a1cda --- /dev/null +++ b/docker/native-image-musl/install-musl.sh @@ -0,0 +1,28 @@ +# Specify an installation directory for musl: +export MUSL_HOME=$PWD/musl-toolchain + +# Download musl and zlib sources: +curl -O https://musl.libc.org/releases/musl-1.2.5.tar.gz +curl -O https://zlib.net/fossils/zlib-1.2.13.tar.gz + +# Build musl from source +tar -xzvf musl-1.2.5.tar.gz +cd musl-1.2.5 +./configure --prefix=$MUSL_HOME --static +# The next operation may require privileged access to system resources, so use sudo +make && make install +cd .. + +# Install a symlink for use by native-image +ln -s $MUSL_HOME/bin/musl-gcc $MUSL_HOME/bin/x86_64-linux-musl-gcc + +# Extend the system path and confirm that musl is available by printing its version +export PATH="$MUSL_HOME/bin:$PATH" +x86_64-linux-musl-gcc --version + +# Build zlib with musl from source and install into the MUSL_HOME directory +tar -xzvf zlib-1.2.13.tar.gz +cd zlib-1.2.13 +CC=musl-gcc ./configure --prefix=$MUSL_HOME --static +make && make install +cd .. diff --git a/docker/native-image/dockerfile b/docker/native-image/dockerfile index 0b1a0c71f..1238ece2f 100644 --- a/docker/native-image/dockerfile +++ b/docker/native-image/dockerfile @@ -2,9 +2,13 @@ # older versions of glibc, specifically glib 2.17. FROM ubuntu:18.04 ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java21 -COPY --from=ghcr.io/graalvm/jdk-community:21 $JAVA_HOME $JAVA_HOME +COPY --from=ghcr.io/graalvm/native-image-community:21 $JAVA_HOME $JAVA_HOME ENV PATH="${JAVA_HOME}/bin:${PATH}" +RUN apt-get update && apt-get install -y software-properties-common +RUN add-apt-repository ppa:ubuntu-toolchain-r/test RUN apt-get update -RUN apt-get install -y git build-essential zlib1g-dev +# We need to update gcc and g++ to 10 for Graal to work on ARM64 +RUN apt-get install -y git build-essential zlib1g-dev gcc-10 g++-10 +RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 60 --slave /usr/bin/g++ g++ /usr/bin/g++-10 # Avoid errors like: "fatal: detected dubious ownership in repository" RUN git config --global --add safe.directory '*' \ No newline at end of file diff --git a/temporal-test-server/build.gradle b/temporal-test-server/build.gradle index 5ef589bfc..3eb701baa 100644 --- a/temporal-test-server/build.gradle +++ b/temporal-test-server/build.gradle @@ -120,7 +120,12 @@ if (project.hasProperty("nativeBuild")) { // If we're on linux, static link everything but libc. Otherwise link // everything dynamically (note the '-' rather than '+' in front of // StaticExecutable) - buildArgs.add(isLinux() ? "-H:+StaticExecutableWithDynamicLibC": "-H:-StaticExecutable") + if (isLinux() && !project.hasProperty("nativeBuildMusl")) { + buildArgs.add("-H:+StaticExecutableWithDynamicLibC") + } else if (isLinux() && project.hasProperty("nativeBuildMusl")) { + buildArgs.add("--static") + buildArgs.add("--libc=musl") + } buildArgs.add("-H:+UnlockExperimentalVMOptions") buildArgs.add("-O4") From 14b11e2112535c6a023b88586205f6a9931c0f46 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 25 Apr 2025 13:06:57 -0700 Subject: [PATCH 2/8] Try to reduce size --- .github/workflows/build-native-image.yml | 2 +- docker/native-image-musl/dockerfile | 4 ++-- docker/native-image/dockerfile | 4 ++-- temporal-test-server/build.gradle | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-native-image.yml b/.github/workflows/build-native-image.yml index 88ca5c998..2aa5d06a9 100644 --- a/.github/workflows/build-native-image.yml +++ b/.github/workflows/build-native-image.yml @@ -60,7 +60,7 @@ jobs: if: matrix.os_family != 'Linux' uses: actions/setup-java@v4 with: - java-version: "21" + java-version: "23" distribution: "graalvm" - name: Set up Gradle diff --git a/docker/native-image-musl/dockerfile b/docker/native-image-musl/dockerfile index 483746241..1c7aac91d 100644 --- a/docker/native-image-musl/dockerfile +++ b/docker/native-image-musl/dockerfile @@ -1,8 +1,8 @@ # Use an old version of Ubuntu to build the test server to maintain compatibility with # older versions of glibc, specifically glib 2.17. FROM ubuntu:18.04 -ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java21 -COPY --from=ghcr.io/graalvm/native-image-community:21 $JAVA_HOME $JAVA_HOME +ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java23 +COPY --from=ghcr.io/graalvm/native-image-community:23 $JAVA_HOME $JAVA_HOME ENV PATH="${JAVA_HOME}/bin:${PATH}" RUN apt-get update RUN apt-get install -y git build-essential curl diff --git a/docker/native-image/dockerfile b/docker/native-image/dockerfile index 1238ece2f..931c737bc 100644 --- a/docker/native-image/dockerfile +++ b/docker/native-image/dockerfile @@ -1,8 +1,8 @@ # Use an old version of Ubuntu to build the test server to maintain compatibility with # older versions of glibc, specifically glib 2.17. FROM ubuntu:18.04 -ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java21 -COPY --from=ghcr.io/graalvm/native-image-community:21 $JAVA_HOME $JAVA_HOME +ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java23 +COPY --from=ghcr.io/graalvm/native-image-community:23 $JAVA_HOME $JAVA_HOME ENV PATH="${JAVA_HOME}/bin:${PATH}" RUN apt-get update && apt-get install -y software-properties-common RUN add-apt-repository ppa:ubuntu-toolchain-r/test diff --git a/temporal-test-server/build.gradle b/temporal-test-server/build.gradle index 3eb701baa..2551b5ebf 100644 --- a/temporal-test-server/build.gradle +++ b/temporal-test-server/build.gradle @@ -127,7 +127,7 @@ if (project.hasProperty("nativeBuild")) { buildArgs.add("--libc=musl") } buildArgs.add("-H:+UnlockExperimentalVMOptions") - buildArgs.add("-O4") + buildArgs.add("-Os") runtimeArgs.add("7233") } From 27dcba22bb52f145badc7205b6fa60307a772ae7 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 25 Apr 2025 13:16:56 -0700 Subject: [PATCH 3/8] fix java version --- .github/workflows/build-native-image.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-native-image.yml b/.github/workflows/build-native-image.yml index 2aa5d06a9..c5c066f28 100644 --- a/.github/workflows/build-native-image.yml +++ b/.github/workflows/build-native-image.yml @@ -60,7 +60,9 @@ jobs: if: matrix.os_family != 'Linux' uses: actions/setup-java@v4 with: - java-version: "23" + java-version: | + 21 + 23 distribution: "graalvm" - name: Set up Gradle From 3b16703c36b236759ebd92ccc5b642e79b740038 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 25 Apr 2025 13:33:09 -0700 Subject: [PATCH 4/8] fix --- .github/workflows/ci.yml | 4 ++-- temporal-sdk/build.gradle | 2 +- .../io.temporal/temporal-test-server/native-image.properties | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ccd0af8b2..5ed1f94fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - name: Set up Java uses: actions/setup-java@v4 with: - java-version: "21" + java-version: "23" distribution: "temurin" - name: Set up Gradle @@ -61,7 +61,7 @@ jobs: uses: actions/setup-java@v4 with: java-version: | - 21 + 23 11 distribution: "temurin" diff --git a/temporal-sdk/build.gradle b/temporal-sdk/build.gradle index 32bfcd832..31f8b36db 100644 --- a/temporal-sdk/build.gradle +++ b/temporal-sdk/build.gradle @@ -51,7 +51,7 @@ dependencies { tasks.named('compileJava21Java') { javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(23) } options.release = 21 } diff --git a/temporal-test-server/src/main/resources/META-INF/native-image/io.temporal/temporal-test-server/native-image.properties b/temporal-test-server/src/main/resources/META-INF/native-image/io.temporal/temporal-test-server/native-image.properties index 4e7bb5701..051d44569 100644 --- a/temporal-test-server/src/main/resources/META-INF/native-image/io.temporal/temporal-test-server/native-image.properties +++ b/temporal-test-server/src/main/resources/META-INF/native-image/io.temporal/temporal-test-server/native-image.properties @@ -23,5 +23,7 @@ Args = -H:+UnlockExperimentalVMOptions \ -H:JNIConfigurationResources=${.}/jni-config.json \ -H:ReflectionConfigurationResources=${.}/reflect-config.json \ -H:ResourceConfigurationResources=${.}/resource-config.json \ - -H:SerializationConfigurationResources=${.}/serialization-config.json + -H:SerializationConfigurationResources=${.}/serialization-config.json \ + --initialize-at-build-time=org.slf4j.helpers.SubstituteLoggerFactory \ + --initialize-at-build-time=org.slf4j.helpers.NOPLoggerFactory From 211583b6205a0f82a76ce19f5571165cd32b72c2 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 25 Apr 2025 13:46:24 -0700 Subject: [PATCH 5/8] update binutils --- docker/native-image-musl/dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/native-image-musl/dockerfile b/docker/native-image-musl/dockerfile index 1c7aac91d..f9fe3f542 100644 --- a/docker/native-image-musl/dockerfile +++ b/docker/native-image-musl/dockerfile @@ -5,7 +5,7 @@ ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java23 COPY --from=ghcr.io/graalvm/native-image-community:23 $JAVA_HOME $JAVA_HOME ENV PATH="${JAVA_HOME}/bin:${PATH}" RUN apt-get update -RUN apt-get install -y git build-essential curl +RUN apt-get install -y git build-essential curl binutils COPY install-musl.sh /opt/install-musl.sh RUN chmod +x /opt/install-musl.sh WORKDIR /opt From d36f570d64f7432a653826f587b85160246cc13a Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 25 Apr 2025 13:58:36 -0700 Subject: [PATCH 6/8] try again --- docker/native-image-musl/dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/native-image-musl/dockerfile b/docker/native-image-musl/dockerfile index f9fe3f542..4f27e1168 100644 --- a/docker/native-image-musl/dockerfile +++ b/docker/native-image-musl/dockerfile @@ -5,7 +5,7 @@ ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java23 COPY --from=ghcr.io/graalvm/native-image-community:23 $JAVA_HOME $JAVA_HOME ENV PATH="${JAVA_HOME}/bin:${PATH}" RUN apt-get update -RUN apt-get install -y git build-essential curl binutils +RUN apt-get install -y git build-essential curl binutils zlib1g-dev gcc-10 g++-10 COPY install-musl.sh /opt/install-musl.sh RUN chmod +x /opt/install-musl.sh WORKDIR /opt From b266fc1849232f7396e55210a7acf3d00c7473b8 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 25 Apr 2025 14:10:18 -0700 Subject: [PATCH 7/8] try updating binutils --- docker/native-image-musl/dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/native-image-musl/dockerfile b/docker/native-image-musl/dockerfile index 4f27e1168..f9fe3f542 100644 --- a/docker/native-image-musl/dockerfile +++ b/docker/native-image-musl/dockerfile @@ -5,7 +5,7 @@ ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java23 COPY --from=ghcr.io/graalvm/native-image-community:23 $JAVA_HOME $JAVA_HOME ENV PATH="${JAVA_HOME}/bin:${PATH}" RUN apt-get update -RUN apt-get install -y git build-essential curl binutils zlib1g-dev gcc-10 g++-10 +RUN apt-get install -y git build-essential curl binutils COPY install-musl.sh /opt/install-musl.sh RUN chmod +x /opt/install-musl.sh WORKDIR /opt From 90a7e9e6c8809447a58bcdf87b4d3e5c0c5850b1 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Fri, 25 Apr 2025 14:21:55 -0700 Subject: [PATCH 8/8] try ubuntu 24 --- docker/native-image-musl/dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/native-image-musl/dockerfile b/docker/native-image-musl/dockerfile index f9fe3f542..47c9d7dfa 100644 --- a/docker/native-image-musl/dockerfile +++ b/docker/native-image-musl/dockerfile @@ -1,6 +1,6 @@ # Use an old version of Ubuntu to build the test server to maintain compatibility with # older versions of glibc, specifically glib 2.17. -FROM ubuntu:18.04 +FROM ubuntu:24.04 ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java23 COPY --from=ghcr.io/graalvm/native-image-community:23 $JAVA_HOME $JAVA_HOME ENV PATH="${JAVA_HOME}/bin:${PATH}"