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.