chore(bazel): generated clippy config from workspace lints at release time
- Added scripts/gen-clippy-bazelrc.ts: emits bazel/clippy.bazelrc from [workspace.lints] in Cargo.toml (groups by ascending priority, then per-lint overrides, alphabetical within each tier); --check mode verifies sync without writing. - release.ts regenerates it alongside the lockfiles; the release_gate CD job runs the --check so drift only blocks publishing, never ordinary CI. Added the gen:clippy package script.
This commit is contained in:
@@ -465,6 +465,13 @@ jobs:
|
|||||||
needs: [release_metadata, check, rust_validate, native_addons, test_workspace, test_coding_agent_singleton, test_ts_native, test_coding_agent_ui, test_coding_agent_runtime, test_coding_agent_native, test_smoke, install_methods]
|
needs: [release_metadata, check, rust_validate, native_addons, test_workspace, test_coding_agent_singleton, test_ts_native, test_coding_agent_ui, test_coding_agent_runtime, test_coding_agent_native, test_smoke, install_methods]
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: ./.github/actions/bun-install
|
||||||
|
# Generated-config drift gate: bazel/clippy.bazelrc is maintained by
|
||||||
|
# scripts/release.ts (like the lockfiles); a stale file only blocks
|
||||||
|
# publishing, never ordinary CI.
|
||||||
|
- name: Check generated clippy config
|
||||||
|
run: bun scripts/gen-clippy-bazelrc.ts --check
|
||||||
- run: echo "release validation green"
|
- run: echo "release validation green"
|
||||||
|
|
||||||
# Builds (does not publish) the Linux-hosted release binaries in parallel
|
# Builds (does not publish) the Linux-hosted release binaries in parallel
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# Generated from [workspace.lints] in Cargo.toml (see .bazelrc clippy-strict).
|
# Generated by scripts/gen-clippy-bazelrc.ts from [workspace.lints] in Cargo.toml.
|
||||||
|
# Do not edit by hand; run `bun run gen:clippy` after changing the lint policy.
|
||||||
# Applies only to crates that opt in via `[lints] workspace = true`.
|
# Applies only to crates that opt in via `[lints] workspace = true`.
|
||||||
build:clippy-strict --@rules_rust//rust/settings:clippy_flag=-Amismatched_lifetime_syntaxes
|
build:clippy-strict --@rules_rust//rust/settings:clippy_flag=-Amismatched_lifetime_syntaxes
|
||||||
build:clippy-strict --@rules_rust//rust/settings:clippy_flag=-Wclippy::all
|
build:clippy-strict --@rules_rust//rust/settings:clippy_flag=-Wclippy::all
|
||||||
|
|||||||
@@ -163,6 +163,7 @@
|
|||||||
"publish:dry": "bun run prepublishOnly && npm publish -ws --access public --dry-run",
|
"publish:dry": "bun run prepublishOnly && npm publish -ws --access public --dry-run",
|
||||||
"release": "bun scripts/release.ts",
|
"release": "bun scripts/release.ts",
|
||||||
"gen:models": "bun --cwd=packages/catalog run gen:models",
|
"gen:models": "bun --cwd=packages/catalog run gen:models",
|
||||||
|
"gen:clippy": "bun scripts/gen-clippy-bazelrc.ts",
|
||||||
"gen:stats": "bun --cwd=packages/stats run gen:stats",
|
"gen:stats": "bun --cwd=packages/stats run gen:stats",
|
||||||
"gen:stats:reset": "bun --cwd=packages/stats run gen:stats:reset",
|
"gen:stats:reset": "bun --cwd=packages/stats run gen:stats:reset",
|
||||||
"gen:changelog": "bun scripts/rewrite-changelog.ts",
|
"gen:changelog": "bun scripts/rewrite-changelog.ts",
|
||||||
|
|||||||
Executable
+86
@@ -0,0 +1,86 @@
|
|||||||
|
#!/usr/bin/env bun
|
||||||
|
/**
|
||||||
|
* Generates `bazel/clippy.bazelrc` from `[workspace.lints]` in `Cargo.toml` so
|
||||||
|
* the bazel `clippy-strict` config (applied to crates that opt in via
|
||||||
|
* `[lints] workspace = true`) can never drift from the cargo lint policy.
|
||||||
|
*
|
||||||
|
* Emission mirrors rustc lint-level resolution: `[workspace.lints.rust]`
|
||||||
|
* entries first (bare rustc lint flags), then clippy entries — negative
|
||||||
|
* `priority` values (the lint groups) before per-lint overrides, alphabetical
|
||||||
|
* within each tier.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* bun scripts/gen-clippy-bazelrc.ts # rewrite bazel/clippy.bazelrc
|
||||||
|
* bun scripts/gen-clippy-bazelrc.ts --check # exit 1 when the file is stale
|
||||||
|
*/
|
||||||
|
import * as path from "node:path";
|
||||||
|
|
||||||
|
type LintLevel = "allow" | "warn" | "deny" | "forbid";
|
||||||
|
type LintEntry = LintLevel | { level: LintLevel; priority?: number };
|
||||||
|
type LintTable = Record<string, LintEntry>;
|
||||||
|
|
||||||
|
const FLAG_BY_LEVEL: Record<LintLevel, string> = { allow: "A", warn: "W", deny: "D", forbid: "F" };
|
||||||
|
|
||||||
|
const repoRoot = path.join(import.meta.dir, "..");
|
||||||
|
const outputPath = path.join(repoRoot, "bazel", "clippy.bazelrc");
|
||||||
|
|
||||||
|
function normalize(entry: LintEntry): { level: LintLevel; priority: number } {
|
||||||
|
if (typeof entry === "string") return { level: entry, priority: 0 };
|
||||||
|
return { level: entry.level, priority: entry.priority ?? 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Lint names ordered by ascending priority tier, alphabetical within a tier. */
|
||||||
|
function orderedNames(table: LintTable): string[] {
|
||||||
|
return Object.keys(table).sort((a, b) => {
|
||||||
|
const pa = normalize(table[a]).priority;
|
||||||
|
const pb = normalize(table[b]).priority;
|
||||||
|
if (pa !== pb) return pa - pb;
|
||||||
|
return a < b ? -1 : a > b ? 1 : 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function flagLines(table: LintTable, prefix: string): string[] {
|
||||||
|
return orderedNames(table).map(name => {
|
||||||
|
const { level } = normalize(table[name]);
|
||||||
|
return `build:clippy-strict --@rules_rust//rust/settings:clippy_flag=-${FLAG_BY_LEVEL[level]}${prefix}${name}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function render(): Promise<string> {
|
||||||
|
const cargo = Bun.TOML.parse(await Bun.file(path.join(repoRoot, "Cargo.toml")).text()) as {
|
||||||
|
workspace?: { lints?: { rust?: LintTable; clippy?: LintTable } };
|
||||||
|
};
|
||||||
|
const lints = cargo.workspace?.lints;
|
||||||
|
if (!lints?.clippy) {
|
||||||
|
throw new Error("Cargo.toml has no [workspace.lints.clippy] table");
|
||||||
|
}
|
||||||
|
const lines = [
|
||||||
|
"# Generated by scripts/gen-clippy-bazelrc.ts from [workspace.lints] in Cargo.toml.",
|
||||||
|
"# Do not edit by hand; run `bun run gen:clippy` after changing the lint policy.",
|
||||||
|
"# Applies only to crates that opt in via `[lints] workspace = true`.",
|
||||||
|
...flagLines(lints.rust ?? {}, ""),
|
||||||
|
...flagLines(lints.clippy, "clippy::"),
|
||||||
|
];
|
||||||
|
return `${lines.join("\n")}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const expected = await render();
|
||||||
|
const current = await Bun.file(outputPath)
|
||||||
|
.text()
|
||||||
|
.catch(() => "");
|
||||||
|
|
||||||
|
if (process.argv.includes("--check")) {
|
||||||
|
if (current !== expected) {
|
||||||
|
console.error(
|
||||||
|
"bazel/clippy.bazelrc is stale relative to [workspace.lints] in Cargo.toml.\n" +
|
||||||
|
"Run `bun run gen:clippy` and commit the result.",
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
console.log("bazel/clippy.bazelrc is in sync with Cargo.toml.");
|
||||||
|
} else if (current === expected) {
|
||||||
|
console.log("bazel/clippy.bazelrc already up to date.");
|
||||||
|
} else {
|
||||||
|
await Bun.write(outputPath, expected);
|
||||||
|
console.log("Wrote bazel/clippy.bazelrc.");
|
||||||
|
}
|
||||||
+5
-1
@@ -340,12 +340,16 @@ async function cmdRelease(versionOrBump: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
console.log(` sentinel: ${sentinelName}\n`);
|
console.log(` sentinel: ${sentinelName}\n`);
|
||||||
|
|
||||||
// 4. Regenerate lockfiles
|
// 4. Regenerate lockfiles and generated configs
|
||||||
console.log("Regenerating lockfiles...");
|
console.log("Regenerating lockfiles...");
|
||||||
await $`rm -f bun.lock`;
|
await $`rm -f bun.lock`;
|
||||||
await $`bun install`;
|
await $`bun install`;
|
||||||
await $`cargo generate-lockfile`;
|
await $`cargo generate-lockfile`;
|
||||||
await generateNixBunDeps(nixBunDepsGenerator);
|
await generateNixBunDeps(nixBunDepsGenerator);
|
||||||
|
// bazel/clippy.bazelrc mirrors [workspace.lints] in Cargo.toml; regenerate
|
||||||
|
// it here (like the lockfiles) so the bazel clippy policy can never drift.
|
||||||
|
// The release_gate CI job runs the matching `--check`.
|
||||||
|
await $`bun scripts/gen-clippy-bazelrc.ts`;
|
||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
// 5. Update changelogs
|
// 5. Update changelogs
|
||||||
|
|||||||
Reference in New Issue
Block a user