agent-orchestrator/frontend/forge.config.ts

159 lines
5.9 KiB
TypeScript

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).
const DEFAULT_RELEASE_REPO = "AgentWrapper/agent-orchestrator";
// parseReleaseRepo turns an "owner/repo" string (from AO_RELEASE_REPO) into the
// publisher-github { owner, name } shape, falling back to the production default
// when unset or malformed.
function parseReleaseRepo(value: string | undefined): { owner: string; name: string } {
const [owner, name] = (value || DEFAULT_RELEASE_REPO).split("/");
if (!owner || !name) {
const [defOwner, defName] = DEFAULT_RELEASE_REPO.split("/");
return { owner: defOwner, name: defName };
}
return { owner, name };
}
const config: ForgeConfig = {
packagerConfig: {
asar: true,
appBundleId: "dev.agent-orchestrator.desktop",
name: "Agent Orchestrator",
executableName: "agent-orchestrator",
appCategoryType: "public.app-category.developer-tools",
// App icon. electron-packager appends the per-platform extension
// (.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", "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
// key id + issuer uuid. Matches the proven local runbook creds.
// - Local: AO_NOTARY_PROFILE, a notarytool keychain profile created with
// `notarytool store-credentials`. See ao-macos-signed-release runbook.
// Both are valid NotaryToolCredentials, so no cast is needed.
osxSign: process.env.APPLE_SIGNING_IDENTITY
? { identity: process.env.APPLE_SIGNING_IDENTITY }
: process.env.CSC_LINK
? {}
: undefined,
osxNotarize: process.env.AO_NOTARY_PROFILE
? { keychainProfile: process.env.AO_NOTARY_PROFILE }
: process.env.APPLE_API_KEY
? {
appleApiKey: process.env.APPLE_API_KEY,
appleApiKeyId: process.env.APPLE_API_KEY_ID!,
appleApiIssuer: process.env.APPLE_API_ISSUER!,
}
: 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).
// Replaces Squirrel.Windows, which only does per-user installs with no
// custom install dir or proper uninstaller (issue #401).
new MakerNSIS(
{
appId: "dev.agent-orchestrator.desktop",
productName: "Agent Orchestrator",
icon: "assets/icon.ico",
},
["win32"],
),
{ name: "@electron-forge/maker-zip", platforms: ["darwin"], config: {} },
// Linux fetch-and-run artifact for `ao start`: a single self-contained
// AppImage the Go bootstrapper downloads and runs directly (see
// makers/maker-appimage.ts). The deb/rpm makers below stay for users who
// prefer a system package.
new MakerAppImage(
{
appId: "dev.agent-orchestrator.desktop",
productName: "Agent Orchestrator",
icon: "assets/icon.png",
},
["linux"],
),
{
name: "@electron-forge/maker-deb",
config: {
options: {
// Must match packagerConfig.executableName, or the deb maker
// looks for the package name and fails with "could not find
// the Electron app binary". (Both are "agent-orchestrator".)
bin: "agent-orchestrator",
icon: "assets/icon.png",
maintainer: "Agent Orchestrator",
homepage: "https://github.com/aoagents/agent-orchestrator",
},
},
},
{
name: "@electron-forge/maker-rpm",
config: {
options: {
icon: "assets/icon.png",
// rpmbuild rejects a spec with an empty License field.
license: "MIT",
homepage: "https://github.com/aoagents/agent-orchestrator",
},
},
},
],
publishers: [
{
name: "@electron-forge/publisher-github",
// Release target is build-time overridable so a fork run publishes to the
// fork without a source edit. AO_RELEASE_REPO is "owner/repo"; it defaults
// to the production target. The dev/test loop sets
// AO_RELEASE_REPO=harshitsinghbhandari/agent-orchestrator (spec §1.1, §8).
// Note: aoagents/agent-orchestrator was the temporary rewrite home and is
// intentionally NOT the default; releases land on AgentWrapper.
config: {
repository: parseReleaseRepo(process.env.AO_RELEASE_REPO),
prerelease: process.env.AO_RELEASE_PRERELEASE === "true",
draft: false,
},
},
],
plugins: [
new VitePlugin({
build: [
{ entry: "src/main.ts", config: "vite.main.config.ts", target: "main" },
{ entry: "src/preload.ts", config: "vite.preload.config.ts", target: "preload" },
{ entry: "src/annotate-preload.ts", config: "vite.preload.config.ts", target: "preload" },
],
renderer: [{ name: "main_window", config: "vite.renderer.config.ts" }],
}),
],
};
export default config;