chore: add package metadata gate
This commit is contained in:
parent
d9d9760405
commit
503e2d1d54
@ -74,6 +74,7 @@ pnpm check:brand
|
|||||||
pnpm check:ci
|
pnpm check:ci
|
||||||
pnpm check:env
|
pnpm check:env
|
||||||
pnpm check:secrets
|
pnpm check:secrets
|
||||||
|
pnpm check:metadata
|
||||||
pnpm check:artifacts
|
pnpm check:artifacts
|
||||||
pnpm check:quality
|
pnpm check:quality
|
||||||
pnpm clean:artifacts
|
pnpm clean:artifacts
|
||||||
|
|||||||
@ -11,6 +11,7 @@ pnpm check:brand
|
|||||||
pnpm check:ci
|
pnpm check:ci
|
||||||
pnpm check:env
|
pnpm check:env
|
||||||
pnpm check:secrets
|
pnpm check:secrets
|
||||||
|
pnpm check:metadata
|
||||||
pnpm exec tsc --noEmit --pretty false
|
pnpm exec tsc --noEmit --pretty false
|
||||||
git diff --check
|
git diff --check
|
||||||
pnpm check:artifacts
|
pnpm check:artifacts
|
||||||
@ -29,7 +30,7 @@ pnpm check:quality
|
|||||||
|
|
||||||
## CI
|
## 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 和本地提交前检查复用同一个入口,避免规则漂移。
|
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 测试值会被允许,避免误伤文档示例。
|
`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
|
```bash
|
||||||
|
|||||||
@ -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。
|
- `pnpm smoke:routes` 验证 `/` 返回 200。
|
||||||
- `/classic` 和 `/chat/test-id` 重定向到 `/`。
|
- `/classic` 和 `/chat/test-id` 重定向到 `/`。
|
||||||
- `/settings` 未登录重定向到 `/login?callbackUrl=%2Fsettings`。
|
- `/settings` 未登录重定向到 `/login?callbackUrl=%2Fsettings`。
|
||||||
|
|||||||
@ -1,7 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "yedir-ai",
|
"name": "yedir-ai",
|
||||||
"version": "3.1.0",
|
"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,
|
"private": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20",
|
||||||
|
"pnpm": "9.12.3"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev --turbo",
|
"dev": "next dev --turbo",
|
||||||
"postinstall": "node scripts/security/auto-enable-perf-guard.mjs",
|
"postinstall": "node scripts/security/auto-enable-perf-guard.mjs",
|
||||||
@ -16,7 +22,8 @@
|
|||||||
"check:ci": "node scripts/check-ci-hygiene.mjs",
|
"check:ci": "node scripts/check-ci-hygiene.mjs",
|
||||||
"check:env": "node scripts/check-env-example.mjs",
|
"check:env": "node scripts/check-env-example.mjs",
|
||||||
"check:secrets": "node scripts/check-secrets.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",
|
"clean:artifacts": "node scripts/clean-local-artifacts.mjs",
|
||||||
"smoke:routes": "node scripts/smoke-routes.mjs",
|
"smoke:routes": "node scripts/smoke-routes.mjs",
|
||||||
"format": "pnpm exec ultracite fix",
|
"format": "pnpm exec ultracite fix",
|
||||||
|
|||||||
45
scripts/check-package-metadata.mjs
Normal file
45
scripts/check-package-metadata.mjs
Normal 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.");
|
||||||
Loading…
x
Reference in New Issue
Block a user