taskfile

Desktop App Publishing Example

Publishing desktop applications (Electron) to multiple distribution channels.

Supported Platforms

Platform Format Signing Distribution
macOS .dmg (Universal) Apple ID + Notarization GitHub Releases, Auto-updater
Windows .exe + .msi EV Code Signing GitHub Releases, Auto-updater
Linux .AppImage, .deb, .snap - GitHub Releases, Snap Store, Flathub

Quick Start

# Initialize project
taskfile run init

# Development
taskfile run dev              # Start dev server
taskfile run test             # Run tests
taskfile run lint             # Lint code

# Build
taskfile --platform macos run build-macos      # macOS (requires macOS)
taskfile --platform windows run build-windows  # Windows
taskfile --platform linux run build-linux      # Linux
taskfile run build-all                           # All platforms

# Code Signing (requires certs)
taskfile --platform macos run sign-macos
taskfile --platform windows run sign-windows

# Distribution
taskfile run release-github   # GitHub Releases
taskfile run release-snap     # Snap Store
taskfile run release-flathub  # Flatpak/Flathub

# Full pipeline
taskfile --env prod run publish-all

Setup

1. Initialize

taskfile run init

This creates .env.local with placeholders for:

2. macOS Notarization

Get from Apple Developer:

  1. Apple ID
  2. App-specific password (appleid.apple.com)
  3. Team ID

Set in .env.prod:

APPLE_ID=your@email.com
APPLE_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx
TEAM_ID=ABCDEF1234

3. Windows Code Signing

Options:

Set in .env.prod:

WINDOWS_CERT=/path/to/cert.pfx
WINDOWS_CERT_PASS=your-password

4. Distribution Channels

Configure in .env:

GH_RELEASES=true      # Publish to GitHub Releases
SNAP_STORE=true       # Publish to Snap Store
FLATHUB=true          # Build Flatpak for Flathub

Publishing Flow

┌─────────────┐    ┌─────────────┐    ┌─────────────────┐
│   Build     │───▶│    Sign     │───▶│   Distribute    │
│             │    │             │    │                 │
│ • macOS     │    │ • Apple ID  │    │ • GitHub        │
│ • Windows   │    │ • Windows   │    │ • Snap Store    │
│ • Linux     │    │   cert      │    │ • Flathub       │
└─────────────┘    └─────────────┘    └─────────────────┘

Task Reference

Build Tasks

Task Platform Description
build-macos macOS Build .dmg universal binary
build-windows Windows Build .exe + .msi
build-linux Linux Build .AppImage + .deb + .snap
build-all All Build all platforms (CI)

Signing Tasks

Task Requirements Description
sign-macos Apple ID + macOS Sign + notarize with Apple
sign-windows Windows cert Sign with EV/OV certificate

Distribution Tasks

Task Channel Description
release-github GitHub Create release with all artifacts
release-snap Snap Store Upload to Snapcraft
release-flathub Flathub Build Flatpak + submit PR

Full Pipeline

Task Description
publish-all Build + sign + distribute to all channels

CI/CD Integration

GitHub Actions

name: Publish Desktop
on:
  push:
    tags: ['v*']

jobs:
  publish-macos:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: taskfile --platform macos run build-macos
        env:
          APPLE_ID: $
          APPLE_APP_PASSWORD: $
      - run: taskfile --platform macos run sign-macos

  publish-windows:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: taskfile --platform windows run build-windows
      - run: taskfile --platform windows run sign-windows

  publish-linux:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: taskfile --platform linux run build-linux
      - run: taskfile run release-snap
        env:
          SNAPCRAFT_TOKEN: $

  release:
    needs: [publish-macos, publish-windows, publish-linux]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: taskfile run release-github

Auto-updater

Configure electron-updater:

// main.js
const { autoUpdater } = require('electron-updater');

autoUpdater.checkForUpdatesAndNotify();

Set server type in package.json:

{
  "build": {
    "publish": {
      "provider": "github",
      "owner": "your-org",
      "repo": "your-app"
    }
  }
}

Best Practices

  1. Separate signing from building: Build on any machine, sign only on secure machines
  2. Use CI for building: GitHub Actions with platform-specific runners
  3. Store certs securely: Use repository secrets or HSM
  4. Test auto-updates: Publish to GitHub Releases first, test update flow
  5. Version sync: Keep package.json version in sync with git tags

See Also