diff --git a/README.md b/README.md index 95068ff59..ee1d2a52c 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ pnpm check:logs pnpm check:brand pnpm check:artifacts pnpm check:quality +pnpm clean:artifacts pnpm exec tsc --noEmit --pretty false pnpm test pnpm db:migrate diff --git a/docs/operations.md b/docs/operations.md index cc658d196..2ff5dc249 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -11,6 +11,7 @@ pnpm check:brand pnpm exec tsc --noEmit --pretty false git diff --check pnpm check:artifacts +pnpm clean:artifacts ``` 等价的一键质量门禁: @@ -21,6 +22,8 @@ pnpm check:quality 其中 `pnpm check:artifacts` 会检查 `.DS_Store`、swap 文件、`.env.local`、`.claude/`、migration backup 和 `tsconfig.tsbuildinfo` 等本地污染物是否被 Git 追踪。 +`pnpm clean:artifacts` 会清理当前工作区常见本地垃圾文件,例如 `.DS_Store`、swap 文件和 `tsconfig.tsbuildinfo`。它会跳过 `.git`、`node_modules`、`.next`、`.pnpm-store`、`.venv` 等重目录,适合在提交或打包前手动执行。 + ## CI `.github/workflows/lint.yml` 是基础质量门禁,运行 `pnpm check:quality`,负责 lint、日志治理、公开交付面品牌治理、类型检查、diff hygiene 和 tracked 污染物检查。 diff --git a/package.json b/package.json index 9afc9954e..093922c91 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "check:artifacts": "node scripts/check-tracked-artifacts.mjs", "check:brand": "node scripts/check-brand-hygiene.mjs", "check:quality": "pnpm lint && pnpm check:logs && pnpm check:brand && 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", "db:generate": "drizzle-kit generate", diff --git a/scripts/clean-local-artifacts.mjs b/scripts/clean-local-artifacts.mjs new file mode 100644 index 000000000..1310f80e9 --- /dev/null +++ b/scripts/clean-local-artifacts.mjs @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +import { readdirSync, rmSync } from "node:fs"; +import { join, relative } from "node:path"; + +const root = process.cwd(); +const skippedDirectories = new Set([ + ".git", + ".next", + ".pnpm-store", + ".turbo", + ".venv", + "node_modules", + "playwright-report", + "test-results", +]); + +const shouldRemove = (name) => + name === ".DS_Store" || name === "tsconfig.tsbuildinfo" || name.endsWith(".swp"); + +const removed = []; + +function walk(directory) { + for (const entry of readdirSync(directory, { withFileTypes: true })) { + const path = join(directory, entry.name); + if (entry.isDirectory()) { + if (skippedDirectories.has(entry.name)) { + continue; + } + walk(path); + continue; + } + + if (!shouldRemove(entry.name)) { + continue; + } + + rmSync(path, { force: true }); + removed.push(relative(root, path)); + } +} + +walk(root); + +if (removed.length === 0) { + console.log("No local artifacts found."); +} else { + console.log(`Removed ${removed.length} local artifact${removed.length === 1 ? "" : "s"}:`); + for (const file of removed) { + console.log(`- ${file}`); + } +}