feat: enhance desktop build process with artifact upload and download, and update server working directory resolution
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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',
|
||||||
|
|||||||
@@ -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'))
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user