perf: 优化客户端升级

This commit is contained in:
kuaifan 2024-11-14 23:07:07 +08:00
parent 0fd37e4c05
commit ca1028921a
7 changed files with 133 additions and 112 deletions

View File

@ -4,6 +4,7 @@ on:
push: push:
branches: branches:
- "pro" - "pro"
- "dev"
jobs: jobs:
check-version: check-version:
@ -47,7 +48,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: create release - name: Create Release
id: create-release id: create-release
uses: actions/github-script@v7 uses: actions/github-script@v7
with: with:
@ -229,25 +230,30 @@ jobs:
run: | run: |
./cmd electron win ./cmd electron win
# publish-release: publish-release:
# needs: [check-version, create-release, build-client] needs: [ check-version, create-release, build-client ]
# if: needs.check-version.outputs.should_release == 'true' if: needs.check-version.outputs.should_release == 'true' && github.ref == 'refs/heads/pro'
# permissions: permissions:
# contents: write contents: write
# runs-on: ubuntu-latest runs-on: ubuntu-latest
# steps: steps:
# - name: publish release - name: Publish Release
# id: publish-release uses: actions/github-script@v7
# uses: actions/github-script@v7 env:
# env: RELEASE_ID: ${{ needs.create-release.outputs.release_id }}
# RELEASE_ID: ${{ needs.create-release.outputs.release_id }} with:
# with: script: |
# script: | github.rest.repos.updateRelease({
# github.rest.repos.updateRelease({ owner: context.repo.owner,
# owner: context.repo.owner, repo: context.repo.repo,
# repo: context.repo.repo, release_id: process.env.RELEASE_ID,
# release_id: process.env.RELEASE_ID, draft: false,
# draft: false, prerelease: false
# prerelease: false })
# })
- name: Publish Official
env:
PUBLISH_KEY: ${{ secrets.PUBLISH_KEY }}
run: |
node ./electron/build.js published

View File

@ -2,18 +2,6 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [0.40.16]
### Performance
- 优化客户端升级
- 优化客户端
- 优化签到错误提示
- 优化图片选择器
- 优化邮件通知
- 优化本地资源
- 修复iOS下载中文名乱码的问题
## [0.39.97] ## [0.39.97]
### Bug Fixes ### Bug Fixes

View File

@ -1,25 +0,0 @@
# 客户端说明
## 1、App客户端
#### 1.1、说明
目录 `resources/mobile`,使用`eeui.app`框架遵从eeui的开发文档进行打包开发app
#### 1.2、编译App
1. 在项目目录执行 `./cmd appbuild [build|setting]` 编译
2. 进入 `resources/mobile` eeui框架内打包Android或iOS应用
## 2、PC/Mac客户端
#### 2.1、说明
目录 `electron`,使用`electron`框架遵从electron的开发文档进行打包客户端
#### 2.2、编译客户端
在项目目录执行 `./cmd electron [dev]` 根据提示编译

View File

@ -1,26 +1,31 @@
# 发布说明 # 发布
## 发布前 ## 准备工作
1. 添加环境变量 `APPLEID``APPLEIDPASS` 用于公证 1. 添加环境变量 `APPLEID``APPLEIDPASS` 用于公证
2. 添加环境变量 `CSC_LINK``CSC_KEY_PASSWORD` 用于签名 2. 添加环境变量 `CSC_LINK``CSC_KEY_PASSWORD` 用于签名
3. 添加环境变量 `GITHUB_TOKEN``GITHUB_REPOSITORY` 用于发布到GitHubGitHub Actions 发布不需要) 3. 添加环境变量 `GITHUB_TOKEN``GITHUB_REPOSITORY` 用于发布到GitHubGitHub Actions 发布不需要)
4. 添加环境变量 `PUBLISH_KEY` 用于发布到私有服务器 4. 添加环境变量 `PUBLISH_KEY` 用于发布到私有服务器
## 通过 GitHub Actions 发布 ## 发布版本
1. 执行 `npm run version` 生成版本 ```shell
2. 执行 `npm run build` 编译前端 npm run translate # 翻译(可选)
3. 执行 `git commit` 提交并推送 npm run version # 生成版本
4. 等待 GitHub Actions 自动发布 npm run build # 编译前端
```
## 本地发布 说明:
- 执行 `npm run build` 作用是生成网页端;
- 客户端 (Windows、Mac、Android) 会通过 GitHub Actions 自动生成并发布所以如果要自动发布只需要提交git并推送即可
- 如果想手动生成客户端执行 `./cmd electron` 根据提示选择操作。
1. 执行 `npm run version` 生成版本
2. 执行 `npm run build` 编译前端
3. 执行 `./cmd electron` 相关操作
## 编译 App ## 编译 App
1. 执行 `./cmd appbuild publish` 编译 ```shell
2. 进入 `resources/mobile` eeui框架内打包Android或iOS应用 ./cmd appbuild publish # 编译生成App需要的资源
```
编译完后进入 `resources/mobile` EEUI框架目录内打包 Android 或 iOS 应用Android 以实现 GitHub Actions 自动发布)

115
electron/build.js vendored
View File

@ -337,6 +337,48 @@ function androidUpload(url) {
}); });
} }
/**
* 通知发布完成
* @param url
*/
async function published(url) {
if (!PUBLISH_KEY) {
console.error("缺少 PUBLISH_KEY 环境变量");
process.exit()
}
const spinner = ora('完成发布...').start();
const formData = new FormData()
formData.append("action", "release");
await axiosAutoTry({
axios: {
method: 'post',
url: url,
data: formData,
headers: {
'Publish-Version': config.version,
'Publish-Key': PUBLISH_KEY,
},
},
retryNumber: 3
}).then(({status, data}) => {
if (status !== 200) {
spinner.fail('发布失败, status: ' + status)
return
}
if (!utils.isJson(data)) {
spinner.fail('发布失败, not json')
return
}
if (data.ret !== 1) {
spinner.fail(`发布失败, ret ${data.ret}`)
return
}
spinner.succeed('发布完成')
}).catch(_ => {
spinner.fail('发布失败')
})
}
/** /**
* 通用发布 * 通用发布
* @param url * @param url
@ -475,31 +517,29 @@ async function startBuild(data) {
// //
if (data.id === 'app') { if (data.id === 'app') {
const eeuiDir = path.resolve(__dirname, "../resources/mobile"); const eeuiDir = path.resolve(__dirname, "../resources/mobile");
const eeuiRun = `--rm -v ${eeuiDir}:/work -w /work kuaifan/eeui-cli:0.0.1` const eeuiRun = `docker run --rm -v ${eeuiDir}:/work -w /work kuaifan/eeui-cli:0.0.1`
const publicDir = path.resolve(__dirname, "../resources/mobile/src/public"); const publicDir = path.resolve(__dirname, "../resources/mobile/src/public");
fse.removeSync(publicDir) fse.removeSync(publicDir)
fse.copySync(electronDir, publicDir) fse.copySync(electronDir, publicDir)
if (argv[3] === "publish") { if (argv[3] === "publish") {
// Android config
const gradleFile = path.resolve(eeuiDir, "platforms/android/eeuiApp/local.properties") const gradleFile = path.resolve(eeuiDir, "platforms/android/eeuiApp/local.properties")
if (fs.existsSync(gradleFile)) { let gradleResult = fs.existsSync(gradleFile) ? fs.readFileSync(gradleFile, 'utf8') : "";
let gradleResult = fs.readFileSync(gradleFile, 'utf8') gradleResult = gradleResult.replace(/(versionCode|versionName)\s*=\s*(.+?)(\n|$)/g, '')
gradleResult = gradleResult.replace(/versionCode\s*=\s*(.+?)(\n|$)/, `versionCode = ${config.codeVerson}\n`) gradleResult += `versionCode = ${config.codeVerson}\nversionName = ${config.version}\n`
gradleResult = gradleResult.replace(/versionName\s*=\s*(.+?)(\n|$)/, `versionName = "${config.version}"\n`)
fs.writeFileSync(gradleFile, gradleResult, 'utf8') fs.writeFileSync(gradleFile, gradleResult, 'utf8')
} // iOS config
const xcconfigFile = path.resolve(eeuiDir, "platforms/ios/eeuiApp/Config/Version.xcconfig") const xcconfigFile = path.resolve(eeuiDir, "platforms/ios/eeuiApp/Config/Version.xcconfig")
if (fs.existsSync(xcconfigFile)) { let xcconfigResult = fs.existsSync(xcconfigFile) ? fs.readFileSync(xcconfigFile, 'utf8') : "";
let xcconfigResult = fs.readFileSync(xcconfigFile, 'utf8') xcconfigResult = xcconfigResult.replace(/(VERSION_CODE|VERSION_NAME)\s*=\s*(.+?)(\n|$)/g, '')
xcconfigResult = xcconfigResult.replace(/VERSION_CODE\s*=\s*(.+?)(\n|$)/, `VERSION_CODE = ${config.codeVerson}\n`) xcconfigResult += `VERSION_CODE = ${config.codeVerson}\nVERSION_NAME = ${config.version}\n`
xcconfigResult = xcconfigResult.replace(/VERSION_NAME\s*=\s*(.+?)(\n|$)/, `VERSION_NAME = ${config.version}\n`)
fs.writeFileSync(xcconfigFile, xcconfigResult, 'utf8') fs.writeFileSync(xcconfigFile, xcconfigResult, 'utf8')
} }
}
if (['build', 'publish'].includes(argv[3])) { if (['build', 'publish'].includes(argv[3])) {
if (!fs.existsSync(path.resolve(eeuiDir, "node_modules"))) { if (!fs.existsSync(path.resolve(eeuiDir, "node_modules"))) {
child_process.execSync(`docker run ${eeuiRun} npm install`, {stdio: "inherit", cwd: "resources/mobile"}); child_process.execSync(`${eeuiRun} npm install`, {stdio: "inherit", cwd: "resources/mobile"});
} }
child_process.execSync(`docker run ${eeuiRun} eeui build --simple`, {stdio: "inherit", cwd: "resources/mobile"}); child_process.execSync(`${eeuiRun} eeui build --simple`, {stdio: "inherit", cwd: "resources/mobile"});
} else { } else {
[ [
path.resolve(publicDir, "../../platforms/ios/eeuiApp/bundlejs/eeui/public"), path.resolve(publicDir, "../../platforms/ios/eeuiApp/bundlejs/eeui/public"),
@ -524,58 +564,58 @@ async function startBuild(data) {
process.on('SIGINT', recoveryPackage); process.on('SIGINT', recoveryPackage);
process.on('SIGHUP', recoveryPackage); process.on('SIGHUP', recoveryPackage);
// package.json Generated // package.json Generated
const econfig = require('./package.json') const appConfig = require('./package.json')
let appName = utils.getDomain(data.url) let appName = utils.getDomain(data.url)
if (appName === "public") appName = "DooTask" if (appName === "public") appName = "DooTask"
econfig.name = data.name; appConfig.name = data.name;
econfig.version = config.version; appConfig.version = config.version;
econfig.build.appId = data.id; appConfig.build.appId = data.id;
econfig.build.artifactName = appName + "-v${version}-${os}-${arch}.${ext}"; appConfig.build.artifactName = appName + "-v${version}-${os}-${arch}.${ext}";
econfig.build.nsis.artifactName = appName + "-v${version}-${os}-${arch}.${ext}"; appConfig.build.nsis.artifactName = appName + "-v${version}-${os}-${arch}.${ext}";
// changelog // changelog
econfig.build.releaseInfo.releaseNotes = changeLog() appConfig.build.releaseInfo.releaseNotes = changeLog()
if (!release) { if (!release) {
econfig.build.releaseInfo.releaseNotes = econfig.build.releaseInfo.releaseNotes.replace(`## [${config.version}]`, `## [${config.version}-Silence]`) appConfig.build.releaseInfo.releaseNotes = appConfig.build.releaseInfo.releaseNotes.replace(`## [${config.version}]`, `## [${config.version}-Silence]`)
} }
// notarize // notarize
if (notarize && APPLEID && APPLEIDPASS) { if (notarize && APPLEID && APPLEIDPASS) {
econfig.build.afterSign = "./notarize.js" appConfig.build.afterSign = "./notarize.js"
} }
// archs // archs
if (archs.length > 0) { if (archs.length > 0) {
econfig.build.mac.target = econfig.build.mac.target.map(target => { appConfig.build.mac.target = appConfig.build.mac.target.map(target => {
if (target.arch) target.arch = target.arch.filter(arch => archs.includes(arch)) if (target.arch) target.arch = target.arch.filter(arch => archs.includes(arch))
return target return target
}) })
econfig.build.win.target = econfig.build.win.target.map(target => { appConfig.build.win.target = appConfig.build.win.target.map(target => {
if (target.arch) target.arch = target.arch.filter(arch => archs.includes(arch)) if (target.arch) target.arch = target.arch.filter(arch => archs.includes(arch))
return target return target
}) })
} }
// github (build && publish) // GitHub (build and publish)
if (publish === true && GITHUB_TOKEN && utils.strExists(GITHUB_REPOSITORY, "/")) { if (publish === true && GITHUB_TOKEN && utils.strExists(GITHUB_REPOSITORY, "/")) {
const repository = GITHUB_REPOSITORY.split("/") const repository = GITHUB_REPOSITORY.split("/")
econfig.build.publish = { appConfig.build.publish = {
"releaseType": "release", "releaseType": "release",
"provider": "github", "provider": "github",
"owner": repository[0], "owner": repository[0],
"repo": repository[1] "repo": repository[1]
} }
econfig.build.directories.output = `${output}-github`; appConfig.build.directories.output = `${output}-github`;
fs.writeFileSync(packageFile, JSON.stringify(econfig, null, 4), 'utf8'); fs.writeFileSync(packageFile, JSON.stringify(appConfig, null, 4), 'utf8');
child_process.execSync(`npm run ${platform}-publish`, {stdio: "inherit", cwd: "electron"}); child_process.execSync(`npm run ${platform}-publish`, {stdio: "inherit", cwd: "electron"});
} }
// generic (build || publish) // generic (build or publish)
econfig.build.publish = data.publish appConfig.build.publish = data.publish
econfig.build.directories.output = `${output}-generic`; appConfig.build.directories.output = `${output}-generic`;
fs.writeFileSync(packageFile, JSON.stringify(econfig, null, 4), 'utf8'); fs.writeFileSync(packageFile, JSON.stringify(appConfig, null, 4), 'utf8');
child_process.execSync(`npm run ${platform}`, {stdio: "inherit", cwd: "electron"}); child_process.execSync(`npm run ${platform}`, {stdio: "inherit", cwd: "electron"});
if (publish === true && PUBLISH_KEY) { if (publish === true && PUBLISH_KEY) {
genericPublish({ genericPublish({
url: econfig.build.publish.url, url: appConfig.build.publish.url,
key: PUBLISH_KEY, key: PUBLISH_KEY,
version: config.version, version: config.version,
output: econfig.build.directories.output output: appConfig.build.directories.output
}) })
} }
// package.json Recovery // package.json Recovery
@ -618,6 +658,13 @@ if (["dev"].includes(argv[2])) {
androidUpload(publish.url) androidUpload(publish.url)
} }
}) })
} else if (["published"].includes(argv[2])) {
// 发布完成GitHub Actions
config.app.forEach(async ({publish}) => {
if (publish.provider === 'generic') {
await published(publish.url)
}
})
} else if (["all", "win", "mac"].includes(argv[2])) { } else if (["all", "win", "mac"].includes(argv[2])) {
// 自动编译GitHub Actions // 自动编译GitHub Actions
platforms.filter(p => { platforms.filter(p => {

View File

@ -1,7 +1,7 @@
{ {
"name": "DooTask", "name": "DooTask",
"version": "0.40.16", "version": "0.39.10",
"codeVerson": 155, "codeVerson": 150,
"description": "DooTask is task management system.", "description": "DooTask is task management system.",
"scripts": { "scripts": {
"start": "./cmd dev", "start": "./cmd dev",

@ -1 +1 @@
Subproject commit a1d11bf46fd751c1a11088a572189d0c2fb6053c Subproject commit c5f85805ddd9f9cc36924b018a1fd779d70025fa