资源发布流水线
资源发布由三个 pnpm 脚本组成:assets:prepare → assets:build → assets:publish。每个命令职责单一,可独立运行。
0. 前置:cos-workspace 镜像
cos-workspace/ 是本地工作目录,必须 gitignored。pnpm assets:prepare 期望一个 cos-workspace/public-root-legacy/ 子目录,内容是当前线上公开桶的镜像(手动 coscli sync 拉一次或直接放进去)。
1. pnpm assets:prepare
scripts/prepare-cos-workspace.mjs:
- 把
cos-workspace/public-root-legacy/重写成cos-workspace/public-root/,路径全部对齐到realm/.../shared/...canonical 形式 - 把对象 base name 规整成短英文 kebab-case(构建期会再追加 hash8)
- 重新生成
cos-workspace/_meta/realm/{home,works,collections,links,audio}.json与 logical asset-source metadata
输出仍是本地文件,不上传。
2. pnpm assets:build
scripts/assets-build.mjs:
- 遍历
cos-workspace/public-root/下所有文件 realm/images/**走processImageFile:sharp读 metadata + content hash + 必要的 resize,输出<name>.<hash8>.<ext>realm/audio/**走processAudioFile:hash + 复制- 其他走
copySharedAsset:直接复制 - 加载
_meta/realm/{home,works,collections,links,audio}.json与可选的legacy-asset-sources.json,把source字段替换成 hashedobjectKey - 写私有 catalog
dist/cos-upload/private-root/realm/catalog/versions/<version>/<section>.json - 写私有
current.json(默认current.next.json;--publish-current时直接写current.json) - 写公开 site catalog
dist/cos-upload/public-root/realm/site-catalog/versions/<version>/assets.json(只含 SITE_ASSET_KEYS) - 写公开
current.json/current.next.json - 写
dist/local-manifest/manifest.generated.json给 publish 脚本读
--publish-current 跳过 staging 阶段,让 current.json 直接指向新版本(用于一次性大版本切换)。
3. pnpm assets:publish
scripts/assets-publish.mjs:
revalidate() 解析响应体:
- 200 +
failed: []→ 成功 - 200 +
partial: true→ 警告,日志输出失败路径,继续 - 5xx → throw,让整个 publish 失败
--dry-run 不执行 coscli、不发 fetch,只打印命令。--force-full 把 cos sync 换成 cos cp -r,做一次性全量重传(排障用)。--rollback <version> 跳过 build,直接 cos cp 写 current.json 指向旧版本。
4. 凭据与本地 dev
COS_SECRET_ID/COS_SECRET_KEY通过node --env-file=.env.local临时注入- 绝不写 coscli 配置文件,绝不打印 secret
COSCLI_PATH默认./cos-workspace/coscli-windows-amd64.exe,可覆盖COS_SESSION_TOKEN可选(STS 场景)
5. 验证清单
发布后:
6. 关键不变量
- 资源版本号(
<version>)是 UTC ISO 去掉分隔符:20260710T120000Z形式 - 对象键是内容寻址(hash 写入 key),所以
cos sync按 etag 跳过未变化对象是安全的 - 写
current.json是最后一步,且只cos cp不cos sync - 本地
cos-workspace/永远 gitignored