Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion eng/pipelines/jobs/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ jobs:
inputs:
- input: pipelineArtifact
artifactName: ${{ parameters.artifactName }}
itemPattern: "**/*.tgz"
# Download the whole artifact (the .tgz packages plus publish-npm-packages.ts, which the
# checkout-less release job runs to publish them).
itemPattern: "**"
targetPath: $(Pipeline.Workspace)/${{ parameters.artifactName }}/

strategy:
Expand Down
3 changes: 3 additions & 0 deletions eng/pipelines/templates/pack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ steps:
echo "Create manifest of unpublished packages in $summaryFilePath"
node core/eng/tsp-core/scripts/filter-unpublished-packages.ts "$outDir" --manifest $summaryFilePath
echo "Copy the publish script into the artifact so the (checkout-less) release job can run it"
Copy-Item core/eng/tsp-core/scripts/publish-npm-packages.ts "$outDir/publish-npm-packages.ts"
name: pack_${{ parameters.name }}
displayName: Pack packages ${{ parameters.artifactName }}
43 changes: 15 additions & 28 deletions eng/pipelines/templates/release/ado-feed-release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# cspell:ignore EPUBLISHCONFLICT
parameters:
- name: tag
type: string
Expand All @@ -8,6 +7,9 @@ parameters:
- name: registryUrl
type: string
default: https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-js/npm/registry/
- name: nodeVersion
type: string
default: 24.16.0

steps:
# Publishing the packages directly to the Azure DevOps `azure-sdk-for-js` feed bypasses the
Expand All @@ -18,32 +20,17 @@ steps:
npmrcPath: ${{ parameters.path }}/.npmrc
registryUrl: ${{ parameters.registryUrl }}

- pwsh: |
$packageFiles = Get-ChildItem -Path . -Filter '*.tgz'
$hadError = $false
foreach ($file in $packageFiles.Name) {
Write-Host "npm publish $file --verbose --access public --tag ${{ parameters.tag }}"
$output = npm publish $file --verbose --access public --tag ${{ parameters.tag }} 2>&1
$output | ForEach-Object { Write-Host $_ }
if ($LASTEXITCODE -ne 0) {
$text = $output -join "`n"
# Treat "version already exists" as a no-op, matching the npm/ESRP behavior of not
# republishing an existing version. Any other failure is a genuine error and must fail.
if ($text -match 'EPUBLISHCONFLICT' -or
$text -match 'cannot publish over the previously published versions' -or
$text -match 'You cannot publish over the previously published versions' -or
$text -match 'previously published version' -or
$text -match '\b409\b') {
Write-Warning "Version for $file already exists in the feed, skipping."
} else {
Write-Error "Failed to publish $file to the DevOps feed."
$hadError = $true
}
}
}
if ($hadError) {
exit 1
}
# This is a 1ES release (deployment) job, which forbids `checkout`, so publish-npm-packages.ts is
# shipped inside the packages artifact (copied there by the pack step) and run from there.
- task: UseNode@1
inputs:
version: ${{ parameters.nodeVersion }}
displayName: Install Node.js
retryCountOnTaskFailure: 3

# The script publishes every *.tgz, treating "version already exists" (ADO feed immutability or an
# existing upstream copy on npmjs) as a skippable no-op while failing on any genuine error. It
# controls its own exit code, so there is no leaked pwsh $LASTEXITCODE to fail the task on a skip.
- script: node "${{ parameters.path }}/publish-npm-packages.ts" "${{ parameters.path }}" --tag ${{ parameters.tag }}
displayName: Publish to DevOps feed (${{ parameters.tag }})
condition: and(succeeded(), ne(variables['SkipPublishing'], 'true'))
workingDirectory: ${{ parameters.path }}
Loading