ci: add pull request validation workflow

This commit is contained in:
xiwangly2
2026-09-26 15:32:26 +08:00
parent dba015eed4
commit 3d36b994c5
7 changed files with 193 additions and 49 deletions

View File

@@ -80,12 +80,16 @@ jobs:
with:
node-version: '22.16.0'
cache: 'npm'
cache-dependency-path: |
package-lock.json
client/package-lock.json
server/package-lock.json
- name: Install dependencies
run: |
npm install
cd client && npm install
cd ../server && npm install
npm ci
npm ci --prefix client
npm ci --prefix server
- name: Build Linux ${{ matrix.arch }} package
run: ${{ matrix.package_command }}
env:
@@ -111,15 +115,15 @@ jobs:
with:
node-version: '22.16.0'
cache: 'npm'
cache-dependency-path: |
package-lock.json
client/package-lock.json
server/package-lock.json
- name: Install dependencies
run: |
npm install
cd client
npm install
cd ..
cd server
npm install
cd ..
npm ci
npm ci --prefix client
npm ci --prefix server
- name: Build package
run: npm run package:windows
env:

106
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,106 @@
name: CI
on:
pull_request:
branches:
- main
types:
- opened
- synchronize
- reopened
- ready_for_review
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
CI: true
NODE_VERSION: '22.16.0'
jobs:
server:
name: Server test and build
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: server/package-lock.json
- name: Install server dependencies
run: npm ci
working-directory: server
- name: Run server tests
run: npm test
working-directory: server
- name: Build server
run: npm run build
working-directory: server
client:
name: Client test and build
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: client/package-lock.json
- name: Install client dependencies
run: npm ci
working-directory: client
- name: Run client tests
run: npm test
working-directory: client
- name: Build client
run: npm run build
working-directory: client
project-scripts:
name: Project scripts
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: package-lock.json
- name: Install root dependencies
run: npm ci
- name: Check packaging scripts syntax
run: |
node --check scripts/package.js
node --check scripts/resolve-build-version.js
- name: Resolve build version
run: node scripts/resolve-build-version.js

View File

@@ -88,6 +88,18 @@ async function waitFor(condition: () => boolean, timeoutMs = 5000): Promise<void
/** 完成所有 XHR 并结束上传流程 */
async function cleanupUpload(uploadPromise: Promise<void>, chunkSize: number): Promise<void> {
try {
;(globalThis.fetch as any).mockImplementation(async (url: string, options?: any) => {
if (options?.body) {
try {
const body = JSON.parse(options.body)
if (body.uploadId !== undefined && body.totalChunks !== undefined && !body.chunkIndex && body.targetPath) {
return { ok: true, json: async () => ({ success: true }) }
}
} catch { /* 非 JSON body */ }
}
return { ok: true, json: async () => ({ uploadedChunks: [] }) }
})
// 多轮完成,处理批次间的延迟和新 XHR 创建
for (let round = 0; round < 5; round++) {
for (const xhr of xhrInstances) {
@@ -98,11 +110,6 @@ async function cleanupUpload(uploadPromise: Promise<void>, chunkSize: number): P
}
await new Promise(r => setTimeout(r, 300))
}
// Mock merge
;(globalThis.fetch as any).mockResolvedValue({
ok: true,
json: async () => ({ success: true }),
})
await Promise.race([
uploadPromise,
new Promise((_, rej) => setTimeout(() => rej(new Error('清理超时')), 8000)),

View File

@@ -419,11 +419,14 @@ describe('保持行为属性测试 — 非进度计算行为不变', () => {
it('属性4: abort 信号正确中止所有 XHR 请求', async () => {
const FILE_SIZE = 200 * MB
const controller = new AbortController()
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
const file = createMockFile(FILE_SIZE)
const uploader = new ChunkUploader({
file,
targetPath: '/test',
maxRetries: 1,
signal: controller.signal,
})
@@ -450,6 +453,10 @@ describe('保持行为属性测试 — 非进度计算行为不变', () => {
// 验证 XHR 实例的 abort 被调用
const abortedCount = xhrBeforeAbort.filter(xhr => xhr._aborted).length
expect(abortedCount).toBe(CONCURRENT_UPLOADS)
await uploadPromise
consoleWarnSpy.mockRestore()
consoleErrorSpy.mockRestore()
})
// ============================================================

View File

@@ -6,7 +6,7 @@
export interface ChunkUploadOptions {
file: File
targetPath: string
chunkSize?: number // 默认50MB
chunkSize?: number // 默认20MB
maxRetries?: number // 单个分片最大重试次数
onProgress?: (progress: number) => void
onChunkProgress?: (chunkIndex: number, totalChunks: number, chunkProgress: number) => void

View File

@@ -2,11 +2,28 @@
## 概述
项目现已支持通过GitHub Actions自动构建多架构Docker镜像,包括AMD64和ARM64平台。
项目通过 GitHub Actions 分离常规 CI 与发布构建:
- `ci.yml`:PR / `main` 分支常规检查,运行服务端测试与构建、前端测试与构建、根级脚本语法检查。
- `build.yml`:发布构建,支持 Linux / Windows 应用包和 Docker 镜像。
## 可用的构建选项
### 1. 主构建工作流 (build.yml)
### 1. 常规 CI 工作流 (ci.yml)
#### 自动触发:
- PR 打开、重新打开、推送新提交或从 Draft 标记为可审阅
- 推送到 `main` 分支
#### 手动触发:
- 支持 `workflow_dispatch`
#### 检查内容:
- 服务端:`npm ci`、`npm test`、`npm run build`
- 前端:`npm ci`、`npm test`、`npm run build`
- 根级脚本:`npm ci`、`node --check scripts/package.js`、`node --check scripts/resolve-build-version.js`
### 2. 发布构建工作流 (build.yml)
#### 手动触发选项:
- ✅ **构建Linux版本** - 构建Linux应用包
@@ -23,22 +40,15 @@
> 导致同一版本启动两次构建、并发推送同一 Docker 标签互相冲突。
> 详见 [Release重复触发CI修复说明.md](./Release重复触发CI修复说明.md)。
### 2. 专用多架构工作流 (docker-multiarch.yml)
提供更详细的多架构构建控制:
- 可选择构建平台组合
- 支持自定义镜像标签
- 包含架构验证测试
## 使用方法
### 方法一:GitHub网页操作
1. 进入GitHub仓库页面
2. 点击 **Actions** 标签
3. 选择 **Build Package** 工作流
3. 选择 **Build Package** 工作流进行发布构建,或选择 **CI** 手动运行常规检查
4. 点击 **Run workflow**
5. 选择需要的构建选项:
5. 如果运行 **Build Package**,选择需要的构建选项:
- ☑️ 构建ARM64 Docker镜像
- ☑️ 构建Docker镜像(多架构)
6. 点击 **Run workflow** 开始构建
@@ -64,8 +74,8 @@ gh workflow run build.yml -f build_docker=true
# 触发所有构建
gh workflow run build.yml -f build_linux=true -f build_windows=true -f build_docker=true -f build_docker_arm=true
# 使用专用多架构工作流
gh workflow run docker-multiarch.yml -f tag=latest -f platforms="linux/amd64,linux/arm64" -f push_to_registry=true
# 手动触发常规 CI
gh workflow run ci.yml
```
## 构建产物
@@ -138,7 +148,7 @@ docker run --platform linux/amd64 --rm xiaozhu674/gameservermanager:latest uname
1. **开发阶段**:使用ARM64专用构建进行快速测试
2. **发布阶段**:使用多架构构建确保兼容性
3. **标签管理**:为不同版本使用语义化版本标签
4. **缓存优化**:GitHub Actions会自动缓存构建层以加速后续构建
4. **缓存优化**:GitHub Actions 会缓存 npm 下载缓存和 Docker 构建层以加速后续构建
## 更新日志
@@ -146,3 +156,4 @@ docker run --platform linux/amd64 --rm xiaozhu674/gameservermanager:latest uname
- **v1.1**: 支持多架构并行构建
- **v1.2**: 添加构建验证和测试步骤
- **v1.3**: 移除 release 事件触发器,修复发布 Release 时重复启动两次构建的问题
- **v1.4**: 新增 PR/main 常规 CI,并将发布构建依赖安装改为 `npm ci`

View File

@@ -1,30 +1,39 @@
# PR 自动语法检查说明
# PR 自动检查说明
## 说明
`pr-auto-check.yml` 现在只负责对 PR 进行代码语法检查,不再执行以下操作:
`.github/workflows/ci.yml` 负责 PR 和 `main` 分支的常规持续集成检查。该流程只做只读校验,不评论 PR、不自动合并,也不修改目标分支。
- 自动切换 PR 的目标分支
- 自动合并 PR
- 自动创建或调整 `feature` 分支
发布构建仍由 `.github/workflows/build.yml` 负责,避免把 PR 校验和 Release 打包推送混在一起。
## 触发时机
- PR 打开、重新打开、推送新提交或从 Draft 标记为可审阅时触发。
- 推送到 `main` 分支时触发。
- 维护者也可以通过 `workflow_dispatch` 手动触发。
同一 PR 或同一分支的旧运行会被自动取消,减少重复排队。
## 检查范围
当前流程会在 PR 打开、重新打开、推送新提交或标记为可审阅时触发,并执行以下内容:
当前 CI 包含三个 job:
1. 读取 PR 变更文件列表,并在评论中提示当前状态
2. 检出 PR 对应提交
3. 判断是否仅包含文档变更
4. 对 `server` 和 `client` 分别执行 `npx tsc --noEmit`
5. 如果检查失败,在 PR 中回复中文错误信息
## 结果说明
- 如果 PR 仅修改文档或文本文件,会跳过代码语法检查,并在 PR 中给出提示
- 如果 `server` 或 `client` 的 TypeScript 检查失败,工作流会返回对应的错误输出
- 如果检查通过,工作流不会再自动合并代码,也不会修改 PR 的目标分支
1. `Server test and build`
- `cd server && npm ci`
- `cd server && npm test`
- `cd server && npm run build`
2. `Client test and build`
- `cd client && npm ci`
- `cd client && npm test`
- `cd client && npm run build`
3. `Project scripts`
- `npm ci`
- `node --check scripts/package.js`
- `node --check scripts/resolve-build-version.js`
- `node scripts/resolve-build-version.js`
## 维护建议
- 如果后续希望增加其他静态检查,可以在这里继续补充流程说明
- 如果需要恢复自动合并,请单独设计新的工作流,不建议和语法检查混在一起
- CI 中优先使用 `npm ci`,确保 lockfile 和实际安装一致。
- 新增必须通过的检查前,先确认当前 `upstream/main` 基线能稳定通过。
- Release 打包、Docker 推送和上传 GitHub Release 资产应继续放在 `build.yml`,并只在标签推送或手动触发时执行。