Compare commits

..

4 Commits

Author SHA1 Message Date
xiaoxia 1a5bb1ab43 feat(ci): optimize web image build with multi-stage Dockerfile + buildx cache
Tests / test (pull_request) Failing after 0s
Tests / lint (pull_request) Failing after 0s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m59s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 2m12s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
2026-07-13 15:11:28 +08:00
xiaoxia bf47e69fa4 feat(ci): add node_modules cache for frontend-lint job 2026-07-13 15:10:44 +08:00
xiaoxia b947bf7569 feat(ci): add node_modules cache for frontend-lint job 2026-07-13 15:09:47 +08:00
xiaoxia f110bc6f16 feat: web.Dockerfile add buildkit cache for npm install 2026-07-13 15:08:49 +08:00
5 changed files with 29 additions and 40 deletions
+11
View File
@@ -192,6 +192,7 @@ jobs:
frontend-lint:
name: Frontend Lint
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Checkout code
@@ -217,7 +218,17 @@ jobs:
tar -xzf /tmp/repo.tar.gz --strip-components=1 -C .
rm -f /tmp/repo.tar.gz
- name: Cache node_modules
id: cache-node-modules
uses: actions/cache@v4
with:
path: apps/web/node_modules
key: ${{ runner.os }}-node-web-${{ hashFiles('apps/web/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-web-
- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
shell: sh
run: |
set -eu
Executable → Regular
+3 -12
View File
@@ -35,7 +35,7 @@ export interface CreateGenerationTaskRequest {
}
/** 创建生成任务响应(对齐后端 GenerationTaskResponse */
export interface GenerationTaskItem {
export interface CreateGenerationTaskResponse {
id: string;
project_id: string;
asset_library_id: string;
@@ -51,22 +51,13 @@ export interface GenerationTaskItem {
error_message: string;
}
/** 批量创建响应(对齐后端 BatchGenerationTaskResponse */
export interface BatchGenerationTaskResponse {
items: GenerationTaskItem[];
total: number;
}
/** @deprecated 请使用 GenerationTaskItem */
export type CreateGenerationTaskResponse = GenerationTaskItem;
/* ──────────── API 函数 ──────────── */
/** 创建生成任务(一键生成) */
export const createGenerationTask = async (
params: CreateGenerationTaskRequest,
): Promise<BatchGenerationTaskResponse> => {
const { data } = await apiClient.post<BatchGenerationTaskResponse>(
): Promise<CreateGenerationTaskResponse> => {
const { data } = await apiClient.post<CreateGenerationTaskResponse>(
"/generation/tasks",
params,
);
@@ -505,20 +505,8 @@ const EditingPlanner: React.FC = () => {
title_ids: [],
voice_ids: voiceIds,
});
/*
* createGenerationTask 返回批量响应 {items, total}
* 取第一个任务的 ID。后端返回裸 UUID,
* 但任务中心 API(getTask)使用带前缀的 IDgeneration:xxx),
* 需补前缀后再查询。
*/
const firstTask = res.items?.[0];
if (!firstTask) {
throw new Error("创建生成任务失败:无返回任务");
}
const rawId = firstTask.id;
const taskId = rawId.includes(":") ? rawId : `generation:${rawId}`;
/* 创建接口返回的是精简响应,需查询完整 TaskItem 用于轮询 */
const task = await getTask(taskId);
const task = await getTask(res.id);
setGenTask(task);
setGenPhase("progress");
message.info("生成任务已创建");
@@ -547,8 +535,8 @@ const EditingPlanner: React.FC = () => {
setGenPhase("failed");
clearInterval(timer);
}
} catch (err) {
console.warn("[生成轮询] 查询任务状态失败", err);
} catch {
/* ignore */
}
}, 3000);
return () => clearInterval(timer);
+3 -1
View File
@@ -5,7 +5,9 @@ ARG VITE_API_URL=https://saas-api.xiaoxiajianji.com
ENV VITE_API_URL=$VITE_API_URL
COPY apps/web/package.json apps/web/package-lock.json ./apps/web/
WORKDIR /app/apps/web
RUN npm config set registry https://registry.npmmirror.com \
RUN \
--mount=type=cache,target=/root/.npm \
npm config set registry https://registry.npmmirror.com \
&& npm ci
COPY apps/web/ ./
RUN npm run build
+9 -12
View File
@@ -72,28 +72,25 @@ else
fi
echo "=== Building Web image (with buildx cache) ==="
# 先构建前端产物
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace/apps/web \
docker.m.daocloud.io/library/node:20 \
sh -lc "npm ci && npm run build"
test -f apps/web/dist/index.html
# 使用多阶段 Dockerfile 构建,配合 buildx cache 缓存 npm 安装和构建产物
WEB_NGINX_CONF="${WEB_NGINX_CONF:-infra/docker/nginx-production.conf}"
WEB_API_URL="${VITE_API_URL:-https://saas-api.xiaoxiajianji.com}"
if [ "$USE_CACHE" -eq 1 ]; then
docker buildx build \
--cache-from "type=registry,ref=${CACHE_REGISTRY}/web-cache:${CACHE_TAG},ignore-error=true" \
--cache-to "type=registry,ref=${CACHE_REGISTRY}/web-cache:${CACHE_TAG},mode=max" \
-f infra/docker/web-artifact.Dockerfile \
--build-arg NGINX_CONF=infra/docker/nginx-production.conf \
-f infra/docker/web.Dockerfile \
--build-arg NGINX_CONF="${WEB_NGINX_CONF}" \
--build-arg VITE_API_URL="${WEB_API_URL}" \
-t "$WEB_IMAGE" \
--load \
.
else
docker build --pull=false \
-f infra/docker/web-artifact.Dockerfile \
--build-arg NGINX_CONF=infra/docker/nginx-production.conf \
-f infra/docker/web.Dockerfile \
--build-arg NGINX_CONF="${WEB_NGINX_CONF}" \
--build-arg VITE_API_URL="${WEB_API_URL}" \
-t "$WEB_IMAGE" \
.
fi