diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5180f6e..d7063f8 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -23,7 +23,7 @@ updates: - dependencies - nuget # ------------------------------------------------------------------------- - # These two carry deliberate per-TFM floors (see the csproj comment): a + # These two carry deliberate per-TFM floors (see Directory.Packages.props): a # net8.0 consumer must stay on its own 8.0.x servicing line, so an # 8.x -> 10.x major PR is never mergeable and would just be weekly noise. # diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9ff46c..5c14aca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,8 +102,20 @@ jobs: # Tests run across every shipped TFM (STANDARD.md 2.3). No --no-build: this job # does not share a filesystem with `build`, and rebuilding is cheaper and less # fragile than shipping obj/ between jobs. + # `-- --coverage` passes through to Microsoft.Testing.Platform's coverage + # extension (STANDARD.md 2.6). Referencing a collector without invoking it is + # worse than none: it reads as coverage in the dependency list while producing + # no data. One .coverage file lands per TFM, under bin/*/TestResults. - name: Test - run: dotnet test --configuration Release --verbosity normal + run: dotnet test --configuration Release --verbosity normal -- --coverage + + - name: Upload coverage + if: always() + uses: actions/upload-artifact@v7 + with: + name: coverage-${{ matrix.os }} + path: '**/TestResults/*.coverage' + if-no-files-found: warn # THE required status check. Aggregates everything above so the ruleset never has to # know the matrix shape. `if: always()` is essential — without it the gate is skipped diff --git a/CHANGELOG.md b/CHANGELOG.md index 137a0e4..59594a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **`.github/dependabot.yml` rewritten.** Minor and patch bumps are grouped into one PR per ecosystem; majors are deliberately left ungrouped so each arrives separately and stays open for review. The two runtime-aligned packages carrying per-TFM floors (`Microsoft.Extensions.DependencyInjection.Abstractions`, `Microsoft.Extensions.Http`) are now under `ignore` for major updates, because an 8.x → 10.x bump on the net8 floor is never mergeable and was weekly noise. - **`global.json` now pins the SDK**, not just the Microsoft.Testing.Platform runner: `10.0.100` with `rollForward: latestFeature`. An unpinned SDK means a contributor on an older one gets different analyzer results from CI, and with `TreatWarningsAsErrors` that is a build which fails for them and passes for everyone else. - **`.gitignore` and `.editorconfig` replaced with the canonical copies.** The `.editorconfig` change is one line that matters: the private-field naming rule had `applicable_kinds = field`, and a `const` *is* a field, so the rule demanded `_nonceSize` for `private const int NonceSize`. An empty `required_modifiers` scopes it to instance fields. Nothing enforces these rules at build time yet (`EnforceCodeStyleInBuild` is off), so this is a no-op for the build today and correct for when it is not. +- **Central Package Management adopted.** Package versions move out of the three project files into a root `Directory.Packages.props`, with `CentralPackageVersionOverrideEnabled=false` so a stray inline `Version=` is a hard build error rather than being silently ignored. The per-TFM floors survive intact — CPM re-evaluates the conditional `ItemGroup`s per target framework during the inner build, so `net8.0` still floors at 8.0.2 / 8.0.1 and `net10.0` at 10.0.11. **Verified behaviour-preserving:** packed before and after from clean `obj/` at the same commit, the `.nuspec`, both `lib/` assemblies, both XML documentation files, both symbol PDBs, the README and the icon are byte-identical; the only differences in either package are the `.psmdcp` filename, which NuGet regenerates per pack, and the `_rels/.rels` entry that names it. No dependency floor was raised — that is consumer-visible and belongs in its own reviewed commit. +- **Properties every project restated now live in `Directory.Build.props`.** `ImplicitUsings`, `SatelliteResourceLanguages`, `AnalysisLevel`, `GenerateDocumentationFile`, `EnablePackageValidation`, `IncludeSymbols`, `SymbolPackageFormat`, `DebugType`, `PublishRepositoryUrl`, `EmbedUntrackedSources`, `ContinuousIntegrationBuild`, `PackageLicenseExpression` and `Copyright`. Duplicated settings are how these repos drifted apart in the first place; each csproj now carries only what is genuinely specific to it. The demo project opts `GenerateDocumentationFile` back off — it is not shipped, so its types are not public surface and demanding XML docs on sample code would fail the build under `TreatWarningsAsErrors`. ### Added +- **Code coverage is now collected.** Adds `Microsoft.Testing.Extensions.CodeCoverage` and — the part that actually matters — has CI invoke it (`dotnet test … -- --coverage`) and upload the result per platform. A collector that is referenced but never invoked is worse than none: it reads as coverage in the dependency list while producing no data. One `.coverage` file lands per target framework, verified locally on both. - **`SECURITY.md`**, with a scope section specific to this library: SHA-256 verification establishes integrity but not authenticity (the expected hash ships from the same release as the asset, and there is no signature checking); `AllowInsecureManifestSource` and `UseDefaultSha256Verifier = false` are documented opt-outs that defeat verification by design; archive path-traversal defence is the framework's `ZipFile`/`TarFile` guard rather than this library's; and `GhCliReleaseSource` trusts whatever `gh` is on `PATH`. Stating the boundary is the point — a report that only restates a documented limitation is not a vulnerability. - **`CONTRIBUTING.md`, `.github/PULL_REQUEST_TEMPLATE.md` and `CLAUDE.md`.** `CLAUDE.md` records the constraints an agent would otherwise violate here — why the three-platform matrix is load-bearing, why one install-lock test returns early on Windows by design, and that `PackageValidationBaselineVersion` tracks the last shipped release. diff --git a/Directory.Build.props b/Directory.Build.props index 08993bb..65a7154 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,25 @@ + enable + enable + en + latest + true + true + true + snupkg + portable + true + true + true + MIT + © Stuart Meeks true Stuart Meeks Next Iteration diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 0000000..568116f --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,78 @@ + + + + true + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/NextIteration.SpectreConsole.SelfUpdate.Demo/NextIteration.SpectreConsole.SelfUpdate.Demo.csproj b/demo/NextIteration.SpectreConsole.SelfUpdate.Demo/NextIteration.SpectreConsole.SelfUpdate.Demo.csproj index ada0496..25222a7 100644 --- a/demo/NextIteration.SpectreConsole.SelfUpdate.Demo/NextIteration.SpectreConsole.SelfUpdate.Demo.csproj +++ b/demo/NextIteration.SpectreConsole.SelfUpdate.Demo/NextIteration.SpectreConsole.SelfUpdate.Demo.csproj @@ -3,9 +3,15 @@ Exe net10.0 - enable - enable false + + false diff --git a/src/NextIteration.SpectreConsole.SelfUpdate/NextIteration.SpectreConsole.SelfUpdate.csproj b/src/NextIteration.SpectreConsole.SelfUpdate/NextIteration.SpectreConsole.SelfUpdate.csproj index fe53967..201b3fb 100644 --- a/src/NextIteration.SpectreConsole.SelfUpdate/NextIteration.SpectreConsole.SelfUpdate.csproj +++ b/src/NextIteration.SpectreConsole.SelfUpdate/NextIteration.SpectreConsole.SelfUpdate.csproj @@ -1,72 +1,63 @@ + net8.0;net10.0 - enable - enable - en - true - latest NextIteration.SpectreConsole.SelfUpdate 0.3.1 - Stuart Meeks Self-update for Spectre.Console CLIs: pluggable update sources (GitHub Releases over HTTP, GitHub Releases via gh CLI for private repos, generic HTTPS manifest, custom), SHA-256 verification, atomic file swap, and a drop-in `update` command. true $(MSBuildThisFileDirectory)..\..\artifacts\packages true - MIT README.md https://github.com/StuartMeeks/NextIteration.SpectreConsole.SelfUpdate https://github.com/StuartMeeks/NextIteration.SpectreConsole.SelfUpdate.git git spectre;cli;self-update;auto-update;github-releases icon.png - © Stuart Meeks - true 0.3.0 - true - true - true - snupkg - portable - true + + + + + + + + + - - + + - - - - - - - - - - + + diff --git a/tests/NextIteration.SpectreConsole.SelfUpdate.Tests/NextIteration.SpectreConsole.SelfUpdate.Tests.csproj b/tests/NextIteration.SpectreConsole.SelfUpdate.Tests/NextIteration.SpectreConsole.SelfUpdate.Tests.csproj index 1ad62f6..e0263f8 100644 --- a/tests/NextIteration.SpectreConsole.SelfUpdate.Tests/NextIteration.SpectreConsole.SelfUpdate.Tests.csproj +++ b/tests/NextIteration.SpectreConsole.SelfUpdate.Tests/NextIteration.SpectreConsole.SelfUpdate.Tests.csproj @@ -3,13 +3,11 @@ net8.0;net10.0 Exe - enable - enable false true false @@ -35,8 +33,15 @@ is pointed at MTP by the `test.runner` setting in global.json. --> - - + + + +