Partager via


Gestion centralisée des packages (CPM)

La gestion des dépendances est une fonctionnalité essentielle de NuGet. La gestion des dépendances pour un seul projet peut être facile. La gestion des dépendances pour les solutions multi-projets peut s’avérer difficile à mesure qu’elles commencent à s’adapter à la taille et à la complexité. Dans les situations où vous gérez les dépendances courantes pour de nombreux projets différents, vous pouvez tirer parti des fonctionnalités de gestion centralisée des packages (CPM) nuGet pour ce faire à partir de la facilité d’un emplacement unique.

Historiquement, les dépendances de package NuGet ont été gérées à l’un des deux emplacements suivants :

  • packages.config : fichier XML utilisé dans les types de projet plus anciens pour conserver la liste des packages référencés par le projet.
  • <PackageReference /> - Un élément XML utilisé dans les projets MSBuild définit les dépendances de package NuGet.

À partir de NuGet 6.2, vous pouvez gérer de manière centralisée vos dépendances dans vos projets avec l’ajout d’un fichier Directory.Packages.props et d’une propriété MSBuild.

La fonctionnalité est disponible dans tous les outils intégrés NuGet, en commençant par les versions suivantes.

Les outils plus anciens ignorent les configurations et fonctionnalités de gestion centralisée des packages. Pour utiliser cette fonctionnalité dans la mesure la plus complète, assurez-vous que tous vos environnements de build utilisent les dernières versions d’outils compatibles.

La gestion centralisée des packages s’applique à tous les projets MSBuild basés sur <PackageReference>(y compris l’ancienneCSPROJ) tant que les outils compatibles sont utilisés.

Activation de la gestion centralisée des packages

Pour commencer à gérer les packages centraux, vous devez créer un fichier Directory.Packages.props à la racine de votre référentiel et définir la propriété MSBuild ManagePackageVersionsCentrally sur true.

Vous pouvez le créer manuellement ou utiliser l’interface CLI dotnet :

dotnet new packagesprops

À l’intérieur, vous définissez ensuite chacune des versions de paquet requises pour vos projets en utilisant des éléments <PackageVersion /> qui définissent l’ID de paquet et la version.

<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
  </ItemGroup>
</Project>

Pour chaque projet, vous définissez ensuite un <PackageReference /> attribut mais omettez l’attribut Version , car la version sera obtenue à partir d’un élément correspondant <PackageVersion /> .

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" />
  </ItemGroup>
</Project>

Vous utilisez maintenant la gestion centralisée des packages et la gestion de vos versions dans un emplacement central !

Règles de gestion centralisée des packages

Le fichier Directory.Packages.props a plusieurs règles en ce qui concerne l’emplacement où il se trouve dans le répertoire d’un référentiel et son contexte. Par souci de simplicité, un seul fichier Directory.Packages.props est évalué pour un projet donné.

Cela signifie que si vous aviez plusieurs fichiers Directory.Packages.props dans votre référentiel, le fichier le plus proche du répertoire de votre projet sera évalué pour celui-ci. Cela vous permet d’effectuer un contrôle supplémentaire à différents niveaux de votre référentiel.

Tenez compte de la structure de référentiel suivante :

📂 (root)
 ├─📄 Directory.Packages.props
 |
 ├─📂Solution1
 |  ├─ 📄Directory.Packages.props
 |  |
 |  └─ 📂 Project1
 |      └─📄Project1.csproj
 |
 └─ 📂 Solution2
    └─ 📂 Project2
        └─ 📄 Project2.csproj
  • Project1.csproj chargera le fichier Directory.Packages.props dans le répertoire Repository\Solution1\ en premier, et il doit importer manuellement tous les fichiers parents si désiré.
    <Project>
      <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Packages.props, $(MSBuildThisFileDirectory)..))" />
      <ItemGroup>
        <PackageVersion Update="Newtonsoft.Json" Version="12.0.1" />
      </ItemGroup>
    </Project>
    
  • Project2.csproj évalue le Directory.Packages.props fichier dans le répertoire racine.

Note: MSBuild n’importe pas automatiquement chacun Directory.Packages.props pour vous, seul le premier trouvé dans le répertoire du projet ou n’importe quel répertoire parent. Si vous avez plusieurs Directory.Packages.props fichiers, vous devez importer les fichiers dans les répertoires parents manuellement.

Démarrer

Pour intégrer entièrement votre référentiel, procédez comme suit :

  1. Créez un fichier à la racine de votre référentiel nommé Directory.Packages.props qui déclare vos versions de package définies de manière centralisée et définissez la propriété MSBuild ManagePackageVersionsCentrally sur true.
  2. Déclarez <PackageVersion /> éléments dans votre Directory.Packages.props.
  3. Déclarez les éléments <PackageReference /> sans attributs Version dans vos fichiers de projet.

Pour une idée de comment la gestion centralisée des paquets pourrait se présenter, reportez-vous à notre dépôt d'exemples .

Épinglage transitif

Vous pouvez automatiquement remplacer une version de package transitive, même sans un <PackageReference /> explicite de niveau supérieur, en choisissant une fonctionnalité appelée épinglage transitif. Cela favorise une dépendance transitive vers une dépendance de niveau supérieur implicitement en votre nom si nécessaire. Notez que les rétrogradations ne sont pas autorisées lors du verrouillage transitif d’un paquet. Si vous tentez d’épingler un package à une version inférieure à celle demandée par vos dépendances, la restauration déclenche une erreur de NU1109.

Vous pouvez activer cette fonctionnalité en définissant la propriété MSBuild CentralPackageTransitivePinningEnabled sur true dans un projet ou dans un Directory.Packages.props ou un fichier d’importation Directory.Build.props :

<PropertyGroup>
  <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>

Épinglage transitif et pack

Lorsqu’un package est épinglé de manière transitive, votre projet utilise une valeur supérieure à celle demandée par vos dépendances. Si vous créez un package à partir de votre projet, afin de vous assurer que votre package fonctionnera correctement, NuGet convertira les dépendances indirectement fixées en dépendances explicites dans le fichier nuspec.

Dans l’exemple suivant, PackageA 1.0.0 a une dépendance sur PackageB 1.0.0.

<Project>
  <ItemGroup>
    <PackageVersion Include="PackageA" Version="1.0.0" />
    <PackageVersion Include="PackageB" Version="2.0.0" />
  </ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="PackageA" />
  </ItemGroup>
</Project>

Lorsque vous utilisez la commande pack pour créer un package, les deux packages apparaissent dans le groupe de dépendances.

      <group targetFramework="net6.0">
        <dependency id="PackageA" version="1.0.0" exclude="Build,Analyzers" />
        <dependency id="PackageB" version="2.0.0" exclude="Build,Analyzers" />
      </group>

Pour cette raison, l'utilisation de l’épinglage transitif doit être soigneusement évaluée lors de l'écriture d'une bibliothèque, car elle peut entraîner des dépendances que vous n’attendiez pas.

Remplacement des versions de paquets

Vous pouvez remplacer une version de package individuelle à l’aide de la propriété VersionOverride sur un élément <PackageReference />. Cela remplace toute <PackageVersion /> définie de manière centralisée.

<Project>
  <ItemGroup>
    <PackageVersion Include="PackageA" Version="1.0.0" />
    <PackageVersion Include="PackageB" Version="2.0.0" />
  </ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="PackageA" VersionOverride="3.0.0" />
  </ItemGroup>
</Project>

Vous pouvez désactiver cette fonctionnalité en définissant la propriété MSBuild CentralPackageVersionOverrideEnabled sur false dans un projet ou dans un fichier d'import Directory.Packages.props ou Directory.Build.props.

<PropertyGroup>
  <CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
</PropertyGroup>

Lorsque cette fonctionnalité est désactivée, la spécification d’un VersionOverride sur n’importe quel élément <PackageReference /> entraîne une erreur au moment de la restauration indiquant que la fonctionnalité est désactivée.

Désactivation de la gestion centralisée des packages

Si vous souhaitez désactiver la gestion centralisée des packages pour un projet particulier, vous pouvez la désactiver en définissant la propriété ManagePackageVersionsCentrally MSBuild sur false:

<PropertyGroup>
  <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>

Références de package globales

Remarque

Cette fonctionnalité est disponible uniquement dans Visual Studio 2022 17.4 ou version ultérieure, .NET SDK 7.0.100.preview7 ou version ultérieure, et NuGet 6.4 ou version ultérieure.

Une référence globale de package est utilisée pour spécifier qu’un package sera utilisé par chaque projet dans un référentiel. Cela inclut les packages qui effectuent le contrôle de version, étendent votre build ou tout autre package requis par tous les projets. Les références globales de package sont ajoutées au groupe d’éléments PackageReference avec les métadonnées suivantes :

  • IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"
    Cela garantit que le package est utilisé uniquement comme dépendance de développement et empêche toute référence d’assembly au moment de la compilation.
  • PrivateAssets="All"
    Cela empêche les références globales de package d’être récupérées par les dépendances en aval.

Les éléments GlobalPackageReference doivent être placés dans votre Directory.Packages.props pour être utilisés par tous les projets d'un dépôt.

<Project>
  <ItemGroup>
    <GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.5.109" />
  </ItemGroup>
</Project>

Avertissement lors de l’utilisation de plusieurs sources de package

Lorsque vous utilisez la gestion centralisée des packages, vous verrez un avertissement NU1507 si vous avez plusieurs sources de package définies dans votre configuration. Pour résoudre cet avertissement, mappez vos sources de package avec mappage de source de package ou spécifiez une source de package unique.

There are 3 package sources defined in your configuration. When using central package management, please map your package sources with package source mapping (https://aka.ms/nuget-package-source-mapping) or specify a single package source.