之前一篇文章介绍了electron-PC端持续集成的设计方案,这里记录下具体的实现细节。
阶段一 打包
首先介绍下,我们使用的electron-vue这个脚手架搭建的项目。
打包我们使用的是electron-builder,这里介绍了基本的使用 electron-build 的使用
我们从打包的npm scripts 入手来看下打包流程:
我们的部署环境分为sit, pro
"build": "node .electron-vue/build-entry.js",
"build:sit-hk": "cross-env ENV_TARGET=sit CLIENT_TYPE=hk yarn build hk",
"build:sit": "cross-env ENV_TARGET=sit CLIENT_TYPE=mainland yarn build mainland",
"build:pro": "cross-env ENV_TARGET=pro CLIENT_TYPE=mainland yarn build mainland",
"build:pro-hk": "cross-env ENV_TARGET=pro CLIENT_TYPE=hk yarn build hk",
我们以其中一个来分析下打包过程:
"build:sit": "cross-env ENV_TARGET=sit CLIENT_TYPE=mainland yarn build mainland"
上述命令表示:
添加了2个环境变量
- ENV_TARGET: 打包的环境
- CLIENT_TYPE : 包的归属。大陆 or 香港
然后执行yarn build mainland来执行构建。其实是执行 node .electron-vue/build-entry.js mainland给build-entry.js脚本传递了mainland这个参数。接下里,我们分析build-entry.js
build-entry.js
const { exec } = require('child_process');
const fs = require('fs');
const path = require('path')
let projects = process.argv.slice(2)
if (projects.length === 0) {
projects = ['mainland']
}
projects.forEach(project => {
// 拿到项目和环境的构建配置
let ymlName = `${project}-${process.env.ENV_TARGET || 'sit'}`
let workerProcess = exec(`node --max_old_space_size=4096 .electron-vue/build.js --project=${project} && electron-builder -c ./build-yml/${ymlName}.yml`, {maxBuffer: 1024*1024*1000}, (err) => {
if (err) {
console.error(err)
}
})
workerProcess.stdout.on('data', function (data) {
console.log(data)
})
})
通过传入的mainland 和 process.env.ENV_TARGET 参数,可以获取到构建的配置文件
构建配置目录:
这里展示下mainland-sit.yml的内容:
#mac 签名文件
afterSign: scripts/notarize.js
# 打包后app名称
productName: 盈立智投SIT
# apple 开发者ID
appId: XXXXXXX
# 可执行文件目录
directories:
output: build/mainland
# 打包输出文件目录
files:
- dist/electron/**/*
# dmg 相关配置
dmg:
sign: false
contents:
- x: 410
y: 150
type: link
path: /Applications
- x: 130
y: 150
type: file
# mac 相关配置
mac:
icon: build/icons/
target: dmg
#签名的相关配置
hardenedRuntime: true
gatekeeperAssess: false
entitlements: build/entitlements.mac.plist
entitlementsInherit: build/entitlements.mac.plist
win:
target:
- target: nsis
arch:
- ia32
icon: build/icons/usmart.ico
signingHashAlgorithms: [sha256,sha1]
rfc3161TimeStampServer: http://timestamp.digicert.com
certificateFile: usmart.pfx
certificatePassword: usmarthk2021
linux:
icon: build/icons
nsis:
oneClick: false
perMachine: false
allowElevation: true
allowtochangeInstallationDirectory: true
# 最终用户许可协议
# license: build/license_zh_CN.txt
deleteAppDataOnUninstall: false
displayLanguageSelector: false
以mac 为例子,打包输出是这样的:
这里的dmg文件就是我们的mac 安装包
阶段二 上传服务器
打包完成之后,我们生成了以.dmg(window的是以.exe结尾)为后缀的安装包。因为安装包都比较大,上传之前,我们应该进行压缩,上传之后,进行解压,然后发送邮件,邮件内容有访问链接等。我们详细分析下此过程:
上传的流程,我们使用了第三方库deploy-cli-service,并在此基础上,我们修改了内部的源码以适应我们的部署方案。我们的上传过程包含了以下几个过程。源码里也清晰的写下了任务流,感兴趣的可以阅读源码学习下。
// 创建任务列表
const createTaskList = (config) => {
const { script, isRemoveRemoteFile = true } = config
taskList = []
// 是否删除本地的打包文件
taskList.push(removeLocalFile)
// 执行构建
script && taskList.push(execBuild)
// 进行压缩
taskList.push(buildZip)
// 远程服务器连接
taskList.push(connectSSH)
// 上传压缩后的安装包
taskList.push(uploadLocalFile)
// 根据变量控制是否删除刚上传的文件
isRemoveRemoteFile && taskList.push(removeRemoteFile)
// 解压上传后的文件
taskList.push(unzipRemoteFile)
// 关闭远程服务器连接
taskList.push(disconnectSSH)
}
'mac-test-hk': ...
'mac-test': {
name: 'mac-test',
script: `yarn build:clean && yarn build:sit`,
host: 'xx.xxx.xx.xxx',
port: 22222,
username: 'root',
password: 'xxxxxx',
distPath: 'build/mainland',
webDir: `/www/desktop-applications/mac/test/${currentTime}`,
isRemoveRemoteFile: false,
isFile: true, // 要打包上传的是否是文件
fileName: `盈立智投SIT-${version}.dmg`, // 文件名设置(如果是文件)
needEmail: true, // 打包完成后是否需要发邮件功能
addressee: addressee, // 收件人
title: `【PC版构建通知】 盈立智投PC版 Mac test | 软件版本:${version}`, // 邮件标题
// 邮件内容
content: `
本邮件由系统自动发出,无需回复!
各位同事,大家好,以下为Mac-test项目构建信息 \n \n
构建目录:${__dirname}
项目名称:盈立智投PC版 Mac test
软件版本:${version}</br>
下载地址:http://XXXXXX/desktop-applications/mac/test/${currentTime}
`
},
'mac-pro-hk': ...
'mac-pro': ...
'win-test': ...
'win-test-hk': ...
'win-pro-hk': ...
'win-pro': ...
有了这个deploy-cli-service之后,我们就可以通过npm script 来进行构建和上传。通过--mode 来指定deploy.config.js 里使用哪个配置文件。
"deploy:mac-test": "deploy-cli-service deploy --mode mac-test",
"deploy:mac-test-hk": "deploy-cli-service deploy --mode mac-test-hk",
"deploy:win-test": "deploy-cli-service deploy --mode win-test",
"deploy:win-test-hk": "deploy-cli-service deploy --mode win-test-hk",
"deploy:mac-pro": "deploy-cli-service deploy --mode mac-pro",
"deploy:mac-pro-hk": "deploy-cli-service deploy --mode mac-pro-hk",
"deploy:win-pro": "deploy-cli-service deploy --mode win-pro",
"deploy:win-pro-hk": "deploy-cli-service deploy --mode win-pro-hk",
阶段三 邮件分发下载地址
在阶段二,我们使用了deploy-cli-service来进行构建和上传,在deploy.config.js的配置中,我们有发送邮件的配置。
needEmail: true, // 打包完成后是否需要发邮件功能
addressee: addressee, // 收件人
title: `【PC版构建通知】 盈立智投PC版 Mac test | 软件版本:${version}`, // 邮件标题
// 邮件内容
// version 从package.json 中获取
content: `
本邮件由系统自动发出,无需回复!
各位同事,大家好,以下为Mac-test项目构建信息 \n \n
构建目录:${__dirname}
项目名称:盈立智投PC版 Mac test
软件版本:${version}</br>
下载地址:http://XXXXX/desktop-applications/mac/test/${currentTime}
对应的邮件展示:
接下来看看为了能自动发邮件,我们做了哪些操作
首先发邮件的操作我们配置在了deploy.config.js中,所以,我们需要在deploy-cli-service添加我们的发邮件逻辑。
在解压远程文件之后,我们执行发邮件的逻辑:
if(config.needEmail){
await ssh.execCommand(
`echo '${config.content}' | mail -s '${config.title}' ${config.addressee}`
)
}
接下来,我们需要配置Nginx, 来让 http://m-dev.yxzq.com/desktop-applications/mac/test/${currentTime} 下载地址能够正确的被访问到
auto_index指令: 启用Nginx目录索引功能. 默认是off
utoindex_exact_size : 制定是否额外得显示文件得大小,单位为字节,mb,gb等等. 默认是 on
autoindex_localtime: 指定是否显示目录或者文件的时间,默认是off。
root: desktop-applications文件夹所在的根目录。
一句话解释: 启用索引功能,并且显示 文件的创建时间 和 文件的大小(单位是字节)
如下图所示,当用户点击链接时,浏览器进行下载的操作,可以将最新构建的包送到相关开发测试产品手里,提高开发测试验收协作效率。
这样我们就完成了构建包的邮件分发
阶段四 版本更新发布
第一期版本发布,比较简单,直接在官方提供下载链接就可以了
后续版本的更新,包含以下几个步骤
- 1: 在中台配置页面,配置当前最新的版本号,以及需要更新的旧版本范围,更新文案等,并上传最新包
- 2:PC端在启动登录之后,会进行版本的判断,如果当前版本在可升级范围内,则弹窗提示升级文案,并提供最新的下载版本
点击去下载,则跳转浏览器进行下载。