NuGet - запретить перезаписывать пакеты (с тем же именем и номером версии)

У меня есть настраиваемый сервер NuGet для моей компании. Все отлично работает - я могу публиковать, просматривать пакеты и т.д.

Моя единственная проблема заключается в том, что я могу опубликовать пакет с тем же именем и номером версии, тем самым перезаписав существующий пакет. Это не идеально, и я бы хотел, чтобы сервер NuGet возвращал ошибку, если пакет с тем же именем и версией уже существует.

Любые подсказки о том, как я могу это сделать?

Ответ 1

Я также очень признателен, если не захочет перезаписывать существующие пакеты. Тем не менее, это не представляется возможным, если использовать сервер NuGet из коробки. Подобный запрос функции был закрыт около двух лет назад.

Но если посмотреть на исходный код, откроется несколько вариантов. Посмотрите на метод CreatePackage(). Он использует службу IPackageAuthenticationService для проверки того, можно ли добавить указанный пакет (только проверяет ключ API) и IServerPackageRepository, чтобы фактически добавить пакет:

// Make sure they can access this package
if (Authenticate(context, apiKey, package.Id))
{
    _serverRepository.AddPackage(package);
    WriteStatus(context, HttpStatusCode.Created, "");
}

Оба передаются при использовании инсталляции конструктора, поэтому легко расширить поведение путем передачи пользовательских реализаций (измените привязки Ninject).

На первый взгляд я бы пошел на пользовательский IServerPackageRepository. Текущая реализация использует IFileSystem.AddFile(...) для добавления пакета. Вы можете использовать IFileSystem.FileExists(...), чтобы проверить, существует ли пакет.

С точки зрения непрерывного интегрирования совершенно необходимо отказаться от перезаписывания существующего пакета, поскольку NuGet следует Semantic Versioning. Таким образом, новая сборка должна включать исправление, новую функцию или изменение разрыва. Однако я бы предпочел разрешить перезапись моментальных снимков/предварительных выпусков.

Обновление: Кажется, что v2.8 будет иметь параметр allowOverrideExistingPackageOnPush, который по умолчанию имеет значение true для обратной совместимости. Он был связан с 1e7345624d. Я понял, что после разветвления. Кажется, я был слишком поздно, -)

Ответ 2

Я столкнулся с той же проблемой. Я запускаю собственный сервер SymbolSource. Я решил сохранить журнал опубликованных пакетов. Прежде чем опубликовать пакет, я могу проверить журнал, чтобы узнать, уже ли он опубликован, а затем не публиковать его. Все это делается в пакетном файле MS-DOS. См. Ниже.

@echo off

rem Requires that the Visual Studio directory is in your 
rem PATH environment variable. It will be something like:
rem C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE

rem API key for publishing to SymbolSource server
set apiKey=<<<GUID>>>

rem URL of the SymbolSource web app
set lib=http://<<<address>>>

rem Path to a simple text file on a file share - which happens to be the 
rem same place that the SymbolSource server web app is published.
set log=\\<<<path>>>\publish_log.txt

rem Path to the Visual Studio solution that contains the projects to be published.
set sln=..\<<<solution name>>>.sln

rem Build all projects in the solution.
devenv %sln% /rebuild Debug

rem Delete packages produced during last run.
del *.nupkg

rem Each line in projects.txt is a path to a .csproj file that we want to 
rem create a nuget package for. Each .csproj file has a corresponding .nuspec 
rem file that lives in the same directory.
for /F %%i in (projects.txt) do nuget.exe pack %%i -IncludeReferencedProjects -Prop Configuration=Debug -Symbols

rem Delete any local packages that have already been published.
for /F %%i in (%log%) do if exist %%i del %%i

for %%F in (".\*.symbols.nupkg") do nuget push %%~nxF %apiKey% -source %lib%

rem Log information about published packages so, in the next run,
rem we can tell what has been published and what has not.
for %%F in (".\*.symbols.nupkg") do echo %%~nxF >> %log%

Ответ 3

Я написал сценарий PowerShell, который удаляет существующую версию пакета, но только если он соответствует версии, которую я хочу отправить:

param (
    [string]$buildconfiguration = "Debug"
 )

function Update-Package ([string]$package,[string]$version,[string]$path)
{
    dotnet nuget delete $package $version -s https://<mynugetserver>/nuget -k <my access code if used> --non-interactive
    dotnet nuget push "$path\bin\$buildconfiguration\$package.$version.nupkg" -s https://<mynugetserver>/nuget -k <my access code if used>
}

Update-Package -package "My.Package" -version "2.2.0" -path "MyPackage"

Основным недостатком этого является возможность изменения пакета, при этом забыть обновить версию пакета в разделе пакета NuSpec или vsproj, а также забыть изменить номер версии в файле сценария.

Я бы никогда не использовал эту технику на общедоступном сервере NuGet.

Я также использую версию этого файла, которая не отправляет, а просто удаляет ее, которая используется в качестве задачи PowerShell в моей сборке Azure DevOps (VSTS).

Я знаю, что NuGet говорит, что в нем будут перечислены доступные версии, но на самом деле мне не хотелось писать скрипт, который мог бы прочитать результат списка, чтобы определить, существует ли уже созданный номер версии.

Одна хорошая вещь - то, что, если новый номер версии не существует, вызов CLI, чтобы удалить, не жалуется слишком, и никакая версия пакета не затронута.