1
0
forked from boos/BoosAPI

feat: enhance desktop build process with artifact upload and download, and update server working directory resolution

This commit is contained in:
cita
2026-03-06 20:25:48 +08:00
parent 6c51801e50
commit 02bf0393e6
6 changed files with 54 additions and 5 deletions
+16 -3
View File
@@ -38,6 +38,13 @@ jobs:
- name: Build - name: Build
run: npm run build run: npm run build
- name: Upload built dist
uses: actions/upload-artifact@v4
with:
name: metapi-dist-${{ github.sha }}
path: dist
if-no-files-found: error
build-packages: build-packages:
name: Build Desktop Package (${{ matrix.os }}) name: Build Desktop Package (${{ matrix.os }})
needs: verify needs: verify
@@ -101,6 +108,12 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
- name: Download built dist
uses: actions/download-artifact@v4
with:
name: metapi-dist-${{ github.sha }}
path: .
- name: Prefetch AppImage tools - name: Prefetch AppImage tools
if: runner.os == 'Linux' if: runner.os == 'Linux'
shell: bash shell: bash
@@ -132,7 +145,7 @@ jobs:
if ($env:WIN_CSC_KEY_PASSWORD_INPUT) { $env:WIN_CSC_KEY_PASSWORD = $env:WIN_CSC_KEY_PASSWORD_INPUT } if ($env:WIN_CSC_KEY_PASSWORD_INPUT) { $env:WIN_CSC_KEY_PASSWORD = $env:WIN_CSC_KEY_PASSWORD_INPUT }
for ($attempt = 1; $attempt -le 2; $attempt++) { for ($attempt = 1; $attempt -le 2; $attempt++) {
Write-Host "Desktop build attempt $attempt/2" Write-Host "Desktop build attempt $attempt/2"
npm run dist:desktop npm run package:desktop
if ($LASTEXITCODE -eq 0) { if ($LASTEXITCODE -eq 0) {
break break
} }
@@ -157,7 +170,7 @@ jobs:
set -euo pipefail set -euo pipefail
for attempt in 1 2; do for attempt in 1 2; do
echo "Desktop build attempt ${attempt}/2" echo "Desktop build attempt ${attempt}/2"
if npm run dist:desktop; then if npm run package:desktop; then
break break
fi fi
if [ "$attempt" -eq 2 ]; then if [ "$attempt" -eq 2 ]; then
@@ -186,7 +199,7 @@ jobs:
if [ -n "${APPLE_TEAM_ID_INPUT:-}" ]; then export APPLE_TEAM_ID="$APPLE_TEAM_ID_INPUT"; fi if [ -n "${APPLE_TEAM_ID_INPUT:-}" ]; then export APPLE_TEAM_ID="$APPLE_TEAM_ID_INPUT"; fi
for attempt in 1 2; do for attempt in 1 2; do
echo "Desktop build attempt ${attempt}/2" echo "Desktop build attempt ${attempt}/2"
if npm run dist:desktop; then if npm run package:desktop; then
break break
fi fi
if [ "$attempt" -eq 2 ]; then if [ "$attempt" -eq 2 ]; then
+1
View File
@@ -27,6 +27,7 @@ linux:
target: target:
- AppImage - AppImage
- deb - deb
maintainer: cita-777 <cita-777@users.noreply.github.com>
publish: publish:
provider: github provider: github
owner: cita-777 owner: cita-777
+6 -1
View File
@@ -31,6 +31,7 @@
"build:desktop": "tsc -p tsconfig.desktop.json", "build:desktop": "tsc -p tsconfig.desktop.json",
"build": "npm run build:web && npm run build:server && npm run build:desktop", "build": "npm run build:web && npm run build:server && npm run build:desktop",
"dist:desktop": "npm run build && electron-builder --config electron-builder.yml --publish never", "dist:desktop": "npm run build && electron-builder --config electron-builder.yml --publish never",
"package:desktop": "electron-builder --config electron-builder.yml --publish never",
"docs:dev": "vitepress dev docs --host 0.0.0.0 --port 4173", "docs:dev": "vitepress dev docs --host 0.0.0.0 --port 4173",
"docs:build": "vitepress build docs", "docs:build": "vitepress build docs",
"docs:preview": "vitepress preview docs --host 0.0.0.0 --port 4173", "docs:preview": "vitepress preview docs --host 0.0.0.0 --port 4173",
@@ -101,5 +102,9 @@
"overrides": { "overrides": {
"minimist": "^1.2.8" "minimist": "^1.2.8"
}, },
"author": "cita-777" "author": {
"name": "cita-777",
"email": "cita-777@users.noreply.github.com",
"url": "https://github.com/cita-777"
}
} }
+6 -1
View File
@@ -18,6 +18,7 @@ import {
createDesktopHealthUrl, createDesktopHealthUrl,
createDesktopServerUrl, createDesktopServerUrl,
isFatalServerExit, isFatalServerExit,
resolveDesktopServerWorkingDir,
waitForServerReady, waitForServerReady,
} from './runtime.js'; } from './runtime.js';
@@ -195,7 +196,11 @@ async function startManagedBackend() {
}); });
const child = spawn(process.execPath, [serverEntryPath], { const child = spawn(process.execPath, [serverEntryPath], {
cwd: app.getAppPath(), cwd: resolveDesktopServerWorkingDir({
appPath: app.getAppPath(),
resourcesPath: process.resourcesPath,
isPackaged: app.isPackaged,
}),
env: { env: {
...env, ...env,
ELECTRON_RUN_AS_NODE: '1', ELECTRON_RUN_AS_NODE: '1',
+15
View File
@@ -3,6 +3,7 @@ import {
buildDesktopServerEnv, buildDesktopServerEnv,
createDesktopServerUrl, createDesktopServerUrl,
isFatalServerExit, isFatalServerExit,
resolveDesktopServerWorkingDir,
waitForServerReady, waitForServerReady,
} from './runtime.js'; } from './runtime.js';
@@ -30,6 +31,20 @@ describe('desktop runtime helpers', () => {
expect(createDesktopServerUrl(4312)).toBe('http://127.0.0.1:4312'); expect(createDesktopServerUrl(4312)).toBe('http://127.0.0.1:4312');
}); });
it('uses resources path as backend cwd for packaged desktop builds', () => {
expect(resolveDesktopServerWorkingDir({
appPath: 'C:/Users/test/AppData/Local/Programs/Metapi/resources/app.asar',
resourcesPath: 'C:/Users/test/AppData/Local/Programs/Metapi/resources',
isPackaged: true,
})).toBe('C:/Users/test/AppData/Local/Programs/Metapi/resources');
expect(resolveDesktopServerWorkingDir({
appPath: '/workspace/metapi',
resourcesPath: '/tmp/electron/resources',
isPackaged: false,
})).toBe('/workspace/metapi');
});
it('waits until the health probe returns ok', async () => { it('waits until the health probe returns ok', async () => {
const fetcher = vi.fn() const fetcher = vi.fn()
.mockRejectedValueOnce(new Error('offline')) .mockRejectedValueOnce(new Error('offline'))
+10
View File
@@ -17,6 +17,12 @@ type ServerExitState = {
signal: NodeJS.Signals | null; signal: NodeJS.Signals | null;
}; };
type DesktopServerWorkingDirInput = {
appPath: string;
resourcesPath: string;
isPackaged: boolean;
};
const DEFAULT_READY_TIMEOUT_MS = 30_000; const DEFAULT_READY_TIMEOUT_MS = 30_000;
const DEFAULT_READY_INTERVAL_MS = 250; const DEFAULT_READY_INTERVAL_MS = 250;
@@ -43,6 +49,10 @@ export function createDesktopHealthUrl(port: number): string {
return `${createDesktopServerUrl(port)}/api/desktop/health`; return `${createDesktopServerUrl(port)}/api/desktop/health`;
} }
export function resolveDesktopServerWorkingDir(input: DesktopServerWorkingDirInput): string {
return input.isPackaged ? input.resourcesPath : input.appPath;
}
export async function waitForServerReady(input: WaitForServerReadyInput): Promise<void> { export async function waitForServerReady(input: WaitForServerReadyInput): Promise<void> {
const fetcher = input.fetcher || ((url: string, init?: RequestInit) => fetch(url, init)); const fetcher = input.fetcher || ((url: string, init?: RequestInit) => fetch(url, init));
const timeoutMs = input.timeoutMs ?? DEFAULT_READY_TIMEOUT_MS; const timeoutMs = input.timeoutMs ?? DEFAULT_READY_TIMEOUT_MS;