如何检查在指定的包源(nuget服务器)中是否存在带有特定版本的nuget包,使用powershell或visual之外的命令行?
设想情况:
我有一个私有的NuGet服务器,我想在这里推送自己的包。在TFS构建过程中,我已经自动创建了包。我错过的是检查包是否先前上传并发布到NuGet服务器。
发布于 2019-10-24 21:26:18
您可以很容易地从PowerShell调用这个CMD脚本,下面就是例子。您可以通过$LastExitCode
来确定如何继续进行,0
意味着您可以发布:
check_nupkg.bat
@echo off
SetLocal EnableDelayedExpansion EnableExtensions
pushd "%~dp0"
set "pkg_name=%~1"
set "pkg_version=%~2"
call nuget list %pkg_name% -AllVersions -Prerelease|findstr /i /r /c:"^%pkg_name% %pkg_version%$" -N>nul 2>&1
if not "%errorlevel%"=="0" (
echo This package can be published
exit /b 0
) else (
echo This package has already been published.
exit /b 1
)
C:\stuff>.\check_nupkg.bat "lolspeak" "1.0.0"
This package has already been published.
C:\stuff>check_nupkg.bat "lolspeak" "11.0.0"
This package can be published
发布于 2019-09-06 13:55:58
我不知道您的私有NuGet服务器是否实现了与nuget.org相同的服务器Api,但我假设它实现了。https://learn.microsoft.com/en-us/nuget/api/registration-base-url-resource描述了可用于检查包是否已发布并获得其版本的API。与nuget list
命令不同,它通过包Id执行精确的匹配。
例如,假设您希望知道包AjaxMin是否已发布。执行nuget list ajaxmin
并不是很有帮助:
C:\> nuget.exe list ajaxmin
BundleTransformer.MicrosoftAjax 1.10.0
Bundler.NET 1.5.7
CodeSlice.Web.Baler.Extensions.AjaxMinifier 0.2.0
combres 2.3.0.4
combres.log4net 2.3.0.4
combres.mvc 2.3.0.4
Delegate.AjaxMinBuilder 1.1.2
DotLessMinification 0.42.1
AjaxMin 5.14.5506.26202
NUglify 1.5.1
NUglify 1.5.13
Pvc.Ajaxmin 0.0.2
RequestReduce 1.8.76
WebMarkupMin.Core 2.6.0
WebMarkupMin.MsAjax 2.6.0
Web.Optimization.Bundles.AjaxMin 0.0.8
Web.Optimization.Bundles.YUI 0.0.8
C:\>
是的,你可以过滤输出,但是我发现它工作太多了。通过使用服务器Api,您可以更加精确。观察:
C:\> $url = 'https://api.nuget.org/v3/registration3-gz-semver2/ajaxmin/index.json'
C:\> $res = Invoke-RestMethod $url
C:\> $res.items.items.catalogEntry.version
4.12.4057.21792
4.13.4076.28499
4.19.4141.18463
4.30.4295.16112
4.36.4337.24224
4.37.4345.34101
4.39.4362.37207
4.40.4369.35534
4.41.4378.21434
4.42.4387.23950
4.43.4392.20083
4.44.4396.18853
4.45.4416.14249
4.46.4422.26284
4.47.4452.34008
4.48.4489.28432
4.49.4503.16524
4.50.4504.34801
4.51.4507.18296
4.52.4518.14738
4.53.4526.21623
4.54.4533.37029
4.55.4545.19776
4.56.4560.33404
4.58.4566.27257
4.59.4576.13504
4.60.4609.17023
4.61.4617.31171
4.62.4618.15628
4.63.4630.14654
4.64.4630.17932
4.66.4633.35991
4.67.4639.17289
4.68.4663.23906
4.69.4665.24361
4.70.4668.12892
4.71.4679.26350
4.72.4679.35523
4.73.4685.17669
4.74.4698.25434
4.75.4713.17606
4.76.4714.20550
4.77.4723.25304
4.78.4724.23869
4.80.4763.16598
4.81.4769.14860
4.82.4784.14537
4.83.4785.14876
4.84.4790.14417
4.85.4828.21154
4.86.4836.34222
4.89.4861.30057
4.90.4864.13402
4.91.4875.26882
4.92.4896.13361
4.93.4902.12739
4.94.4916.15482
4.95.4924.12392
4.96.4941.15389
4.97.4951.28483
5.0.5007.14585
5.1.5007.23730
5.2.5021.15814
5.3.5068.16463
5.4.5085.25629
5.5.5091.22839
5.6.5100.19204
5.7.5124.21499
5.8.5172.27710
5.9.5229.26438
5.10.5260.16959
5.11.5295.12309
5.12.5436.22734
5.13.5463.15282
5.14.5506.26202
C:\>
我们得到了这个包裹的所有版本。现在,如果您想检查某个版本是否已经发布-您可以:
C:\> $url = 'https://api.nuget.org/v3/registration3-gz-semver2/ajaxmin/5.14.5506.26202.json'
C:\> $res = Invoke-RestMethod $url
C:\> $res
@id : https://api.nuget.org/v3/registration3-gz-semver2/ajaxmin/5.14.5506.26202.json
@type : {Package, http://schema.nuget.org/catalog#Permalink}
catalogEntry : https://api.nuget.org/v3/catalog0/data/2018.10.06.23.54.33/ajaxmin.5.14.5506.26202.json
listed : True
packageContent : https://api.nuget.org/v3-flatcontainer/ajaxmin/5.14.5506.26202/ajaxmin.5.14.5506.26202.nupkg
published : 2015-01-28T22:45:45.577+00:00
registration : https://api.nuget.org/v3/registration3-gz-semver2/ajaxmin/index.json
@context : @{@vocab=http://schema.nuget.org/schema#; xsd=http://www.w3.org/2001/XMLSchema#; catalogEntry=; registration=; packageContent=; published=}
C:\>
现在,如果我们要求一个不存在的版本,会发生什么?我们开始:
C:\> $url = 'https://api.nuget.org/v3/registration3-gz-semver2/ajaxmin/5.14.5506.26196.json'
C:\> $res = Invoke-RestMethod $url
Invoke-RestMethod : BlobNotFoundThe specified blob does not exist.
RequestId:cd1579e6-801e-007d-5eba-64ac9d000000
Time:2019-09-06T13:53:54.6832811Z
At line:1 char:8
+ $res = Invoke-RestMethod $url
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
C:\>
要求一个不存在的包怎么样?让我们搜索ajaxmi (no 'n'):
C:\> $url = 'https://api.nuget.org/v3/registration3-gz-semver2/ajaxmi/index.json'
C:\> $res = Invoke-RestMethod $url
Invoke-RestMethod : BlobNotFoundThe specified blob does not exist.
RequestId:23d96274-b01e-0018-3bba-641dc0000000
Time:2019-09-06T13:55:35.5288968Z
At line:1 char:8
+ $res = Invoke-RestMethod $url
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
C:\>
发布于 2020-03-12 17:35:17
我所使用的方法,基于其他一些答案,最近有所突破,所以我想更全面地描述一下我们如何发现URL并进行实际的验证。
NuGet.org提供了一个服务指标,它提供了按类型索引的基本URL列表。此服务索引可在https://api.nuget.org/v3/index.json
上使用。
它以以下结构返回数据(为简洁起见而截断):
PS> Invoke-RESTmethod -uri 'https://api.nuget.org/v3/index.json'
version resources
------- ---------
3.0.0 {@{@id=https://azuresearch-usnc.nuget.org/query; ...
换句话说,服务索引提供了一组可用的API版本和相应的资源集(即端点/可查询API)。这些资源对应于具有非常特定功能的URL,这些URL都应该被记录下来。在撰写本文时,我们只有3.0.0版本的选项,所以让我们检查一下这些资源,我们可以看到这些端点是什么样子,将输出过滤到与包注册和元数据相关的端点
PS> (Invoke-RESTmethod -uri 'https://api.nuget.org/v3/index.json' | `
? { $_.version -eq '3.0.0' }).resources | `
? { $_.'@type' -like '*Registration*' } | `
select-object -Property '@id','@type'
@id @type
--- -----
https://api.nuget.org/v3/registration4/ RegistrationsBaseUrl
https://api.nuget.org/v3/registration4/ RegistrationsBaseUrl/3.0.0-rc
https://api.nuget.org/v3/registration4/ RegistrationsBaseUrl/3.0.0-beta
https://api.nuget.org/v3/registration4-gz/ RegistrationsBaseUrl/3.4.0
https://api.nuget.org/v3/registration4-gz-semver2/ RegistrationsBaseUrl/3.6.0
https://api.nuget.org/v3/registration4-gz-semver2/ RegistrationsBaseUrl/Versioned
我忽略了输出的一个有用的属性是,存在一个comment
属性,它提供了对端点的有用描述。例如,对于RegistrationsBaseUrl
,我们有以下注释:
存储NuGet包注册信息的Azure存储库的基本URL
从上面,我们可以看到我们的基本URL将是上面左边的URL之一。检查医生们是否有@type
RegistrationsBaseUrl:
这些注册没有被压缩(这意味着它们使用了隐含的内容-编码:标识)。SemVer 2.0.0包是排除的。
为了满足我的需要,我希望包含SemVer 2.0.0,所以我想使用不同的端点。再次检查医生们
这些注册是使用内容编码: gzip压缩的。SemVer 2.0.0包包含在这个单元中。
因此,根据前面的查询结果,我需要以下url:
https://api.nuget.org/v3/registration4-gz-semver2/
在阅读文档时,我们了解到我们对我们要查询的包的注册页感兴趣。URL语法将是:
$BASEURL/<PackageName>/<PackageVersion>.json
使用Newtonsoft.Json作为示例包并展开:
https://api.nuget.org/v3/registration4-gz-semver2/newtonsoft.json/12.0.3.json
既然我们知道了如何获得URL,以及它可能随时间变化并应该被动态检索这一事实,让我们编写一些PowerShell,以确定是否已经将NuGet包发布到给定的源:
param (
[Parameter(Mandatory=$true)]
[string]$Id,
[Parameter(Mandatory=$true)]
[string]$Version,
[Parameter(Mandatory=$false)]
[string]$source = "https://api.nuget.org/v3/index.json"
)
$resources = (invoke-restmethod -uri $source | ? { $_.version -eq '3.0.0' }).resources
$baseUrl = ($resources | ? { $_.'@type' -eq 'RegistrationsBaseUrl/3.6.0' }).'@id'
try
{
$packageName = $Id.ToLowerInvariant()
$packageVersion = $Version.ToLower()
# Use supported HEAD method for performance
Invoke-RestMethod -uri "$($baseUrl)$($packageName)/$($packageVersion).json" -Method HEAD > $null 2>&1
# method didn't throw so the NuGet package exists
$true
}
catch
{
# method threw, so the NuGet package doesn't exist
$false
}
它的使用情况如下:
PS> Get-NuGetPackageExists.ps1 -Id Newtonsoft.Json -Version 10.0.2
True
https://stackoverflow.com/questions/35631016
复制相似问题