From 66ce0ee623bfac020f9524f989b2f1f600e2631a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 9 Oct 2026 12:24:06 +0000 Subject: [PATCH 1/3] ci(release): publish OpenAPI packages and symbols through ESRP Co-authored-by: baywet <7905502+baywet@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ec81052a-ebe3-41e4-877c-46fb21141af7 --- .azure-pipelines/ci-build.yml | 122 ++++++++++++++++++++++++++++++---- 1 file changed, 109 insertions(+), 13 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 9c94a117e..79e01776b 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -21,6 +21,7 @@ pr: variables: buildPlatform: 'Any CPU' buildConfiguration: 'Release' + NuGetOrganizationName: 'openapinet' ProductBinPath: '$(Build.SourcesDirectory)\src\Microsoft.OpenApi\bin\$(BuildConfiguration)' resources: @@ -205,7 +206,9 @@ extends: inputs: targetFolder: $(Build.ArtifactStagingDirectory)/Nugets sourceFolder: $(Build.ArtifactStagingDirectory) - content: '*.nupkg' + Contents: | + *.nupkg + *.snupkg - stage: deploy condition: and(contains(variables['Build.SourceBranch'], 'refs/tags/v'), succeeded()) @@ -232,13 +235,60 @@ extends: pool: vmImage: ubuntu-latest steps: - - task: 1ES.PublishNuget@1 - displayName: 'NuGet push' + - pwsh: | + $pkg = Get-ChildItem -Path "$(Pipeline.Workspace)" -Filter "Microsoft.OpenApi.*.nupkg" | Where-Object { $_.Name -match '^Microsoft\.OpenApi\.(\d[\w\.\-]*)\.nupkg$' } | Select-Object -First 1 + if (-not $pkg) { throw "No Microsoft.OpenApi nupkg found to publish." } + $version = $pkg.Name -replace '^Microsoft\.OpenApi\.', '' -replace '\.nupkg$', '' + $id = 'microsoft.openapi' + $uri = "https://api.nuget.org/v3-flatcontainer/$id/index.json" + try { + $resp = Invoke-RestMethod -Uri $uri -Headers @{ 'User-Agent' = 'openapinet-azdo-pipeline' } + if ($resp.versions -contains $version) { + Write-Host "NuGet $id $version already published; skipping ESRP release (idempotent re-run)." + Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]true" + } else { + Write-Host "NuGet $id $version not found on nuget.org; will publish via ESRP." + Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]false" + } + } catch { + if ($_.Exception.Response.StatusCode.value__ -eq 404) { + Write-Host "NuGet $id has no published versions yet; will publish via ESRP." + Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]false" + } else { throw } + } + displayName: 'Check whether NuGet package version already published (idempotent)' + - task: CopyFiles@2 + displayName: 'Stage OpenAPI NuGet packages for ESRP release' + condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) + inputs: + SourceFolder: '$(Pipeline.Workspace)' + Contents: | + Microsoft.OpenApi.*.nupkg + Microsoft.OpenApi.*.snupkg + !Microsoft.OpenApi.YamlReader.* + TargetFolder: '$(Pipeline.Workspace)/nuget-packages/$(NuGetOrganizationName)/openapi' + CleanTargetFolder: true + - task: EsrpRelease@14 + displayName: 'ESRP Release - OpenAPI NuGet' + condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) inputs: - packagesToPush: '$(Pipeline.Workspace)/Microsoft.OpenApi.[0-9]*.nupkg' - packageParentPath: '$(Pipeline.Workspace)' - nuGetFeedType: external - publishFeedCredentials: 'OpenAPI Nuget Connection' + connectedservicename: 'Federated DevX ESRP Managed Identity Connection' + usemanagedidentity: false + keyvaultname: 'akv-prod-eastus' + authcertname: 'ReferenceLibraryPrivateCert' + signcertname: 'ReferencePackagePublisherCertificate' + clientid: '65035b7f-7357-4f29-bf25-c5ee5c3949f8' + intent: 'packagedistribution' + contenttype: 'NuGet' + organizationname: '$(NuGetOrganizationName)' + contentsource: 'Folder' + folderlocation: '$(Pipeline.Workspace)/nuget-packages/$(NuGetOrganizationName)/openapi' + waitforreleasecompletion: true + owners: 'christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com' + approvers: 'christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com' + serviceendpointurl: 'https://api.esrp.microsoft.com/' + mainpublisher: 'ESRPRELPACMAN' + domaintenantid: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' - deployment: deploy_yaml_reader condition: and(contains(variables['build.SourceBranch'], 'refs/tags/v'), succeeded()) @@ -257,13 +307,59 @@ extends: pool: vmImage: ubuntu-latest steps: - - task: 1ES.PublishNuget@1 - displayName: 'NuGet push' + - pwsh: | + $pkg = Get-ChildItem -Path "$(Pipeline.Workspace)" -Filter "Microsoft.OpenApi.YamlReader.*.nupkg" | Where-Object { $_.Name -match '^Microsoft\.OpenApi\.YamlReader\.(\d[\w\.\-]*)\.nupkg$' } | Select-Object -First 1 + if (-not $pkg) { throw "No Microsoft.OpenApi.YamlReader nupkg found to publish." } + $version = $pkg.Name -replace '^Microsoft\.OpenApi\.YamlReader\.', '' -replace '\.nupkg$', '' + $id = 'microsoft.openapi.yamlreader' + $uri = "https://api.nuget.org/v3-flatcontainer/$id/index.json" + try { + $resp = Invoke-RestMethod -Uri $uri -Headers @{ 'User-Agent' = 'openapinet-azdo-pipeline' } + if ($resp.versions -contains $version) { + Write-Host "NuGet $id $version already published; skipping ESRP release (idempotent re-run)." + Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]true" + } else { + Write-Host "NuGet $id $version not found on nuget.org; will publish via ESRP." + Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]false" + } + } catch { + if ($_.Exception.Response.StatusCode.value__ -eq 404) { + Write-Host "NuGet $id has no published versions yet; will publish via ESRP." + Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]false" + } else { throw } + } + displayName: 'Check whether NuGet package version already published (idempotent)' + - task: CopyFiles@2 + displayName: 'Stage YAML reader NuGet packages for ESRP release' + condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) + inputs: + SourceFolder: '$(Pipeline.Workspace)' + Contents: | + Microsoft.OpenApi.YamlReader.*.nupkg + Microsoft.OpenApi.YamlReader.*.snupkg + TargetFolder: '$(Pipeline.Workspace)/nuget-packages/$(NuGetOrganizationName)/yaml-reader' + CleanTargetFolder: true + - task: EsrpRelease@14 + displayName: 'ESRP Release - YAML reader NuGet' + condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) inputs: - packagesToPush: '$(Pipeline.Workspace)/Microsoft.OpenApi.YamlReader.*.nupkg' - packageParentPath: '$(Pipeline.Workspace)' - nuGetFeedType: external - publishFeedCredentials: 'OpenAPI Nuget Connection' + connectedservicename: 'Federated DevX ESRP Managed Identity Connection' + usemanagedidentity: false + keyvaultname: 'akv-prod-eastus' + authcertname: 'ReferenceLibraryPrivateCert' + signcertname: 'ReferencePackagePublisherCertificate' + clientid: '65035b7f-7357-4f29-bf25-c5ee5c3949f8' + intent: 'packagedistribution' + contenttype: 'NuGet' + organizationname: '$(NuGetOrganizationName)' + contentsource: 'Folder' + folderlocation: '$(Pipeline.Workspace)/nuget-packages/$(NuGetOrganizationName)/yaml-reader' + waitforreleasecompletion: true + owners: 'christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com' + approvers: 'christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com' + serviceendpointurl: 'https://api.esrp.microsoft.com/' + mainpublisher: 'ESRPRELPACMAN' + domaintenantid: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' - deployment: create_github_release condition: and(contains(variables['build.SourceBranch'], 'refs/tags/v'), succeeded()) From 1eb068f68074ff352278a71820c28c014cc5f60a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 9 Oct 2026 12:46:16 +0000 Subject: [PATCH 2/3] ci(release): share authenticated private-feed version checks Co-authored-by: baywet <7905502+baywet@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ec81052a-ebe3-41e4-877c-46fb21141af7 --- .azure-pipelines/ci-build.yml | 68 +++++++++++++---------------------- scripts/checkNuGetVersion.ps1 | 61 +++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 43 deletions(-) create mode 100644 scripts/checkNuGetVersion.ps1 diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 79e01776b..759f7b5be 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -22,6 +22,7 @@ variables: buildPlatform: 'Any CPU' buildConfiguration: 'Release' NuGetOrganizationName: 'openapinet' + privateFeedBaseUrl: 'https://microsoftgraph.pkgs.visualstudio.com/0985d294-5762-4bc2-a565-161ef349ca3e/_packaging/GraphDeveloperExperiences_Public' ProductBinPath: '$(Build.SourcesDirectory)\src\Microsoft.OpenApi\bin\$(BuildConfiguration)' resources: @@ -82,7 +83,7 @@ extends: - + "@ | Set-Content -Path "$(Build.SourcesDirectory)/nuget.config" -Encoding UTF8 @@ -210,6 +211,13 @@ extends: *.nupkg *.snupkg + - task: CopyFiles@2 + displayName: 'Include version-check script in Nugets artifact' + inputs: + SourceFolder: '$(Build.SourcesDirectory)/scripts' + Contents: 'checkNuGetVersion.ps1' + TargetFolder: '$(Build.ArtifactStagingDirectory)/Nugets/scripts' + - stage: deploy condition: and(contains(variables['Build.SourceBranch'], 'refs/tags/v'), succeeded()) dependsOn: build @@ -235,28 +243,15 @@ extends: pool: vmImage: ubuntu-latest steps: - - pwsh: | - $pkg = Get-ChildItem -Path "$(Pipeline.Workspace)" -Filter "Microsoft.OpenApi.*.nupkg" | Where-Object { $_.Name -match '^Microsoft\.OpenApi\.(\d[\w\.\-]*)\.nupkg$' } | Select-Object -First 1 - if (-not $pkg) { throw "No Microsoft.OpenApi nupkg found to publish." } - $version = $pkg.Name -replace '^Microsoft\.OpenApi\.', '' -replace '\.nupkg$', '' - $id = 'microsoft.openapi' - $uri = "https://api.nuget.org/v3-flatcontainer/$id/index.json" - try { - $resp = Invoke-RestMethod -Uri $uri -Headers @{ 'User-Agent' = 'openapinet-azdo-pipeline' } - if ($resp.versions -contains $version) { - Write-Host "NuGet $id $version already published; skipping ESRP release (idempotent re-run)." - Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]true" - } else { - Write-Host "NuGet $id $version not found on nuget.org; will publish via ESRP." - Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]false" - } - } catch { - if ($_.Exception.Response.StatusCode.value__ -eq 404) { - Write-Host "NuGet $id has no published versions yet; will publish via ESRP." - Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]false" - } else { throw } - } + - task: PowerShell@2 displayName: 'Check whether NuGet package version already published (idempotent)' + inputs: + targetType: filePath + filePath: '$(Pipeline.Workspace)/scripts/checkNuGetVersion.ps1' + arguments: '-PackageId "Microsoft.OpenApi" -PackageDirectory "$(Pipeline.Workspace)" -NuGetServiceIndexUrl "$(privateFeedBaseUrl)/nuget/v3/index.json"' + pwsh: true + env: + FEED_ACCESS_TOKEN: $(System.AccessToken) - task: CopyFiles@2 displayName: 'Stage OpenAPI NuGet packages for ESRP release' condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) @@ -307,28 +302,15 @@ extends: pool: vmImage: ubuntu-latest steps: - - pwsh: | - $pkg = Get-ChildItem -Path "$(Pipeline.Workspace)" -Filter "Microsoft.OpenApi.YamlReader.*.nupkg" | Where-Object { $_.Name -match '^Microsoft\.OpenApi\.YamlReader\.(\d[\w\.\-]*)\.nupkg$' } | Select-Object -First 1 - if (-not $pkg) { throw "No Microsoft.OpenApi.YamlReader nupkg found to publish." } - $version = $pkg.Name -replace '^Microsoft\.OpenApi\.YamlReader\.', '' -replace '\.nupkg$', '' - $id = 'microsoft.openapi.yamlreader' - $uri = "https://api.nuget.org/v3-flatcontainer/$id/index.json" - try { - $resp = Invoke-RestMethod -Uri $uri -Headers @{ 'User-Agent' = 'openapinet-azdo-pipeline' } - if ($resp.versions -contains $version) { - Write-Host "NuGet $id $version already published; skipping ESRP release (idempotent re-run)." - Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]true" - } else { - Write-Host "NuGet $id $version not found on nuget.org; will publish via ESRP." - Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]false" - } - } catch { - if ($_.Exception.Response.StatusCode.value__ -eq 404) { - Write-Host "NuGet $id has no published versions yet; will publish via ESRP." - Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]false" - } else { throw } - } + - task: PowerShell@2 displayName: 'Check whether NuGet package version already published (idempotent)' + inputs: + targetType: filePath + filePath: '$(Pipeline.Workspace)/scripts/checkNuGetVersion.ps1' + arguments: '-PackageId "Microsoft.OpenApi.YamlReader" -PackageDirectory "$(Pipeline.Workspace)" -NuGetServiceIndexUrl "$(privateFeedBaseUrl)/nuget/v3/index.json"' + pwsh: true + env: + FEED_ACCESS_TOKEN: $(System.AccessToken) - task: CopyFiles@2 displayName: 'Stage YAML reader NuGet packages for ESRP release' condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) diff --git a/scripts/checkNuGetVersion.ps1 b/scripts/checkNuGetVersion.ps1 new file mode 100644 index 000000000..02a261bc1 --- /dev/null +++ b/scripts/checkNuGetVersion.ps1 @@ -0,0 +1,61 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +param( + [Parameter(Mandatory = $true)] + [string]$PackageId, + [Parameter(Mandatory = $true)] + [string]$PackageDirectory, + [Parameter(Mandatory = $true)] + [string]$NuGetServiceIndexUrl +) + +$ErrorActionPreference = 'Stop' + +if ([string]::IsNullOrWhiteSpace($env:FEED_ACCESS_TOKEN)) { + throw 'No Azure Artifacts access token available for the version check.' +} + +$packagePattern = '^' + [regex]::Escape($PackageId) + '\.(\d[\w\.\-]*)\.nupkg$' +$packages = @(Get-ChildItem -Path $PackageDirectory -Filter "$PackageId.*.nupkg" | + Where-Object { $_.Name -match $packagePattern }) +if ($packages.Count -ne 1) { + throw "Expected exactly one $PackageId nupkg to publish; found $($packages.Count)." +} +$version = [regex]::Match($packages[0].Name, $packagePattern, 'IgnoreCase').Groups[1].Value +$id = $PackageId.ToLowerInvariant() +$credentials = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("AzureDevOps:$($env:FEED_ACCESS_TOKEN)")) +$headers = @{ + 'User-Agent' = 'openapinet-azdo-pipeline' + 'Authorization' = "Basic $credentials" +} + +$serviceIndex = Invoke-RestMethod -Uri $NuGetServiceIndexUrl -Headers $headers +$packageBaseAddress = $serviceIndex.resources | + Where-Object { $_.'@type' -eq 'PackageBaseAddress/3.0.0' } | + Select-Object -First 1 -ExpandProperty '@id' +if ([string]::IsNullOrWhiteSpace($packageBaseAddress)) { + throw 'The private NuGet feed does not advertise a package base address.' +} + +$uri = "$($packageBaseAddress.TrimEnd('/'))/$id/index.json" +try { + $response = Invoke-RestMethod -Uri $uri -Headers $headers + if ($null -eq $response.versions) { + throw 'The private NuGet feed returned an invalid package version response.' + } + $alreadyPublished = $response.versions -contains $version +} catch { + if ([int]$_.Exception.Response.StatusCode -eq 404) { + $alreadyPublished = $false + } else { + throw + } +} + +if ($alreadyPublished) { + Write-Host "NuGet $id $version already present in the private feed; skipping ESRP release (idempotent re-run)." +} else { + Write-Host "NuGet $id $version not found in the private feed; will publish via ESRP." +} +Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]$($alreadyPublished.ToString().ToLowerInvariant())" From 8d8c96cef1e87af1b93df86d0e63ff94ac1a52c8 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 9 Oct 2026 11:26:13 -0400 Subject: [PATCH 3/3] ci(release): align NuGet publication checks across repositories Port commit 8ed2fbc743b4c33c3a13daca2a87279e2f7bae61 from #3107. Preserve the shared authenticated publication script and update both remaining library deployment call sites; omit Hidi and Docker changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ec81052a-ebe3-41e4-877c-46fb21141af7 --- .azure-pipelines/ci-build.yml | 6 +- scripts/check-nuget-package-published.ps1 | 84 +++++++++++++++++++++++ scripts/checkNuGetVersion.ps1 | 61 ---------------- 3 files changed, 87 insertions(+), 64 deletions(-) create mode 100644 scripts/check-nuget-package-published.ps1 delete mode 100644 scripts/checkNuGetVersion.ps1 diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 759f7b5be..1281acf0a 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -215,7 +215,7 @@ extends: displayName: 'Include version-check script in Nugets artifact' inputs: SourceFolder: '$(Build.SourcesDirectory)/scripts' - Contents: 'checkNuGetVersion.ps1' + Contents: 'check-nuget-package-published.ps1' TargetFolder: '$(Build.ArtifactStagingDirectory)/Nugets/scripts' - stage: deploy @@ -247,7 +247,7 @@ extends: displayName: 'Check whether NuGet package version already published (idempotent)' inputs: targetType: filePath - filePath: '$(Pipeline.Workspace)/scripts/checkNuGetVersion.ps1' + filePath: '$(Pipeline.Workspace)/scripts/check-nuget-package-published.ps1' arguments: '-PackageId "Microsoft.OpenApi" -PackageDirectory "$(Pipeline.Workspace)" -NuGetServiceIndexUrl "$(privateFeedBaseUrl)/nuget/v3/index.json"' pwsh: true env: @@ -306,7 +306,7 @@ extends: displayName: 'Check whether NuGet package version already published (idempotent)' inputs: targetType: filePath - filePath: '$(Pipeline.Workspace)/scripts/checkNuGetVersion.ps1' + filePath: '$(Pipeline.Workspace)/scripts/check-nuget-package-published.ps1' arguments: '-PackageId "Microsoft.OpenApi.YamlReader" -PackageDirectory "$(Pipeline.Workspace)" -NuGetServiceIndexUrl "$(privateFeedBaseUrl)/nuget/v3/index.json"' pwsh: true env: diff --git a/scripts/check-nuget-package-published.ps1 b/scripts/check-nuget-package-published.ps1 new file mode 100644 index 000000000..84f45419d --- /dev/null +++ b/scripts/check-nuget-package-published.ps1 @@ -0,0 +1,84 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +<# +.SYNOPSIS +Checks whether a NuGet artifact's version exists in an authenticated Azure Artifacts feed. +.DESCRIPTION +Resolves the package content endpoint from the private feed's NuGet v3 service index. +Sets nugetAlreadyPublished for the ESRP release steps; only a missing package or version +permits publishing. Feed authentication and other lookup failures fail the step. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$PackageDirectory, + [Parameter(Mandatory = $true)] + [string]$PackageId, + [Parameter(Mandatory = $true)] + [string]$NuGetServiceIndexUrl, + [string]$FeedAccessToken = $env:FEED_ACCESS_TOKEN +) + +$ErrorActionPreference = 'Stop' + +function Assert-PrivateFeedUrl { + param([string]$Url) + + $uri = [uri]$Url + if (-not $uri.IsAbsoluteUri -or $uri.Scheme -ne 'https' -or + ($uri.Host -ne 'pkgs.dev.azure.com' -and -not $uri.Host.EndsWith('.pkgs.visualstudio.com'))) { + throw "NuGet lookups must use an HTTPS Azure Artifacts feed: $Url" + } +} + +Assert-PrivateFeedUrl -Url $NuGetServiceIndexUrl +if ([string]::IsNullOrWhiteSpace($FeedAccessToken)) { + throw 'FEED_ACCESS_TOKEN is required to query the private NuGet feed.' +} + +$packagePattern = '^' + [regex]::Escape($PackageId) + '\.(\d[\w\.\-]*)\.nupkg$' +$packages = @(Get-ChildItem -Path $PackageDirectory -File -Filter "$PackageId.*.nupkg" | + Where-Object { $_.Name -match $packagePattern }) +if ($packages.Count -ne 1) { + throw "Expected exactly one $PackageId nupkg to publish; found $($packages.Count)." +} +$version = [regex]::Match($packages[0].Name, $packagePattern, 'IgnoreCase').Groups[1].Value +$id = $PackageId.ToLowerInvariant() +$credentials = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("AzureDevOps:$FeedAccessToken")) +$headers = @{ + 'Authorization' = "Basic $credentials" + 'User-Agent' = 'openapi-azdo-pipeline' +} + +$index = Invoke-RestMethod -Uri $NuGetServiceIndexUrl -Headers $headers -MaximumRedirection 0 +$resource = $index.resources | Where-Object { $_.'@type' -eq 'PackageBaseAddress/3.0.0' } | Select-Object -First 1 +if ([string]::IsNullOrWhiteSpace($resource.'@id')) { + throw "No PackageBaseAddress resource found in the NuGet service index at $NuGetServiceIndexUrl" +} +$uri = "$($resource.'@id'.TrimEnd('/'))/$id/index.json" +Assert-PrivateFeedUrl -Url $uri + +try { + $response = Invoke-RestMethod -Uri $uri -Headers $headers -MaximumRedirection 0 + if ($null -eq $response.versions) { + throw "No versions returned for NuGet $id by the private feed." + } + $alreadyPublished = $response.versions -contains $version +} +catch { + if ([int]$_.Exception.Response.StatusCode -eq 404) { + $alreadyPublished = $false + } + else { + throw + } +} + +if ($alreadyPublished) { + Write-Host "NuGet $id $version already present in the private feed; skipping ESRP release (idempotent re-run)." +} +else { + Write-Host "NuGet $id $version not found in the private feed; will publish via ESRP." +} +Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]$($alreadyPublished.ToString().ToLowerInvariant())" diff --git a/scripts/checkNuGetVersion.ps1 b/scripts/checkNuGetVersion.ps1 deleted file mode 100644 index 02a261bc1..000000000 --- a/scripts/checkNuGetVersion.ps1 +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -param( - [Parameter(Mandatory = $true)] - [string]$PackageId, - [Parameter(Mandatory = $true)] - [string]$PackageDirectory, - [Parameter(Mandatory = $true)] - [string]$NuGetServiceIndexUrl -) - -$ErrorActionPreference = 'Stop' - -if ([string]::IsNullOrWhiteSpace($env:FEED_ACCESS_TOKEN)) { - throw 'No Azure Artifacts access token available for the version check.' -} - -$packagePattern = '^' + [regex]::Escape($PackageId) + '\.(\d[\w\.\-]*)\.nupkg$' -$packages = @(Get-ChildItem -Path $PackageDirectory -Filter "$PackageId.*.nupkg" | - Where-Object { $_.Name -match $packagePattern }) -if ($packages.Count -ne 1) { - throw "Expected exactly one $PackageId nupkg to publish; found $($packages.Count)." -} -$version = [regex]::Match($packages[0].Name, $packagePattern, 'IgnoreCase').Groups[1].Value -$id = $PackageId.ToLowerInvariant() -$credentials = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("AzureDevOps:$($env:FEED_ACCESS_TOKEN)")) -$headers = @{ - 'User-Agent' = 'openapinet-azdo-pipeline' - 'Authorization' = "Basic $credentials" -} - -$serviceIndex = Invoke-RestMethod -Uri $NuGetServiceIndexUrl -Headers $headers -$packageBaseAddress = $serviceIndex.resources | - Where-Object { $_.'@type' -eq 'PackageBaseAddress/3.0.0' } | - Select-Object -First 1 -ExpandProperty '@id' -if ([string]::IsNullOrWhiteSpace($packageBaseAddress)) { - throw 'The private NuGet feed does not advertise a package base address.' -} - -$uri = "$($packageBaseAddress.TrimEnd('/'))/$id/index.json" -try { - $response = Invoke-RestMethod -Uri $uri -Headers $headers - if ($null -eq $response.versions) { - throw 'The private NuGet feed returned an invalid package version response.' - } - $alreadyPublished = $response.versions -contains $version -} catch { - if ([int]$_.Exception.Response.StatusCode -eq 404) { - $alreadyPublished = $false - } else { - throw - } -} - -if ($alreadyPublished) { - Write-Host "NuGet $id $version already present in the private feed; skipping ESRP release (idempotent re-run)." -} else { - Write-Host "NuGet $id $version not found in the private feed; will publish via ESRP." -} -Write-Host "##vso[task.setvariable variable=nugetAlreadyPublished]$($alreadyPublished.ToString().ToLowerInvariant())"