Files
triangles_v5/.github/workflows/build-all.yml
T
SamiAhmed7777 b40c58f886 Add triangles-cli: JSON-RPC client (port bitcoin-cli pattern) (#7)
* Add triangles-cli: JSON-RPC client (port bitcoin-cli pattern)

Triangles never had a CLI client (bitcoin-cli analog). This adds
triangles-cli as a third build target alongside trianglesd and
triangles-qt.

- src/triangles-cli.cpp: self-contained JSON-RPC 1.0 client.
  Reads triangles.conf for credentials, supports -rpcuser/-rpcpassword
  /-rpcconnect/-rpcport/-testnet/-datadir/-conf flags. Implements
  -getinfo (synthesized summary from getnetworkinfo/getblockchaininfo
  /getwalletinfo) and raw method dispatch. JSON via json_spirit compat
  shim (json_compat.h), HTTP via boost::asio, base64 auth inline.
  No util.cpp / wallet.cpp / net.cpp / triangles_common link dep —
  keeps the binary small (~600 KB Linux, ~1.5 MB Windows).

- CMake: new option(BUILD_CLI ON) + add_executable(triangles-cli)
  in src/CMakeLists.txt. Status line added.

- CI: BUILD_CLI=ON added to build-windows-daemon and build-linux-daemon
  jobs. triangles-cli.exe bundled into windows-daemon artifact
  alongside trianglesd.exe. triangles-cli added to linux-daemon .deb
  package (with launcher in /usr/bin).

- Default ON; set BUILD_CLI=OFF to skip.

Closes the open 'triangles-cli.exe missing from Windows build'
follow-up (the binary wasn't missing — it never existed).

Patterned after Bitcoin Core bitcoin-cli and Dash Core dash-cli.

* Fix macOS build: drop Boost::system/find_package component, use std::filesystem

Homebrew's boost formula doesn't ship the boost_system CMake config file,
so find_package(Boost REQUIRED COMPONENTS system) failed on macOS.

- Replace boost::filesystem with std::filesystem (C++17, no Boost dep)
- Drop 'filesystem' from find_package — only headers needed (asio + system)
- Link libboost_system explicitly per-platform by library name, resolved
  via the platform's default search path (Homebrew toolchain on macOS,
  system libs on Linux, MSYS2 on Windows)

CI will rerun automatically on PR push.

* Fix macOS build: add Boost::boost target for headers, link boost_system

The previous fix dropped the find_package component but also killed the
boost include path. Now use the modern Boost::boost header-only target
(available in Boost 1.83+) which sets up include directories without
requiring a per-component config file.

Link libboost_system explicitly by name on all platforms — the linker
finds it via the platform's default search path:
- Linux: /usr/lib (libboost_system.so)
- macOS Homebrew: /opt/homebrew/lib (libboost_system.dylib)
- Windows MSYS2: mingw64/bin (libboost_system-mt-X-XX.dll)

* Drop Boost entirely from triangles-cli: use raw sockets for HTTP

Third time's the charm. After two CI failures chasing boost::asio / libboost_system
linking issues across platforms (Homebrew missing config on macOS, MSYS2 versioned
names on Windows, CMake targets that don't quite work everywhere), rip the whole
Boost dependency out of the CLI and use raw POSIX/Winsock sockets.

- triangles-cli.cpp: replaced boost::asio with raw socket() / connect() / send()
  / recv() / getaddrinfo(). Cross-platform: #ifdef _WIN32 for Winsock + WSAStartup
  / WSACleanup, else POSIX. ~100 lines of clean portable socket code.
- src/CMakeLists.txt: dropped find_package(Boost) entirely. Only links
  json_compat (header-only) + ws2_32 on Windows. No boost libs to find.

Should be the last fix needed for this PR.

* Fix Windows packaging step: simplify bash { } | sort -u | while pattern

The previous step used a bash group command piped through sort -u and a
while loop. Under MSYS2 bash + 'set -e -o pipefail' (GitHub Actions
default), this triggered a non-zero exit even when the loop body
succeeded, causing the Windows daemon job to fail at the packaging step
(the actual link of both trianglesd.exe and triangles-cli.exe succeeded).

Replaced the { } | sort -u | while pattern with a temp-file-based dedup:
- ldd both binaries, append to /tmp/cli-dlls.txt (or cli-libs.txt on Linux)
- sort -u the temp file
- pipe the result into the while loop (simpler pipeline, no group)

Also applied the same simplification to the Linux .deb packaging for
consistency, even though the Linux build was passing.

* Simplify DLL packaging: plain for loop, no pipe-into-while

The previous attempts used 'ldd | sort -u | while read; do ... done' patterns
that exit 1 under MSYS2 bash + 'set -e -o pipefail' even when the script
ran successfully. Replaced with a plain 'for bin in ...; do ldd > list.txt;
while read; do cp; done < list.txt; done' pattern that has no pipelines
other than the standard redirection, and uses IFS= read -r for safe line
iteration.

Also moved temp files from /tmp to the working directory (./dll-list.txt)
to avoid any MSYS2 /tmp path-translation edge cases.

* diagnostic: add tracing to Windows packaging step

* Add package-windows-daemon.sh + package-linux-daemon.sh scripts

Move the Windows daemon packaging step and the Linux .deb build into
committed shell scripts under scripts/ci/. This bypasses GitHub Actions'
inline-run-block quirks (silent exit 1 under msys2 + set -e -o pipefail
with multi-line scripts) and makes the packaging logic debuggable locally.

* Switch to script-file packaging for Windows + Linux daemon jobs

Replace inline multi-line run: blocks with invocations of the
scripts/ci/package-*.sh scripts. This sidesteps the GitHub Actions
msys2 + 'set -e -o pipefail' issue that caused silent exit 1 on the
Windows daemon packaging step. The scripts are also debuggable locally.

---------

Co-authored-by: Krystie <krystie@sami>
2026-06-18 20:05:54 -07:00

638 lines
24 KiB
YAML

name: Build All Platforms
on:
push:
branches: [master, cpp20-modernization]
tags: ['v*']
pull_request:
branches: [master]
workflow_dispatch:
jobs:
test-linux-unit:
runs-on: ubuntu-22.04
continue-on-error: true
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build \
libboost-all-dev libssl-dev libdb++-dev libleveldb-dev \
librocksdb-dev libevent-dev libminiupnpc-dev zlib1g-dev
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_QT=OFF \
-DBUILD_DAEMON=ON \
-DBUILD_TESTS=ON \
-DUSE_UPNP=OFF
- name: Build
run: cmake --build build -j$(nproc)
- name: Run unit tests
run: cd build && ctest --output-on-failure || true
test-linux-sanitizers:
# ASan + UBSan build of the daemon + unit tests. Allowed to fail until
# findings are triaged — see .github/workflows/lint.yml comment block.
# Once the test suite is clean under sanitizers, drop continue-on-error.
runs-on: ubuntu-22.04
continue-on-error: true
env:
# ASan: leak detection off by default (BDB and OpenSSL produce noise on shutdown).
# Re-enable once we've quieted the legitimate suspects.
ASAN_OPTIONS: "detect_leaks=0:halt_on_error=1:abort_on_error=1:print_stacktrace=1:strict_string_checks=1:detect_stack_use_after_return=1"
# UBSan: print full stack traces on first error and exit non-zero.
UBSAN_OPTIONS: "halt_on_error=1:abort_on_error=1:print_stacktrace=1"
# Suppress UB categories that are pervasive in the Hash9 C cascade
# and BDB until they're fixed file-by-file.
SAN_FLAGS: "-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=undefined -fno-sanitize=alignment,signed-integer-overflow,vptr"
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build \
libboost-all-dev libssl-dev libdb++-dev libleveldb-dev \
librocksdb-dev libevent-dev libminiupnpc-dev zlib1g-dev
- name: Configure with sanitizers
run: |
cmake -B build-san -G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS="$SAN_FLAGS" \
-DCMAKE_CXX_FLAGS="$SAN_FLAGS" \
-DCMAKE_EXE_LINKER_FLAGS="$SAN_FLAGS" \
-DCMAKE_SHARED_LINKER_FLAGS="$SAN_FLAGS" \
-DBUILD_QT=OFF \
-DBUILD_DAEMON=ON \
-DBUILD_TESTS=ON \
-DUSE_UPNP=OFF
- name: Build
run: cmake --build build-san -j$(nproc)
- name: Run unit tests under sanitizers
run: cd build-san && ctest --output-on-failure
build-windows-qt:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
mingw-w64-x86_64-gcc
mingw-w64-x86_64-cmake
mingw-w64-x86_64-ninja
mingw-w64-x86_64-qt5-base
mingw-w64-x86_64-qt5-tools
mingw-w64-x86_64-boost
mingw-w64-x86_64-openssl
mingw-w64-x86_64-db
mingw-w64-x86_64-libevent
mingw-w64-x86_64-miniupnpc
mingw-w64-x86_64-zlib
mingw-w64-x86_64-rocksdb
- name: Set VERSION
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
else
MAJOR=$(grep 'CLIENT_VERSION_MAJOR' src/clientversion.h | awk '{print $3}')
MINOR=$(grep 'CLIENT_VERSION_MINOR' src/clientversion.h | awk '{print $3}')
REV=$(grep 'CLIENT_VERSION_REVISION' src/clientversion.h | awk '{print $3}')
echo "VERSION=${MAJOR}.${MINOR}.${REV}" >> $GITHUB_ENV
fi
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_QT=ON \
-DBUILD_DAEMON=OFF \
-DBUILD_TESTS=OFF \
-DUSE_UPNP=ON \
-DUSE_QRCODE=OFF
- name: Build
run: cmake --build build -j$(nproc)
- name: Package
run: |
mkdir -p dist
cp build/bin/triangles-qt.exe dist/
windeployqt dist/triangles-qt.exe || true
# Copy ALL runtime DLLs the binary needs
# MinGW runtime
for dll in libgcc_s_seh-1.dll libstdc++-6.dll libwinpthread-1.dll; do
cp /mingw64/bin/$dll dist/ 2>/dev/null || true
done
# Boost
for dll in /mingw64/bin/libboost_system*.dll /mingw64/bin/libboost_filesystem*.dll \
/mingw64/bin/libboost_thread*.dll /mingw64/bin/libboost_program_options*.dll \
/mingw64/bin/libboost_chrono*.dll; do
cp $dll dist/ 2>/dev/null || true
done
# OpenSSL
for dll in /mingw64/bin/libssl*.dll /mingw64/bin/libcrypto*.dll; do
cp $dll dist/ 2>/dev/null || true
done
# BerkeleyDB, libevent, miniupnpc, zlib
for dll in /mingw64/bin/libdb*.dll /mingw64/bin/libevent*.dll \
/mingw64/bin/libminiupnpc*.dll /mingw64/bin/zlib1.dll; do
cp $dll dist/ 2>/dev/null || true
done
# Catch anything we missed: scan ldd output for /mingw64 deps
ldd dist/triangles-qt.exe | grep '/mingw64' | awk '{print $3}' | while read dll; do
cp "$dll" dist/ 2>/dev/null || true
done
# Write qt.conf so the exe finds plugins relative to itself
printf '[Paths]\nPlugins = .\n' > dist/qt.conf
# Ensure Qt platform plugins are present (windeployqt sometimes misses them in MSYS2)
if [ ! -f dist/platforms/qwindows.dll ]; then
echo "WARNING: windeployqt did not copy platform plugins, copying manually..."
mkdir -p dist/platforms
cp /mingw64/share/qt5/plugins/platforms/qwindows.dll dist/platforms/ 2>/dev/null || \
cp /mingw64/lib/qt5/plugins/platforms/qwindows.dll dist/platforms/ 2>/dev/null || \
find /mingw64 -name 'qwindows.dll' -exec cp {} dist/platforms/ \; 2>/dev/null
fi
# Also copy styles and imageformats for good measure
for plugdir in styles imageformats; do
if [ ! -d "dist/$plugdir" ]; then
srcdir=$(find /mingw64 -type d -name "$plugdir" -path "*/plugins/*" 2>/dev/null | head -1)
if [ -n "$srcdir" ]; then
cp -r "$srcdir" dist/
fi
fi
done
strip --strip-all dist/triangles-qt.exe
echo "=== dist/ contents ==="
find dist/ -type f | head -50
- name: Download Tor
shell: powershell
run: |
$TOR_VERSION = "15.0.9"
$TOR_URL = "https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/tor-expert-bundle-windows-x86_64-${TOR_VERSION}.tar.gz"
Invoke-WebRequest -Uri $TOR_URL -OutFile tor-bundle.tar.gz
New-Item -ItemType Directory -Path tor-extract -Force
tar -xzf tor-bundle.tar.gz -C tor-extract
New-Item -ItemType Directory -Path tor-files -Force
Copy-Item -Recurse tor-extract/tor/* tor-files/
if (Test-Path tor-extract/tor/pluggable_transports) {
Copy-Item -Recurse tor-extract/tor/pluggable_transports tor-files/pluggable_transports -Force
}
if (Test-Path tor-extract/data) {
Copy-Item -Recurse tor-extract/data tor-files/data
}
Write-Host "Bundled Tor runtime files:"
Get-ChildItem -Recurse tor-files | Select-Object FullName
- name: Install NSIS via MSYS2
run: pacman -S --noconfirm mingw-w64-x86_64-nsis
- name: Install NSIS inetc plugin
run: |
pacman -S --noconfirm unzip
NSIS_DIR="/mingw64/share/nsis"
cd /tmp
curl -L -o Inetc.zip "https://nsis.sourceforge.io/mediawiki/images/c/c9/Inetc.zip"
unzip -o Inetc.zip -d inetc_extract
# MSYS2 mingw64 NSIS is 64-bit, needs amd64-unicode plugin in Plugins/unicode/
mkdir -p "$NSIS_DIR/Plugins/unicode"
cp inetc_extract/Plugins/amd64-unicode/INetC.dll "$NSIS_DIR/Plugins/unicode/"
echo "Installed 64-bit INetC.dll to $NSIS_DIR/Plugins/unicode/"
- name: Build NSIS installer
run: makensis //DVERSION=$VERSION contrib/nsis/setup.nsi
- name: Upload installer
uses: actions/upload-artifact@v4
with:
name: windows-qt-setup
path: contrib/nsis/Cryptographic-Triangles-*-setup.exe
build-windows-daemon:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
mingw-w64-x86_64-gcc
mingw-w64-x86_64-cmake
mingw-w64-x86_64-ninja
mingw-w64-x86_64-boost
mingw-w64-x86_64-openssl
mingw-w64-x86_64-db
mingw-w64-x86_64-libevent
mingw-w64-x86_64-miniupnpc
mingw-w64-x86_64-zlib
mingw-w64-x86_64-rocksdb
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_QT=OFF \
-DBUILD_DAEMON=ON \
-DBUILD_CLI=ON \
-DBUILD_TESTS=OFF \
-DUSE_UPNP=ON
- name: Build
run: |
cmake --build build -j$(nproc)
strip --strip-all build/bin/trianglesd.exe
strip --strip-all build/bin/triangles-cli.exe
- name: Package daemon with DLLs
run: bash scripts/ci/package-windows-daemon.sh daemon-dist trianglesd triangles-cli
- name: Bundle Tor for daemon
shell: powershell
run: |
$TOR_VERSION = "15.0.9"
Invoke-WebRequest -Uri "https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/tor-expert-bundle-windows-x86_64-${TOR_VERSION}.tar.gz" -OutFile tor-bundle.tar.gz
New-Item -ItemType Directory -Path tor-extract -Force
tar -xzf tor-bundle.tar.gz -C tor-extract
Copy-Item -Recurse tor-extract/tor/* daemon-dist/tor/
if (Test-Path tor-extract/data) {
Copy-Item -Recurse tor-extract/data daemon-dist/tor/data
}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: windows-daemon
path: daemon-dist/
build-linux-qt:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set VERSION
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
else
MAJOR=$(grep 'CLIENT_VERSION_MAJOR' src/clientversion.h | awk '{print $3}')
MINOR=$(grep 'CLIENT_VERSION_MINOR' src/clientversion.h | awk '{print $3}')
REV=$(grep 'CLIENT_VERSION_REVISION' src/clientversion.h | awk '{print $3}')
echo "VERSION=${MAJOR}.${MINOR}.${REV}" >> $GITHUB_ENV
fi
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build \
qtbase5-dev qttools5-dev-tools \
libboost-all-dev libssl-dev libdb++-dev \
libleveldb-dev librocksdb-dev libevent-dev libminiupnpc-dev zlib1g-dev
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_QT=ON \
-DBUILD_DAEMON=OFF \
-DBUILD_TESTS=OFF \
-DUSE_UPNP=ON
- name: Build
run: cmake --build build -j$(nproc)
- name: Strip binary
run: strip --strip-all build/bin/triangles-qt
- name: Build .deb package (fully self-contained)
run: |
TOR_VERSION="15.0.9"
curl -sL "https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/tor-expert-bundle-linux-x86_64-${TOR_VERSION}.tar.gz" -o tor-bundle.tar.gz
mkdir -p tor-extract && tar -xzf tor-bundle.tar.gz -C tor-extract
PKG="cryptographic-triangles_${VERSION}_amd64"
mkdir -p ${PKG}/DEBIAN
mkdir -p ${PKG}/usr/lib/cryptographic-triangles/lib
mkdir -p ${PKG}/usr/lib/cryptographic-triangles/tor
mkdir -p ${PKG}/usr/bin
mkdir -p ${PKG}/usr/share/applications
mkdir -p ${PKG}/usr/share/pixmaps
cp build/bin/triangles-qt ${PKG}/usr/lib/cryptographic-triangles/
cp tor-extract/tor/tor ${PKG}/usr/lib/cryptographic-triangles/tor/
chmod +x ${PKG}/usr/lib/cryptographic-triangles/tor/tor
[ -d tor-extract/data ] && cp -r tor-extract/data ${PKG}/usr/lib/cryptographic-triangles/tor/data
# Bundle ALL shared library dependencies (except glibc/kernel)
ldd build/bin/triangles-qt | grep '=> /' | awk '{print $3}' | while read lib; do
case "$lib" in
/lib/x86_64-linux-gnu/libc.so*|/lib/x86_64-linux-gnu/libm.so*|/lib/x86_64-linux-gnu/libpthread.so*|/lib/x86_64-linux-gnu/libdl.so*|/lib/x86_64-linux-gnu/librt.so*|/lib/x86_64-linux-gnu/ld-linux*|/lib64/ld-linux*)
;; # Skip glibc core — always present
*)
cp -L "$lib" ${PKG}/usr/lib/cryptographic-triangles/lib/ 2>/dev/null || true
;;
esac
done
echo "=== Bundled libs ==="
ls ${PKG}/usr/lib/cryptographic-triangles/lib/ | wc -l
ls ${PKG}/usr/lib/cryptographic-triangles/lib/
# Launcher with LD_LIBRARY_PATH
cat > ${PKG}/usr/bin/cryptographic-triangles << 'LAUNCHER'
#!/bin/bash
INSTALL_DIR=/usr/lib/cryptographic-triangles
export LD_LIBRARY_PATH="${INSTALL_DIR}/lib:${LD_LIBRARY_PATH}"
exec "${INSTALL_DIR}/triangles-qt" "$@"
LAUNCHER
sed -i 's/^ //' ${PKG}/usr/bin/cryptographic-triangles
chmod +x ${PKG}/usr/bin/cryptographic-triangles
cat > ${PKG}/usr/share/applications/cryptographic-triangles.desktop << 'DESKTOP'
[Desktop Entry]
Name=Cryptographic Triangles
Comment=Triangles Cryptocurrency Wallet
Exec=cryptographic-triangles
Terminal=false
Type=Application
Icon=cryptographic-triangles
Categories=Finance;Network;
DESKTOP
sed -i 's/^ //' ${PKG}/usr/share/applications/cryptographic-triangles.desktop
cp src/qt/res/icons/triangles.ico ${PKG}/usr/share/pixmaps/cryptographic-triangles.ico 2>/dev/null || true
cat > ${PKG}/DEBIAN/control << CTRL
Package: cryptographic-triangles
Version: ${VERSION}
Architecture: amd64
Maintainer: Cryptographic Triangles <dev@cryptographic-triangles.org>
Description: Cryptographic Triangles wallet with integrated Tor
Fully self-contained wallet with all libraries and Tor bundled.
No external dependencies required — runs on any x86_64 Linux.
Section: finance
Priority: optional
CTRL
sed -i 's/^ //' ${PKG}/DEBIAN/control
dpkg-deb --build ${PKG}
- name: Upload .deb
uses: actions/upload-artifact@v4
with:
name: linux-qt-deb
path: cryptographic-triangles_*_amd64.deb
build-linux-daemon:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set VERSION
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
else
MAJOR=$(grep 'CLIENT_VERSION_MAJOR' src/clientversion.h | awk '{print $3}')
MINOR=$(grep 'CLIENT_VERSION_MINOR' src/clientversion.h | awk '{print $3}')
REV=$(grep 'CLIENT_VERSION_REVISION' src/clientversion.h | awk '{print $3}')
echo "VERSION=${MAJOR}.${MINOR}.${REV}" >> $GITHUB_ENV
fi
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build \
libboost-all-dev libssl-dev libdb++-dev libleveldb-dev \
librocksdb-dev libevent-dev libminiupnpc-dev zlib1g-dev
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_QT=OFF \
-DBUILD_DAEMON=ON \
-DBUILD_CLI=ON \
-DBUILD_TESTS=OFF \
-DUSE_UPNP=ON
- name: Build
run: cmake --build build -j$(nproc)
- name: Strip binary
run: |
strip --strip-all build/bin/trianglesd
strip --strip-all build/bin/triangles-cli
- name: Build .deb package (fully self-contained)
run: bash scripts/ci/package-linux-daemon.sh "${VERSION}"
- name: Upload .deb
uses: actions/upload-artifact@v4
with:
name: linux-daemon-deb
path: cryptographic-triangles-daemon_*_amd64.deb
build-macos:
runs-on: macos-15
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set VERSION
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
else
MAJOR=$(grep 'CLIENT_VERSION_MAJOR' src/clientversion.h | awk '{print $3}')
MINOR=$(grep 'CLIENT_VERSION_MINOR' src/clientversion.h | awk '{print $3}')
REV=$(grep 'CLIENT_VERSION_REVISION' src/clientversion.h | awk '{print $3}')
echo "VERSION=${MAJOR}.${MINOR}.${REV}" >> $GITHUB_ENV
fi
- name: Install dependencies
run: |
brew install cmake ninja qt@5 openssl@3 boost berkeley-db@5 leveldb rocksdb libevent miniupnpc
- name: Configure
run: |
export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_QT=ON \
-DBUILD_DAEMON=OFF \
-DBUILD_TESTS=OFF \
-DUSE_UPNP=ON \
-DBOOST_ROOT=/opt/homebrew/opt/boost \
-DBDB_INCLUDE_PATH=/opt/homebrew/opt/berkeley-db@5/include \
-DBDB_LIB_PATH=/opt/homebrew/opt/berkeley-db@5/lib \
-DOPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl@3 \
-DEVENT_INCLUDE_PATH=/opt/homebrew/opt/libevent/include \
-DEVENT_LIB_PATH=/opt/homebrew/opt/libevent/lib \
-DMINIUPNPC_INCLUDE_PATH=/opt/homebrew/opt/miniupnpc/include \
-DMINIUPNPC_LIB_PATH=/opt/homebrew/opt/miniupnpc/lib \
-DQt5_DIR=/opt/homebrew/opt/qt@5/lib/cmake/Qt5
- name: Build
run: cmake --build build -j$(sysctl -n hw.ncpu)
- name: Create .app bundle
run: |
export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"
macdeployqt build/bin/Triangles-Qt.app -verbose=1 || \
macdeployqt build/bin/triangles-qt.app -verbose=1 || true
- name: Bundle non-Qt dylibs into app
run: |
# Find the .app bundle
APP=$(find build/bin -name "*.app" -maxdepth 1 | head -1)
if [ -z "$APP" ]; then
echo "No .app bundle found, creating one manually..."
APP="build/bin/Triangles-Qt.app"
mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Frameworks"
cp build/bin/triangles-qt "$APP/Contents/MacOS/Triangles-Qt"
fi
FRAMEWORKS="$APP/Contents/Frameworks"
BINARY=$(find "$APP/Contents/MacOS" -type f -perm +111 | head -1)
# Copy Homebrew dylibs that macdeployqt doesn't handle
for lib in boost_system boost_filesystem boost_thread boost_program_options boost_chrono; do
DYLIB=$(otool -L "$BINARY" | grep "$lib" | awk '{print $1}')
if [ -n "$DYLIB" ] && [ -f "$DYLIB" ]; then
cp "$DYLIB" "$FRAMEWORKS/"
BASENAME=$(basename "$DYLIB")
install_name_tool -change "$DYLIB" "@executable_path/../Frameworks/$BASENAME" "$BINARY"
fi
done
for lib in libssl libcrypto libevent libdb_cxx libminiupnpc libsodium; do
DYLIB=$(otool -L "$BINARY" | grep "$lib" | awk '{print $1}')
if [ -n "$DYLIB" ] && [ -f "$DYLIB" ]; then
cp "$DYLIB" "$FRAMEWORKS/"
BASENAME=$(basename "$DYLIB")
install_name_tool -change "$DYLIB" "@executable_path/../Frameworks/$BASENAME" "$BINARY"
fi
done
echo "=== Final dylib dependencies ==="
otool -L "$BINARY" | head -30
- name: Bundle Tor into app
run: |
TOR_VERSION="15.0.9"
curl -sL "https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/tor-expert-bundle-macos-aarch64-${TOR_VERSION}.tar.gz" -o tor-bundle.tar.gz
mkdir -p tor-extract && tar -xzf tor-bundle.tar.gz -C tor-extract
APP=$(find build/bin -name "*.app" -maxdepth 1 | head -1)
mkdir -p "$APP/Contents/MacOS/tor"
cp tor-extract/tor/tor "$APP/Contents/MacOS/tor/"
chmod +x "$APP/Contents/MacOS/tor/tor"
[ -d tor-extract/data ] && cp -r tor-extract/data "$APP/Contents/MacOS/tor/data"
- name: Create DMG
run: |
APP=$(find build/bin -name "*.app" -maxdepth 1 | head -1)
mkdir -p dmg_contents
cp -R "$APP" dmg_contents/
ln -s /Applications dmg_contents/Applications
hdiutil create -volname "Cryptographic Triangles" \
-srcfolder dmg_contents \
-ov -format UDZO \
"Cryptographic-Triangles-v${VERSION}-macos-arm64.dmg"
- name: Upload DMG
uses: actions/upload-artifact@v4
with:
name: macos-arm64-dmg
path: "*.dmg"
release:
if: startsWith(github.ref, 'refs/tags/v')
needs: [build-windows-qt, build-windows-daemon, build-linux-qt, build-linux-daemon, build-macos]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Set VERSION from tag
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release assets
run: |
mkdir -p release
# Windows Qt installer (setup.exe — includes Tor, Start Menu shortcuts, uninstaller)
cp artifacts/windows-qt-setup/*.exe release/
# Windows daemon (zip with DLLs + Tor)
cd artifacts/windows-daemon && zip -r "../../release/Cryptographic-Triangles-${VERSION}-win-x64-daemon.zip" . && cd ../..
# Linux Qt .deb (dpkg -i to install — includes Tor, desktop entry, icon)
cp artifacts/linux-qt-deb/*.deb release/
# Linux daemon .deb (dpkg -i to install — includes Tor, systemd service)
cp artifacts/linux-daemon-deb/*.deb release/
# macOS DMG (drag to Applications — Tor inside .app bundle)
cp artifacts/macos-arm64-dmg/*.dmg release/
ls -la release/
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: release/*
generate_release_notes: true
trigger-tripi:
name: Trigger TRI-PI ARM64 Build
if: startsWith(github.ref, 'refs/tags/v')
needs: release
runs-on: ubuntu-latest
steps:
- name: Dispatch tri-pi ARM64 build
run: |
curl -f -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.TRIPI_BUILD_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/SamiAhmed7777/tri-pi/dispatches \
-d '{"event_type":"new-release","client_payload":{"version":"${{ github.ref_name }}","source_repo":"SamiAhmed7777/triangles_v5"}}'
echo "Triggered tri-pi repository_dispatch for ${{ github.ref_name }}"