mirror of
https://github.com/storytold/craft-launcher.git
synced 2026-11-14 22:25:05 +00:00
* Add Linux riscv64 release build and switch runners to Ubuntu 26.04 - release.yml: new linux-riscv64 job cross-compiled on ubuntu-26.04 against ports.ubuntu.com riscv64 libs, tar.gz only, artcraft-launcher --version smoke-tested under QEMU. Updated flatpak runner matrix to ubuntu-26.04. Draft-release job now requires linux-riscv64 and checks the tarball. - packaging/linux/package.sh: CROSS_ARCH / CROSS_TARGET / CROSS_COMPILE / EMULATOR support. - platform.rs: add Arch::Riscv64 variant, map linux-riscv64 token, and prioritize tarball format for riscv64 on Linux. - web.rs: detect riscv64 architecture in visitor user agent. - README and AGENTS.md: document the riscv64 tarball. * linux: build deb and rpm packages for riscv64 * ci: configure actionlint to recognize ubuntu-26.04 runner labels * Keep riscv64 and Flatpak release jobs on Ubuntu 24.04 24.04 is what PhotoCraft's linux-riscv64 job uses, so the riscv64 binaries need glibc 2.39 (as the README says) rather than 26.04's newer glibc, and the release pipeline keeps runner images it has already proven on. Drop the actionlint label config that 26.04 needed, revert the default_kinds and download_kinds matches to match on the OS alone, simplify the riscv UA check, and rustfmt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
158 lines
7.2 KiB
Bash
Executable File
158 lines
7.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Build and package ArtCraft Launcher for Linux (<arch> is x86_64, aarch64 or riscv64):
|
|
#
|
|
# $DIST/artcraft-launcher-<version>-linux-<arch>.AppImage any distro with glibc >= the build host's
|
|
# $DIST/artcraft-launcher-<version>-linux-<arch>.AppImage.zsync delta updates (needs zsyncmake)
|
|
# $DIST/artcraft-launcher-<version>-linux-<arch>.deb Debian, Ubuntu, Mint, Pop!_OS, ...
|
|
# $DIST/artcraft-launcher-<version>-linux-<arch>.rpm Fedora, openSUSE, RHEL, ...
|
|
# $DIST/artcraft-launcher-<version>-linux-<arch>.tar.gz plain FHS-style tree (bin/, share/)
|
|
#
|
|
# Usage: packaging/linux/package.sh [--skip-build] [--formats "appimage deb rpm tar"]
|
|
#
|
|
# Needs: cargo; nfpm for deb/rpm (https://nfpm.goreleaser.com); appimagetool for the AppImage
|
|
# (downloaded into $CARGO_TARGET_DIR if missing). Build on an old distro (CI: Ubuntu 22.04,
|
|
# glibc 2.35) so the binaries run on newer ones. Optional: desktop-file-validate, appstreamcli,
|
|
# zsyncmake (the zsync package) for the AppImage's .zsync.
|
|
#
|
|
# Cross builds (CI: riscv64, deb/rpm/tar.gz): set CROSS_ARCH (riscv64), CROSS_TARGET (the Rust
|
|
# triple), CROSS_COMPILE (binutils prefix, for strip) and optionally EMULATOR (e.g. qemu-riscv64)
|
|
# to smoke-test the CLI.
|
|
set -euo pipefail
|
|
# shellcheck source=../env.sh
|
|
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
|
|
HERE="$ROOT/packaging/linux"
|
|
APP_ID=ai.storyteller.artcraft-launcher
|
|
PKG=artcraft-launcher
|
|
|
|
SKIP_BUILD=0
|
|
FORMATS="appimage deb rpm tar"
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--skip-build) SKIP_BUILD=1; shift ;;
|
|
--formats) FORMATS="$2"; shift 2 ;;
|
|
-h | --help) sed -n '2,19p' "$0"; exit 0 ;;
|
|
*) echo "unknown argument: $1" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
ARCH="${CROSS_ARCH:-$(uname -m)}"
|
|
case "$ARCH" in
|
|
riscv64) DEB_ARCH=riscv64 ;;
|
|
x86_64) DEB_ARCH=amd64 ;;
|
|
aarch64 | arm64) ARCH=aarch64; DEB_ARCH=arm64 ;;
|
|
*) echo "unsupported architecture $ARCH" >&2; exit 2 ;;
|
|
esac
|
|
export ARTCRAFT_LAUNCHER_MAINTAINER="${ARTCRAFT_LAUNCHER_MAINTAINER:-ArtCraft Launcher maintainers <craft-launcher@storyteller.ai>}"
|
|
BASENAME="$PKG-$VERSION-linux-$ARCH"
|
|
|
|
echo "==> ArtCraft Launcher $VERSION for Linux $ARCH ($FORMATS)"
|
|
|
|
if [ "$SKIP_BUILD" = 0 ]; then
|
|
if [ -n "${CROSS_TARGET:-}" ]; then
|
|
(cd "$ROOT" && cargo build --release --locked -p "$PKG" --target "$CROSS_TARGET")
|
|
else
|
|
(cd "$ROOT" && cargo build --release --locked -p "$PKG")
|
|
fi
|
|
fi
|
|
BIN="$CARGO_TARGET_DIR/${CROSS_TARGET:+$CROSS_TARGET/}release"
|
|
WORK="$CARGO_TARGET_DIR/linux-package"
|
|
STAGE="$WORK/root"
|
|
rm -rf "$WORK"
|
|
|
|
# ---- stage an FHS tree (shared by every format) -------------------------------------------------
|
|
install -Dm755 "$BIN/$PKG" "$STAGE/usr/bin/$PKG"
|
|
"${CROSS_COMPILE:-}strip" "$STAGE/usr/bin/$PKG" 2>/dev/null || true
|
|
install -Dm644 "$HERE/$APP_ID.desktop" "$STAGE/usr/share/applications/$APP_ID.desktop"
|
|
mkdir -p "$STAGE/usr/share/metainfo"
|
|
sed -e "s/@VERSION@/$VERSION/g" -e "s/@DATE@/$ARTCRAFT_LAUNCHER_BUILD_DATE/g" \
|
|
"$HERE/$APP_ID.metainfo.xml.in" >"$STAGE/usr/share/metainfo/$APP_ID.metainfo.xml"
|
|
mkdir -p "$STAGE/usr/share/icons"
|
|
cp -R "$ROOT/assets/app-icon/hicolor" "$STAGE/usr/share/icons/"
|
|
mkdir -p "$STAGE/usr/share/doc/$PKG"
|
|
copy_docs "$STAGE/usr/share/doc/$PKG"
|
|
|
|
if command -v desktop-file-validate >/dev/null; then
|
|
desktop-file-validate "$STAGE/usr/share/applications/$APP_ID.desktop"
|
|
fi
|
|
if command -v appstreamcli >/dev/null; then
|
|
appstreamcli validate --no-net --explain "$STAGE/usr/share/metainfo/$APP_ID.metainfo.xml"
|
|
fi
|
|
|
|
has() { case " $FORMATS " in *" $1 "*) return 0 ;; *) return 1 ;; esac; }
|
|
|
|
# ---- .tar.gz ------------------------------------------------------------------------------------
|
|
if has tar; then
|
|
mkdir -p "$WORK/tar"
|
|
cp -R "$STAGE/usr" "$WORK/tar/$BASENAME"
|
|
tar -C "$WORK/tar" -czf "$DIST/$BASENAME.tar.gz" "$BASENAME"
|
|
echo "wrote $DIST/$BASENAME.tar.gz"
|
|
fi
|
|
|
|
# ---- .deb / .rpm --------------------------------------------------------------------------------
|
|
if has deb || has rpm; then
|
|
command -v nfpm >/dev/null || { echo "error: nfpm not found (https://nfpm.goreleaser.com/install/)" >&2; exit 1; }
|
|
export VERSION
|
|
export NFPM_ARCH="$DEB_ARCH"
|
|
# nfpm expands env vars in fields like `version` and `arch`, but not in `contents[].src`.
|
|
sed "s|\${STAGE}|$STAGE|g" "$HERE/nfpm.yaml" >"$WORK/nfpm.yaml"
|
|
for fmt in deb rpm; do
|
|
if has "$fmt"; then (cd "$ROOT" && nfpm package -f "$WORK/nfpm.yaml" -p "$fmt" -t "$DIST/$BASENAME.$fmt"); fi
|
|
done
|
|
fi
|
|
|
|
# ---- AppImage -----------------------------------------------------------------------------------
|
|
if has appimage; then
|
|
APPDIR="$WORK/ArtCraftLauncher.AppDir"
|
|
cp -R "$STAGE" "$APPDIR"
|
|
mv "$APPDIR/usr/share/doc" "$WORK/doc-unused"
|
|
# AppRun is a script, not a symlink: it installs the .desktop entry and icons into
|
|
# $XDG_DATA_HOME before launching, so Wayland compositors can resolve the window's
|
|
# app_id to our icon instead of the generic Wayland logo (opt-out env in the
|
|
# script header). Logic is covered by packaging/linux/apprun-test.sh.
|
|
install -Dm755 "$HERE/AppRun" "$APPDIR/AppRun"
|
|
cp "$HERE/$APP_ID.desktop" "$APPDIR/$APP_ID.desktop"
|
|
cp "$ROOT/assets/app-icon/hicolor/256x256/apps/$APP_ID.png" "$APPDIR/$APP_ID.png"
|
|
ln -s "$APP_ID.png" "$APPDIR/.DirIcon"
|
|
|
|
TOOL="${APPIMAGETOOL:-$(command -v appimagetool || true)}"
|
|
if [ -z "$TOOL" ]; then
|
|
TOOL="$CARGO_TARGET_DIR/appimagetool-$ARCH.AppImage"
|
|
if [ ! -x "$TOOL" ]; then
|
|
curl -fsSL -o "$TOOL" "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$ARCH.AppImage"
|
|
chmod +x "$TOOL"
|
|
fi
|
|
fi
|
|
# Absolute, because appimagetool runs in $DIST below (CARGO_TARGET_DIR or APPIMAGETOOL may be
|
|
# relative, e.g. target/agent-<name>).
|
|
OUT="$(cd "$DIST" && pwd)/$BASENAME.AppImage"
|
|
APPDIR="$(cd "$APPDIR" && pwd)"
|
|
TOOL="$(cd "$(dirname "$TOOL")" && pwd)/$(basename "$TOOL")"
|
|
# A .zsync left by an earlier run would hide a missing zsyncmake and describe another file.
|
|
rm -f "$OUT.zsync"
|
|
# Update information: AppImageUpdate, AppImageLauncher and the like read it from the
|
|
# file and fetch only the blocks that changed in a newer release, through the .zsync published
|
|
# next to each AppImage on GitHub Releases. `latest` is the newest published release that is
|
|
# not a pre-release. A fork's builds point at its own releases through GITHUB_REPOSITORY.
|
|
# The repo is craft-launcher while the files are artcraft-launcher-*.
|
|
REPO="${GITHUB_REPOSITORY:-storytold/craft-launcher}"
|
|
UPDATE_INFO="gh-releases-zsync|${REPO%%/*}|${REPO#*/}|latest|$PKG-*-linux-$ARCH.AppImage.zsync"
|
|
# Extract-and-run: works without FUSE (containers, CI). The output embeds the static runtime,
|
|
# so users don't need libfuse2 either. With zsyncmake on the host (CI installs the zsync
|
|
# package) appimagetool also writes the .zsync, into its working directory, hence the cd.
|
|
(cd "$DIST" && ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "$TOOL" --no-appstream -u "$UPDATE_INFO" "$APPDIR" "$OUT")
|
|
echo "wrote $OUT"
|
|
if [ -s "$OUT.zsync" ]; then
|
|
echo "wrote $OUT.zsync"
|
|
else
|
|
warn "zsyncmake not found, so $OUT.zsync was not written; AppImage delta updates need it"
|
|
fi
|
|
fi
|
|
|
|
if [ -z "${CROSS_TARGET:-}" ]; then
|
|
"$STAGE/usr/bin/$PKG" --version
|
|
elif [ -n "${EMULATOR:-}" ]; then
|
|
"$EMULATOR" "$STAGE/usr/bin/$PKG" --version
|
|
fi
|
|
echo "==> done"
|
|
ls -lh "$DIST"
|