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:
parent
97f42cb990
commit
3d161afd9d
6 changed files with 424 additions and 4 deletions
202
.github/workflows/release-wallet.yml
vendored
Normal file
202
.github/workflows/release-wallet.yml
vendored
Normal 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') }}
|
||||
52
.github/workflows/release.yml
vendored
52
.github/workflows/release.yml
vendored
|
|
@ -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 }}
|
||||
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ WORKDIR /app
|
|||
|
||||
# Copy manifests
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
COPY src/ src/
|
||||
COPY crates/ crates/
|
||||
COPY apps/ apps/
|
||||
|
||||
|
|
|
|||
|
|
@ -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
171
docs/CODE_SIGNING.md
Normal 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)
|
||||
Loading…
Add table
Reference in a new issue