refactor: cut cyclomatic complexity of five hot spots and pin their behavior with tests
Risk labels, menu callback parsing, settings callbacks, table cell width and markdown link targets now use tables and small helpers (CC <= 10).
This commit is contained in:
1 parent
bf4a2021e8
commit
6a6e75fe32
8 files changed
+648
-294
No files matched your search
+110
-66
@@ -223,76 +223,120 @@ function hasSecretTouchingText(parts: string[]): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
interface CommandTemplateRiskContext {
|
||||
command: string;
|
||||
args: string[];
|
||||
parts: string[];
|
||||
}
|
||||
|
||||
const COMMAND_TEMPLATE_NETWORK_EXECUTABLES = [
|
||||
"curl",
|
||||
"wget",
|
||||
"ssh",
|
||||
"scp",
|
||||
"sftp",
|
||||
"rsync",
|
||||
"nc",
|
||||
"ncat",
|
||||
"telnet",
|
||||
"ftp",
|
||||
];
|
||||
|
||||
const COMMAND_TEMPLATE_PLATFORM_EXECUTABLES = [
|
||||
"systemctl",
|
||||
"launchctl",
|
||||
"osascript",
|
||||
"open",
|
||||
"xdg-open",
|
||||
"powershell",
|
||||
"pwsh",
|
||||
"cmd.exe",
|
||||
"apt",
|
||||
"apt-get",
|
||||
"dnf",
|
||||
"yum",
|
||||
"brew",
|
||||
"pacman",
|
||||
"apk",
|
||||
"xclip",
|
||||
"wl-copy",
|
||||
];
|
||||
|
||||
const COMMAND_TEMPLATE_RISK_RULES: Array<
|
||||
[CommandTemplateRiskLabel, (context: CommandTemplateRiskContext) => boolean]
|
||||
> = [
|
||||
["risk.shell", ({ command }) => ["bash", "sh", "zsh", "fish"].includes(command)],
|
||||
[
|
||||
"risk.eval",
|
||||
({ command, args }) =>
|
||||
(["bash", "sh", "zsh", "fish"].includes(command) &&
|
||||
hasAnyFlag(args, ["-c"])) ||
|
||||
(["node", "deno", "bun"].includes(command) &&
|
||||
hasAnyFlag(args, ["-e", "--eval"])) ||
|
||||
(["python", "python3", "perl", "ruby"].includes(command) &&
|
||||
hasAnyFlag(args, ["-c", "-e"])),
|
||||
],
|
||||
[
|
||||
"risk.destructive_fs",
|
||||
({ command, args }) =>
|
||||
command === "rm" &&
|
||||
(args.some((arg) => /^-[^-]*[rf]/.test(arg)) || hasRiskyPathArg(args)),
|
||||
],
|
||||
[
|
||||
"risk.broad_fs_write",
|
||||
({ command, args }) =>
|
||||
["mv", "cp", "rsync"].includes(command) && hasRiskyPathArg(args),
|
||||
],
|
||||
[
|
||||
"risk.network",
|
||||
({ command, args }) =>
|
||||
COMMAND_TEMPLATE_NETWORK_EXECUTABLES.includes(command) ||
|
||||
(command === "git" &&
|
||||
hasAnyArg(args, ["clone", "fetch", "pull", "push", "ls-remote"])) ||
|
||||
["npm", "pnpm", "yarn", "pip", "cargo"].includes(command),
|
||||
],
|
||||
[
|
||||
"risk.external_side_effect",
|
||||
({ command, args }) =>
|
||||
["gh", "glab", "hub", "kubectl", "terraform"].includes(command) ||
|
||||
(command === "git" && hasAnyArg(args, ["push"])) ||
|
||||
(["npm", "pnpm", "yarn"].includes(command) &&
|
||||
hasAnyArg(args, ["publish", "login", "logout", "deprecate"])),
|
||||
],
|
||||
[
|
||||
"risk.long_running",
|
||||
({ command, args }) =>
|
||||
command === "sleep" ||
|
||||
command === "watch" ||
|
||||
(command === "tail" && hasAnyFlag(args, ["-f"])) ||
|
||||
hasAnyArg(args, ["--watch", "--serve", "serve"]),
|
||||
],
|
||||
[
|
||||
"risk.platform_specific",
|
||||
({ command }) => COMMAND_TEMPLATE_PLATFORM_EXECUTABLES.includes(command),
|
||||
],
|
||||
[
|
||||
"risk.secret_touching",
|
||||
({ command, parts }) =>
|
||||
["pass", "gpg", "ssh-add"].includes(command) ||
|
||||
hasSecretTouchingText(parts),
|
||||
],
|
||||
];
|
||||
|
||||
function getLeafCommandTemplateRiskLabels(
|
||||
config: CommandTemplateLeafConfig,
|
||||
): CommandTemplateRiskLabel[] {
|
||||
const parts = splitCommandTemplate(config.template);
|
||||
const command = getExecutableName(parts[0]);
|
||||
const args = parts.slice(1);
|
||||
const labels = new Set<CommandTemplateRiskLabel>();
|
||||
if (["bash", "sh", "zsh", "fish"].includes(command)) {
|
||||
labels.add("risk.shell");
|
||||
if (hasAnyFlag(args, ["-c"])) labels.add("risk.eval");
|
||||
}
|
||||
if (
|
||||
["node", "deno", "bun"].includes(command) &&
|
||||
hasAnyFlag(args, ["-e", "--eval"])
|
||||
) {
|
||||
labels.add("risk.eval");
|
||||
}
|
||||
if (
|
||||
["python", "python3", "perl", "ruby"].includes(command) &&
|
||||
hasAnyFlag(args, ["-c", "-e"])
|
||||
) {
|
||||
labels.add("risk.eval");
|
||||
}
|
||||
if (
|
||||
command === "rm" &&
|
||||
(args.some((arg) => /^-[^-]*r/.test(arg) || /^-[^-]*f/.test(arg)) ||
|
||||
hasRiskyPathArg(args))
|
||||
) {
|
||||
labels.add("risk.destructive_fs");
|
||||
}
|
||||
if (["mv", "cp", "rsync"].includes(command) && hasRiskyPathArg(args)) {
|
||||
labels.add("risk.broad_fs_write");
|
||||
}
|
||||
if (
|
||||
["curl", "wget", "ssh", "scp", "sftp", "rsync", "nc", "ncat", "telnet", "ftp"].includes(
|
||||
command,
|
||||
) ||
|
||||
(command === "git" &&
|
||||
hasAnyArg(args, ["clone", "fetch", "pull", "push", "ls-remote"])) ||
|
||||
["npm", "pnpm", "yarn", "pip", "cargo"].includes(command)
|
||||
) {
|
||||
labels.add("risk.network");
|
||||
}
|
||||
if (
|
||||
["gh", "glab", "hub", "kubectl", "terraform"].includes(command) ||
|
||||
(command === "git" && hasAnyArg(args, ["push"])) ||
|
||||
(["npm", "pnpm", "yarn"].includes(command) &&
|
||||
hasAnyArg(args, ["publish", "login", "logout", "deprecate"]))
|
||||
) {
|
||||
labels.add("risk.external_side_effect");
|
||||
}
|
||||
if (
|
||||
command === "sleep" ||
|
||||
command === "watch" ||
|
||||
(command === "tail" && hasAnyFlag(args, ["-f"])) ||
|
||||
hasAnyArg(args, ["--watch", "--serve", "serve"])
|
||||
) {
|
||||
labels.add("risk.long_running");
|
||||
}
|
||||
if (
|
||||
["systemctl", "launchctl", "osascript", "open", "xdg-open", "powershell", "pwsh", "cmd.exe", "apt", "apt-get", "dnf", "yum", "brew", "pacman", "apk", "xclip", "wl-copy"].includes(
|
||||
command,
|
||||
)
|
||||
) {
|
||||
labels.add("risk.platform_specific");
|
||||
}
|
||||
if (["pass", "gpg", "ssh-add"].includes(command) || hasSecretTouchingText(parts)) {
|
||||
labels.add("risk.secret_touching");
|
||||
}
|
||||
return sortRiskLabels(labels);
|
||||
const context: CommandTemplateRiskContext = {
|
||||
command: getExecutableName(parts[0]),
|
||||
args: parts.slice(1),
|
||||
parts,
|
||||
};
|
||||
return sortRiskLabels(
|
||||
COMMAND_TEMPLATE_RISK_RULES.filter(([, matches]) => matches(context)).map(
|
||||
([label]) => label,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function getLeafCommandTemplateWarnings(
|
||||
|
||||
Reference in new issue
Block a user