diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..68d269ec --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,65 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + strategy: + fail-fast: false + matrix: + include: + - os: macos-latest + platform: mac + - os: windows-latest + platform: win + - os: ubuntu-latest + platform: linux + + runs-on: ${{ matrix.os }} + + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: latest + run_install: false + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build and release (macOS) + if: matrix.platform == 'mac' + run: pnpm build:mac --publish always + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CSC_LINK: ${{ secrets.MAC_CERTS }} + CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTS_PASSWORD }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + + - name: Build and release (Windows) + if: matrix.platform == 'win' + run: pnpm build:win --publish always + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and release (Linux) + if: matrix.platform == 'linux' + run: pnpm build:linux --publish always + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/dev-app-update.yml b/dev-app-update.yml index e2b243d5..f91b51c2 100644 --- a/dev-app-update.yml +++ b/dev-app-update.yml @@ -1,3 +1,4 @@ -provider: generic -url: https://example.com/auto-updates +provider: github +owner: stablyai +repo: orca updaterCacheDirName: orca-updater diff --git a/electron-builder.yml b/electron-builder.yml index 62fd641f..bd5ea412 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -1,4 +1,4 @@ -appId: com.electron.app +appId: com.stablyai.orca productName: orca directories: buildResources: build @@ -25,7 +25,17 @@ mac: - NSMicrophoneUsageDescription: Application requests access to the device's microphone. - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. - notarize: false + hardenedRuntime: true + notarize: true + target: + - target: dmg + arch: + - x64 + - arm64 + - target: zip + arch: + - x64 + - arm64 dmg: artifactName: ${name}-${version}.${ext} linux: @@ -33,13 +43,12 @@ linux: - AppImage - snap - deb - maintainer: electronjs.org + maintainer: stablyai category: Utility appImage: artifactName: ${name}-${version}.${ext} npmRebuild: false publish: - provider: generic - url: https://example.com/auto-updates -electronDownload: - mirror: https://npmmirror.com/mirrors/electron/ + provider: github + owner: stablyai + repo: orca diff --git a/package.json b/package.json index d43d0b03..758ab103 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,8 @@ "name": "orca", "version": "1.0.0", "description": "An Electron application with React and TypeScript", - "homepage": "https://electron-vite.org", - "author": "example.com", + "homepage": "https://github.com/stablyai/orca", + "author": "stablyai", "main": "./out/main/index.js", "scripts": { "format": "oxfmt --write .", @@ -19,7 +19,10 @@ "build:unpack": "npm run build && electron-builder --dir", "build:win": "npm run build && electron-builder --win", "build:mac": "electron-vite build && electron-builder --mac", - "build:linux": "electron-vite build && electron-builder --linux" + "build:linux": "electron-vite build && electron-builder --linux", + "release:patch": "npm version patch && git push --follow-tags", + "release:minor": "npm version minor && git push --follow-tags", + "release:major": "npm version major && git push --follow-tags" }, "dependencies": { "@dnd-kit/core": "^6.3.1", diff --git a/src/main/index.ts b/src/main/index.ts index 05ece8cc..631a6ee5 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -14,6 +14,7 @@ import { registerShellHandlers } from './ipc/shell' import { registerSessionHandlers } from './ipc/session' import { registerUIHandlers } from './ipc/ui' import { warmSystemFontFamilies } from './system-fonts' +import { setupAutoUpdater } from './updater' let mainWindow: BrowserWindow | null = null let store: Store | null = null @@ -67,7 +68,7 @@ function createWindow(): BrowserWindow { // App lifecycle // --------------------------------------------------------------------------- app.whenReady().then(() => { - electronApp.setAppUserModelId('com.electron') + electronApp.setAppUserModelId('com.stablyai.orca') app.setName('Orca') if (process.platform === 'darwin') { @@ -152,6 +153,7 @@ app.whenReady().then(() => { registerSessionHandlers(store) registerUIHandlers(store) warmSystemFontFamilies() + setupAutoUpdater(mainWindow) // macOS re-activate app.on('activate', function () { diff --git a/src/main/updater.ts b/src/main/updater.ts new file mode 100644 index 00000000..5632e4ea --- /dev/null +++ b/src/main/updater.ts @@ -0,0 +1,28 @@ +import { app, BrowserWindow, dialog } from 'electron' +import { autoUpdater } from 'electron-updater' +import { is } from '@electron-toolkit/utils' + +export function setupAutoUpdater(mainWindow: BrowserWindow): void { + if (!app.isPackaged && !is.dev) return + + // In dev, electron-updater reads from dev-app-update.yml but we skip it + if (is.dev) return + + autoUpdater.autoDownload = true + autoUpdater.autoInstallOnAppQuit = true + + autoUpdater.on('update-downloaded', (info) => { + dialog + .showMessageBox(mainWindow, { + type: 'info', + title: 'Update Ready', + message: `Version ${info.version} has been downloaded. Restart to install.`, + buttons: ['Restart Now', 'Later'] + }) + .then(({ response }) => { + if (response === 0) autoUpdater.quitAndInstall() + }) + }) + + autoUpdater.checkForUpdatesAndNotify() +}