diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0da1543..435c29c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,12 +14,15 @@ permissions: jobs: build: runs-on: ubuntu-latest + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: '1' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y python3 make g++ @@ -105,7 +108,16 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' + + - name: Cache Electron binary + uses: actions/cache@v4 + with: + path: ~/.cache/electron + key: electron-linux-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + electron-linux- - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y python3 make g++ xvfb @@ -143,12 +155,15 @@ jobs: name: Windows Build Verification runs-on: windows-latest needs: build + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: '1' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - name: Install npm dependencies run: npm ci diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fea3616..779cd94 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -98,7 +98,8 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - name: Install npm dependencies run: npm ci @@ -131,7 +132,8 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - name: Install npm dependencies run: npm ci @@ -167,12 +169,14 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + ELECTRON_SKIP_BINARY_DOWNLOAD: '1' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - name: Install npm dependencies run: npm ci diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index ecca90e..6a7bc8a 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -22,7 +22,8 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - run: npm ci --ignore-scripts @@ -44,7 +45,8 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - run: npm ci --ignore-scripts @@ -64,7 +66,8 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - run: npm ci --ignore-scripts @@ -74,12 +77,15 @@ jobs: test-security: name: Security Tests runs-on: ubuntu-latest + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: '1' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y python3 make g++ @@ -101,17 +107,20 @@ jobs: load-test: name: Performance Load Test runs-on: ubuntu-latest + env: + ELECTRON_SKIP_BINARY_DOWNLOAD: '1' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y python3 make g++ - - run: npm install + - run: npm ci - name: Rebuild native modules run: npm rebuild better-sqlite3-multiple-ciphers @@ -127,7 +136,8 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' + cache: 'npm' - name: Verify lockfile is committed run: | diff --git a/electron/database/init.cjs b/electron/database/init.cjs index 684dea3..f11882b 100644 --- a/electron/database/init.cjs +++ b/electron/database/init.cjs @@ -20,7 +20,12 @@ const Database = require('better-sqlite3-multiple-ciphers'); const path = require('path'); const fs = require('fs'); const crypto = require('crypto'); -const { app, safeStorage } = require('electron'); +// Guarded require: electron is only available inside the Electron main process. +// Unit tests (plain Node) load this module without launching Electron, so we +// fall back to undefined. All code paths that use app/safeStorage are inside +// function bodies that are never called during unit tests. +let app, safeStorage; +try { ({ app, safeStorage } = require('electron')); } catch { /* plain Node / CI */ } const { createSchema, createIndexes, createAuditLogTriggers, addOrgIdToExistingTables } = require('./schema.cjs'); const { runMigrations } = require('./migrations.cjs');