Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ All notable changes to this project are documented here. The format follows [Kee

## [Unreleased]

### Breaking changes

- Warning and error codes drop the underscore after the prefix: `MSKITVER006`, `MSKITPKG015`, and so on, with the same family and number. `NoWarn`, `WarningsAsErrors`, `WarningsNotAsErrors` and `MSKit_SkipPackageChecks` entries that name a code the old way no longer match: rename them. Each section of the [code reference](./docs/reference/codes.md) names the code's former spelling.

### Added

- Every warning and error links to its section of the [code reference](./docs/reference/codes.md) (`HelpLink`, shown by the terminal logger and IDEs). `MSKit_CodesHelpBaseUrl` points the links at another copy of the page.
- `manager/`: the first build of `mskit-manager`, the `DragoAnt.MSBuildKit.Manager` .NET tool (`net8.0`, `net10.0`, `RollForward=Major`) that will install, update and migrate the kit. This build has one command, `status [--json]`, which prints the tool version; the logo goes to stderr, only on a terminal and never with `--no-logo`, so `--json` output always parses. Each run writes a log under `<system temp>/mskit-manager/logs/`, named after the command, newest 20 kept. Not published yet.

### Changed
Expand All @@ -14,7 +19,7 @@ All notable changes to this project are documented here. The format follows [Kee

### Fixed

- A JPEG `PackageIconPath` no longer fails `dotnet pack` with NU5046: the icon is packed as `icon.<extension>`, lowercased (`icon.jpg`), and the nuspec names that file. `MSKIT_PKG015` accepts a 128×128 JPEG as well as a PNG, as nuget.org does ([#11](https://github.com/DragoAnt/MSBuildKit/pull/11)).
- A JPEG `PackageIconPath` no longer fails `dotnet pack` with NU5046: the icon is packed as `icon.<extension>`, lowercased (`icon.jpg`), and the nuspec names that file. `MSKITPKG015` accepts a 128×128 JPEG as well as a PNG, as nuget.org does ([#11](https://github.com/DragoAnt/MSBuildKit/pull/11)).

## [0.2.1] - 2026-10-05

Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ You need the .NET 10 SDK and the .NET 8 runtime, plus `sh` (Git Bash on Windows)
sh tests/run.sh
```

It installs the working-tree kit into the sample and the fixtures with `update.sh`, then checks the computed versions for local, branch, pull-request and tag builds, runs the sample's tests with coverage, inspects the packed nuspec, asserts that every `MSKIT_PKG` check fires on the fixtures, and runs `sh tools/docs-check.sh`. CI runs the same script on Linux and Windows.
It installs the working-tree kit into the sample and the fixtures with `update.sh`, then checks the computed versions for local, branch, pull-request and tag builds, runs the sample's tests with coverage, inspects the packed nuspec, asserts that every `MSKITPKG` check fires on the fixtures, and runs `sh tools/docs-check.sh`. CI runs the same script on Linux and Windows.

The tool's tests run from `manager/`, so its `global.json` selects Microsoft.Testing.Platform:

Expand All @@ -32,7 +32,7 @@ CI's `manager` job also packs the tool, installs it into a tool path and runs `m
## Changing the kit

- A new property defaults with `Condition="'$(Name)'==''"`, so a consumer's value always wins, and gets a row in [docs/reference/properties.md](./docs/reference/properties.md) plus a mention on its topic page.
- A new check gets an `MSKIT_<AREA><nnn>` code (a shipped code is never renumbered or reused), a message that says how to fix it, a section in [docs/reference/codes.md](./docs/reference/codes.md) headed by the code id without the underscore, a fixture that triggers it and a line in `tests/run.sh`.
- A new check gets an `MSKIT<AREA><nnn>` code with no separator (a shipped code is never renumbered or reused), a `HelpLink="$(MSKit_CodesHelpBaseUrl)#<code, lower case>"`, a message that says how to fix it, a section in [docs/reference/codes.md](./docs/reference/codes.md) headed by the code, a fixture that triggers it and a line in `tests/run.sh`.
- `sh tools/docs-check.sh` fails on a property, item or code without its reference entry, on a name the docs mention that the kit lacks, and on a broken relative link; `--list properties|items|codes` prints the kit's inventory with the file and line of each.
- The README stays short: key features, install, links. Detail goes to the topic page in `docs/`.
- A new part needs a line in `kit/.toolkit/kit.parts` and its `init.props` / `init.targets` imports in the entry points.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Shared MSBuild settings for .NET repositories that publish NuGet packages: nuget

## Key features

- **Packages that pass nuget.org's rules by default.** Licence, icon, README, [Source Link](https://learn.microsoft.com/dotnet/standard/library-guidance/sourcelink), symbols, repository and release-notes links, [package validation](https://learn.microsoft.com/dotnet/fundamentals/apicompat/package-validation/overview) and [NuGet audit](https://learn.microsoft.com/nuget/concepts/auditing-packages); nineteen `MSKIT_PKG` checks run on `dotnet pack`, warnings on your machine and errors on CI. [Packaging](./docs/packaging.md)
- **Packages that pass nuget.org's rules by default.** Licence, icon, README, [Source Link](https://learn.microsoft.com/dotnet/standard/library-guidance/sourcelink), symbols, repository and release-notes links, [package validation](https://learn.microsoft.com/dotnet/fundamentals/apicompat/package-validation/overview) and [NuGet audit](https://learn.microsoft.com/nuget/concepts/auditing-packages); nineteen `MSKITPKG` checks run on `dotnet pack`, warnings on your machine and errors on CI. [Packaging](./docs/packaging.md)
- **One README for the repository and its packages.** `MSKit_PackageReadmeFrom=README.md` generates each package's readme on pack, with links pinned to the commit. [Package readme](./docs/package-readme.md)
- **Versions from release tags.** Tag `v1.4.0` and the packages are `1.4.0`; branch builds are `1.4.0-ci.<run>`, pull requests `1.4.0-pr.<n>.<run>`, local builds `9999.0.0`. [Versioning](./docs/versioning.md)
- **Tests on Microsoft.Testing.Platform v2.** Projects named `*.Tests` become [xUnit v3](https://xunit.net/docs/getting-started/v3/microsoft-testing-platform) test projects with coverage, TRX and JUnit reports, an assertion library and [NSubstitute](https://nsubstitute.github.io/). [Testing](./docs/testing.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Read in this order; each page stands on its own, so jump to the one you need.
| 5 | [Versioning](./versioning.md) | control how package versions are computed |
| 6 | [Local files and secrets](./local-files.md) | keep secrets and machine-only source files out of the repository |
| 7 | [Optional parts](./optional-parts.md) | debug a dependency from source, list a project's packages, run Entity Framework migrations |
| 8 | [Packaging](./packaging.md) | understand the nuget.org defaults and the `MSKIT_PKG` checks |
| 8 | [Packaging](./packaging.md) | understand the nuget.org defaults and the `MSKITPKG` checks |
| 9 | [Package readme](./package-readme.md) | generate every package's readme from the repository README |
| 10 | [Testing](./testing.md) | set up test projects, assertions, mocking and coverage |
| 11 | [Roslyn components](./roslyn.md) | build analyzers, code fixes and source generators |
Expand Down
18 changes: 9 additions & 9 deletions docs/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The owner layer adds `IsPackable=True`, `TreatWarningsAsErrors=True`, `NoWarn` `
| | Developer machine | CI |
| --- | --- | --- |
| Version | `9999.0.0` | from the tag, pull request or run ([Versioning](./versioning.md)) |
| `MSKIT_PKG` checks | warnings | errors ([Packaging](./packaging.md)) |
| `MSKITPKG` checks | warnings | errors ([Packaging](./packaging.md)) |
| [`ContinuousIntegrationBuild`](https://learn.microsoft.com/dotnet/core/project-sdk/msbuild-props#continuousintegrationbuild) | unset (PDBs keep real paths) | `true` |
| Local secrets | created from templates | deleted ([Local files](./local-files.md)) |
| `TreatWarningsAsErrors` drift check | on | off: CI passes its own `-p:TreatWarningsAsErrors` |
Expand Down Expand Up @@ -52,9 +52,9 @@ Declare `TargetFramework` or `TargetFrameworks` once, in `Directory.Build.props`

| Code | When |
| --- | --- |
| [`MSKIT_SHARED006`](./reference/codes.md#mskitshared006), [`MSKIT_SHARED007`](./reference/codes.md#mskitshared007) | error: the csproj repeats the shared `TargetFramework` / `TargetFrameworks` value |
| [`MSKIT_SHARED008`](./reference/codes.md#mskitshared008), [`MSKIT_SHARED009`](./reference/codes.md#mskitshared009) | warning: the csproj sets a different value of the same shape; `MSKit_SkipAudit_TargetFrameworkOverride=True` accepts it |
| [`MSKIT_SHARED010`](./reference/codes.md#mskitshared010) | error: the csproj declares both shapes |
| [`MSKITSHARED006`](./reference/codes.md#mskitshared006), [`MSKITSHARED007`](./reference/codes.md#mskitshared007) | error: the csproj repeats the shared `TargetFramework` / `TargetFrameworks` value |
| [`MSKITSHARED008`](./reference/codes.md#mskitshared008), [`MSKITSHARED009`](./reference/codes.md#mskitshared009) | warning: the csproj sets a different value of the same shape; `MSKit_SkipAudit_TargetFrameworkOverride=True` accepts it |
| [`MSKITSHARED010`](./reference/codes.md#mskitshared010) | error: the csproj declares both shapes |

`MSKit_GuardXmlPeekRoutine=False` and `MSKit_GuardXmlPeekAudit=False` turn off a cheap text pre-check and always parse the csproj; leave them alone unless a declaration is missed.

Expand Down Expand Up @@ -86,7 +86,7 @@ A project with `ExcludeFromCodeCoverage=true` gets the [`[ExcludeFromCodeCoverag

## Central package versions

The parts that add package references also provide their versions: as `PackageVersion` items with [central package management](https://learn.microsoft.com/nuget/consume-packages/central-package-management), else on the `PackageReference` itself when it has no version. Each version is a property you can override, `MSKit_PackageVersion_<Package>` (lists: [Testing](./testing.md#package-versions), [Roslyn](./roslyn.md#package-versions)); `MSKit_ImplicitPackageVersions=False` turns them all off. A `PackageVersion` of yours for the same id fails restore with [`MSKIT_DUP001`](./reference/codes.md#mskitdup001) (bypass: `MSKit_SkipAudit_ImplicitPackageDuplicates=True`).
The parts that add package references also provide their versions: as `PackageVersion` items with [central package management](https://learn.microsoft.com/nuget/consume-packages/central-package-management), else on the `PackageReference` itself when it has no version. Each version is a property you can override, `MSKit_PackageVersion_<Package>` (lists: [Testing](./testing.md#package-versions), [Roslyn](./roslyn.md#package-versions)); `MSKit_ImplicitPackageVersions=False` turns them all off. A `PackageVersion` of yours for the same id fails restore with [`MSKITDUP001`](./reference/codes.md#mskitdup001) (bypass: `MSKit_SkipAudit_ImplicitPackageDuplicates=True`).

`PrivateAssets=all` is set on references to `Fody`, `ConfigureAwait.Fody`, `IgnoresAccessChecksToGenerator`, `Grpc.Tools`, `Microsoft.EntityFrameworkCore.Design` and `Microsoft.EntityFrameworkCore.Tools`, so these build-time tools never become package dependencies. Add your own `Update` items in `Directory.Packages.Metadata.targets`.

Expand All @@ -101,13 +101,13 @@ The parts that add package references also provide their versions: as `PackageVe
</ItemGroup>
```

A reference to a `Type="Error"` package fails with [`MSKIT_RES001`](./reference/codes.md#mskitres001), a `Type="Warning"` one warns with [`MSKIT_RES002`](./reference/codes.md#mskitres002). `SkipGlobalRestriction="True"` on one `PackageReference` allows it (an error becomes a warning). The owner layer bans `Moq`.
A reference to a `Type="Error"` package fails with [`MSKITRES001`](./reference/codes.md#mskitres001), a `Type="Warning"` one warns with [`MSKITRES002`](./reference/codes.md#mskitres002). `SkipGlobalRestriction="True"` on one `PackageReference` allows it (an error becomes a warning). The owner layer bans `Moq`.

**Allow-list mode.** With `MSKit_RestrictProjectReferences=True` (or `MSKit_RestrictPackageReferences`, or `MSKit_RestrictReferences` for both) every reference must carry `Allowed="True"`, else [`MSKIT_RES003`](./reference/codes.md#mskitres003) / [`MSKIT_RES004`](./reference/codes.md#mskitres004). Off by default.
**Allow-list mode.** With `MSKit_RestrictProjectReferences=True` (or `MSKit_RestrictPackageReferences`, or `MSKit_RestrictReferences` for both) every reference must carry `Allowed="True"`, else [`MSKITRES003`](./reference/codes.md#mskitres003) / [`MSKITRES004`](./reference/codes.md#mskitres004). Off by default.

**Prerelease dependencies on a stable branch.** On a stable branch a reference to a prerelease version of a package whose id starts with `MSKit_PrereleasePackagePrefix` (owner layer: `DragoAnt.`) warns with [`MSKIT_PRE001`](./reference/codes.md#mskitpre001); `MSKit_PrereleasePackageCheckAsWarning=false` makes it an error.
**Prerelease dependencies on a stable branch.** On a stable branch a reference to a prerelease version of a package whose id starts with `MSKit_PrereleasePackagePrefix` (owner layer: `DragoAnt.`) warns with [`MSKITPRE001`](./reference/codes.md#mskitpre001); `MSKit_PrereleasePackageCheckAsWarning=false` makes it an error.

**`TreatWarningsAsErrors` drift.** On a developer machine a csproj that changes the shared `TreatWarningsAsErrors` fails with [`MSKIT_SHARED020`](./reference/codes.md#mskitshared020); `MSKit_SkipAudit_TreatWarningsAsErrors=True` allows it.
**`TreatWarningsAsErrors` drift.** On a developer machine a csproj that changes the shared `TreatWarningsAsErrors` fails with [`MSKITSHARED020`](./reference/codes.md#mskitshared020); `MSKit_SkipAudit_TreatWarningsAsErrors=True` allows it.

## Private references

Expand Down
2 changes: 1 addition & 1 deletion docs/customizing.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Almost every default is written as `<X Condition="'$(X)'==''">`, so the first va
| `MSKit_TestingFramework`, `MSKit_TestsAssertions` | `xunit.v3`, `AwesomeAssertions` | [Testing](./testing.md) |
| `MSKit_RestrictPackageReference` | `Moq` as an error | [reference checks](./build.md#reference-checks) |

**Another owner:** fork the kit, change `kit/.toolkit/msbuild/init.company.props` (and `.targets`) and `kit/.toolkit/res/package.icon.png`, publish releases from the fork and install with `update.sh --repo <owner>/<fork>` (recorded in `kit.json`, so later updates come from the fork). No part names an owner.
**Another owner:** fork the kit, change `kit/.toolkit/msbuild/init.company.props` (and `.targets`) and `kit/.toolkit/res/package.icon.png`, publish releases from the fork and install with `update.sh --repo <owner>/<fork>` (recorded in `kit.json`, so later updates come from the fork). Set `MSKit_CodesHelpBaseUrl` in the owner layer to point the code links at the fork's code reference. No part names an owner.

## Extension files

Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ A project whose name ends in `.Tests` is a test project: [xUnit v3](https://xuni
</Project>
```

With [central package management](https://learn.microsoft.com/nuget/consume-packages/central-package-management), leave the test packages out of `Directory.Packages.props`: the kit provides their versions ([`MSKIT_DUP001`](./reference/codes.md#mskitdup001) reports a duplicate).
With [central package management](https://learn.microsoft.com/nuget/consume-packages/central-package-management), leave the test packages out of `Directory.Packages.props`: the kit provides their versions ([`MSKITDUP001`](./reference/codes.md#mskitdup001) reports a duplicate).

## 5 Build, test, pack

Expand Down
2 changes: 1 addition & 1 deletion docs/migrating-from-msbuild-routine.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
1. **Remove the submodule:** `git rm .msbuild`, delete `.gitmodules`, and drop `submodules:` from your workflows.
2. **Install the kit** ([Getting started](./getting-started.md)), with `--add PackageAsProj` if you use `Directory.PackageAsProj.targets`, and replace the `.msbuild\shared\init.props` / `init.targets` imports with the `.toolkit/msbuild/` ones.
3. **Drop what is now a default:** `Copyright`, `PackageLicenseExpression`, `RepositoryUrl`, `PackageReleaseNotes`, `TargetFrameworkStrategy`, and the `.msbuild\tfm.constants.props` import.
4. **Remove the versions the kit provides** from `Directory.Packages.props` (`xunit.v3*`, `xunit.runner.visualstudio`, `Microsoft.NET.Test.Sdk`, `Microsoft.Testing.Extensions.CodeCoverage`, `NSubstitute*`, your assertion library, `coverlet.collector`) and the explicit `Microsoft.Testing.Extensions.CodeCoverage` references from test projects; [`MSKIT_DUP001`](./reference/codes.md#mskitdup001) lists any you missed. To keep FluentAssertions 7, set `MSKit_TestsAssertions=FluentAssertions`.
4. **Remove the versions the kit provides** from `Directory.Packages.props` (`xunit.v3*`, `xunit.runner.visualstudio`, `Microsoft.NET.Test.Sdk`, `Microsoft.Testing.Extensions.CodeCoverage`, `NSubstitute*`, your assertion library, `coverlet.collector`) and the explicit `Microsoft.Testing.Extensions.CodeCoverage` references from test projects; [`MSKITDUP001`](./reference/codes.md#mskitdup001) lists any you missed. To keep FluentAssertions 7, set `MSKit_TestsAssertions=FluentAssertions`.
5. **Add `Directory.Version.props`** with the next `VersionPrefix`, and publish releases with tags such as `v2.0.1` ([Versioning](./versioning.md)).

Renamed properties:
Expand Down
4 changes: 2 additions & 2 deletions docs/optional-parts.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ The kit imports `Directory.PackageAsProj.targets` from the solution folder when

| Code | When |
| --- | --- |
| [`MSKIT_PAP001`](./reference/codes.md#mskitpap001) | a package switched to a project is still resolved from the package: restore with `--force` |
| [`MSKIT_PAP002`](./reference/codes.md#mskitpap002) | a package switched back is not restored yet: restore with `--force`, or set `PackageAsProj_SkipChecks=True` |
| [`MSKITPAP001`](./reference/codes.md#mskitpap001) | a package switched to a project is still resolved from the package: restore with `--force` |
| [`MSKITPAP002`](./reference/codes.md#mskitpap002) | a package switched back is not restored yet: restore with `--force`, or set `PackageAsProj_SkipChecks=True` |

Keep `Directory.PackageAsProj.targets` out of git if the paths point at your own checkouts.

Expand Down
Loading
Loading