This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-graalvm-distro.git


The following commit(s) were added to refs/heads/main by this push:
     new e7946e2  Native distro packaging, Docker image, and CI pipeline
e7946e2 is described below

commit e7946e270ccedc7ae816e6356007fce216c7fbe9
Author: Wu Sheng <[email protected]>
AuthorDate: Tue Feb 24 16:31:30 2026 +0800

    Native distro packaging, Docker image, and CI pipeline
    
    - Add native assembly descriptor (binary + config + logs)
    - Add Dockerfile.native for packaging pre-built native binary
    - Merge CI and Docker workflows: shared skywalking submodule cache
    - Build multi-arch Docker image (amd64 + arm64) to ghcr.io
    - Fix javadoc error in FieldsHelper (MethodHandle#invoke reference)
---
 .dockerignore                                      |  20 +++
 .github/workflows/ci.yml                           | 163 ++++++++++++++++++++-
 Makefile                                           |  16 +-
 docker/Dockerfile.native                           |  47 ++++++
 oap-graalvm-native/pom.xml                         |  18 +++
 .../src/main/assembly/native-distribution.xml      |  86 +++++++++++
 .../oap/server/library/util/FieldsHelper.java      |   2 +-
 7 files changed, 344 insertions(+), 8 deletions(-)

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..92a6d8b
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,20 @@
+# IDE and OS
+.idea/
+*.iml
+.vscode/
+.DS_Store
+
+# Claude Code
+.claude/
+
+# Git
+.git/
+
+# Exclude everything except the native distro tarball and docker context
+skywalking/
+build-tools/
+oap-graalvm-server/
+oap-libs-for-graalvm/
+
+# Allow native distro tarball through
+!oap-graalvm-native/target/oap-graalvm-native-*-native-dist.tar.gz
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 13bc159..c14c0cb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,11 +20,15 @@ on:
     branches: [ main ]
   pull_request:
     branches: [ main ]
+  workflow_dispatch:
 
 concurrency:
   group: ci-${{ github.ref }}
   cancel-in-progress: true
 
+env:
+  IMAGE: ghcr.io/apache/skywalking-graal-distro
+
 jobs:
   license-header:
     name: License Header Check
@@ -36,10 +40,12 @@ jobs:
       - name: Check license headers
         uses: apache/skywalking-eyes/header@main
 
-  build-graal-jvm-distro:
-    name: Build GraalVM JVM Distro
+  # ── Shared: build skywalking submodule and cache .m2/repository ──
+  build-skywalking:
+    name: Build SkyWalking Submodule
     runs-on: ubuntu-latest
-
+    outputs:
+      cache-key: ${{ steps.cache-key.outputs.key }}
     steps:
       - name: Checkout with submodules
         uses: actions/checkout@v4
@@ -51,12 +57,46 @@ jobs:
         with:
           java-version: '25'
           distribution: 'graalvm'
-          cache: 'maven'
+
+      - name: Compute cache key
+        id: cache-key
+        run: echo "key=m2-skywalking-$(git -C skywalking rev-parse HEAD)" >> 
"$GITHUB_OUTPUT"
+
+      - name: Restore Maven cache
+        id: cache
+        uses: actions/cache@v4
+        with:
+          path: ~/.m2/repository
+          key: ${{ steps.cache-key.outputs.key }}
 
       - name: Build SkyWalking submodule
+        if: steps.cache.outputs.cache-hit != 'true'
         run: make build-skywalking
 
-      - name: Style check + Compile + Install
+  # ── CI: compile, javadoc, test, distro ──
+  ci:
+    name: Build & Test
+    runs-on: ubuntu-latest
+    needs: build-skywalking
+    steps:
+      - name: Checkout with submodules
+        uses: actions/checkout@v4
+        with:
+          submodules: recursive
+
+      - name: Set up GraalVM JDK 25
+        uses: graalvm/setup-graalvm@v1
+        with:
+          java-version: '25'
+          distribution: 'graalvm'
+
+      - name: Restore Maven cache
+        uses: actions/cache/restore@v4
+        with:
+          path: ~/.m2/repository
+          key: ${{ needs.build-skywalking.outputs.cache-key }}
+
+      - name: Compile & Install
         run: make compile
 
       - name: Javadoc
@@ -67,3 +107,116 @@ jobs:
 
       - name: Build distribution
         run: make build-distro
+
+  # ── Native image build per architecture ──
+  build-native:
+    name: Native ${{ matrix.arch }}
+    runs-on: ${{ matrix.runner }}
+    needs: build-skywalking
+    if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
+    strategy:
+      matrix:
+        include:
+          - arch: amd64
+            runner: ubuntu-latest
+            platform: linux/amd64
+          - arch: arm64
+            runner: ubuntu-24.04-arm
+            platform: linux/arm64
+    permissions:
+      contents: read
+      packages: write
+    steps:
+      - name: Checkout with submodules
+        uses: actions/checkout@v4
+        with:
+          submodules: recursive
+
+      - name: Set up GraalVM JDK 25
+        uses: graalvm/setup-graalvm@v1
+        with:
+          java-version: '25'
+          distribution: 'graalvm'
+
+      - name: Restore Maven cache
+        uses: actions/cache/restore@v4
+        with:
+          path: ~/.m2/repository
+          key: ${{ needs.build-skywalking.outputs.cache-key }}
+
+      - name: Build native image
+        run: make native-image
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v3
+
+      - name: Log in to GHCR
+        uses: docker/login-action@v3
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Locate distro tarball
+        id: dist
+        run: echo "path=$(ls 
oap-graalvm-native/target/oap-graalvm-native-*-native-dist.tar.gz)" >> 
"$GITHUB_OUTPUT"
+
+      - name: Build and push by digest
+        id: build
+        uses: docker/build-push-action@v6
+        with:
+          context: .
+          file: docker/Dockerfile.native
+          platforms: ${{ matrix.platform }}
+          build-args: |
+            DIST=${{ steps.dist.outputs.path }}
+          outputs: type=image,name=${{ env.IMAGE 
}},push-by-digest=true,name-canonical=true,push=true
+
+      - name: Export digest
+        run: |
+          mkdir -p /tmp/digests
+          digest="${{ steps.build.outputs.digest }}"
+          touch "/tmp/digests/${digest#sha256:}"
+
+      - name: Upload digest
+        uses: actions/upload-artifact@v4
+        with:
+          name: digests-${{ matrix.arch }}
+          path: /tmp/digests/*
+          if-no-files-found: error
+          retention-days: 1
+
+  # ── Merge per-arch images into multi-arch manifest ──
+  docker-manifest:
+    name: Docker Manifest
+    runs-on: ubuntu-latest
+    needs: build-native
+    permissions:
+      contents: read
+      packages: write
+    steps:
+      - name: Download digests
+        uses: actions/download-artifact@v4
+        with:
+          path: /tmp/digests
+          pattern: digests-*
+          merge-multiple: true
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v3
+
+      - name: Log in to GHCR
+        uses: docker/login-action@v3
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Create and push manifest
+        working-directory: /tmp/digests
+        run: |
+          SHORT_SHA=${GITHUB_SHA::7}
+          docker buildx imagetools create \
+            -t ${{ env.IMAGE }}:latest \
+            -t ${{ env.IMAGE }}:${SHORT_SHA} \
+            $(printf '${{ env.IMAGE }}@sha256:%s ' *)
diff --git a/Makefile b/Makefile
index 011cfb3..3062af1 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@ SW_VERSION := $(shell grep '<revision>' skywalking/pom.xml | 
head -1 | sed 's/.*
 MVN := ./mvnw
 MVN_ARGS := -Dskywalking.version=$(SW_VERSION)
 
-.PHONY: all clean build init-submodules build-skywalking build-distro compile 
test javadoc dist info docker-up docker-down boot shutdown native-image 
trace-agent
+.PHONY: all clean build init-submodules build-skywalking build-distro compile 
test javadoc dist info docker-up docker-down boot shutdown native-image 
native-dist trace-agent docker-native
 
 all: build
 
@@ -60,10 +60,16 @@ build-distro:
 
 # Show the distribution directory
 dist: build-distro
-       @echo "Distribution created at:"
+       @echo "JVM distribution created at:"
        @echo "  
oap-graalvm-server/target/oap-graalvm-jvm-distro/oap-graalvm-jvm-distro/"
        @echo "  oap-graalvm-server/target/oap-graalvm-jvm-distro.tar.gz"
 
+# Show the native distribution directory
+native-dist: native-image
+       @echo "Native distribution created at:"
+       @ls -d 
oap-graalvm-native/target/oap-graalvm-native-*-native-dist/oap-native/ 
2>/dev/null
+       @ls oap-graalvm-native/target/oap-graalvm-native-*-native-dist.tar.gz 
2>/dev/null
+
 # Full build: skywalking first, then distro
 build: build-skywalking build-distro
 
@@ -98,6 +104,12 @@ trace-agent: build-distro docker-up
        JAVA_OPTS="-Xms256M -Xmx4096M 
-agentlib:native-image-agent=config-merge-dir=oap-graalvm-native/src/main/resources/META-INF/native-image/org.apache.skywalking/oap-graalvm-native"
 \
          
oap-graalvm-server/target/oap-graalvm-jvm-distro/oap-graalvm-jvm-distro/bin/oapService.sh
 
+# Build Docker image with native binary (requires prior: make native-image)
+docker-native:
+       docker build -f docker/Dockerfile.native \
+               --build-arg DIST=$$(ls 
oap-graalvm-native/target/oap-graalvm-native-*-native-dist.tar.gz) \
+               -t skywalking-oap-native .
+
 # Build distro and boot OAP with BanyanDB
 boot: build-distro docker-up
        SW_STORAGE_BANYANDB_TARGETS=localhost:17912 \
diff --git a/docker/Dockerfile.native b/docker/Dockerfile.native
new file mode 100644
index 0000000..7aa29fa
--- /dev/null
+++ b/docker/Dockerfile.native
@@ -0,0 +1,47 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
+#
+#     http://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.
+
+# Packages a pre-built native binary into a minimal runtime image.
+#
+# Prerequisites (host or CI):
+#   make build-skywalking   # install upstream JARs to .m2
+#   make native-image       # build native binary + distro tarball
+#
+# Usage:
+#   docker build -f docker/Dockerfile.native \
+#     --build-arg 
DIST=oap-graalvm-native/target/oap-graalvm-native-1.0.0-SNAPSHOT-native-dist.tar.gz
 \
+#     -t skywalking-oap-native .
+#
+#   docker run -e SW_STORAGE_BANYANDB_TARGETS=host.docker.internal:17912 
skywalking-oap-native
+
+FROM debian:bookworm-slim
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+        zlib1g ca-certificates fontconfig \
+    && rm -rf /var/lib/apt/lists/*
+
+ENV OAP_HOME=/skywalking
+WORKDIR $OAP_HOME
+
+ARG DIST
+COPY ${DIST} /tmp/native-dist.tar.gz
+RUN tar -xzf /tmp/native-dist.tar.gz --strip-components=1 -C . \
+    && rm /tmp/native-dist.tar.gz \
+    && mkdir -p logs \
+    && chmod +x oap-server
+
+EXPOSE 12800 11800 1234
+
+ENTRYPOINT ["./oap-server"]
diff --git a/oap-graalvm-native/pom.xml b/oap-graalvm-native/pom.xml
index 7f4de45..f9b805a 100644
--- a/oap-graalvm-native/pom.xml
+++ b/oap-graalvm-native/pom.xml
@@ -92,6 +92,24 @@
                             </execution>
                         </executions>
                     </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-assembly-plugin</artifactId>
+                        <configuration>
+                            <descriptors>
+                                
<descriptor>src/main/assembly/native-distribution.xml</descriptor>
+                            </descriptors>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>native-dist</id>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>single</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
diff --git a/oap-graalvm-native/src/main/assembly/native-distribution.xml 
b/oap-graalvm-native/src/main/assembly/native-distribution.xml
new file mode 100644
index 0000000..0eefddd
--- /dev/null
+++ b/oap-graalvm-native/src/main/assembly/native-distribution.xml
@@ -0,0 +1,86 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You 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
+  ~
+  ~     http://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.
+  -->
+
+<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0";
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0
+                              http://maven.apache.org/xsd/assembly-2.2.0.xsd";>
+    <id>native-dist</id>
+    <formats>
+        <format>dir</format>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>true</includeBaseDirectory>
+    <baseDirectory>oap-native</baseDirectory>
+
+    <fileSets>
+        <!-- Native binary -->
+        <fileSet>
+            <directory>${project.build.directory}</directory>
+            <outputDirectory>.</outputDirectory>
+            <includes>
+                <include>oap-server</include>
+            </includes>
+            <fileMode>0755</fileMode>
+        </fileSet>
+        <!-- config/ — application.yml -->
+        <fileSet>
+            
<directory>${project.basedir}/../oap-graalvm-server/src/main/resources</directory>
+            <outputDirectory>config</outputDirectory>
+            <includes>
+                <include>application.yml</include>
+            </includes>
+        </fileSet>
+        <!-- config/ — production configs from dist-material (same as upstream 
apm-dist) -->
+        <fileSet>
+            
<directory>${project.basedir}/../skywalking/dist-material</directory>
+            <outputDirectory>config</outputDirectory>
+            <includes>
+                <include>log4j2.xml</include>
+                <include>alarm-settings.yml</include>
+            </includes>
+        </fileSet>
+        <!-- config/ — upstream resource files loaded at runtime.
+             Same set as JVM distro: BanyanDB config, UI templates, rules, 
etc. -->
+        <fileSet>
+            
<directory>${project.basedir}/../skywalking/oap-server/server-starter/src/main/resources</directory>
+            <outputDirectory>config</outputDirectory>
+            <includes>
+                <include>bydb.yml</include>
+                <include>bydb-topn.yml</include>
+                <include>ui-initialized-templates/**</include>
+                <include>cilium-rules/**</include>
+                <include>openapi-definitions/**</include>
+                <include>component-libraries.yml</include>
+                <include>endpoint-name-grouping.yml</include>
+                <include>gateways.yml</include>
+                <include>hierarchy-definition.yml</include>
+                <include>metadata-service-mapping.yaml</include>
+                <include>service-apdex-threshold.yml</include>
+                <include>trace-sampling-policy-settings.yml</include>
+            </includes>
+        </fileSet>
+        <!-- logs/ — empty directory for runtime logs -->
+        <fileSet>
+            <directory>.</directory>
+            <outputDirectory>logs</outputDirectory>
+            <excludes>
+                <exclude>**/*</exclude>
+            </excludes>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git 
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/FieldsHelper.java
 
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/FieldsHelper.java
index b9db45c..b0fb2b0 100644
--- 
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/FieldsHelper.java
+++ 
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/FieldsHelper.java
@@ -47,7 +47,7 @@ import java.util.stream.Collectors;
  *
  * <p>Upstream uses {@code LambdaMetafactory.metafactory()} to create setter
  * wrappers at runtime, which fails in GraalVM native images (cannot define
- * classes at runtime). This replacement uses {@link MethodHandle#invoke()}
+ * classes at runtime). This replacement uses {@link MethodHandle}
  * directly, which is supported by GraalVM.
  */
 @Slf4j

Reply via email to