Skip to content

Commit b661481

Browse files
committed
fix: address SonarQube code quality issues
- Move workflow permissions to job level in ci.yml - Simplify regex patterns in edge builders - Remove pip-audit from pre-commit hooks - Fix unused variables and parameters - Extract terraform.py nested conditional - Add constant for kubernetes.py yaml extensions - Fix test assertions and exception handling
1 parent 68c9822 commit b661481

14 files changed

Lines changed: 40 additions & 35 deletions

File tree

.github/workflows/ci.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
# .github/workflows/ci.yml
22
name: treemapper CI
33

4-
permissions:
5-
contents: read
6-
74
'on':
85
pull_request:
96
branches: ['**']
@@ -18,6 +15,8 @@ jobs:
1815
pre-commit:
1916
name: Pre-commit hooks
2017
runs-on: ubuntu-latest
18+
permissions:
19+
contents: read
2120
steps:
2221
- uses: actions/checkout@v6
2322

@@ -46,6 +45,8 @@ jobs:
4645
lint-type-check:
4746
name: Lint & Type Check
4847
runs-on: ubuntu-latest
48+
permissions:
49+
contents: read
4950
steps:
5051
- name: Checkout Code
5152
uses: actions/checkout@v6
@@ -89,6 +90,8 @@ jobs:
8990
python-version: ['3.10', '3.11', '3.12', '3.13']
9091

9192
runs-on: ${{ matrix.os }}
93+
permissions:
94+
contents: read
9295

9396
steps:
9497
- name: Checkout Code
@@ -149,6 +152,8 @@ jobs:
149152
test-pypy:
150153
needs: [pre-commit, lint-type-check]
151154
runs-on: ubuntu-latest
155+
permissions:
156+
contents: read
152157
strategy:
153158
fail-fast: false
154159
matrix:
@@ -187,6 +192,8 @@ jobs:
187192
mutation-testing:
188193
name: Mutation Testing
189194
runs-on: ubuntu-latest
195+
permissions:
196+
contents: read
190197
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
191198

192199
steps:
@@ -217,6 +224,8 @@ jobs:
217224
complexity-checks:
218225
name: Complexity & Maintainability Analysis
219226
runs-on: ubuntu-latest
227+
permissions:
228+
contents: read
220229

221230
steps:
222231
- uses: actions/checkout@v6
@@ -253,6 +262,8 @@ jobs:
253262
architecture-checks:
254263
name: Architecture & Import Contracts
255264
runs-on: ubuntu-latest
265+
permissions:
266+
contents: read
256267

257268
steps:
258269
- uses: actions/checkout@v6

src/treemapper/diffctx/edges/config/build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
_MAKEFILE_NAMES = {"makefile", "gnumakefile"}
1010
_MAKEFILE_EXTS = {".mk", ".mak", ".make"}
1111

12-
_MAKE_TARGET_RE = re.compile(r"^([a-zA-Z_][a-zA-Z0-9_.-]*)(?:\s*:(?!=))", re.MULTILINE)
12+
_MAKE_TARGET_RE = re.compile(r"^([a-zA-Z_][a-zA-Z0-9_.-]*)\s*:(?!=)", re.MULTILINE)
1313
_MAKE_INCLUDE_RE = re.compile(r"^(?:-)?include\s+(.+)$", re.MULTILINE)
1414
_MAKE_VAR_RE = re.compile(r"^\s*([A-Z_][A-Z0-9_]*)\s*[:?]?=", re.MULTILINE)
1515
_MAKE_RECIPE_RE = re.compile(r"^\t(.+)$", re.MULTILINE)

src/treemapper/diffctx/edges/config/cicd.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
from ...types import Fragment
77
from ..base import EdgeBuilder, EdgeDict, FragmentIndex, discover_files_by_refs
88

9-
_GHA_RUN_RE = re.compile(r"^\s*-?\s*run:\s*[|>]?\s*(.+?)(?:\n\s{4,}|\n[^\s]|$)", re.MULTILINE | re.DOTALL)
9+
_GHA_RUN_RE = re.compile(r"^\s*-?\s*run:\s*[|>]?\s*(.+)(?:\n\s{4,}|\n[^\s]|$)", re.MULTILINE | re.DOTALL)
1010

1111
_GITLAB_SCRIPT_RE = re.compile(r"^\s*(?:script|before_script|after_script):\s*\n((?:\s+-\s*.+\n)+)", re.MULTILINE)
1212
_GITLAB_INCLUDE_RE = re.compile(r"^\s*-?\s*(?:local|project|remote|template):\s*['\"]?([^'\"#\n]+)", re.MULTILINE)
1313

14-
_JENKINS_SH_RE = re.compile(r"sh\s*(?:\(['\"]|['\"])(.+?)(?:['\"])\)?", re.MULTILINE | re.DOTALL)
14+
_JENKINS_SH_RE = re.compile(r"sh\s*(?:\(['\"]|['\"])(.+?)['\"]\)?", re.MULTILINE | re.DOTALL)
1515
_JENKINS_SCRIPT_RE = re.compile(r"script\s*\{([^}]+)\}", re.MULTILINE | re.DOTALL)
1616

1717
_SCRIPT_CALL_RE = re.compile(r"(?:bash|sh|python|python3|node|npm|yarn|pnpm|make|go|cargo|dotnet|mvn|gradle)\s+([^\s;&|]+)")
@@ -154,8 +154,6 @@ def build(self, fragments: list[Fragment], repo_root: Path | None = None) -> Edg
154154
idx = FragmentIndex(fragments, repo_root)
155155

156156
for ci in ci_frags:
157-
refs: set[str] = set()
158-
159157
if _is_github_actions(ci.path):
160158
refs = _extract_gha_refs(ci.content)
161159
elif _is_gitlab_ci(ci.path):

src/treemapper/diffctx/edges/config/kubernetes.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
_VOLUME_SECRET_RE = re.compile(r"secret:\s*\n\s+secretName:\s*['\"]?([^'\"#\n]+)", re.MULTILINE)
3232
_VOLUME_PVC_RE = re.compile(r"persistentVolumeClaim:\s*\n\s+claimName:\s*['\"]?([^'\"#\n]+)", re.MULTILINE)
3333

34+
_YAML_EXTS = {".yaml", ".yml"}
35+
3436
_K8S_KINDS = {
3537
"Deployment",
3638
"Service",
@@ -57,7 +59,7 @@
5759

5860

5961
def _is_kubernetes_manifest(path: Path, content: str | None = None) -> bool:
60-
if path.suffix.lower() not in {".yaml", ".yml"}:
62+
if path.suffix.lower() not in _YAML_EXTS:
6163
return False
6264

6365
if content is None:
@@ -132,7 +134,7 @@ def discover_related_files(
132134
) -> list[Path]:
133135
k8s_files: list[Path] = []
134136
for f in changed_files:
135-
if f.suffix.lower() in {".yaml", ".yml"}:
137+
if f.suffix.lower() in _YAML_EXTS:
136138
try:
137139
content = f.read_text(encoding="utf-8")
138140
if _is_kubernetes_manifest(f, content):
@@ -156,7 +158,7 @@ def discover_related_files(
156158
if candidate in changed_set:
157159
continue
158160

159-
if candidate.suffix.lower() not in {".yaml", ".yml"}:
161+
if candidate.suffix.lower() not in _YAML_EXTS:
160162
continue
161163

162164
for k8s_dir in k8s_dirs:
@@ -215,7 +217,7 @@ def build(self, fragments: list[Fragment], repo_root: Path | None = None) -> Edg
215217
self._build_configmap_edges(frag, configmaps, edges)
216218
self._build_secret_edges(frag, secrets, edges)
217219
self._build_service_edges(frag, services, edges)
218-
self._build_volume_edges(frag, configmaps, secrets, pvcs, edges)
220+
self._build_volume_edges(frag, pvcs, edges)
219221
self._build_selector_edges(frag, pods_with_labels, edges)
220222
self._build_image_edges(frag, images, edges)
221223

@@ -290,8 +292,6 @@ def _build_service_edges(
290292
def _build_volume_edges(
291293
self,
292294
frag: Fragment,
293-
configmaps: dict[str, list[FragmentId]],
294-
secrets: dict[str, list[FragmentId]],
295295
pvcs: dict[str, list[FragmentId]],
296296
edges: EdgeDict,
297297
) -> None:

src/treemapper/diffctx/edges/config/terraform.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,12 @@ def _build_module_source_edges(
202202
module_dir = (base_dir / source).resolve()
203203
for p, frag_ids in path_to_frags.items():
204204
try:
205-
resolved = p.resolve() if p.is_absolute() else (repo_root / p).resolve() if repo_root else p
205+
if p.is_absolute():
206+
resolved = p.resolve()
207+
elif repo_root:
208+
resolved = (repo_root / p).resolve()
209+
else:
210+
resolved = p
206211
if resolved.parent == module_dir or str(resolved).startswith(str(module_dir)):
207212
for frag_id in frag_ids:
208213
if frag_id != f.id:

src/treemapper/diffctx/edges/semantic/dotnet.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
r"^\s*(?:public|private|protected|internal)?\s*(?:static|sealed|abstract|partial)?\s*(?:class|interface|struct|record|enum)\s+([A-Z]\w*)",
1818
re.MULTILINE,
1919
)
20-
_CS_INHERIT_RE = re.compile(r"(?:class|interface|struct|record)\s+\w+\s*(?:<[^>]+>)?\s*:\s*([A-Z]\w*(?:\s*,\s*[A-Z]\w*)*)")
20+
_CS_INHERIT_RE = re.compile(r"(?:class|struct|record)\s+\w+[^:]*:\s*([A-Z]\w*(?:,\s*[A-Z]\w*)*)")
2121
_CS_GENERIC_RE = re.compile(r"<([A-Z]\w*(?:\s*,\s*[A-Z]\w*)*)>")
2222
_CS_METHOD_RE = re.compile(
23-
r"^\s*(?:public|private|protected|internal)?\s*(?:static|virtual|override|abstract|async)?\s*(?:[A-Z]\w*(?:<[^>]+>)?)\s+([A-Z]\w*)\s*\(",
23+
r"^\s*(?:public|private|protected|internal)?\s*\w*\s*[A-Z]\w*(?:<[^>]+>)?\s+([A-Z]\w*)\s*\(",
2424
re.MULTILINE,
2525
)
2626

src/treemapper/diffctx/edges/semantic/javascript.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
_JS_SYMBOL_REF_WEIGHT = 0.75
1515
_JS_TYPE_REF_WEIGHT = 0.65
1616

17-
_JS_IMPORT_RE = re.compile(r"""(?:import\s+(?:.*?\s+from\s+)?['"]([^'"]+)['"]|require\s*\(\s*['"]([^'"]+)['"]\s*\))""")
17+
_JS_IMPORT_RE = re.compile(r"""import\s+[^'"]*['"]([^'"]+)['"]|require\s*\(\s*['"]([^'"]+)['"]\s*\)""")
1818
_JS_EXPORT_FROM_RE = re.compile(r"""export\s+.*?\s+from\s+['"]([^'"]+)['"]""")
1919

2020

src/treemapper/diffctx/edges/semantic/jvm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
_KOTLIN_IMPORT_RE = re.compile(r"^\s*import\s+([a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*(?:\.[A-Z]\w*)?)", re.MULTILINE)
2424
_KOTLIN_CLASS_RE = re.compile(
25-
r"^\s*(?:public|private|internal|protected)?\s*(?:abstract|open|sealed|data|inline|value)?\s*(?:class|interface|object|enum)\s+([A-Z]\w*)",
25+
r"^\s*(?:\w+\s+)*(?:class|interface|object|enum)\s+([A-Z]\w*)",
2626
re.MULTILINE,
2727
)
2828
_KOTLIN_FUN_RE = re.compile(

src/treemapper/diffctx/edges/semantic/ruby.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
_RUBY_INHERIT_RE = re.compile(r"class\s+\w+\s*<\s*([A-Z]\w*(?:::[A-Z]\w*)*)")
2323

2424
_RUBY_CONST_REF_RE = re.compile(r"(?<![a-z_])([A-Z]\w*(?:::[A-Z]\w*)*)")
25-
_RUBY_METHOD_CALL_RE = re.compile(r"\.([a-z_]\w*)\s*(?:\(|$|[^a-z_])")
25+
_RUBY_METHOD_CALL_RE = re.compile(r"\.([a-z_]\w*)\s*(?:$|[^a-z_])")
2626

2727

2828
def _is_ruby_file(path: Path) -> bool:

src/treemapper/diffctx/edges/semantic/rust.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
_RUST_STRUCT_RE = re.compile(r"^\s*(?:pub(?:\([^)]*\))?\s+)?struct\s+([A-Z]\w*)", re.MULTILINE)
1616
_RUST_ENUM_RE = re.compile(r"^\s*(?:pub(?:\([^)]*\))?\s+)?enum\s+([A-Z]\w*)", re.MULTILINE)
1717
_RUST_TRAIT_RE = re.compile(r"^\s*(?:pub(?:\([^)]*\))?\s+)?trait\s+([A-Z]\w*)", re.MULTILINE)
18-
_RUST_IMPL_RE = re.compile(r"^\s*impl(?:<[^>]+>)?\s+(?:([A-Z]\w*)|(?:\w+\s+for\s+)?([A-Z]\w*))", re.MULTILINE)
18+
_RUST_IMPL_RE = re.compile(r"^\s*impl(?:<[^>]+>)?\s+(?:\w+\s+for\s+)?([A-Z]\w*)", re.MULTILINE)
1919
_RUST_TYPE_ALIAS_RE = re.compile(r"^\s*(?:pub(?:\([^)]*\))?\s+)?type\s+([A-Z]\w*)", re.MULTILINE)
2020

2121
_RUST_TYPE_REF_RE = re.compile(r"(?<![a-z_])([A-Z]\w*)\b")
@@ -53,8 +53,6 @@ def _extract_definitions(content: str) -> tuple[set[str], set[str], set[str]]:
5353
for m in _RUST_IMPL_RE.finditer(content):
5454
if m.group(1):
5555
types.add(m.group(1))
56-
if m.group(2):
57-
types.add(m.group(2))
5856

5957
traits = {m.group(1) for m in _RUST_TRAIT_RE.finditer(content)}
6058
return funcs, types, traits

0 commit comments

Comments
 (0)