Compare commits

..

2 Commits

Author SHA1 Message Date
XiaoXia Bot f17e607ad2 fix(ci): 修复build-staging在PR模式下被跳过的问题
CI Build & Deploy / Build Production API Image (push) Has been skipped
CI Build & Deploy / Build Production Web Image (push) Has been skipped
CI Build & Deploy / Build Production Worker Image (push) Has been skipped
CI Build & Deploy / Build Production API Image (pull_request) Has been skipped
CI Build & Deploy / Build Production Web Image (pull_request) Has been skipped
CI Build & Deploy / Build Production Worker Image (pull_request) Has been skipped
CI Build & Deploy / Deploy Production (push) Has been skipped
CI Build & Deploy / Production Browser E2E (push) Has been skipped
CI Build & Deploy / Deploy Production (pull_request) Has been skipped
CI Build & Deploy / Production Browser E2E (pull_request) Has been skipped
CI Build & Deploy / Build Staging API Image (push) Failing after 32s
CI/CD Pipeline / Frontend Lint (push) Failing after 35s
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 2m10s
CI/CD Pipeline / Unit Tests (push) Successful in 2m12s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m51s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 2m12s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m21s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m32s
CI/CD Pipeline / Integration Tests (push) Successful in 1m46s
CI Build & Deploy / Build Staging Web Image (pull_request) Successful in 13m21s
CI Build & Deploy / Build Staging API Image (pull_request) Successful in 21m27s
CI Build & Deploy / Build Staging Web Image (push) Successful in 29m32s
CI Build & Deploy / Build Staging Worker Image (pull_request) Failing after 40m1s
CI Build & Deploy / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI Build & Deploy / Staging E2E Tests (pull_request) Has been skipped
CI Build & Deploy / Staging API Integration Tests (pull_request) Has been skipped
CI Build & Deploy / Build Staging Worker Image (push) Successful in 48m31s
CI Build & Deploy / Deploy Staging (Watchtower auto-deploy) (push) Has been skipped
CI Build & Deploy / Staging E2E Tests (push) Has been skipped
CI Build & Deploy / Staging API Integration Tests (push) Has been skipped
2026-07-15 16:58:43 +08:00
XiaoXia Bot 3cb232a84d feat(ci): 拆分构建workflow + buildx动态命名
CI Build & Deploy / Build Staging API Image (push) Has been skipped
CI Build & Deploy / Build Staging Web Image (push) Has been skipped
CI Build & Deploy / Build Staging Worker Image (push) Has been skipped
CI Build & Deploy / Build Production API Image (push) Has been skipped
CI Build & Deploy / Build Production Web Image (push) Has been skipped
CI Build & Deploy / Build Production Worker Image (push) Has been skipped
CI Build & Deploy / Deploy Staging (Watchtower auto-deploy) (push) Has been skipped
CI Build & Deploy / Deploy Production (push) Has been skipped
CI Build & Deploy / Staging API Integration Tests (push) Has been skipped
CI Build & Deploy / Production Browser E2E (push) Has been skipped
CI Build & Deploy / Staging E2E Tests (push) Has been skipped
CI Build & Deploy / Build Staging API Image (pull_request) Has been skipped
CI Build & Deploy / Build Staging Web Image (pull_request) Has been skipped
CI Build & Deploy / Build Staging Worker Image (pull_request) Has been skipped
CI Build & Deploy / Build Production API Image (pull_request) Has been skipped
CI Build & Deploy / Build Production Web Image (pull_request) Has been skipped
CI Build & Deploy / Build Production Worker Image (pull_request) Has been skipped
CI Build & Deploy / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI Build & Deploy / Deploy Production (pull_request) Has been skipped
CI Build & Deploy / Staging API Integration Tests (pull_request) Has been skipped
CI Build & Deploy / Staging E2E Tests (pull_request) Has been skipped
CI Build & Deploy / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Successful in 59s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 52s
CI/CD Pipeline / Unit Tests (push) Successful in 2m7s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m4s
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 2m28s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 2m24s
CI/CD Pipeline / Integration Tests (push) Successful in 1m28s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m23s
问题1 - cancel-in-progress踩踏:
- 将构建类job拆分到独立的 .gitea/workflows/ci-build.yml
- 新workflow cancel-in-progress: false,构建启动后不被新commit顶掉
- 原ci-cd.yml保留4个门禁job(validate/unit/integration/frontend-lint)
- 门禁workflow保持cancel-in-progress: true,快速响应新commit

问题2 - buildx name冲突:
- 所有 docker buildx create/use/rm 的 ci-builder 改为动态名
- 动态命名:ci-builder-${{ github.run_id }}-${{ github.job }}
- 每个job每个run独立builder实例,多runner同机构建不冲突

变更统计:
- ci-cd.yml:910行 → 406行(仅门禁)
- ci-build.yml:新增535行(构建+部署+E2E)
- buildx实例:10处引用全部动态化
2026-07-15 16:49:04 +08:00
12 changed files with 80 additions and 450 deletions
File diff suppressed because one or more lines are too long
+7 -3
View File
@@ -142,11 +142,15 @@ jobs:
python3 scripts/check_schema_metadata.py
'
- name: Check migration safety
- name: Prepare git for migration diff
shell: sh
env:
GITHUB_TOKEN: ${{ github.token }}
run: "set -eu\npython3 scripts/check_migration_safety.py --allow-medium-risk --diff-against origin/develop\n"
GITHUB_SERVER_URL: ${{ github.server_url }}
run: "set -eu\nif command -v git >/dev/null 2>&1; then\n if [ ! -d .git ]; then\n git init -q\n git config user.email \"ci@localhost\"\n git config user.name \"CI\"\n git add .\n git commit -q -m \"current\"\n REPO_URL=\"https://x-access-token:${GITHUB_TOKEN}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git\"\n git remote add origin \"$REPO_URL\"\n fi\n git fetch origin main --depth=1 -q 2>/dev/null || echo \"WARN: cannot fetch main, will check all migrations\"\nelse\n echo \"WARN: git not available, will check all migrations\"\nfi\n"
- name: Check migration safety
shell: sh
run: "set -eu\nif git rev-parse origin/main >/dev/null 2>&1; then\n python3 scripts/check_migration_safety.py --allow-medium-risk --diff-against origin/main\nelse\n python3 scripts/check_migration_safety.py --allow-medium-risk\nfi\n"
- name: Job duration summary
if: always()
shell: sh
@@ -399,4 +403,4 @@ jobs:
NOTIFY_MODE=failure JOB_NAME="Frontend Lint" python3 scripts/ci_notify.py
'
'
-37
View File
@@ -1,37 +0,0 @@
name: Debug Build Schedule
on:
push:
branches:
- debug/ci-build-schedule
jobs:
test-simple:
name: Test Simple Job
runs-on: host
steps:
- name: Hello
shell: sh
run: echo "Hello from simple job"
test-matrix:
name: Test Matrix ${{ matrix.name }}
runs-on: host
strategy:
fail-fast: false
matrix:
include:
- name: A
timeout: 5
- name: B
timeout: 5
timeout-minutes: ${{ matrix.timeout }}
steps:
- name: Hello
shell: sh
run: echo "Hello from matrix job ${{ matrix.name }}"
test-if:
name: Test If Condition
runs-on: host
if: github.event_name == "push" && github.ref_name == "debug/ci-build-schedule"
steps:
- name: Hello
shell: sh
run: echo "Hello from if job"
-64
View File
@@ -1,64 +0,0 @@
name: Debug Build Schedule v2 - Copy CI Build Structure
on:
push:
branches:
- debug/ci-build-schedule
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: false
jobs:
build-staging:
name: Build Staging ${{ matrix.service_display }} Image
runs-on: host
timeout-minutes: ${{ matrix.timeout }}
if: github.event_name == "push" && github.ref_name == "debug/ci-build-schedule"
strategy:
fail-fast: false
matrix:
include:
- service: api
service_display: API
timeout: 10
- service: worker
service_display: Worker
timeout: 10
- service: web
service_display: Web
timeout: 10
steps:
- name: Step 1
shell: sh
run: echo "Step 1"
- name: Step 2
shell: sh
run: echo "Step 2"
- name: Step 3
shell: sh
run: echo "Step 3"
deploy-staging:
name: Deploy Staging
runs-on: host
timeout-minutes: 15
if: github.event_name == "push" && github.ref_name == "debug/ci-build-schedule"
needs:
- build-staging
steps:
- name: Deploy
shell: sh
run: echo "Deploy"
build-production:
name: Build Production ${{ matrix.service_display }} Image
runs-on: host
timeout-minutes: ${{ matrix.timeout }}
if: startsWith(github.ref, "refs/tags/v")
strategy:
fail-fast: false
matrix:
include:
- service: api
service_display: API
timeout: 10
steps:
- name: Step 1
shell: sh
run: echo "Step 1"
-2
View File
@@ -72,7 +72,6 @@ class EditPlanResponse(BaseModel):
name: str
status: str
total_duration: float
result_count: int = 0
project_id: str = ""
created_by_user_id: str = ""
config: dict[str, Any]
@@ -242,7 +241,6 @@ def _to_response(p: EditPlan) -> EditPlanResponse:
name=p.name,
status=p.status.value if hasattr(p.status, "value") else p.status,
total_duration=p.total_duration,
result_count=getattr(p, "result_count", 0),
project_id=p.project_id or "",
created_by_user_id=p.created_by_user_id or "",
config=p.config,
+6 -15
View File
@@ -130,8 +130,6 @@ export interface EditPlan {
name: string;
status: EditPlanStatus;
total_duration: number;
/** 生成视频数量(后端 EditPlanResponse.result_count */
result_count: number;
config: EditPlanConfig;
created_at: string;
updated_at: string;
@@ -163,21 +161,14 @@ export interface GenerateResponse {
clip_count: number;
}
/** 剪辑计划关联的生成记录(实际是 GenerationTask 对象) */
/** 剪辑计划关联的生成记录 */
export interface EditPlanGeneration {
id: string; // 即 generation_task_id
source_edit_plan_id: string;
template_id: string;
asset_ids: string[];
id: string;
edit_plan_id: string;
generation_task_id: string;
status: EditPlanStatus;
progress: number;
result_count: number;
error_message: string;
error_info: Record<string, unknown>;
logs: Array<Record<string, unknown>>;
retry_count: number;
created_at?: string;
updated_at?: string;
created_at: string;
updated_at: string;
}
/** 片段生成状态 */
@@ -254,16 +254,6 @@ export default function EditPlans() {
<span className="plan-duration">{formatDuration(seconds)}</span>
),
},
{
title: "视频数",
dataIndex: "result_count",
key: "result_count",
width: 80,
align: "center",
render: (count: number) => (
<span className="plan-result-count">{count > 0 ? count : "—"}</span>
),
},
{
title: "创建时间",
dataIndex: "created_at",
@@ -1279,8 +1279,8 @@ const EditingPlanner: React.FC = () => {
{/* ═══ 生成进度弹窗 ═══ */}
<Modal
title={genError ? "生成失败" : generated ? "生成完成" : "正在生成视频"}
open={generating || generated || !!genError}
title={generated ? "生成完成" : "正在生成视频"}
open={generating || generated}
footer={
generated
? [
@@ -65,7 +65,7 @@ const GenerationHistoryModal: React.FC<GenerationHistoryModalProps> = ({
return (
<tr key={gen.id} className="ep-gh-table-row">
<td className="ep-gh-td ep-gh-td-id">
{gen.id ? `${gen.id.slice(0, 8)}...` : "—"}
{gen.generation_task_id.slice(0, 8)}...
</td>
<td className="ep-gh-td">
<span className={`ep-gh-status-tag ${statusClass}`}>
+1 -2
View File
@@ -1,10 +1,9 @@
from datetime import datetime, timezone
from typing import Any
from sqlalchemy import JSON, Boolean, Column, DateTime, Float, Integer, String, Text, UniqueConstraint
from sqlalchemy.orm import declarative_base
Base: Any = declarative_base()
Base = declarative_base()
class UserModel(Base):
+22 -32
View File
@@ -30,13 +30,10 @@
from __future__ import annotations
import argparse
import json
import os
import re
import subprocess
import sys
import urllib.error
import urllib.request
from pathlib import Path
from typing import List, Tuple
@@ -102,37 +99,30 @@ def extract_upgrade_content(content: str) -> str:
def get_new_migrations_via_diff(diff_target: str) -> List[Path]:
"""
通过 Gitea API 对比目标分支,找出 alembic/versions/ 下新增的迁移文件。
不依赖本地 git,避免 CI 环境下 git 操作不稳定的问题
通过 git diff 对比目标分支/commit,找出 alembic/versions/ 下新增的迁移文件。
只包含新增文件(A状态),不包含修改或删除的文件
"""
api_url = os.environ.get("GITHUB_API_URL", "")
repo = os.environ.get("GITHUB_REPOSITORY", "")
token = os.environ.get("GITHUB_TOKEN", "")
branch = diff_target.replace("origin/", "")
if not api_url or not repo or not token:
print("⚠️ CI 环境变量不完整,降级为检查所有迁移文件")
return sorted(ALEMBIC_VERSIONS_DIR.glob("*.py"))
try:
url = f"{api_url}/repos/{repo}/contents/alembic/versions?ref={branch}"
req = urllib.request.Request(url, headers={"Authorization": f"token {token}"})
with urllib.request.urlopen(req, timeout=15) as resp:
data = json.loads(resp.read().decode())
remote_files = {item["name"] for item in data if item["name"].endswith(".py")}
local_files = {f.name for f in ALEMBIC_VERSIONS_DIR.glob("*.py")}
new_file_names = sorted(local_files - remote_files)
if new_file_names:
result = [ALEMBIC_VERSIONS_DIR / f for f in new_file_names]
print(f" API 对比 {branch} 分支,发现 {len(result)} 个新增迁移)")
return result
else:
print(f" API 对比 {branch} 分支,无新增迁移)")
return []
except Exception as e:
print(f"⚠️ API 获取迁移列表失败:{e}")
result = subprocess.run(
[
"git",
"diff",
"--name-only",
"--diff-filter=A",
diff_target,
"HEAD",
"--",
"alembic/versions/",
],
cwd=str(REPO_ROOT),
capture_output=True,
text=True,
check=True,
)
files = [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
return [REPO_ROOT / f for f in files]
except subprocess.CalledProcessError as e:
print(f"⚠️ git diff 失败({diff_target}):{e.stderr.strip()}")
print(" 降级为检查所有迁移文件")
return sorted(ALEMBIC_VERSIONS_DIR.glob("*.py"))
+4 -4
View File
@@ -7,7 +7,7 @@
# 环境变量:
# IMAGE_TAG - 镜像版本 tag(如 commit SHA 或分支名)
# REGISTRY_TOKEN - Registry 访问令牌
# REGISTRY - Registry 地址(默认 xiaoxia-registry.cn-hangzhou.cr.aliyuncs.com/xiaoxiakeji
# REGISTRY - Registry 地址(默认 git.xiaoxiajianji.com/xiaoxia/xiaoxia-saas
# REGISTRY_USER - Registry 用户名(默认 xiaoxia
# ENV_FILE - 环境变量文件路径
# GENERATED_DIR - 生成文件目录
@@ -16,9 +16,9 @@
set -eu
IMAGE_TAG="${IMAGE_TAG:-}"
REGISTRY="${REGISTRY:-xiaoxia-registry.cn-hangzhou.cr.aliyuncs.com/xiaoxiakeji}"
REGISTRY_USER="${ACR_USERNAME:-${REGISTRY_USER:-nick0415343655}}"
REGISTRY_TOKEN="${ACR_PASSWORD:-${REGISTRY_TOKEN:-}}"
REGISTRY="${REGISTRY:-git.xiaoxiajianji.com/xiaoxia/xiaoxia-saas}"
REGISTRY_USER="${REGISTRY_USER:-xiaoxia}"
REGISTRY_TOKEN="${REGISTRY_TOKEN:-}"
ENV_FILE="${ENV_FILE:-/var/lib/xiaoxia-saas-staging/.env}"
GENERATED_DIR="${GENERATED_DIR:-/var/lib/xiaoxia-saas-staging/generated}"