Skip to content
BETAGuardrails are in beta. The library, the configuration format and the CLI command can still change.

Guardrails / Collectors

.NET build

The .NET build in the project directory: the SDK it pins, every project file and the frameworks each targets, the packages they reference and which of them are pinned or supplied centrally, and the lock files beside them.

Facts keydotnet
Versionv1
Scriptdotnet.py
Timeout45 seconds

Inputs

InputDescriptionDefaultEnvironment
projectDirDirectory holding the project, relative to the directory the CLI runs in..GUARDRAIL_INPUT_PROJECTDIR
maxProjectsMost project files to describe. A solution past this carries the ones found first in path order.200GUARDRAIL_INPUT_MAXPROJECTS

A guardrail that declares an input of the same name passes it through, so the guardrail's configuration in buildnote.json is what decides these values.

A guardrail asks for these facts by name, and reads them back the same way:

json
{
  "collect": ["dotnet"]
}
python
dotnet = guardrail.facts("dotnet")

Facts

The document dotnet collects. A path carrying [] is an entry of the list before it, and one carrying [path] is a key of the object before it.

FactMeaning
directoryThe projectDir input, as the guardrail configured it.
existsWhether that directory is there. Nothing else is collected when it is not.
manifestPath of the primary manifest, relative to projectDir: the solution when the checkout has one, otherwise the first project file found.
sourcesEvery project file, global.json and Directory.Packages.props that was read and understood. One the reader could not handle is in unparsed instead.
declaredThe SDK version global.json pins, or null when the checkout pins none and whatever SDK the runner has is used.
declared.versionVersion exactly as written, such as 8.0.204.
declared.sourceFile declaring it, relative to projectDir.
declared.pinnedWhether the SDK is held to that version. A rollForward other than disable lets a newer SDK take over, so it is not pinned.
rollForwardThe rollForward policy global.json declares, such as latestFeature, or null when it declares none.
targetFrameworksEvery target framework moniker any project declares, sorted, such as net8.0. A project targeting several carries all of them.
solutionPath of the solution file, relative to projectDir, or null when the checkout carries none.
centralPackageManagementWhether a Directory.Packages.props declares the versions centrally, which is what makes a PackageReference without a version correct rather than broken.
projectsEvery project file found, in path order.
projects[].pathDirectory of the project, relative to projectDir, . for the project directory itself.
projects[].manifestThe project file, relative to projectDir.
projects[].nameAssembly name the project declares, or the project file's own stem when it declares none.
projects[].targetFrameworksTarget framework monikers that project declares.
dependenciesWhat the projects reference, split by whether the build asks for it itself.
dependencies.directEvery PackageReference any project declares, in project order.
dependencies.direct[].namePackage id, such as Serilog.
dependencies.direct[].versionVersion exactly as written, or null when the reference carries none and a central version supplies it.
dependencies.direct[].scopesdefault, or development when the reference sets PrivateAssets to all, which keeps it out of what consumers restore.
dependencies.direct[].sourceProject file declaring it, relative to projectDir.
dependencies.direct[].pinnedWhether the version names one exact release. A floating 8.0.*, a range in brackets and an unresolved $(Property) are not pinned.
dependencies.direct[].managedByDirectory.Packages.props when a central PackageVersion supplied the version, or null when the reference carried its own.
dependencies.transitiveAlways empty. What packages.lock.json resolves is not read: lockfiles says whether one is committed.
lockfilesEvery packages.lock.json committed, relative to projectDir. Restore only honours them when the build sets RestorePackagesWithLockFile.
droppedProject files left out because maxProjects was reached. Above zero means projects and dependencies describe part of the solution rather than all of it.
unparsedEvery file the reader could not handle, so a guardrail can tell a build that declares nothing from one nobody could read.
unparsed[].pathPath of that file, relative to projectDir.
unparsed[].reasonWhat stopped the reader.

A collector that cannot finish prints what it had along with an incomplete key saying why, so the facts below the point it stopped are absent. A check that cares reads incomplete before the rest.

Example facts

The example facts collected by dotnet collector:

json
{
  "directory": ".",
  "exists": true,
  "manifest": "src/Widget/Widget.csproj",
  "sources": [
    "Directory.Packages.props",
    "global.json",
    "src/Widget/Widget.csproj"
  ],
  "declared": {
    "version": "8.0.204",
    "source": "global.json",
    "pinned": true
  },
  "rollForward": "disable",
  "targetFrameworks": [
    "net8.0"
  ],
  "solution": null,
  "centralPackageManagement": true,
  "projects": [
    {
      "path": "src/Widget",
      "manifest": "src/Widget/Widget.csproj",
      "name": "Acme.Widget",
      "targetFrameworks": [
        "net8.0"
      ]
    }
  ],
  "dependencies": {
    "direct": [
      {
        "name": "Serilog",
        "version": "4.0.0",
        "scopes": [
          "default"
        ],
        "source": "src/Widget/Widget.csproj",
        "pinned": true,
        "managedBy": "Directory.Packages.props"
      },
      {
        "name": "Npgsql",
        "version": "8.0.3",
        "scopes": [
          "default"
        ],
        "source": "src/Widget/Widget.csproj",
        "pinned": true,
        "managedBy": null
      },
      {
        "name": "StyleCop.Analyzers",
        "version": "1.2.0-beta.556",
        "scopes": [
          "development"
        ],
        "source": "src/Widget/Widget.csproj",
        "pinned": true,
        "managedBy": null
      }
    ],
    "transitive": []
  },
  "lockfiles": [
    "src/Widget/packages.lock.json"
  ],
  "dropped": 0,
  "unparsed": []
}

Collected for

GuardrailCategoryInputs
dotnet/central-package-managementdotnetprojectDir
dotnet/dependencies-versioneddotnetprojectDir
dotnet/sdk-pinneddotnetprojectDir
dotnet/target-framework-floordotnetprojectDir

All collectors

Buildnote Limited
Registered in England and Wales, Reg: 16140412