diff --git a/.github/workflows/oracle.yml b/.github/workflows/oracle.yml
index 3a6a81dd..acf767e6 100644
--- a/.github/workflows/oracle.yml
+++ b/.github/workflows/oracle.yml
@@ -83,8 +83,10 @@ jobs:
scripts/own-check.sh --format human -- "$scan" > own.txt 2> own-extract.log
echo "own-check rc=$? ; $(wc -l < own.txt) finding line(s)"
- # CodeQL — database from source (no build), default queries; we filter to
- # the dispose/leak family in the comparator.
+ # CodeQL — database from source (no build). The dispose/leak queries
+ # (cs/local-not-disposed & friends) are *quality* queries, absent from the
+ # default code-scanning (security) suite — so request security-and-quality,
+ # else CodeQL silently contributes zero. Comparator filters to the leak family.
- name: CodeQL init
uses: github/codeql-action/init@v3
continue-on-error: true
@@ -92,6 +94,7 @@ jobs:
languages: csharp
build-mode: none
source-root: target
+ queries: security-and-quality
- name: CodeQL analyze
uses: github/codeql-action/analyze@v3
continue-on-error: true
@@ -101,12 +104,31 @@ jobs:
upload: false
# Infer# — needs compiled binaries; build the target into one output dir.
+ # `dotnet build
` errors (MSB1050) when a repo root holds more than one
+ # project/solution, so choose a target: explicit `build` input wins; else a
+ # lone solution (root-preferred); else the dir (continue-on-error -> partial).
- name: Build the target (for Infer#)
env:
BUILD: ${{ inputs.build }}
continue-on-error: true
run: |
- tgt="target"; [[ -n "$BUILD" ]] && tgt="target/$BUILD"
+ if [[ -n "$BUILD" ]]; then
+ tgt="target/$BUILD"
+ else
+ # Prefer a unique solution at the repo root; else a unique solution
+ # anywhere (covers a lone deep .sln); else fall back to the dir + note.
+ mapfile -t root_slns < <(find target -maxdepth 1 -name '*.sln' | sort)
+ mapfile -t all_slns < <(find target -name '*.sln' | sort)
+ if [[ ${#root_slns[@]} -eq 1 ]]; then
+ tgt="${root_slns[0]}"
+ elif [[ ${#root_slns[@]} -eq 0 && ${#all_slns[@]} -eq 1 ]]; then
+ tgt="${all_slns[0]}"
+ else
+ tgt="target"
+ echo "note: ${#root_slns[@]} root / ${#all_slns[@]} total .sln under target; pass the 'build' input to disambiguate"
+ fi
+ fi
+ echo "Infer# build target: $tgt"
if dotnet build "$tgt" -c Release -o _bin -v quiet; then
echo "BUILD_OK=1" >> "$GITHUB_ENV"
else
diff --git a/docs/notes/oracle.md b/docs/notes/oracle.md
index e892c3da..27f8112e 100644
--- a/docs/notes/oracle.md
+++ b/docs/notes/oracle.md
@@ -36,7 +36,10 @@ Two classes sit **outside** the three-way diff and are reported separately:
CodeQL constructs a database (here via `build-mode: none`, from source), Infer#
analyses compiled `.dll`+`.pdb`. So the oracle run can fail where ours doesn't
— that asymmetry is the point, and each oracle step is `continue-on-error` so a
- build failure still yields a partial report.
+ build failure still yields a partial report. (For Infer#, the workflow
+ auto-builds a lone solution — a root-level `*.sln` preferred, else a unique one
+ anywhere; a repo with several needs the `build` input, since `dotnet build
+ ` is ambiguous otherwise, MSB1050.)
- **Path/line matching is deliberately loose.** Tools disagree on the exact line
(allocation site vs declaration) and on path prefixes. The comparator matches
on **basename + a line window** (`--line-tol`, default 3). Robust to prefixes;
@@ -91,9 +94,12 @@ line up with two independent engines.
- **No tool versions pinned in the report yet.** `microsoft/infersharpaction@v1.5`
and `github/codeql-action@v3` float on tags; the report header names the tools
but not exact analyser versions. A later pass can stamp them.
-- **CodeQL runs the default suite, filtered in the comparator** (rather than a
- single-query pack). Simpler and robust to suite/version drift; the filter keys
- on the dispose/leak rule family.
+- **CodeQL runs the `security-and-quality` suite, filtered in the comparator**
+ (rather than a single-query pack). This matters: the dispose/leak queries
+ (`cs/local-not-disposed` & friends) are *quality* queries, **absent from the
+ default code-scanning (security) suite** — without the suite, CodeQL silently
+ contributes zero. The filter keys on the dispose/leak rule family; robust to
+ version drift.
- **One target, by hand.** Same discipline as mining: a deliberate spot-check,
not a crawler. Be a good citizen (shallow, read-only).
- **Agreement is necessary, not sufficient.** Two tools can share a blind spot.