mirror of
https://github.com/wownero/wowlet.git
synced 2026-10-17 07:11:29 +02:00
Run artifacts upload fine, but this Gitea reports zero artifacts for every run through its REST API, and the web download route answers "Not found." under token, bearer and basic auth alike. A signed build was therefore unreachable from anywhere except the browser session that produced it. Release assets do work: create, upload, list and download all round-trip with an ordinary token, so tag builds now attach their output to the tag's release as well as to the run. Retrieval must use browser_download_url; the asset-id API path returns the asset's JSON metadata even when asked for octet-stream. The step is fail-safe on purpose. With no token, no resolvable release, or a non-201 upload it explains itself and exits 0 rather than turning a green build red. The macOS upload also gains if-no-files-found, without which an empty publish passes silently.
195 lines
9.9 KiB
YAML
195 lines
9.9 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: |
|
|
# ubuntu-latest and windows-latest both resolve to the same host in
|
|
# host mode, so a fixed /tmp path lets a concurrently dispatched job's
|
|
# `rm -rf` delete this job's binary between fetch and configure. Scope
|
|
# every extract to the run.
|
|
EMBED="/tmp/wowlet-${GITHUB_RUN_ID:-local}"
|
|
rm -rf "$EMBED/wownerod-embed" && mkdir -p "$EMBED/wownerod-embed"
|
|
curl -fL -o "$EMBED/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 "$EMBED/wow-x" && mkdir -p "$EMBED/wow-x"
|
|
tar xjf "$EMBED/wownero.tar.bz2" -C "$EMBED/wow-x"
|
|
find "$EMBED/wow-x" -name wownerod -type f -exec cp {} "$EMBED/wownerod-embed/" \;
|
|
chmod +x "$EMBED/wownerod-embed/wownerod"
|
|
ls -la "$EMBED/wownerod-embed"
|
|
|
|
- name: fetch tor to embed
|
|
run: |
|
|
EMBED="/tmp/wowlet-${GITHUB_RUN_ID:-local}"
|
|
rm -rf "$EMBED/tor-embed" && mkdir -p "$EMBED/tor-embed"
|
|
curl -fL -o "$EMBED/teb.tgz" \
|
|
https://archive.torproject.org/tor-package-archive/torbrowser/15.0/tor-expert-bundle-linux-x86_64-15.0.tar.gz
|
|
rm -rf "$EMBED/teb" && mkdir -p "$EMBED/teb" && tar xzf "$EMBED/teb.tgz" -C "$EMBED/teb"
|
|
cp "$EMBED/teb/tor/tor" "$EMBED/teb/tor/libssl.so.3" "$EMBED/teb/tor/libevent-2.1.so.7" \
|
|
"$EMBED/teb/tor/libcrypto.so.3" "$EMBED/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' "$EMBED/tor-embed/$f"
|
|
done
|
|
chmod +x "$EMBED/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.
|
|
EMBED="/tmp/wowlet-${GITHUB_RUN_ID:-local}"
|
|
TORVER=$("$EMBED/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="$EMBED/wownerod-embed" \
|
|
-DTOR_DIR="$EMBED/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
|
|
|
|
- name: publish the AppImage to the tag's release
|
|
# The artifact above uploads fine but this Gitea's REST listing reports
|
|
# zero artifacts for every run, so a tag build's output cannot be fetched
|
|
# back through the API. Release assets can, so publish there as well.
|
|
# Fail-safe by design: with no usable token this says why and exits 0,
|
|
# it never turns a green build red.
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
env:
|
|
RELEASE_TOKEN: ${{ github.token }}
|
|
run: |
|
|
set -eu
|
|
FILE=wowlet-x86_64.AppImage
|
|
TAG="${GITHUB_REF#refs/tags/}"
|
|
API="${GITHUB_SERVER_URL:-https://git.such.software}/api/v1/repos/$GITHUB_REPOSITORY"
|
|
if [ -z "${RELEASE_TOKEN:-}" ]; then
|
|
echo "no token available to this runner, skipping the release upload" >&2
|
|
exit 0
|
|
fi
|
|
H="Authorization: token $RELEASE_TOKEN"
|
|
# Single-line python on purpose: a continuation line at column 0 would
|
|
# end this block scalar and break the workflow's YAML. `|| true` keeps
|
|
# a malformed response from aborting the step under `set -e`.
|
|
rid=$(curl -sS -H "$H" "$API/releases/tags/$TAG" | python3 -c "import json,sys;print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
|
if [ -z "$rid" ]; then
|
|
rid=$(curl -sS -H "$H" -H "Content-Type: application/json" -X POST \
|
|
-d "{\"tag_name\":\"$TAG\",\"name\":\"wowlet $TAG\"}" "$API/releases" | python3 -c "import json,sys;print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
|
fi
|
|
if [ -z "$rid" ]; then
|
|
echo "could not resolve or create a release for $TAG, skipping the upload" >&2
|
|
exit 0
|
|
fi
|
|
code=$(curl -sS -H "$H" -o /dev/null -w '%{http_code}' -X POST \
|
|
-F "attachment=@$FILE" "$API/releases/$rid/assets?name=$(basename "$FILE")")
|
|
echo "release asset upload returned HTTP $code"
|
|
if [ "$code" != "201" ]; then
|
|
echo "the release upload did not return 201; the run artifact still holds the build" >&2
|
|
fi
|