Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 107 additions & 32 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -470,24 +470,22 @@ jobs:
include:
- target: x86_64-unknown-linux-gnu
arch: x64
sharun_arch: x86_64
runs-on: ubuntu-24.04
- target: aarch64-unknown-linux-gnu
arch: arm64
sharun_arch: aarch64
runs-on: ubuntu-24.04-arm
env:
# Pinned to commit 2affcd6 of pkgforge-dev/Anylinux-AppImages
# (latest commit touching quick-sharun.sh / get-debloated-pkgs.sh)
ANYLINUX_REF: 2affcd69e3b3fccab4507dbdbaed5d1a04bedfa9
# Pinned appimagetool release; quick-sharun honours APPIMAGETOOL_LINK.
APPIMAGETOOL_VERSION: "0.3.0"
# anylinux.c moved out of Anylinux-AppImages into its own repo on
# 2026-09-10 (Anylinux-sharun commit a84aa4b, "move and build helper
# libraries to this repository"). quick-sharun.sh at the ref above still
# defaults to the old `refs/heads/main` path, which now 404s -- so point
# it at the new home, pinned to a release tag rather than a branch.
ANYLINUX_SHARUN_VERSION: "3.2.1"
# quick-sharun + get-debloated-pkgs come from Anylinux-AppImages, tracking
# main rather than a pinned commit. Upstream moved anylinux.c out to its own
# repo (Anylinux-sharun) on 2026-09-10, and the commit we used to pin here
# still fetched it from the old refs/heads/main path -- which 404s, so the
# script's five silent retries could never succeed ("Failed to download 5
# times!"). Current quick-sharun does not build the helper libs at all: it
# pulls them prebuilt from an Anylinux-sharun release, and sha256-pins that
# tarball (and appimagetool) inside the script itself, so tracking main keeps
# the script and everything it downloads in step. Set this to a commit SHA if
# a future upstream change ever needs to be held back.
ANYLINUX_REF: refs/heads/main
# See build-windows: keep APP_VERSION consistent across Test and Build.
RELEASE_VERSION: ${{ needs.generate-version.outputs.version }}
steps:
Expand Down Expand Up @@ -594,17 +592,15 @@ jobs:
export OUTPATH="$PWD/dist"
export OUTNAME="$OUT"
export VERSION
# Pin appimagetool (quick-sharun downloads via this URL).
export APPIMAGETOOL_LINK="https://github.com/pkgforge-dev/appimagetool/releases/download/${APPIMAGETOOL_VERSION}/appimagetool-${{ matrix.sharun_arch }}-linux"
# anylinux.c now lives in Anylinux-sharun (see the env note). The
# script's default still points at the old repo's main branch, which
# 404s -- and its five retries just repeat a request that cannot
# succeed ("Failed to download 5 times!"), which reads like a network
# blip rather than a moved file.
export ANYLINUX_LIB_SOURCE="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-sharun/${ANYLINUX_SHARUN_VERSION}/lib/anylinux.c"
curl -fsI "$ANYLINUX_LIB_SOURCE" >/dev/null \
|| { echo "::error::anylinux.c unreachable at Anylinux-sharun ${ANYLINUX_SHARUN_VERSION}; upstream may have moved it again"; exit 1; }
# GITHUB_REPOSITORY is set by Actions; appimagetool auto-emits zsync.
# appimagetool is deliberately NOT overridden here: quick-sharun
# sha256-checks it against the version it ships with, so pointing
# APPIMAGETOOL_LINK elsewhere fails that check. Same for the sharun
# helper-libs tarball (which is where anylinux.so now comes from).
# OUTNAME/VERSION/OUTPATH are still read by appimagetool, so the
# artifact name below is unchanged.
# Explicit UPINFO: the guessed default matches *x86_64.AppImage.zsync,
# never our -x64-<ver> names. Setting it also emits the .zsync.
export UPINFO="gh-releases-zsync|${GITHUB_REPOSITORY%/*}|${GITHUB_REPOSITORY#*/}|latest|Rusty-Backup-linux-${{ matrix.arch }}-*.AppImage.zsync"

mkdir -p "$OUTPATH"
./quick-sharun /usr/bin/rusty-backup
Expand Down Expand Up @@ -763,8 +759,9 @@ jobs:

- name: Build Debian package
run: |
cargo deb --target ${{ matrix.target }} --no-build
mv target/${{ matrix.target }}/debian/*.deb Rusty-Backup-linux-${{ matrix.arch }}-${{ needs.generate-version.outputs.version }}.deb
# -o: cargo-deb only mirrors into target/<triple>/debian as a deprecated back-compat copy.
cargo deb --target ${{ matrix.target }} --no-build \
-o Rusty-Backup-linux-${{ matrix.arch }}-${{ needs.generate-version.outputs.version }}.deb

- name: Build RPM package
run: |
Expand Down Expand Up @@ -1229,10 +1226,11 @@ jobs:
# cross-compiled on x64. There is no GitHub-hosted riscv64 runner, so unlike
# the x64/arm64 AppImage jobs this can't build/package natively: we cross-link
# the default feature set (GUI + CHD + optical) against a riscv64 GTK/GL sysroot
# pulled in via dpkg multiarch (ubuntu-ports), then ship a plain dynamically-
# linked tarball — NOT a self-contained AppImage; it uses the user's system
# GTK3 at runtime. libchdman-rs 0.288.10 publishes the riscv64gc prebuilt that
# makes the CHD core link. continue-on-error: best-effort, can't block release.
# pulled in via dpkg multiarch (ubuntu-ports), then ship a .deb, .rpm and plain
# tarball, all dynamically linked — NOT a self-contained AppImage; they use the
# user's system GTK3 at runtime. libchdman-rs 0.288.10 publishes the riscv64gc
# prebuilt that makes the CHD core link. continue-on-error: best-effort, can't
# block release.
build-gui-linux-riscv64:
name: Build Linux RISC-V 64 GUI (rusty-backup)
# Skipped only when a manual run unticks "desktop"; every push builds it.
Expand Down Expand Up @@ -1401,6 +1399,82 @@ jobs:
name: Rusty-Backup-linux-riscv64-${{ needs.generate-version.outputs.version }}
path: Rusty-Backup-linux-riscv64-${{ needs.generate-version.outputs.version }}.tar.gz

- name: Install cargo packaging tools
# Host tools, so drop the job's riscv64 pkg-config env or any -sys crate
# they build would link against the riscv64 sysroot.
run: |
sudo apt-get install -y dpkg-dev rpm
for crate in cargo-deb cargo-generate-rpm; do
for attempt in 1 2 3; do
if env -u PKG_CONFIG_LIBDIR -u PKG_CONFIG_SYSROOT_DIR -u PKG_CONFIG_ALLOW_CROSS \
cargo install --locked "$crate"; then
continue 2
fi
echo "Install of $crate failed (attempt $attempt/3)"
sleep 15
done
echo "::error::failed to install $crate after 3 attempts"
exit 1
done

# Same Cargo.toml metadata as the x64/arm64 packages; --target makes both
# tools read target/riscv64gc-unknown-linux-gnu/release/rusty-backup.
- name: Build Debian package
run: |
set -euo pipefail
DEB="Rusty-Backup-linux-riscv64-${{ needs.generate-version.outputs.version }}.deb"
# --no-strip: already stripped with the cross strip above; the host
# `strip` can't read a riscv64 ELF.
# -o: cargo-deb only mirrors into target/<triple>/debian as a deprecated back-compat copy.
cargo deb --target riscv64gc-unknown-linux-gnu --no-build --no-strip -o "$DEB"
dpkg-deb -f "$DEB" Package Version Architecture Depends
# $auto runs dpkg-shlibdeps against the :riscv64 multiarch packages.
# When it fails cargo-deb only warns and ships a .deb whose Depends is
# just the static list, so check the resolved deps actually landed.
[ "$(dpkg-deb -f "$DEB" Architecture)" = riscv64 ] \
|| { echo "::error::$DEB is not Architecture: riscv64"; exit 1; }
DEPENDS=$(dpkg-deb -f "$DEB" Depends)
case "$DEPENDS" in
*libc6*) ;;
*) echo "::error::\$auto deps did not resolve (no libc6 in Depends: $DEPENDS)"; exit 1 ;;
esac
case "$DEPENDS" in
*-cross*) echo "::error::Depends names a host cross-toolchain package: $DEPENDS"; exit 1 ;;
esac

- name: Build RPM package
run: |
set -euo pipefail
ELF=target/riscv64gc-unknown-linux-gnu/release/rusty-backup
RPM="Rusty-Backup-linux-riscv64-${{ needs.generate-version.outputs.version }}.rpm"
# Auto-requires runs the host ldd, which can't load a riscv64 ELF, so
# emit the same soname()(64bit) requires from the cross objdump instead.
# --set-metadata replaces the whole requires table: restate gtk3/openssl.
REQS=$(riscv64-linux-gnu-objdump -p "$ELF" \
| awk '$1 == "NEEDED" { printf "\"%s()(64bit)\" = \"*\", ", $2 }')
[ -n "$REQS" ] || { echo "::error::no NEEDED entries in $ELF"; exit 1; }
# The target triple's first segment is riscv64gc; RPM distros say riscv64.
cargo generate-rpm --target riscv64gc-unknown-linux-gnu --arch riscv64 \
--auto-req disabled \
--set-metadata "requires = { ${REQS}gtk3 = \"*\", openssl = \"*\" }"
mv target/riscv64gc-unknown-linux-gnu/generate-rpm/*.rpm "$RPM"
rpm -qp --qf '%{NAME} %{VERSION} %{ARCH}\n' "$RPM"
rpm -qp --requires "$RPM"
[ "$(rpm -qp --qf '%{ARCH}' "$RPM")" = riscv64 ] \
|| { echo "::error::$RPM is not arch riscv64"; exit 1; }

- name: Upload Debian package
uses: actions/upload-artifact@v7
with:
name: Rusty-Backup-linux-riscv64-${{ needs.generate-version.outputs.version }}-deb
path: Rusty-Backup-linux-riscv64-${{ needs.generate-version.outputs.version }}.deb

- name: Upload RPM package
uses: actions/upload-artifact@v7
with:
name: Rusty-Backup-linux-riscv64-${{ needs.generate-version.outputs.version }}-rpm
path: Rusty-Backup-linux-riscv64-${{ needs.generate-version.outputs.version }}.rpm

# Turn the `appliance` choice input into a JSON arch list for the matrix
# below. A manual dispatch honours none / i586 / i686 / both. A push to
# main/master builds both arches automatically (the full Buildroot build is
Expand Down Expand Up @@ -2221,6 +2295,7 @@ jobs:
"Rusty-Backup-linux-arm64-${VER}.AppImage" "Rusty-Backup-linux-arm64-${VER}.deb" \
"Rusty-Backup-linux-arm64-${VER}.rpm" "Rusty-Backup-linux-arm64-${VER}.pkg.tar.zst" \
"Rusty-Backup-windows-arm64-${VER}.zip" "Rusty-Backup-linux-riscv64-${VER}.tar.gz" \
"Rusty-Backup-linux-riscv64-${VER}.deb" "Rusty-Backup-linux-riscv64-${VER}.rpm" \
"rb-cli-windows-x64-${VER}.zip" "rb-cli-windows-x86-${VER}.zip" \
"rb-cli-macos-arm64-${VER}.zip" "rb-cli-macos-x64-${VER}.zip" \
"rb-cli-linux-x64-${VER}.tar.gz" "rb-cli-linux-arm64-${VER}.tar.gz" \
Expand Down Expand Up @@ -2254,10 +2329,10 @@ jobs:
| **macOS 10.13+** | Intel (x64) | [.dmg](${BASE}/Rusty-Backup-macos-x64-${VER}.dmg) | [rb-cli](${BASE}/rb-cli-macos-x64-${VER}.zip) |
| **Linux** (glibc >= 2.39) | x64 | [AppImage](${BASE}/Rusty-Backup-linux-x64-${VER}.AppImage) · [deb](${BASE}/Rusty-Backup-linux-x64-${VER}.deb) · [rpm](${BASE}/Rusty-Backup-linux-x64-${VER}.rpm) · [pkg](${BASE}/Rusty-Backup-linux-x64-${VER}.pkg.tar.zst) | [rb-cli](${BASE}/rb-cli-linux-x64-${VER}.tar.gz) |
| **Linux** (glibc >= 2.39) | arm64 | [AppImage](${BASE}/Rusty-Backup-linux-arm64-${VER}.AppImage) · [deb](${BASE}/Rusty-Backup-linux-arm64-${VER}.deb) · [rpm](${BASE}/Rusty-Backup-linux-arm64-${VER}.rpm) · [pkg](${BASE}/Rusty-Backup-linux-arm64-${VER}.pkg.tar.zst) | [rb-cli](${BASE}/rb-cli-linux-arm64-${VER}.tar.gz) |
| **Linux** (glibc >= 2.39) | RISC-V 64-bit (\`riscv64gc\`) | [tar.gz](${BASE}/Rusty-Backup-linux-riscv64-${VER}.tar.gz) | [rb-cli](${BASE}/rb-cli-linux-riscv64-${VER}.tar.gz) |
| **Linux** (glibc >= 2.39) | RISC-V 64-bit (\`riscv64gc\`) | [deb](${BASE}/Rusty-Backup-linux-riscv64-${VER}.deb) · [rpm](${BASE}/Rusty-Backup-linux-riscv64-${VER}.rpm) · [tar.gz](${BASE}/Rusty-Backup-linux-riscv64-${VER}.tar.gz) | [rb-cli](${BASE}/rb-cli-linux-riscv64-${VER}.tar.gz) |
| **MiSTer FPGA** (Cortex-A9, glibc 2.31) | armv7 hardfloat | _(GUI not built for this target)_ | [rb-cli-mini](${BASE}/rb-cli-mini-armv7-linux-${VER}.tar.gz) |

<sub>**Windows:** x86 = 32-bit (Windows 10, the last Windows with 32-bit support). · **macOS:** requires 10.13 High Sierra or later. · **Linux:** deb = Debian/Ubuntu, rpm = Fedora/RHEL/openSUSE, pkg = Arch/Manjaro; the packages and \`rb-cli\` are built against **glibc 2.39** (Ubuntu 24.04), while the **AppImage** is self-contained and runs on most distributions regardless of glibc. · **Windows ARM64 / RISC-V 64:** cross-compiled, build-only legs — the Windows ARM64 app is a portable zip and the RISC-V 64 app is a plain dynamically-linked tarball that uses your system GTK3 (not a self-contained AppImage like x64/arm64). · **MiSTer FPGA:** \`rb-cli-mini\` is a slim \`rb-cli\` cross-compiled for the MiSTer's armv7 hardfloat Intel Cyclone V SoC against Ubuntu 20.04 glibc 2.31 — same baseline as the MiSTer Buildroot rootfs and the upstream \`libchdman-rs\` armv7 prebuilt. The GUI is off; CHD, optical and the full-screen \`rb-cli tui\` terminal UI are in. Drop it onto the SD at \`/media/fat/Scripts/rb-cli\`. · Every **rb-cli** download contains a single \`rb-cli\` executable (\`rb-cli.exe\` on Windows).</sub>
<sub>**Windows:** x86 = 32-bit (Windows 10, the last Windows with 32-bit support). · **macOS:** requires 10.13 High Sierra or later. · **Linux:** deb = Debian/Ubuntu, rpm = Fedora/RHEL/openSUSE, pkg = Arch/Manjaro; the packages and \`rb-cli\` are built against **glibc 2.39** (Ubuntu 24.04), while the **AppImage** is self-contained and runs on most distributions regardless of glibc. · **Windows ARM64 / RISC-V 64:** cross-compiled, build-only legs — the Windows ARM64 app is a portable zip and the RISC-V 64 app ships as a deb, rpm or plain tarball, all dynamically linked against your system GTK3 (no self-contained AppImage like x64/arm64). · **MiSTer FPGA:** \`rb-cli-mini\` is a slim \`rb-cli\` cross-compiled for the MiSTer's armv7 hardfloat Intel Cyclone V SoC against Ubuntu 20.04 glibc 2.31 — same baseline as the MiSTer Buildroot rootfs and the upstream \`libchdman-rs\` armv7 prebuilt. The GUI is off; CHD, optical and the full-screen \`rb-cli tui\` terminal UI are in. Drop it onto the SD at \`/media/fat/Scripts/rb-cli\`. · Every **rb-cli** download contains a single \`rb-cli\` executable (\`rb-cli.exe\` on Windows).</sub>

### Command-line (\`rb-cli\`) for other CPU architectures

Expand Down
Loading