Packaging: build targets + Linux update-ping (v1.0.0)

- electron-builder: linux targets = deb, flatpak, tar.gz, pacman; win = nsis.
- updater.ts: Linux is notify-only (deb/pacman are package-manager owned,
  flatpak is sandboxed) — reads the same Codeberg feed as Windows and shows a
  "Blap X is available" desktop notification linking to HOW-TO-UPDATE.md.
  Windows/macOS keep electron-updater in-place install.
- HOW-TO-UPDATE.md: per-format update instructions.

Version stays 1.0.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 20:53:46 -07:00
parent aa8a765cf7
commit c9f73c26fa
3 changed files with 103 additions and 16 deletions
+35
View File
@@ -0,0 +1,35 @@
# Updating Blap
All builds are published on the **[Blap releases page](https://codeberg.org/Enkisu/Blap/releases)**.
Grab the newest file for your platform below.
## Windows
Automatic — when a new version is out, Blap shows a **"New update"** prompt; click it and Blap
updates itself. (Or download the latest `Blap Setup X.Y.Z.exe` and run it.)
## Linux
Blap can't update itself on Linux (packages are owned by your package manager / the flatpak
sandbox), so it just **notifies** you — then you update with one command for your format:
### Flatpak (Bazzite, etc.)
Download the new `Blap-X.Y.Z-x86_64.flatpak` and:
```
flatpak install --user Blap-X.Y.Z-x86_64.flatpak
```
(installing the newer bundle upgrades the existing install)
### Debian / Ubuntu (`.deb`)
```
sudo apt install ./blap_X.Y.Z_amd64.deb
```
### Arch (`.pacman`)
```
sudo pacman -U blap-X.Y.Z.pacman
```
### Portable (`.tar.gz`)
Extract the new tarball over your existing copy and run the `blap` executable — no install needed.
---
_Replace `X.Y.Z` with the version from the [releases page](https://codeberg.org/Enkisu/Blap/releases)._
+3 -5
View File
@@ -138,8 +138,7 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
channel: "latest",
},
linux: {
// AppImage is the only Linux format electron-updater can auto-update in-app.
target: ["tar.gz", "deb", "AppImage"],
target: ["deb", "flatpak", "tar.gz", "pacman"],
category: "Network;InstantMessaging;Chat",
icon: "icon.png",
executableName: variant.name, // element-desktop or element-desktop-nightly
@@ -196,9 +195,8 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
badgeIcon: "build/icon.icon",
},
win: {
// NSIS is required for electron-updater auto-update on Windows (replaces
// the old Squirrel target). msi kept for manual/enterprise installs.
target: ["nsis", "msi"],
// NSIS = the .exe installer (also what electron-updater uses on Windows).
target: ["nsis"],
signtoolOptions: {
signingHashAlgorithms: ["sha256"],
},
+65 -11
View File
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { app, ipcMain } from "electron";
import { app, ipcMain, Notification, shell } from "electron";
// electron-updater is CommonJS; this is the documented ESM interop form.
import electronUpdater, { type UpdateInfo } from "electron-updater";
@@ -14,6 +14,11 @@ const { autoUpdater } = electronUpdater;
const UPDATE_POLL_INTERVAL_MS = 60 * 60 * 1000;
const INITIAL_UPDATE_DELAY_MS = 30 * 1000;
// Blap update feed (same Codeberg release the electron-builder `publish` config points at).
const CODEBERG_BASE = "https://codeberg.org/Enkisu/Blap";
const LINUX_FEED_URL = `${CODEBERG_BASE}/releases/latest/download/latest-linux.yml`;
const HOWTO_UPDATE_URL = `${CODEBERG_BASE}/src/branch/main/HOW-TO-UPDATE.md`;
function ipcChannelSendUpdateStatus(status: boolean | string): void {
global.mainWindow?.webContents.send("check_updates", status);
}
@@ -34,18 +39,56 @@ async function pollForUpdates(): Promise<void> {
}
}
/** Compare dotted numeric versions; true if `latest` is strictly newer than `current`. */
function isNewer(latest: string, current: string): boolean {
const l = latest.split(".").map((n) => parseInt(n, 10) || 0);
const c = current.split(".").map((n) => parseInt(n, 10) || 0);
for (let i = 0; i < Math.max(l.length, c.length); i++) {
const a = l[i] ?? 0;
const b = c[i] ?? 0;
if (a !== b) return a > b;
}
return false;
}
let lastLinuxNotifiedVersion: string | undefined;
/**
* Linux notify-only update check.
*
* Linux builds can't self-install (deb/pacman are package-manager owned, flatpak
* is sandboxed), so instead of updating in place we read the same Codeberg feed
* the Windows updater uses and, if there's a newer version, show a desktop
* notification that opens HOW-TO-UPDATE.md (which has the per-format commands).
*/
async function checkLinuxUpdate(): Promise<void> {
try {
const res = await fetch(`${LINUX_FEED_URL}?t=${Date.now()}`);
if (!res.ok) return;
const text = await res.text();
const latest = /^version:\s*(.+)$/m.exec(text)?.[1]?.trim();
if (!latest || !isNewer(latest, app.getVersion())) return;
if (latest === lastLinuxNotifiedVersion) return; // don't nag every poll
lastLinuxNotifiedVersion = latest;
if (!Notification.isSupported()) return;
const notification = new Notification({
title: `Blap ${latest} is available`,
body: "Click to see how to update.",
});
notification.on("click", () => void shell.openExternal(HOWTO_UPDATE_URL));
notification.show();
} catch (e) {
console.log("Couldn't check for Linux update", e);
}
}
/**
* Start the auto-updater.
*
* Uses electron-updater, which reads its feed from `app-update.yml` baked in at
* package time from the electron-builder `publish` config (a Codeberg release
* "latest/download" URL). No runtime feed URL is needed.
*
* Notes:
* - Only works for packaged builds (dev has no app-update.yml).
* - On Linux, electron-updater only supports AppImage; deb/flatpak update via
* their own channels, so this no-ops there.
* - macOS would need a signed build + zip target to update.
* Windows/macOS use electron-updater (reads its feed from `app-update.yml`, baked
* in at package time from the electron-builder Codeberg `publish` config), which
* downloads and installs in place. Linux uses a notify-only check (see above).
* Only runs for packaged builds (dev has no app-update.yml).
*/
export async function start(): Promise<void> {
if (!app.isPackaged) {
@@ -53,6 +96,13 @@ export async function start(): Promise<void> {
return;
}
if (process.platform === "linux") {
console.log("Starting Linux update notifier (notify-only)");
setTimeout(checkLinuxUpdate, INITIAL_UPDATE_DELAY_MS);
setInterval(checkLinuxUpdate, UPDATE_POLL_INTERVAL_MS);
return;
}
console.log("Starting auto update via electron-updater");
autoUpdater.autoDownload = true;
@@ -89,4 +139,8 @@ export async function start(): Promise<void> {
}
ipcMain.on("install_update", installUpdate);
ipcMain.on("check_updates", pollForUpdates);
ipcMain.on("check_updates", () => {
// Manual "check for updates" from the renderer.
if (process.platform === "linux") void checkLinuxUpdate();
else void pollForUpdates();
});