-
Notifications
You must be signed in to change notification settings - Fork 100
Expand file tree
/
Copy pathpublish-extension.yml
More file actions
237 lines (218 loc) Β· 8.92 KB
/
publish-extension.yml
File metadata and controls
237 lines (218 loc) Β· 8.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# Template (jobs): Sign and Publish Extension
# Encapsulates Sign, optional manual validation, and Publish jobs with MicroBuild signing.
# This template defines multiple jobs with templateContext for MicroBuild signing.
#
# Usage (example inside a stage):
# jobs:
# - template: build/templates/publish-extension.yml@self
# parameters:
# buildPlatforms: ${{ parameters.buildPlatforms }}
# publishExtension: ${{ parameters.publishExtension }}
# preRelease: false
# teamName: $(TeamName)
# ghCreateRelease: true
# ghCreateTag: true
# waitForValidation: true
#
# Notes:
# - Requires MicroBuild pool (VSEngSS-MicroBuild2022-1ES) for signing.
# - Downloads platform-specific artifacts from previous stage.
# - Publishes signed artifacts as 'extension' pipeline artifact with SBOM.
# - Optionally creates a GitHub release and waits for manual validation before marketplace publishing.
parameters:
# Build platforms
- name: buildPlatforms
type: object
displayName: 'List of platforms to sign and publish'
- name: customNPMRegistry
type: string
default: ''
displayName: 'Custom NPM registry (optional)'
- name: nodeVersion
type: string
default: '22.17.0'
displayName: 'Node version to install'
# Signing parameters
- name: signType
type: string
default: real
displayName: 'MicroBuild sign type (real or test)'
- name: verifySignature
type: boolean
default: true
displayName: 'Verify signature after signing'
- name: teamName
type: string
default: VSCode-python-debugger
displayName: 'Team name for signing'
# Publishing parameters
- name: publishExtension
type: boolean
default: false
displayName: 'Publish extension to marketplace'
- name: preRelease
type: boolean
default: false
displayName: 'Publish as pre-release'
- name: azureSubscription
type: string
default: PylancePublishPipelineSecureConnectionWithManagedIdentity
displayName: 'Azure subscription for marketplace auth'
# GitHub Release parameters
- name: ghCreateTag
type: boolean
default: false
displayName: 'Create GitHub tag'
- name: ghCreateRelease
type: boolean
default: false
displayName: 'Create GitHub release'
- name: ghReleaseAddChangeLog
type: boolean
default: true
displayName: 'Add changelog to GitHub release'
- name: ghTagPrefix
type: string
default: 'v'
displayName: 'Prefix for GitHub tag (e.g., v for v2025.1.0)'
# Manual validation parameters
- name: waitForValidation
type: boolean
default: true
displayName: 'Wait for manual validation before publishing'
- name: validationNotifyUsers
type: string
default: ''
displayName: 'Users to notify for manual validation (comma-separated emails)'
- name: validationInstructions
type: string
default: 'Please test the latest draft release then approve to publish to marketplace.'
displayName: 'Instructions for manual validation'
- name: validationTimeoutInMinutes
type: number
default: 1440
displayName: 'Timeout for manual validation in minutes (default: 1 day)'
# Paths
- name: workingDirectory
type: string
default: '$(Build.StagingDirectory)\extension'
displayName: 'Working directory for signing artifacts'
- name: publishFolder
type: string
default: extension
displayName: 'Folder containing signed artifacts for publishing'
- name: manifestName
type: string
default: extension.manifest
displayName: 'Manifest filename'
- name: signatureName
type: string
default: extension.signature.p7s
displayName: 'Signature filename'
jobs:
# Job 1: Sign extension and create GitHub release
- job: Sign
displayName: Sign Extension
pool:
name: VSEngSS-MicroBuild2022-1ES
os: windows
templateContext:
mb:
signing:
enabled: true
signType: ${{ parameters.signType }}
signWithProd: true
outputs:
- output: pipelineArtifact
displayName: 'Publish Extension Artifact'
targetPath: '${{ parameters.workingDirectory }}'
artifactName: extension
sbomEnabled: true
steps:
# Download platform-specific artifacts to Build.BinariesDirectory
- ${{ each platform in parameters.buildPlatforms }}:
- ${{ if eq(platform.vsceTarget, '') }}:
- task: DownloadPipelineArtifact@2
inputs:
artifactName: vsix-universal
targetPath: $(Build.BinariesDirectory)/vsix-universal
displayName: π Download extension (universal)
- ${{ if ne(platform.vsceTarget, '') }}:
- task: DownloadPipelineArtifact@2
inputs:
artifactName: vsix-${{ platform.vsceTarget }}
targetPath: $(Build.BinariesDirectory)/vsix-${{ platform.vsceTarget }}
displayName: π Download extension (${{ platform.vsceTarget }})
- template: sign.yml
parameters:
buildPlatforms: ${{ parameters.buildPlatforms }}
workingDirectory: ${{ parameters.workingDirectory }}
signType: ${{ parameters.signType }}
verifySignature: ${{ parameters.verifySignature }}
teamName: ${{ parameters.teamName }}
customNPMRegistry: ${{ parameters.customNPMRegistry }}
nodeVersion: ${{ parameters.nodeVersion }}
# Job 2: Publish to marketplace
- ${{ if eq(parameters.publishExtension, true) }}:
- job: Publish
displayName: Publish to Marketplace and GitHub
dependsOn: Sign
pool:
name: AzurePipelines-EO
image: 1ESPT-Windows2022
os: windows
templateContext:
type: releaseJob # This makes a job a release job
isProduction: true # Indicates a production release
steps:
- task: 1ES.DownloadPipelineArtifact@1
inputs:
artifactName: extension
targetPath: $(Build.ArtifactStagingDirectory)/${{ parameters.publishFolder }}
displayName: π Download signed extension
- template: setup.yml
parameters:
installNode: true
installPython: false
customNPMRegistry: ${{ parameters.customNPMRegistry }}
nodeVersion: ${{ parameters.nodeVersion }}
# Extract VSIX to read publisher/version for GitHub release tagging.
# Use Agent.TempDirectory to avoid reusing Build.ArtifactStagingDirectory which
# is reserved for final artifact staging.
- task: ExtractFiles@1
inputs:
archiveFilePatterns: $(Build.ArtifactStagingDirectory)/${{ parameters.publishFolder }}/**/*.vsix
destinationFolder: $(Agent.TempDirectory)/vsix-extracted
cleanDestinationFolder: true
overwriteExistingFiles: true
displayName: π¦ Extract VSIX package
- pwsh: |
$extensionDir = Get-ChildItem -Path . -Directory -Filter 'extension*' | Select-Object -First 1
if (-not $extensionDir) {
throw "Could not find extracted extension folder under: $PWD"
}
$packageJsonPath = Join-Path $extensionDir.FullName 'package.json'
if (-not (Test-Path $packageJsonPath)) {
throw "Could not find package.json at: $packageJsonPath"
}
$package = Get-Content $packageJsonPath -Raw | ConvertFrom-Json
Write-Host "##vso[task.setvariable variable=publisher;isOutput=true]$($package.publisher)"
Write-Host "##vso[task.setvariable variable=version;isOutput=true]$($package.version)"
name: SetPublisherAndVersion
displayName: π Get Publisher & Version
workingDirectory: $(Agent.TempDirectory)/vsix-extracted
# Get version from package.json for GitHub release tagging
- ${{ if and(eq(parameters.ghCreateTag, true), eq(parameters.ghCreateRelease, true)) }}:
- template: createGitHubRelease.yml
parameters:
isPreRelease: ${{ parameters.preRelease }}
ghReleaseAddChangeLog: ${{ parameters.ghReleaseAddChangeLog }}
tagName: ${{ parameters.ghTagPrefix }}$(SetPublisherAndVersion.version)
- template: publish.yml
parameters:
azureSubscription: ${{ parameters.azureSubscription }}
buildPlatforms: ${{ parameters.buildPlatforms }}
manifestName: ${{ parameters.manifestName }}
signatureName: ${{ parameters.signatureName }}
publishFolder: ${{ parameters.publishFolder }}
preRelease: ${{ parameters.preRelease }}