Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
24093ca
fix: strip nested node_modules from file:-linked packages + tar --for…
Mar 24, 2026
38093cc
fix: Windows build — strip nested node_modules + tar --force-local
BitHighlander Mar 24, 2026
382635e
fix: CSV report exports were dead clicks
BitHighlander Mar 24, 2026
fc34656
Merge pull request #61 from keepkey/fix/csv-report-dead-clicks
BitHighlander Mar 24, 2026
da793f1
feat: add KeepKey CSV export with full portfolio data
BitHighlander Mar 24, 2026
114c08e
fix: tx history empty — wrong Pioneer method name + no retry on async…
BitHighlander Mar 24, 2026
62bbd20
Merge pull request #63 from keepkey/fix/pioneer-tx-history
BitHighlander Mar 24, 2026
443df87
feat: add Zcash deshielding (Orchard → transparent)
BitHighlander Mar 24, 2026
6424663
fix: address validation, fee estimation, and progress channel for des…
BitHighlander Mar 24, 2026
88450d6
Merge pull request #64 from keepkey/feat/zcash-deshielding
BitHighlander Mar 25, 2026
82d70e3
feat: add mobile pairing via vault.keepkey.com relay
BitHighlander Mar 26, 2026
f88259f
fix: remove unused imports from MobilePanel
BitHighlander Mar 26, 2026
3089c35
Merge pull request #67 from keepkey/feat/mobile-pairing
BitHighlander Mar 26, 2026
5112ba9
fix: use user's fiat currency and locale settings consistently app-wide
BitHighlander Mar 26, 2026
faa2406
fix: address review — reports stay USD, AnimatedUsd uses Intl, zero p…
BitHighlander Mar 26, 2026
17e3e1d
fix: CI macOS dual-arch builds + architecture verification gate
BitHighlander Mar 26, 2026
5a431c2
fix: sign-release uploads signed auto-update payloads, guards against…
BitHighlander Mar 26, 2026
38d680f
fix: install protoc on macOS CI runners for zcash-cli build
BitHighlander Mar 26, 2026
3ad56da
fix: use macos-15-intel runner for x86_64 builds (macos-13 deprecated)
BitHighlander Mar 26, 2026
dee7bc1
fix: build x64 macOS variant via binary swap on ARM64 runner
BitHighlander Mar 26, 2026
739cd5e
Merge pull request #69 from keepkey/fix/ci-macos-dual-arch
BitHighlander Mar 26, 2026
25010fb
fix: swap node-hid prebuild to x64 in Intel variant (required for fir…
BitHighlander Mar 26, 2026
9ae714d
chore: bump version to 1.2.10
BitHighlander Mar 26, 2026
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
236 changes: 233 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ jobs:
fail-fast: false
matrix:
include:
# macOS and Windows are built + signed locally (see `make build-signed`)
- name: Linux x64
runner: ubuntu-latest
artifact-suffix: linux-x64

- name: macOS
runner: macos-14
artifact-suffix: macos
expected-arch: arm64

steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -72,6 +76,16 @@ jobs:
path: projects/keepkey-vault/node_modules
key: vault-${{ runner.os }}-${{ hashFiles('projects/keepkey-vault/package.json') }}

- name: Cache Rust/Cargo (macOS)
if: runner.os == 'macOS'
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
projects/keepkey-vault/zcash-cli/target
key: zcash-cli-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('projects/keepkey-vault/zcash-cli/Cargo.lock') }}

- name: Build modules (hdwallet + proto-tx-builder)
shell: bash
run: |
Expand Down Expand Up @@ -131,6 +145,20 @@ jobs:
run: cd projects/keepkey-vault && bun install
shell: bash

- name: Install protoc (macOS)
if: runner.os == 'macOS'
run: brew install protobuf

- name: Build zcash-cli sidecar (macOS)
if: runner.os == 'macOS'
shell: bash
run: |
echo "=== Building zcash-cli for $(uname -m) ==="
cd projects/keepkey-vault/zcash-cli
cargo test
cargo build --release
file target/release/zcash-cli

- name: Build unsigned app (CI mode)
env:
CI: 'true'
Expand All @@ -141,6 +169,198 @@ jobs:
run: cd projects/keepkey-vault && bun scripts/prune-app-bundle.ts
shell: bash

- name: Verify binary architecture (macOS)
if: runner.os == 'macOS'
shell: bash
run: |
EXPECTED="${{ matrix.expected-arch }}"
echo "=== Verifying macOS binary architecture (expecting $EXPECTED) ==="

TAR_ZST=$(find projects/keepkey-vault/artifacts -name "*.app.tar.zst" | head -1)
if [ -z "$TAR_ZST" ]; then echo "::error::No .app.tar.zst found"; exit 1; fi

WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT

zstd -d "$TAR_ZST" -o "$WORK/app.tar" --force
LAUNCHER=$(tar tf "$WORK/app.tar" | grep "MacOS/launcher$" | head -1)
BUN_BIN=$(tar tf "$WORK/app.tar" | grep "MacOS/bun$" | head -1)

if [ -z "$LAUNCHER" ]; then echo "::error::No launcher binary found in archive"; exit 1; fi
tar xf "$WORK/app.tar" -C "$WORK/" "$LAUNCHER"
if [ -n "$BUN_BIN" ]; then tar xf "$WORK/app.tar" -C "$WORK/" "$BUN_BIN"; fi

echo "Checking binaries:"
for BIN in "$WORK/$LAUNCHER" "$WORK/$BUN_BIN"; do
[ -f "$BIN" ] || continue
ACTUAL=$(lipo -archs "$BIN" 2>/dev/null)
NAME=$(basename "$BIN")
echo " $NAME: $ACTUAL"
if [ "$ACTUAL" != "$EXPECTED" ]; then
echo "::error::Architecture mismatch! $NAME is $ACTUAL but expected $EXPECTED"
exit 1
fi
done

# Also verify node-hid prebuild matches
HID_DIR=$(tar tf "$WORK/app.tar" | grep "node-hid/prebuilds/HID-darwin" | head -1)
if [ -n "$HID_DIR" ]; then
echo " node-hid prebuild dir: $(dirname $HID_DIR | xargs basename)"
fi

echo "Architecture verified: $EXPECTED"

- name: Create unsigned DMG (macOS)
if: runner.os == 'macOS'
shell: bash
run: |
cd projects/keepkey-vault/artifacts
TAR_ZST=$(ls *.app.tar.zst 2>/dev/null | head -1)
if [ -z "$TAR_ZST" ]; then echo "No .app.tar.zst found, skipping DMG"; exit 0; fi

VERSION=$(grep '"version"' ../package.json | head -1 | sed 's/.*"version": "\(.*\)".*/\1/')
ARCH=$(uname -m)
DMG_NAME="KeepKey-Vault-${VERSION}-${ARCH}.dmg"
echo "Creating unsigned DMG: $DMG_NAME"

STAGING=$(mktemp -d)
trap 'rm -rf "$STAGING"' EXIT

zstd -d "$TAR_ZST" -o "$STAGING/app.tar" --force
tar xf "$STAGING/app.tar" -C "$STAGING/"
rm "$STAGING/app.tar"

APP=$(find "$STAGING" -name "*.app" -maxdepth 1 | head -1)
if [ -z "$APP" ]; then echo "No .app found after extraction"; exit 1; fi

ln -s /Applications "$STAGING/Applications"
hdiutil create -volname "KeepKey Vault" -srcfolder "$STAGING" -ov -format UDZO "$DMG_NAME"
echo "Created: $DMG_NAME (unsigned — sign locally with 'make sign-release')"

- name: Create x86_64 variant (macOS)
if: runner.os == 'macOS'
shell: bash
run: |
echo "=== Creating x86_64 variant from ARM64 build ==="

# Get Electrobun version for downloading matching x64 binaries
ELECTROBUN_VER=$(node -p "require('./projects/keepkey-vault/node_modules/electrobun/package.json').version")
echo "Electrobun version: v$ELECTROBUN_VER"

# Download x64 Electrobun core binaries
echo "Downloading Electrobun core for x86_64..."
curl -fsSL "https://github.com/blackboardsh/electrobun/releases/download/v${ELECTROBUN_VER}/electrobun-core-darwin-x64.tar.gz" \
-o /tmp/electrobun-core-x64.tar.gz
mkdir -p /tmp/electrobun-x64
tar xzf /tmp/electrobun-core-x64.tar.gz -C /tmp/electrobun-x64/

# Find the directory containing the x64 binaries (handles nested or flat tar structure)
X64_BIN_DIR=$(find /tmp/electrobun-x64 -name "launcher" -type f -exec dirname {} \; | head -1)
if [ -z "$X64_BIN_DIR" ]; then echo "::error::No launcher found in electrobun-core-x64"; exit 1; fi
echo "x64 binaries at: $X64_BIN_DIR"
ls "$X64_BIN_DIR/"

# Find the ARM64 tar.zst
ARM64_TAR=$(find projects/keepkey-vault/artifacts -name "*.app.tar.zst" | head -1)
if [ -z "$ARM64_TAR" ]; then echo "::error::No ARM64 tar.zst found"; exit 1; fi
echo "Source: $ARM64_TAR"

# Extract the ARM64 .app
WORK=$(mktemp -d)
zstd -d "$ARM64_TAR" -o "$WORK/app.tar" --force
tar xf "$WORK/app.tar" -C "$WORK/"
rm "$WORK/app.tar"

APP=$(find "$WORK" -name "*.app" -maxdepth 1 | head -1)
if [ -z "$APP" ]; then echo "::error::No .app found after extraction"; exit 1; fi

# Swap Electrobun runtime binaries with x64 versions
echo "Swapping Electrobun binaries for x86_64..."
for BIN in launcher bun libNativeWrapper.dylib libasar.dylib; do
SRC="$X64_BIN_DIR/$BIN"
DEST=$(find "$APP" -name "$BIN" -type f | head -1)
if [ -f "$SRC" ] && [ -n "$DEST" ]; then
cp "$SRC" "$DEST"
ARCH=$(lipo -archs "$DEST" 2>/dev/null || echo "non-macho")
echo " $BIN: $ARCH"
elif [ -f "$SRC" ]; then
echo " $BIN: not found in .app (skipping)"
fi
done

# Swap node-hid prebuilds: replace ARM64 with x64 (required for firmware updates + HID transport)
HID_SRC="projects/keepkey-vault/node_modules/node-hid/prebuilds/HID-darwin-x64"
if [ -d "$HID_SRC" ]; then
HID_DEST=$(find "$APP" -type d -name "HID-darwin-arm64" | head -1)
if [ -n "$HID_DEST" ]; then
HID_PARENT=$(dirname "$HID_DEST")
rm -rf "$HID_DEST"
cp -r "$HID_SRC" "$HID_PARENT/HID-darwin-x64"
echo " node-hid: swapped ARM64 → x64 prebuild"
else
echo " node-hid: HID-darwin-arm64 not found in bundle (skipping)"
fi
else
echo "::warning::node-hid HID-darwin-x64 prebuild not found in node_modules"
fi

# Remove zcash-cli from x64 bundle (Zcash shielded not supported on Intel)
ZCASH_DEST=$(find "$APP" -name "zcash-cli" -type f | head -1)
if [ -n "$ZCASH_DEST" ]; then
rm "$ZCASH_DEST"
echo " zcash-cli: removed (Intel not supported)"
fi

# Verify key binaries are now x86_64
echo "Verifying swapped binaries:"
FAIL=0
for BIN in launcher bun; do
FOUND=$(find "$APP" -name "$BIN" -path "*/MacOS/*" | head -1)
if [ -n "$FOUND" ]; then
ACTUAL=$(lipo -archs "$FOUND" 2>/dev/null)
echo " $BIN: $ACTUAL"
if [ "$ACTUAL" != "x86_64" ]; then
echo "::error::$BIN is $ACTUAL, expected x86_64"
FAIL=1
fi
fi
done
if [ "$FAIL" = "1" ]; then exit 1; fi

# Re-pack as x64 tar.zst
X64_TAR="projects/keepkey-vault/artifacts/stable-macos-x64-keepkey-vault.app.tar.zst"
(cd "$WORK" && tar cf - "$(basename "$APP")") | zstd -o "$X64_TAR" --force
echo "Created: $X64_TAR ($(du -h "$X64_TAR" | cut -f1))"

# Cleanup
rm -rf "$WORK" /tmp/electrobun-x64 /tmp/electrobun-core-x64.tar.gz

- name: Create unsigned x86_64 DMG (macOS)
if: runner.os == 'macOS'
shell: bash
run: |
cd projects/keepkey-vault/artifacts
TAR_ZST="stable-macos-x64-keepkey-vault.app.tar.zst"
if [ ! -f "$TAR_ZST" ]; then echo "No x64 tar.zst, skipping DMG"; exit 0; fi

VERSION=$(grep '"version"' ../package.json | head -1 | sed 's/.*"version": "\(.*\)".*/\1/')
DMG_NAME="KeepKey-Vault-${VERSION}-x86_64.dmg"
echo "Creating unsigned x86_64 DMG: $DMG_NAME"

STAGING=$(mktemp -d)
trap 'rm -rf "$STAGING"' EXIT

zstd -d "$TAR_ZST" -o "$STAGING/app.tar" --force
tar xf "$STAGING/app.tar" -C "$STAGING/"
rm "$STAGING/app.tar"

APP=$(find "$STAGING" -name "*.app" -maxdepth 1 | head -1)
if [ -z "$APP" ]; then echo "No .app found after extraction"; exit 1; fi

ln -s /Applications "$STAGING/Applications"
hdiutil create -volname "KeepKey Vault" -srcfolder "$STAGING" -ov -format UDZO "$DMG_NAME"
echo "Created: $DMG_NAME (unsigned — sign locally with 'make sign-release')"

- name: Package AppImage (Linux)
if: runner.os == 'Linux'
run: |
Expand Down Expand Up @@ -203,8 +423,8 @@ jobs:
- name: Generate checksums
run: |
cd projects/keepkey-vault/artifacts
shasum -a 256 * > SHA256SUMS.txt 2>/dev/null || true
cat SHA256SUMS.txt
shasum -a 256 * > SHA256SUMS-${{ matrix.artifact-suffix }}.txt 2>/dev/null || true
cat SHA256SUMS-${{ matrix.artifact-suffix }}.txt

- name: List artifacts
run: ls -lh projects/keepkey-vault/artifacts/
Expand Down Expand Up @@ -246,6 +466,16 @@ jobs:
path: artifacts
merge-multiple: true

- name: Generate combined checksums
run: |
cd artifacts
# Remove per-platform checksum files (will regenerate combined)
rm -f SHA256SUMS-*.txt SHA256SUMS.txt
# Generate checksums for release-worthy files only
shasum -a 256 *.dmg *.AppImage *.exe *.tar.zst 2>/dev/null > SHA256SUMS.txt || true
echo "=== Release checksums ==="
cat SHA256SUMS.txt

- name: List release artifacts
run: find artifacts -type f | sort

Expand Down
Loading
Loading