feat: add desktop node installation CI/CD and documentation

- Add Windows x86_64 build target to release.yml for synord/synor-cli
- Create release-wallet.yml workflow for Tauri desktop wallet builds
  - macOS (Intel + Apple Silicon), Windows, Linux support
  - Code signing integration (Apple + Windows certificates)
  - Tauri auto-update signing support
- Fix Dockerfiles to include src/ directory required by workspace
- Add CODE_SIGNING.md documentation for Apple/Windows certificates
This commit is contained in:
Gulshan Yadav 2026-02-02 00:43:20 +05:30
parent 97f42cb990
commit 3d161afd9d
6 changed files with 424 additions and 4 deletions

202
.github/workflows/release-wallet.yml vendored Normal file
View file

@ -0,0 +1,202 @@
name: Release Desktop Wallet
on:
push:
tags:
- 'wallet-v*'
workflow_dispatch:
inputs:
draft:
description: 'Create as draft release'
required: false
default: true
type: boolean
env:
CARGO_TERM_COLOR: always
permissions:
contents: write
jobs:
build-tauri:
name: Build Wallet (${{ matrix.platform }})
strategy:
fail-fast: false
matrix:
include:
- platform: macos-latest
target: aarch64-apple-darwin
artifact-suffix: macos-aarch64
- platform: macos-latest
target: x86_64-apple-darwin
artifact-suffix: macos-x86_64
- platform: windows-latest
target: x86_64-pc-windows-msvc
artifact-suffix: windows-x86_64
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install pnpm
run: npm install -g pnpm
- name: Setup Rust
uses: dtolnay/rust-action@stable
with:
targets: ${{ matrix.target }}
- name: Install dependencies (macOS)
if: matrix.platform == 'macos-latest'
run: |
brew install rocksdb
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: ${{ runner.os }}-${{ matrix.target }}-cargo-wallet-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.target }}-cargo-wallet-
- name: Cache pnpm store
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('apps/desktop-wallet/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install frontend dependencies
working-directory: apps/desktop-wallet
run: pnpm install
- name: Build Tauri app
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# macOS code signing (optional - set these secrets in GitHub)
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
# Tauri updater signing (optional - for auto-updates)
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: apps/desktop-wallet
tagName: wallet-v__VERSION__
releaseName: 'Synor Wallet v__VERSION__'
releaseBody: |
## Synor Desktop Wallet
A secure desktop wallet for the Synor blockchain network with post-quantum cryptography support (Dilithium3).
### Installation
**macOS:**
- Download the `.dmg` file for your architecture (Intel or Apple Silicon)
- Open the DMG and drag Synor Wallet to Applications
- First launch: Right-click → Open (to bypass Gatekeeper if not code-signed)
**Windows:**
- Download the `.msi` installer
- Run the installer and follow the prompts
- Or download the `.exe` for portable installation
### Features
- 24-word BIP39 mnemonic generation
- Post-quantum Dilithium3 signatures
- OS keychain integration (macOS Keychain, Windows Credential Manager)
- System tray support
- Auto-updates (when signed)
### Security Note
Always verify the checksums of downloaded files.
releaseDraft: ${{ github.event.inputs.draft || true }}
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
args: --target ${{ matrix.target }}
# Build Linux AppImage separately (needs different runner config)
build-linux:
name: Build Wallet (Linux)
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install pnpm
run: npm install -g pnpm
- name: Setup Rust
uses: dtolnay/rust-action@stable
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf \
libclang-dev \
llvm-dev
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: ${{ runner.os }}-cargo-wallet-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-wallet-
- name: Cache pnpm store
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('apps/desktop-wallet/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install frontend dependencies
working-directory: apps/desktop-wallet
run: pnpm install
- name: Build Tauri app
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: apps/desktop-wallet
tagName: wallet-v__VERSION__
releaseName: 'Synor Wallet v__VERSION__'
releaseBody: ''
releaseDraft: ${{ github.event.inputs.draft || true }}
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}

View file

@ -37,6 +37,10 @@ jobs:
target: aarch64-apple-darwin
artifact-name: synor-macos-aarch64
archive-ext: tar.gz
- os: windows-latest
target: x86_64-pc-windows-msvc
artifact-name: synor-windows-x86_64
archive-ext: zip
steps:
- name: Checkout repository
@ -81,7 +85,8 @@ jobs:
restore-keys: |
${{ runner.os }}-${{ matrix.target }}-cargo-target-release-
- name: Build release binaries
- name: Build release binaries (Unix)
if: runner.os != 'Windows'
env:
TARGET: ${{ matrix.target }}
CROSS: ${{ matrix.cross }}
@ -93,7 +98,14 @@ jobs:
fi
cargo build --release --workspace --target "$TARGET"
- name: Prepare release archive
- name: Build release binaries (Windows)
if: runner.os == 'Windows'
env:
TARGET: ${{ matrix.target }}
run: cargo build --release --workspace --target "$env:TARGET"
- name: Prepare release archive (Unix)
if: runner.os != 'Windows'
env:
TARGET: ${{ matrix.target }}
ARTIFACT_NAME: ${{ matrix.artifact-name }}
@ -115,13 +127,44 @@ jobs:
cd release
tar czvf "../$ARTIFACT_NAME.tar.gz" *
- name: Upload release artifact
- name: Prepare release archive (Windows)
if: runner.os == 'Windows'
env:
TARGET: ${{ matrix.target }}
ARTIFACT_NAME: ${{ matrix.artifact-name }}
run: |
New-Item -ItemType Directory -Force -Path release
# Copy binaries
Copy-Item "target/$env:TARGET/release/synord.exe" release/ -ErrorAction SilentlyContinue
Copy-Item "target/$env:TARGET/release/synor-cli.exe" release/ -ErrorAction SilentlyContinue
Copy-Item "target/$env:TARGET/release/synor-faucet.exe" release/ -ErrorAction SilentlyContinue
Copy-Item "target/$env:TARGET/release/synor-explorer.exe" release/ -ErrorAction SilentlyContinue
# Copy documentation
Copy-Item README.md release/ -ErrorAction SilentlyContinue
Copy-Item LICENSE* release/ -ErrorAction SilentlyContinue
Copy-Item CHANGELOG.md release/ -ErrorAction SilentlyContinue
# Create archive
Compress-Archive -Path release/* -DestinationPath "$env:ARTIFACT_NAME.zip"
- name: Upload release artifact (Unix)
if: runner.os != 'Windows'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact-name }}
path: ${{ matrix.artifact-name }}.tar.gz
retention-days: 1
- name: Upload release artifact (Windows)
if: runner.os == 'Windows'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact-name }}
path: ${{ matrix.artifact-name }}.zip
retention-days: 1
create-release:
name: Create GitHub Release
runs-on: ubuntu-latest
@ -187,7 +230,7 @@ jobs:
echo "" >> CHANGELOG_BODY.md
echo '```' >> CHANGELOG_BODY.md
cd artifacts
find . -name "*.tar.gz" -exec sha256sum {} \; | sed 's|./[^/]*/||' >> ../CHANGELOG_BODY.md
find . \( -name "*.tar.gz" -o -name "*.zip" \) -exec sha256sum {} \; | sed 's|./[^/]*/||' >> ../CHANGELOG_BODY.md
echo '```' >> CHANGELOG_BODY.md
- name: Create GitHub Release
@ -199,6 +242,7 @@ jobs:
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
files: |
artifacts/**/*.tar.gz
artifacts/**/*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -20,6 +20,7 @@ WORKDIR /app
# Copy manifests first (for better caching)
COPY Cargo.toml Cargo.lock ./
COPY src/ src/
COPY crates/ crates/
COPY apps/ apps/
COPY contracts/ contracts/

View file

@ -19,6 +19,7 @@ WORKDIR /app
# Copy manifests
COPY Cargo.toml Cargo.lock ./
COPY src/ src/
COPY crates/ crates/
COPY apps/ apps/

View file

@ -20,6 +20,7 @@ WORKDIR /app
# Copy manifests first (for better caching)
COPY Cargo.toml Cargo.lock ./
COPY src/ src/
COPY crates/ crates/
COPY apps/ apps/

171
docs/CODE_SIGNING.md Normal file
View file

@ -0,0 +1,171 @@
# Code Signing Setup Guide
This guide explains how to set up code signing for Synor desktop applications.
## Why Code Sign?
Code signing provides:
- **User trust**: No "unknown developer" warnings on macOS/Windows
- **Auto-updates**: Tauri's updater requires signed binaries
- **Security**: Users can verify the software hasn't been tampered with
## macOS Code Signing
### Prerequisites
1. **Apple Developer Account** ($99/year): https://developer.apple.com/programs/enroll/
2. **Developer ID Application Certificate**: For distributing outside the Mac App Store
### Create Certificates
1. Go to https://developer.apple.com/account/resources/certificates/list
2. Click "+" to create a new certificate
3. Select "Developer ID Application"
4. Follow the instructions to create a CSR from Keychain Access
5. Download and install the certificate
### Export for CI/CD
```bash
# Export certificate as .p12 from Keychain Access
# Then base64 encode it for GitHub secrets:
base64 -i certificate.p12 -o certificate_base64.txt
```
### GitHub Secrets Required
| Secret | Description | How to Get |
|--------|-------------|------------|
| `APPLE_CERTIFICATE` | Base64-encoded .p12 certificate | Export from Keychain Access |
| `APPLE_CERTIFICATE_PASSWORD` | Password for .p12 | Set when exporting |
| `APPLE_SIGNING_IDENTITY` | Certificate name | e.g., "Developer ID Application: G1 Technologies (TEAMID)" |
| `APPLE_ID` | Your Apple ID email | Your developer account email |
| `APPLE_PASSWORD` | App-specific password | Generate at appleid.apple.com |
| `APPLE_TEAM_ID` | 10-character team ID | Find at developer.apple.com/account |
### Generate App-Specific Password
1. Go to https://appleid.apple.com/account/manage
2. Sign in with your Apple ID
3. Under "App-Specific Passwords", click "Generate Password"
4. Name it "Synor CI" and save the password
### Notarization
Apple requires notarization for apps distributed outside the App Store. The Tauri action handles this automatically when the secrets are set.
## Windows Code Signing
### Options
1. **OV (Organization Validation) Certificate**: ~$200-500/year
- From providers like DigiCert, Sectigo, GlobalSign
- Requires business verification
2. **EV (Extended Validation) Certificate**: ~$400-700/year
- Higher trust level, no SmartScreen warnings
- Requires hardware token (USB)
### Purchase Certificate
1. Choose a provider (DigiCert, Sectigo, GlobalSign, etc.)
2. Complete organization validation
3. Receive certificate file (.pfx)
### GitHub Secrets Required
| Secret | Description |
|--------|-------------|
| `WINDOWS_CERTIFICATE` | Base64-encoded .pfx certificate |
| `WINDOWS_CERTIFICATE_PASSWORD` | Password for .pfx |
### Encode Certificate
```powershell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("certificate.pfx")) | Out-File certificate_base64.txt
```
## Tauri Auto-Update Signing
### Generate Signing Keypair
```bash
# Generate keypair (do this once, store securely)
cargo tauri signer generate -w ~/.tauri/synor-wallet.key
```
This outputs:
- Private key (save to `TAURI_SIGNING_PRIVATE_KEY` secret)
- Public key (already in `tauri.conf.json`)
### GitHub Secrets Required
| Secret | Description |
|--------|-------------|
| `TAURI_SIGNING_PRIVATE_KEY` | Private key from signer generate |
| `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` | Password if you set one |
### Update tauri.conf.json
The public key is already configured in `apps/desktop-wallet/src-tauri/tauri.conf.json`:
```json
"updater": {
"endpoints": [
"https://releases.synor.io/wallet/{{target}}/{{arch}}/{{current_version}}"
],
"pubkey": "YOUR_PUBLIC_KEY_HERE"
}
```
## Setting Up GitHub Secrets
1. Go to your repository on GitHub
2. Navigate to Settings → Secrets and variables → Actions
3. Click "New repository secret" for each secret
## Testing Without Signing
For development and testing, you can build without signing:
```bash
cd apps/desktop-wallet
pnpm tauri:build
```
Users will see warnings, but the app will still work.
## Verification
### macOS
```bash
# Check if app is signed
codesign -dv --verbose=4 "Synor Wallet.app"
# Check if notarized
spctl -a -v "Synor Wallet.app"
```
### Windows
```powershell
# Check signature
Get-AuthenticodeSignature "Synor Wallet.exe"
```
## Cost Summary
| Item | Cost (Annual) |
|------|---------------|
| Apple Developer Program | $99 |
| Windows OV Certificate | $200-500 |
| Windows EV Certificate | $400-700 |
**Minimum recommended**: Apple + Windows OV = ~$300-600/year
## Resources
- [Tauri Code Signing Guide](https://tauri.app/guides/building/code-signing/)
- [Apple Developer Documentation](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution)
- [Microsoft Authenticode](https://docs.microsoft.com/en-us/windows/win32/seccrypto/authenticode)