chore: add package metadata gate

This commit is contained in:
Your Name 2026-05-27 12:16:43 +08:00
parent d9d9760405
commit 503e2d1d54
5 changed files with 65 additions and 3 deletions

View File

@ -74,6 +74,7 @@ pnpm check:brand
pnpm check:ci
pnpm check:env
pnpm check:secrets
pnpm check:metadata
pnpm check:artifacts
pnpm check:quality
pnpm clean:artifacts

View File

@ -11,6 +11,7 @@ pnpm check:brand
pnpm check:ci
pnpm check:env
pnpm check:secrets
pnpm check:metadata
pnpm exec tsc --noEmit --pretty false
git diff --check
pnpm check:artifacts
@ -29,7 +30,7 @@ pnpm check:quality
## CI
`.github/workflows/lint.yml` 是基础质量门禁,运行 `pnpm check:quality`,负责 lint、日志治理、公开交付面品牌治理、CI hygiene、环境变量示例卫生、secret hygiene、类型检查、diff hygiene 和 tracked 污染物检查。
`.github/workflows/lint.yml` 是基础质量门禁,运行 `pnpm check:quality`,负责 lint、日志治理、公开交付面品牌治理、CI hygiene、环境变量示例卫生、secret hygiene、package metadata、类型检查、diff hygiene 和 tracked 污染物检查。
CI 和本地提交前检查复用同一个入口,避免规则漂移。
@ -85,6 +86,14 @@ pnpm check:secrets
`pnpm check:secrets` 会扫描 Git 已追踪文本文件,拦截真实形态的常见 API key、GitHub token、AWS key、Slack token、Authorization/Cookie 长值和私钥块。明显的 `xxxx`、placeholder、example 或 redaction 测试值会被允许,避免误伤文档示例。
## Package Metadata
```bash
pnpm check:metadata
```
`pnpm check:metadata` 会检查 `package.json` 的项目名、描述、许可证、Node/pnpm 版本和 package manager 声明是否符合当前交付基线。`repository/homepage/bugs` 会等 canonical remote 仓库完成重命名并验证后再添加,避免对外链接撒谎。
## 首页性能烟测
```bash

View File

@ -13,7 +13,7 @@ SMOKE_BASE_URL=http://127.0.0.1:3001 pnpm smoke:routes
预期:
- `pnpm check:quality` 通过 lint、日志脱敏门禁、公开交付面品牌治理、CI hygiene、环境变量示例卫生、secret hygiene、类型检查、diff hygiene 和 tracked 污染物检查。
- `pnpm check:quality` 通过 lint、日志脱敏门禁、公开交付面品牌治理、CI hygiene、环境变量示例卫生、secret hygiene、package metadata、类型检查、diff hygiene 和 tracked 污染物检查。
- `pnpm smoke:routes` 验证 `/` 返回 200。
- `/classic` 和 `/chat/test-id` 重定向到 `/`。
- `/settings` 未登录重定向到 `/login?callbackUrl=%2Fsettings`。

View File

@ -1,7 +1,13 @@
{
"name": "yedir-ai",
"version": "3.1.0",
"description": "Production-oriented AI design workspace with Lovart-style home, Canvas/Agent workflows, image editing, 3D/CAD, and admin governance.",
"private": true,
"license": "Apache-2.0",
"engines": {
"node": ">=20",
"pnpm": "9.12.3"
},
"scripts": {
"dev": "next dev --turbo",
"postinstall": "node scripts/security/auto-enable-perf-guard.mjs",
@ -16,7 +22,8 @@
"check:ci": "node scripts/check-ci-hygiene.mjs",
"check:env": "node scripts/check-env-example.mjs",
"check:secrets": "node scripts/check-secrets.mjs",
"check:quality": "pnpm lint && pnpm check:logs && pnpm check:brand && pnpm check:ci && pnpm check:env && pnpm check:secrets && pnpm exec tsc --noEmit --pretty false && git diff --check && pnpm check:artifacts",
"check:metadata": "node scripts/check-package-metadata.mjs",
"check:quality": "pnpm lint && pnpm check:logs && pnpm check:brand && pnpm check:ci && pnpm check:env && pnpm check:secrets && pnpm check:metadata && pnpm exec tsc --noEmit --pretty false && git diff --check && pnpm check:artifacts",
"clean:artifacts": "node scripts/clean-local-artifacts.mjs",
"smoke:routes": "node scripts/smoke-routes.mjs",
"format": "pnpm exec ultracite fix",

View File

@ -0,0 +1,45 @@
#!/usr/bin/env node
import { readFileSync } from "node:fs";
const packageJson = JSON.parse(readFileSync("package.json", "utf8"));
const licenseText = readFileSync("LICENSE", "utf8");
const violations = [];
const expectEqual = (path, actual, expected) => {
if (actual !== expected) {
violations.push(`package.json ${path}: expected "${expected}", received "${actual ?? "<missing>"}"`);
}
};
const expectNonEmpty = (path, actual) => {
if (typeof actual !== "string" || actual.trim().length === 0) {
violations.push(`package.json ${path}: expected a non-empty string`);
}
};
expectEqual("name", packageJson.name, "yedir-ai");
expectNonEmpty("description", packageJson.description);
expectEqual("private", packageJson.private, true);
expectEqual("license", packageJson.license, "Apache-2.0");
expectEqual("packageManager", packageJson.packageManager, "pnpm@9.12.3");
expectEqual("engines.node", packageJson.engines?.node, ">=20");
expectEqual("engines.pnpm", packageJson.engines?.pnpm, "9.12.3");
if (!licenseText.includes("Apache License, Version 2.0")) {
violations.push("LICENSE: expected Apache License, Version 2.0 text");
}
if (packageJson.repository || packageJson.homepage || packageJson.bugs) {
violations.push(
"package.json: repository/homepage/bugs metadata should be added only after the canonical remote repository is renamed and verified"
);
}
if (violations.length > 0) {
console.error("Package metadata check failed.");
console.error(violations.join("\n"));
process.exit(1);
}
console.log("Package metadata check passed.");