From c78563cbb1f5fb3ed3a0c28878d2ff333031a397 Mon Sep 17 00:00:00 2001 From: VasiliyF <5789590+vfofanov@users.noreply.github.com> Date: Tue, 6 Oct 2026 11:28:21 +0200 Subject: [PATCH 1/3] Test MSKit_DefaultPackageIconUrl next to the kit's icon - iconUrl only with the kit's embedded icon, never with the project's own PackageIcon or an empty property; MSKITPKG008 only for a project-set PackageIconUrl --- tests/package-icon.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/package-icon.sh b/tests/package-icon.sh index 6e18a21..35b0666 100644 --- a/tests/package-icon.sh +++ b/tests/package-icon.sh @@ -21,6 +21,10 @@ ic_icon() { actual=$(sed -n 's:.*\(.*\).*:\1:p' "$out/icon-$1.nuspec") [ "$actual" = "$2" ] && pass "icon $1: nuspec $actual" || bad "icon $1: nuspec expected '$2', got '$actual'" } +ic_icon_url() { + actual=$(sed -n 's:.*\(.*\).*:\1:p' "$out/icon-$1.nuspec") + [ "$actual" = "$2" ] && pass "icon $1: nuspec $actual" || bad "icon $1: nuspec expected '$2', got '$actual'" +} ic_entry() { grep -qx -- "$2" "$out/icon-$1.files" && pass "icon $1: nupkg contains $2" || bad "icon $1: nupkg lacks $2"; } ic_no_entry() { grep -qx -- "$2" "$out/icon-$1.files" && bad "icon $1: nupkg still contains $2" || pass "icon $1: nupkg has no $2"; } ic_warns() { grep -q "warning $2" "$out/icon-$1.log" && pass "icon $1 warns $2" || bad "icon $1 does not warn $2 (see $out/icon-$1.log)"; } @@ -58,3 +62,21 @@ ic_icon own logo.png ic_entry own logo.png ic_no_entry own icon.png ic_quiet own MSKITPKG015 + +# MSKit_DefaultPackageIconUrl goes into the nuspec next to the kit's own embedded icon only. +icon_url=https://example.com/fixture-icon.png +ic_icon_url default "" +ic_pack url Icons -p:MSKit_DefaultPackageIconUrl=$icon_url +ic_icon url icon.png +ic_icon_url url "$icon_url" +ic_quiet url MSKITPKG008 +ic_quiet url NU5048 + +ic_pack own-url Own -p:MSKit_DefaultPackageIconUrl=$icon_url +ic_icon own-url logo.png +ic_icon_url own-url "" + +# A PackageIconUrl the project sets itself is still reported, and the kit's default does not replace it. +ic_pack project-url Icons -p:PackageIconUrl=https://example.com/own.png -p:MSKit_DefaultPackageIconUrl=$icon_url +ic_icon_url project-url https://example.com/own.png +ic_warns project-url MSKITPKG008 From 1eeea98883e880dc41d4d7785114bdd66aacc025 Mon Sep 17 00:00:00 2001 From: VasiliyF <5789590+vfofanov@users.noreply.github.com> Date: Tue, 6 Oct 2026 11:36:01 +0200 Subject: [PATCH 2/3] Add MSKit_DefaultPackageIconUrl next to the kit's icon - package.targets writes it as PackageIconUrl only when the kit's own icon is packed and the project set no PackageIconUrl - MSKITPKG008 skips the kit-set URL, still reports a project-set one --- .../audit/audit.package.targets | 4 ++-- .../msbuild/DragoAnt.MSBuildKit.Packaging/package.targets | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/kit/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets b/kit/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets index bf15e43..1bad3e6 100644 --- a/kit/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets +++ b/kit/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets @@ -68,8 +68,8 @@ <_MSKit_PkgFinding Include="MSKITPKG007" Condition="'$(PackageLicenseUrl)'!=''" Text="Package '$(PackageId)' uses the deprecated PackageLicenseUrl. Replace it with PackageLicenseExpression (an SPDX id) or PackageLicenseFile." Rule="$(_MSKit_PkgRules)#licensing" /> - <_MSKit_PkgFinding Include="MSKITPKG008" Condition="'$(PackageIconUrl)'!=''" - Text="Package '$(PackageId)' uses the deprecated PackageIconUrl. Pack the image and point PackageIcon (or the kit's PackageIconPath) at it." + <_MSKit_PkgFinding Include="MSKITPKG008" Condition="'$(PackageIconUrl)'!='' AND '$(_MSKit_SetsIconUrl)'!='True'" + Text="Package '$(PackageId)' uses the deprecated PackageIconUrl. Pack the image and point PackageIcon (or the kit's PackageIconPath) at it; for older clients, set MSKit_DefaultPackageIconUrl to write the URL next to the kit's icon." Rule="$(_MSKit_PkgRules)#icon" /> <_MSKit_PkgFinding Include="MSKITPKG009" Condition="'$(_MSKit_RelativeImages)'!=''" Text="The package README of '$(PackageId)' has relative images, which nuget.org does not render: $(_MSKit_RelativeImages). Use absolute https URLs from an allowed host." diff --git a/kit/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets b/kit/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets index b299d47..2c9767e 100644 --- a/kit/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets +++ b/kit/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets @@ -56,6 +56,12 @@ icon$([System.IO.Path]::GetExtension('$(PackageIconPath)').ToLowerInvariant()) <_MSKit_PacksIcon>True + + + $(MSKit_DefaultPackageIconUrl) + <_MSKit_SetsIconUrl>True + $(PackageIconPath) $(MSBuildProjectDirectory)/$(PackageIcon) From 614513ade93457a88381dc31f3fab15298233265 Mon Sep 17 00:00:00 2001 From: VasiliyF <5789590+vfofanov@users.noreply.github.com> Date: Tue, 6 Oct 2026 11:39:26 +0200 Subject: [PATCH 3/3] Document MSKit_DefaultPackageIconUrl - property row, the icon line in packaging, the MSKITPKG008 section, the owner-layer note and an Unreleased changelog entry --- CHANGELOG.md | 1 + docs/customizing.md | 1 + docs/packaging.md | 4 ++-- docs/reference/codes.md | 2 +- docs/reference/properties.md | 1 + 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f4ca31..2218b93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project are documented here. The format follows [Kee ### 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. +- `MSKit_DefaultPackageIconUrl`: when the kit packs its own icon, this URL is also written as `PackageIconUrl`, so clients that predate embedded icons show it; nuget.org keeps showing the embedded one. Empty by default; an owner sets it in its owner layer. `MSKITPKG008` now reports only a `PackageIconUrl` the project sets itself. See [docs/packaging.md](./docs/packaging.md#package-metadata). - `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 `/mskit-manager/logs/`, named after the command, newest 20 kept. Not published yet. ### Changed diff --git a/docs/customizing.md b/docs/customizing.md index 351030a..839e619 100644 --- a/docs/customizing.md +++ b/docs/customizing.md @@ -22,6 +22,7 @@ Almost every default is written as ``, so the first va | `ManufacturerName`, `FullManufacturerName` | `DragoAnt` | **unconditional**: set them below the kit import to change them; they feed `Authors`, `Company`, `Copyright` | | `PackageLicenseExpression` | `MIT`, unless `PackageLicenseFile` is set | | | `PackageIconPath` | `.toolkit/res/package.icon.png` | | +| `MSKit_DefaultPackageIconUrl` | not set | another owner sets it here to a hosted copy of its icon, so older clients show it too ([Packaging](./packaging.md#package-metadata)) | | `MSKit_PrereleasePackagePrefix` | `DragoAnt.` | [prerelease check](./build.md#reference-checks) | | `MSKit_IsStableBranchRegex` | `^(main\|release/.+)$` | | | `MSKit_VersionStrategy` | `ReleaseTag` | [Versioning](./versioning.md) | diff --git a/docs/packaging.md b/docs/packaging.md index 1c86cfa..50e1735 100644 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -23,7 +23,7 @@ For projects with `IsPackable=True` (the owner layer makes that the default; tes | `PackageLicenseExpression` | `MIT` (owner layer), unless `PackageLicenseFile` is set | [licensing](https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices#licensing) | | `PackageRequireLicenseAcceptance` | `false` | | | `Authors`, `Copyright` | the owner; `Copyright (c) ` ([Build](./build.md#language-and-product-defaults)) | [copyright](https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices#copyright) | -| `PackageIcon` | `PackageIconPath` (owner layer: `.toolkit/res/package.icon.png`, 128×128; PNG or JPEG) packed as `icon` (`icon.png`, `icon.jpg`); a `PackageIcon` the project sets is kept | [icon](https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices#icon) | +| `PackageIcon` | `PackageIconPath` (owner layer: `.toolkit/res/package.icon.png`, 128×128; PNG or JPEG) packed as `icon` (`icon.png`, `icon.jpg`); a `PackageIcon` the project sets is kept. With the kit's icon, `MSKit_DefaultPackageIconUrl` also writes `PackageIconUrl` (nuget.org shows the embedded icon, older clients the URL) | [icon](https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices#icon) | | `PackageReadmeFile` | generated from `MSKit_PackageReadmeFrom` ([Package readme](./package-readme.md)), else `package.readme.md` next to the csproj, else `README.md` next to it; packed as `readme.md`. `MSKit_PackageReadmeSourcePath` names another file | [README](https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices#readme) | | `RepositoryType`, `RepositoryUrl`, `PackageProjectUrl` | `git`; `GITHUB_SERVER_URL/GITHUB_REPOSITORY` on GitHub Actions, else the git remote [Source Link](https://learn.microsoft.com/dotnet/standard/library-guidance/sourcelink) reads, without `.git` | [repository](https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices#repository-type-and-url) | | `PackageReleaseNotes` | on a `https://github.com/` repository the tag's release page on a tag build, else its releases page; on other hosts the releases page the generated readme links (needs `MSKit_PackageReadmeFrom`). `MSKit_DefaultReleaseNotes=False` turns the default off | [release notes](https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices#release-notes) | @@ -47,7 +47,7 @@ Set `MSKit_PackageValidationBaselineVersion` to the last published version once | [`MSKITPKG005`](./reference/codes.md#mskitpkg005) | no icon | | [`MSKITPKG006`](./reference/codes.md#mskitpkg006) | no licence expression or file | | [`MSKITPKG007`](./reference/codes.md#mskitpkg007) | the deprecated `PackageLicenseUrl` is set | -| [`MSKITPKG008`](./reference/codes.md#mskitpkg008) | the deprecated `PackageIconUrl` is set | +| [`MSKITPKG008`](./reference/codes.md#mskitpkg008) | the project sets the deprecated `PackageIconUrl` (the one `MSKit_DefaultPackageIconUrl` writes is not reported) | | [`MSKITPKG009`](./reference/codes.md#mskitpkg009) | the README has relative images | | [`MSKITPKG010`](./reference/codes.md#mskitpkg010) | the README contains HTML | | [`MSKITPKG011`](./reference/codes.md#mskitpkg011) | the README uses GitHub alerts (`> [!NOTE]`) | diff --git a/docs/reference/codes.md b/docs/reference/codes.md index bea7a21..e5add78 100644 --- a/docs/reference/codes.md +++ b/docs/reference/codes.md @@ -48,7 +48,7 @@ Earlier releases put an underscore between the prefix and the family; each secti ### MSKITPKG008 -`MSKITPKG008` (formerly `MSKIT_PKG008`) — the deprecated `PackageIconUrl` is set. Pack the image and use `PackageIcon` or `PackageIconPath`. +`MSKITPKG008` (formerly `MSKIT_PKG008`) — the project sets the deprecated `PackageIconUrl`. Pack the image and use `PackageIcon` or `PackageIconPath`. To keep a URL for older clients, set `MSKit_DefaultPackageIconUrl` instead: the kit writes it only next to its own embedded icon, and that one is not reported. ### MSKITPKG009 diff --git a/docs/reference/properties.md b/docs/reference/properties.md index 868d637..5ccdde9 100644 --- a/docs/reference/properties.md +++ b/docs/reference/properties.md @@ -95,6 +95,7 @@ Every property and item the kit sets or reads, grouped by topic. **Set** = a val | --- | --- | --- | --- | | `IsPackable` | set | `True` (owner layer); `False` for test projects and code fixes | | | `PackageIconPath` | set | `.toolkit/res/package.icon.png` (owner layer) | The icon (PNG or JPEG), packed as `icon` | +| `MSKit_DefaultPackageIconUrl` | set | empty (off) | A URL of the same icon, written as `PackageIconUrl` next to the kit's embedded icon for older clients; ignored when the project sets `PackageIcon` or `PackageIconUrl` ([Packaging](../packaging.md#package-metadata)) | | `MSKit_PackageIconSourcePath` | out | | The icon file the checks read | | `MSKit_PackageReadmeSourcePath` | set | `package.readme.md`, else `README.md` next to the csproj | The README packed as `readme.md` | | `MSKit_PackageValidationBaselineVersion` | set | empty | The release package validation compares against |