fix windows release #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Desktop App | ||
| on: | ||
| push: | ||
| branches: [ main, master ] | ||
| tags: [ 'v*' ] | ||
| pull_request: | ||
| branches: [ main, master ] | ||
| workflow_dispatch: | ||
| jobs: | ||
| build: | ||
| runs-on: ${{ matrix.os }} | ||
| strategy: | ||
| matrix: | ||
| os: [ubuntu-latest, windows-latest, macos-latest] | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '18' | ||
| cache: 'npm' | ||
| - name: Install dependencies | ||
| run: npm ci | ||
| - name: Build web app | ||
| run: npm run build | ||
| - name: Install Electron dependencies | ||
| run: | | ||
| npm install --save-dev electron electron-builder | ||
| - name: Create Electron main process | ||
| run: | | ||
| node -e " | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| // Create electron directory | ||
| if (!fs.existsSync('electron')) { | ||
| fs.mkdirSync('electron', { recursive: true }); | ||
| } | ||
| // Create main.js content | ||
| const mainJsContent = \`const { app, BrowserWindow, Menu, shell } = require('electron'); | ||
| const path = require('path'); | ||
| const isDev = process.env.NODE_ENV === 'development'; | ||
| let mainWindow; | ||
| function createWindow() { | ||
| mainWindow = new BrowserWindow({ | ||
| width: 1200, | ||
| height: 800, | ||
| minWidth: 800, | ||
| minHeight: 600, | ||
| webPreferences: { | ||
| nodeIntegration: false, | ||
| contextIsolation: true, | ||
| enableRemoteModule: false, | ||
| webSecurity: true | ||
| }, | ||
| icon: path.join(__dirname, '../build/icon.ico'), | ||
| titleBarStyle: process.platform === 'darwin' ? 'hiddenInset' : 'default', | ||
| show: false | ||
| }); | ||
| // Load the app | ||
| if (isDev) { | ||
| mainWindow.loadURL('http://localhost:5173'); | ||
| mainWindow.webContents.openDevTools(); | ||
| } else { | ||
| mainWindow.loadFile(path.join(__dirname, '../dist/index.html')); | ||
| } | ||
| mainWindow.once('ready-to-show', () => { | ||
| mainWindow.show(); | ||
| // Set application menu for macOS | ||
| if (process.platform === 'darwin') { | ||
| const template = [ | ||
| { | ||
| label: 'GitHub Stars Manager', | ||
| submenu: [ | ||
| { role: 'about' }, | ||
| { type: 'separator' }, | ||
| { role: 'services' }, | ||
| { type: 'separator' }, | ||
| { role: 'hide' }, | ||
| { role: 'hideothers' }, | ||
| { role: 'unhide' }, | ||
| { type: 'separator' }, | ||
| { role: 'quit' } | ||
| ] | ||
| }, | ||
| { | ||
| label: 'Edit', | ||
| submenu: [ | ||
| { role: 'undo' }, | ||
| { role: 'redo' }, | ||
| { type: 'separator' }, | ||
| { role: 'cut' }, | ||
| { role: 'copy' }, | ||
| { role: 'paste' }, | ||
| { role: 'selectall' } | ||
| ] | ||
| }, | ||
| { | ||
| label: 'View', | ||
| submenu: [ | ||
| { role: 'reload' }, | ||
| { role: 'forceReload' }, | ||
| { role: 'toggleDevTools' }, | ||
| { type: 'separator' }, | ||
| { role: 'resetZoom' }, | ||
| { role: 'zoomIn' }, | ||
| { role: 'zoomOut' }, | ||
| { type: 'separator' }, | ||
| { role: 'togglefullscreen' } | ||
| ] | ||
| }, | ||
| { | ||
| label: 'Window', | ||
| submenu: [ | ||
| { role: 'minimize' }, | ||
| { role: 'close' } | ||
| ] | ||
| } | ||
| ]; | ||
| Menu.setApplicationMenu(Menu.buildFromTemplate(template)); | ||
| } | ||
| }); | ||
| // Handle external links | ||
| mainWindow.webContents.setWindowOpenHandler(({ url }) => { | ||
| shell.openExternal(url); | ||
| return { action: 'deny' }; | ||
| }); | ||
| mainWindow.on('closed', () => { | ||
| mainWindow = null; | ||
| }); | ||
| } | ||
| app.whenReady().then(createWindow); | ||
| app.on('window-all-closed', () => { | ||
| if (process.platform !== 'darwin') { | ||
| app.quit(); | ||
| } | ||
| }); | ||
| app.on('activate', () => { | ||
| if (BrowserWindow.getAllWindows().length === 0) { | ||
| createWindow(); | ||
| } | ||
| }); | ||
| // Security settings | ||
| app.on('web-contents-created', (event, contents) => { | ||
| contents.on('new-window', (event, navigationUrl) => { | ||
| event.preventDefault(); | ||
| shell.openExternal(navigationUrl); | ||
| }); | ||
| }); | ||
| \`; | ||
| // Write main.js file | ||
| fs.writeFileSync('electron/main.js', mainJsContent); | ||
| // Create package.json for electron | ||
| const electronPackageJson = { | ||
| name: 'github-stars-manager-desktop', | ||
| version: '1.0.0', | ||
| description: 'GitHub Stars Manager Desktop App', | ||
| main: 'main.js', | ||
| author: 'GitHub Stars Manager', | ||
| license: 'MIT' | ||
| }; | ||
| fs.writeFileSync('electron/package.json', JSON.stringify(electronPackageJson, null, 2)); | ||
| console.log('Electron files created successfully'); | ||
| " | ||
| - name: Create Electron package.json | ||
| run: | | ||
| echo "Electron package.json already created in previous step" | ||
| - name: Update main package.json for Electron | ||
| run: | | ||
| node -e " | ||
| const fs = require('fs'); | ||
| const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); | ||
| packageJson.main = 'electron/main.js'; | ||
| packageJson.homepage = './'; | ||
| packageJson.scripts = packageJson.scripts || {}; | ||
| packageJson.scripts.electron = 'electron .'; | ||
| packageJson.scripts['electron-dev'] = 'NODE_ENV=development electron .'; | ||
| packageJson.scripts.dist = 'electron-builder'; | ||
| packageJson.build = { | ||
| appId: 'com.github-stars-manager.app', | ||
| productName: 'GitHub Stars Manager', | ||
| directories: { | ||
| output: 'release' | ||
| }, | ||
| files: [ | ||
| 'dist/**/*', | ||
| 'electron/**/*', | ||
| 'node_modules/**/*', | ||
| 'package.json' | ||
| ] | ||
| }; | ||
| fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2)); | ||
| console.log('Package.json updated successfully'); | ||
| " | ||
| - name: Configure platform-specific build settings | ||
| shell: bash | ||
| run: | | ||
| node -e " | ||
| const fs = require('fs'); | ||
| const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); | ||
| if [[ "${{ matrix.os }}" == "windows-latest" ]]; then | ||
| packageJson.build.win = { | ||
| target: 'nsis', | ||
| icon: 'build/icon.ico' | ||
| }; | ||
| packageJson.build.nsis = { | ||
| oneClick: false, | ||
| allowToChangeInstallationDirectory: true | ||
| }; | ||
| elif [[ "${{ matrix.os }}" == "macos-latest" ]]; then | ||
| packageJson.build.mac = { | ||
| target: 'dmg', | ||
| icon: 'build/icon.icns', | ||
| category: 'public.app-category.productivity' | ||
| }; | ||
| else | ||
| packageJson.build.linux = { | ||
| target: 'AppImage', | ||
| icon: 'build/icon-512x512.png', | ||
| category: 'Office' | ||
| }; | ||
| fi | ||
| fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2)); | ||
| console.log('Platform-specific settings configured'); | ||
| " | ||
| - name: Build Electron app | ||
| run: npm run dist | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Upload artifacts (Windows) | ||
| if: matrix.os == 'windows-latest' | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: windows-app | ||
| path: release/*.exe | ||
| - name: Upload artifacts (macOS) | ||
| if: matrix.os == 'macos-latest' | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: macos-app | ||
| path: release/*.dmg | ||
| - name: Upload artifacts (Linux) | ||
| if: matrix.os == 'ubuntu-latest' | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: linux-app | ||
| path: release/*.AppImage | ||
| release: | ||
| needs: build | ||
| runs-on: ubuntu-latest | ||
| if: startsWith(github.ref, 'refs/tags/v') | ||
| steps: | ||
| - name: Download all artifacts | ||
| uses: actions/download-artifact@v4 | ||
| - name: Create Release | ||
| uses: softprops/action-gh-release@v1 | ||
| with: | ||
| files: | | ||
| windows-app/* | ||
| macos-app/* | ||
| linux-app/* | ||
| draft: false | ||
| prerelease: false | ||
| generate_release_notes: true | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||