Build Spring Native Maven #6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Build specialized Spring Boot nmvn native images (nmvn-spring-<bootVersion>) per platform. | |
| # | |
| # Same commands as local. Scripts write under build/ by default: | |
| # build/catalogs/ — catalogs | |
| # build/work/ — scratch | |
| # build/nmvn-spring-* — images | |
| # Maven dist stays in apache-maven/target/. | |
| # | |
| # Toolchain: download GraalVM CE 25.2.4, set JAVA_HOME (+ bin on PATH). Finding native-image | |
| # (including Windows native-image.cmd) and Crema checks live in build-nmvn-prebuilt.sh. | |
| # | |
| # Per platform, for Boot 4.1.0 and 4.0.7: | |
| # resolve_boot_catalog.py → build-nmvn-catalog.sh → zip to dist/ | |
| # | |
| name: Build Spring Native Maven | |
| on: | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: {} | |
| env: | |
| # https://github.com/graalvm/graalvm-ce-builds/releases/tag/graal-25.2.4 | |
| GRAAL_TAG: graal-25.2.4 | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest-32-cores | |
| platform: linux-x86_64 | |
| graal_file: graalvm-community-jdk-25i2-25.0.4_linux-x64_bin.tar.gz | |
| - os: ubuntu-latest-32-cores-arm64 | |
| platform: linux-aarch64 | |
| graal_file: graalvm-community-jdk-25i2-25.0.4_linux-aarch64_bin.tar.gz | |
| - os: macos-arm64-cipool | |
| platform: macos-aarch64 | |
| graal_file: graalvm-community-jdk-25i2-25.0.4_macos-aarch64_bin.tar.gz | |
| - os: windows-latest-16-cores | |
| platform: windows-x86_64 | |
| graal_file: graalvm-community-jdk-25i2-25.0.4_windows-x64_bin.zip | |
| runs-on: ${{ matrix.os }} | |
| defaults: | |
| run: | |
| shell: bash | |
| permissions: | |
| contents: read | |
| env: | |
| BOOT_VERSIONS: "4.1.0 4.0.7" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Download and install GraalVM 25.2 | |
| run: | | |
| set -euo pipefail | |
| GRAAL_URL="https://github.com/graalvm/graalvm-ce-builds/releases/download/${GRAAL_TAG}/${{ matrix.graal_file }}" | |
| INSTALL_ROOT="${RUNNER_TEMP:-/tmp}/graalvm-25.2" | |
| ARCHIVE="${RUNNER_TEMP:-/tmp}/${{ matrix.graal_file }}" | |
| echo ">>> Downloading ${GRAAL_URL}" | |
| rm -rf "${INSTALL_ROOT}" | |
| mkdir -p "${INSTALL_ROOT}" | |
| curl -fsSL "${GRAAL_URL}" -o "${ARCHIVE}" | |
| case "${{ matrix.graal_file }}" in | |
| *.zip) | |
| if command -v unzip >/dev/null 2>&1; then | |
| unzip -q "${ARCHIVE}" -d "${INSTALL_ROOT}" | |
| else | |
| pwsh -NoProfile -Command "Expand-Archive -Path '${ARCHIVE}' -DestinationPath '${INSTALL_ROOT}' -Force" | |
| fi | |
| ;; | |
| *) | |
| tar -xzf "${ARCHIVE}" -C "${INSTALL_ROOT}" | |
| ;; | |
| esac | |
| # Locate JAVA_HOME (macOS: Contents/Home; Linux/Windows: unpacked root). | |
| JAVA_HOME_CANDIDATE="" | |
| for d in "${INSTALL_ROOT}"/*/Contents/Home "${INSTALL_ROOT}"/*/*/Contents/Home; do | |
| if [ -f "${d}/bin/native-image" ] || [ -f "${d}/bin/native-image.cmd" ] || [ -f "${d}/bin/native-image.exe" ]; then | |
| JAVA_HOME_CANDIDATE="$d" | |
| break | |
| fi | |
| done | |
| if [ -z "${JAVA_HOME_CANDIDATE}" ]; then | |
| for d in "${INSTALL_ROOT}"/*; do | |
| if [ -d "$d" ] && { [ -f "${d}/bin/native-image" ] || [ -f "${d}/bin/native-image.cmd" ] || [ -f "${d}/bin/native-image.exe" ]; }; then | |
| JAVA_HOME_CANDIDATE="$d" | |
| break | |
| fi | |
| done | |
| fi | |
| if [ -z "${JAVA_HOME_CANDIDATE}" ]; then | |
| echo "::error::Could not find native-image under ${INSTALL_ROOT}" | |
| find "${INSTALL_ROOT}" -maxdepth 5 -type f \( -name 'native-image' -o -name 'native-image.cmd' -o -name 'native-image.exe' \) 2>/dev/null | head -20 || true | |
| exit 1 | |
| fi | |
| # Git Bash on Windows: store Unix-style JAVA_HOME for later bash steps. | |
| if command -v cygpath >/dev/null 2>&1; then | |
| JAVA_HOME_CANDIDATE="$(cygpath -u "${JAVA_HOME_CANDIDATE}")" | |
| fi | |
| # Subsequent steps inherit these (GITHUB_ENV / GITHUB_PATH). | |
| echo "JAVA_HOME=${JAVA_HOME_CANDIDATE}" >> "$GITHUB_ENV" | |
| echo "${JAVA_HOME_CANDIDATE}/bin" >> "$GITHUB_PATH" | |
| echo ">>> JAVA_HOME=${JAVA_HOME_CANDIDATE}" | |
| - name: Strip SNAPSHOT from versions | |
| run: LC_ALL=C find . -name 'pom.xml' -exec sed -i'' -e 's/-SNAPSHOT//g' {} + | |
| - name: Build Maven distribution | |
| run: | | |
| chmod +x ./mvnw | |
| ./mvnw clean package -B -DskipTests -Drat.skip=true -Dcheckstyle.skip=true | |
| - name: Resolve catalogs and build Spring specialized images | |
| run: | | |
| set -euo pipefail | |
| chmod +x catalog/resolve_boot_catalog.py build-nmvn-catalog.sh build-nmvn-prebuilt.sh | |
| # Fresh build tree (same layout as local defaults). | |
| rm -rf build dist | |
| mkdir -p dist | |
| package_zip() { | |
| local zip_name="$1" | |
| shift | |
| if command -v zip >/dev/null 2>&1; then | |
| zip -j "${zip_name}" "$@" | |
| else | |
| pwsh -NoProfile -Command \ | |
| "Compress-Archive -Path @($(printf "'%s'," "$@" | sed 's/,$//')) -DestinationPath '${zip_name}' -Force" | |
| fi | |
| } | |
| for BOOT in $BOOT_VERSIONS; do | |
| CATALOG="build/catalogs/nmvn-spring-${BOOT}.json" | |
| echo "==========================================" | |
| echo ">>> Boot ${BOOT}" | |
| echo "==========================================" | |
| ./catalog/resolve_boot_catalog.py \ | |
| --boot-version "${BOOT}" \ | |
| --language java | |
| ./build-nmvn-catalog.sh "${CATALOG}" | |
| BIN="build/nmvn-spring-${BOOT}" | |
| if [ -f "${BIN}.exe" ]; then | |
| BIN="${BIN}.exe" | |
| fi | |
| if [ ! -f "${BIN}" ]; then | |
| echo "::error::Expected binary ${BIN} after build for Boot ${BOOT}" | |
| ls -la build/ || true | |
| exit 1 | |
| fi | |
| PLUGINS="build/nmvn-spring-${BOOT}.plugins" | |
| ZIP="nmvn-spring-${BOOT}-${{ matrix.platform }}-${{ github.sha }}.zip" | |
| package_zip "dist/${ZIP}" "${BIN}" "${PLUGINS}" | |
| echo ">>> Packaged dist/${ZIP}" | |
| done | |
| ls -la dist/ | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: nmvn-spring-${{ matrix.platform }} | |
| path: dist/*.zip | |
| if-no-files-found: error | |
| - name: Clean workspace outputs | |
| if: always() | |
| run: rm -rf build dist | |
| publish: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name == 'workflow_dispatch' }} | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| merge-multiple: true | |
| path: artifacts | |
| - name: List artifacts | |
| run: find artifacts -type f | sort | |
| - name: Publish to R2 | |
| uses: elide-tools/r2-upload-action@main | |
| with: | |
| path: artifacts | |
| target: native-maven | |
| bucket: elide-userdata-public | |
| account-id: ${{ secrets.R2_ACCOUNT_ID }} | |
| access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} | |
| secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} | |
| - name: Clean downloaded artifacts | |
| if: always() | |
| run: rm -rf artifacts |