Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .codacy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
#
# Recommended enabled tools:
# - markdownlint: documentation linting
# - opengrep: repository-owned Rust Semgrep rules from .semgrep.yaml
# - ruff: Python utility linting
# - shellcheck: shell-script linting
# - duplication: advisory duplicate-code metric
# - lizard: advisory complexity feedback
#
# Recommended disabled tools:
# - bandit, prospector, pylintpython3: redundant with Ruff/ty for this repo
# - opengrep: keep broad/default rules disabled until repo-owned rules in
# .semgrep.yaml are cleaned up and enabled
# - trivy: dependency vulnerability scanning is handled by cargo-audit and
# Dependabot unless this repository adds containers or IaC
# - jacksonlinter, spectral: not relevant to the current project surface
Expand Down Expand Up @@ -50,6 +49,9 @@ engines:
- "**/*.md"
config:
file: ".markdownlint.json"
opengrep:
include_paths:
- "src/**/*.rs"
ruff:
include_paths:
- "scripts/**/*.py"
Expand Down
7 changes: 3 additions & 4 deletions .coderabbit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,10 @@ reviews:
yamllint:
enabled: true

# Semantic code analysis is intentionally disabled until the staged,
# repository-owned rules in .semgrep.yaml are enabled after legacy cleanup.
# Default Semgrep packs are noisy here and duplicate CodeQL/cargo-audit.
# Semantic code analysis uses only the focused, repository-owned rules in
# .semgrep.yaml. Default Semgrep packs remain disabled in CodeRabbit.
semgrep:
enabled: false
enabled: true
Comment on lines +109 to +112
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name ".semgrep.yaml" -o -name "semgrep.yaml" -o -name "semgrep.yml" -o -name "semgrep.config.yml" -o -name "semgrep.config.yaml" 2>/dev/null | head -20

Repository: acgetchell/delaunay

Length of output: 79


🌐 Web query:

CodeRabbit Semgrep config file auto-discovery behavior documentation

💡 Result:

CodeRabbit's Semgrep config file auto-discovery behavior is documented in the official docs at https://docs.coderabbit.ai/tools/semgrep. By default, CodeRabbit automatically uses Semgrep config files named semgrep.yml, semgrep.yaml, semgrep.config.yml, or semgrep.config.yaml if present in the root directory of the repository. Semgrep only runs if a config file is found using these default names, or if a custom path is explicitly specified via: - reviews.tools.semgrep.config_file in the repository's .coderabbit.yaml file, or - The "Reviews → Tools → Semgrep → Config File" field in CodeRabbit's web settings UI. Due to licensing restrictions, CodeRabbit does not include community Semgrep rules and requires a user-provided config with rules. Note that the related OpenGrep tool (Semgrep-compatible) has a broader fallback search order including Semgrep files, starting from repo root and PR-changed files, then broader search—but Semgrep itself sticks to root defaults or explicit paths.

Citations:


Add config_file: .semgrep.yaml to enable Semgrep with repository-owned rules.

CodeRabbit auto-discovers only semgrep.yml, semgrep.yaml, semgrep.config.yml, and semgrep.config.yaml. This repository uses .semgrep.yaml, which falls outside the auto-discovery pattern. Setting enabled: true alone will not load your repository-owned rules. Explicitly specify the config file path to enable Semgrep properly.

Suggested fix
     semgrep:
       enabled: true
+      config_file: .semgrep.yaml
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Semantic code analysis uses only the focused, repository-owned rules in
# .semgrep.yaml. Default Semgrep packs remain disabled in CodeRabbit.
semgrep:
enabled: false
enabled: true
# Semantic code analysis uses only the focused, repository-owned rules in
# .semgrep.yaml. Default Semgrep packs remain disabled in CodeRabbit.
semgrep:
enabled: true
config_file: .semgrep.yaml
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.coderabbit.yml around lines 109 - 112, Add the repository-owned Semgrep
config path under the existing semgrep section so CodeRabbit loads
.semgrep.yaml: in the .coderabbit.yml semgrep block (the keys "semgrep" and
"enabled") add a "config_file: .semgrep.yaml" entry alongside enabled: true to
explicitly point CodeRabbit to the repository's Semgrep rules file.


# Python linter (ruff provides comprehensive Python analysis)
ruff:
Expand Down
26 changes: 16 additions & 10 deletions .github/workflows/codacy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
# separate terms of service, privacy policy, and support
# documentation.

# This workflow checks out code, runs Codacy's Markdownlint engine only, and
# integrates the results with GitHub Advanced Security code scanning.
# This workflow checks out code, runs selected Codacy engines, and integrates
# the results with GitHub Advanced Security code scanning.
# For more information on the Codacy analysis action usage and
# parameters, see https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.

name: Codacy Markdownlint Scan
name: Codacy Quality Scan

concurrency:
# This concurrency group ensures that only one Codacy analysis runs at a time
Expand All @@ -30,7 +30,7 @@ permissions:
contents: read

jobs:
codacy-markdownlint-scan:
codacy-quality-scan:
permissions:
# for actions/checkout to fetch code
contents: read
Expand All @@ -39,9 +39,15 @@ jobs:
# only required for a private repository by
# github/codeql-action/upload-sarif to get the Action run status
actions: read
name: Codacy Markdownlint Scan
name: Codacy ${{ matrix.tool }} Scan
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
tool:
- markdownlint
- opengrep
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
Expand All @@ -51,17 +57,17 @@ jobs:
run: |
set -euo pipefail
echo "CODACY_WORKDIR=$RUNNER_TEMP/codacy-src" >> "$GITHUB_ENV"
echo "CODACY_SARIF=$RUNNER_TEMP/results.sarif" >> "$GITHUB_ENV"
echo "CODACY_SARIF=$RUNNER_TEMP/results-${{ matrix.tool }}.sarif" >> "$GITHUB_ENV"

- name: Prepare workspace copy without .git
run: |
set -euo pipefail
mkdir -p "$CODACY_WORKDIR"
rsync -a --delete --exclude '.git' ./ "$CODACY_WORKDIR/"

# Execute Codacy Analysis CLI with a single tool. The Codacy GitHub App may
# run curated PR-quality tools, but this SARIF workflow stays Markdownlint
# only so maintainability checks are not mirrored into GitHub Code Scanning.
# Execute Codacy Analysis CLI with one selected tool per matrix entry.
# Opengrep reads the repository-owned rules from .semgrep.yaml; broad
# default Semgrep/Opengrep packs remain disabled.
- name: Run Codacy Analysis CLI
# Cap Codacy runtime so a hung analyzer does not consume the full job timeout.
timeout-minutes: 20
Expand All @@ -76,7 +82,7 @@ jobs:
directory: ${{ env.CODACY_WORKDIR }}
output: ${{ env.CODACY_SARIF }}
format: sarif
tool: markdownlint
tool: ${{ matrix.tool }}
skip-uncommitted-files-check: true
# Adjust severity of non-security issues
gh-code-scanning-compat: true
Expand Down
167 changes: 158 additions & 9 deletions .semgrep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
# been noisy for this Rust library and duplicate CodeQL, cargo-audit, Clippy,
# Ruff, and ShellCheck coverage.
#
# The rules below are intentionally disabled with an impossible include path
# while legacy call sites are cleaned up in
# https://github.com/acgetchell/delaunay/issues/338. To enable one, replace its
# "__semgrep_disabled__/**" include with the intended path such as "src/**/*.rs"
# and remove the "enabled: false" metadata note.
# These rules encode repository-specific Rust invariants. Keep them focused so
# local and CodeRabbit Semgrep runs stay low-noise.

rules:
- id: delaunay.rust.no-stdio-diagnostics-in-src
Expand All @@ -18,13 +15,12 @@ rules:
severity: WARNING
message: "Use tracing macros for production diagnostics instead of stdout/stderr macros."
metadata:
enabled: false
category: maintainability
tracking_issue: "https://github.com/acgetchell/delaunay/issues/338"
rationale: "Runtime diagnostics should be filterable through tracing and RUST_LOG."
paths:
include:
- "/__semgrep_disabled__/**/*.rs"
- "/src/**/*.rs"
exclude:
- "/tests/**"
- "/examples/**"
Expand All @@ -33,6 +29,10 @@ rules:
- pattern-either:
- pattern: println!(...)
- pattern: eprintln!(...)
- pattern-not-inside: |
mod tests {
...
}
- pattern-not-inside: |
#[cfg(test)]
mod $MOD {
Expand Down Expand Up @@ -70,15 +70,14 @@ rules:
severity: WARNING
message: "Do not hide failed floating-point conversion with NaN or infinity defaults."
metadata:
enabled: false
category: correctness
tracking_issue: "https://github.com/acgetchell/delaunay/issues/338"
rationale: >-
Geometric predicates and diagnostics should not synthesize non-finite
sentinels after conversion failure.
paths:
include:
- "/__semgrep_disabled__/**/*.rs"
- "/src/**/*.rs"
pattern-either:
- pattern: $VALUE.unwrap_or(f64::NAN)
- pattern: $VALUE.unwrap_or(f64::INFINITY)
Expand All @@ -89,3 +88,153 @@ rules:
- pattern: $VALUE.unwrap_or_else(|| f64::NAN)
- pattern: $VALUE.unwrap_or_else(|| f64::INFINITY)
- pattern: $VALUE.unwrap_or_else(|| f64::NEG_INFINITY)

- id: delaunay.rust.no-std-hash-collections-in-hot-src
languages:
- rust
severity: WARNING
message: "Use crate FastHashMap/FastHashSet aliases in hot source paths instead of std hash collections."
metadata:
category: performance
rationale: >-
Performance-sensitive topology and geometry paths should use the
repository's optimized hash aliases unless a local exception is
documented outside these paths.
paths:
include:
- "/src/core/algorithms/**/*.rs"
- "/src/core/collections/**/*.rs"
- "/src/core/tds.rs"
- "/src/core/triangulation.rs"
- "/src/geometry/algorithms/**/*.rs"
- "/src/triangulation/**/*.rs"
patterns:
- pattern-either:
- pattern: use std::collections::HashMap;
- pattern: use std::collections::HashSet;
- pattern-regex: '^\s*use\s+std::collections::\{[^;\n]*\bHashMap\b[^;\n]*\};'
- pattern-regex: '^\s*use\s+std::collections::\{[^;\n]*\bHashSet\b[^;\n]*\};'
- pattern: std::collections::HashMap::new()
- pattern: std::collections::HashSet::new()
- pattern: std::collections::HashMap::default()
- pattern: std::collections::HashSet::default()
- pattern: std::collections::HashMap::with_capacity(...)
- pattern: std::collections::HashSet::with_capacity(...)
- pattern: std::collections::HashMap::with_hasher(...)
- pattern: std::collections::HashSet::with_hasher(...)
- pattern: std::collections::HashMap::with_capacity_and_hasher(...)
- pattern: std::collections::HashSet::with_capacity_and_hasher(...)
- pattern: std::collections::HashMap::<$KEY, $VALUE>::new()
- pattern: std::collections::HashSet::<$VALUE>::new()
- pattern: std::collections::HashMap::<$KEY, $VALUE>::default()
- pattern: std::collections::HashSet::<$VALUE>::default()
- pattern: std::collections::HashMap::<$KEY, $VALUE>::with_capacity(...)
- pattern: std::collections::HashSet::<$VALUE>::with_capacity(...)
- pattern: std::collections::HashMap::<$KEY, $VALUE>::with_hasher(...)
- pattern: std::collections::HashSet::<$VALUE>::with_hasher(...)
- pattern: std::collections::HashMap::<$KEY, $VALUE>::with_capacity_and_hasher(...)
- pattern: std::collections::HashSet::<$VALUE>::with_capacity_and_hasher(...)
- pattern: "let $NAME: std::collections::HashMap<$KEY, $VALUE> = $INIT;"
- pattern: "let $NAME: std::collections::HashSet<$VALUE> = $INIT;"
- pattern: "type $NAME = std::collections::HashMap<$KEY, $VALUE>;"
- pattern: "type $NAME = std::collections::HashSet<$VALUE>;"
- pattern: "fn $FUNC(...) -> std::collections::HashMap<$KEY, $VALUE> { ... }"
- pattern: "fn $FUNC(...) -> std::collections::HashSet<$VALUE> { ... }"
- pattern: "fn $FUNC(...) -> std::collections::HashMap<$KEY, $VALUE>;"
- pattern: "fn $FUNC(...) -> std::collections::HashSet<$VALUE>;"
- pattern: $ITER.collect::<std::collections::HashMap<$KEY, $VALUE>>()
- pattern: $ITER.collect::<std::collections::HashSet<$VALUE>>()
- pattern-not-inside: |
mod tests {
...
}

- id: delaunay.rust.no-silent-conversion-fallbacks
languages:
- rust
severity: WARNING
message: "Handle numeric conversion failures explicitly instead of hiding them behind unwrap_or fallbacks."
metadata:
category: correctness
rationale: >-
Geometry and topology code should preserve conversion failure context
or choose an explicit fallback branch rather than silently substituting
sentinel values.
paths:
include:
- "/src/core/**/*.rs"
- "/src/geometry/**/*.rs"
- "/src/topology/**/*.rs"
- "/src/triangulation/**/*.rs"
patterns:
- pattern-either:
- pattern: NumCast::from($VALUE).unwrap_or($FALLBACK)
- pattern: NumCast::from($VALUE).unwrap_or_else($FALLBACK)
- pattern: num_traits::NumCast::from($VALUE).unwrap_or($FALLBACK)
- pattern: num_traits::NumCast::from($VALUE).unwrap_or_else($FALLBACK)
- patterns:
- pattern: $SAFE($ARGS...).unwrap_or($FALLBACK)
- metavariable-regex:
metavariable: $SAFE
regex: safe_[A-Za-z0-9_]+
- pattern-not-inside: |
mod tests {
...
}

- id: delaunay.rust.no-production-unwrap-panic
languages:
- rust
severity: WARNING
message: "Avoid unwrap/panic in non-test source; return typed errors or document an internal invariant."
metadata:
category: correctness
rationale: "Public library paths should fail explicitly rather than panicking on user input."
paths:
include:
- "/src/**/*.rs"
patterns:
- pattern-either:
- pattern: $VALUE.unwrap()
- pattern: panic!(...)
- pattern-not-inside: |
mod tests {
...
}

- id: delaunay.rust.no-env-gated-stdio-diagnostics
languages:
- rust
severity: WARNING
message: "Environment-gated diagnostics should use tracing and repository feature gates instead of stdio macros."
metadata:
category: maintainability
rationale: "Debug hooks should remain filterable through tracing and RUST_LOG."
paths:
include:
- "/src/**/*.rs"
pattern-either:
- pattern: |
if std::env::var_os($NAME).is_some() {
...
println!(...);
...
}
- pattern: |
if std::env::var_os($NAME).is_some() {
...
eprintln!(...);
...
}
- pattern: |
if env::var_os($NAME).is_some() {
...
println!(...);
...
}
- pattern: |
if env::var_os($NAME).is_some() {
...
eprintln!(...);
...
}
12 changes: 7 additions & 5 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,8 @@ help-workflows:
# All linting: code + documentation + configuration
lint: lint-code lint-docs lint-config

# Code linting: Rust (fmt-check, clippy, docs) + Python (ruff, ty, mypy) + Shell scripts
lint-code: fmt-check clippy doc-check python-lint shell-lint
# Code linting: Rust (fmt-check, clippy, docs, Semgrep) + Python (ruff, ty, mypy) + Shell scripts
lint-code: fmt-check clippy doc-check semgrep semgrep-test python-lint shell-lint

# Configuration validation: JSON, TOML, YAML, GitHub Actions workflows
lint-config: validate-json toml-lint toml-fmt-check yaml-lint action-lint
Expand Down Expand Up @@ -580,10 +580,12 @@ python-sync: _ensure-uv
python-typecheck: _ensure-uv
uv run ty check scripts/ --error all

# Repository-owned Semgrep rules. Currently opt-in because the Rust rules are
# staged but disabled while legacy diagnostics are cleaned up.
# Repository-owned Semgrep rules for project-specific Rust diagnostics.
semgrep: _ensure-uv
uv run semgrep --config .semgrep.yaml .
uv run semgrep --error --strict --timeout 30 --config .semgrep.yaml .

semgrep-test: _ensure-uv
uv run semgrep scan --test --strict --config .semgrep.yaml tests/semgrep/src/core/algorithms/no_std_hash_collections.rs
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

# Development setup
setup: setup-tools
Expand Down
4 changes: 3 additions & 1 deletion src/core/algorithms/pl_manifold_repair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,9 @@ where
for (idx, d) in diff.iter_mut().enumerate() {
*d = vi.point().coords()[idx] - vj.point().coords()[idx];
}
let len: f64 = NumCast::from(hypot(&diff)).unwrap_or(f64::MAX);
let Some(len): Option<f64> = NumCast::from(hypot(&diff)) else {
return f64::MAX;
};
edge_lengths.push(len);
}
}
Expand Down
Loading
Loading