electron实现github自动升级
实现 GitHub 自动升级需要编写一些自动化脚本,以下是一个简单的方案:
- 在 Electron 应用的主进程中,使用
electron-updater
模块实现自动更新功能。这个模块提供了一些 API,可以方便地检查和下载最新的应用版本。 - 将应用的安装包发布到 GitHub Release 中。每次发布新版本时,需要将安装包上传到对应的 Release 中,并将版本号和更新说明填写好。
- 编写一个自动化脚本,定期检查 GitHub Release 中是否有新版本的安装包发布。可以使用 GitHub API 获取最新的 Release 信息,并比较版本号判断是否需要更新。
- 如果检测到有新版本发布,则使用
electron-updater
模块下载最新的安装包,并启动安装程序完成升级操作。
需要注意的是,为了保证应用的安全性,下载的安装包应该来自可信的来源,比如使用 HTTPS 协议获取 GitHub Release 中的安装包,并验证其数字签名。同时,在自动升级过程中,需要确保用户的数据不会丢失或被覆盖,建议在升级前进行数据备份。
检查 GitHub Release 中是否有新版本的安装包发布
js
const https = require('https');
const { exec } = require('child_process');
const OWNER = 'your_github_username';
const REPO = 'your_github_repo';
const getCurrentVersion = () => {
// 获取当前应用的版本号,可以根据实际情况进行修改
const { version } = require('./package.json');
return version;
};
const getLatestRelease = async () => {
// 使用 GitHub API 获取最新的 Release 信息
const url = `https://api.github.com/repos/${OWNER}/${REPO}/releases/latest`;
const options = {
headers: { 'User-Agent': 'Mozilla/5.0' }
};
return new Promise((resolve, reject) => {
https.get(url, options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const release = JSON.parse(data);
resolve(release);
} catch (err) {
reject(err);
}
});
}).on('error', (err) => {
reject(err);
});
});
};
const compareVersions = (v1, v2) => {
// 比较版本号大小,返回 true 表示 v1 > v2,需要升级
const v1Parts = v1.split('.');
const v2Parts = v2.split('.');
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
const v1Part = Number(v1Parts[i] || 0);
const v2Part = Number(v2Parts[i] || 0);
if (v1Part > v2Part) {
return true;
} else if (v1Part < v2Part) {
return false;
}
}
return false;
};
const checkForUpdates = async () => {
const currentVersion = getCurrentVersion();
const latestRelease = await getLatestRelease();
const latestVersion = latestRelease.tag_name.replace(/^v/, '');
if (compareVersions(latestVersion, currentVersion)) {
console.log(`New version ${latestVersion} is available. Run "npm run update" to install.`);
} else {
console.log(`You have the latest version ${currentVersion}.`);
}
};
checkForUpdates();
const https = require('https');
const { exec } = require('child_process');
const OWNER = 'your_github_username';
const REPO = 'your_github_repo';
const getCurrentVersion = () => {
// 获取当前应用的版本号,可以根据实际情况进行修改
const { version } = require('./package.json');
return version;
};
const getLatestRelease = async () => {
// 使用 GitHub API 获取最新的 Release 信息
const url = `https://api.github.com/repos/${OWNER}/${REPO}/releases/latest`;
const options = {
headers: { 'User-Agent': 'Mozilla/5.0' }
};
return new Promise((resolve, reject) => {
https.get(url, options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const release = JSON.parse(data);
resolve(release);
} catch (err) {
reject(err);
}
});
}).on('error', (err) => {
reject(err);
});
});
};
const compareVersions = (v1, v2) => {
// 比较版本号大小,返回 true 表示 v1 > v2,需要升级
const v1Parts = v1.split('.');
const v2Parts = v2.split('.');
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
const v1Part = Number(v1Parts[i] || 0);
const v2Part = Number(v2Parts[i] || 0);
if (v1Part > v2Part) {
return true;
} else if (v1Part < v2Part) {
return false;
}
}
return false;
};
const checkForUpdates = async () => {
const currentVersion = getCurrentVersion();
const latestRelease = await getLatestRelease();
const latestVersion = latestRelease.tag_name.replace(/^v/, '');
if (compareVersions(latestVersion, currentVersion)) {
console.log(`New version ${latestVersion} is available. Run "npm run update" to install.`);
} else {
console.log(`You have the latest version ${currentVersion}.`);
}
};
checkForUpdates();
Skip checkForUpdates because application is not packed and dev update config is not forced
如果你在开发过程中遇到了"Skip checkForUpdates because application is not packed and dev update config is not forced"这个错误,通常是因为在开发环境下直接运行Electron应用程序,而不是打包后运行。在这种情况下,Electron-updater会默认跳过自动更新检查,以避免在开发环境下不必要的网络请求和处理。
如果你想在开发环境下测试自动更新,可以通过以下两种方式解决这个问题:
在
setFeedURL
方法中设置updateConfigPath
选项,将其指向一个本地的JSON文件,用于模拟自动更新的配置信息。例如:jscodeautoUpdater.setFeedURL({ provider: 'generic', url: 'http://localhost:3000/updates/', channel: 'latest', updateConfigPath: path.join(__dirname, 'dev-app-update.yml') });
codeautoUpdater.setFeedURL({ provider: 'generic', url: 'http://localhost:3000/updates/', channel: 'latest', updateConfigPath: path.join(__dirname, 'dev-app-update.yml') });
在
dev-app-update.yml
文件中,可以指定自动更新的配置信息,例如:ymlcodeversion: '1.0.0' releaseDate: '2022-03-23T00:00:00Z' url: 'http://localhost:3000/updates/app-1.0.0.dmg' sha512: '1234567890abcdef'
codeversion: '1.0.0' releaseDate: '2022-03-23T00:00:00Z' url: 'http://localhost:3000/updates/app-1.0.0.dmg' sha512: '1234567890abcdef'
这样,在开发环境下,Electron-updater就会读取本地的JSON文件,模拟自动更新的配置信息,从而可以测试自动更新功能。
在Electron应用程序的启动脚本中,设置环境变量
ELECTRON_FORCE_WINDOW_UPDATE
为true
,强制启用自动更新检查。例如:jscodeprocess.env.ELECTRON_FORCE_WINDOW_UPDATE = 'true'; app.on('ready', () => { autoUpdater.checkForUpdatesAndNotify(); // ... });
codeprocess.env.ELECTRON_FORCE_WINDOW_UPDATE = 'true'; app.on('ready', () => { autoUpdater.checkForUpdatesAndNotify(); // ... });
这样,在开发环境下,Electron-updater就会强制启用自动更新检查,从而可以测试自动更新功能。注意,这种方式可能会产生不必要的网络请求和处理,建议仅在开发环境下使用。