11parameters :
2- Tag : ' latest '
2+ Tag : ' auto '
33 ArtifactName : ' packages'
4+ ArtifactSubPath : ' '
5+ DeploymentName : ' PublishPackage'
46 DependsOn : []
57 Environment : ' package-publish'
68 Registry : ' https://registry.npmjs.org/'
9+ Pool : # hardcoding the pool and image name because deployment jobs do not support variable expansion in pool names
10+ name : azsdk-pool
11+ image : ubuntu-24.04
12+ os : linux
13+ CustomCondition : succeeded()
14+ FailOnMissingPackages : true
715
816jobs :
9- - deployment : PublishPackage_${{ parameters.ArtifactName }}
10- displayName : ' Publish ${{ parameters.ArtifactName }} to ${{ parameters.Registry }}'
17+ - deployment : ${{ parameters.DeploymentName }}
18+ displayName : ' Publish ${{ parameters.ArtifactName }} to ${{ parameters.Registry }}'
19+ condition : ${{ parameters.CustomCondition }}
1120 environment : ${{ parameters.Environment }}
1221 dependsOn : ${{ parameters.DependsOn }}
1322 variables :
1423 - name : ArtifactPath
15- value : $(Pipeline.Workspace)/${{ parameters.ArtifactName }}
24+ value : $(Pipeline.Workspace)/${{ parameters.ArtifactName }}/${{ parameters.ArtifactSubPath }}
1625
1726 templateContext :
1827 type : releaseJob
@@ -21,26 +30,48 @@ jobs:
2130 - input : pipelineArtifact
2231 artifactName : ${{ parameters.ArtifactName }}
2332 itemPattern : ' **/*.tgz'
24- targetPath : $(ArtifactPath)
33+ targetPath : $(Pipeline.Workspace)/${{ parameters.ArtifactName }}/
2534
26- pool :
27- name : azsdk-pool
28- image : ubuntu-24.04
29- os : linux
35+ pool : ${{ parameters.Pool }}
3036
3137 strategy :
3238 runOnce :
3339 deploy :
3440 steps :
3541 - pwsh : |
42+ $containsBeta = $false
43+ $containsPackages = $false
3644 foreach ($package in (dir $(ArtifactPath) *.tgz -Recurse)) {
37- Write-Host "Publishing $package to ${{ parameters.Registry }} with tag ${{ parameters.Tag }}"
45+ if ($package.Name -match "[\d\.]+-[a-zA-Z]+") { $containsBeta = $true }
46+ Write-Host "Publishing $package to ${{ parameters.Registry }}"
47+ $containsPackages = $true
48+ }
49+ if (!$containsPackages) {
50+ Write-Host "##vso[task.setvariable variable=SkipPublishing]true"
51+ if ("${{ parameters.FailOnMissingPackages }}" -eq 'true') {
52+ Write-Error "No packages found to publish, but FailOnMissingPackages is set to true. Failing the job."
53+ exit 1
54+ }
55+ else {
56+ Write-Host "No packages found to publish in $(ArtifactPath), so skipping publishing."
57+ exit 0
58+ }
3859 }
39- displayName: 'Display packages to be published'
60+
61+ $tag = '${{ parameters.Tag }}'
62+ if ($tag -eq '' -or $tag -eq 'auto') {
63+ $tag = 'latest'
64+ # If the package is prerelease publish it under 'beta' tag
65+ if ($containsBeta) { $tag = 'beta'}
66+ }
67+ Write-Host "##vso[task.setvariable variable=TagName]$tag"
68+ Write-Host "Publishing packages with tag: $tag"
69+ displayName: 'Packages to be published'
4070
4171 - ${{ if eq(parameters.Registry, 'https://registry.npmjs.org/') }} :
4272 - task : EsrpRelease@9
4373 displayName : ' Publish ${{ parameters.ArtifactName }} via ESRP'
74+ condition : and(succeeded(), ne(variables['SkipPublishing'], 'true'))
4475 inputs :
4576 ConnectedServiceName : ' Azure SDK PME Managed Identity'
4677 ClientId : ' 5f81938c-2544-4f1f-9251-dd9de5b8a81b'
@@ -55,23 +86,47 @@ jobs:
5586 Approvers :
${{ coalesce(variables['Build.RequestedForEmail'], '[email protected] ') }} 5687 ServiceEndpointUrl : ' https://api.esrp.microsoft.com'
5788 MainPublisher : ' ESRPRELPACMANTEST'
58- productstate : ${{ parameters.Tag }}
89+ productstate : $(TagName)
90+
91+ - pwsh : |
92+ foreach ($package in (dir $(ArtifactPath) *.tgz -Recurse)) {
93+ $packageJson = tar -xOf $package "package/package.json" | ConvertFrom-Json
94+ if (!$packageJson) {
95+ Write-Warning "Could not read package.json from $package"
96+ continue;
97+ }
98+ Write-Host "Verifying tag '$(TagName)' is set for '$($packageJson.name)' version '$($packageJson.version)'"
99+ $packageTags = npm view $packageJson.name "dist-tags" -json -silent | ConvertFrom-Json
100+ if ($LASTEXITCODE -ne 0 -or !$packageTags) {
101+ Write-Warning "Failed to retrieve dist-tags for $packageJson.name. It is possible the package hasn't been indexed yet so ignoring."
102+ continue
103+ }
104+
105+ if ($packageTags."$(TagName)" -ne $packageJson.version) {
106+ Write-Error "The dist-tag '$(TagName)' for package '$($packageJson.name)' is not correctly set something must have gone wrong during the ESRP release process."
107+ exit 1
108+ }
109+ }
110+ displayName: 'Verify tag after ESRP release'
111+ condition: and(succeeded(), ne(variables['SkipPublishing'], 'true'))
59112
60113 - ${{ else }} :
61114 - template : /eng/common/pipelines/templates/steps/create-authenticated-npmrc.yml
62115 parameters :
63116 npmrcPath : $(ArtifactPath)/.npmrc
64117 registryUrl : ${{ parameters.Registry }}
118+ CustomCondition : and(succeeded(), ne(variables['SkipPublishing'], 'true'))
65119
66120 - pwsh : |
67121 foreach ($package in (dir $(ArtifactPath) *.tgz -Recurse)) {
68- Write-Host "npm publish $package --verbose --access public --tag ${{ parameters.Tag }} --registry ${{ parameters.Registry }}"
69- npm publish $package --verbose --access public --tag ${{ parameters.Tag }} --registry ${{ parameters.Registry }}
122+ Write-Host "npm publish $package --verbose --access public --tag $(TagName) --registry ${{ parameters.Registry }}"
123+ npm publish $package --verbose --access public --tag $(TagName) --registry ${{ parameters.Registry }}
70124 if ($LASTEXITCODE -ne 0) {
71125 Write-Error "Failed to publish $package to ${{ parameters.Registry }}"
72126 exit $LASTEXITCODE
73127 }
74128 }
75129 displayName: 'Publish ${{ parameters.ArtifactName }}'
130+ condition: and(succeeded(), ne(variables['SkipPublishing'], 'true'))
76131 workingDirectory: $(ArtifactPath)
77132
0 commit comments