Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/bug-server-pr-bundle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ permissions:

jobs:
build-pr-bundle:
if: github.event.pull_request.head.repo.full_name != github.repository
runs-on: macos-latest
timeout-minutes: 30
steps:
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/bug-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
workflow_dispatch:
inputs:
pr_number:
description: '待验证的 PR 编号(支持外部 fork PR)'
description: '待验证的外部 fork PR 编号'
required: true
type: string
head_sha:
Expand All @@ -22,9 +22,10 @@ permissions:

jobs:
build:
if: github.event_name != 'workflow_dispatch'
if: >-
github.event_name == 'push' ||
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
runs-on: macos-latest

strategy:
matrix:
node-version: [18.x]
Expand Down
17 changes: 16 additions & 1 deletion docs/superpowers/plans/2026-09-17-bug-server-dispatch.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@
- [x] 从最终 workflow 提取下载、ZIP 读取、提交命令,在隔离目录模拟 artifact 到客户端的完整数据流,确认产物仅作为字节上传。
- [x] 检查格式及最终 diff,记录本地验证和线上未验证项。

## 验证结果
## 任务 4:按 PR 来源分流

文件:`.github/workflows/bug-server.yml`、`.github/workflows/bug-server-pr-bundle.yml`、`tools/bugserver-trigger/README.md`。

- [x] 将 CI 的 `build.if` 改为 `github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)`,保留两个手动 job 的条件。
- [x] 为 `build-pr-bundle` 添加 `if: github.event.pull_request.head.repo.full_name != github.repository`。
- [x] 中文说明明确仓库内 PR 自动测试、fork PR 构建后手动测试、另一构建 job 显示 skipped,以及仓库内 PR 应重跑 CI。
- [x] 从 YAML 读取实际条件,验证仓库内 PR、fork PR、`main` push、手动触发的执行矩阵;使用 actionlint 校验两个 workflow,运行现有 Node/Python 测试和 `git diff --check`。

## 原手动入口验证结果

- Node 来源校验测试 36 项、Python ZIP 测试 6 项全部通过。
- 本地 macOS / Node.js 24.19.0 使用现有依赖完成四步构建,生成约 5.1 MB 的 bundle,`node --check` 通过。CI 构建沿用 Node.js 18;本地未重新安装全部 Rush 依赖。构建保留已有 sourcemap、ES module this 和循环依赖告警。
Expand All @@ -51,3 +60,9 @@
- 读取所得的抛错 JavaScript bundle 交给隔离客户端 mock,成功、图片失败、SCM 失败、token 缺失四种场景通过;PR 元数据与 API 顺序保持正确,bundle 未执行。
- resolver 和 ZIP 读取器与 VRender 最新实现相同;仅 workflow 的 runner、构建步骤、依赖版本、超时及中文说明保留 VChart 适配。
- 本次未推送或运行 VChart 线上 Actions/CodeQL,也未调用真实 Bug Server。VRender 的线上验证记录不能替代 VChart 自身的线上验收。

## PR 来源分流验证结果

- 仓库内 PR、外部 fork PR、同组织不同仓库 PR、`main` push、手动触发共 5 种场景的实际条件求值通过;每个 PR 只执行一个构建 job,手动提交仍依赖校验 job。
- actionlint 1.7.12、现有 Node 测试 36 项、Python 测试 6 项和 `git diff --check` 通过。
- 构建步骤及提交脚本未变,本次未重跑完整构建,未触发线上 Actions 或 Bug Server。
12 changes: 10 additions & 2 deletions docs/superpowers/specs/2026-09-17-bug-server-dispatch-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,21 @@

## 数据流

1. `bug-server-pr-bundle.yml` 仅由 `pull_request` 触发,检出准确 head SHA,沿用 VChart 的 macOS、Node.js 18 和 Rush 构建顺序。关闭持久 checkout 凭据、不传入 Bug Server token,缓存写入属于 PR 作用域。上传 `bug-server-pr-<编号>-<SHA>`,保留 7 天。
1. `bug-server-pr-bundle.yml` 仅在来自外部 fork 的 `pull_request` 中执行构建,检出准确 head SHA,沿用 VChart 的 macOS、Node.js 18 和 Rush 构建顺序。关闭持久 checkout 凭据、不传入 Bug Server token,缓存写入属于 PR 作用域。上传 `bug-server-pr-<编号>-<SHA>`,保留 7 天。
2. 仅从仓库默认分支运行 `workflow_dispatch`,从固定的 `github.workflow_sha` 加载校验脚本。校验 PR 编号、40 位十六进制 SHA、PR 所属仓库和当前 head。
3. 通过 workflow ID/路径、PR 事件、成功状态、base/head 仓库 ID、源分支及 run SHA 绑定来源构建。fork 的运行记录可能没有 PR 列表;如列表存在则必须包含目标 PR。
4. 选择最新匹配运行中唯一、未过期的命名产物,复核 artifact API 的 run ID、仓库 ID、SHA。不回退到较旧运行;失败时要求先成功运行 PR bundle workflow。
5. 提交 runner 从 workflow SHA 加载可信脚本,按 artifact ID 下载 ZIP,只接受一个普通 `index.js` 文件,最大 64 MiB。只读取文件字节到固定目标,禁止路径解压、覆盖已有文件或执行产物。
6. 固定版本客户端依赖独立安装且禁用 lifecycle scripts。仅触发 API 的 step 接收 `BUG_SERVER_TOKEN`,传入被测 SHA、PR ref、源分支,保留图片测试和性能测试行为。
7. 两个 workflow 默认 `contents: read`;查询/下载 job 需要 `actions: read`,目标校验另需 `pull-requests: read`。summary 记录 PR、SHA 和来源构建,日志保留用例结果。既有 push / pull_request 自动构建与测试行为保留。
7. 两个 workflow 默认 `contents: read`;查询/下载 job 需要 `actions: read`,目标校验另需 `pull-requests: read`。summary 记录 PR、SHA 和来源构建,日志保留用例结果。`main` push 和仓库内 PR 继续自动构建与测试。

## 按 PR 来源分流

PR 目标分支仍为 `main`、`develop`、`dev/**`。比较 `github.event.pull_request.head.repo.full_name` 与 `github.repository`:相等时只执行 **Bug Server CI** 的 `build` job,不相等时只执行 **Bug Server PR Bundle** 的 `build-pr-bundle` job。每个 PR 事件只实际构建一次。

GitHub 的 PR 事件过滤器不能按来源仓库过滤,因此使用 job 级 `if`;另一个 workflow 仍可生成运行记录,但其构建 job 会跳过,不分配 runner。`main` push 继续执行 CI 构建,`workflow_dispatch` 仅执行既有校验和提交 job。仓库内 PR 重跑 CI 即可;fork PR 先构建 bundle,再由维护者手动提交测试。

验证覆盖仓库内 PR、fork PR、`main` push 和手动触发四种事件,检查构建互斥及手动 job 的条件;运行 actionlint 和现有来源、ZIP 校验测试。构建命令不变,无需重复完整构建。

## 维护者操作

Expand Down
20 changes: 17 additions & 3 deletions tools/bugserver-trigger/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,25 @@

`scripts/trigger-test.ts` 上传 `dist/index.js`,等待 SCM 构建,运行并等待图片测试,然后触发性能测试。调用接口需要仓库 secret `BUG_SERVER_TOKEN`。

## 自动执行规则

目标分支为 `main`、`develop`、`dev/**` 的 PR,按来源仓库分流,每个 PR 事件只实际构建一次:

| 事件 | Bug Server CI | Bug Server PR Bundle |
| -------------- | ------------------ | -------------------------------------- |
| 仓库内 PR | 构建并提交测试 | 跳过构建 |
| 外部 fork PR | 跳过自动构建与测试 | 构建并保存产物,等待维护者手动提交测试 |
| push 到 `main` | 构建并提交测试 | 不触发 |

来源判断使用 PR head 仓库的完整名称与当前仓库名称比较。GitHub 的 `pull_request` 触发器不能按来源仓库过滤,因此在 job 级设置互斥条件;两个 workflow 仍可能出现运行记录,但另一构建 job 显示 `skipped`,不会启动 runner。

仓库内 PR 如需重新验证,重跑 **Bug Server CI**。下面的手动入口用于外部 fork PR,依赖 **Bug Server PR Bundle** 产物;仓库内 PR 不再生成该产物。

## 手动验证外部 PR

两个 workflow 合入仓库默认分支 `develop` 后,先等待该 PR head 的 **Bug Server PR Bundle** 构建成功。外部 fork 的运行可能需要维护者先批准。随后拥有仓库写权限的维护者可打开 **Actions → Bug Server CI → Run workflow**,选择 **develop** 并填写:

- `pr_number`:VChart 仓库的 PR 编号,支持外部 fork PR。
- `pr_number`:提交到 VChart 仓库的外部 fork PR 编号。
- `head_sha`:已审查的 PR head 的完整 40 位 SHA。

也可使用 GitHub CLI(替换下面的 PR 编号和 SHA):
Expand Down Expand Up @@ -34,13 +48,13 @@ gh workflow run bug-server.yml \

## 执行边界

1. **Bug Server PR Bundle** 仅由 `pull_request` 触发,在 macOS runner 上检出准确 head SHA,使用 Node.js 18 依次构建 vutils-extension、vchart、vchart-extension 和 bugserver-trigger。不持有 Bug Server token、不保留 checkout 凭据,缓存写入仅属于 PR 作用域;产物名为 `bug-server-pr-<编号>-<SHA>`。
1. **Bug Server PR Bundle** 仅在来自外部 fork 的 `pull_request` 中执行构建,在 macOS runner 上检出准确 head SHA,使用 Node.js 18 依次构建 vutils-extension、vchart、vchart-extension 和 bugserver-trigger。不持有 Bug Server token、不保留 checkout 凭据,缓存写入仅属于 PR 作用域;产物名为 `bug-server-pr-<编号>-<SHA>`。
2. 手动校验 job 从默认分支 workflow 的固定提交加载脚本,通过 GitHub API 确认当前 PR head,并校验来源 workflow ID/路径、PR 事件、成功状态、base/head 仓库 ID、源分支和 run SHA。选择最新匹配运行中唯一且未过期的命名产物,再复核产物的运行 ID、仓库 ID 和 SHA。fork 的运行记录可能没有 PR 列表,此时由仓库、分支、SHA 绑定来源;如列表存在,则还必须包含目标 PR。
3. 提交 job 使用 workflow 固定提交中的可信脚本,按 artifact ID 下载 ZIP,只接受单一普通 `index.js` 文件,最大 64 MiB。读取器只把字节写入固定路径,不按 ZIP 路径解压。客户端依赖以 `--ignore-scripts` 独立安装;bundle 只作为文件上传,此 runner 不执行 PR bundle 或其 package scripts。

两个 workflow 默认 `contents: read`;手动查询和下载 job 另需 `actions: read`,目标校验还需 `pull-requests: read`。token 仅注入最后调用 Bug Server API 的 step。默认分支手动流程不检出或构建 PR 代码;仅省略缓存步骤无法消除默认分支缓存写权限,因此采用 PR 事件隔离构建。

已有 push / pull_request 自动入口保留。外部 fork 的自动运行仍然无法获得仓库 secret,使用上述手动入口完成验证。
`main` push 和仓库内 PR 保留自动构建与测试。外部 fork PR 的自动运行只构建产物,不调用需要仓库 secret 的 Bug Server API,使用上述手动入口完成验证。

## 本地检查

Expand Down
Loading