feat(ops): U4 后端镜像瘦身 282MB→107MB (62%降幅)
- 移除 git/docker-cli/docker-cli-buildx (~100MB) 改为懒加载 - PipelineHandler 注入 ToolInstaller, runCheckout/runImageBuild 调 EnsureAvailable - UpgradeTools 自动升级 DB 中 git/docker-cli preinstall→lazy - 仅内置 linux-amd64 agent (~12MB节省), arm64/darwin 通过下载API - kubectl 改用 install-kubectl.sh 下载 stripped 版本 - .dockerignore 排除 backend/kubectl 60MB 二进制 - Dockerfile.embed + backend/Dockerfile 同步更新 - 17/17 集成测试通过
This commit is contained in:
1 parent
8dd5a07b70
commit
c624ca5b4a
11 files changed
+159
-31
No files matched your search
@@ -27,3 +27,6 @@ docs/
|
|||||||
# IDE
|
# IDE
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
# U4: 大型预装二进制(kubectl 通过 install-kubectl.sh 下载, 不需要构建上下文中携带 60MB)
|
||||||
|
backend/kubectl
|
||||||
+9
-10
@@ -94,14 +94,15 @@ FROM alpine:3.20
|
|||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG KUBECTL_VERSION=v1.32.2
|
ARG KUBECTL_VERSION=v1.32.2
|
||||||
|
|
||||||
# 安装运行时依赖(核心最小集,重型工具改为懒加载)// Logan.Li
|
# 安装运行时依赖(U4 镜像瘦身 — 核心最小集, git/docker-cli 改为懒加载)// Logan.Li
|
||||||
# kubectl 从本地 backend/kubectl 复制(预打包进镜像,避免网络下载)// Logan.Li
|
# kubectl 通过 install-kubectl.sh 下载(避免构建上下文携带 60MB 二进制)// Logan.Li
|
||||||
COPY scripts/setup-alpine-mirrors.sh /tmp/setup-alpine-mirrors.sh
|
COPY scripts/setup-alpine-mirrors.sh scripts/install-kubectl.sh /tmp/
|
||||||
RUN chmod +x /tmp/setup-alpine-mirrors.sh && /tmp/setup-alpine-mirrors.sh && \
|
RUN chmod +x /tmp/setup-alpine-mirrors.sh && /tmp/setup-alpine-mirrors.sh && \
|
||||||
apk --no-cache add ca-certificates tzdata bash curl git docker-cli docker-cli-buildx
|
apk add --no-cache ca-certificates tzdata bash curl && \
|
||||||
COPY backend/kubectl /usr/local/bin/kubectl
|
chmod +x /tmp/install-kubectl.sh && \
|
||||||
RUN chmod +x /usr/local/bin/kubectl && \
|
TARGET_OS=linux TARGET_ARCH="${TARGETARCH}" KUBECTL_VERSION="${KUBECTL_VERSION}" \
|
||||||
rm -f /tmp/setup-alpine-mirrors.sh
|
/tmp/install-kubectl.sh /usr/local/bin/kubectl && \
|
||||||
|
rm -f /tmp/setup-alpine-mirrors.sh /tmp/install-kubectl.sh
|
||||||
|
|
||||||
# Maven 阿里云镜像加速(maven 懒加载后生效)
|
# Maven 阿里云镜像加速(maven 懒加载后生效)
|
||||||
RUN mkdir -p /root/.m2 && \
|
RUN mkdir -p /root/.m2 && \
|
||||||
@@ -120,10 +121,8 @@ COPY --from=backend-builder /app/aiops .
|
|||||||
# 创建运行时目录
|
# 创建运行时目录
|
||||||
RUN mkdir -p /app/agent/bin /app/agent/deploy
|
RUN mkdir -p /app/agent/bin /app/agent/deploy
|
||||||
|
|
||||||
# 复制 agent 二进制
|
# 复制 agent 二进制(U4: 仅 linux-amd64 内置, arm64/darwin 通过下载 API 提供)// Logan.Li
|
||||||
COPY --from=agent-builder /agent/bin/aiops-agent-linux-amd64 /app/agent/bin/
|
COPY --from=agent-builder /agent/bin/aiops-agent-linux-amd64 /app/agent/bin/
|
||||||
COPY --from=agent-builder /agent/bin/aiops-agent-linux-arm64 /app/agent/bin/
|
|
||||||
COPY --from=agent-builder /agent/bin/aiops-agent-darwin-arm64 /app/agent/bin/
|
|
||||||
|
|
||||||
# 复制 agent 安装脚本
|
# 复制 agent 安装脚本
|
||||||
COPY agent/deploy/install.sh /app/agent/deploy/
|
COPY agent/deploy/install.sh /app/agent/deploy/
|
||||||
|
|||||||
@@ -171,7 +171,7 @@
|
|||||||
|
|
||||||
| 镜像 | 大小 | 评估 |
|
| 镜像 | 大小 | 评估 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| aiops-backend | 277 MB | ⚠️ 偏大(含 Agent 编译工具链) |
|
| aiops-backend | ~~277 MB~~ → **107 MB** | ✅ U4 镜像瘦身完成(git/docker-cli 改懒加载, 仅 amd64 agent, kubectl stripped) |
|
||||||
| aiops-frontend | 69.8 MB | ✅ Nginx Alpine |
|
| aiops-frontend | 69.8 MB | ✅ Nginx Alpine |
|
||||||
| aiops-embed | 54.9 MB | ✅ 单文件 |
|
| aiops-embed | 54.9 MB | ✅ 单文件 |
|
||||||
|
|
||||||
@@ -202,6 +202,6 @@
|
|||||||
| 功能完整性 | **88/100** | 8 大模块齐全,K8s 管理极为完善;扣分项:监控大屏/链路追踪/告警静默未对接 |
|
| 功能完整性 | **88/100** | 8 大模块齐全,K8s 管理极为完善;扣分项:监控大屏/链路追踪/告警静默未对接 |
|
||||||
| 代码质量 | **82/100** | 后端规范好(0 panic, 1 TODO);前端 any 从 1026 降至 40 + tsc --noEmit 零错误,类型安全大幅提升 |
|
| 代码质量 | **82/100** | 后端规范好(0 panic, 1 TODO);前端 any 从 1026 降至 40 + tsc --noEmit 零错误,类型安全大幅提升 |
|
||||||
| 架构设计 | **86/100** | 前后端分离清晰,自研轻量 K8s 客户端;kubernetes.go/api.ts 已拆分,K8s 双路由已统一为 code 路由为主 (A1 done),WebSocket 统一管理 (A3 done) |
|
| 架构设计 | **86/100** | 前后端分离清晰,自研轻量 K8s 客户端;kubernetes.go/api.ts 已拆分,K8s 双路由已统一为 code 路由为主 (A1 done),WebSocket 统一管理 (A3 done) |
|
||||||
| 部署运维 | **87/100** | 三种部署方式 + run.sh 统一入口;扣分项:后端镜像偏大 |
|
| 部署运维 | **90/100** | 三种部署方式 + run.sh 统一入口;镜像优化 U4 done (282MB→107MB) |
|
||||||
| 用户体验 | **88/100** | 骨架屏 + 页面过渡 + 5 套主题 + 懒加载 + 虚拟滚动 + 统一 DataTable;扣分项:无 i18n |
|
| 用户体验 | **88/100** | 骨架屏 + 页面过渡 + 5 套主题 + 懒加载 + 虚拟滚动 + 统一 DataTable;扣分项:无 i18n |
|
||||||
| **综合** | **87/100** | 企业级运维平台,功能覆盖全面,P0 全部完成,P1 全部完成,P2 A1/A2/A3 全部完成,P3 U1 虚拟滚动 done, U2 统一 DataTable done |
|
| **综合** | **88/100** | 企业级运维平台,功能覆盖全面,P0 全部完成,P1 全部完成,P2 A1/A2/A3 全部完成,P3 U1/U2/U4 done (仅 U3 国际化 pending) |
|
||||||
+21
-4
@@ -267,9 +267,26 @@ services/api.ts (1324L)
|
|||||||
- 提取所有中文文案到 `i18n/zh-CN.json`
|
- 提取所有中文文案到 `i18n/zh-CN.json`
|
||||||
- 预留 `en-US.json` 扩展
|
- 预留 `en-US.json` 扩展
|
||||||
|
|
||||||
### U4: 后端镜像优化 [pending]
|
### U4: 后端镜像优化 [done]
|
||||||
- Backend 277MB → 目标 < 150MB(多阶段构建优化,移除 Agent 编译工具链)
|
|
||||||
- 或使用 distroless 基础镜像
|
**问题**: Backend 镜像 282MB 偏大(含 docker-cli 52MB + docker-cli-buildx 28MB + git 20MB + 3 平台 agent 18MB + 未裁剪 kubectl 60MB)
|
||||||
|
|
||||||
|
**已完成 (2026-06-27)**:
|
||||||
|
- ✅ **移除 git/docker-cli/docker-cli-buildx** (节省 ~100MB) — 改为懒加载(首次流水线使用时通过 `apk add --no-cache` 自动安装)
|
||||||
|
- ✅ **PipelineHandler 注入 ToolInstaller** — `runCheckout` 调 `EnsureAvailable("git")`,`runImageBuild` 调 `EnsureAvailable("docker-cli")`
|
||||||
|
- ✅ **UpgradeTools** 函数 — 自动将 DB 中 git/docker-cli 从 `preinstall` 升级为 `lazy`(带 apk install script)
|
||||||
|
- ✅ **仅内置 linux-amd64 agent** (节省 ~12MB) — arm64/darwin 通过下载 API 提供
|
||||||
|
- ✅ **kubectl 改用 install-kubectl.sh 下载** (~47MB stripped vs 60MB 未裁剪) — 同时从 .dockerignore 排除 backend/kubectl 60MB 二进制
|
||||||
|
- ✅ **Dockerfile.embed + backend/Dockerfile 同步更新**
|
||||||
|
|
||||||
|
**验收标准**:
|
||||||
|
- [x] 镜像从 282MB 降至 **107MB**(目标 < 150MB ✅,降幅 62%)
|
||||||
|
- [x] `go build` 零错误
|
||||||
|
- [x] 17/17 集成测试通过
|
||||||
|
- [x] 前端正常服务(embed 模式)
|
||||||
|
- [x] git/docker 确认不在镜像中(`which git` / `which docker` 返回失败)
|
||||||
|
- [x] kubectl 确认在镜像中(`which kubectl` 返回 `/usr/local/bin/kubectl`)
|
||||||
|
- [x] UpgradeTools 日志确认 git/docker-cli preinstall→lazy 升级成功
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -289,7 +306,7 @@ services/api.ts (1324L)
|
|||||||
| U1 | 虚拟滚动 | P3 | **done** |
|
| U1 | 虚拟滚动 | P3 | **done** |
|
||||||
| U2 | 统一 DataTable | P3 | **done** |
|
| U2 | 统一 DataTable | P3 | **done** |
|
||||||
| U3 | 国际化 | P3 | pending |
|
| U3 | 国际化 | P3 | pending |
|
||||||
| U4 | 镜像优化 | P3 | pending |
|
| U4 | 镜像优化 | P3 | **done** |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+50
@@ -672,3 +672,53 @@ python3 tests/integration_test.py --host 127.0.0.1 --port 8080 | tail -3
|
|||||||
- [x] U7: LogDatasourcePage 迁移到 DataTable(含搜索/排序/CRUD)
|
- [x] U7: LogDatasourcePage 迁移到 DataTable(含搜索/排序/CRUD)
|
||||||
- [x] U8: 支持 6+ 核心功能开关(sortable/searchable/pagination/selectable/exportable/columnToggle)
|
- [x] U8: 支持 6+ 核心功能开关(sortable/searchable/pagination/selectable/exportable/columnToggle)
|
||||||
- [x] U9: 17/17 集成回归测试通过
|
- [x] U9: 17/17 集成回归测试通过
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## P3-U4: 后端镜像优化
|
||||||
|
|
||||||
|
### 验证用例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# U1: 镜像大小
|
||||||
|
docker images --format '{{.Repository}}:{{.Tag}} {{.Size}}' | grep aiops
|
||||||
|
# 期望: < 150MB
|
||||||
|
|
||||||
|
# U2: Go 编译
|
||||||
|
cd /srv/aiops/backend && go build ./...
|
||||||
|
# 期望: 零错误
|
||||||
|
|
||||||
|
# U3: git 不在镜像中(懒加载)
|
||||||
|
docker exec aiops which git 2>&1 || echo "git NOT in image"
|
||||||
|
# 期望: git NOT in image
|
||||||
|
|
||||||
|
# U4: docker 不在镜像中(懒加载)
|
||||||
|
docker exec aiops which docker 2>&1 || echo "docker NOT in image"
|
||||||
|
# 期望: docker NOT in image
|
||||||
|
|
||||||
|
# U5: kubectl 在镜像中
|
||||||
|
docker exec aiops which kubectl
|
||||||
|
# 期望: /usr/local/bin/kubectl
|
||||||
|
|
||||||
|
# U6: 仅 linux-amd64 agent
|
||||||
|
docker exec aiops ls /app/agent/bin/
|
||||||
|
# 期望: 只有 aiops-agent-linux-amd64
|
||||||
|
|
||||||
|
# U7: UpgradeTools 日志
|
||||||
|
docker logs aiops 2>&1 | grep 'U4 upgrade'
|
||||||
|
# 期望: git preinstall→lazy, docker-cli preinstall→lazy
|
||||||
|
|
||||||
|
# U8: 集成回归测试
|
||||||
|
python3 tests/integration_test.py --host 127.0.0.1 --port 8080 | tail -3
|
||||||
|
# 期望: 17/17 passed
|
||||||
|
```
|
||||||
|
|
||||||
|
### 通过标准
|
||||||
|
- [x] U1: 镜像从 282MB 降至 **107MB**(< 150MB 目标 ✅)
|
||||||
|
- [x] U2: `go build` 零错误
|
||||||
|
- [x] U3: git 不在镜像中(首次流水线使用时通过 `apk add --no-cache git` 懒加载)
|
||||||
|
- [x] U4: docker 不在镜像中(首次流水线使用时通过 `apk add --no-cache docker-cli` 懒加载)
|
||||||
|
- [x] U5: kubectl 在镜像中(通过 install-kubectl.sh 下载 stripped 版本)
|
||||||
|
- [x] U6: 仅 linux-amd64 agent 二进制(arm64/darwin 通过下载 API)
|
||||||
|
- [x] U7: UpgradeTools 自动升级 git/docker-cli preinstall→lazy
|
||||||
|
- [x] U8: 17/17 集成回归测试通过
|
||||||
+3
-5
@@ -81,10 +81,10 @@ FROM alpine:3.20
|
|||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG KUBECTL_VERSION=v1.32.2
|
ARG KUBECTL_VERSION=v1.32.2
|
||||||
|
|
||||||
# 安装运行时依赖(核心最小集,重型工具改为懒加载)// Logan.Li
|
# 安装运行时依赖(U4 镜像瘦身 — 核心最小集, git/docker-cli 改为懒加载)// Logan.Li
|
||||||
COPY scripts/setup-alpine-mirrors.sh scripts/install-kubectl.sh /tmp/
|
COPY scripts/setup-alpine-mirrors.sh scripts/install-kubectl.sh /tmp/
|
||||||
RUN chmod +x /tmp/setup-alpine-mirrors.sh && /tmp/setup-alpine-mirrors.sh && \
|
RUN chmod +x /tmp/setup-alpine-mirrors.sh && /tmp/setup-alpine-mirrors.sh && \
|
||||||
apk add --no-cache ca-certificates tzdata bash curl git docker-cli docker-cli-buildx && \
|
apk add --no-cache ca-certificates tzdata bash curl && \
|
||||||
chmod +x /tmp/install-kubectl.sh && \
|
chmod +x /tmp/install-kubectl.sh && \
|
||||||
TARGET_OS=linux TARGET_ARCH="${TARGETARCH}" KUBECTL_VERSION="${KUBECTL_VERSION}" \
|
TARGET_OS=linux TARGET_ARCH="${TARGETARCH}" KUBECTL_VERSION="${KUBECTL_VERSION}" \
|
||||||
/tmp/install-kubectl.sh /usr/local/bin/kubectl && \
|
/tmp/install-kubectl.sh /usr/local/bin/kubectl && \
|
||||||
@@ -106,10 +106,8 @@ COPY --from=builder /app/aiops .
|
|||||||
# 创建运行时目录(agent 二进制 + 安装脚本)
|
# 创建运行时目录(agent 二进制 + 安装脚本)
|
||||||
RUN mkdir -p /app/agent/bin /app/agent/deploy
|
RUN mkdir -p /app/agent/bin /app/agent/deploy
|
||||||
|
|
||||||
# 复制 agent 二进制(三个平台)
|
# 复制 agent 二进制(U4: 仅 linux-amd64 内置, arm64/darwin 通过下载 API 提供)// Logan.Li
|
||||||
COPY --from=agent-builder /agent/bin/aiops-agent-linux-amd64 /app/agent/bin/
|
COPY --from=agent-builder /agent/bin/aiops-agent-linux-amd64 /app/agent/bin/
|
||||||
COPY --from=agent-builder /agent/bin/aiops-agent-linux-arm64 /app/agent/bin/
|
|
||||||
COPY --from=agent-builder /agent/bin/aiops-agent-darwin-arm64 /app/agent/bin/
|
|
||||||
|
|
||||||
# 复制 agent 安装脚本和 systemd service 模板
|
# 复制 agent 安装脚本和 systemd service 模板
|
||||||
COPY agent/deploy/install.sh /app/agent/deploy/
|
COPY agent/deploy/install.sh /app/agent/deploy/
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"ezops/model"
|
"ezops/model"
|
||||||
"ezops/middleware"
|
"ezops/middleware"
|
||||||
ezredis "ezops/pkg/redis"
|
ezredis "ezops/pkg/redis"
|
||||||
|
"ezops/pkg/toolinstaller"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -55,11 +56,12 @@ func validateCode(db *gorm.DB, code string, excludeID uint) string {
|
|||||||
type PipelineHandler struct {
|
type PipelineHandler struct {
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
cache ezredis.Cache
|
cache ezredis.Cache
|
||||||
|
toolInstaller *toolinstaller.ToolInstaller
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPipelineHandler 创建流水线处理器
|
// NewPipelineHandler 创建流水线处理器
|
||||||
func NewPipelineHandler(db *gorm.DB, cache ezredis.Cache) *PipelineHandler {
|
func NewPipelineHandler(db *gorm.DB, cache ezredis.Cache, ti *toolinstaller.ToolInstaller) *PipelineHandler {
|
||||||
return &PipelineHandler{db: db, cache: cache}
|
return &PipelineHandler{db: db, cache: cache, toolInstaller: ti}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PipelineListItem 列表项(含最近一次运行摘要)// Logan.Li
|
// PipelineListItem 列表项(含最近一次运行摘要)// Logan.Li
|
||||||
|
|||||||
@@ -222,6 +222,13 @@ func (h *PipelineHandler) runCheckout(url, branch, workspace string, logFn func(
|
|||||||
}
|
}
|
||||||
logFn("info", "代码检出", "> Git 拉取 "+url+" (分支: "+branch+")")
|
logFn("info", "代码检出", "> Git 拉取 "+url+" (分支: "+branch+")")
|
||||||
|
|
||||||
|
// U4: 确保工具可用(slim 镜像模式下 git 为懒加载)// Logan.Li
|
||||||
|
if h.toolInstaller != nil {
|
||||||
|
if err := h.toolInstaller.EnsureAvailable("git"); err != nil {
|
||||||
|
return fmt.Errorf("git 不可用(安装失败): %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cmd := exec.Command("git", "clone", "--depth", "1", "-b", branch, url, workspace)
|
cmd := exec.Command("git", "clone", "--depth", "1", "-b", branch, url, workspace)
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
// 流式输出到日志
|
// 流式输出到日志
|
||||||
@@ -429,6 +436,14 @@ func (h *PipelineHandler) runDockerBuild(workspace string, pipeline model.Pipeli
|
|||||||
}
|
}
|
||||||
|
|
||||||
logFn("info", "镜像打包", fmt.Sprintf(">>> Docker 构建 (dockerfile: %s)", dfPath))
|
logFn("info", "镜像打包", fmt.Sprintf(">>> Docker 构建 (dockerfile: %s)", dfPath))
|
||||||
|
|
||||||
|
// U4: 确保 Docker CLI 可用(slim 镜像模式下 docker-cli 为懒加载)// Logan.Li
|
||||||
|
if h.toolInstaller != nil {
|
||||||
|
if err := h.toolInstaller.EnsureAvailable("docker-cli"); err != nil {
|
||||||
|
return fmt.Errorf("docker 不可用(安装失败): %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cmd := exec.Command("docker", "build", "-t", fullImage, "-f", dfPath, ".")
|
cmd := exec.Command("docker", "build", "-t", fullImage, "-f", dfPath, ".")
|
||||||
cmd.Dir = buildDir
|
cmd.Dir = buildDir
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
|
|||||||
@@ -191,28 +191,30 @@ echo "[Node.js] Installed: $(node --version) / npm $(npm --version)"
|
|||||||
`,
|
`,
|
||||||
SortOrder: 4,
|
SortOrder: 4,
|
||||||
},
|
},
|
||||||
// ──── Git — 版本控制(预装)// Logan.Li ────
|
// ──── Git — 版本控制(懒加载, U4 镜像瘦身)// Logan.Li ────
|
||||||
{
|
{
|
||||||
Name: "git",
|
Name: "git",
|
||||||
DisplayName: "Git",
|
DisplayName: "Git",
|
||||||
Description: "版本控制工具,流水线代码拉取使用",
|
Description: "版本控制工具,流水线代码拉取使用(首次使用自动安装)",
|
||||||
Category: "build",
|
Category: "build",
|
||||||
InstallMethod: ToolPreinstall,
|
InstallMethod: ToolLazy,
|
||||||
BinaryName: "git",
|
BinaryName: "git",
|
||||||
InstallPath: "/usr/bin/git",
|
InstallPath: "/usr/bin/git",
|
||||||
CheckCommand: "git --version 2>/dev/null",
|
CheckCommand: "git --version 2>/dev/null",
|
||||||
|
InstallScript: `apk add --no-cache git`,
|
||||||
SortOrder: 5,
|
SortOrder: 5,
|
||||||
},
|
},
|
||||||
// ──── Docker CLI — 容器构建(预装)// Logan.Li ────
|
// ──── Docker CLI — 容器构建(懒加载, U4 镜像瘦身)// Logan.Li ────
|
||||||
{
|
{
|
||||||
Name: "docker-cli",
|
Name: "docker-cli",
|
||||||
DisplayName: "Docker CLI",
|
DisplayName: "Docker CLI",
|
||||||
Description: "Docker 命令行工具,流水线镜像构建/推送使用",
|
Description: "Docker 命令行工具,流水线镜像构建/推送使用(首次使用自动安装)",
|
||||||
Category: "deploy",
|
Category: "deploy",
|
||||||
InstallMethod: ToolPreinstall,
|
InstallMethod: ToolLazy,
|
||||||
BinaryName: "docker",
|
BinaryName: "docker",
|
||||||
InstallPath: "/usr/bin/docker",
|
InstallPath: "/usr/bin/docker",
|
||||||
CheckCommand: "docker --version 2>/dev/null",
|
CheckCommand: "docker --version 2>/dev/null",
|
||||||
|
InstallScript: `apk add --no-cache docker-cli`,
|
||||||
SortOrder: 6,
|
SortOrder: 6,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -327,6 +327,8 @@ func (ti *ToolInstaller) SeedTools() {
|
|||||||
var count int64
|
var count int64
|
||||||
ti.db.Model(&model.DeployTool{}).Count(&count)
|
ti.db.Model(&model.DeployTool{}).Count(&count)
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
|
// U4: 即使已有数据也升级工具配置(git/docker-cli 从 preinstall→lazy)
|
||||||
|
ti.UpgradeTools()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,4 +353,44 @@ func (ti *ToolInstaller) SeedTools() {
|
|||||||
} else {
|
} else {
|
||||||
log.Printf("[ToolInstaller] Seeded %d tools", len(tools))
|
log.Printf("[ToolInstaller] Seeded %d tools", len(tools))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// U4: 新种子也执行升级
|
||||||
|
ti.UpgradeTools()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpgradeTools updates existing tool configs to match latest predefined definitions.
|
||||||
|
// U4: git/docker-cli 从 preinstall 迁移到 lazy(镜像瘦身)。
|
||||||
|
func (ti *ToolInstaller) UpgradeTools() {
|
||||||
|
upgrades := map[string]struct {
|
||||||
|
installMethod model.ToolInstallMethod
|
||||||
|
installScript string
|
||||||
|
description string
|
||||||
|
}{
|
||||||
|
"git": {
|
||||||
|
installMethod: model.ToolLazy,
|
||||||
|
installScript: "apk add --no-cache git",
|
||||||
|
description: "版本控制工具,流水线代码拉取使用(首次使用自动安装)",
|
||||||
|
},
|
||||||
|
"docker-cli": {
|
||||||
|
installMethod: model.ToolLazy,
|
||||||
|
installScript: "apk add --no-cache docker-cli",
|
||||||
|
description: "Docker 命令行工具,流水线镜像构建/推送使用(首次使用自动安装)",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, up := range upgrades {
|
||||||
|
var tool model.DeployTool
|
||||||
|
if err := ti.db.Where("name = ?", name).First(&tool).Error; err != nil {
|
||||||
|
continue // tool not in DB, skip
|
||||||
|
}
|
||||||
|
if tool.InstallMethod == up.installMethod && tool.InstallScript == up.installScript {
|
||||||
|
continue // already up to date
|
||||||
|
}
|
||||||
|
log.Printf("[ToolInstaller] U4 upgrade: %s %s→%s", name, tool.InstallMethod, up.installMethod)
|
||||||
|
ti.db.Model(&model.DeployTool{}).Where("name = ?", name).Updates(map[string]interface{}{
|
||||||
|
"install_method": up.installMethod,
|
||||||
|
"install_script": up.installScript,
|
||||||
|
"description": up.description,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ func Register(r *gin.Engine, db *gorm.DB, log *zap.Logger, cfg *config.Config, c
|
|||||||
api.POST("/auth/register", authHandler.Register)
|
api.POST("/auth/register", authHandler.Register)
|
||||||
|
|
||||||
// Webhook 触发路由(无需 JWT,由 Webhook Token 签名验证)
|
// Webhook 触发路由(无需 JWT,由 Webhook Token 签名验证)
|
||||||
pipelineHandler := controller.NewPipelineHandler(db, redisCache)
|
pipelineHandler := controller.NewPipelineHandler(db, redisCache, ti)
|
||||||
webhookGroup := api.Group("/webhook")
|
webhookGroup := api.Group("/webhook")
|
||||||
{
|
{
|
||||||
webhookGroup.POST("/job/:jobName", pipelineHandler.WebhookTrigger)
|
webhookGroup.POST("/job/:jobName", pipelineHandler.WebhookTrigger)
|
||||||
|
|||||||
Reference in new issue
Block a user