Налаштування автоматичного CI/CD для збірки десктоп-додатку
Десктоп-додаток на Electron, Tauri або Qt — це не веб-сервіс: кожен релиз потрібно зібрати під Windows (x64, arm64), macOS (Intel, Apple Silicon), Linux (deb, rpm, AppImage). Робити це вручну означає вісім-десять збірок вручну, потенціальні помилки при підписі та трудомістка публікація. CI/CD усуває цю механічну роботу.
Архітектура пайплайну
Типовий пайплайн для кросплатформеного десктоп-додатку:
push to main / tag v*
│
├── lint & unit tests (ubuntu-latest, швидко)
│
├── build:windows (windows-latest)
├── build:macos (macos-latest, Intel + arm64)
└── build:linux (ubuntu-latest)
│
└── sign & notarize (macOS)
│
└── draft GitHub Release / upload to S3
│
└── notify (Slack/Telegram)
GitHub Actions: матричная сборка
# .github/workflows/build.yml
name: Build Desktop App
on:
push:
tags:
- 'v*'
workflow_dispatch:
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
platform: win
arch: x64
- os: macos-latest
platform: mac
arch: x64
- os: macos-latest
platform: mac
arch: arm64
- os: ubuntu-22.04
platform: linux
arch: x64
runs-on: ${{ matrix.os }}
name: Build ${{ matrix.platform }}-${{ matrix.arch }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build & package (Electron)
env:
CSC_LINK: ${{ secrets.APPLE_CERT_P12 }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
WIN_CSC_LINK: ${{ secrets.WIN_CERT_P12 }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CERT_PASSWORD }}
run: |
npx electron-builder \
--${{ matrix.platform }} \
--${{ matrix.arch }} \
--publish never
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dist-${{ matrix.platform }}-${{ matrix.arch }}
path: dist/
retention-days: 7
Підпис коду
Без підпису Windows показує SmartScreen «Файл завантажений з інтернету», macOS — блокує Gatekeeper.
Windows: сертифіката Code Signing (EV або OV) від DigiCert/Sectigo/Certum. EV дає миттєву репутацію в SmartScreen.
macOS: Developer ID Application сертифіката з Apple Developer Program ($99/рік) + нотаризація.
Секрети зберігаються в GitHub Secrets, ніколи в репо:
# Додавання сертифіката в GitHub Secrets
base64 -i certificate.p12 | pbcopy
# Вставляємо в APPLE_CERT_P12 через GitHub UI
Нотаризація macOS займає 1–5 хвилин — цим пояснюється додатковий крок wait-for-notarization.
Tauri: альтернатива Electron
Для Tauri (Rust backend), сборка через офіційний tauri-action:
- name: Build Tauri app
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
with:
tagName: ${{ github.ref_name }}
releaseName: 'App v__VERSION__'
releaseBody: 'See CHANGELOG for details'
releaseDraft: true
Tauri має вбудоване обновлення (updater) — підписані update.json та бінари автоматично публікуються в релиз.
Авто-обновлення
Electron + electron-updater (частина electron-builder):
// main.js
const { autoUpdater } = require('electron-updater');
autoUpdater.setFeedURL({
provider: 'github',
owner: 'your-org',
repo: 'your-app',
private: false
});
app.whenReady().then(() => {
autoUpdater.checkForUpdatesAndNotify();
});
autoUpdater.on('update-downloaded', () => {
autoUpdater.quitAndInstall();
});
electron-builder публікує latest.yml / latest-mac.yml / latest-linux.yml в GitHub Releases. Додаток перевіряє їх при старті.
Версіонування
Версія беруться з package.json. При створенні тага v1.2.3 CI автоматично проставляє версію в збірку:
# У workflow — перед сборкою
- name: Set version from tag
run: |
VERSION="${GITHUB_REF_NAME#v}"
npm version $VERSION --no-git-tag-version
Кешування залежностей
Для Electron-проекту node_modules важить 500 МБ+. Кеш actions/setup-node з cache: 'npm' скорочує час встановлення з 3–4 хвилин до 30–60 секунд при cache hit.
Для Rust/Tauri — кеш Cargo:
- uses: Swatinem/rust-cache@v2
with:
workspaces: './src-tauri -> target'
Публікація релиза
publish:
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist-all/
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
draft: true
generate_release_notes: true
files: |
dist-all/**/*.exe
dist-all/**/*.dmg
dist-all/**/*.AppImage
dist-all/**/*.deb
dist-all/**/*.rpm
Draft-релиз дозволяє перевірити артефакти перед публічною публікацією.
Строки збірки
| Платформа | Без кешу | З кешем |
|---|---|---|
| Windows x64 | 8–12 хв | 4–6 хв |
| macOS x64 + нотаризація | 10–15 хв | 6–8 хв |
| macOS arm64 | 10–14 хв | 6–7 хв |
| Linux x64 | 5–8 хв | 2–4 хв |
Весь пайплайн (паралельно) займає 12–18 хвилин. Для Tauri — трохи довше через компіляцію Rust.
Строки налаштування
Базовий пайплайн без підпису — 1 день. Підпис Windows + нотаризація macOS + auto-updater — ще 1–2 дні (більшість часу уходит на отримання та налаштування сертифікатів).







