forked from github-such-software/hash-wallet
The previous Linux artifact was a zip of the Flutter bundle/ directory. That's awkward to distribute — users have to unzip, find the binary, chmod +x, and figure out the lib/ layout themselves. Replace with a proper AppImage: single file, double-click to run, no install, no Flutter knowledge required. Build steps: - Stage AppDir with the Flutter bundle under usr/bin/ (the binary's RPATH=\$ORIGIN/lib already finds plugin libs there). - Add .desktop file (Hash Bags / Office;Finance;) and 256x256 hash icon scaled from the iOS marketing PNG. - Download appimagetool and invoke with --appimage-extract-and-run so it works inside the build container without FUSE. Artifact name: hash-wallet-linux-appimage-<sha>.
254 lines
11 KiB
YAML
254 lines
11 KiB
YAML
name: Hash Bags Linux build
|
|
|
|
# Triggers:
|
|
# - on push to dev/main (validates the foundation each time we land work)
|
|
# - on PRs targeting dev/main (gates merges)
|
|
# - manual via workflow_dispatch ("Run workflow" button in the UI)
|
|
on:
|
|
# Manual-only for now — auto-run on every push was too noisy. Trigger
|
|
# via Actions → "Hash Bags Linux build" → Run workflow when you want a
|
|
# build. Add `push:` back here if/when we want pre-merge validation.
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: linux-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
jobs:
|
|
build:
|
|
# Both your Gitea linux-beast runner and GitHub-hosted ubuntu runners
|
|
# carry the `ubuntu-latest` label, so this works on either platform.
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
# Cake Labs' prebuilt build image with Flutter 3.32.0, Go 1.24.1, NDK r28,
|
|
# Rust nightly, and all the C++ build deps (boost, openssl, libsodium,
|
|
# libzmq, unbound, icu) preinstalled. Saves us from doing the simplybs
|
|
# source-bootstrap dance that ate 9GB on jw-laptop.
|
|
image: ghcr.io/cake-tech/cake_wallet:debian13-flutter3.32.0-ndkr28-go1.24.1-ruststablenightly
|
|
env:
|
|
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
|
# cake_wallet build profile name, retained from upstream — internal
|
|
# identifier only, doesn't appear in the binary or UI.
|
|
APP_LINUX_TYPE: cakewallet
|
|
|
|
steps:
|
|
- name: Fix Actions HOME pointing at /github/home (breaks ~/.cache writes)
|
|
run: echo "HOME=/root" >> $GITHUB_ENV
|
|
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
|
|
- name: Configure git inside the container
|
|
run: |
|
|
git config --global --add safe.directory '*'
|
|
git config --global user.email "ci@suchsoftware.com"
|
|
git config --global user.name "Hash Bags CI"
|
|
|
|
# ---- Secrets ---------------------------------------------------------
|
|
# IMPORTANT: don't pre-write any of the tool/.*secrets-config.json
|
|
# files. The generator at tool/generate_secrets_config.dart has an
|
|
# early-return if tool/.secrets-config.json already exists (lines
|
|
# 57-63), which then ALSO skips creating the per-module configs
|
|
# (evm, nano, bitcoin) — every cw_* module then fails to compile
|
|
# with "Undefined name secrets.xxx" for dozens of keys.
|
|
#
|
|
# Instead: run the generator first so it creates all configs from the
|
|
# full SecretKey list (with empty defaults), then sed-inject Trocador
|
|
# values into the freshly-generated lib/.secrets.g.dart.
|
|
|
|
# ---- External clones (use prebuilt tarballs, NOT prepare_*.sh) -------
|
|
# The prepare_torch.sh / prepare_reown.sh scripts do dev-time clones
|
|
# that take forever; CI uses the pre-tagged release tarballs instead.
|
|
- name: Fetch prebuilt torch_dart
|
|
run: |
|
|
set -x -e
|
|
pushd scripts
|
|
rm -rf torch_dart torch_dart.tar.gz
|
|
wget -q https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz -O torch_dart.tar.gz
|
|
mkdir torch_dart
|
|
tar -xzf torch_dart.tar.gz -C torch_dart
|
|
rm torch_dart.tar.gz
|
|
popd
|
|
|
|
- name: Fetch prebuilt reown_flutter
|
|
run: |
|
|
set -x -e
|
|
pushd scripts
|
|
rm -rf reown_flutter reown_flutter.tar.gz
|
|
wget -q https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz -O reown_flutter.tar.gz
|
|
mkdir reown_flutter
|
|
tar -xzf reown_flutter.tar.gz -C reown_flutter
|
|
rm reown_flutter.tar.gz
|
|
popd
|
|
|
|
- name: Clone BitBox Flutter (small, builds fast)
|
|
run: |
|
|
set -x -e
|
|
pushd scripts
|
|
./build_bitbox_flutter.sh
|
|
popd
|
|
|
|
# ---- Native crypto cores (monero_c prebuilt bundle) ------------------
|
|
# Skips the full simplybs toolchain bootstrap. The bundle has libmonero,
|
|
# libwownero, AND libzano .so files; CMake only installs the ones we
|
|
# ship (monero + wownero) — libzano is dropped at install time even
|
|
# though monero_c builds it.
|
|
- name: Fetch prebuilt monero_c .so bundle
|
|
run: |
|
|
set -x -e
|
|
./scripts/prepare_moneroc.sh
|
|
MONERO_C_TAG=$(cd scripts/monero_c && git describe --tags)
|
|
echo "monero_c TAG: $MONERO_C_TAG"
|
|
mkdir -p "scripts/monero_c/release/$MONERO_C_TAG"
|
|
pushd "scripts/monero_c/release/$MONERO_C_TAG"
|
|
wget -q https://github.com/MrCyjaneK/monero_c/releases/download/v0.18.4.6-RC1/release-bundle.zip
|
|
unzip -q release-bundle.zip
|
|
rm release-bundle.zip
|
|
ls x86_64-linux-gnu/
|
|
popd
|
|
|
|
# ---- Configure: pubspec.yaml, AndroidManifest.xml, env vars ----------
|
|
- name: Run configure (cakewallet build profile)
|
|
run: |
|
|
pushd scripts/linux
|
|
source ./app_env.sh cakewallet
|
|
./app_config.sh
|
|
popd
|
|
|
|
# ---- Codegen: mobx, hive adapters, FFI bindings ----------------------
|
|
# model_generator.sh is already trimmed to our 8 enabled chains.
|
|
# Use `async` flag for parallel build_runner across modules.
|
|
- name: Generate per-module secrets.g.dart files (all empty defaults)
|
|
run: dart run tool/generate_new_secrets.dart
|
|
|
|
- name: Inject Trocador affiliate secrets into lib/.secrets.g.dart
|
|
env:
|
|
TROCADOR_API_KEY: ${{ secrets.TROCADOR_API_KEY }}
|
|
TROCADOR_MONERO_API_KEY: ${{ secrets.TROCADOR_MONERO_API_KEY }}
|
|
TROCADOR_EXCHANGE_MARKUP: ${{ secrets.TROCADOR_EXCHANGE_MARKUP }}
|
|
run: |
|
|
# Replace empty default '' with real values for the three Trocador keys.
|
|
# Other ~80 secrets stay as empty strings — code that uses them just
|
|
# fails-soft at runtime (no transaction history without Etherscan key,
|
|
# no Cake Pay without API key, etc.). Add more sed lines here as we
|
|
# acquire other affiliate keys.
|
|
sed -i \
|
|
-e "s|const trocadorApiKey = '';|const trocadorApiKey = '${TROCADOR_API_KEY}';|" \
|
|
-e "s|const trocadorMoneroApiKey = '';|const trocadorMoneroApiKey = '${TROCADOR_MONERO_API_KEY}';|" \
|
|
-e "s|const trocadorExchangeMarkup = '';|const trocadorExchangeMarkup = '${TROCADOR_EXCHANGE_MARKUP:-1}';|" \
|
|
lib/.secrets.g.dart
|
|
grep '^const trocador' lib/.secrets.g.dart # verify the substitutions
|
|
|
|
# Initialize Flutter SDK once before parallel-ish work happens. flutter
|
|
# precache for Flutter 3.32.0 hits a 404 on flutter_gpu.zip (asset not
|
|
# actually published at the path Flutter constructs); the `|| true`
|
|
# absorbs that — desktop Linux build doesn't need flutter_gpu.
|
|
- name: Initialize Flutter SDK
|
|
run: |
|
|
flutter --version
|
|
flutter precache --linux --no-android --no-ios --no-macos --no-windows --no-fuchsia --no-web || true
|
|
|
|
# Sequential — async flag races on Flutter's startup lock and corrupts
|
|
# the SDK state, causing the "doesn't support null safety" cascade.
|
|
- name: Build generated code (mobx + hive adapters)
|
|
run: bash model_generator.sh
|
|
|
|
- name: Generate localization
|
|
run: dart run tool/generate_localization.dart
|
|
|
|
- name: Compile SVG assets (res/pictures/*.svg → assets/new-ui/*.svg.vec)
|
|
run: ./compile_graphics.sh
|
|
|
|
# ---- Compile + package ----------------------------------------------
|
|
- name: Build Linux app
|
|
run: flutter build linux --dart-define-from-file=env.json --release
|
|
|
|
# ---- Package as AppImage --------------------------------------------
|
|
# Self-contained .AppImage is the user-facing Linux deliverable: single
|
|
# file, double-click to run, no install, works on any glibc Linux from
|
|
# the last few years. appimagetool is run with --appimage-extract-and-run
|
|
# so it works inside the container without FUSE.
|
|
- name: Stage AppDir
|
|
run: |
|
|
set -e -x
|
|
REL=build/linux/x64/release
|
|
APPDIR=$REL/Hash_Bags.AppDir
|
|
rm -rf "$APPDIR"
|
|
mkdir -p "$APPDIR/usr/bin" \
|
|
"$APPDIR/usr/share/applications" \
|
|
"$APPDIR/usr/share/icons/hicolor/256x256/apps"
|
|
|
|
# The whole Flutter Linux bundle (binary + data/ + lib/) lives
|
|
# under usr/bin/. The Flutter binary has RPATH=$ORIGIN/lib, so
|
|
# plugin/native libs in usr/bin/lib/ resolve naturally.
|
|
cp -r "$REL/bundle"/* "$APPDIR/usr/bin/"
|
|
|
|
# Icon: scale the iOS marketing icon to 256 if convert is around,
|
|
# else copy as-is (appimagetool only requires that AppDir root and
|
|
# the hicolor path contain a same-named PNG).
|
|
ICON_SRC=assets/images/ios_icons/hashwallet_ios_icons/Icon-App-1024x1024@1x.png
|
|
ICON_DEST="$APPDIR/usr/share/icons/hicolor/256x256/apps/hash_bags.png"
|
|
if command -v convert >/dev/null 2>&1; then
|
|
convert "$ICON_SRC" -resize 256x256 "$ICON_DEST"
|
|
else
|
|
cp "$ICON_SRC" "$ICON_DEST"
|
|
fi
|
|
cp "$ICON_DEST" "$APPDIR/hash_bags.png"
|
|
|
|
# .desktop file (at both canonical locations; appimagetool checks both)
|
|
cat > "$APPDIR/hash_bags.desktop" <<'DESKTOP'
|
|
[Desktop Entry]
|
|
Name=Hash Bags
|
|
Comment=Non-custodial multi-chain crypto wallet
|
|
Exec=hash_wallet
|
|
Icon=hash_bags
|
|
Type=Application
|
|
Categories=Office;Finance;
|
|
Terminal=false
|
|
DESKTOP
|
|
# Strip the leading whitespace from the heredoc
|
|
sed -i 's/^ //' "$APPDIR/hash_bags.desktop"
|
|
cp "$APPDIR/hash_bags.desktop" "$APPDIR/usr/share/applications/"
|
|
|
|
# AppRun: the entry point AppImage executes. Adds the bundled lib/
|
|
# dir to LD_LIBRARY_PATH and exec's the Flutter binary.
|
|
cat > "$APPDIR/AppRun" <<'APPRUN'
|
|
#!/bin/bash
|
|
HERE="$(dirname "$(readlink -f "${0}")")"
|
|
export LD_LIBRARY_PATH="${HERE}/usr/bin/lib:${LD_LIBRARY_PATH}"
|
|
exec "${HERE}/usr/bin/hash_wallet" "$@"
|
|
APPRUN
|
|
sed -i 's/^ //' "$APPDIR/AppRun"
|
|
chmod +x "$APPDIR/AppRun"
|
|
|
|
ls -la "$APPDIR"
|
|
|
|
- name: Build AppImage
|
|
run: |
|
|
set -e -x
|
|
REL=build/linux/x64/release
|
|
wget -q https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /tmp/appimagetool
|
|
chmod +x /tmp/appimagetool
|
|
# --appimage-extract-and-run avoids the FUSE requirement (no fusermount
|
|
# in the build container). ARCH= tells appimagetool which arch tag to
|
|
# embed in the filename.
|
|
ARCH=x86_64 /tmp/appimagetool --appimage-extract-and-run \
|
|
"$REL/Hash_Bags.AppDir" \
|
|
"$REL/Hash_Bags-x86_64.AppImage"
|
|
ls -la "$REL"/*.AppImage
|
|
|
|
# actions/upload-artifact@v4 uses an HTTP API that Gitea Actions does
|
|
# not implement (only the v1/v3 wire format). Pinned to @v3 for Gitea
|
|
# compatibility — also works on GitHub Actions.
|
|
- name: Upload AppImage artifact
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: hash-wallet-linux-appimage-${{ github.sha }}
|
|
path: build/linux/x64/release/Hash_Bags-x86_64.AppImage
|
|
retention-days: 14
|