[Infra] cgmanifest.json generation drops SQLitePCLRaw registration; checked-in manifest is stale and guidance is contradictory
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 297
Description
### Description
The Component Governance manifest infrastructure for `src/Templates/src/cgmanifest.json` has a concrete dependency-coverage bug plus several process/documentation issues that make it easy for the manifest to drift.
## 1. Concrete bug: SQLitePCLRaw is dropped by regeneration
`eng/scripts/update-cgmanifest.ps1` maps:
```powershell
'SQLitePCLRaw.bundle_e_sqlite3' = 'SQLitePCLRawBundleESqlite3PackageVersion'
```
at `eng/scripts/update-cgmanifest.ps1:60`, but there is no `SQLitePCLRawBundleESqlite3PackageVersion` in `eng/Versions.props`. The only related property I found is `SQLitePCLRawBundleGreenPackageVersion` at `eng/Versions.props:171`.
I verified the template dependency with grep on both this PR branch and `origin/net11.0`: `src/Templates/src/templates/maui-mobile/MauiApp.1.csproj:86` references:
```xml
```
Running the generator prints:
```text
WARNING: Could not find version for SQLitePCLRaw.bundle_e_sqlite3 (property: SQLitePCLRawBundleESqlite3PackageVersion)
```
and emits no registration for that package. Because the script then replaces the whole registrations array (`eng/scripts/update-cgmanifest.ps1:146`), the checked-in `SQLitePCLRaw.bundle_green` entry at `src/Templates/src/cgmanifest.json:116-117` is deleted on regeneration, but no `SQLitePCLRaw.bundle_e_sqlite3` entry is added.
So today the checked-in manifest has a stale/wrong SQLite package (`SQLitePCLRaw.bundle_green` `2.1.10`), while the package actually used by the template (`SQLitePCLRaw.bundle_e_sqlite3` `3.0.3`) is not represented after generation.
## 2. Documentation bug: docs say manual entries are preserved, but the script replaces everything
`docs/CgManifest.md:108` says:
> If you need to manually add packages that aren't in `Versions.props`, you can edit the `cgmanifest.json` file directly. The update scripts preserve manually added entries and only update versions for packages it knows about.
That is not what the script does. It builds a new list and assigns it wholesale:
```powershell
$cgManifest.registrations = $sortedRegistrations
```
at `eng/scripts/update-cgmanifest.ps1:146`.
This makes the SQLitePCLRaw issue more dangerous: contributors are told direct edits are preserved, but regeneration silently removes any entry not backed by the script/version mapping.
There is also a small typo at `docs/CgManifest.md:18`: `dotnet tool resotre` should be `dotnet tool restore`.
## 3. The checked-in manifest is stale on `net11.0`
I backed up `src/Templates/src/cgmanifest.json`, ran:
```bash
pwsh -NonInteractive -ExecutionPolicy Bypass -File eng/scripts/update-cgmanifest.ps1
```
then restored the file. The generated manifest differed from the committed file (`1 file changed, 26 insertions(+), 17 deletions(-)` on the current #35950 branch, which already adds Avalonia registrations). Meaningful drift included:
| Package | Checked-in `src/Templates/src/cgmanifest.json` | Generated from `eng/Versions.props` |
| --- | --- | --- |
| `Microsoft.Extensions.Configuration` | `10.0.0` (`cgmanifest.json:53-54`) | `11.0.0-preview.7.26365.101` |
| `Microsoft.Extensions.DependencyInjection` | `10.0.0` (`cgmanifest.json:62-63`) | `11.0.0-preview.7.26365.101` |
| `Microsoft.Extensions.Logging.Debug` | `10.0.0` (`cgmanifest.json:71-72`) | `11.0.0-preview.7.26365.101` |
| `Microsoft.WindowsAppSDK` | `1.8.251106002` (`cgmanifest.json:107-108`) | `2.3.1` |
| `Microsoft.Graphics.Win2D` | `1.3.2` (`cgmanifest.json:80-81`) | `1.4.0` |
| `Microsoft.Windows.SDK.BuildTools` | `10.0.26100.4654` (`cgmanifest.json:98-99`) | `10.0.28000.2526` |
| `xunit` | `2.9.0` (`cgmanifest.json:134-135`) | `2.9.3` |
| `xunit.analyzer` | `1.15.0` (`cgmanifest.json:143-144`) | `1.18.0` |
| `SQLitePCLRaw.bundle_green` | `2.1.10` (`cgmanifest.json:116-117`) | deleted, and no `SQLitePCLRaw.bundle_e_sqlite3` replacement is emitted |
## 4. Nothing appears to keep the checked-in copy in sync, and it may not need to be checked in
`eng/CgManifest.targets` is imported at the top of `src/Templates/src/Microsoft.Maui.Templates.csproj` (`Microsoft.Maui.Templates.csproj:3`). Its `UpdateCgManifest` target runs before build by default:
- `eng/CgManifest.targets:15` defaults `UpdateCgManifestBeforeBuild` to `true`.
- `eng/CgManifest.targets:24` runs `UpdateCgManifest` `BeforeTargets="BeforeBuild"`.
- `src/Templates/src/Microsoft.Maui.Templates.csproj:148` also sets `UpdateCgManifestBeforeBuild` to `true`.
That means template builds regenerate the file on disk, but the generated working-tree change is thrown away unless a human notices and commits it. I did not find a workflow/pipeline under `.github/workflows` or `eng/pipelines` that sets `GenerateCgManifest=true` or gates on `src/Templates/src/cgmanifest.json` being clean after regeneration.
Also, `src/Templates/src/Microsoft.Maui.Templates.csproj:65` only packs the manifest when `GenerateCgManifest` is true:
```xml
```
The property defaults to false (`eng/CgManifest.targets:20`, `Microsoft.Maui.Templates.csproj:150`), and I only found examples/docs/target declarations, not a real pipeline setting it to true. So the manifest does not appear to be shipped in the template nupkg today.
That raises the design question: if the Component Governance scanner only needs this file on disk at build/scan time, and the build already regenerates it before the scan, should `src/Templates/src/cgmanifest.json` be `.gitignore`d and treated as a build artifact instead of checked in? The checked-in copy seems to drift permanently and creates confusing PR diffs.
## 5. Repo guidance is contradictory
Different repo guidance says different things:
- `.github/copilot-instructions.md:150-154`: `cgmanifest.json` is auto-generated and must not be committed.
- `.github/agents/maui-expert-reviewer.md:436`: never commit `cgmanifest.json`.
- `.github/instructions/templates.instructions.md:72-76`: never modify `cgmanifest.json`; it is regenerated during build.
- `docs/CgManifest.md:108`: says contributors can edit `cgmanifest.json` directly and manual entries are preserved.
History also shows manual commits: #32360 (`Update cgmanifest`) was authored by a human; #32361 appears to be the automated backport. This contradiction surfaced again in #35950, where a contributor reasonably hand-edited the manifest and review had to determine whether it was needed.
## Proposed fixes
1. Fix the SQLitePCLRaw mapping so the package actually referenced by the template is emitted. Options include:
- add a `SQLitePCLRawBundleESqlite3PackageVersion` property with the template's `3.0.3` value and keep the current mapping, or
- update the script/mapping/template version source so `SQLitePCLRaw.bundle_e_sqlite3` resolves consistently.
2. Remove or correct the false `docs/CgManifest.md:108` claim that manual entries are preserved.
3. Fix the `dotnet tool resotre` typo in `docs/CgManifest.md:18`.
4. Decide the intended model for `src/Templates/src/cgmanifest.json`:
- treat it as a generated build artifact and `.gitignore` it, or
- keep it checked in but add a CI/build verification gate that regenerates and fails on drift.
5. Reconcile `.github/*` agent/contributor instructions with `docs/CgManifest.md` so contributors get one consistent rule.
Related context: this was surfaced while reviewing #35950. Prior manual update example: #32360. This issue intentionally does not use closing keywords.
### Steps to Reproduce
1. From a clean `net11.0`-based checkout, inspect `eng/scripts/update-cgmanifest.ps1:60` and `eng/Versions.props:171`.
2. Confirm `src/Templates/src/templates/maui-mobile/MauiApp.1.csproj:86` references `SQLitePCLRaw.bundle_e_sqlite3`.
3. Back up `src/Templates/src/cgmanifest.json`.
4. Run `pwsh -NonInteractive -ExecutionPolicy Bypass -File eng/scripts/update-cgmanifest.ps1`.
5. Observe the warning for `SQLitePCLRaw.bundle_e_sqlite3` and the generated diff that deletes `SQLitePCLRaw.bundle_green` without adding `SQLitePCLRaw.bundle_e_sqlite3`.
6. Restore the backed-up manifest.
Expected outcome: every NuGet package that the templates require and that CG cannot otherwise discover is represented in the generated manifest, and the committed/generated state is either intentionally absent or kept in sync.
Actual outcome: `SQLitePCLRaw.bundle_e_sqlite3` is omitted by generation, the checked-in manifest is stale, and repo docs/instructions conflict on whether direct manifest edits are allowed.
### Link to public reproduction project repository
N/A
### Version with bug
11.0.0-preview.6 / `net11.0` branch infrastructure
### Is this a regression from previous behavior?
Not sure, did not test other versions
### Last version that worked well
Unknown/Other
### Affected platforms
Other (engineering infrastructure / Component Governance)
### Affected platform versions
N/A
### Did you find any workaround?
Manual restoration/edits are possible, but the current generator will remove entries it does not know how to recreate. A reliable workaround is to fix the mapping/version source or stop checking in the generated file.
### Relevant log output
```shell
Reading versions from: .../eng/Versions.props
Reading existing cgmanifest.json: .../src/Templates/src/cgmanifest.json
Setting up CommunityToolkit.Maui entries...
WARNING: Could not find version for SQLitePCLRaw.bundle_e_sqlite3 (property: SQLitePCLRawBundleESqlite3PackageVersion)
Updated cgmanifest.json saved to: .../src/Templates/src/cgmanifest.json
Successfully added 18 package registrations to cgmanifest.json
```
Contributor guide
Research direction
Start with eng/scripts/update-cgmanifest.ps1, eng/Versions.props, and src/Templates/src/templates/maui-mobile/MauiApp.1.csproj, then run the documented PowerShell generator to reproduce the missing SQLitePCLRaw registration. Review src/Templates/src/cgmanifest.json, eng/CgManifest.targets, the template project, docs/CgManifest.md, and the referenced .github guidance. Done means the dependency coverage, generated-file policy, and contributor instructions agree and the documented regeneration outcome is correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, powershell
- Domain
- build-system, documentation, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100