Files
wowlet/.gitea/workflows/build-linux.yml
T
jwinterm ea9c73826b fix(build): ship the binary as wowlet, not feather
The CMake target keeps its upstream name so the twenty-odd target_* calls stay
put, but OUTPUT_NAME now produces build/bin/wowlet, and on macOS a wowlet.app
whose CFBundleExecutable matches it.

Linux and Windows already renamed the artifact as they copied it, so their cp
lines just move to the new path. macOS copied the whole bundle instead, so it
shipped Contents/MacOS/feather with a Feather name in the Info.plist, which is
what anyone installing it actually saw. The Linux install rules had the same
problem one level down: they installed feather.desktop, which sets Exec=feather
and Name=Feather Wallet, while the correct wowlet.desktop sat unused beside it.

CFBundleIdentifier moves to org.wownero.wowlet. Nothing in signing or
notarization reads it, but macOS keys per-app state by bundle id, so an existing
install starts with fresh window state.
2026-09-13 10:49:00 -04:00

150 lines
7.2 KiB
YAML

name: linux appimage (gitea self-hosted)
# Runs ONLY on Gitea (GitHub ignores .gitea/workflows), in the private Builds
# repository. Gitea is master; GitHub is a mirror and a release surface.
#
# Unlike the Windows lane, which builds a static toolchain of its own through
# contrib/depends, the x86_64 AppImage links against the host's Qt6. Those
# dependencies are owned by such-fleet (roles/wowlet_build_host) rather than
# installed here: a workflow that apt-installs needs sudo on a shared runner and
# makes the build host's contents a property of whichever job ran last.
#
# Dispatch-only. The runner is capacity 1 and shared with the fleet gates.
on: [workflow_dispatch]
jobs:
appimage:
name: "Linux x86_64 (host Qt6 AppImage)"
runs-on: ubuntu-latest # gitea label ubuntu-latest:host -> deb, host mode
steps:
- name: verify the build host has its dependencies
run: |
missing=0
for t in cmake make curl bzip2 git patchelf pkg-config qmake6; do
command -v "$t" >/dev/null || { echo "MISSING TOOL: $t"; missing=1; }
done
for h in /usr/include/boost/version.hpp; do
[ -f "$h" ] || { echo "MISSING HEADER: $h"; missing=1; }
done
pkg-config --exists libsodium || { echo "MISSING: libsodium"; missing=1; }
[ "$missing" = 0 ] || {
echo "Run playbooks/wowlet-build-host.yml in such-fleet; do not apt-install from CI."
exit 1; }
echo "qt $(qmake6 -query QT_VERSION)"; nproc; free -g | head -2
- name: configure git
run: git config --global --add safe.directory '*'
- uses: actions/checkout@v4
with:
submodules: recursive
- name: fetch wownerod to embed
run: |
rm -rf /tmp/wownerod-embed && mkdir -p /tmp/wownerod-embed
curl -fL -o /tmp/wownero.tar.bz2 \
https://github.com/wownero/wownero-codeberg-mirror/releases/download/v0.11.4.0/wownero-x86_64-linux-gnu-v0.11.4.0.tar.bz2
rm -rf /tmp/wow-x && mkdir -p /tmp/wow-x
tar xjf /tmp/wownero.tar.bz2 -C /tmp/wow-x
find /tmp/wow-x -name wownerod -type f -exec cp {} /tmp/wownerod-embed/ \;
chmod +x /tmp/wownerod-embed/wownerod
ls -la /tmp/wownerod-embed
- name: fetch tor to embed
run: |
rm -rf /tmp/tor-embed && mkdir -p /tmp/tor-embed
curl -fL -o /tmp/teb.tgz \
https://archive.torproject.org/tor-package-archive/torbrowser/15.0/tor-expert-bundle-linux-x86_64-15.0.tar.gz
rm -rf /tmp/teb && mkdir -p /tmp/teb && tar xzf /tmp/teb.tgz -C /tmp/teb
cp /tmp/teb/tor/tor /tmp/teb/tor/libssl.so.3 /tmp/teb/tor/libevent-2.1.so.7 \
/tmp/teb/tor/libcrypto.so.3 /tmp/tor-embed/
# The expert bundle's tor carries no rpath; point it and its libs at
# $ORIGIN so the embedded copy resolves them from the extract dir on
# any distro.
for f in tor libssl.so.3 libevent-2.1.so.7 libcrypto.so.3; do
patchelf --set-rpath '$ORIGIN' /tmp/tor-embed/$f
done
chmod +x /tmp/tor-embed/tor
- name: build
run: |
# TOR_VERSION must EXACTLY match `tor --version` of the embedded
# binary, or TorManager::unpackBins() sees embedded > unpacked and
# rewrites Tor on every launch. The bundle's release number (15.0) is
# not its tor version, so derive it.
TORVER=$(/tmp/tor-embed/tor --version | grep -oE '[0-9]+(\.[0-9]+){3}' | head -1)
echo "embedded tor version: $TORVER"
# ARCH=x86-64, never native: the build host's CPU is newer than many
# users' and native bakes in unsupported instructions -> SIGILL.
cmake -S . -B build \
-DWITH_SCANNER=OFF \
-DARCH=x86-64 \
-DWOWNEROD_DIR=/tmp/wownerod-embed \
-DTOR_DIR=/tmp/tor-embed \
-DTOR_VERSION="$TORVER"
cmake --build build -j6
ls -la build/bin/
- name: package AppImage
run: |
rm -rf AppDir
mkdir -p AppDir/usr/bin AppDir/usr/share/applications \
AppDir/usr/share/icons/hicolor/256x256/apps
cp build/bin/wowlet AppDir/usr/bin/wowlet
chmod +x AppDir/usr/bin/wowlet
cp src/assets/wowlet.desktop AppDir/usr/share/applications/wowlet.desktop
cp src/assets/images/appicons/256x256.png \
AppDir/usr/share/icons/hicolor/256x256/apps/wowlet.png
curl -sL -o linuxdeploy https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
curl -sL -o linuxdeploy-plugin-qt https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
curl -sL -o appimagetool https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x linuxdeploy linuxdeploy-plugin-qt appimagetool
export APPIMAGE_EXTRACT_AND_RUN=1
export QMAKE="$(command -v qmake6)"
export EXTRA_QT_PLUGINS="svg;multimedia;tls"
export QML_SOURCES_PATHS="$PWD/src/assets/qml"
export PATH="$PWD:$PATH"
./linuxdeploy --appdir AppDir --plugin qt \
-d AppDir/usr/share/applications/wowlet.desktop \
-i AppDir/usr/share/icons/hicolor/256x256/apps/wowlet.png
# qmlimportscanner reads only the `import` lines in our QML; it does
# not follow a module's own qmldir depends/default-import chain, so
# transitive modules (QtQuick -> QtQml.WorkerScript/Models) are
# silently skipped. Blanket-copy the trees, then resolve each copied
# plugin's Qt libs ourselves -- linuxdeploy only does that for modules
# it deployed, not ones we copied by hand.
QMLDIR=$(qmake6 -query QT_INSTALL_QML)
mkdir -p AppDir/usr/qml AppDir/usr/lib
for m in QtQuick QtQml; do cp -rn "$QMLDIR/$m" AppDir/usr/qml/ 2>/dev/null || true; done
find AppDir/usr/qml -name '*.so' -print0 | while IFS= read -r -d '' so; do
ldd "$so" 2>/dev/null | awk '/=> \//{print $3}' \
| grep -E '/(libQt6|libicu|libpcre2|libdouble-conversion|libzstd|libb2|libpng|libharfbuzz|libmd4c|libglib|libgraphite)' \
| while read -r lib; do cp -L -n "$lib" AppDir/usr/lib/ 2>/dev/null || true; done
done
echo "=== qt.conf ==="; cat AppDir/usr/bin/qt.conf
# Guard: mining.qml must not pull in QtQuick.Controls. If a future
# edit re-adds a Controls type this fails loudly instead of shipping
# a white mining tab.
if grep -q 'import QtQuick.Controls' src/assets/qml/mining.qml; then
echo "ERROR: mining.qml imports QtQuick.Controls again." >&2
exit 1
fi
ARCH=x86_64 ./appimagetool AppDir wowlet-x86_64.AppImage
ls -la wowlet-x86_64.AppImage
- name: upload wowlet AppImage
# v3: Gitea implements the older artifact protocol and rejects
# @actions/artifact v2 clients (upload-artifact@v4+) as unsupported.
uses: actions/upload-artifact@v3
with:
name: wowlet-x86_64-linux-AppImage
path: wowlet-x86_64.AppImage
if-no-files-found: error