Construir pacotes determinísticos

A partir do .NET 11, os pacotes NuGet são determinísticos (ou reproduzíveis) por defeito.

Isto significa que reconstruir o mesmo pacote deve gerar um ficheiro nupkg idêntico.

A única ressalva conhecida é o tempo de modificação nos ficheiros. Os pacotes NuGet contêm vários ficheiros. O carimbo temporal da modificação do ficheiro nesses ficheiros baseia-se no carimbo temporal dos ficheiros originais no disco, que pode mudar por várias razões, mesmo que o conteúdo dos ficheiros seja idêntico.

Para criar pacotes NuGet idênticos a bits, pode definir a DeterministicTimestamp propriedade para um valor conhecido/fixo. Para reproduzir um pacote existente, podes encontrar o valor DeterministicTimestamp usado por essa build e passá-lo para uma nova build que queiras fazer.

A variável de ambiente bem conhecida SOURCE_DATE_EPOCH pode ser definida para ativar o mesmo comportamento que definir DeterministicTimestamp.

Construir pacotes determinísticos

Construir em modo determinístico é o padrão a partir do .NET 11.

  • Usando a linha de comandos:

    dotnet pack
    

Se quiseres definir o tempo com base no tempo de commit do último commit do Git, podes usar algo assim:

export DeterministicTimestamp=$(git log -1 --pretty=%ct)
echo $DeterministicTimestamp
dotnet pack

Isto irá definir a variável de ambiente chamada DeterministicTimestamp para o timestamp do commit git, que o msbuild irá usar automaticamente. Reproduzir o pacote é então uma questão de executar novamente o mesmo conjunto de comandos.

Replicar um pacote

Se quiseres reproduzir um pacote idêntico, bit a bit, descobre o valor DeterministicTimestamp usado na primeira compilação e volta a usá-lo:

dotnet pack -p:DeterministicTimestamp=<value from previous build>

Desativar marcas temporais fixas

Se quiser manter as datas de modificação originais dos ficheiros nos seus pacotes NuGet, pode definir DeterministicTimestamp para false.

  • Usando a linha de comandos:

    dotnet pack -p:DeterministicTimestamp=false
    
  • Utilizar o ficheiro .csproj:

    <PropertyGroup>
        <DeterministicTimestamp>false</DeterministicTimestamp>
    </PropertyGroup>