push-nuget.ps1 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. # push-nuget.ps1
  2. param(
  3. [string]$ApiKey,
  4. [string]$Source = 'https://api.nuget.org/v3/index.json',
  5. [string]$PackageDir,
  6. [switch]$SkipConfirm
  7. )
  8. $ErrorActionPreference = 'Stop'
  9. $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
  10. $RootDir = Split-Path -Parent $ScriptDir
  11. $VersionPropsFile = Join-Path $RootDir 'Directory.Build.Version.props'
  12. $DefaultPackageDir = Join-Path $RootDir 'nupkgs'
  13. $ApiKeyFile = Join-Path $ScriptDir 'NuGet_Apq_Key.txt'
  14. function Write-ColorText {
  15. param([string]$Text, [string]$Color = 'White')
  16. Write-Host $Text -ForegroundColor $Color
  17. }
  18. # 读取 Y/N 确认,按Q立即退出
  19. function Read-Confirm {
  20. param([string]$Prompt)
  21. Write-Host $Prompt -NoNewline
  22. while ($true) {
  23. $key = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
  24. if ($key.Character -eq 'q' -or $key.Character -eq 'Q') {
  25. Write-Host ''
  26. Write-ColorText '已退出' 'Yellow'
  27. exit 0
  28. }
  29. if ($key.Character -eq 'y' -or $key.Character -eq 'Y') {
  30. Write-Host 'Y'
  31. return $true
  32. }
  33. if ($key.Character -eq 'n' -or $key.Character -eq 'N') {
  34. Write-Host 'N'
  35. return $false
  36. }
  37. }
  38. }
  39. # 从 Directory.Build.Version.props 获取版本号
  40. function Get-Version {
  41. if (-not (Test-Path $VersionPropsFile)) {
  42. return $null
  43. }
  44. $content = [System.IO.File]::ReadAllText($VersionPropsFile)
  45. if ($content -match '<ApqChangeBubblingVersion>([^<]+)</ApqChangeBubblingVersion>') {
  46. return $Matches[1]
  47. }
  48. return $null
  49. }
  50. Write-ColorText "`n========================================" 'Cyan'
  51. Write-ColorText ' Apq.ChangeBubbling NuGet 发布工具' 'Cyan'
  52. Write-ColorText "========================================" 'Cyan'
  53. Write-ColorText ' 按 Q 随时退出' 'DarkGray'
  54. Write-ColorText "========================================`n" 'Cyan'
  55. if (-not (Test-Path $VersionPropsFile)) {
  56. Write-ColorText '错误: 找不到 Directory.Build.Version.props 文件' 'Red'
  57. Write-ColorText "路径: $VersionPropsFile" 'Red'
  58. exit 1
  59. }
  60. # 读取当前版本
  61. $currentVersion = Get-Version
  62. if (-not $currentVersion) {
  63. Write-ColorText '错误: 无法读取当前版本号' 'Red'
  64. exit 1
  65. }
  66. Write-ColorText "当前版本: $currentVersion" 'Yellow'
  67. # 设置包目录
  68. if ([string]::IsNullOrWhiteSpace($PackageDir)) {
  69. $PackageDir = $DefaultPackageDir
  70. }
  71. if (-not (Test-Path $PackageDir)) {
  72. Write-ColorText '错误: 包目录不存在' 'Red'
  73. Write-ColorText "路径: $PackageDir" 'Red'
  74. Write-ColorText '请先运行 pack-release.bat 生成包' 'Yellow'
  75. exit 1
  76. }
  77. # 查找当前版本的包
  78. $packages = Get-ChildItem -Path $PackageDir -Filter "*.nupkg" | Where-Object { $_.Name -match "Apq\.ChangeBubbling.*\.$([regex]::Escape($currentVersion))\.nupkg$" }
  79. $symbolPackages = Get-ChildItem -Path $PackageDir -Filter "*.snupkg" | Where-Object { $_.Name -match "Apq\.ChangeBubbling.*\.$([regex]::Escape($currentVersion))\.snupkg$" }
  80. if ($packages.Count -eq 0) {
  81. Write-ColorText "错误: 未找到版本 $currentVersion 的包" 'Red'
  82. Write-ColorText "路径: $PackageDir" 'Red'
  83. Write-ColorText '请先运行 pack-release.bat 生成包' 'Yellow'
  84. exit 1
  85. }
  86. Write-Host ''
  87. Write-ColorText '将要发布的包:' 'Cyan'
  88. foreach ($pkg in $packages) {
  89. $size = [math]::Round($pkg.Length / 1KB, 1)
  90. Write-ColorText " $($pkg.Name) ($size KB)" 'White'
  91. }
  92. if ($symbolPackages.Count -gt 0) {
  93. Write-Host ''
  94. Write-ColorText '符号包 (将自动上传):' 'Cyan'
  95. foreach ($pkg in $symbolPackages) {
  96. $size = [math]::Round($pkg.Length / 1KB, 1)
  97. Write-ColorText " $($pkg.Name) ($size KB)" 'Gray'
  98. }
  99. }
  100. Write-Host ''
  101. Write-ColorText "目标源: $Source" 'Gray'
  102. Write-Host ''
  103. # 获取 API Key
  104. if ([string]::IsNullOrWhiteSpace($ApiKey)) {
  105. # 从文件读取 API Key
  106. if (Test-Path $ApiKeyFile) {
  107. $ApiKey = (Get-Content $ApiKeyFile -First 1 -Encoding UTF8).Trim()
  108. if ([string]::IsNullOrWhiteSpace($ApiKey)) {
  109. Write-ColorText '错误: API Key 文件内容为空' 'Red'
  110. Write-ColorText "路径: $ApiKeyFile" 'Red'
  111. exit 1
  112. }
  113. Write-ColorText "已从文件读取 API Key: $ApiKeyFile" 'Gray'
  114. } else {
  115. Write-ColorText '错误: 找不到 API Key 文件' 'Red'
  116. Write-ColorText "路径: $ApiKeyFile" 'Red'
  117. exit 1
  118. }
  119. }
  120. Write-Host ''
  121. if (-not $SkipConfirm) {
  122. if (-not (Read-Confirm '确认发布到 NuGet? (Y/N): ')) {
  123. Write-ColorText '已取消' 'Yellow'
  124. exit 0
  125. }
  126. }
  127. Write-Host ''
  128. Write-ColorText '开始并行发布...' 'Cyan'
  129. Write-Host ''
  130. $successCount = 0
  131. $failCount = 0
  132. # 使用 ForEach-Object -Parallel 并行发布(线程池,无额外进程)
  133. $results = $packages | ForEach-Object -Parallel {
  134. $pkg = $_
  135. $result = & dotnet nuget push $pkg.FullName -s $using:Source -k $using:ApiKey --skip-duplicate 2>&1
  136. [PSCustomObject]@{
  137. ExitCode = $LASTEXITCODE
  138. Output = ($result | Out-String)
  139. PkgName = $pkg.Name
  140. }
  141. } -ThrottleLimit 8
  142. # 处理结果
  143. foreach ($result in $results) {
  144. if ($result.ExitCode -eq 0) {
  145. Write-ColorText " $($result.PkgName) - 成功" 'Green'
  146. $successCount++
  147. } else {
  148. if ($result.Output -match 'already exists') {
  149. Write-ColorText " $($result.PkgName) - 跳过 (已存在)" 'Yellow'
  150. $successCount++
  151. } else {
  152. Write-ColorText " $($result.PkgName) - 失败: $($result.Output)" 'Red'
  153. $failCount++
  154. }
  155. }
  156. }
  157. Write-Host ''
  158. Write-ColorText "========================================" 'Cyan'
  159. Write-ColorText "发布完成: 成功 $successCount, 失败 $failCount" $(if ($failCount -eq 0) { 'Green' } else { 'Yellow' })
  160. Write-ColorText "========================================" 'Cyan'
  161. Write-Host ''
  162. if ($failCount -eq 0) {
  163. Write-ColorText '所有包已成功发布!' 'Green'
  164. Write-Host ''
  165. Write-ColorText '查看已发布的包:' 'Yellow'
  166. Write-ColorText ' https://www.nuget.org/profiles/Apq' 'DarkGray'
  167. } else {
  168. Write-ColorText "有 $failCount 个包发布失败,请检查错误信息" 'Red'
  169. }
  170. Write-Host ''