feat(M7): electron-builder packaging (MSI + NSIS) + electron-updater
- electron-builder.yml: msi(fixed upgradeCode)+nsis x64, asarUnpack node-pty/ssh2, npmRebuild off, publish generic for latest.yml - updater: packaged-only, OT_UPDATE_URL/OT_UPDATE_TOKEN env, ready+5s check, warn-only failures; auto-update channel is NSIS (MSI not supported by electron-updater) - scripts dist/dist:dir; win-unpacked smoke verified (native modules load)
This commit is contained in:
1 parent
fa83097528
commit
2a32ee910a
4 files changed
+110
-2
No files matched your search
@@ -0,0 +1,50 @@
|
|||||||
|
appId: site.codingplan.openterminal
|
||||||
|
productName: OpenTerminal
|
||||||
|
|
||||||
|
directories:
|
||||||
|
output: release
|
||||||
|
|
||||||
|
files:
|
||||||
|
- out/**
|
||||||
|
- package.json
|
||||||
|
|
||||||
|
asar: true
|
||||||
|
asarUnpack:
|
||||||
|
- "**/node_modules/@lydell/node-pty/**"
|
||||||
|
- "**/node_modules/ssh2/**"
|
||||||
|
|
||||||
|
# @lydell/node-pty ships prebuilt binaries; do not trigger a rebuild.
|
||||||
|
npmRebuild: false
|
||||||
|
|
||||||
|
# Electron-updater only supports NSIS auto-updates (MSI has no update channel).
|
||||||
|
# The NSIS .exe + latest.yml get uploaded together; MSI is manual/enterprise only.
|
||||||
|
win:
|
||||||
|
target:
|
||||||
|
- target: msi
|
||||||
|
- target: nsis
|
||||||
|
|
||||||
|
msi:
|
||||||
|
oneClick: false
|
||||||
|
# Fixed upgrade code keeps the upgrade chain consistent across releases.
|
||||||
|
upgradeCode: "{5ab9f79e-e4eb-4052-9df6-3af3a301ab0a}"
|
||||||
|
artifactName: ${productName}-${version}-setup.${ext}
|
||||||
|
# No build/icon.ico exists. The WiX template only emits <Icon> when an icon is
|
||||||
|
# set, but the shortcut elements still reference Icon=<iconId>, so MSI linking
|
||||||
|
# fails with LGHT0094. Disabling MSI shortcuts drops the dangling reference.
|
||||||
|
# NSIS still creates its shortcuts independently.
|
||||||
|
createDesktopShortcut: false
|
||||||
|
createStartMenuShortcut: false
|
||||||
|
|
||||||
|
nsis:
|
||||||
|
oneClick: false
|
||||||
|
allowToChangeInstallationDirectory: true
|
||||||
|
perMachine: false
|
||||||
|
artifactName: ${productName}-${version}-setup.${ext}
|
||||||
|
|
||||||
|
# Declaring a publish provider makes electron-builder emit the update-info file
|
||||||
|
# (latest.yml) into directories.output for upload. No token is stored here; the
|
||||||
|
# main agent handles feed authentication during upload. Build runs with the
|
||||||
|
# default publish policy, so nothing is uploaded from this script.
|
||||||
|
publish:
|
||||||
|
provider: generic
|
||||||
|
url: https://git.codingplan.site/api/packages/admin/generic/openterminal-update/stable/
|
||||||
+4
-2
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "open-terminal",
|
"name": "open-terminal",
|
||||||
"productName": "OpenTerminal",
|
"productName": "OpenTerminal",
|
||||||
"version": "0.1.0",
|
"version": "0.7.0",
|
||||||
"description": "Terminal with split panes, themes and fonts (XTerminal-inspired)",
|
"description": "Terminal with split panes, themes and fonts (XTerminal-inspired)",
|
||||||
"main": "out/main/index.js",
|
"main": "out/main/index.js",
|
||||||
"author": "Bill",
|
"author": "Bill",
|
||||||
@@ -10,7 +10,9 @@
|
|||||||
"dev": "electron-vite dev",
|
"dev": "electron-vite dev",
|
||||||
"build": "electron-vite build",
|
"build": "electron-vite build",
|
||||||
"preview": "electron-vite preview",
|
"preview": "electron-vite preview",
|
||||||
"typecheck": "tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json"
|
"typecheck": "tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json",
|
||||||
|
"dist": "electron-vite build && electron-builder --win msi nsis",
|
||||||
|
"dist:dir": "electron-vite build && electron-builder --win --dir"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lydell/node-pty": "^1.2.0-beta.15",
|
"@lydell/node-pty": "^1.2.0-beta.15",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { join } from 'path'
|
|||||||
import { registerIpc } from './ipc'
|
import { registerIpc } from './ipc'
|
||||||
import { killAllPtys } from './pty'
|
import { killAllPtys } from './pty'
|
||||||
import { applyStartupSystemSettings, loadSettings } from './settingsStore'
|
import { applyStartupSystemSettings, loadSettings } from './settingsStore'
|
||||||
|
import { configureAutoUpdater } from './updater'
|
||||||
|
|
||||||
function createWindow(): void {
|
function createWindow(): void {
|
||||||
const win = new BrowserWindow({
|
const win = new BrowserWindow({
|
||||||
@@ -54,6 +55,7 @@ app.whenReady().then(() => {
|
|||||||
// settings dialog is never opened this run.
|
// settings dialog is never opened this run.
|
||||||
applyStartupSystemSettings(loadSettings())
|
applyStartupSystemSettings(loadSettings())
|
||||||
createWindow()
|
createWindow()
|
||||||
|
configureAutoUpdater()
|
||||||
|
|
||||||
app.on('activate', () => {
|
app.on('activate', () => {
|
||||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { app } from 'electron'
|
||||||
|
import { autoUpdater } from 'electron-updater'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default update feed (generic provider). The main agent uploads latest.yml and
|
||||||
|
* the NSIS installer to this stable path.
|
||||||
|
*
|
||||||
|
* KNOWN LIMITATION: electron-updater does NOT support MSI auto-updates. The
|
||||||
|
* update channel always runs through the NSIS .exe (latest.yml + .exe are
|
||||||
|
* uploaded together). MSI is manual/enterprise distribution only.
|
||||||
|
*/
|
||||||
|
const DEFAULT_FEED_URL =
|
||||||
|
'https://git.codingplan.site/api/packages/admin/generic/openterminal-update/stable/'
|
||||||
|
|
||||||
|
export function configureAutoUpdater(): void {
|
||||||
|
// Update checks only run in packaged builds; no-op during development.
|
||||||
|
if (!app.isPackaged) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = process.env.OT_UPDATE_URL || DEFAULT_FEED_URL
|
||||||
|
const token = process.env.OT_UPDATE_TOKEN
|
||||||
|
|
||||||
|
autoUpdater.setFeedURL({
|
||||||
|
provider: 'generic',
|
||||||
|
url,
|
||||||
|
...(token ? { requestHeaders: { Authorization: `token ${token}` } } : {})
|
||||||
|
})
|
||||||
|
|
||||||
|
autoUpdater.logger = console
|
||||||
|
autoUpdater.autoDownload = true
|
||||||
|
autoUpdater.autoInstallOnAppQuit = true
|
||||||
|
|
||||||
|
// Check shortly after startup; log errors without crashing the app.
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
autoUpdater
|
||||||
|
.checkForUpdatesAndNotify()
|
||||||
|
.catch((err) => console.warn('[updater] checkForUpdates failed:', err))
|
||||||
|
}, 5000)
|
||||||
|
timer.unref?.()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Public entry point for later UI wiring (not connected this milestone). */
|
||||||
|
export function checkForUpdates(): Promise<void> {
|
||||||
|
if (!app.isPackaged) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
return autoUpdater
|
||||||
|
.checkForUpdates()
|
||||||
|
.then(() => {})
|
||||||
|
.catch((err) => {
|
||||||
|
console.warn('[updater] checkForUpdates failed:', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in new issue
Block a user