diff --git a/.github/workflows/ci-electron.yml b/.github/workflows/ci-electron.yml new file mode 100644 index 0000000..00dbc1f --- /dev/null +++ b/.github/workflows/ci-electron.yml @@ -0,0 +1,74 @@ +name: Electron CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build-and-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: | + package-lock.json + web/package-lock.json + native/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Install web dependencies + working-directory: web + run: npm ci + + - name: Build web + working-directory: web + run: npm run build + + - name: Setup Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Cache Rust build + uses: actions/cache@v4 + with: + path: native/target + key: native-${{ runner.os }}-x64-${{ hashFiles('native/Cargo.lock') }} + restore-keys: native-${{ runner.os }}-x64- + + - name: Install native addon dependencies + working-directory: native + run: npm ci + + - name: Build native addon + working-directory: native + run: npm run build + + - name: Build TypeScript root + run: npx tsc + + - name: Bundle Electron + working-directory: packages/electron + run: node electron/build.mjs + + - name: Pack Electron (Linux) + working-directory: packages/electron + run: npm run pack:linux + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Playwright Chrome + run: npx playwright install --with-deps chromium + + - name: Run Electron Launch Smoke Test + run: xvfb-run -a npm run test -- packages/electron/__tests__/launch-smoke.test.ts + env: + RUN_E2E_SMOKE: '1' diff --git a/package-lock.json b/package-lock.json index 15c06d0..c70c66f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codex-proxy", - "version": "2.0.41", + "version": "2.0.53", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codex-proxy", - "version": "2.0.41", + "version": "2.0.53", "workspaces": [ "packages/*" ], @@ -1220,6 +1220,22 @@ "node": ">=14" } }, + "node_modules/@playwright/test": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz", + "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.59.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.59.0", "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", @@ -5607,6 +5623,53 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", + "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.59.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", + "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/plist": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", @@ -7349,14 +7412,16 @@ }, "packages/electron": { "name": "@codex-proxy/electron", - "version": "2.0.41", + "version": "2.0.53", "dependencies": { "electron-updater": "^6.3.0" }, "devDependencies": { + "@playwright/test": "^1.59.1", "electron": "^35.7.5", "electron-builder": "^26.0.0", - "esbuild": "^0.25.12" + "esbuild": "^0.25.12", + "playwright": "^1.59.1" } }, "packages/electron/node_modules/@esbuild/aix-ppc64": { diff --git a/packages/electron/__tests__/launch-smoke.test.ts b/packages/electron/__tests__/launch-smoke.test.ts new file mode 100644 index 0000000..d90e120 --- /dev/null +++ b/packages/electron/__tests__/launch-smoke.test.ts @@ -0,0 +1,27 @@ +import { test, expect, describe } from 'vitest'; +import { _electron as electron } from 'playwright'; +import { join } from 'path'; + +describe.runIf(process.env.CI || process.env.RUN_E2E_SMOKE)('Electron App Launch Smoke Test', () => { + test('Launches and main window opens', async () => { + const executablePath = join(__dirname, '..'); + const electronApp = await electron.launch({ + args: ['--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage', executablePath], + env: { + ...process.env, + ELECTRON_ENABLE_LOGGING: '1', + } + }); + + electronApp.process().stdout?.on('data', (d) => console.log(`stdout: ${d.toString()}`)); + electronApp.process().stderr?.on('data', (d) => console.error(`stderr: ${d.toString()}`)); + + const window = await electronApp.firstWindow(); + expect(window).toBeTruthy(); + + const title = await window.title(); + expect(title).toBe('Codex Proxy Developer Dashboard'); + + await electronApp.close(); + }, 60000); +}); diff --git a/packages/electron/package.json b/packages/electron/package.json index 5c8fdd4..43e7b4f 100644 --- a/packages/electron/package.json +++ b/packages/electron/package.json @@ -6,6 +6,7 @@ "main": "dist-electron/main.cjs", "author": "codex-proxy", "scripts": { + "test": "vitest run", "build": "node electron/build.mjs", "dev": "cd ../.. && npm run build && cd packages/electron && npm run build && electron .", "prepack": "node electron/prepare-pack.mjs", @@ -19,8 +20,10 @@ "electron-updater": "^6.3.0" }, "devDependencies": { + "@playwright/test": "^1.59.1", "electron": "^35.7.5", "electron-builder": "^26.0.0", - "esbuild": "^0.25.12" + "esbuild": "^0.25.12", + "playwright": "^1.59.1" } }