mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-12 23:36:15 -08:00
ci(workspace): [ENG-02] add read-only checks and isolated Pages workflow
This commit is contained in:
1 parent
9a6cfe5c6b
commit
833cc11674
16 files changed
+347
-61
No files matched your search
@@ -1,43 +1,79 @@
|
||||
name: Node CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
branches: [master, 'codex/**']
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
pages-artifact:
|
||||
description: Prepare the checked docs directory for the separate Pages workflow
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: checks-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || github.event_name == 'push' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
checks:
|
||||
name: Checks and build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20.x]
|
||||
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
CI: true
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: install, lint, build, and test
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
package-manager-cache: false
|
||||
- name: Install the pinned package manager
|
||||
run: npm install --global --force yarn@1.22.22
|
||||
- name: Validate workflow syntax
|
||||
run: |
|
||||
yarn
|
||||
yarn test:playback
|
||||
yarn lint
|
||||
yarn build:all
|
||||
yarn test:dash-control
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
if: success()
|
||||
curl --fail --silent --show-error --location https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz --output "$RUNNER_TEMP/actionlint.tar.gz"
|
||||
printf '%s %s\n' '8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8' "$RUNNER_TEMP/actionlint.tar.gz" | sha256sum --check
|
||||
tar -xzf "$RUNNER_TEMP/actionlint.tar.gz" -C "$RUNNER_TEMP" actionlint
|
||||
"$RUNNER_TEMP/actionlint" -color
|
||||
- name: Frozen install
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
git add -f docs
|
||||
git commit -m 'Deploy to GitHub Pages'
|
||||
git subtree split --prefix docs master -b gh-pages-temp
|
||||
git push origin gh-pages-temp:refs/heads/gh-pages --force
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
mkdir -p refactor/.cache/ci
|
||||
yarn install --frozen-lockfile --non-interactive 2>&1 | tee refactor/.cache/ci/install.log
|
||||
- name: Read-only checks and tests
|
||||
run: yarn ci:check 2>&1 | tee refactor/.cache/ci/check.log
|
||||
- name: Build libraries and documentation
|
||||
run: yarn ci:build 2>&1 | tee refactor/.cache/ci/build.log
|
||||
- name: Record source and tool versions
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p refactor/.cache/ci
|
||||
git rev-parse HEAD > refactor/.cache/ci/source.txt
|
||||
node --version > refactor/.cache/ci/node.txt
|
||||
yarn --version > refactor/.cache/ci/yarn.txt
|
||||
sha256sum yarn.lock > refactor/.cache/ci/lock.sha256
|
||||
git diff --stat > refactor/.cache/ci/generated-diff.txt
|
||||
- name: Upload available logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: checks-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
path: refactor/.cache/ci/
|
||||
include-hidden-files: true
|
||||
retention-days: 14
|
||||
if-no-files-found: warn
|
||||
- name: Prepare Pages artifact
|
||||
if: inputs.pages-artifact && github.ref == 'refs/heads/master'
|
||||
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
||||
with:
|
||||
path: docs
|
||||
include-hidden-files: true
|
||||
@@ -0,0 +1,34 @@
|
||||
name: Deploy Pages
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: pages
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
if: github.ref == 'refs/heads/master' && vars.PAGES_DEPLOY_ENABLED == 'true'
|
||||
uses: ./.github/workflows/nodejs.yml
|
||||
with:
|
||||
pages-artifact: true
|
||||
|
||||
deploy:
|
||||
if: github.ref == 'refs/heads/master' && vars.PAGES_DEPLOY_ENABLED == 'true'
|
||||
needs: validate
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Deploy the validated artifact
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
|
||||
@@ -74,7 +74,7 @@ Use the repo scripts rather than ad hoc bundler commands.
|
||||
### Development
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Starts the local dev site on port `8082` and interactively selects a package to watch. The selected package is built into:
|
||||
@@ -84,7 +84,7 @@ Starts the local dev site on port `8082` and interactively selects a package to
|
||||
### Production Build
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
yarn build
|
||||
```
|
||||
|
||||
Interactive build for one package. Outputs:
|
||||
@@ -95,25 +95,27 @@ Interactive build for one package. Outputs:
|
||||
Build all packages:
|
||||
|
||||
```bash
|
||||
npm run build all
|
||||
yarn build all
|
||||
```
|
||||
|
||||
### Other Project Scripts
|
||||
|
||||
```bash
|
||||
npm run build:i18n
|
||||
npm run build:ts
|
||||
npm run build:docs
|
||||
npm run build:llm
|
||||
npm run build:test
|
||||
npm run lint
|
||||
npm run build:all
|
||||
yarn build:i18n
|
||||
yarn build:ts
|
||||
yarn build:docs
|
||||
yarn build:llm
|
||||
yarn build:test
|
||||
yarn lint
|
||||
yarn build:all
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- `npm run lint` targets package source/types plus scripts and TypeScript demo assets.
|
||||
- `npm run build:all` is expensive; use it when a change truly spans builds/docs/types/lint together.
|
||||
- `yarn lint` is read-only; `yarn lint:fix` explicitly fixes the same source/type/script range.
|
||||
- `yarn ci:check` runs strict toolchain/plan/lint/tests; `yarn ci:build` generates outputs and checks imports.
|
||||
- See `refactor/ci-setup.md` for CI and separate Pages deployment; remote activation is tracked separately.
|
||||
- `yarn build:all` is expensive; use it when a change truly spans builds/docs/types/lint together.
|
||||
|
||||
## Useful Local URLs
|
||||
|
||||
@@ -251,9 +253,9 @@ If adding HLS-like quality/audio selection elsewhere:
|
||||
|
||||
For package-specific builds, the normal flow is:
|
||||
|
||||
1. `npm run dev` and pick the package for fast local iteration
|
||||
1. `yarn dev` and pick the package for fast local iteration
|
||||
2. validate in `http://localhost:8082`
|
||||
3. `npm run build` and pick the package when ready to update shippable artifacts
|
||||
3. `yarn build` and pick the package when ready to update shippable artifacts
|
||||
|
||||
## Documentation Expectations
|
||||
|
||||
|
||||
+10
-3
@@ -38,9 +38,16 @@
|
||||
"test:dash-control": "node --test test/dash-control.test.js",
|
||||
"dev": "npx cross-env NODE_ENV=development node ./scripts/dev.js",
|
||||
"build": "npx cross-env NODE_ENV=production node ./scripts/build.js",
|
||||
"lint": "npx eslint packages/*/{src,types,package.json} scripts/*.js test/* docs/assets/ts/* --fix",
|
||||
"build:all": "npm run build all && npm run build:i18n && npm run build:ts && npm run build:docs && npm run lint",
|
||||
"check:toolchain": "node scripts/check-toolchain.mjs"
|
||||
"lint": "eslint \"packages/*/{src,types,package.json}\" \"scripts/*.{js,mjs}\" \"test/*\" \"docs/assets/ts/*\" --no-fix",
|
||||
"build:all": "yarn ci:build && yarn lint",
|
||||
"check:toolchain": "node scripts/check-toolchain.mjs",
|
||||
"lint:fix": "eslint \"packages/*/{src,types,package.json}\" \"scripts/*.{js,mjs}\" \"test/*\" \"docs/assets/ts/*\" --fix",
|
||||
"check:plan": "node refactor/scripts/plan.mjs --check",
|
||||
"test:node": "node --test test/playback.test.js test/dash-control.test.js test/toolchain.test.js test/build-docs.test.js",
|
||||
"test:baseline": "node --test refactor/scripts/*.test.mjs",
|
||||
"ci:check": "yarn check:toolchain --strict && yarn check:plan && yarn lint && yarn test:node && yarn test:baseline",
|
||||
"ci:build": "yarn build all && yarn build:i18n && yarn build:ts && yarn build:docs && yarn test:imports",
|
||||
"test:imports": "node --test test/esm.test.js test/i18n.test.js test/ssr.test.js"
|
||||
},
|
||||
"browserslist": "last 1 Chrome version",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
| [工具链与发布](toolchain-release.md) | TypeScript、Bun、构建、版本管理和发布回退 |
|
||||
| [已实现的开发环境](toolchain-setup.md) | Node/Yarn 固定版本、锁文件、安装命令和实际验证范围 |
|
||||
| [全包大版本策略](version-policy.md) | 每包分别升级一个 major 的目标清单、兼容要求和版本落地步骤 |
|
||||
| [已实现的 CI 入口](ci-setup.md) | Yarn 检查/构建、只读 lint、Pages 隔离及远端待验收状态 |
|
||||
| [GitHub CI/CD](github-ci-cd.md) | PR/兼容矩阵、构建报告、Pages、npm 发布及远端准入验证 |
|
||||
| [AI 协作流程](ai-workflow.md) | AI 接续工作、任务边界、验证、记录和交接模板 |
|
||||
| [架构决策](decisions.md) | 已选方向、待验证方案及被拒绝方案 |
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"task": "ENG-02",
|
||||
"date": "2026-09-10",
|
||||
"sourceCommit": "9a6cfe5c",
|
||||
"node": "24.21.0",
|
||||
"yarn": "1.22.22",
|
||||
"platform": "win32-x64",
|
||||
"inputs": {
|
||||
"package.json": "3d5cb61b9a802c19d7cdbb19318ab38562846725d972dcd3cf494d2754c779a8",
|
||||
"yarn.lock": "5921f159477b65161b48d4b768f462cb05a537b6a257e62732ec9dfaf4d69e7e",
|
||||
".node-version": "73fb1b615e2043a933be1c0895cde4358036acc28d785692509b822aa53c761f",
|
||||
".github/workflows/nodejs.yml": "803842ba0c5bf5bd1806604ecdf0571792a245fff09865c6dc3c94fd9fbc4a1c",
|
||||
".github/workflows/pages.yml": "e63fb5609a98ae745ff5af68ddbf3adf18a9b483fee9d9d05a957674672f3459",
|
||||
"scripts/build-docs.js": "95aae678608df443ccd14579fa39f2787ac364705f5d0c360ed55e8b0c8ca6e3",
|
||||
"scripts/build-ts.js": "1e1f3448de0fbd88939c3a2ecaebc8a11a48e3b1b4c23dbaeac8b58a92ab7813",
|
||||
"test/build-docs.test.js": "4382e9f445118ac02984425673c84b0678f598cc03ac418ec2bf3b0b2bad23d2"
|
||||
},
|
||||
"actionlint": {
|
||||
"version": "1.7.12",
|
||||
"windowsArchiveSha256": "6e7241b51e6817ea6a047693d8e6fed13b31819c9a0dd6c5a726e1592d22f6e9",
|
||||
"linuxArchiveSha256": "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8",
|
||||
"workflows": 2,
|
||||
"passed": true,
|
||||
"localShellcheck": false,
|
||||
"localPyflakes": false,
|
||||
"invalidKeyRejected": true
|
||||
},
|
||||
"check": {
|
||||
"command": "yarn ci:check",
|
||||
"passed": true,
|
||||
"behaviorTests": 21,
|
||||
"baselineTests": 2,
|
||||
"sourceFilesUnchanged": 426,
|
||||
"lintFailureRejectedWithoutFixing": true
|
||||
},
|
||||
"declarationGeneration": {
|
||||
"command": "yarn build:ts",
|
||||
"filesCompared": 21,
|
||||
"typescriptPrinterOutputUnchanged": true,
|
||||
"formattingFixTypes": [
|
||||
"layout"
|
||||
]
|
||||
},
|
||||
"build": {
|
||||
"command": "yarn ci:build",
|
||||
"libraryPackages": 21,
|
||||
"libraryArtifacts": 63,
|
||||
"i18n": true,
|
||||
"editorDeclarations": true,
|
||||
"vitepress": true,
|
||||
"postBuildImportSmokeFiles": 3,
|
||||
"passed": true
|
||||
},
|
||||
"remote": {
|
||||
"actionsRuns": "unverified",
|
||||
"branchProtection": "unverified",
|
||||
"pagesSource": "unverified",
|
||||
"pagesEnableVariable": "unverified",
|
||||
"npmPublication": "not performed"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# ENG-02:只读 PR 检查与独立 Pages 流程
|
||||
|
||||
日期:2026-09-10;分支 codex/compatible-modernization;起点 9a6cfe5c。
|
||||
|
||||
## 改动
|
||||
|
||||
- lint 改为只读,lint:fix 显式修复,覆盖新增 MJS 工具。新增 ci:check、ci:build、test:node、test:baseline、test:imports、check:plan;旧测试/构建入口保留。
|
||||
- Node CI 支持 PR、master/codex/** push、手动和复用调用;固定 Actions SHA、Node/Yarn、冻结安装、只读权限、并发与超时,失败也上传可获得的日志/来源摘要。
|
||||
- Pages 改为独立手动 workflow,仅 master 且 PAGES_DEPLOY_ENABLED=true 时准备和部署。复用同一次检查/构建得到的 docs artifact;仅部署作业有 Pages/OIDC 权限,移除 CI 内 Git 提交、subtree 和 force push。
|
||||
- 当前仅实现隔离框架,未切换远端 Pages source 或启用变量。合并后原 master 自动部署会停止;CI-02 完成域名/路径/恢复验证后再启用,详见 ci-setup.md。
|
||||
|
||||
## 检查中发现并修复
|
||||
|
||||
原 build-docs.js 没有把构建子进程的失败传给调用方,导致 CI 可能错误成功。新增 error/close 处理,并用真实子进程退出 23/0 验证失败和成功均正确传播。
|
||||
|
||||
声明生成器产生的 46 处格式错误以前由 lint --fix 清理。将 layout 修正纳入声明生成器,只处理它刚生成的文件,不能自动改生产源码或调整类型逻辑。21 份声明经 TypeScript printer 规范化后与格式修正前完全一致,构建后只读 lint 通过。声明拼接本身的设计问题仍由后续类型/站点任务处理。
|
||||
|
||||
旧 esm/i18n/ssr 文件只有导入和 console,不是完整行为断言;把它们放到构建后的 test:imports,避免检查旧 dist 后宣称候选已测。
|
||||
|
||||
## 验证
|
||||
|
||||
- Node 24.21.0 / Yarn 1.22.22,使用 ENG-PM-01 冻结安装的独立环境;开发依赖和 yarn.lock 未变。
|
||||
- 最终 ci:check 通过:21 项有行为断言的 Node 测试、2 项发布包/HTTP 基线测试。426 个源码/类型/测试文件检查前后哈希不变。
|
||||
- ci:build 的库包、i18n、编辑器声明、VitePress 全流程通过;21 库包 63 产物,构建后另有 3 个导入 smoke 通过。
|
||||
- 两份 workflow 经 actionlint 1.7.12 本地检查;Windows 归档 SHA-256 已核对。Windows 本轮禁用不可用的 shellcheck/pyflakes,Linux CI 命令保留其默认检查,远端尚未运行。
|
||||
- 负例:故意引入格式错误导致 ci:check 失败且文件字节未被修改;非法 workflow key 被 actionlint 拒绝。负例均在临时副本恢复,没有修改生产文件。
|
||||
- 计划/链接/依赖、源码 lint 和 Git 差异检查通过;报告见 [ci-validation.json](../baselines/ci-validation.json)。
|
||||
|
||||
没有运行新的远端 workflow、发布或推送。最低 Node/跨平台/浏览器/完整类型/候选包矩阵由后续 ENG/CI 任务实施,不能将本次绿色基础检查等同整个重构通过。
|
||||
|
||||
## 维护与回退
|
||||
|
||||
根 AGENTS、ci-setup.md、github-ci-cd.md、工具说明和任务状态同步维护。新增第三方工具只有校验归档方式使用的 actionlint 1.7.12;Actions 固定 SHA 和版本在 YAML 注释中,来源是官方发布 tag 对应提交。
|
||||
|
||||
可撤销 ENG-02 提交恢复旧脚本/workflow 配置;重新执行旧自动部署仍需要核对远端 Pages 状态。下一个任务 BASE-02 使用内置浏览器继续公共 API 快照,再推进事件/生命周期及试点所需测试基础。每项任务继续独立提交。
|
||||
@@ -0,0 +1,50 @@
|
||||
# PR 检查和 Pages 操作说明
|
||||
|
||||
## 本地命令
|
||||
|
||||
使用 toolchain-setup.md 的 Node/Yarn 环境与冻结安装。
|
||||
|
||||
| 命令 | 行为 |
|
||||
| --- | --- |
|
||||
| `yarn lint` | 只读 ESLint,覆盖包源码/声明、JS/MJS 工具、测试和编辑器声明 |
|
||||
| `yarn lint:fix` | 显式自动修复相同范围 |
|
||||
| `yarn test:node` | 显式执行 4 个有行为断言的 Node 测试文件,保留原 test:playback/test:dash-control 入口 |
|
||||
| `yarn test:imports` | 3 个既有包导入 smoke,构建后执行以使用新产物;不把 console 示例视为完整行为断言 |
|
||||
| `yarn test:baseline` | 固定发布包完整性及本地 HTTP 基线测试;首次可能下载已固定归档到缓存 |
|
||||
| `yarn ci:check` | 严格 Node/Yarn/锁检查、计划、只读 lint、Node 和基线测试;允许写忽略缓存,不修改源码 |
|
||||
| `yarn ci:build` | 21 库包、i18n、编辑器声明和文档站构建,以及构建后包导入 smoke;会生成 dist 和 docs 内容 |
|
||||
| `yarn build:all` | 保留旧入口,执行 ci:build 后只读 lint |
|
||||
|
||||
scripts/build-docs.js 保留原 npm run build 子命令兼容入口,现在传播失败退出码;包管理/锁维护继续使用 Yarn。MOD-02 可再统一旧内部脚本。build-ts.js 仅对刚生成的声明执行 ESLint layout 格式修正,使只读 lint 在构建后仍能通过;不是对生产源码执行自动修复。
|
||||
|
||||
## PR 和主线
|
||||
|
||||
.github/workflows/nodejs.yml 在 PR、master/codex/** push 和手动运行时触发,也供 Pages 复用。Checks and build 作业只授予 contents: read,checkout 不保留 Git 凭据,没有提交、推送、npm 发布或部署步骤。PR/推送取消过期运行,手动部署不被中途取消;初始 Ubuntu 作业限时 30 分钟。
|
||||
|
||||
Actions 固定完整 SHA,Node 来自 .node-version,Yarn 固定 1.22.22;安装使用 frozen-lockfile。actionlint 1.7.12 从官方固定归档取得,先核对提交在 workflow 中的 SHA-256,再执行。没有执行 curl 管道脚本。日志在失败时也尽量上传,包含源码 SHA、工具版本、锁摘要和生成差异概览,保留 14 天。
|
||||
|
||||
本轮不缓存 node_modules;矩阵、下载缓存、覆盖率、浏览器 trace 和候选 tarball 汇总由 CI-01 等后续任务扩展。当前测试通过不代表尚未实现的类型消费者或浏览器矩阵通过。将来的稳定 required 汇总名称由 CI-01/CI-04 核实后设置,不把本地 YAML 当作分支保护已生效。
|
||||
|
||||
## Pages 隔离与启用条件
|
||||
|
||||
.github/workflows/pages.yml 仅支持手动运行,限定 master,且仓库变量 PAGES_DEPLOY_ENABLED 必须为 true。初始启用状态未经远端核实;没有修改该变量或其他 GitHub 设置。保留此门槛用于 CI-02 完成域名、路径和远端配置验收后再启用,不能直接自动部署 PR 产物。
|
||||
|
||||
Pages 先调用同一检查/构建 workflow,成功后上传同一次运行生成的完整 docs artifact,再在 github-pages 环境的独立作业调用官方 deploy-pages。仅 deploy 作业有 pages: write / id-token: write,没有 Git contents 写权限,也没有原先的 gh-pages force push。发布排队执行,不取消正在执行的发布。
|
||||
|
||||
已静态核对当前 docs/CNAME 为 github.artplayer.org;上传包含隐藏文件以保留 .nojekyll。docs 根、document、compiled、旧 HTML/编辑器等实际线上路径和历史站点来源仍需 CI-02 逐项预检;目前未确认或修改线上 Pages source。合并该变更后旧 push-master 自动部署会停止,需先完成以下迁移步骤再启用新流程。
|
||||
|
||||
1. CI-02 记录当前 Pages source、gh-pages ref、域名/DNS、关键 URL 和可恢复的旧产物。
|
||||
2. 先验证 artifact 内容及旧路径;设置 Pages source 为 GitHub Actions,核对 github-pages 环境只允许受信任 master 部署和所需审批。
|
||||
3. 经实际部署授权后设置 PAGES_DEPLOY_ENABLED=true,在 master 手动运行 Deploy Pages;记录 CI 和部署 URL,逐项探测旧路径。
|
||||
4. 出现问题时关闭启用变量,按保存的 Pages source/gh-pages ref 恢复;不默认重新 force push 覆盖历史。恢复旧 workflow 可从 ENG-02 前 Git 历史取回,但执行远端写入仍按部署授权处理。
|
||||
|
||||
## 待核实的外部状态
|
||||
|
||||
| 项目 | 当前证据 | 负责任务 |
|
||||
| --- | --- | --- |
|
||||
| 新 PR/主线 workflow 实际执行、故障演练 | 仅本地静态和命令验证,无远端 run | CI-04 |
|
||||
| required checks、fork 权限和环境审批 | 未读取/修改仓库设置 | CI-04 |
|
||||
| Pages source、启用变量、域名和回退目标 | 只读源码 CNAME,远端未知 | CI-02 |
|
||||
| npm 权限、trusted publisher、候选发布 | 未配置、未执行 | CI-03/CI-04 |
|
||||
|
||||
参考:[GitHub Pages 自定义 workflow](https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages)、[setup-node](https://github.com/actions/setup-node)、[actionlint 1.7.12](https://github.com/rhysd/actionlint/releases/tag/v1.7.12)。本轮已核对选用 Actions 的实际 action.yml 和发布 tag 对应 SHA;后续升级需重新检查。
|
||||
@@ -1,12 +1,12 @@
|
||||
# GitHub CI/CD 优化与验收
|
||||
|
||||
2026-09-10 用户明确要求在本次重构中优化和增强 GitHub CI/CD。范围包含仓库检查、测试矩阵、构建产物、文档站部署和 npm 发布准备,并持续维护脚本文档及故障处理指南。本文是待实施规范,不代表 workflows 已更新或远端运行成功。
|
||||
2026-09-10 用户明确要求在本次重构中优化和增强 GitHub CI/CD。范围包含仓库检查、测试矩阵、构建产物、文档站部署和 npm 发布准备,并持续维护脚本文档及故障处理指南。ENG-02 已实现初步检查与部署隔离,操作见 [ci-setup.md](ci-setup.md);完整矩阵及远端验收仍待后续任务。
|
||||
|
||||
## 当前源码基线
|
||||
## ENG-02 前源码基线
|
||||
|
||||
[nodejs.yml](../.github/workflows/nodejs.yml) 是当前唯一 workflow:仅 push master 触发,Ubuntu + Node 20.x,checkout/setup-node 使用 v2;单一 job 执行 yarn 安装、两组 Node 测试、lint 和 build:all,再提交 docs、subtree split 并 force push gh-pages。
|
||||
[nodejs.yml](../.github/workflows/nodejs.yml) 曾是唯一 workflow:仅 push master 触发,Ubuntu + Node 20.x,checkout/setup-node 使用 v2;单一 job 执行 yarn 安装、两组 Node 测试、lint 和 build:all,再提交 docs、subtree split 并 force push gh-pages。
|
||||
|
||||
[package.json](../package.json) 中 lint 使用 --fix,build:all 又包含 lint;当前 workflow 没有 PR 触发、真实浏览器矩阵、类型消费者/tarball 检查、显式权限、并发取消、超时或报告上传。上述是文件检查结果,尚未核对 GitHub 的实际历史运行、Pages 配置、分支保护、环境规则或 npm 账号配置。旧流程的部署目标与访问路径必须先核实,不能仅改 YAML 就宣称迁移完成。
|
||||
改造前 [package.json](../package.json) 中 lint 使用 --fix,build:all 又包含 lint;当前 workflow 没有 PR 触发、真实浏览器矩阵、类型消费者/tarball 检查、显式权限、并发取消、超时或报告上传。上述是文件检查结果,尚未核对 GitHub 的实际历史运行、Pages 配置、分支保护、环境规则或 npm 账号配置。旧流程的部署目标与访问路径必须先核实,不能仅改 YAML 就宣称迁移完成。
|
||||
|
||||
## 目标流水线
|
||||
|
||||
@@ -22,7 +22,7 @@ ENG-02 先建立只读 PR 检查和部署隔离框架,后续 CI 任务逐步
|
||||
|
||||
## CI 的可靠性与运行成本
|
||||
|
||||
- Node/TS/包管理器版本来自 ENG-01、BASE-08 和 Bun 试点;最低消费者兼容与构建所需运行时分别验证,不因 Actions 升级静默提高消费者要求。
|
||||
- Node/TS/包管理器版本来自 ENG-01/ENG-PM-01 和 BASE-08;用户指定 Yarn 为包管理器,Bun 仅隔离评估。最低消费者兼容与构建所需运行时分别验证,不因 Actions 升级静默提高消费者要求。
|
||||
- 覆盖 Linux 与 Windows 的关键脚本;浏览器覆盖 Chromium/Firefox/WebKit 和有需要的正式 Chrome。真机、Cast 等证据仍使用环境矩阵,不将 hosted runner 通过当作真机通过。
|
||||
- 安装使用选定包管理器的锁定模式;缓存按 OS、运行时、包管理器及锁文件隔离,浏览器缓存还绑定测试工具版本。禁止无关 PR 缓存/产物进入有发布权限的任务。
|
||||
- 快速检查依据依赖图而非简单路径过滤;共享核心/构建/锁文件变化扩大检查,影响不确定时完整回归。文档单改可缩小范围,但 required 汇总检查必须给出真实结果,不能将失败/取消误报成功或留下永久 pending。
|
||||
|
||||
+3
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 214 项,范围 22 个包及工作区/示例。
|
||||
|
||||
状态:todo 197 / doing 0 / blocked 0 / done 17 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
|
||||
状态:todo 196 / doing 0 / blocked 0 / done 18 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
|
||||
|
||||
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| ENG-01 | workspace<br>固定 Node、包管理器与依赖 | BASE-01 | 版本 pin、唯一锁文件、安装说明 | 干净环境可复现,最低 Node 与构建依赖一致,未夹带全量升级 | M | done |
|
||||
| ENG-PM-01 | workspace<br>按用户选择切换固定 Yarn 包管理器 | ENG-01 | Yarn 固定版本、唯一 yarn.lock、工具检查与安装维护文档 | 干净冻结安装、Node 测试和全部构建通过;记录解析差异和依赖用途,独立提交 | M | done |
|
||||
| ENG-02 | workspace<br>拆分只读检查并建立 PR CI | ENG-01, ENG-PM-01 | lint/lint:fix、PR 与主线检查、独立部署任务;遵循 github-ci-cd.md,PR/重构分支触发、最小权限及 workflow 静态检查 | 仓库内检查可执行且不改源码、不发布;required checks 的外部设置状态列入发布台账,不阻塞本地框架建设 | M | todo |
|
||||
| ENG-02 | workspace<br>拆分只读检查并建立 PR CI | ENG-01, ENG-PM-01 | lint/lint:fix、PR 与主线检查、独立部署任务;遵循 github-ci-cd.md,PR/重构分支触发、最小权限及 workflow 静态检查 | 仓库内检查可执行且不改源码、不发布;required checks 的外部设置状态列入发布台账,不阻塞本地框架建设 | M | done |
|
||||
| ENG-03 | workspace<br>建立公共行为与单元测试入口 | ENG-02, BASE-03 | 保留现有 node:test,测试目录/夹具/统一入口 | 已有 19 项回归保留,旧版与候选可用同一夹具运行 | M | todo |
|
||||
| ENG-04 | workspace<br>建立类型测试基础 | ENG-02, BASE-05 | 根与分包 tsconfig、显式 TS 依赖、正反例测试 | 核心/试点与迁移模块严格检查,未迁移第三方/包历史问题独立台账;明确最低/当前 TS 和各环境类型 | M | todo |
|
||||
| ENG-05 | workspace<br>建立真实浏览器测试服务 | ENG-03, BASE-04, BASE-08 | Playwright projects、本地 Range/失败媒体服务;复用 docs 页面/样本的状态隔离、错误采集与候选资源映射 | Chromium/Firefox/WebKit 的基础播放 smoke 和报告可执行;以媒体状态断言判定通过,区分轻量用例与真实编辑器交互 | M | todo |
|
||||
@@ -420,3 +420,4 @@
|
||||
- BASE-HARNESS-01: [记录](changes/2026-09-10-BASE-HARNESS-01-browser-fixture.md)
|
||||
- ENG-01: [记录](changes/2026-09-10-ENG-01-reproducible-toolchain.md) [记录](baselines/toolchain-validation.json)
|
||||
- ENG-PM-01: [记录](changes/2026-09-10-ENG-PM-01-yarn-toolchain.md) [记录](baselines/yarn-validation.json)
|
||||
- ENG-02: [记录](changes/2026-09-10-ENG-02-readonly-ci.md) [记录](baselines/ci-validation.json)
|
||||
@@ -1,5 +1,11 @@
|
||||
# 进度与证据
|
||||
|
||||
## 当前实施:ENG-02 只读检查与 CI 基础已完成
|
||||
|
||||
新增 PR/主线/复用检查与独立手动 Pages 流程;lint 与自动修复拆分,修复文档构建退出码和生成声明格式。23 项 Node/基线测试、3 个构建后导入 smoke、21 库包 63 产物与文档构建通过;426 个源/类型/测试文件只读检查前后不变,actionlint 静态和负例通过。详见 [ENG-02](changes/2026-09-10-ENG-02-readonly-ci.md) 与 [操作说明](ci-setup.md)。
|
||||
|
||||
当前 214 项任务,18 完成、196 待办。ENG-PM-01 已提交 9a6cfe5c;本轮独立提交 ENG-02。未推送、未启用远端 CI/Pages、未发布;CI-02/CI-04 继续负责远端验收。下一任务 BASE-02,使用内置浏览器保存并校验公共 API 基线。
|
||||
|
||||
## 当前实施:ENG-PM-01 已完成 Yarn 切换
|
||||
|
||||
标准工具链为 Node 24.21.0 / Yarn Classic 1.22.22,唯一维护 yarn.lock。最终干净冻结安装、20 项 Node 测试、只读工具检查、21 库包及文档站构建通过,63 个库产物与 npm 基线 SHA-256 全同。详见 [ENG-PM-01](changes/2026-09-10-ENG-PM-01-yarn-toolchain.md)。既有搜索 peer 警告交 SITE-05 验证。
|
||||
|
||||
+5
-2
@@ -439,11 +439,14 @@
|
||||
"ENG-01",
|
||||
"ENG-PM-01"
|
||||
],
|
||||
"status": "todo",
|
||||
"status": "done",
|
||||
"risk": "M",
|
||||
"deliverable": "lint/lint:fix、PR 与主线检查、独立部署任务;遵循 github-ci-cd.md,PR/重构分支触发、最小权限及 workflow 静态检查",
|
||||
"acceptance": "仓库内检查可执行且不改源码、不发布;required checks 的外部设置状态列入发布台账,不阻塞本地框架建设",
|
||||
"evidence": []
|
||||
"evidence": [
|
||||
"changes/2026-09-10-ENG-02-readonly-ci.md",
|
||||
"baselines/ci-validation.json"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ENG-03",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
1. 切换到 .node-version 指定的 Node,安装 Yarn 1.22.22;例如 `npm install --global yarn@1.22.22`,然后确认 `node --version` 和 `yarn --version`。npm 仅可用于安装 Yarn 工具及消费者兼容检查,不用于维护本仓库依赖锁。
|
||||
2. 干净 checkout 执行 `yarn install --frozen-lockfile --non-interactive`,禁止 CI 自动更新锁或忽略安装脚本/engines。参见 [Yarn Classic install](https://classic.yarnpkg.com/en/docs/cli/install/)。
|
||||
3. 执行 `yarn check:toolchain --strict`,核对实际 Node/Yarn、19 个固定开发工具和 22 个 workspace 的声明及传递依赖锁条目。普通检查允许满足最低工具要求的 Node,同时打印标准版本。
|
||||
4. 执行 `yarn test:playback`、`yarn test:dash-control`、`yarn build all` 和 `yarn workspace artplayer-vitepress build`。只读 lint 和 PR CI 的拆分由 ENG-02 完成;旧 lint 当前仍有 --fix。
|
||||
4. 执行 `yarn test:playback`、`yarn test:dash-control`、`yarn build all` 和 `yarn workspace artplayer-vitepress build`。ENG-02 已拆分只读 lint 与 lint:fix;PR/主线入口和独立 Pages 流程见 ci-setup.md。
|
||||
|
||||
私有根包最低 Node 为 ^20.19.0 || >=22.12.0,与原本使用的 Vite 7 一致。本轮验证 Node 24.21.0,其他版本矩阵由 CI-01 接续,不能宣称所有最低环境已经通过。
|
||||
|
||||
|
||||
@@ -3,7 +3,13 @@ import spawn from 'cross-spawn'
|
||||
|
||||
const proc = spawn('npm', ['run', 'build'], {
|
||||
cwd: './packages/artplayer-vitepress/',
|
||||
stdio: 'inherit',
|
||||
})
|
||||
|
||||
proc.stdout.pipe(process.stdout)
|
||||
proc.stderr.pipe(process.stderr)
|
||||
proc.on('error', (error) => {
|
||||
console.error(error.message)
|
||||
process.exitCode = 1
|
||||
})
|
||||
proc.on('close', (code) => {
|
||||
process.exitCode = code ?? 1
|
||||
})
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { ESLint } from 'eslint'
|
||||
import { glob } from 'glob'
|
||||
|
||||
function ensureDirExists(filePath) {
|
||||
@@ -57,6 +58,13 @@ console.log(`✨ Built ${artplayerTSoutput}`);
|
||||
|
||||
pluginFiles.sort()
|
||||
const allFiles = [...pluginFiles, 'artplayer.d.ts']
|
||||
const eslint = new ESLint({ fix: true, fixTypes: ['layout'] })
|
||||
const results = await eslint.lintFiles(allFiles.map(file => path.join('docs/assets/ts', file)))
|
||||
await ESLint.outputFixes(results)
|
||||
if (results.some(result => result.errorCount)) {
|
||||
const formatter = await eslint.loadFormatter('stylish')
|
||||
throw new Error(formatter.format(results))
|
||||
}
|
||||
const commonJsPath = path.join('docs/assets/js/common.js')
|
||||
const commonJsContent = fs.readFileSync(commonJsPath, 'utf-8')
|
||||
const newLibUris = allFiles.map(file => `'./assets/ts/${file}'`).join(',\n ')
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
// eslint-disable-next-line test/no-import-node-test -- Verify the CLI failure contract using a real child process.
|
||||
import { test } from 'node:test'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const root = fileURLToPath(new URL('../', import.meta.url))
|
||||
|
||||
test('documentation build forwards child failure and success exit codes', () => {
|
||||
const cache = path.join(root, 'refactor/.cache')
|
||||
fs.mkdirSync(cache, { recursive: true })
|
||||
const fixture = fs.mkdtempSync(path.join(cache, 'docs-exit-'))
|
||||
try {
|
||||
const pkg = path.join(fixture, 'packages/artplayer-vitepress')
|
||||
fs.mkdirSync(pkg, { recursive: true })
|
||||
for (const code of [23, 0]) {
|
||||
fs.writeFileSync(path.join(pkg, 'package.json'), JSON.stringify({
|
||||
private: true,
|
||||
scripts: { build: `node -e "process.exit(${code})"` },
|
||||
}))
|
||||
const result = spawnSync(process.execPath, [path.join(root, 'scripts/build-docs.js')], {
|
||||
cwd: fixture,
|
||||
encoding: 'utf8',
|
||||
})
|
||||
assert.equal(result.status, code, result.stderr)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
const relative = path.relative(cache, fixture)
|
||||
assert(relative.startsWith('docs-exit-') && !relative.includes(path.sep))
|
||||
fs.rmSync(fixture, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
Reference in new issue
Block a user