perf: 优化客户端升级

This commit is contained in:
kuaifan 2024-11-14 14:49:14 +08:00
parent da066e40ce
commit 21eab03684
9 changed files with 305 additions and 163 deletions

View File

@ -1,63 +0,0 @@
name: Publish Android
on:
push:
tags:
- 'v*'
jobs:
Build:
name: Build Android
runs-on: ubuntu-latest
environment: build
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Use Node.js 20.x
uses: actions/setup-node@v1
with:
node-version: 20.x
- name: Build Js
uses: nick-fields/retry@v2
with:
timeout_minutes: 10
max_attempts: 5
command: |
git submodule init
git submodule update --remote "resources/mobile"
./cmd appbuild publish
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '11'
- name: Build Android
uses: nick-fields/retry@v2
with:
timeout_minutes: 60
max_attempts: 10
command: |
cd resources/mobile/platforms/android/eeuiApp
chmod +x ./gradlew
./gradlew assembleRelease --quiet
- name: Upload File
env:
DP_KEY: ${{ secrets.DP_KEY }}
run: |
node ./electron/build.js android-upload
- name: Release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
with:
files: |
resources/mobile/platforms/android/eeuiApp/app/build/outputs/apk/release/*.apk

View File

@ -1,35 +0,0 @@
name: Publish Mac
on:
push:
tags:
- 'v*'
jobs:
Build:
name: Build Mac
runs-on: macos-12
environment: build
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Use Node.js 20.x
uses: actions/setup-node@v1
with:
node-version: 20.x
- name: Build
env:
APPLEID: ${{ secrets.APPLEID }}
APPLEIDPASS: ${{ secrets.APPLEIDPASS }}
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
DP_KEY: ${{ secrets.DP_KEY }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GH_REPOSITORY: ${{ github.repository }}
run: |
./cmd electron mac

View File

@ -1,31 +0,0 @@
name: Publish Win
on:
push:
tags:
- 'v*'
jobs:
Build:
name: Build Windows
runs-on: windows-latest
environment: build
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Use Node.js 20.x
uses: actions/setup-node@v1
with:
node-version: 20.x
- name: Build
env:
DP_KEY: ${{ secrets.DP_KEY }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GH_REPOSITORY: ${{ github.repository }}
shell: bash
run: |
./cmd electron win

244
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,244 @@
name: "Publish"
on:
push:
branches:
- "pro"
jobs:
check-version:
permissions:
contents: read
runs-on: ubuntu-latest
outputs:
should_release: ${{ steps.check-tag.outputs.should_release }}
version: ${{ steps.get-version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Get version from package.json
id: get-version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Check if tag exists
id: check-tag
run: |
VERSION=${{ steps.get-version.outputs.version }}
if git ls-remote --tags origin | grep -q "refs/tags/v${VERSION}$"; then
echo "This version v${VERSION} has been released"
echo "should_release=false" >> $GITHUB_OUTPUT
else
echo "Version v${VERSION} has not been released, continue building"
echo "should_release=true" >> $GITHUB_OUTPUT
fi
create-release:
needs: check-version
if: needs.check-version.outputs.should_release == 'true'
permissions:
contents: write
runs-on: ubuntu-latest
outputs:
release_id: ${{ steps.create-release.outputs.result }}
steps:
- uses: actions/checkout@v4
- name: create release
id: create-release
uses: actions/github-script@v7
with:
script: |
// 获取最新的 tag
const { data: tags } = await github.rest.repos.listTags({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 1
});
// 获取提交日志
let changelog = '';
if (tags.length > 0) {
const { data: commits } = await github.rest.repos.compareCommits({
owner: context.repo.owner,
repo: context.repo.repo,
base: tags[0].name,
head: 'HEAD'
});
// 按类型分组提交
const groups = {
'feat:': { title: '## Features', commits: [] },
'fix:': { title: '## Bug Fixes', commits: [] },
'perf:': { title: '## Performance Improvements', commits: [] }
};
// 分类收集提交
commits.commits.forEach(commit => {
const message = commit.commit.message.split('\n')[0].trim();
for (const [prefix, group] of Object.entries(groups)) {
if (message.startsWith(prefix)) {
// 移除前缀后添加到对应分组
const cleanMessage = message.slice(prefix.length).trim();
group.commits.push(`- ${cleanMessage}`);
break;
}
}
});
// 生成更新日志
const sections = [];
for (const group of Object.values(groups)) {
if (group.commits.length > 0) {
sections.push(`${group.title}\n\n${group.commits.join('\n')}`);
}
}
if (sections.length > 0) {
changelog = '# Changelog\n\n' + sections.join('\n\n');
}
}
// 创建 release
const { data } = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: `v${{ needs.check-version.outputs.version }}`,
name: `${{ needs.check-version.outputs.version }}`,
body: changelog || 'No significant changes in this release.',
draft: true,
prerelease: false
})
return data.id
build-client:
needs: [ check-version, create-release ]
if: needs.check-version.outputs.should_release == 'true'
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: "macos-latest"
build_type: "mac"
args: "--target aarch64-apple-darwin"
- platform: "macos-latest"
build_type: "mac"
args: "--target x86_64-apple-darwin"
- platform: "ubuntu-latest"
build_type: "android"
args: ""
- platform: "windows-latest"
build_type: "windows"
args: ""
runs-on: ${{ matrix.platform }}
environment: build
steps:
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v1
with:
node-version: 20.x
# Android 构建步骤
- name: Build Js for Android
if: matrix.build_type == 'android'
uses: nick-fields/retry@v2
with:
timeout_minutes: 10
max_attempts: 5
command: |
git submodule init
git submodule update --remote "resources/mobile"
./cmd appbuild publish
- name: Setup JDK 11 for Android
if: matrix.build_type == 'android'
uses: actions/setup-java@v3
with:
distribution: "zulu"
java-version: "11"
- name: Build Android App
if: matrix.build_type == 'android'
uses: nick-fields/retry@v2
with:
timeout_minutes: 60
max_attempts: 10
command: |
cd resources/mobile/platforms/android/eeuiApp
chmod +x ./gradlew
./gradlew assembleRelease --quiet
- name: Upload Android File
if: matrix.build_type == 'android'
env:
DP_KEY: ${{ secrets.DP_KEY }}
run: |
node ./electron/build.js android-upload
# Mac 构建步骤
- name: Build Mac App
if: matrix.build_type == 'mac'
env:
APPLEID: ${{ secrets.APPLEID }}
APPLEIDPASS: ${{ secrets.APPLEIDPASS }}
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
DP_KEY: ${{ secrets.DP_KEY }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GH_REPOSITORY: ${{ github.repository }}
run: |
./cmd electron mac
# Windows 构建步骤
- name: Build Windows App
if: matrix.build_type == 'windows'
env:
DP_KEY: ${{ secrets.DP_KEY }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GH_REPOSITORY: ${{ github.repository }}
shell: bash
run: |
./cmd electron win
# 上传Android构建产物
- name: Upload Android Release Assets
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
if: matrix.build_type == 'android'
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.check-version.outputs.version }}
files: |
resources/mobile/platforms/android/eeuiApp/app/build/outputs/apk/release/*.apk
# publish-release:
# needs: [check-version, create-release, builds]
# if: needs.check-version.outputs.should_release == 'true'
# permissions:
# contents: write
# runs-on: ubuntu-latest
# steps:
# - name: publish release
# id: publish-release
# uses: actions/github-script@v7
# env:
# release_id: ${{ needs.create-release.outputs.release_id }}
# with:
# script: |
# github.rest.repos.updateRelease({
# owner: context.repo.owner,
# repo: context.repo.repo,
# release_id: process.env.release_id,
# draft: false,
# prerelease: false
# })

View File

@ -126,7 +126,7 @@ class IndexController extends InvokeController
// 其他
'bot', 'robot', 'auto', 'anonymous', 'guest', 'default', 'new', 'old'
];
$filterWords = array_map(function($word) {
$filterWords = array_map(function ($word) {
return preg_quote($word, '/');
}, $filterWords);
$name = preg_replace('/' . implode('|', $filterWords) . '/iu', '', $name) ?: $name;
@ -157,7 +157,7 @@ class IndexController extends InvokeController
'\x{1F900}-\x{1F9FF}',
'\x{1F600}-\x{1F64F}'
];
$filterSymbols = array_map(function($symbol) {
$filterSymbols = array_map(function ($symbol) {
return preg_quote($symbol, '/');
}, $filterSymbols);
$name = preg_replace('/[' . implode('', $filterSymbols) . ']/u', '', $name) ?: $name;
@ -171,7 +171,7 @@ class IndexController extends InvokeController
if (empty($color)) {
$color = '#ffffff';
$cacheKey = "avatarBackgroundColor::" . md5($name);
$background = Cache::rememberForever($cacheKey, function() {
$background = Cache::rememberForever($cacheKey, function () {
return RandomColor::one(['luminosity' => 'dark']);
});
}
@ -192,7 +192,7 @@ class IndexController extends InvokeController
'shape' => 'square',
'width' => $size,
'height' => $size,
'chars' => 2,
'chars' => 2,
'fontSize' => $size / 2.9,
'uppercase' => true,
'fonts' => [resource_path('assets/statics/fonts/Source_Han_Sans_SC_Regular.otf')],
@ -264,7 +264,6 @@ class IndexController extends InvokeController
public function desktop__publish($name = '')
{
$publishVersion = Request::header('publish-version');
$fileNum = Request::get('file_num', 1);
$latestFile = public_path("uploads/desktop/latest");
$latestVersion = file_exists($latestFile) ? trim(file_get_contents($latestFile)) : "0.0.1";
if (strtolower($name) === 'latest') {
@ -272,27 +271,29 @@ class IndexController extends InvokeController
}
// 上传
if (preg_match("/^\d+\.\d+\.\d+$/", $publishVersion)) {
$uploadSuccessFileNum = (int)Cache::get($publishVersion, 0);
// 判断密钥
$publishKey = Request::header('publish-key');
if ($publishKey !== env('APP_KEY')) {
return Base::retError("key error");
}
// 判断版本
if (version_compare($publishVersion, $latestVersion) > -1) { // 限制上传版本必须 ≥ 当前版本
$publishPath = "uploads/desktop/{$publishVersion}/";
$res = Base::upload([
"file" => Request::file('file'),
"type" => 'publish',
"path" => $publishPath,
"fileName" => true,
"quality" => 100
]);
if (Base::isSuccess($res)) {
$action = Request::get('action');
$draftPath = "uploads/desktop-draft/{$publishVersion}/";
if ($action === 'release') {
// 将草稿版本发布为正式版本
$draftPath = public_path($draftPath);
$releasePath = public_path("uploads/desktop/{$publishVersion}/");
if (!file_exists($draftPath)) {
return Base::retError("draft version not exists");
}
if (file_exists($releasePath)) {
Base::deleteDirAndFile($releasePath);
}
Base::copyDirectory($draftPath, $releasePath);
file_put_contents($latestFile, $publishVersion);
$uploadSuccessFileNum = $uploadSuccessFileNum + 1;
Cache::set($publishVersion, $uploadSuccessFileNum, 7200);
}
if ($uploadSuccessFileNum >= $fileNum) {
// 删除旧版本
Base::deleteDirAndFile(public_path("uploads/desktop-draft"));
$dirs = Base::recursiveDirs(public_path("uploads/desktop"), false);
sort($dirs);
$num = 0;
@ -309,8 +310,16 @@ class IndexController extends InvokeController
Base::deleteDirAndFile($dir);
}
}
return Base::retSuccess('success');
}
return $res;
// 上传草稿版本
return Base::upload([
"file" => Request::file('file'),
"type" => 'publish',
"path" => $draftPath,
"fileName" => true,
"quality" => 100
]);
}
}
// 列表

View File

@ -13,7 +13,6 @@ use League\CommonMark\Exception\CommonMarkException;
use Overtrue\Pinyin\Pinyin;
use Redirect;
use Request;
use Response;
use Storage;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\File;
@ -372,6 +371,34 @@ class Base
}
}
/**
* 复制文件夹
* @param $source
* @param $destination
* @return bool
*/
public static function copyDirectory($source, $destination)
{
if (!is_dir($source)) {
return false;
}
if (!is_dir($destination)) {
Base::makeDir($destination);
}
$dir = opendir($source);
while (false !== ($file = readdir($dir))) {
if (($file != '.') && ($file != '..')) {
if (is_dir($source . '/' . $file)) {
self::copyDirectory($source . '/' . $file, $destination . '/' . $file);
} else {
copy($source . '/' . $file, $destination . '/' . $file);
}
}
}
closedir($dir);
return true;
}
/**
*
* 截取字符串

1
cmd
View File

@ -174,6 +174,7 @@ run_electron() {
mkdir -p ./electron/public
cp ./electron/index.html ./electron/public/index.html
npx vite build -- fromcmd electronBuild
echo ""
fi
node ./electron/build.js $argv
}

14
electron/build.js vendored
View File

@ -292,7 +292,7 @@ function androidUpload(url) {
uploadOras[filename] = ora(`Upload [0%] ${filename}`).start()
const formData = new FormData()
formData.append("file", fs.createReadStream(localFile));
formData.append("file_num", 1);
formData.append("action", "draft");
await axiosAutoTry({
axios: {
method: 'post',
@ -358,16 +358,6 @@ function genericPublish({url, key, version, output}) {
if (err) {
console.warn(err)
} else {
let uploadFileNum = 0;
for (const filename of files) {
const localFile = path.join(filePath, filename)
if (fs.existsSync(localFile)) {
const fileStat = fs.statSync(localFile)
if (fileStat.isFile()) {
uploadFileNum += 1;
}
}
}
const uploadOras = {}
for (const filename of files) {
const localFile = path.join(filePath, filename)
@ -377,7 +367,7 @@ function genericPublish({url, key, version, output}) {
uploadOras[filename] = ora(`Upload [0%] ${filename}`).start()
const formData = new FormData()
formData.append("file", fs.createReadStream(localFile));
formData.append("file_num", uploadFileNum);
formData.append("action", "draft");
await axiosAutoTry({
axios: {
method: 'post',

View File

@ -1,6 +1,6 @@
{
"name": "DooTask",
"version": "0.39.97",
"version": "0.39.98",
"codeVerson": 154,
"description": "DooTask is task management system.",
"scripts": {