Skip to content

Commit 079330f

Browse files
dguidoclaude
andauthored
feat: add --foundry-deny flag to control forge diagnostic errors (#637)
* feat: add --foundry-deny flag to control forge diagnostic errors Forge's linter returns exit code 1 on warnings, causing crytic-compile to interpret this as a compilation failure even when Solidity compilation succeeded. This breaks analysis of many Foundry projects that have linter warnings. - Add `--deny never` to forge build command by default - Add `--foundry-deny` flag to allow users to override if needed Co-Authored-By: Claude Opus 4.5 <[email protected]> * feat: add version detection for --deny flag (Foundry 1.4+) The --deny flag is only available in Foundry 1.4+. This change: - Adds version detection for forge - Only adds --deny when forge >= 1.4.0 - Changes default from "never" to None (auto-detect) - Updates help text to reflect auto-detection behavior Co-Authored-By: Claude Opus 4.5 <[email protected]> --------- Co-authored-by: Claude Opus 4.5 <[email protected]>
1 parent f0e771f commit 079330f

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

crytic_compile/cryticparser/cryticparser.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,3 +465,11 @@ def _init_foundry(parser: ArgumentParser) -> None:
465465
dest="foundry_compile_all",
466466
default=DEFAULTS_FLAG_IN_CONFIG["foundry_compile_all"],
467467
)
468+
469+
group_foundry.add_argument(
470+
"--foundry-deny",
471+
help="Forge diagnostic level to deny (never, warn, all). Auto-detected for Foundry 1.4+",
472+
action="store",
473+
dest="foundry_deny",
474+
default=DEFAULTS_FLAG_IN_CONFIG["foundry_deny"],
475+
)

crytic_compile/cryticparser/defaults.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"foundry_out_directory": None,
4747
"foundry_build_info_directory": None,
4848
"foundry_compile_all": False,
49+
"foundry_deny": None,
4950
"export_dir": "crytic-export",
5051
"compile_libraries": None,
5152
}

crytic_compile/platform/foundry.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import json
66
import logging
7+
import re
78
import subprocess
89
from pathlib import Path
910
from typing import TYPE_CHECKING, TypeVar
@@ -22,6 +23,28 @@
2223
LOGGER = logging.getLogger("CryticCompile")
2324

2425

26+
def _get_forge_version() -> tuple[int, int, int] | None:
27+
"""Get forge version as tuple, or None if unable to parse.
28+
29+
Returns:
30+
Version tuple (major, minor, patch) or None if detection fails.
31+
"""
32+
try:
33+
result = subprocess.run(
34+
["forge", "--version"],
35+
capture_output=True,
36+
text=True,
37+
timeout=10,
38+
)
39+
versions = re.findall(r"\d+\.\d+\.\d+", result.stdout)
40+
if versions:
41+
parts = versions[0].split(".")
42+
return (int(parts[0]), int(parts[1]), int(parts[2]))
43+
except Exception: # noqa: BLE001
44+
pass
45+
return None
46+
47+
2548
class Foundry(AbstractPlatform):
2649
"""
2750
Foundry platform
@@ -45,7 +68,7 @@ def compile(self, crytic_compile: "CryticCompile", **kwargs: str) -> None:
4568
Args:
4669
crytic_compile (CryticCompile): CryticCompile object to populate
4770
**kwargs: optional arguments. Used: "foundry_ignore_compile", "foundry_out_directory",
48-
"foundry_build_info_directory"
71+
"foundry_build_info_directory", "foundry_deny"
4972
5073
"""
5174

@@ -60,12 +83,21 @@ def compile(self, crytic_compile: "CryticCompile", **kwargs: str) -> None:
6083
"--ignore-compile used, if something goes wrong, consider removing the ignore compile flag"
6184
)
6285
else:
86+
deny_level = kwargs.get("foundry_deny")
87+
if deny_level is None:
88+
forge_version = _get_forge_version()
89+
if forge_version and forge_version >= (1, 4, 0):
90+
deny_level = "never"
91+
6392
compilation_command = [
6493
"forge",
6594
"build",
6695
"--build-info",
6796
]
6897

98+
if deny_level:
99+
compilation_command.extend(["--deny", deny_level])
100+
69101
targeted_build = not self._project_root.samefile(self._target)
70102
if targeted_build:
71103
compilation_command += [

0 commit comments

Comments
 (0)