Ha spedito la build di Electron, la pagina di rilascio è live e arriva il primo ticket di supporto prima che il macchinario del caffè finisca. Un utente dice che l'app non ha trovato l'aggiornamento. Un altro l'ha scaricato ma non può installarlo. Un terzo sta ancora eseguendo una versione vecchia con un flusso di autenticazione rotto, mentre i suoi log mostrano quasi nulla utile.
That’s the uncomfortable reality of l'aggiornamento automatico dell'app Electron. The updater API is only one component. A production release also depends on platform signing, transport policy, manifests, hosting, lifecycle events, observability, rollout controls, and a rollback path. Treat any one of those as optional and a routine patch can become an overnight incident.
la firma della piattaforma
- The 2 A.M. Update Incident That Started This Guide
- Scegliere il Percorso di Aggiornamento Electron Giusto
- La vicenda di aggiornamento notturna che ha ispirato questa guida
- Wiring CI/CD per rilasci firmati e manifesti
- Rollout, canali e strategia di rollback
- Treating Auto-Update as a Security Control
- Il Runbook e il Checklist di Aggiornamento di Produzione
The 2 A.M. Update Incident That Started This Guide
La release era passata al CI e sembrava ordinaria. La sera di venerdì, un developer ha spinto un build di Electron non firmato, e il job di pubblicazione ha caricato abbastanza asset per rendere la release completa. L'applicazione è stata lanciata in testing, ma nessuno aveva esercitato il percorso di aggiornamento da un build di produzione installato.
At 2:08 a.m., PagerDuty ha avvertito l'ingegnere in servizio. Una nuova flussi di autenticazione è fallita per una parte della flotta, e gli utenti che hanno ricevuto l'aggiornamento non sono riusciti a completare l'accesso. Gli altri utenti sono rimasti sulla versione precedente perché l'aggiornatore non è stato in grado di verificare o installare l'artifact. Alcuni clienti avevano una versione rotta, mentre il resto della flotta ha eseguito una versione diversa senza una spiegazione chiara.
Il team ha condotto cinque controlli:
- Controllare il feed di rilascio. Esisteva il binario, ma i metadati previsti non stabilivano chiaramente quali clienti dovrebbero riceverlo. Un manifesto è un contratto tra la pipeline di rilascio e i clienti installati, non un dettaglio di caricamento facoltativo.
- Ispezionare la firma. La rilascio non era firmata correttamente, quindi la verifica è fallita sulle piattaforme interessate. La firma deve bloccare la pubblicazione quando è mancante o invalida.
- Confrontare i log dei clienti. Gli errori di aggiornamento non raggiungono mai la telemetria centrale. L'applicazione ingoia l'evento e continua a funzionare, lasciando il team senza prove affidabili.
- Controllare i controlli di distribuzione. Non c'era un canale interno o un gruppo di staging. Tutti i clienti idonei utilizzavano lo stesso feed, quindi il fallimento si è propagato senza un punto di contenimento.
- Cercare un rollback. La squadra non aveva una procedura testata per ripubblicare la versione precedente o per dirigere i clienti lontano dalla versione rotta.
La documentazione ufficiale di Electron chiarisce i limiti della piattaforma. Linux has no built-in auto-updater supporte richiedono aggiornamenti macOS App Transport Security requirementsLa documentazione identifica inoltre la firma come prerequisito per aggiornamenti macOS affidabili e verifica delle versioni di rilascio. Electron autoUpdater documentation definisce le API restrizioni, mentre il sistema di rilascio deve attuare i controlli operativi circostanti.
Lezione postuma: Si raccomanda di consultare la documentazione ufficiale di Electron per ulteriori informazioni.
The cost extended beyond engineering time. Customers lost confidence in the desktop client, support had to explain inconsistent behavior, and the team spent the next workday rebuilding a release process that should have existed before the incident.
Aggiornamento automatico come un sistema operativo. La firma è una porta di uscita di rilascio, i manifesti definiscono il contratto del client, i canali di rilascio limitano l'esposizione e il rollback rimane un percorso testato piuttosto che un'invenzione di emergenza.
Scegliere il Percorso Giusto per l'Aggiornamento di Electron
Alle 2 del mattino, la scelta sbagliata dell'aggiornatore diventa un problema operativo. Un aggiornamento binario nativo deve gestire la firma, i manifesti, gli installatori e il rollback. Un cambiamento JavaScript o CSS esclusivamente per il renderer segue un percorso diverso. Le restrizioni di hosting anche contano: un piccolo progetto ospitato da GitHub non ha bisogno dei medesimi controlli di rilascio di un servizio di distribuzione aziendale.
Per progetti che utilizzano electron-builder con pubblicazione di artefatti firmati, electron-updater è di solito la scelta pratica di default. La sua ecosistema copre i target di pubblicazione, i manifesti di rilascio, i download degli artefatti e l'installazione alla prossima esecuzione. Supporta diversi modelli di hosting, ma il tuo team deve comunque gestire la firma, la disponibilità del feed, la politica dei canali, i controlli di rilascio e la monitoraggio. Il L'integrazione dell'aggiornatore di Electron per Capgo è rilevante quando si valuta un modello di consegna ibrido per i bundle di layer web accanto ai rilasci nativi.
update-electron-app si adatta a team che vogliono un'integrazione piccola intorno ai rilasci di GitHub. Controlla all'avvio e poi su un intervallo ricorrente, il che mantiene la configurazione semplice ma lascia meno spazio per la selezione avanzata dei canali, il traffico in fase di staging e le regole di rollback personalizzate. Il pacchetto è ragionevole per un processo di rilascio piccolo, purché i rilasci di GitHub e la sua disponibilità siano in linea con i requisiti operativi.
| Opzione | Controllo di Hosting | Supporto alla Firma | Canali & Staged Rollout | Fardello di Manutenzione |
|---|---|---|---|---|
| electron-updater | S3, GitHub, HTTPS generico e altri target di pubblicazione | Integra la firma di rilascio del pacchetto | Fondamento solido, la politica personalizzata vive di solito intorno al feed | Moderato |
| aggiorna-app-elettronica | Lavora principalmente con semplici flussi di rilascio GitHub | Utilizza il modello di firma di base di Electron | Limitato a meno che non si aggiungano servizi circostanti | Basso |
| Squirrel.Windows o Squirrel.Mac | Ciclo di distribuzione orientato alla piattaforma | Dipende dalle richieste di firma della piattaforma | È possibile, ma di solito richiede un'infrastruttura di rilascio aggiuntiva | Moderato per applicazioni legacy |
| Servizio personalizzato | Pieno controllo sui manifesti, l'autorizzazione, i cohort e i feed | La gestione della verifica e delle chiavi è tua responsabilità | Massima flessibilità | Alto |
| Capgo aggiornamenti in tempo reale | Distribuzione gestita per bundle di layer web | Uses its updater and delivery model | Target di pubblico e consegna basata su canale | Modello operativo separato dalle aggiornamenti binari nativi |
Un servizio personalizzato come Hazel, Nuts o un feed interno si adatta quando l'autorizzazione di rilascio, la destinazione del tenant, i registri di audit o le regole di distribuzione regolamentate giustificano il costo di implementazione. Il trade-off è la proprietà continua. Il tuo team deve definire la semantica del manifesto, proteggere le chiavi di firma, preservare la compatibilità del client, testare i download falliti, le rilasci rifiutati e il comportamento di rollback.
Gli aggiornamenti in tempo reale possono inviare modifiche al renderer senza ricostruire la shell nativa. Non sostituiscono gli aggiornamenti binari quando cambiano Electron, moduli nativi, autorizzazioni o comportamento dell'installatore. Usa electron-updater a meno che non richieda logica di rollout personalizzata. Se è richiesta logica personalizzata, costruisci intorno alle convenzioni di manifesto e artefatto esistenti piuttosto che ricreare il comportamento di download e differenziale di aggiornamento. Un percorso affidabile è quello che il tuo team può osservare, mettere in scena e annullare sotto pressione.
Implementare il Flusso di Aggiornamento Auto in Processo Principale
Il processo principale dovrebbe gestire i controlli di aggiornamento e l'installazione. Il renderer può visualizzare lo stato, ma non dovrebbe decidere se un aggiornamento eseguibile è affidabile o quando l'applicazione esce.
Configura il target di pubblicazione per primo
Una configurazione minimale di electron-builder potrebbe avere questo aspetto:
{
"build": {
"appId": "com.example.desktop",
"publish": [
{
"provider": "s3",
"bucket": "example-electron-releases",
"channel": "stable"
}
],
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true
}
}
}
Tenere separate le feed beta e stabili. Un canale è una politica di rilascio, non un etichetta nell'interfaccia utente. Ogni canale dovrebbe risolvere correttamente l'artefatto firmato e il manifesto.
Programmare controlli e esporre eventi di ciclo di vita
Chiamare checkForUpdates() Solo durante l'avvio è un comune errore di produzione. Un utente può lasciare l'applicazione aperta per giorni, quindi il processo principale ha bisogno di un intervallo controllato e una strategia di riprova che rispetti l'operazione offline.
const { app, BrowserWindow, ipcMain } = require('electron');
const { autoUpdater } = require('electron-updater');
let mainWindow;
let isQuitting = false;
let retryDelay = 60 * 1000;
function sendUpdateStatus(status, payload = {}) {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('update-status', { status, ...payload });
}
}
function scheduleUpdateCheck() {
setTimeout(async () => {
try {
await autoUpdater.checkForUpdates();
retryDelay = 60 * 1000;
} catch (error) {
sendUpdateStatus('error', { message: error.message });
retryDelay = Math.min(retryDelay * 2, 30 * 60 * 1000);
}
scheduleUpdateCheck();
}, retryDelay);
}
app.whenReady().then(() => {
mainWindow = new BrowserWindow({
webPreferences: {
preload: require('path').join(__dirname, 'preload.js')
}
});
autoUpdater.autoDownload = true;
autoUpdater.autoInstallOnAppQuit = false;
autoUpdater.on('checking-for-update', () => {
sendUpdateStatus('checking');
});
autoUpdater.on('update-available', info => {
sendUpdateStatus('available', { version: info.version });
});
autoUpdater.on('download-progress', progress => {
sendUpdateStatus('progress', { percent: progress.percent });
});
autoUpdater.on('update-downloaded', info => {
sendUpdateStatus('downloaded', { version: info.version });
});
autoUpdater.on('error', error => {
sendUpdateStatus('error', { message: error.message });
});
autoUpdater.checkForUpdates().catch(error => {
sendUpdateStatus('error', { message: error.message });
});
scheduleUpdateCheck();
});
ipcMain.handle('install-update', () => {
isQuitting = true;
autoUpdater.quitAndInstall(false, true);
});
app.on('before-quit', event => {
if (!isQuitting) {
return;
}
});
Il comportamento esatto dell'evento di aggiornamento varia a seconda della piattaforma e della configurazione di packaging, quindi testa dagli artefatti installati piuttosto che dal modo di sviluppo. La documentazione di Electron anche segnala preoccupazioni relative al timing di avvio su Windows, compreso il caso Squirrel di prima esecuzione. Non attivare un controllo di aggiornamento prima che l'applicazione abbia completato l'inizializzazione specifica della piattaforma di cui ha bisogno.
Tenere informato il renderer senza bloccare il lavoro
La passerella di preload dovrebbe esporre un API ristretto:
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('updates', {
onStatus(callback) {
ipcRenderer.on('update-status', (_event, status) => callback(status));
},
install() {
return ipcRenderer.invoke('install-update');
}
});
Un barra di avanzamento del renderer può rimanere deliberatamente semplice:
window.updates.onStatus(status => {
const progress = document.querySelector('#update-progress');
const message = document.querySelector('#update-message');
if (status.status === 'progress') {
progress.hidden = false;
progress.value = status.percent;
message.textContent = `Downloading update, ${Math.round(status.percent)}%`;
}
if (status.status === 'downloaded') {
message.textContent = `Version ${status.version} is ready to install`;
}
if (status.status === 'error') {
message.textContent = 'The update could not be downloaded. We will retry later.';
}
});
Installazione della porta dietro consenso dell'utente in produzione a meno che la tua applicazione non abbia una forte ragione per riavviarsi immediatamente. Imposta un isQuitting flag prima quitAndInstall()perché i normali gestori di chiusura della finestra possono altrimenti impedire all'installatore di prendere il controllo.

Due a due fallimenti meritano test espliciti. Primo, un client già in esecuzione deve chiamare checkForUpdates() su un orario prestabilito, non solo al lancio. Secondo, l' error evento deve raggiungere i log e la telemetria. Se l'app assorbe l'evento senza segnalarlo, il tuo Flusso di lavoro di risoluzione problemi dell'app si basa sulle congetture invece che sull'evidenza.
Wiring CI/CD per rilasci firmati e manifesti
La pipeline di rilascio è la fonte di verità per ciò che gli utenti installano. Una costruzione locale che funziona su una macchina di un singolo sviluppatore non dimostra che il binario pubblicato, il manifesto, la firma e il canale descrivano tutti la stessa versione.
L'Electron-builder richiede che i metadati di rilascio e l'obiettivo di aggiornamento viaggino insieme. Per molte configurazioni, ciò significa un artefatto come latest.yml per Windows e latest-mac.yml per macOS, insieme a pacchetti specifici per piattaforma e file di blockmap. Un manifesto mancante può rendere un binario perfettamente valido invisibile ai client.
Fai esplicito il firmatario in CI
Un pattern di Actions semplificato di GitHub assomiglia a questo:
name: release
on:
push:
tags:
- "v*"
jobs:
build:
strategy:
matrix:
os: [macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run test
- run: npm run build
- name: Build and publish
shell: bash
env:
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: npx electron-builder --publish always
Utilizzare segreti specifici per piattaforma e mantenere il materiale di firma fuori dal repository. Un fallimento di firma dovrebbe fermare il lavoro, non produrre un fallback non firmato che qualcuno carica manualmente.
| Variabile | Scopo |
|---|---|
CSC_LINK |
Certificato macOS o riferimento al certificato |
CSC_KEY_PASSWORD |
Password per il materiale di firma macOS |
WIN_CSC_LINK |
Certificato Windows o riferimento al certificato |
AWS_ACCESS_KEY_ID |
Creare credenziali di pubblicazione con accesso ristretto |
AWS_SECRET_ACCESS_KEY |
Segreto associato alle credenziali di pubblicazione |
La configurazione di pubblicazione dovrebbe identificare il provider e il canale coerentemente:
{
"build": {
"publish": {
"provider": "s3",
"bucket": "example-electron-releases",
"channel": "stable",
"publishAutoUpdate": true,
"updaterCacheDirName": "example-desktop-updater"
}
}
}
Prima della pubblicazione, blocca il lavoro sulla versione del pacchetto, sulla etichetta, sul SHA del commit e sul risultato del test di fumo. Dopo la pubblicazione, verificare che il feed contenga il manifesto previsto e che il manifesto punti all'artefatto esatto generato da quel lavoro. Il Guida di configurazione per l'integrazione continua è utile quando formalizzi quei controlli, e le squadre che confrontano l'orchestrazione delle pipeline possono anche trarre vantaggio dall'aver capito When usare insieme Jenkins e Ansible.
Il comando che comunemente esporre un rilascio incompleto è intenzionalmente noioso:
npx electron-builder --publish never
test -f dist/latest.yml
test -f dist/latest-mac.yml
find dist -name "*.blockmap" -print
Quei controlli non sostituiscono un test di installazione firmato. Catturano l'errore operativo di caricamento di un binario senza i metadati necessari per scoprirlo.
Rollout, canali e strategia di annullamento
Un feed di rilascio dovrebbe comportarsi più come un obiettivo di distribuzione che come una cartella di download. Mantieni interni, beta, e ultimo canali separati, con ogni canale supportato da un proprio manifesto e set di artefatti firmati. La promozione dovrebbe spostare un rilascio testato tra le politiche, non sovrascrivere un file mentre i clienti lo stanno scaricando.
La separazione dei canali protegge anche la produzione da costruzioni di test accidentalali. L'aggiornatore dovrebbe sapere se un client appartiene a un gruppo di cohort interno, un pubblico di beta o alla popolazione stabile prima di valutare il feed.
Utilizzare i cohort prima dell'esposizione ampia
A custom manifest field can express staged delivery:
version: 4.8.0
path: Example-Setup-4.8.0.exe
sha512: signed-artifact-hash
rolloutPercentage: 10
Il processo principale può assegnare un bucket stabile per utente, quindi confrontarlo con rolloutPercentage. L'assegnazione stabile conta. Un utente che si sposta tra stati eleggibili e non eleggibili a ogni controllo riceverà comportamenti imprevedibili e renderà i rapporti di supporto difficili da interpretare.
Espandere il cohorto solo dopo che la release ha superato la sua finestra di osservazione. La finestra esatta dovrebbe riflettere il tuo pattern di utilizzo, ma la decisione dovrebbe essere basata su segnali, non su un calendario da solo. Tracciare i risultati delle verifiche di aggiornamento, la completa del download, la salute di lancio, i crash, le eccezioni del renderer e il successo dell'autenticazione.
| Segnale | Azione | Motivo |
|---|---|---|
| Errori di feed o firma superano il limite approvato dalla squadra | Ritardare il rollout | I clienti potrebbero non essere in grado di validare o scoprire la release |
| I controlli di lancio post-aggiornamento falliscono | Ripristina feed | Il binario può installarsi ma fallire durante l'avvio |
| Le eccezioni del renderer aumentano dopo la promozione | Mantenersi all'attuale cohort | L'installatore nativo può essere sano mentre la nuova applicazione code non lo è |
| I segnali rimangono entro il budget di rilascio | Espandere la cohort | Le prove supportano un'esposizione più ampia |
Non confondere il rollback con la cancellazione di un artefatto. Gli clienti esistenti possono avere i metadati memorizzati in cache, e alcuni possono già essere in esecuzione della versione cattiva. Un piano di rollback richiede una versione precedente firmata, un cambio di feed e un comportamento del client che possa riprendersi.
Regola operativa: Il rollback deve essere eseguibile dall'ingegnere di chiamata senza ricostruire l'applicazione durante l'incidente.
In pratica, il runbook dovrebbe promuovere il manifesto di rilascio precedente di nuovo nel canale interessato, invalidare il marker di staging e confermare che le nuove verifiche risolvano alla versione sicura. Se l'errore è nel renderer code piuttosto che nella shell nativa, un rollback web-layer mirato può essere più veloce. Una piattaforma come Capgo rollouts fasi Può essere rilevante per quel livello di consegna separata, ma non deve oscurare il confine tra un rollback binario nativo e un rollback di bundle web.
Treating Auto-Update as a Security Control
Un aggiornatore di Electron scarica l'eseguibile code e può installarlo con una bassa interazione utente. Ciò rende il percorso di aggiornamento un barriera di sicurezza, non solo una caratteristica di comodità. La documentazione ufficiale di Electron descrive le restrizioni del sistema come ATS di macOS, e la copertura di sicurezza ha documentato uno scenario del 2022 in cui gli attaccanti che controllavano l'infrastruttura di aggiornamento potevano servire pacchetti maliziosi che superavano comunque i controlli di firma code, come discusso nella documentazione di sicurezza di aggiornamento di Electron Builder.
La firma di Code rimane fondamentale, ma non è l'intero modello di fiducia. Firmare ogni rilascio, verificare il certificato e l'identità durante la CI e mantenere una procedura di rotazione delle chiavi documentata. Su macOS, combinare la firma con la notarizzazione e il runtime hardenato appropriato per l'applicazione. Su Windows, rendere la proprietà del certificato, la rinnovazione e l'accesso alla costruzione auditabile. Linux richiede una strategia specifica per la distribuzione perché Electron non fornisce un aggiornatore universale integrato lì.
Proteggere i metadati con la stessa cura del binario
A un binario firmato può ancora essere associato alla versione sbagliata se il canale di metadati è compromesso o configurato in modo errato. Considera l'aggiunta di una firma di manifesto verificata contro una chiave pubblica incorporata nell'applicazione, imponi una versione minima consentita e rifiuta le riduzioni inaspettate a meno che un percorso di recupero autorizzato non le consenta esplicitamente.
La feed merita anche controlli di produzione:
- Limitare l'accesso alla pubblicazione: Dai solo alle CI le autorizzazioni necessarie per pubblicare gli asset delle versioni.
- Proteggere i segreti di firma: Mantieni i certificati e le chiavi private in archiviazione segreta gestita, non nei file del repository.
- Pianifica le dipendenze: Blocca Electron, electron-builder e le dipendenze transitive nelle CI.
- Verifica gli artefatti: Scansiona i pacchetti generati e confrontali con il commit e la versione previsti.
- Richiedi un trasporto sicuro: Segui i requisiti ATS e HTTPS rigorosi per le richieste di aggiornamento.
- Verifica fallimenti di monitoraggio: Tratta fallimenti ripetuti di firma o manifesto come eventi di sicurezza, non come rumore di rete ordinario.
L'ecosistema di strumenti mantenuti da Electron continua ad aggiungere copertura di packaging e aggiornamenti, ma la manutenzione non elimina la necessità di modellazione di minacce. L'obiettivo pratico è assicurarsi che un attaccante che compromette un contenitore, una rete CDN o un passaggio di costruzione non possa comunque far accettare al client un rilascio non autorizzato. La guida per la verifica della firma fornisce un utile contesto per progettare quella layer di verifica aggiuntiva.

Il Runbook e il Checklist di Rilascio
Un rilascio è pronto solo quando un altro ingegnere può operarlo sotto pressione. Tieni il checklist vicino al lavoro di deployment e al canale degli incidenti.
Gli ostacoli di pre-rilascio
- L'identità della versione: Conferma la versione del pacchetto, la tag di rilascio, l'SHA del commit e il changelog.
- La firma: Verifica che ogni artefatto del sistema sia firmato e che la notarizzazione o la validazione equivalente sia stata completata.
- Contratto del manifesto: Conferma
latest.yml,latest-mac.yml, hash, percorsi e blockmap corrispondono agli artefatti caricati. - Sicurezza del canale: Pubblica sul feed interno o beta prima di promuovere il canale di rilascio.
- Telemetria: Verifiche di aggiornamento confermate, progresso di download, completamento dell'installazione, salute al lancio e errori in arrivo.
Canarino e rilascio completo
- Controllo del cohort: Inizia con un piccolo pubblico interno o beta deliberatamente limitato.
- Budget di salute: Tenere la promozione se le fallite di lancio, le fallite di download dell'aggiornamento, le eccezioni del renderer o le fallite di autenticazione superano i limiti approvati dalla squadra.
- Approvazione della promozione: Richiedere una decisione esplicita di andare o non andare prima di spostare la versione nella feed stabile.
- Impatto del cliente: Preparare il messaggio di supporto prima della distribuzione ampia, non dopo il primo incidente.
Risposta all'incidente
Se il nuovo binario non riesce a lanciarsi, la creazione di processi si blocca o i download degli aggiornamenti si interrompono, fermare la promozione immediatamente. Ripristina il manifesto firmato precedente, invalida il marker di staging e verifica che i clienti freschi si risolvano alla versione precedente. Poi conferma attraverso la telemetria che la flotta sta riprendendo prima di comunicare la chiusura.
Le comandi di rollback esatti dipendono dal tuo provider, ma la sequenza dovrebbe essere sempre documentata: Capovolgi il manifesto del canale alla versione precedente, invalida il tag di staging, sposta un marker di aggiornamento forzato se il recupero lo richiede e verifica il percorso di downgrade con la telemetria in tempo reale.Un rollback non testato è solo una speranza.

Capgo offre un aggiornatore per Electron per consegnare cambiamenti di layer web firmati, canali mirati, controlli di distribuzione e osservabilità degli aggiornamenti senza ricostruire la shell nativa per ogni cambiamento del renderer. Se vuoi separare le rilasci binari native dalle consegne di JavaScript e CSS controllate, visita Capgo e valuta insieme alla tua pipeline di rilascio di Electron.