#!/usr/bin/env bash # ========================================= # .FILE # deploy-native # # .SYNOPSIS # Build Serinity desktop artifacts (jar, native app-image, and installers). # # .DESCRIPTION # This script packages the desktop app from the project root. # It can generate: # - executable jar # - native app-image (via jpackage) # - installers (deb/rpm/dmg/pkg/exe/msi) # Installers depend on OS and local packaging tools. # # .PARAMETERS # -t, --type # Comma-separated artifact types: # jar, native (alias: app-image), deb, rpm (alias: rmp), dmg, pkg, exe, msi, all # -h, --help # Show usage information. # # .INPUTS # - Maven modules in this repository # - Runtime dependencies copied to app/target/dependency # - Optional .env.example copied into generated app-image # # .OUTPUTS # - app/target/native/serinity (app-image) # - app/target/dist/* (jar/installers) # # .REQUIREMENTS # - Java + jpackage available # - Maven installed # - For Linux installers: # deb -> dpkg-deb # rpm -> rpmbuild # # .NOTES # Version : 1.0 # Author : @ZouariOmar # Created : 14/03/2026 # Change Log : 1469c79 # # .EXAMPLES # ./deploy-native # ./deploy-native --type jar # ./deploy-native --type native,deb,rpm # PACKAGE_TYPES=all ./scripts/deploy-native # ========================================= set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT_DIR" # Configuration vars APP_NAME="serinity" OUT_DIR="app/target/native" DIST_DIR="app/target/dist" INPUT_DIR="app/target/dependency" APP_DIR="${OUT_DIR}/${APP_NAME}" usage() { cat <<'EOF' Usage: ./deploy-native [OPTIONS] Build and package serinity desktop artifacts. Options: -t, --type Comma-separated output types to generate. Supported values: jar, native (alias: app-image), deb, rpm (alias: rmp), dmg, pkg, exe, msi, all Examples: --type jar --type native,deb,rpm --type all -h, --help Show this help message. Notes: - "all" generates: jar + native app-image + OS-default installer types. - You can still use PACKAGE_TYPES env var (same values as --type). - Installer generation is OS/tool dependent (e.g. rpmbuild for rpm, dpkg-deb for deb). EOF } detect_default_installers() { case "$(uname -s)" in Linux*) echo "deb rpm" ;; Darwin*) echo "dmg pkg" ;; MINGW* | MSYS* | CYGWIN*) echo "exe msi" ;; *) echo "" ;; esac } normalize_type() { case "$1" in app-image) echo "native" ;; rmp) echo "rpm" ;; *) echo "$1" ;; esac } TARGETS_INPUT="" while [[ $# -gt 0 ]]; do case "$1" in -h | --help) usage exit 0 ;; -t | --type) [[ $# -lt 2 ]] && { echo "[deploy-native] Missing value for $1" >&2 exit 1 } TARGETS_INPUT="$2" shift 2 ;; --type=*) TARGETS_INPUT="${1#*=}" shift ;; *) echo "[deploy-native] Unknown option: $1" >&2 usage exit 1 ;; esac done if [[ -z "${TARGETS_INPUT}" && -n "${PACKAGE_TYPES:-}" ]]; then TARGETS_INPUT="${PACKAGE_TYPES}" fi if [[ -z "${TARGETS_INPUT}" ]]; then TARGETS_INPUT="all" fi TARGETS_INPUT="${TARGETS_INPUT//,/ }" REQUESTED_TARGETS=() for token in ${TARGETS_INPUT}; do t="$(normalize_type "${token,,}")" case "$t" in all | jar | native | deb | rpm | dmg | pkg | exe | msi) REQUESTED_TARGETS+=("$t") ;; *) echo "[deploy-native] Unsupported type: ${token}" >&2 usage exit 1 ;; esac done contains_target() { local needle="$1" shift local i for i in "$@"; do [[ "$i" == "$needle" ]] && return 0 done return 1 } EXPANDED_TARGETS=() if contains_target "all" "${REQUESTED_TARGETS[@]}"; then EXPANDED_TARGETS+=(jar native) for os_t in $(detect_default_installers); do EXPANDED_TARGETS+=("${os_t}") done else EXPANDED_TARGETS=("${REQUESTED_TARGETS[@]}") fi NEEDS_NATIVE=0 INSTALLER_TYPES=() for t in "${EXPANDED_TARGETS[@]}"; do case "$t" in native) NEEDS_NATIVE=1 ;; deb | rpm | dmg | pkg | exe | msi) NEEDS_NATIVE=1 INSTALLER_TYPES+=("$t") ;; esac done echo "[deploy-native] Building all modules (tests skipped) and collecting runtime deps..." mvn -pl app -am -Dmaven.test.skip=true package dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=target/dependency APP_JAR_PATH="$(ls app/target/app-*-all.jar 2>/dev/null | head -n1 || true)" if [[ -z "${APP_JAR_PATH}" || ! -f "${APP_JAR_PATH}" ]]; then APP_JAR_PATH="$(ls app/target/app-*.jar | grep -v -- '-all\.jar$' | head -n1 || true)" fi if [[ -z "${APP_JAR_PATH}" || ! -f "${APP_JAR_PATH}" ]]; then echo "[deploy-native] Could not find app jar in app/target (expected fat jar app-*-all.jar)" >&2 exit 1 fi APP_JAR="$(basename "${APP_JAR_PATH}")" mkdir -p "${DIST_DIR}" echo "[deploy-native] Ensuring app and OpenCV jars are included in package input..." cp -f "${APP_JAR_PATH}" "${INPUT_DIR}/" cp -f "access-control/lib/opencv-4130.jar" "${INPUT_DIR}/" if contains_target "jar" "${EXPANDED_TARGETS[@]}"; then rm -f "${DIST_DIR}"/app-*.jar cp -f "${APP_JAR_PATH}" "${DIST_DIR}/${APP_JAR}" fi if [[ "${NEEDS_NATIVE}" -eq 1 ]]; then echo "[deploy-native] Creating app-image..." rm -rf "${APP_DIR}" jpackage \ --name "${APP_NAME}" \ --input "${INPUT_DIR}" \ --main-jar "${APP_JAR}" \ --main-class com.serinity.app.Launcher \ --type app-image \ --dest "${OUT_DIR}" \ --java-options "--enable-native-access=ALL-UNNAMED" if [[ -f ".env.example" ]]; then cp -f ".env.example" "${APP_DIR}/.env.example" fi cat >"${APP_DIR}/serinity" <<'RUNNER' #!/usr/bin/env bash set -euo pipefail APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$APP_DIR" if [[ ! -f ".env" ]]; then echo "[serinity] Missing .env in $APP_DIR" echo "[serinity] Create it from .env.example before launching." exit 1 fi set -a source "$APP_DIR/.env" set +a export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS:-} -Dserinity.env.dir=$APP_DIR" exec "$APP_DIR/bin/serinity" "$@" RUNNER chmod +x "${APP_DIR}/serinity" fi for TYPE in "${INSTALLER_TYPES[@]}"; do if [[ "${TYPE}" == "rpm" ]] && ! command -v rpmbuild >/dev/null 2>&1; then echo "[deploy-native] Skipping rpm: rpmbuild is not installed" continue fi if [[ "${TYPE}" == "deb" ]] && ! command -v dpkg-deb >/dev/null 2>&1; then echo "[deploy-native] Skipping deb: dpkg-deb is not installed" continue fi echo "[deploy-native] Creating ${TYPE} installer..." if [[ "$(uname -s)" == "Linux" ]]; then jpackage --name "${APP_NAME}" --type "${TYPE}" --app-image "${APP_DIR}" --dest "${DIST_DIR}" --linux-package-name serinity else jpackage --name "${APP_NAME}" --type "${TYPE}" --app-image "${APP_DIR}" --dest "${DIST_DIR}" fi done echo "[deploy-native] Done." if [[ "${NEEDS_NATIVE}" -eq 1 ]]; then echo "[deploy-native] App image: ${APP_DIR}" fi if contains_target "jar" "${EXPANDED_TARGETS[@]}"; then echo "[deploy-native] Jar: ${DIST_DIR}/${APP_JAR}" fi echo "[deploy-native] Installers output: ${DIST_DIR}" find "${DIST_DIR}" -maxdepth 1 -type f | sort