Gerir atualizações de dependência no projeto .NET

Concluído

Mais cedo ou mais tarde, você deseja atualizar para uma nova versão de uma biblioteca. Talvez uma função esteja marcada como obsoleta ou talvez haja um novo recurso em uma versão posterior de um pacote que você está usando.

Considere o seguinte antes de tentar atualizar uma biblioteca:

  • O tipo de atualização: Que tipo de atualização está disponível? É uma pequena correção de erros? Está a adicionar uma nova funcionalidade necessária? Ele quebra o seu código? Pode comunicar o tipo de atualização através de um sistema denominado controlo de versões semântico. A forma como o número de versão da biblioteca é expresso comunica aos desenvolvedores o tipo de atualização com a qual eles estão lidando.
  • Se o projeto está configurado corretamente: Você pode configurar seu projeto .NET para obter apenas os tipos de atualizações desejados. Você executa uma atualização somente se um tipo específico de atualização estiver disponível. Recomendamos essa abordagem, porque você não corre o risco de ter surpresas.
  • Problemas de segurança: gerenciar as dependências do seu projeto ao longo do tempo envolve estar ciente dos problemas que podem acontecer. Os problemas ocorrem à medida que as vulnerabilidades são detetadas, por exemplo. Idealmente, são lançados patches que você pode baixar. A ferramenta .NET Core ajuda-o a executar uma auditoria nas suas bibliotecas para saber se tem pacotes que devem ser atualizados. Também o ajuda a tomar as medidas adequadas para corrigir um problema.

Utilizar o controlo de versões semântico

Há um padrão do setor chamado versionamento semântico, que é como você expressa o tipo de alteração que você ou algum outro desenvolvedor está introduzindo em uma biblioteca. O controle de versão semântico funciona garantindo que um pacote tenha um número de versão e que o número da versão seja dividido nestas seções:

  • Versão principal: O número mais à esquerda. Por exemplo, é o 1 in 1.0.0. Uma alteração nesse número significa que você pode esperar "alterações de quebra" em seu código. Poderá ser necessário reescrever parte do seu código.
  • Versão secundária: O número do meio. Por exemplo, é o 2 in 1.2.0. Uma alteração nesse número significa que os recursos foram adicionados. O seu código deve continuar a funcionar. Normalmente, é seguro aceitar a atualização.
  • Versão do patch: O número mais à direita. Por exemplo, é o 3 in 1.2.3. Uma alteração nesse número significa que foi aplicada uma alteração que corrige algo no código que deveria estar funcionando. Deve ser seguro aceitar a atualização.

Esta tabela ilustra como o número da versão muda para cada tipo de versão:

Type O que acontece
Versão principal 1.0.0 alterações à 2.0.0
Versão secundária 1.1.1 alterações à 1.2.0
Versão de Patch 1.0.1 alterações à 1.0.2

Muitas empresas e desenvolvedores usam este sistema. Se você pretende publicar pacotes e enviá-los por push para o registro NuGet, espera-se que siga o controle de versão semântico. Mesmo que transfira apenas pacotes do registo do NuGet, é expectável que estes pacotes sigam o controlo de versões semântico.

As alterações a um pacote podem introduzir riscos, incluindo o risco de um erro que pode prejudicar a sua empresa. Alguns riscos podem exigir que reescreva parte do código. Reescrever o código leva tempo e custa dinheiro.

Abordagem da atualização

Como um desenvolvedor .NET, você pode comunicar o comportamento de atualização que você deseja .NET. Pense na atualização consoante o risco. Eis algumas abordagens:

  • Versão principal: Estou bem com a atualização para a versão principal mais recente assim que ela for lançada. Eu aceito o fato de que eu posso precisar mudar o código do meu lado.
  • Versão secundária: Estou bem com um novo recurso sendo adicionado. Não aceito que código seja quebrado.
  • Versão do patch: As únicas atualizações com as quais estou bem são correções de bugs.

Se estiver a gerir um projeto .NET novo ou pequeno, pode dar-se ao luxo de não ser demasiado rigoroso com a forma como define a estratégia de atualização. Por exemplo, pode sempre atualizar para a versão mais recente. Para projetos mais complexos, existe mais nuance, mas iremos abordar este tema num módulo futuro.

Em geral, quanto menor a dependência que você está atualizando, menos dependências ela tem e maior a probabilidade de que o processo de atualização seja fácil.

Configurar o ficheiro de projeto para atualização

Quando você estiver adicionando uma ou mais dependências, configure seu arquivo de projeto para que você obtenha um comportamento previsível ao restaurar, compilar ou executar seu projeto. Pode comunicar a abordagem que pretende adotar para um pacote. O NuGet tem os conceitos de intervalos de versões e versões flutuantes.

Os intervalos de versões são uma notação especial que você pode usar para indicar um intervalo específico de versões que deseja resolver.

Anotações Regra aplicada Description
1.0 x >= 1,0 Versão mínima, inclusive
(1.0,) x > 1,0 Versão mínima, exclusive
[1.0] x == 1.0 Correspondência de versão exata
(,1.0] x ≤ 1.0 Versão máxima, inclusive
(,1.0) x < 1,0 Versão máxima, exclusive
[1.0,2.0] 1.0 ≤ x ≤ 2.0 Intervalo exato, inclusive
(1.0,2.0) 1,0 < x < 2,0 Intervalo exato, exclusive
[1.0,2.0) 1,0 ≤ x < 2,0 Versão mínima inclusiva e versão máxima exclusiva
(1.0) inválido inválido

O NuGet também suporta o uso de uma notação de versão flutuante para partes principais, secundárias, patch e sufixo de pré-lançamento do número. Esta notação é um asterisco (*). Por exemplo, a especificação da versão 6.0.* diz "use a versão 6.0.x mais recente". Em outro exemplo, 4.* significa "usar a versão 4.x mais recente". O uso de uma versão flutuante reduz as alterações no arquivo de projeto, mantendo-se atualizado com a versão mais recente de uma dependência.

Nota

Recomendamos a instalação de uma versão específica em vez de utilizar as notações flutuantes. A instalação de uma versão específica garante que suas compilações sejam repetíveis, a menos que você solicite explicitamente uma atualização para uma dependência.

Ao utilizar uma versão flutuante, o NuGet resolve a versão mais recente de um pacote correspondente ao padrão da versão. No exemplo a seguir, 6.0.* obtém a versão mais recente de um pacote que começa com 6.0. Essa versão é a 6.0.1.

Diagrama mostrando a escolha da versão mais recente quando uma versão flutuante é solicitada.

Eis alguns exemplos que pode configurar para as versões principal, secundária ou de patch:

<!-- Accepts any version 6.1 and later. -->
<PackageReference Include="ExamplePackage" Version="6.1" />

<!-- Accepts any 6.x.y version. -->
<PackageReference Include="ExamplePackage" Version="6.*" />
<PackageReference Include="ExamplePackage" Version="[6,7)" />

<!-- Accepts any later version, but not including 4.1.3. Could be
     used to guarantee a dependency with a specific bug fix. -->
<PackageReference Include="ExamplePackage" Version="(4.1.3,)" />

<!-- Accepts any version earlier than 5.x, which might be used to prevent pulling in a later
     version of a dependency that changed its interface. However, we don't recommend this form because determining the earliest version can be difficult. -->
<PackageReference Include="ExamplePackage" Version="(,5.0)" />

<!-- Accepts any 1.x or 2.x version, but not 0.x or 3.x and later. -->
<PackageReference Include="ExamplePackage" Version="[1,3)" />

<!-- Accepts 1.3.2 up to 1.4.x, but not 1.5 and later. -->
<PackageReference Include="ExamplePackage" Version="[1.3.2,1.5)" />

Encontrar e atualizar pacotes desatualizados

O comando dotnet list package --outdated apresenta uma lista de pacotes desatualizados. Este comando pode ajudá-lo a saber quando estão disponíveis versões de pacotes mais recentes. Eis um resultado típico deste comando:

Top-level Package      Requested   Resolved   Latest
> Humanizer            2.7.*       2.7.9      2.8.26

Eis os significados dos nomes das colunas do resultado:

  • Requested: A versão ou intervalo de versões que você especificou.
  • Resolved: A versão real baixada para o projeto que corresponde à versão especificada.
  • Latest: A versão mais recente disponível para atualização do NuGet.

O fluxo de trabalho recomendado é executar os seguintes comandos, nesta ordem:

  1. Execute o dotnet list package --outdated. Este comando apresenta uma lista de todos os pacotes desatualizados. Fornece informações nas colunas Requested, Resolved e Latest.
  2. Execute o dotnet add package <package name>. Se você executar esse comando, ele tentará atualizar para a versão mais recente. Opcionalmente, pode transmitir --version=<version number/range>.