mirror of
https://github.com/Quad4-Software/MeshChatX.git
synced 2026-08-18 09:49:09 -04:00
179 lines
6 KiB
Bash
Executable file
179 lines
6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Build wheel, Linux AppImage/deb (x64 + arm64), optional RPM/APK, frontend zip, and SBOM under ./release-assets/.
|
|
# Expects repo root as cwd, dependencies installed (task install / pnpm), and meshchatx/public populated when building Electron.
|
|
# Optional: SKIP_WHEEL=1, SKIP_ELECTRON=1, TRIVY_SBOM=0
|
|
# Optional: MESHCHATX_LINUX_FORMATS = comma list of appimage,deb,rpm,apk (default: all four)
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
cd "$ROOT"
|
|
|
|
# shellcheck source=scripts/ci/ci-node-path.sh
|
|
. "$(dirname "$0")/ci-node-path.sh"
|
|
|
|
require_node_min() {
|
|
_min_major="${1:-22}"
|
|
_ver="$(node -v 2>/dev/null || true)"
|
|
_major="${_ver#v}"
|
|
_major="${_major%%.*}"
|
|
if [ -z "$_major" ] || [ "$_major" -lt "$_min_major" ]; then
|
|
echo "Node.js ${_min_major}+ required (got: ${_ver:-unknown}); check PATH does not prefer /usr/local/bin over setup-node." >&2
|
|
command -v node >&2 || true
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
require_node_min 24
|
|
|
|
mkdir -p release-assets
|
|
|
|
HOST_ARCH="$(uname -m)"
|
|
case "$HOST_ARCH" in
|
|
x86_64) NATIVE_ARCH="x64" ;;
|
|
aarch64|arm64) NATIVE_ARCH="arm64" ;;
|
|
*) NATIVE_ARCH="$HOST_ARCH" ;;
|
|
esac
|
|
|
|
LINUX_FORMATS="${MESHCHATX_LINUX_FORMATS:-all}"
|
|
if [ "$LINUX_FORMATS" = "all" ]; then
|
|
LINUX_FORMATS="appimage,deb,rpm,apk"
|
|
fi
|
|
|
|
has_format() {
|
|
case ",$LINUX_FORMATS," in
|
|
*",$1,"*) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
for _fmt in ${LINUX_FORMATS//,/ }; do
|
|
case "$_fmt" in
|
|
appimage|deb|rpm|apk) ;;
|
|
*)
|
|
echo "Unknown Linux package format '$_fmt' in MESHCHATX_LINUX_FORMATS (expected appimage, deb, rpm, apk, or all)" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
appimage_deb_targets=""
|
|
has_format appimage && appimage_deb_targets="$appimage_deb_targets AppImage"
|
|
has_format deb && appimage_deb_targets="$appimage_deb_targets deb"
|
|
appimage_deb_targets="${appimage_deb_targets# }"
|
|
|
|
if [ -n "${GITHUB_TOKEN:-}" ] && [ -z "${GH_TOKEN:-}" ]; then
|
|
export GH_TOKEN="$GITHUB_TOKEN"
|
|
fi
|
|
|
|
# Retry electron-builder when GitHub CDN drops the TLS stream (ECONNRESET).
|
|
# Freeze already finished. This only re-runs packaging.
|
|
run_electron_builder() {
|
|
_max="${ELECTRON_BUILDER_RETRIES:-5}"
|
|
_n=1
|
|
_delay=8
|
|
while true; do
|
|
_log="$(mktemp)"
|
|
set +e
|
|
pnpm exec electron-builder "$@" 2>&1 | tee "$_log"
|
|
_status="${PIPESTATUS[0]}"
|
|
set -e
|
|
if [ "$_status" -eq 0 ]; then
|
|
rm -f "$_log"
|
|
return 0
|
|
fi
|
|
if [ "$_n" -ge "$_max" ]; then
|
|
echo "electron-builder failed after ${_n} attempt(s)" >&2
|
|
rm -f "$_log"
|
|
return "$_status"
|
|
fi
|
|
if ! grep -Eqi 'ECONNRESET|ETIMEDOUT|ECONNREFUSED|ENOTFOUND|EPIPE|socket hang up|RequestError' "$_log"; then
|
|
rm -f "$_log"
|
|
return "$_status"
|
|
fi
|
|
echo "electron-builder hit a transient network error (attempt ${_n}/${_max}). Retrying in ${_delay}s." >&2
|
|
rm -f "$_log"
|
|
sleep "$_delay"
|
|
_n=$((_n + 1))
|
|
_delay=$((_delay * 2))
|
|
if [ "$_delay" -gt 60 ]; then
|
|
_delay=60
|
|
fi
|
|
done
|
|
}
|
|
|
|
if [ "${SKIP_WHEEL:-0}" != 1 ]; then
|
|
if [ "$NATIVE_ARCH" = "x64" ]; then
|
|
echo "Building Python wheel..."
|
|
task build:wheel
|
|
else
|
|
echo "Skipping wheel on $NATIVE_ARCH runner (pure-Python wheel built on x64)."
|
|
fi
|
|
else
|
|
echo "Skipping wheel (SKIP_WHEEL=1)."
|
|
fi
|
|
|
|
if [ "${SKIP_ELECTRON:-0}" != 1 ]; then
|
|
if [ -n "$appimage_deb_targets" ]; then
|
|
if has_format appimage; then
|
|
bash scripts/ci/github-warm-appimage-tools.sh
|
|
fi
|
|
pnpm run electron-postinstall
|
|
if [ "$NATIVE_ARCH" = "x64" ]; then
|
|
echo "Electron linux x64 ($appimage_deb_targets)..."
|
|
PLATFORM=linux ARCH=x64 pnpm run build
|
|
# shellcheck disable=SC2086
|
|
run_electron_builder --linux $appimage_deb_targets --x64 --publish=never
|
|
elif [ "$NATIVE_ARCH" = "arm64" ]; then
|
|
echo "Electron linux arm64 ($appimage_deb_targets)..."
|
|
PLATFORM=linux ARCH=arm64 pnpm run build
|
|
# shellcheck disable=SC2086
|
|
run_electron_builder --linux $appimage_deb_targets --arm64 --publish=never
|
|
fi
|
|
else
|
|
echo "Skipping AppImage/deb (not selected in MESHCHATX_LINUX_FORMATS)."
|
|
fi
|
|
|
|
if [ "$NATIVE_ARCH" = "x64" ]; then
|
|
if has_format rpm; then
|
|
echo "RPM (best-effort)..."
|
|
if ! task dist:fe:rpm; then
|
|
echo "RPM build failed or skipped; continuing." >&2
|
|
fi
|
|
fi
|
|
if has_format apk; then
|
|
echo "APK (best-effort)..."
|
|
if ! task dist:fe:apk; then
|
|
echo "APK build failed or skipped; continuing." >&2
|
|
fi
|
|
fi
|
|
elif has_format rpm || has_format apk; then
|
|
echo "Skipping RPM/APK on $NATIVE_ARCH runner (built on x64 only)." >&2
|
|
fi
|
|
else
|
|
echo "Skipping Electron packages (SKIP_ELECTRON=1)."
|
|
fi
|
|
|
|
echo "Collecting release files..."
|
|
find dist -maxdepth 1 -type f \( -name "*-linux*.AppImage" -o -name "*-linux*.deb" -o -name "*-linux*.rpm" -o -name "*-linux*.apk" \) -exec cp -f {} release-assets/ \; 2>/dev/null || true
|
|
find python-dist -maxdepth 1 -type f -name "*.whl" -exec cp -f {} release-assets/ \; 2>/dev/null || true
|
|
|
|
if [ -d meshchatx/public ] && [ "${SKIP_ELECTRON:-0}" != 1 ]; then
|
|
( cd meshchatx/public && zip -qr "${ROOT}/release-assets/meshchatx-frontend.zip" . )
|
|
fi
|
|
|
|
{
|
|
echo "## Integrity"
|
|
echo ""
|
|
echo "Each artifact may have a matching **\`*.cosign.bundle\`** when repository signing secrets are configured (see SECURITY.md)."
|
|
echo ""
|
|
echo "SBOM: **\`sbom.cyclonedx.json\`** (CycloneDX) when produced by CI."
|
|
} > release-body.md
|
|
|
|
if [ "${TRIVY_SBOM:-1}" != 0 ] && command -v trivy >/dev/null 2>&1; then
|
|
echo "Generating SBOM..."
|
|
trivy fs --format cyclonedx --include-dev-deps --output release-assets/sbom.cyclonedx.json .
|
|
else
|
|
echo "Skipping SBOM (trivy not on PATH or TRIVY_SBOM=0)." >&2
|
|
fi
|
|
|
|
echo "github-build-linux-release-assets.sh: done; see ./release-assets/"
|