Regression / regression (push) Canceled after 0s
本提交含两条并行工作线,因互相咬合(package.json scripts、regression.yml、 npm run build 链)无法按文件干净拆分,故合并为一次自洽提交。 ## 详情页减重(本轮主任务:修复「AI 干太重」) - 导航收敛:宽屏只用右侧目录、≤1200px 只用页内 sticky 导航,纯 CSS 媒体查询 实现(不引入 JS 宽度监听)。此前两套导航同时可见,active 状态互相打架。 - 入口去重:标题区由「查看示例/在线测试/契约 JSON」三个减为「在线测试」一个; 契约 JSON 归入实现资源;删除示例底部重复的「在线测试」。 - 示例工具栏:删除与目录锚点重复的示例下拉选择器;「全部展开代码」只在 示例数 >1 时出现(103 个组件里 49 个仅 1 个示例,此前恒显示)。 - 重复文案:示例区两句同义导语合并为一句。 - 首页 CTA 由 5 个减为 2 个(浏览组件/快速开始),测试总览入口挂到已有的 通过率统计卡上,不再另占 Hero 按钮。 - 统一详情取数:抽出 fetchDetail/loadDetail 作为 details/*.json 的唯一路径, FAQ 不再自行 fetch 一遍,与组件页共用缓存与失败兜底。 ## i18n - 删除 12 组重复键(含整段 FAQ 说明),字典 604 → 585 唯一键。 - 删除本次改动产生的 6 个死键。 - verify-i18n.mjs 新增 `unique dictionary keys` 断言:重复键在对象字面量里 是静默的后值覆盖,此前无从发现;现由门禁拦住。 ## 文档事实修正(实测为准) - TESTING/CONTRIBUTING:79 → 103 组件;旧断言数改为回指 tests/report.json。 - PLATFORMS:移动端 108 文件/18 端 → 282 文件/47 端;契约 5 → 47; 令牌 17 → 15;uni-app SFC 21 → 50。 - AGENTS:断言 1405/18 页 → 1464/103 页(PC)、807/47 页(移动端)。 - package.json:YOUR-ACCOUNT 占位 → gitea 实址与 kole-ui.mymoyu.top。 ## 品牌标识(并行会话成果,一并入库) - brand-mark.json 收归真源,build:brand 生成 favicon 与单色 SVG; PC 与移动端共用资产,verify:brand 24 条断言。 - regression.yml 增加 verify:brand 步骤。 ## 门禁与验收 新增工具:verify-component-page.mjs(86 条真实浏览器断言,随详情页改造同步 更新为「只允许一套导航可见」)、verify-brand-mark.mjs、lib/i18n-dead-keys.mjs (只读诊断)。 回归:PC 100%(1464/1464,103 页,N/A 50)· 移动端 100%(807/807,47 页)。 门禁:component-page 86 · i18n 17 · brand 24 · routes all · smoke all · theme OK · isolation 31 · nav all · examples 9 · api-docs 10 · mobile-docs 12。 已知未做:i18n 另有约 44 条历史死键(非本次产生),已记为 ROADMAP S8-P6; 顶栏与悬浮区的两个主题入口为刻意设计(verify-theme 断言其互斥),未删。
236 lines
11 KiB
YAML
236 lines
11 KiB
YAML
name: Regression
|
||
|
||
# 每次 push / PR 自动跑回归。
|
||
# 所有检查都在 Node 20 上执行;playwright 仅作为 CI 开发依赖。
|
||
|
||
on:
|
||
push:
|
||
branches: [main]
|
||
pull_request:
|
||
branches: [main]
|
||
workflow_dispatch:
|
||
|
||
permissions:
|
||
contents: read
|
||
|
||
jobs:
|
||
regression:
|
||
runs-on: ubuntu-latest
|
||
timeout-minutes: 20
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v4
|
||
with:
|
||
persist-credentials: false
|
||
|
||
- name: Setup Node
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '20'
|
||
|
||
- name: Cache playwright browsers
|
||
uses: actions/cache@v4
|
||
with:
|
||
path: ~/.cache/ms-playwright
|
||
key: ${{ runner.os }}-playwright-${{ hashFiles('package.json', 'package-lock.json') }}
|
||
restore-keys: |
|
||
${{ runner.os }}-playwright-
|
||
|
||
- name: Install dependencies
|
||
run: npm ci
|
||
|
||
- name: Install playwright chromium
|
||
run: npx --no-install playwright install --with-deps chromium
|
||
|
||
# npm run verify:nav 的断言依赖字体度量(7 条链接的文字宽度决定顶栏装不装得下)。
|
||
# 缺 CJK 字体时中文会退化成豆腐块或拉丁回退,宽度随之改变 → 断言假失败。
|
||
- name: Install CJK fonts
|
||
run: sudo apt-get update -qq && sudo apt-get install -y -qq fonts-noto-cjk
|
||
|
||
- name: Verify zero runtime dependencies
|
||
run: |
|
||
node -e "
|
||
const p = require('./package.json');
|
||
const deps = Object.keys(p.dependencies || {});
|
||
if (deps.length) {
|
||
console.error('FAIL: 运行时依赖必须为空,实际: ' + deps.join(', '));
|
||
process.exit(1);
|
||
}
|
||
console.log('zero-dep OK');
|
||
"
|
||
|
||
- name: Start dev server
|
||
run: |
|
||
node site/dev-server.js &
|
||
for i in $(seq 1 30); do
|
||
if curl -sf http://127.0.0.1:3311/site/data.json > /dev/null; then
|
||
echo "server ready after ${i} attempt(s)"
|
||
exit 0
|
||
fi
|
||
sleep 0.5
|
||
done
|
||
echo "FAIL: dev-server 未在 15 秒内就绪"
|
||
exit 1
|
||
|
||
# 三套分发产物都要能重建:PC(dist/)+ 移动端(dist/mobile/)+ PC×uni-app(dist/uniapp-pc/)。
|
||
# dist/ 不入库,所以必须先构建,后面的隔离门禁(C 组)才检查得到真实产物。
|
||
- name: Build distribution artifacts
|
||
run: npm run build
|
||
|
||
- name: Verify project brand mark
|
||
run: npm run verify:brand
|
||
|
||
# 移动端的 site/m 与 tests/mobile 是**生成物且入库**(与 PC 的 site/components、tests/<slug>.html 同策略:
|
||
# 部署直接拷仓库,不跑构建)。因此必须证明「仓库里的版本 = 构建能复现的版本」,
|
||
# 否则会出现「改了索引忘了重跑构建」→ 部署的仍是旧页面,且没有任何报错。
|
||
- name: Assert mobile artifacts are reproducible
|
||
run: |
|
||
if ! git diff --quiet -- site/m tests/mobile; then
|
||
echo "FAIL: 移动端生成物与仓库内已提交版本不一致,请重跑 npm run build:mobile 并提交"
|
||
git diff --stat -- site/m tests/mobile
|
||
exit 1
|
||
fi
|
||
echo "mobile artifacts reproducible"
|
||
|
||
# 隔离这种"没发生的事"只能靠断言证明:PC 的目录/数据/测试/分发里不得出现任何移动端痕迹,
|
||
# 移动端索引声明的 6 端文件必须齐全。28 条断言,见 tools/verify-mobile-isolation.mjs。
|
||
- name: Verify mobile isolation
|
||
run: npm run verify:isolation
|
||
|
||
# uni-app 端(移动端 18 个 + PC 端 3 个试点):SFC 结构 / node --check 语法 / 禁 DOM API /
|
||
# 手势必须 touch 事件 / 类名与令牌前缀按平台隔离 / 移动 rpx、PC px。
|
||
- name: Verify uni-app ends
|
||
run: npm run verify:uniapp
|
||
|
||
# uni-app **真实编译**(H5 + 微信小程序):静态门禁只能证明「源码长得合规」,
|
||
# 证明不了「编译器接受它」——本仓库有两次「静态全绿却编译不过」的实例
|
||
# (RangeQuickPicker 的 const 重赋值、CodeInput 的 emit 遮蔽),都是真编译才暴露的。
|
||
# 依赖装在隔离目录 .tmp/uniapp-build,主 job 的依赖不含 @dcloudio;
|
||
# 未缓存时**跳过并告警**而不是红:那是环境问题不是代码问题(脚本自身退出码 2)。
|
||
- name: Verify uni-app real build
|
||
run: |
|
||
if [ -d .tmp/uniapp-build/node_modules/@dcloudio ]; then
|
||
node tools/verify-uniapp-build.mjs
|
||
else
|
||
echo "::warning::uni-app 工具链未缓存,跳过真实编译验证(安装命令见 tools/verify-uniapp-build.mjs 头部)"
|
||
fi
|
||
|
||
# 移动端文档站的完整性(生成物的"缺内容"不会报错,只会悄悄少一块):
|
||
# 组件页 14 个小节齐全 / 侧栏列全组件且恰好一个高亮 / **契约 API 与 4 个框架端源码逐名一致**
|
||
# / 每端代码块非空 / 契约变体类名在 CSS 里真实存在 / 页面壳无残留占位符。
|
||
- name: Verify mobile docs completeness
|
||
run: npm run verify:mobile-docs
|
||
|
||
- name: Verify i18n
|
||
run: node tools/verify-i18n.mjs
|
||
|
||
# API 表说明的出处可溯性:每条说明都要能指认来源,「规格」类必须是规格原文逐字引用
|
||
# (判据与反例见 tools/verify-api-docs.mjs 头部)。
|
||
- name: Verify API docs provenance
|
||
run: npm run verify:api-docs
|
||
|
||
- name: Verify site routing
|
||
run: node tools/verify-site-routing.mjs
|
||
|
||
# 无 # 路由(History API)只在真浏览器里成立:服务器回落 + SPA 壳 <base> +
|
||
# 资源绝对地址 + pushState/历史四件事得同时对,静态检查只能证明文件里有那几行。
|
||
- name: Verify site routes in browser
|
||
run: node tools/verify-site-routes.mjs
|
||
|
||
- name: Verify cross-platform structure
|
||
run: node tools/verify-cross-platform.mjs
|
||
|
||
- name: Verify theme modes
|
||
run: node tools/verify-theme.mjs
|
||
|
||
# 模板页库(S4-P11):4 个典型后台页的浏览器实测 —— 令牌生效 / 非白屏 / 零控制台错误 /
|
||
# 逐页交互(表单校验、筛选分页、批量操作、抽屉、开关、保存与放弃)/ 375–1024px 无横向溢出。
|
||
# 静态检查证明不了「交互可用」,而模板页的价值恰恰全在交互上。
|
||
- name: Verify page templates
|
||
run: npm run verify:templates
|
||
|
||
# 演示帧内「覆盖型浮层」必须铺满真实视口:模态 / 图片预览 / 全屏弹窗 / 加载遮罩的
|
||
# position:fixed 以帧视口为包含块,而演示帧是按内容高度撑开的 —— 「点击图片只在
|
||
# 演示框内全屏」就是本脚本要拦的缺陷。含反向用例:贴边浮层与水印不得被提升。
|
||
- name: Verify stage overlay lift
|
||
run: npm run verify:stage-overlay
|
||
|
||
- name: Run regression
|
||
run: node tools/run-regression.mjs
|
||
|
||
# 移动端回归:同引擎同口径,不同数据源(site/m/data.mobile.json)与报告(tests/mobile-report.json)。
|
||
# 触控行为断言(滑动/下拉/标签切换)只在移动端行为库里,PC 侧不加载、不受影响。
|
||
- name: Run mobile regression
|
||
run: npm run regression:mobile
|
||
|
||
# 移动端文档站/测试站的浏览器实测:本次实测踩到「组件文档页资源路径少一级 → 样式与演示帧静默 404,
|
||
# 页面文字照常显示、结构断言全过」。四类取值只能在真浏览器里拿到:HTTP 状态、控制台错误、
|
||
# 演示帧是否真有内容(不是 404 页)、令牌是否解析成 44px。
|
||
- name: Verify mobile site in browser
|
||
run: npm run verify:mobile-site
|
||
|
||
- name: Smoke test site
|
||
run: npm run smoke:site
|
||
|
||
# 顶栏窄屏折叠(≤1366px 汉堡 + 抽屉):18 个宽度 × 中英双语 + 抽屉交互,约 35 秒。
|
||
# 必须在浏览器里跑 —— 元素"可见"不等于"点得到":遮罩层叠、visibility 过渡
|
||
# 都会让点击静默失效,而矩形与可见性断言全都会通过(改动前实测踩中两个)。
|
||
- name: Verify responsive nav
|
||
run: npm run verify:nav
|
||
|
||
# 「在线测试」页把用户编辑的 HTML 灌进 iframe 跑,是站上唯一的不可信内容入口。
|
||
# 安全边界(不透明源 / sandbox 权限 / 两条 CSP 取交集)与预览帧的资源基准
|
||
# (srcdoc 继承父页 URL,演示源码里的 ./Xxx.css 会解析错)都只在真浏览器里可判:
|
||
# 静态读代码只能看到属性字符串,看不到"到底拦没拦住、样式落在哪个 URL"。
|
||
- name: Verify playground
|
||
run: npm run verify:playground
|
||
|
||
- name: Upload report
|
||
uses: actions/upload-artifact@v4
|
||
if: always()
|
||
with:
|
||
name: regression-report
|
||
path: |
|
||
tests/report.json
|
||
tests/report-junit.xml
|
||
tests/cross-platform-report.json
|
||
tests/mobile-report.json
|
||
tests/mobile-report-junit.xml
|
||
retention-days: 30
|
||
|
||
- name: Publish test summary
|
||
if: always()
|
||
run: |
|
||
if [ -f tests/report.json ]; then
|
||
node -e "
|
||
const r = require('./tests/report.json');
|
||
const a = r.assertions;
|
||
console.log('## 回归结果(PC)');
|
||
console.log('');
|
||
console.log('| 项 | 值 |');
|
||
console.log('|---|---|');
|
||
console.log('| 通过率 | ' + r.passRate + '% |');
|
||
console.log('| 断言 | ' + a.pass + '/' + (a.pass + a.fail) + ' |');
|
||
console.log('| N/A | ' + (a.na || 0) + ' |');
|
||
console.log('| 页面全通过 | ' + r.pagesAllPass + '/' + r.pages + ' |');
|
||
console.log('| 超时 | ' + ((r.timedOut || []).length) + ' |');
|
||
" >> "$GITHUB_STEP_SUMMARY"
|
||
fi
|
||
if [ -f tests/mobile-report.json ]; then
|
||
node -e "
|
||
const r = require('./tests/mobile-report.json');
|
||
const a = r.assertions;
|
||
console.log('');
|
||
console.log('## 回归结果(移动端)');
|
||
console.log('');
|
||
console.log('| 项 | 值 |');
|
||
console.log('|---|---|');
|
||
console.log('| 通过率 | ' + r.passRate + '% |');
|
||
console.log('| 断言 | ' + a.pass + '/' + (a.pass + a.fail) + ' |');
|
||
console.log('| N/A | ' + (a.na || 0) + ' |');
|
||
console.log('| 页面全通过 | ' + r.pagesAllPass + '/' + r.pages + ' |');
|
||
console.log('| 超时 | ' + ((r.timedOut || []).length) + ' |');
|
||
" >> "$GITHUB_STEP_SUMMARY"
|
||
fi
|