Skip to content

Commit 4ddc44c

Browse files
Update npm-publish template (#41690)
- Add basic tag support beta or latest - Add tag validation for ESRP - Support subpaths from the artifact to scope to just some packages - Co-authored-by: Wes Haggard <Wes.Haggard@microsoft.com>
1 parent af1cb19 commit 4ddc44c

File tree

3 files changed

+75
-15
lines changed

3 files changed

+75
-15
lines changed
Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
parameters:
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

816
jobs:
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'], 'azuresdk@microsoft.com') }}
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

eng/common/pipelines/templates/steps/create-authenticated-npmrc.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ parameters:
33
type: string
44
- name: registryUrl
55
type: string
6+
- name: CustomCondition
7+
type: string
8+
default: succeeded()
69

710
steps:
811
- pwsh: |
@@ -17,7 +20,9 @@ steps:
1720
$content = "registry=${{ parameters.registryUrl }}`n`nalways-auth=true"
1821
$content | Out-File '${{ parameters.npmrcPath }}'
1922
displayName: 'Create .npmrc'
23+
condition: ${{ parameters.CustomCondition }}
2024
- task: npmAuthenticate@0
2125
displayName: Authenticate .npmrc
26+
condition: ${{ parameters.CustomCondition }}
2227
inputs:
2328
workingFile: ${{ parameters.npmrcPath }}

eng/common/scripts/copy-docs-to-blobstorage.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function ToSemVer($version){
6161

6262
function SortSemVersions($versions)
6363
{
64-
return $versions | Sort -Property Major, Minor, Patch, PrereleaseLabel, PrereleaseNumber -Descending
64+
return $versions | Sort-Object -Property Major, Minor, Patch, PrereleaseLabel, PrereleaseNumber -Descending
6565
}
6666

6767
function Sort-Versions

0 commit comments

Comments
 (0)