fix(update): bundle app-update.yml so electron-updater can install (forge omits it) (#2244)
* fix(update): generate app-update.yml at build time; drop runtime setFeedURL electron-forge does not emit app-update.yml; electron-updater requires it at process.resourcesPath to resolve the GitHub release feed. Without it every packaged app threw ENOENT on the first download attempt, making updates detected but never installed. Two-part fix: - forge.config.ts: add postPackage hook that writes app-update.yml into each platform's Resources dir (baked from AO_RELEASE_REPO so fork builds point at the fork, prod at AgentWrapper/agent-orchestrator). - auto-updater.ts: remove setFeedURL + repo() + DEFAULT_RELEASE_REPO; configureFeed now only sets channel + allowDowngrade. electron-updater auto-loads the bundled yml on the first checkForUpdates call. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: format with prettier [skip ci] * fix(update): generate app-update.yml before signing, not after The postPackage hook wrote app-update.yml into Contents/Resources AFTER osxSign sealed the bundle, so the added file was unsealed and macOS reported the app as "damaged" (codesign: "a sealed resource is missing or invalid"). Generate it in a prePackage hook and ship it via packagerConfig.extraResource, so it is copied into the bundle and signed as part of the seal. The generated app-update.yml is gitignored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: format with prettier [skip ci] * ci(release): move Intel leg to macos-15-intel and gate the feed on it macos-13 is deprecated and has no runner capacity (multi-hour queues), so the detached release-intel leg never completed. Switch it to the supported macos-15-intel image in both the release and nightly workflows. Now that the Intel leg gets a runner and builds + signs the x64 installer reliably (verified on fork v0.10.10), re-couple it into publish-feed (needs: [release, release-intel]) so latest-mac.yml / nightly-mac.yml always carry the x64 entry and Intel macOS users receive auto-updates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
ff23e66055
commit
965e388792
|
|
@ -93,15 +93,15 @@ jobs:
|
|||
# macOS signing + notarization env is exported by the "macOS signing
|
||||
# setup" step above via $GITHUB_ENV; the cert is in the keychain.
|
||||
|
||||
# Dedicated Intel (darwin-x64) nightly build leg, decoupled from the release
|
||||
# matrix so the scarce macos-13 runner does not block publish-feed. Mirrors
|
||||
# the release job's macOS steps exactly. publish-feed stays needs: release
|
||||
# only (three fast legs); the x64 feed entry appears if this job finishes
|
||||
# first, but the feed is not gated on it.
|
||||
# Dedicated Intel (darwin-x64) nightly build leg. Kept separate from the
|
||||
# release matrix (only a macOS host can build the x64 installer); publish-feed
|
||||
# now waits on it so the x64 entry is present in nightly-mac.yml and Intel
|
||||
# nightly users get auto-updates. Mirrors the release job's macOS steps exactly.
|
||||
# Runner is macos-15-intel (macos-13 deprecated/no capacity; see release wf).
|
||||
release-intel:
|
||||
needs: guard
|
||||
if: needs.guard.outputs.should_build == 'true'
|
||||
runs-on: macos-13
|
||||
runs-on: macos-15-intel
|
||||
permissions:
|
||||
contents: write
|
||||
defaults:
|
||||
|
|
@ -161,7 +161,7 @@ jobs:
|
|||
# assets. The nightly version is only stamped in-memory on the build runners,
|
||||
# so derive the tag from the guard job's computed version, not package.json.
|
||||
publish-feed:
|
||||
needs: [guard, release]
|
||||
needs: [guard, release, release-intel]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ jobs:
|
|||
# release the publish step just created, with --clobber (so re-runs replace).
|
||||
#
|
||||
# Arch-coverage note: each runner only builds its host arch. macos-latest
|
||||
# (Apple silicon) produces darwin-arm64; macos-13 (Intel x64) produces
|
||||
# (Apple silicon) produces darwin-arm64; macos-15-intel (Intel x64) produces
|
||||
# darwin-x64. Both macOS runners run this step (see the `if` below), so the
|
||||
# arm64 and x64 stable aliases are now both built (spec §8).
|
||||
# The Linux stable name is undecided (spec §11.3), so we build the deb/rpm
|
||||
|
|
@ -155,13 +155,14 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Dedicated Intel (darwin-x64) build leg, decoupled from the release matrix so
|
||||
# the scarce macos-13 runner does not block publish-feed. publish-feed needs
|
||||
# only the three fast legs (release); this job uploads the x64 installer and
|
||||
# stable alias independently. feed.mjs includes the x64 entry if this job
|
||||
# finishes before publish-feed, but the feed is not gated on it.
|
||||
# Dedicated Intel (darwin-x64) build leg. Kept a separate job (not in the
|
||||
# release matrix) because only a macOS host can build the x64 installer, but
|
||||
# publish-feed now waits on it (needs: [release, release-intel]) so the x64
|
||||
# entry is always present in latest-mac.yml and Intel users get auto-updates.
|
||||
# Runner is macos-15-intel: macos-13 is deprecated/has no capacity (multi-hour
|
||||
# queues), so this leg uses the supported Intel x64 image.
|
||||
release-intel:
|
||||
runs-on: macos-13
|
||||
runs-on: macos-15-intel
|
||||
environment: release # same approval gate as the matrix release job
|
||||
permissions:
|
||||
contents: write
|
||||
|
|
@ -216,7 +217,7 @@ jobs:
|
|||
# assets and upload them to the same release. Runs once, on Linux: it only
|
||||
# hashes already-built artifacts, so it needs no per-OS runner.
|
||||
publish-feed:
|
||||
needs: release
|
||||
needs: [release, release-intel]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
app-update.yml
|
||||
|
|
@ -2,6 +2,7 @@ import type { ForgeConfig } from "@electron-forge/shared-types";
|
|||
import { VitePlugin } from "@electron-forge/plugin-vite";
|
||||
import MakerNSIS from "./makers/maker-nsis";
|
||||
import MakerAppImage from "./makers/maker-appimage";
|
||||
import { writeFileSync } from "node:fs";
|
||||
|
||||
// Default GitHub release target (production). aoagents was the temporary rewrite
|
||||
// home; releases land on AgentWrapper (spec §1.1).
|
||||
|
|
@ -30,7 +31,7 @@ const config: ForgeConfig = {
|
|||
// (.icns on macOS, .ico on Windows); Linux menu icons come from the
|
||||
// deb/rpm makers below, and the runtime window icon from src/main.ts.
|
||||
icon: "assets/icon",
|
||||
extraResource: ["daemon", "assets/icon.png"],
|
||||
extraResource: ["daemon", "assets/icon.png", "app-update.yml"],
|
||||
// Notarization. Two paths:
|
||||
// - CI: an App Store Connect API key. APPLE_API_KEY is a PATH to the .p8
|
||||
// (the workflow decodes APPLE_API_KEY_BASE64 to a temp file), plus the
|
||||
|
|
@ -53,6 +54,27 @@ const config: ForgeConfig = {
|
|||
}
|
||||
: undefined,
|
||||
},
|
||||
hooks: {
|
||||
// electron-forge does not generate app-update.yml (electron-builder does);
|
||||
// electron-updater reads it from the app's Resources dir at runtime to know
|
||||
// which GitHub repo to pull from, else it throws ENOENT during download.
|
||||
// Generate it in prePackage (BEFORE osxSign) and ship it via extraResource
|
||||
// above, so it is copied into the bundle and SIGNED as part of the seal.
|
||||
// Writing it after signing (a postPackage hook) adds an unsealed resource
|
||||
// and macOS reports the app as "damaged". owner/repo are baked from
|
||||
// AO_RELEASE_REPO at build time.
|
||||
prePackage: async () => {
|
||||
const { owner, name } = parseReleaseRepo(process.env.AO_RELEASE_REPO);
|
||||
const yml = [
|
||||
"provider: github",
|
||||
`owner: ${owner}`,
|
||||
`repo: ${name}`,
|
||||
"updaterCacheDirName: agent-orchestrator-updater",
|
||||
"",
|
||||
].join("\n");
|
||||
writeFileSync("app-update.yml", yml);
|
||||
},
|
||||
},
|
||||
rebuildConfig: {},
|
||||
makers: [
|
||||
// Windows installer: NSIS via electron-builder (see makers/maker-nsis.ts).
|
||||
|
|
|
|||
|
|
@ -10,22 +10,12 @@ import {
|
|||
type UpdateStatus,
|
||||
} from "./update-settings";
|
||||
|
||||
// Default release repo, mirroring backend cli.releaseRepo. Override via env for
|
||||
// fork test builds (AO_RELEASE_REPO=owner/repo).
|
||||
const DEFAULT_RELEASE_REPO = "AgentWrapper/agent-orchestrator";
|
||||
|
||||
function repo(): { owner: string; name: string } {
|
||||
const [owner, name] = (process.env.AO_RELEASE_REPO || DEFAULT_RELEASE_REPO).split("/");
|
||||
if (owner && name) return { owner, name };
|
||||
const [defOwner, defName] = DEFAULT_RELEASE_REPO.split("/");
|
||||
return { owner: defOwner, name: defName };
|
||||
}
|
||||
|
||||
// configureFeed points electron-updater at the GitHub Releases feed for the
|
||||
// chosen channel. Shared by the launch auto-check and the manual Settings flow.
|
||||
// configureFeed sets the update channel on electron-updater. The repo/owner
|
||||
// are loaded automatically from app-update.yml (written by forge.config.ts's
|
||||
// postPackage hook into the app's Resources dir at build time). No runtime env
|
||||
// or setFeedURL call is needed; electron-updater reads the bundled yml on first
|
||||
// checkForUpdates.
|
||||
function configureFeed(channel: UpdateChannel): void {
|
||||
const { owner, name } = repo();
|
||||
autoUpdater.setFeedURL({ provider: "github", owner, repo: name });
|
||||
autoUpdater.channel = channel; // "latest" | "nightly"
|
||||
autoUpdater.allowDowngrade = true; // permits a nightly -> stable channel switch
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue