feat: import Chinese-localized Buzz source snapshot
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { promises as fs } from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
function git(args, cwd, options = {}) {
|
||||
return execFileSync("git", args, {
|
||||
cwd,
|
||||
encoding: "utf8",
|
||||
maxBuffer: 10 * 1024 * 1024,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
function toPosixPath(relativePath) {
|
||||
return relativePath.split(path.sep).join("/");
|
||||
}
|
||||
|
||||
export function countLines(content) {
|
||||
if (content.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
return content.split(/\r?\n/).length;
|
||||
}
|
||||
|
||||
export function allowedLineCount(baseLines, maxLines) {
|
||||
return baseLines == null || baseLines <= maxLines ? maxLines : baseLines;
|
||||
}
|
||||
|
||||
export function evaluateFileSize({ baseLines, candidateLines, maxLines }) {
|
||||
const limit = allowedLineCount(baseLines, maxLines);
|
||||
return { limit, violates: candidateLines > limit };
|
||||
}
|
||||
|
||||
function findRule(rules, relativePath) {
|
||||
return rules.find((rule) => relativePath.startsWith(`${rule.root}/`));
|
||||
}
|
||||
|
||||
export function resolveBaseRef(repoRoot, env = process.env) {
|
||||
if (env.CHECK_FILE_SIZES_BASE) {
|
||||
return env.CHECK_FILE_SIZES_BASE;
|
||||
}
|
||||
|
||||
if (env.GITHUB_ACTIONS === "true") {
|
||||
return "HEAD^1";
|
||||
}
|
||||
|
||||
try {
|
||||
const mergeBase = git(
|
||||
["merge-base", "origin/main", "HEAD"],
|
||||
repoRoot,
|
||||
).trim();
|
||||
const head = git(["rev-parse", "HEAD"], repoRoot).trim();
|
||||
return mergeBase === head ? "HEAD" : mergeBase;
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
"Could not resolve the file-size base from origin/main. Fetch origin/main or set CHECK_FILE_SIZES_BASE to an explicit commit.",
|
||||
{ cause: error },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function parseChangedFiles(output) {
|
||||
const fields = output.split("\0");
|
||||
const changes = [];
|
||||
|
||||
for (let index = 0; index < fields.length - 1; ) {
|
||||
const status = fields[index++];
|
||||
if (status.startsWith("R") || status.startsWith("C")) {
|
||||
changes.push({
|
||||
status: status[0],
|
||||
oldPath: fields[index++],
|
||||
path: fields[index++],
|
||||
});
|
||||
} else {
|
||||
changes.push({ status: status[0], path: fields[index++] });
|
||||
}
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
function changedProjectFiles({ repoRoot, projectRelative, baseRef }) {
|
||||
const output = git(
|
||||
["diff", "--name-status", "-z", "-M", baseRef, "--", projectRelative],
|
||||
repoRoot,
|
||||
);
|
||||
const changes = parseChangedFiles(output);
|
||||
const trackedPaths = new Set(changes.map((change) => change.path));
|
||||
const untracked = git(
|
||||
["ls-files", "--others", "--exclude-standard", "-z", "--", projectRelative],
|
||||
repoRoot,
|
||||
)
|
||||
.split("\0")
|
||||
.filter(Boolean);
|
||||
|
||||
for (const filePath of untracked) {
|
||||
if (!trackedPaths.has(filePath)) {
|
||||
changes.push({ status: "A", path: filePath });
|
||||
}
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
function readBaseFile(repoRoot, baseRef, filePath) {
|
||||
return git(["show", `${baseRef}:${filePath}`], repoRoot, {
|
||||
encoding: null,
|
||||
}).toString("utf8");
|
||||
}
|
||||
|
||||
export async function runFileSizeCheck({ projectRoot, rules, label }) {
|
||||
// Every governed project is a direct child of the repository root. Derive
|
||||
// these paths without Git so hook-provided repository environment variables
|
||||
// cannot collapse the project pathspec to an empty string.
|
||||
const repoRoot = path.dirname(projectRoot);
|
||||
const projectRelative = toPosixPath(path.basename(projectRoot));
|
||||
const baseRef = resolveBaseRef(repoRoot);
|
||||
|
||||
// Fail clearly instead of silently turning a missing/shallow base into a pass.
|
||||
git(["cat-file", "-e", `${baseRef}^{commit}`], repoRoot);
|
||||
|
||||
const violations = [];
|
||||
for (const change of changedProjectFiles({
|
||||
repoRoot,
|
||||
projectRelative,
|
||||
baseRef,
|
||||
})) {
|
||||
if (change.status === "D") continue;
|
||||
|
||||
const relativePath = toPosixPath(
|
||||
path.relative(projectRelative, change.path),
|
||||
);
|
||||
const rule = findRule(rules, relativePath);
|
||||
if (!rule || !rule.extensions.has(path.extname(relativePath))) continue;
|
||||
|
||||
const candidatePath = path.join(repoRoot, change.path);
|
||||
const candidateLines = countLines(await fs.readFile(candidatePath, "utf8"));
|
||||
const basePath = change.oldPath ?? change.path;
|
||||
const baseContent =
|
||||
change.status === "A" ? null : readBaseFile(repoRoot, baseRef, basePath);
|
||||
const baseLines = baseContent == null ? null : countLines(baseContent);
|
||||
const result = evaluateFileSize({
|
||||
baseLines,
|
||||
candidateLines,
|
||||
maxLines: rule.maxLines,
|
||||
});
|
||||
|
||||
if (result.violates) {
|
||||
violations.push({
|
||||
relativePath,
|
||||
baseLines,
|
||||
candidateLines,
|
||||
limit: result.limit,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (violations.length === 0) return;
|
||||
|
||||
console.error(`${label} file size ratchet failed (base ${baseRef}):`);
|
||||
for (const violation of violations) {
|
||||
const before = violation.baseLines == null ? "new" : violation.baseLines;
|
||||
const delta =
|
||||
violation.baseLines == null
|
||||
? ""
|
||||
: ` (${violation.candidateLines - violation.baseLines >= 0 ? "+" : ""}${violation.candidateLines - violation.baseLines})`;
|
||||
console.error(
|
||||
`- ${violation.relativePath}: ${before} -> ${violation.candidateLines}${delta} lines (allowed ${violation.limit})`,
|
||||
);
|
||||
}
|
||||
console.error(
|
||||
"Keep new files at or below the limit; files already over it may not grow.",
|
||||
);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
Reference in New Issue
Block a user