From 1487185a467684b0f8e86d52184b3f4d06a3fbc2 Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 22 Aug 2026 02:06:41 +0000 Subject: [PATCH] chore: align codeql.yml with buildless standard; fix remaining scanning alerts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align with the updated NextIteration.Standards §4.4 / §3.0.1 and resolve the three remaining open code-scanning alerts with genuine fixes. - codeql.yml now matches the canonical template verbatim (non-comment content): the C# analysis runs `build-mode: none`, dropping the Setup .NET / Restore / Build steps. This is load-bearing — GitHub honours the `paths-ignore` for **/obj/** and **/bin/** only under buildless extraction, so under the previous explicit build the exclusion was inert and the generated xUnit entry point in obj/ was analysed. This clears the audit-drift `3.0.1 workflow content` FAIL (the only failing clause) and genuinely excludes the two cs/missed-ternary-operator alerts against generated code. - cs/local-not-disposed: the previous fluent `new TestConsole().Interactive()` left CodeQL unable to connect the allocation to the disposed `using` variable, so the alert reopened. Bind `using` directly to `new TestConsole()` and call `.Interactive()` as a separate statement (it mutates in place and returns the same instance) so the disposal is visible to dataflow. audit-drift.sh (scoped to this repo): 32/32 clauses green after this change. Build clean (0 warnings); 64/64 tests pass on net8.0 and net10.0. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/codeql.yml | 42 ++++++++++--------- CHANGELOG.md | 23 +++++++++- .../Infrastructure/CliHarness.cs | 3 +- 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 662dd1a..776630f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,23 +32,36 @@ jobs: - name: Checkout uses: actions/checkout@v7 - - name: Setup .NET - uses: actions/setup-dotnet@v6 - with: - dotnet-version: | - 8.0.x - 10.0.x - - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: languages: csharp + # build-mode: none analyses the C# source directly, without a build. + # It is load-bearing, not a convenience, for two reasons: + # + # 1. paths-ignore (below) only takes effect in this mode. When CodeQL + # builds a compiled language, GitHub applies no path filter — every + # file the compiler sees is analysed, obj/ included — so under the + # explicit build this workflow used to run, paths-ignore was + # silently inert and the xUnit auto-generated entry point in obj/ + # was analysed and flagged in every repo. Buildless extraction + # honours the filter, so the exclusion the standard mandates + # actually happens. + # + # 2. It reads the source across every target framework at once. These + # repos multi-target, and autobuild has picked a single TFM in the + # past, silently analysing half the code; the explicit build existed + # to guard against that. Buildless extraction reads the source + # itself, not one TFM's build output, so it covers all of it with no + # build step to get wrong. + build-mode: none # security-and-quality is broader than the default security-extended; # these are small libraries, so the extra findings are affordable. queries: security-and-quality # Analyse source only. obj/ and bin/ hold generated and compiled # output — e.g. the xUnit auto-generated entry point — so findings - # there are noise against code no human maintains. + # there are noise against code no human maintains. Effective only + # under build-mode: none (above). # # query-filters excludes the two audit queries that fire on every # P/Invoke declaration and call site (cs/unmanaged-code, @@ -57,9 +70,7 @@ jobs: # noise there and non-native repos have no P/Invoke for them to hit. # This excludes ONLY those two queries — every other # security-and-quality query still runs on the interop files, so no - # real finding is lost (STANDARD.md 4.4). This repo has no P/Invoke, - # so the block matches nothing here; it is carried to keep the - # workflow identical to the template (STANDARD.md 3.0.1). + # real finding is lost (STANDARD.md 4.4). config: | paths-ignore: - "**/obj/**" @@ -70,15 +81,6 @@ jobs: - exclude: id: cs/call-to-unmanaged-code - # Explicit build rather than autobuild: these repos multi-target, and - # autobuild has picked a single TFM in the past, silently analysing half - # the code. Restore is separate so a restore failure is legible. - - name: Restore - run: dotnet restore - - - name: Build - run: dotnet build --configuration Release --no-restore - - name: Perform CodeQL analysis uses: github/codeql-action/analyze@v4 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index f8a5ee9..ea574b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Aligned `codeql.yml` with the updated canonical template (`STANDARD.md` 4.4, + 3.0.1): the C# analysis now runs `build-mode: none` (buildless extraction), so + the `Setup .NET` / `Restore` / `Build` steps are gone. This is load-bearing, + not cosmetic — GitHub applies the `paths-ignore` for `**/obj/**` and + `**/bin/**` *only* under buildless extraction; under the previous explicit + build every file the compiler saw was analysed, `obj/` included, so the + exclusion was silently inert and the xUnit auto-generated entry point in + `obj/` was scanned and flagged. Buildless extraction honours the filter (and + reads the source across both target frameworks at once, with no build step to + get wrong). + ### Fixed +- Genuinely excluded the two `cs/missed-ternary-operator` alerts CodeQL raised + against the generated `obj/**/XunitAutoGeneratedEntryPoint.cs` — the + `paths-ignore` now takes effect (see the `build-mode: none` change above) + rather than the alerts sitting open against code no human maintains. - Resolved every open CodeQL code-scanning alert from the `security-and-quality` pack with a genuine code change rather than a suppression (no consumer-visible behaviour changes): @@ -31,7 +48,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `cs/missed-using-statement`: the debounce task now scopes its `CancellationTokenSource` with a `using` block instead of a manual `finally`-dispose, preserving the existing (idempotent) disposal semantics. - - `cs/local-not-disposed`: the test CLI harness now disposes its `TestConsole`. + - `cs/local-not-disposed`: the test CLI harness binds its `using` directly to + the `new TestConsole()` allocation and calls `.Interactive()` as a separate + statement, so the disposal is visible to dataflow — the earlier fluent + `new TestConsole().Interactive()` left CodeQL unable to connect the + allocation to the disposed variable. ## [1.0.0] — 2026-08-21 diff --git a/tests/NextIteration.SpectreConsole.Settings.Tests/Infrastructure/CliHarness.cs b/tests/NextIteration.SpectreConsole.Settings.Tests/Infrastructure/CliHarness.cs index 90da33a..d12ea38 100644 --- a/tests/NextIteration.SpectreConsole.Settings.Tests/Infrastructure/CliHarness.cs +++ b/tests/NextIteration.SpectreConsole.Settings.Tests/Infrastructure/CliHarness.cs @@ -37,7 +37,8 @@ public static async Task RunAsync( var app = new CommandApp(new TypeRegistrar(services)); app.Configure(config => config.AddSettingsBranch()); - using var console = new TestConsole().Interactive(); + using var console = new TestConsole(); + console.Interactive(); foreach (var line in consoleInput) { console.Input.PushTextWithEnter(line);