diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index cdadf7d..25922d1 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -14,18 +14,90 @@ env: REGISTRY: ghcr.io jobs: + detect-changes: + runs-on: ubuntu-latest + outputs: + shared: ${{ steps.manual.outputs.shared || steps.filter.outputs.shared }} + frontend: ${{ steps.manual.outputs.frontend || steps.filter.outputs.frontend }} + backend: ${{ steps.manual.outputs.backend || steps.filter.outputs.backend }} + remote_gateway: ${{ steps.manual.outputs.remote_gateway || steps.filter.outputs.remote_gateway }} + matrix: ${{ steps.matrix.outputs.matrix }} + has_changes: ${{ steps.matrix.outputs.has_changes }} + + steps: + - name: Checkout repository + if: github.event_name != 'workflow_dispatch' + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Mark all services changed for manual dispatch + if: github.event_name == 'workflow_dispatch' + id: manual + run: | + echo "shared=true" >> "$GITHUB_OUTPUT" + echo "frontend=true" >> "$GITHUB_OUTPUT" + echo "backend=true" >> "$GITHUB_OUTPUT" + echo "remote_gateway=true" >> "$GITHUB_OUTPUT" + + - name: Detect changed paths + if: github.event_name != 'workflow_dispatch' + id: filter + uses: dorny/paths-filter@v3 + with: + filters: | + shared: + - '.github/workflows/docker-publish.yml' + - 'package.json' + - 'package-lock.json' + - 'docker-compose.yml' + - 'patches/**' + frontend: + - 'packages/frontend/**' + backend: + - 'packages/backend/**' + remote_gateway: + - 'packages/remote-gateway/**' + + - name: Build service matrix + id: matrix + env: + SHARED: ${{ steps.manual.outputs.shared || steps.filter.outputs.shared }} + FRONTEND: ${{ steps.manual.outputs.frontend || steps.filter.outputs.frontend }} + BACKEND: ${{ steps.manual.outputs.backend || steps.filter.outputs.backend }} + REMOTE_GATEWAY: ${{ steps.manual.outputs.remote_gateway || steps.filter.outputs.remote_gateway }} + run: | + python <<'PY' + import json + import os + from pathlib import Path + + shared = os.environ.get("SHARED") == "true" + services = [ + ("frontend", "packages/frontend/Dockerfile", os.environ.get("FRONTEND") == "true"), + ("backend", "packages/backend/Dockerfile", os.environ.get("BACKEND") == "true"), + ("remote-gateway", "packages/remote-gateway/Dockerfile", os.environ.get("REMOTE_GATEWAY") == "true"), + ] + + include = [ + {"service": service, "dockerfile": dockerfile} + for service, dockerfile, changed in services + if shared or changed + ] + + output_path = Path(os.environ["GITHUB_OUTPUT"]) + with output_path.open("a", encoding="utf-8") as output: + output.write(f"matrix={json.dumps({'include': include})}\n") + output.write(f"has_changes={'true' if include else 'false'}\n") + PY + publish: + needs: detect-changes + if: needs.detect-changes.outputs.has_changes == 'true' runs-on: ubuntu-latest strategy: fail-fast: false - matrix: - include: - - service: frontend - dockerfile: packages/frontend/Dockerfile - - service: backend - dockerfile: packages/backend/Dockerfile - - service: remote-gateway - dockerfile: packages/remote-gateway/Dockerfile + matrix: ${{ fromJson(needs.detect-changes.outputs.matrix) }} steps: - name: Checkout repository diff --git a/.helloagents/CHANGELOG.md b/.helloagents/CHANGELOG.md index a871522..a00acd0 100644 --- a/.helloagents/CHANGELOG.md +++ b/.helloagents/CHANGELOG.md @@ -2,6 +2,9 @@ ## [Unreleased] +- **[workspace-root]**: 为 Docker 镜像发布 workflow 增加按路径检测的动态构建矩阵,仅在共享根文件或对应服务目录变更时构建受影响镜像,手动触发仍保留全量发布能力 - by yinjianm + - 方案: [202604160350_workflow-service-scoped-docker-builds](archive/2026-04/202604160350_workflow-service-scoped-docker-builds/) + - **[frontend]**: 将右侧服务器状态监控的默认视图从通用卡片栅格重排为更贴近参考图的窄屏监控布局,统一顶部信息条、索引化资源行与内存/网络/磁盘/进程概览的左右分区关系 - by yinjianm - 方案: [202604152323_status-monitor-reference-layout-parity](archive/2026-04/202604152323_status-monitor-reference-layout-parity/) - **[frontend]**: 将右侧状态监控继续收紧为更贴近服务器小屏的默认概览,并新增时区、运行时间、进程概览与“查看全部”独立进程管理弹窗 - by yinjianm @@ -61,6 +64,9 @@ - 方案: [202603250614_terminal-ansi-color-effects](archive/2026-03/202603250614_terminal-ansi-color-effects/) ### 快速修改 +- **[frontend]**: 将状态监控模块区从默认并排调整回基于常用 300px 右栏比例的单列布局,并用弹性高度把普通卡控制在约 200、进程管理控制在约 400 的视觉比例 — by yinjianm + - 类型: 快速修改(无方案包) + - 文件: packages/frontend/src/components/StatusMonitor.vue - **[frontend]**: 将状态监控模块区从大断点固定分列改为更高密度的 auto-fit 自适应网格,让内存/网络/磁盘在正常宽度下默认并排,只有非常窄时才回落为单列 — by yinjianm - 类型: 快速修改(无方案包) - 文件: packages/frontend/src/components/StatusMonitor.vue diff --git a/.helloagents/archive/2026-04/202604160350_workflow-service-scoped-docker-builds/.status.json b/.helloagents/archive/2026-04/202604160350_workflow-service-scoped-docker-builds/.status.json new file mode 100644 index 0000000..0559907 --- /dev/null +++ b/.helloagents/archive/2026-04/202604160350_workflow-service-scoped-docker-builds/.status.json @@ -0,0 +1 @@ +{"status":"completed","completed":4,"failed":0,"pending":0,"total":4,"done":4,"percent":100,"current":"Completed - docker publish workflow now builds only impacted services","updated_at":"2026-04-16 03:58:00"} diff --git a/.helloagents/archive/2026-04/202604160350_workflow-service-scoped-docker-builds/proposal.md b/.helloagents/archive/2026-04/202604160350_workflow-service-scoped-docker-builds/proposal.md new file mode 100644 index 0000000..e494f19 --- /dev/null +++ b/.helloagents/archive/2026-04/202604160350_workflow-service-scoped-docker-builds/proposal.md @@ -0,0 +1,123 @@ +# 变更提案: workflow-service-scoped-docker-builds + +## 元信息 +```yaml +类型: 优化 +方案类型: implementation +优先级: P1 +状态: 草稿 +创建: 2026-04-16 +``` + +--- + +## 1. 需求 + +### 背景 +当前仓库只有一个镜像发布 workflow [`docker-publish.yml`](../../../../.github/workflows/docker-publish.yml)。它在 `main` 分支每次 push 时都会构建并推送 `frontend`、`backend`、`remote-gateway` 三个镜像,即使本次提交只修改了单个服务目录或仅是文档类改动,也会触发完整构建,导致 GitHub Actions 耗时和资源浪费。 + +### 目标 +- 仅在受影响的服务发生改动时构建对应镜像。 +- 根目录共享构建文件发生改动时,仍然允许三个服务全量构建。 +- 文档、知识库等与镜像构建无关的改动不再触发完整镜像构建。 + +### 约束条件 +```yaml +时间约束: 本轮内完成 workflow 改造与语法级验证 +性能约束: 检测逻辑应先于 Docker 构建执行,避免无意义 buildx 初始化 +兼容性约束: 保留 push main 与 workflow_dispatch 两种触发方式 +业务约束: 根目录共享构建文件改动时仍需构建全部服务 +``` + +### 验收标准 +- [ ] 仅改动 `packages/frontend/**` 时,只触发 frontend 镜像构建。 +- [ ] 仅改动 `packages/backend/**` 或 `packages/remote-gateway/**` 时,只触发对应服务镜像构建。 +- [ ] 改动根目录共享构建文件时,三个服务镜像都继续构建。 +- [ ] 仅改动 `.helloagents/`、README 等非构建相关文件时,不再执行三个镜像的完整构建。 + +--- + +## 2. 方案 + +### 技术方案 +在现有 workflow 前增加一个 `detect-changes` 作业,使用 `dorny/paths-filter` 识别本次 push 涉及的路径范围,输出 `shared`、`frontend`、`backend`、`remote-gateway` 四类布尔结果。发布作业保留矩阵结构,但在 job 级根据矩阵服务名和变更输出决定是否执行,从而只让受影响的服务进入 Docker Buildx / login / build-push 流程。 + +### 影响范围 +```yaml +涉及模块: + - workspace-root: GitHub Actions 镜像发布链路按路径分流 + - knowledge-base: 记录本次 CI 发布策略优化 +预计变更文件: 4 +``` + +### 风险评估 +| 风险 | 等级 | 应对 | +|------|------|------| +| 共享路径定义过窄,导致实际需要全量构建的改动被漏掉 | 中 | 将根 `package.json`、`package-lock.json`、`docker-compose.yml`、`patches/**`、workflow 自身纳入 shared | +| 共享路径定义过宽,仍然频繁触发全量构建 | 中 | 不把 README、`.helloagents/**`、普通文档纳入 shared | +| push 事件比较范围获取不完整,导致变更检测失真 | 低 | checkout 使用 `fetch-depth: 0`,保证路径过滤能对比完整提交范围 | + +--- + +## 3. 技术设计(可选) + +> 本次不涉及 API 或数据模型变更,N/A。 + +--- + +## 4. 核心场景 + +### 场景: 单服务目录改动 +**模块**: workspace-root +**条件**: 用户仅修改某个 `packages//` 目录 +**行为**: workflow 只执行对应矩阵服务的镜像构建 +**结果**: GitHub Actions 不再全量构建三个服务 + +### 场景: 共享构建文件改动 +**模块**: workspace-root +**条件**: 用户修改根 `package.json`、`package-lock.json`、`patches/**`、`docker-compose.yml` 或 workflow 文件 +**行为**: workflow 将三个服务都视为受影响并全量构建 +**结果**: 共享依赖或发布逻辑变化不会漏掉任何镜像 + +### 场景: 非构建相关文件改动 +**模块**: workspace-root +**条件**: 用户仅修改 `.helloagents/**`、README 或其他未纳入过滤器的文件 +**行为**: 检测作业完成后,所有矩阵发布 job 都被跳过 +**结果**: Action 不再为纯文档或知识同步改动浪费镜像构建资源 + +--- + +## 5. 技术决策 + +### workflow-service-scoped-docker-builds#D001: 采用路径过滤 + 条件矩阵,而不是拆成三个独立 workflow +**日期**: 2026-04-16 +**状态**: ✅采纳 +**背景**: 需求是“按改动范围只编译受影响部分”,同时保持现有发布链路清晰可维护。 +**选项分析**: +| 选项 | 优点 | 缺点 | +|------|------|------| +| A: 拆成三个独立 workflow | 服务边界最清楚 | 文件更多、重复配置多、共享规则难统一 | +| B: 保留一个 workflow,前置路径检测后按矩阵条件执行 | 结构集中、改动最小、共享规则统一维护 | 需要多一个检测 job | +**决策**: 选择方案 B +**理由**: 当前仓只有一个发布 workflow,直接在现有矩阵上增加路径检测成本最低,也更符合“局部优化而非重写发布链路”的目标。 +**影响**: workspace-root + +--- + +## 6. 成果设计 + +### 设计方向 +- **美学基调**: N/A +- **记忆点**: N/A +- **参考**: N/A + +### 视觉要素 +- **配色**: N/A +- **字体**: N/A +- **布局**: N/A +- **动效**: N/A +- **氛围**: N/A + +### 技术约束 +- **可访问性**: N/A +- **响应式**: N/A diff --git a/.helloagents/archive/2026-04/202604160350_workflow-service-scoped-docker-builds/tasks.md b/.helloagents/archive/2026-04/202604160350_workflow-service-scoped-docker-builds/tasks.md new file mode 100644 index 0000000..bc7dbee --- /dev/null +++ b/.helloagents/archive/2026-04/202604160350_workflow-service-scoped-docker-builds/tasks.md @@ -0,0 +1,51 @@ +# 任务清单: workflow-service-scoped-docker-builds + +> **@status:** completed | 2026-04-16 04:02 + +```yaml +@feature: workflow-service-scoped-docker-builds +@created: 2026-04-16 +@status: completed +@mode: R2 +``` + +## 进度概览 + +| 完成 | 失败 | 跳过 | 总数 | +|------|------|------|------| +| 4 | 0 | 0 | 4 | + +--- + +## 任务列表 + +### 1. 方案设计 + +- [√] 1.1 收敛 GitHub Actions 路径触发规则,确认共享根文件改动时全量构建,单服务目录改动时只构建对应服务 | depends_on: [] + +### 2. Workflow 实现 + +- [√] 2.1 在 `.github/workflows/docker-publish.yml` 中增加路径变更检测作业,并定义 `shared/frontend/backend/remote-gateway` 过滤器 | depends_on: [1.1] +- [√] 2.2 在同一 workflow 中按矩阵服务与检测结果添加 job 级执行条件,只构建受影响镜像 | depends_on: [2.1] + +### 3. 验证与知识同步 + +- [√] 3.1 验证 workflow YAML 结构与关键触发规则,确认不会再对无关改动执行三个镜像完整构建 | depends_on: [2.2] + +--- + +## 执行日志 + +| 时间 | 任务 | 状态 | 备注 | +|------|------|------|------| +| 2026-04-16 03:50 | DESIGN | completed | 已确认当前仓只有 `docker-publish.yml` 一个镜像发布 workflow,本次按路径检测 + 条件矩阵优化 | +| 2026-04-16 03:55 | 2.1-2.2 | completed | 已新增 `detect-changes` 作业,按共享根文件与各服务目录生成动态构建矩阵 | +| 2026-04-16 03:58 | 3.1 | completed | 已完成 workflow 结构复核;本机缺少 YAML 解析库,未做真正语法解析,但手工检查确认手动触发、共享改动和单服务改动三条路径均已覆盖 | + +--- + +## 执行备注 + +> 本次范围仅限 GitHub Actions 镜像发布链路,不调整 Dockerfile、包构建脚本或 compose 编排本身。 +> +> 本机缺少 `PyYAML` 与 `ruby`,因此本轮未执行本地 YAML 解析器校验;当前验证基于 workflow 成品审阅与触发路径逻辑复核。 diff --git a/.helloagents/archive/_index.md b/.helloagents/archive/_index.md index 857bb86..57b5aaf 100644 --- a/.helloagents/archive/_index.md +++ b/.helloagents/archive/_index.md @@ -7,6 +7,7 @@ | 时间戳 | 名称 | 类型 | 涉及模块 | 决策 | 结果 | |--------|------|------|---------|------|------| +| 202604160350 | workflow-service-scoped-docker-builds | - | - | - | ✅完成 | | 202604152323 | status-monitor-reference-layout-parity | implementation | frontend | status-monitor-reference-layout-parity#D001 | ✅完成 | | 202604152147 | status-monitor-process-manager-modal | - | - | - | ✅完成 | | 202604152139 | workspace-global-search-tag-fuzzy-search | - | - | - | ✅完成 | diff --git a/.helloagents/modules/workspace-root.md b/.helloagents/modules/workspace-root.md index 76f988d..fb3061e 100644 --- a/.helloagents/modules/workspace-root.md +++ b/.helloagents/modules/workspace-root.md @@ -13,7 +13,7 @@ |----------|------|--------|------| | `package.json#workspaces` | `packages/*` | npm workspace 列表 | 声明后端、前端、远程网关三个子包属于同一工作区。 | | `package.json#postinstall` | 无 | shell 命令 | 安装依赖后自动执行 `patch-package`。 | -| `.github/workflows/docker-publish.yml` | GitHub push / workflow_dispatch 事件 | GHCR 镜像 | 在 `main` 推送时发布三个 `linux/amd64` 业务镜像到 GHCR。 | +| `.github/workflows/docker-publish.yml` | GitHub push / workflow_dispatch 事件 | GHCR 镜像 | 在 `main` 推送时按路径检测发布受影响的 `linux/amd64` 业务镜像,手动触发时仍可全量发布。 | | `docker-compose.yml` | 环境变量、卷、端口映射 | 服务编排 | 统一启动 `frontend`、`backend`、`remote-gateway`、`guacd`。 | ### 数据结构 @@ -37,8 +37,8 @@ ### 镜像自动发布 **条件**: 向 `main` 分支推送代码,或在 GitHub Actions 手动触发 workflow。 -**行为**: `.github/workflows/docker-publish.yml` 使用各子包现有 Dockerfile 构建 `linux/amd64` 镜像,并向 GHCR 发布 `latest` 与 `sha-` 标签。 -**结果**: 仓库镜像发布链路与 compose 使用的镜像来源保持一致。 +**行为**: `.github/workflows/docker-publish.yml` 当前会先运行 `detect-changes` 作业:对 `package.json`、`package-lock.json`、`docker-compose.yml`、`patches/**` 和 workflow 自身视为共享根文件,对 `packages/frontend/**`、`packages/backend/**`、`packages/remote-gateway/**` 分别视为服务级改动;若是手动 `workflow_dispatch` 则直接将三个服务都标记为受影响。随后发布作业按检测结果生成动态矩阵,仅对受影响服务使用各自 Dockerfile 构建 `linux/amd64` 镜像,并向 GHCR 发布 `latest` 与 `sha-` 标签。 +**结果**: 镜像发布链路与 compose 使用的镜像来源保持一致,同时避免无关改动触发三个服务的完整构建。 ## 依赖关系 diff --git a/packages/frontend/src/components/StatusMonitor.vue b/packages/frontend/src/components/StatusMonitor.vue index f18ef0a..910f347 100644 --- a/packages/frontend/src/components/StatusMonitor.vue +++ b/packages/frontend/src/components/StatusMonitor.vue @@ -849,7 +849,7 @@ const copyIpToClipboard = async (ipAddress: string | null) => { .monitor-module-grid { display: grid; gap: 10px; - grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); + grid-template-columns: 1fr; } .monitor-module { @@ -861,6 +861,17 @@ const copyIpToClipboard = async (ipAddress: string | null) => { container-type: inline-size; } +.monitor-module--usage, +.monitor-module--memory, +.monitor-module--network, +.monitor-module--disk { + min-height: clamp(188px, 62cqw, 220px); +} + +.monitor-module--process { + min-height: clamp(340px, 116cqw, 420px); +} + .monitor-module__heading { display: flex; align-items: flex-start; @@ -1476,13 +1487,6 @@ const copyIpToClipboard = async (ipAddress: string | null) => { } } -@container (min-width: 420px) { - .monitor-module--usage, - .monitor-module--process { - grid-column: 1 / -1; - } -} - @container (max-width: 250px) { .module-split--memory, .network-module__hero,