mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 02:06:43 +00:00
fix(ci): honor Periphery ignores in shared intersection (#110839)
This commit is contained in:
@@ -23,6 +23,10 @@ export function parseRepoLocation(location: string): {
|
||||
file: string;
|
||||
line: string;
|
||||
};
|
||||
export function filterIgnoredFindings(
|
||||
findings: PeripheryFinding[],
|
||||
repoRoot?: string,
|
||||
): PeripheryFinding[];
|
||||
export function escapeCommandData(value: unknown): string;
|
||||
export function escapeCommandProperty(value: unknown): string;
|
||||
export function formatAnnotation(finding: PeripheryFinding): string;
|
||||
|
||||
@@ -5,6 +5,8 @@ import path from "node:path";
|
||||
import { isDirectRunUrl } from "./lib/direct-run.mjs";
|
||||
|
||||
const SHARED_LOCATION_PREFIX = "../shared/OpenClawKit/Sources/";
|
||||
const SHARED_SOURCE_ROOT = "apps/shared/OpenClawKit/Sources";
|
||||
const BARE_PERIPHERY_IGNORE_COMMENT = /\/\/\/?\s*periphery:ignore(?![:\w])/;
|
||||
|
||||
function requireValue(args, index, option) {
|
||||
const value = args[index + 1];
|
||||
@@ -107,6 +109,39 @@ export function parseRepoLocation(location) {
|
||||
};
|
||||
}
|
||||
|
||||
export function filterIgnoredFindings(findings, repoRoot = process.cwd()) {
|
||||
const sourceRoot = path.resolve(repoRoot, SHARED_SOURCE_ROOT);
|
||||
const sourceLines = new Map();
|
||||
|
||||
return findings.filter((finding) => {
|
||||
const location = parseRepoLocation(finding.location);
|
||||
const sourceFile = path.resolve(repoRoot, location.file);
|
||||
const relativeSource = path.relative(sourceRoot, sourceFile);
|
||||
if (
|
||||
!relativeSource ||
|
||||
path.isAbsolute(relativeSource) ||
|
||||
relativeSource === ".." ||
|
||||
relativeSource.startsWith(`..${path.sep}`)
|
||||
) {
|
||||
throw new Error(`invalid shared Periphery source path: ${location.file}`);
|
||||
}
|
||||
let lines = sourceLines.get(sourceFile);
|
||||
if (!lines) {
|
||||
lines = fs.readFileSync(sourceFile, "utf8").split(/\r?\n/);
|
||||
sourceLines.set(sourceFile, lines);
|
||||
}
|
||||
|
||||
const declarationIndex = Number(location.line) - 1;
|
||||
if (declarationIndex < 0 || declarationIndex >= lines.length) {
|
||||
throw new Error(`invalid shared Periphery source line: ${finding.location}`);
|
||||
}
|
||||
|
||||
return ![lines[declarationIndex - 1], lines[declarationIndex]].some(
|
||||
(line) => typeof line === "string" && BARE_PERIPHERY_IGNORE_COMMENT.test(line),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function escapeCommandData(value) {
|
||||
return String(value ?? "")
|
||||
.replaceAll("%", "%25")
|
||||
@@ -166,9 +201,11 @@ export function run(args, env = process.env) {
|
||||
const options = parseArgs(args);
|
||||
readStatus(options.iosStatus, "iOS");
|
||||
readStatus(options.macosStatus, "macOS");
|
||||
const findings = intersectFindings(
|
||||
readFindings(options.iosResults, "iOS"),
|
||||
readFindings(options.macosResults, "macOS"),
|
||||
const findings = filterIgnoredFindings(
|
||||
intersectFindings(
|
||||
readFindings(options.iosResults, "iOS"),
|
||||
readFindings(options.macosResults, "macOS"),
|
||||
),
|
||||
);
|
||||
|
||||
fs.mkdirSync(path.dirname(options.output), { recursive: true });
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, join } from "node:path";
|
||||
import { compileFunction } from "node:vm";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { parse } from "yaml";
|
||||
import {
|
||||
buildSummary,
|
||||
filterIgnoredFindings,
|
||||
formatAnnotation,
|
||||
intersectFindings,
|
||||
parseRepoLocation,
|
||||
@@ -11,6 +14,7 @@ import {
|
||||
} from "../../scripts/periphery-intersection.mjs";
|
||||
|
||||
const WORKFLOW_PATH = ".github/workflows/shared-openclawkit-periphery.yml";
|
||||
const FINDING_SOURCE = "../shared/OpenClawKit/Sources/OpenClawKit/Example.swift";
|
||||
|
||||
type WorkflowStep = {
|
||||
id?: string;
|
||||
@@ -35,12 +39,24 @@ function finding(overrides: Record<string, unknown> = {}) {
|
||||
return {
|
||||
ids: ["s:11OpenClawKit7ExampleV"],
|
||||
kind: "struct",
|
||||
location: "../shared/OpenClawKit/Sources/OpenClawKit/Example.swift:12:8",
|
||||
location: `${FINDING_SOURCE}:12:8`,
|
||||
name: "Example",
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function withSharedSource(source: string, test: (repoRoot: string) => void) {
|
||||
const repoRoot = mkdtempSync(join(tmpdir(), "openclaw-periphery-intersection-"));
|
||||
const sourceFile = join(repoRoot, "apps/shared/OpenClawKit/Sources/OpenClawKit/Example.swift");
|
||||
mkdirSync(dirname(sourceFile), { recursive: true });
|
||||
writeFileSync(sourceFile, source);
|
||||
try {
|
||||
test(repoRoot);
|
||||
} finally {
|
||||
rmSync(repoRoot, { force: true, recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
describe("Periphery intersection", () => {
|
||||
it("matches exact Swift USRs instead of declaration names", () => {
|
||||
const sameNameDifferentUsr = finding({ ids: ["s:11OpenClawKit7ExampleV_other"] });
|
||||
@@ -62,6 +78,32 @@ describe("Periphery intersection", () => {
|
||||
expect(intersectFindings([later, finding()], [finding(), later])).toEqual([finding(), later]);
|
||||
});
|
||||
|
||||
it("honors bare Periphery ignore comments on or above declarations", () => {
|
||||
withSharedSource(
|
||||
[
|
||||
"// periphery:ignore - exported package surface",
|
||||
"public struct Example {}",
|
||||
"",
|
||||
'public init(value: String = "value") {} // periphery:ignore - exported initializer',
|
||||
].join("\n"),
|
||||
(repoRoot) => {
|
||||
const declaration = finding({ location: `${FINDING_SOURCE}:2:8` });
|
||||
const inline = finding({ location: `${FINDING_SOURCE}:4:8` });
|
||||
expect(filterIgnoredFindings([declaration, inline], repoRoot)).toEqual([]);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("does not treat scoped Periphery commands as bare ignores", () => {
|
||||
withSharedSource(
|
||||
["// periphery:ignore:parameters value", "public struct Example {}"].join("\n"),
|
||||
(repoRoot) => {
|
||||
const command = finding({ location: `${FINDING_SOURCE}:2:8` });
|
||||
expect(filterIgnoredFindings([command], repoRoot)).toEqual([command]);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("fails closed when a finding has no USR", () => {
|
||||
expect(() => validateFindings([finding({ ids: [] })], "iOS")).toThrow(
|
||||
"iOS finding 0 has no usable Swift USR",
|
||||
|
||||
Reference in New Issue
Block a user