mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
docs: document release audit scripts
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
// Creates the debug proxy CA and, on macOS, trusts it in the system keychain.
|
||||||
import { spawnSync } from "node:child_process";
|
import { spawnSync } from "node:child_process";
|
||||||
import process from "node:process";
|
import process from "node:process";
|
||||||
import { resolveSystemBin } from "../src/infra/resolve-system-bin.js";
|
import { resolveSystemBin } from "../src/infra/resolve-system-bin.js";
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// Prunes omitted bundled plugin files and their unshared runtime dependencies
|
||||||
|
// from Docker-oriented production package output.
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { pathToFileURL } from "node:url";
|
import { pathToFileURL } from "node:url";
|
||||||
@@ -18,6 +20,9 @@ function parsePluginList(value) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses OPENCLAW_EXTENSIONS into the bundled plugin ids that Docker should keep.
|
||||||
|
*/
|
||||||
export function parseDockerPluginKeepList(value) {
|
export function parseDockerPluginKeepList(value) {
|
||||||
return parsePluginList(value);
|
return parsePluginList(value);
|
||||||
}
|
}
|
||||||
@@ -67,7 +72,9 @@ function collectPackageRuntimeClosure(repoRoot, seedPackageNames) {
|
|||||||
}
|
}
|
||||||
seen.add(packageName);
|
seen.add(packageName);
|
||||||
|
|
||||||
const packageJson = readPackageJson(path.join(nodeModulePath(repoRoot, packageName), "package.json"));
|
const packageJson = readPackageJson(
|
||||||
|
path.join(nodeModulePath(repoRoot, packageName), "package.json"),
|
||||||
|
);
|
||||||
for (const dependencyName of collectRuntimeDependencyNames(packageJson)) {
|
for (const dependencyName of collectRuntimeDependencyNames(packageJson)) {
|
||||||
if (!seen.has(dependencyName)) {
|
if (!seen.has(dependencyName)) {
|
||||||
stack.push(dependencyName);
|
stack.push(dependencyName);
|
||||||
@@ -106,7 +113,9 @@ function pruneNodeModulesForOmittedPlugins(repoRoot, bundledPluginDir, omittedPl
|
|||||||
const omittedSeeds = new Set();
|
const omittedSeeds = new Set();
|
||||||
|
|
||||||
for (const pluginId of omittedPluginIds) {
|
for (const pluginId of omittedPluginIds) {
|
||||||
const packageJson = readPackageJson(path.join(repoRoot, bundledPluginDir, pluginId, "package.json"));
|
const packageJson = readPackageJson(
|
||||||
|
path.join(repoRoot, bundledPluginDir, pluginId, "package.json"),
|
||||||
|
);
|
||||||
if (typeof packageJson?.name === "string") {
|
if (typeof packageJson?.name === "string") {
|
||||||
omittedPackageNames.add(packageJson.name);
|
omittedPackageNames.add(packageJson.name);
|
||||||
}
|
}
|
||||||
@@ -116,7 +125,11 @@ function pruneNodeModulesForOmittedPlugins(repoRoot, bundledPluginDir, omittedPl
|
|||||||
}
|
}
|
||||||
|
|
||||||
const keptSeeds = new Set(collectRuntimeDependencyNames(rootPackageJson));
|
const keptSeeds = new Set(collectRuntimeDependencyNames(rootPackageJson));
|
||||||
for (const dependencyName of collectWorkspacePackageRuntimeSeeds(repoRoot, "packages", new Set())) {
|
for (const dependencyName of collectWorkspacePackageRuntimeSeeds(
|
||||||
|
repoRoot,
|
||||||
|
"packages",
|
||||||
|
new Set(),
|
||||||
|
)) {
|
||||||
keptSeeds.add(dependencyName);
|
keptSeeds.add(dependencyName);
|
||||||
}
|
}
|
||||||
for (const dependencyName of collectWorkspacePackageRuntimeSeeds(
|
for (const dependencyName of collectWorkspacePackageRuntimeSeeds(
|
||||||
@@ -150,18 +163,25 @@ function pruneNodeModulesForOmittedPlugins(repoRoot, bundledPluginDir, omittedPl
|
|||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes omitted plugin dist trees plus node_modules packages not needed by kept runtime code.
|
||||||
|
*/
|
||||||
export function pruneDockerPluginDist(params = {}) {
|
export function pruneDockerPluginDist(params = {}) {
|
||||||
const repoRoot = params.cwd ?? params.repoRoot ?? process.cwd();
|
const repoRoot = params.cwd ?? params.repoRoot ?? process.cwd();
|
||||||
const env = params.env ?? process.env;
|
const env = params.env ?? process.env;
|
||||||
const bundledPluginDir = env.OPENCLAW_BUNDLED_PLUGIN_DIR ?? "extensions";
|
const bundledPluginDir = env.OPENCLAW_BUNDLED_PLUGIN_DIR ?? "extensions";
|
||||||
const keepPluginIds = parseDockerPluginKeepList(env.OPENCLAW_EXTENSIONS);
|
const keepPluginIds = parseDockerPluginKeepList(env.OPENCLAW_EXTENSIONS);
|
||||||
const excludedPluginIds = collectRootPackageExcludedExtensionDirs({ cwd: repoRoot });
|
const excludedPluginIds = collectRootPackageExcludedExtensionDirs({ cwd: repoRoot });
|
||||||
const omittedPluginIds = new Set([...excludedPluginIds].filter((pluginId) => !keepPluginIds.has(pluginId)));
|
const omittedPluginIds = new Set(
|
||||||
|
[...excludedPluginIds].filter((pluginId) => !keepPluginIds.has(pluginId)),
|
||||||
|
);
|
||||||
const removed = [];
|
const removed = [];
|
||||||
|
|
||||||
removed.push(...pruneNodeModulesForOmittedPlugins(repoRoot, bundledPluginDir, omittedPluginIds));
|
removed.push(...pruneNodeModulesForOmittedPlugins(repoRoot, bundledPluginDir, omittedPluginIds));
|
||||||
|
|
||||||
for (const pluginId of [...omittedPluginIds].toSorted((left, right) => left.localeCompare(right))) {
|
for (const pluginId of [...omittedPluginIds].toSorted((left, right) =>
|
||||||
|
left.localeCompare(right),
|
||||||
|
)) {
|
||||||
for (const pluginPath of [
|
for (const pluginPath of [
|
||||||
path.join(bundledPluginDir, pluginId),
|
path.join(bundledPluginDir, pluginId),
|
||||||
path.join("dist", "extensions", pluginId),
|
path.join("dist", "extensions", pluginId),
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
// Coordinates release-candidate validation runs and emits the publish command
|
||||||
|
// only after required local, CI, npm, plugin, and E2E evidence is green.
|
||||||
import { spawnSync } from "node:child_process";
|
import { spawnSync } from "node:child_process";
|
||||||
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||||
import { basename, join } from "node:path";
|
import { basename, join } from "node:path";
|
||||||
@@ -50,6 +52,9 @@ function requireValue(argv, index, flag) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses release-candidate validation options and enforces publish-scope policy.
|
||||||
|
*/
|
||||||
export function parseArgs(argv) {
|
export function parseArgs(argv) {
|
||||||
const args = stripLeadingPackageManagerSeparator(argv);
|
const args = stripLeadingPackageManagerSeparator(argv);
|
||||||
const options = {
|
const options = {
|
||||||
@@ -201,6 +206,9 @@ function githubApiTimedOut(error) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the GitHub REST API with the gh-auth token and a bounded timeout.
|
||||||
|
*/
|
||||||
export async function githubApi(path, options = {}) {
|
export async function githubApi(path, options = {}) {
|
||||||
const token = options.token ?? run("gh", ["auth", "token"], { capture: true }).trim();
|
const token = options.token ?? run("gh", ["auth", "token"], { capture: true }).trim();
|
||||||
const timeoutMs = options.timeoutMs ?? githubApiTimeoutMs();
|
const timeoutMs = options.timeoutMs ?? githubApiTimeoutMs();
|
||||||
@@ -254,6 +262,9 @@ async function runArtifacts(repo, runId) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chooses the expected artifact name, allowing one same-prefix fallback per run.
|
||||||
|
*/
|
||||||
export function resolveArtifactName(artifacts, preferredName, prefix) {
|
export function resolveArtifactName(artifacts, preferredName, prefix) {
|
||||||
const available = artifacts
|
const available = artifacts
|
||||||
.filter((artifact) => artifact.expired !== true)
|
.filter((artifact) => artifact.expired !== true)
|
||||||
@@ -312,6 +323,9 @@ function runLocalGeneratedCheckIfNeeded(options) {
|
|||||||
return { status: "passed", command: "pnpm release:generated:check" };
|
return { status: "passed", command: "pnpm release:generated:check" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts a GitHub Actions run id from gh workflow dispatch output.
|
||||||
|
*/
|
||||||
export function parseRunIdFromDispatchOutput(output) {
|
export function parseRunIdFromDispatchOutput(output) {
|
||||||
return output.match(/actions\/runs\/([0-9]+)/u)?.[1] ?? "";
|
return output.match(/actions\/runs\/([0-9]+)/u)?.[1] ?? "";
|
||||||
}
|
}
|
||||||
@@ -498,6 +512,9 @@ function shellQuote(value) {
|
|||||||
return `'${String(value).replace(/'/gu, "'\\''")}'`;
|
return `'${String(value).replace(/'/gu, "'\\''")}'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the final release publish workflow command once validation evidence is ready.
|
||||||
|
*/
|
||||||
export function buildPublishCommand(options) {
|
export function buildPublishCommand(options) {
|
||||||
const fields = [
|
const fields = [
|
||||||
["tag", options.tag],
|
["tag", options.tag],
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
// Checks or refreshes generated release artifacts before a release publish.
|
||||||
import { runManagedCommand } from "./lib/managed-child-process.mjs";
|
import { runManagedCommand } from "./lib/managed-child-process.mjs";
|
||||||
|
|
||||||
const args = new Set(process.argv.slice(2));
|
const args = new Set(process.argv.slice(2));
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// Resolves Docker upgrade-survivor baseline specs from requested tokens and
|
||||||
|
// live release history JSON captured by release workflows.
|
||||||
import { readFileSync, writeFileSync } from "node:fs";
|
import { readFileSync, writeFileSync } from "node:fs";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import { normalizeUpgradeSurvivorBaselineSpec } from "./lib/docker-e2e-plan.mjs";
|
import { normalizeUpgradeSurvivorBaselineSpec } from "./lib/docker-e2e-plan.mjs";
|
||||||
@@ -101,6 +103,9 @@ function readStableReleases(file, publishedVersions) {
|
|||||||
.toSorted((a, b) => String(b.publishedAt).localeCompare(String(a.publishedAt)));
|
.toSorted((a, b) => String(b.publishedAt).localeCompare(String(a.publishedAt)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands the release-history token into recent stable plus pinned historical baselines.
|
||||||
|
*/
|
||||||
export function resolveReleaseHistory(args) {
|
export function resolveReleaseHistory(args) {
|
||||||
const releasesJson = args.get("releases-json");
|
const releasesJson = args.get("releases-json");
|
||||||
if (!releasesJson) {
|
if (!releasesJson) {
|
||||||
@@ -128,6 +133,9 @@ export function resolveReleaseHistory(args) {
|
|||||||
return dedupeSpecs(versions);
|
return dedupeSpecs(versions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the last N stable release versions from release metadata.
|
||||||
|
*/
|
||||||
export function resolveLastStable(args, count) {
|
export function resolveLastStable(args, count) {
|
||||||
const releasesJson = args.get("releases-json");
|
const releasesJson = args.get("releases-json");
|
||||||
if (!releasesJson) {
|
if (!releasesJson) {
|
||||||
@@ -141,6 +149,9 @@ export function resolveLastStable(args, count) {
|
|||||||
return dedupeSpecs(releases.slice(0, count).map((release) => release.version));
|
return dedupeSpecs(releases.slice(0, count).map((release) => release.version));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves all stable release versions at or after the requested minimum.
|
||||||
|
*/
|
||||||
export function resolveAllSince(args, minimumVersion) {
|
export function resolveAllSince(args, minimumVersion) {
|
||||||
const releasesJson = args.get("releases-json");
|
const releasesJson = args.get("releases-json");
|
||||||
if (!releasesJson) {
|
if (!releasesJson) {
|
||||||
@@ -155,6 +166,9 @@ export function resolveAllSince(args, minimumVersion) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands requested baseline tokens into normalized package/version specs.
|
||||||
|
*/
|
||||||
export function resolveBaselines(args) {
|
export function resolveBaselines(args) {
|
||||||
const requested = args.get("requested") ?? "";
|
const requested = args.get("requested") ?? "";
|
||||||
const fallback = args.get("fallback") ?? "openclaw@latest";
|
const fallback = args.get("fallback") ?? "openclaw@latest";
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
// Audits root package runtime dependencies against source imports and bundled
|
||||||
|
// plugin ownership so extension-owned deps can move out of root.
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { pathToFileURL } from "node:url";
|
import { pathToFileURL } from "node:url";
|
||||||
@@ -79,6 +81,9 @@ function sectionFor(relativePath) {
|
|||||||
return section;
|
return section;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects static and simple constant-backed package specifiers from source text.
|
||||||
|
*/
|
||||||
export function collectModuleSpecifiers(source) {
|
export function collectModuleSpecifiers(source) {
|
||||||
const specifiers = new Set();
|
const specifiers = new Set();
|
||||||
for (const pattern of IMPORT_PATTERNS) {
|
for (const pattern of IMPORT_PATTERNS) {
|
||||||
@@ -210,6 +215,9 @@ function sectionSetIsSubsetOf(sectionSet, allowed) {
|
|||||||
return sectionSet.size > 0;
|
return sectionSet.size > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classifies whether a root dependency is core-owned, shared, or extension-local.
|
||||||
|
*/
|
||||||
export function classifyRootDependencyOwnership(record) {
|
export function classifyRootDependencyOwnership(record) {
|
||||||
const sections = new Set(record.sections);
|
const sections = new Set(record.sections);
|
||||||
|
|
||||||
@@ -276,6 +284,9 @@ export function classifyRootDependencyOwnership(record) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds dependency ownership records from root package.json and scanned imports.
|
||||||
|
*/
|
||||||
export function collectRootDependencyOwnershipAudit(params = {}) {
|
export function collectRootDependencyOwnershipAudit(params = {}) {
|
||||||
const repoRoot = path.resolve(params.repoRoot ?? process.cwd());
|
const repoRoot = path.resolve(params.repoRoot ?? process.cwd());
|
||||||
const rootPackageJson = readJson(path.join(repoRoot, "package.json"));
|
const rootPackageJson = readJson(path.join(repoRoot, "package.json"));
|
||||||
@@ -352,6 +363,9 @@ export function collectRootDependencyOwnershipAudit(params = {}) {
|
|||||||
.toSorted((left, right) => left.depName.localeCompare(right.depName));
|
.toSorted((left, right) => left.depName.localeCompare(right.depName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns actionable errors for dependencies that should not remain root-owned.
|
||||||
|
*/
|
||||||
export function collectRootDependencyOwnershipCheckErrors(records) {
|
export function collectRootDependencyOwnershipCheckErrors(records) {
|
||||||
return records
|
return records
|
||||||
.filter((record) => record.category === "extension_only_localizable")
|
.filter((record) => record.category === "extension_only_localizable")
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
// Runs additional architecture and boundary checks with sharding, concurrency,
|
||||||
|
// timeout handling, and grouped CI output.
|
||||||
import { spawn } from "node:child_process";
|
import { spawn } from "node:child_process";
|
||||||
import { performance } from "node:perf_hooks";
|
import { performance } from "node:perf_hooks";
|
||||||
|
|
||||||
@@ -6,6 +8,7 @@ const DEFAULT_CHECK_TIMEOUT_MS = 10 * 60 * 1000;
|
|||||||
const DEFAULT_OUTPUT_MAX_BYTES = 512 * 1024;
|
const DEFAULT_OUTPUT_MAX_BYTES = 512 * 1024;
|
||||||
const TIMEOUT_KILL_GRACE_MS = 5_000;
|
const TIMEOUT_KILL_GRACE_MS = 5_000;
|
||||||
|
|
||||||
|
/** Ordered list of supplemental boundary checks used by CI sharding. */
|
||||||
export const BOUNDARY_CHECKS = [
|
export const BOUNDARY_CHECKS = [
|
||||||
["prompt:snapshots:check", "pnpm", ["prompt:snapshots:check"]],
|
["prompt:snapshots:check", "pnpm", ["prompt:snapshots:check"]],
|
||||||
["plugin-extension-boundary", "pnpm", ["run", "lint:plugins:no-extension-imports"]],
|
["plugin-extension-boundary", "pnpm", ["run", "lint:plugins:no-extension-imports"]],
|
||||||
@@ -66,10 +69,16 @@ export const BOUNDARY_CHECKS = [
|
|||||||
["lint:ui:no-raw-window-open", "pnpm", ["lint:ui:no-raw-window-open"]],
|
["lint:ui:no-raw-window-open", "pnpm", ["lint:ui:no-raw-window-open"]],
|
||||||
].map(([label, command, args]) => ({ label, command, args }));
|
].map(([label, command, args]) => ({ label, command, args }));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the configured boundary-check concurrency.
|
||||||
|
*/
|
||||||
export function resolveConcurrency(value, fallback = 4, label = "concurrency") {
|
export function resolveConcurrency(value, fallback = 4, label = "concurrency") {
|
||||||
return resolvePositiveInteger(value, fallback, label);
|
return resolvePositiveInteger(value, fallback, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses positive integer CLI/env options with a fallback.
|
||||||
|
*/
|
||||||
export function resolvePositiveInteger(value, fallback, label = "value") {
|
export function resolvePositiveInteger(value, fallback, label = "value") {
|
||||||
if (value === undefined || value === null || value === "") {
|
if (value === undefined || value === null || value === "") {
|
||||||
return fallback;
|
return fallback;
|
||||||
@@ -85,6 +94,9 @@ export function resolvePositiveInteger(value, fallback, label = "value") {
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses one N/TOTAL shard selector into zero-based index form.
|
||||||
|
*/
|
||||||
export function parseShardSpec(value) {
|
export function parseShardSpec(value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return null;
|
return null;
|
||||||
@@ -107,6 +119,9 @@ export function parseShardSpec(value) {
|
|||||||
return { count, index: index - 1, label: `${index}/${count}` };
|
return { count, index: index - 1, label: `${index}/${count}` };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a comma-separated list of N/TOTAL shard selectors.
|
||||||
|
*/
|
||||||
export function parseShardSelection(value) {
|
export function parseShardSelection(value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return null;
|
return null;
|
||||||
@@ -124,6 +139,9 @@ export function parseShardSelection(value) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects checks whose ordinal belongs to the requested shard set.
|
||||||
|
*/
|
||||||
export function selectChecksForShard(checks, shardSpec) {
|
export function selectChecksForShard(checks, shardSpec) {
|
||||||
const shards =
|
const shards =
|
||||||
typeof shardSpec === "string"
|
typeof shardSpec === "string"
|
||||||
@@ -141,10 +159,16 @@ export function selectChecksForShard(checks, shardSpec) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a check command for CI group output.
|
||||||
|
*/
|
||||||
export function formatCommand({ command, args }) {
|
export function formatCommand({ command, args }) {
|
||||||
return [command, ...args].join(" ");
|
return [command, ...args].join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps only the tail of noisy check output so failure logs stay bounded.
|
||||||
|
*/
|
||||||
export function createBoundedOutputBuffer(maxBytes = DEFAULT_OUTPUT_MAX_BYTES) {
|
export function createBoundedOutputBuffer(maxBytes = DEFAULT_OUTPUT_MAX_BYTES) {
|
||||||
const limit = Math.max(1, maxBytes);
|
const limit = Math.max(1, maxBytes);
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
@@ -247,6 +271,9 @@ function installActiveChildCleanup(activeChildren) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs one boundary check with timeout and process-group termination.
|
||||||
|
*/
|
||||||
export function runSingleCheck(
|
export function runSingleCheck(
|
||||||
check,
|
check,
|
||||||
{
|
{
|
||||||
@@ -359,6 +386,9 @@ function writeTimingSummary(results, output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs boundary checks with bounded concurrency and returns the failure count.
|
||||||
|
*/
|
||||||
export async function runChecks(
|
export async function runChecks(
|
||||||
checks = BOUNDARY_CHECKS,
|
checks = BOUNDARY_CHECKS,
|
||||||
{
|
{
|
||||||
@@ -442,11 +472,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
|||||||
process.env.OPENCLAW_ADDITIONAL_BOUNDARY_CONCURRENCY === undefined
|
process.env.OPENCLAW_ADDITIONAL_BOUNDARY_CONCURRENCY === undefined
|
||||||
? "OPENCLAW_EXTENSION_BOUNDARY_CONCURRENCY"
|
? "OPENCLAW_EXTENSION_BOUNDARY_CONCURRENCY"
|
||||||
: "OPENCLAW_ADDITIONAL_BOUNDARY_CONCURRENCY";
|
: "OPENCLAW_ADDITIONAL_BOUNDARY_CONCURRENCY";
|
||||||
const concurrency = resolveConcurrency(
|
const concurrency = resolveConcurrency(concurrencyRaw, 4, concurrencyLabel);
|
||||||
concurrencyRaw,
|
|
||||||
4,
|
|
||||||
concurrencyLabel,
|
|
||||||
);
|
|
||||||
const checkTimeoutMs = resolvePositiveInteger(
|
const checkTimeoutMs = resolvePositiveInteger(
|
||||||
process.env.OPENCLAW_ADDITIONAL_BOUNDARY_TIMEOUT_MS,
|
process.env.OPENCLAW_ADDITIONAL_BOUNDARY_TIMEOUT_MS,
|
||||||
DEFAULT_CHECK_TIMEOUT_MS,
|
DEFAULT_CHECK_TIMEOUT_MS,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Runs oxlint over bundled plugin source files using the shared extension lint runner.
|
||||||
import { runExtensionOxlint } from "./lib/run-extension-oxlint.mjs";
|
import { runExtensionOxlint } from "./lib/run-extension-oxlint.mjs";
|
||||||
|
|
||||||
runExtensionOxlint({
|
runExtensionOxlint({
|
||||||
|
|||||||
Reference in New Issue
Block a user