Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: auto updater electron forge #547

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions .github/workflows/prod-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ jobs:
run: |
sudo apt-get install --no-install-recommends -y rpm libarchive-tools

# https://github.com/electron/forge/issues/2807
- if: ${{ matrix.os == 'macos-latest' }}
run: python3 -m pip install setuptools

- name: Used variables
run: |
echo "MP_PROJECT_ENV variable : ${{ vars.MP_PROJECT_ENV }}"
Expand All @@ -35,12 +39,19 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
# cache: npm

- name: Install dependencies
run: |
npm ci

- if: ${{ matrix.os == 'macos-latest' }}
name: Import Certs
uses: apple-actions/import-codesign-certs@v2
with:
p12-file-base64: ${{ secrets.CSC_LINK }}
p12-password: ${{ secrets.CSC_KEY_PASSWORD }}

- name: Publish releases
env:
# macOS code signing and notarization
Expand All @@ -49,9 +60,9 @@ jobs:
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_PROD_CERT_NAME: ${{ secrets.APPLE_PROD_CERT_NAME }}

CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}

WIN_CSC_LINK: ${{ secrets.WIN_CSC_BASE64 }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD_2 }}
# CSC_IDENTITY_AUTO_DISCOVERY: false
Expand All @@ -64,5 +75,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

run: |
npm run publish
npm run publish -- --arch=x64
npm run publish -- --arch=arm64

6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,9 @@ npm run storybook
`npx @electron/asar extract app.asar <destfolder>` can be used to determine the contents of asar

`npm run package` followed by `mkdir outAsar` and `npx @electron/asar extract ./out/NiceNode-darwin-arm64/NiceNode.app/Contents/Resources/app.asar outAsar` on macOS

## Debugging update server (macOS and Windows)
`curl https://update.electronjs.org/NiceNode/nice-node/darwin-arm64/5.2.0-alpha` returns if there is an update detected by the update server. The end of the URL is <platform>-<arch>/<version>.

Also, NiceNode app auto update logs are in ../NiceNode/logs/autoUpdater*.log.

60 changes: 33 additions & 27 deletions forge.config.cts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import type { ForgeConfig, ForgePackagerOptions } from '@electron-forge/shared-types';
import { MakerSquirrel } from '@electron-forge/maker-squirrel';
// import { MakerSquirrel } from '@electron-forge/maker-squirrel';
import { MakerZIP } from '@electron-forge/maker-zip';
import { MakerDeb } from '@electron-forge/maker-deb';
import { MakerRpm } from '@electron-forge/maker-rpm';
// import { MakerDeb } from '@electron-forge/maker-deb';
// import { MakerRpm } from '@electron-forge/maker-rpm';
import { MakerDMG } from '@electron-forge/maker-dmg';
import { VitePlugin } from '@electron-forge/plugin-vite';
import { FusesPlugin } from '@electron-forge/plugin-fuses';
import { FuseV1Options, FuseVersion } from '@electron/fuses';
import * as path from 'node:path';
import packageJson from './package.json';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const { version } = packageJson;

Expand All @@ -32,6 +30,28 @@ const packagerConfig: ForgePackagerOptions = {
// ignore: [ /stories/, /__tests__/, /.storybook/, /storybook/, /storybook-static/ ],
};

const commonLinuxConfig = {
icon: {
scalable: path.resolve(iconDir, 'icon.svg'),
// scalable: './assets/icons/icon.svg',
'1024x1024': path.resolve(iconDir, '1024x1024.png'),
'512x512': path.resolve(iconDir, '512x512.png'),
'256x256': path.resolve(iconDir, '256x256.png'),
'128x128': path.resolve(iconDir, '128x128.png'),
'96x96': path.resolve(iconDir, '96x96.png'),
'64x64': path.resolve(iconDir, '64x64.png'),
'48x48': path.resolve(iconDir, '48x48.png'),
'32x32': path.resolve(iconDir, '32x32.png'),
'16x16': path.resolve(iconDir, '16x16.png'),
},
executableName: 'nice-node',
productName: 'NiceNode',
productDescription: "By running a node you become part of a global movement to decentralize a world of information. Prevent leaking your personal data to third party nodes. Ensure access when you need it, and don't be censored. Decentralization starts with you. Voice your choice, help your peers.",
maintainer: "NiceNode LLC <johns@nicenode.xyz>",
categories: ['Utility', 'System', 'Network', 'Development'],
mimeType: ['application/x-nice-node', 'x-scheme-handler/nice-node'],
}

// skip signing & notarizing on local builds
console.log("process.env.CI: ", process.env.CI);
if(process.env.CI && process.env.NO_CODE_SIGNING !== 'true') {
Expand All @@ -47,6 +67,8 @@ if(process.env.CI && process.env.NO_CODE_SIGNING !== 'true') {
appleIdPassword: process.env.APPLE_ID_PASSWORD,
teamId: process.env.APPLE_TEAM_ID
};
} else if(process.env.LOCAL_MAC_SIGNING === 'true') {
packagerConfig.osxSign = {}; // local keychain works automatically
}

const config: ForgeConfig = {
Expand All @@ -67,31 +89,15 @@ const config: ForgeConfig = {
}),
},
new MakerZIP({}),
new MakerRpm({}, ['linux']),
{
name: '@electron-forge/maker-rpm',
platforms: ['linux'],
config: commonLinuxConfig
},
{
name: '@electron-forge/maker-deb',
platforms: ['linux'],
config: {
icon: {
scalable: path.resolve(iconDir, 'icon.svg'),
// scalable: './assets/icons/icon.svg',
'1024x1024': path.resolve(iconDir, '1024x1024.png'),
'512x512': path.resolve(iconDir, '512x512.png'),
'256x256': path.resolve(iconDir, '256x256.png'),
'128x128': path.resolve(iconDir, '128x128.png'),
'96x96': path.resolve(iconDir, '96x96.png'),
'64x64': path.resolve(iconDir, '64x64.png'),
'48x48': path.resolve(iconDir, '48x48.png'),
'32x32': path.resolve(iconDir, '32x32.png'),
'16x16': path.resolve(iconDir, '16x16.png'),
},
executableName: 'nice-node',
productName: 'NiceNode',
productDescription: "By running a node you become part of a global movement to decentralize a world of information. Prevent leaking your personal data to third party nodes. Ensure access when you need it, and don't be censored. Decentralization starts with you. Voice your choice, help your peers.",
maintainer: "NiceNode LLC <johns@nicenode.xyz>",
categories: ['Utility', 'System', 'Network', 'Development'],
mimeType: ['application/x-nice-node', 'x-scheme-handler/nice-node'],
}
config: commonLinuxConfig
},
new MakerDMG({
background: './assets/dmg-background.tiff',
Expand Down
19 changes: 17 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nice-node",
"version": "5.1.2-alpha",
"version": "6.0.0-alpha",
"description": "Run a node at home, the easy way.",
"homepage": "https://nicenode.xyz",
"productName": "NiceNode",
Expand Down Expand Up @@ -90,6 +90,7 @@
"docker-cli-js": "^2.10.0",
"dotenv": "^16.0.3",
"du": "^1.0.0",
"electron-log": "^5.1.2",
"electron-squirrel-startup": "^1.0.0",
"electron-store": "^8.1.0",
"highcharts": "^11.0.0",
Expand All @@ -109,6 +110,7 @@
"react-select": "^5.8.0",
"systeminformation": "^5.21.24",
"throttle-debounce": "^5.0.0",
"tiny-typed-emitter": "^2.1.0",
"update-electron-app": "^3.0.0",
"uuid": "^9.0.0",
"winston": "^3.13.0",
Expand Down
11 changes: 10 additions & 1 deletion src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,12 @@ export const createWindow = async () => {

// App auto updates
updater.initialize(mainWindow);
updater.checkForUpdates(false);
// disabled in dev env
if (!isDevelopment) {
updater.checkForUpdates(false);
} else {
logger.info('updater.checkForUpdates() skipped. Disabled in development env');
}

menuBuilder = new MenuBuilder(mainWindow);
menuBuilder.buildMenu();
Expand Down Expand Up @@ -205,6 +210,10 @@ export const fullQuit = () => {
app.quit();
};

export const setFullQuitForNextQuit = (_isNextQuitAFullQuit: boolean) => {
isFullQuit = _isNextQuitAFullQuit;
};

// Emitted on app.quit() after all windows have been closed
app.on('will-quit', (e) => {
// Remove dev env check to test background. This is to prevent
Expand Down
66 changes: 66 additions & 0 deletions src/main/nn-auto-updater/findPackageManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { exec as execCallback } from 'node:child_process';
import { promisify } from 'node:util';

const exec = promisify(execCallback);

export type PackageType = "deb" | "rpm";
export type PackageManager = "dpkg" | "dnf" | "yum" | "zypper";

interface PackageManagerMap {
[key: string]: PackageManager;
}

interface PackageManagerToTypeMap {
[key: string]: PackageType;
}

const packageManagers: PackageManagerMap = {
"apt-get": "dpkg", // "deb (apt)",
dnf: "dnf", // "rpm (dnf)",
yum: "yum", // "rpm (yum)",
// pacman: "pacman",
zypper: "zypper", // "rpm (zypper)"
};

const packageTypes: PackageManagerToTypeMap = {
"apt-get": "deb", // "deb (apt)",
dnf: "rpm", // "rpm (dnf)",
yum: "rpm", // "rpm (yum)",
// pacman: "pacman",
zypper: "rpm", // "rpm (zypper)"
};

export const findPackageManager = async (): Promise<PackageManager | null> => {
for (const pkgManager of Object.keys(packageManagers)) {
try {
const { stdout } = await exec(`command -v ${pkgManager}`);
if (stdout.trim()) {
return packageManagers[pkgManager];
}
} catch (error) {
// Command not found, continue checking the next
}
}
// "Package manager not found.";
return null;
}

export const findPackageType = async (): Promise<PackageType | null> => {
for (const pkgManager of Object.keys(packageManagers)) {
try {
const { stdout } = await exec(`command -v ${pkgManager}`);
if (stdout.trim()) {
return packageTypes[pkgManager];
}
} catch (error) {
// Command not found, continue checking the next
}
}
// "Package manager not found.";
return null;
}

// (async () => {
// const result = await findPackageManager();
// console.log("+++++++++++++++++++++++++", result);
// })();
Loading
Loading