-
Notifications
You must be signed in to change notification settings - Fork 105
Expand file tree
/
Copy pathpublish.yml
More file actions
173 lines (153 loc) · 8.26 KB
/
publish.yml
File metadata and controls
173 lines (153 loc) · 8.26 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
# Template (steps): PublishMarketplace for VS Code extension
# Publishes platform-specific VSIX packages to the VS Code Marketplace.
# Iterates over buildPlatforms to publish each platform's signed artifacts.
#
# Usage (example inside a stage job):
# steps:
# - template: build/templates/publish.yml@self
# parameters:
# azureSubscription: PublishServiceConnectionWithManagedIdentity
# buildPlatforms:
# - name: Linux
# vsceTarget: ''
# - name: Linux
# vsceTarget: linux-arm64
# manifestName: extension.manifest
# signatureName: extension.signature.p7s
# publishFolder: extension
# preRelease: true
#
# Notes:
# - Azure DevOps Marketplace resource GUID (499b84ac-1321-427f-aa17-267ca6975798) is hardcoded in publish script.
# - This uses Managed Identity via AzureCLI@2 to acquire an AAD token and passes it as a PAT.
# - Requires extension artifacts already signed (signature file present).
# - Node & vsce expected to be prepared by parent pipeline; omit local installation here.
# - Artifacts are expected at: $(Build.ArtifactStagingDirectory)/publishFolder/{platform}/
parameters:
- name: azureSubscription
type: string
- name: buildPlatforms
type: object
displayName: 'List of platforms to publish'
- name: manifestName
type: string
default: extension.manifest
- name: signatureName
type: string
default: extension.signature.p7s
- name: publishFolder
type: string
default: extension
- name: preRelease
type: boolean
default: false
- name: enabledApiProposalsJson
type: string
default: ''
steps:
# Node & vsce expected to be prepared by parent pipeline; omit local installation.
# Assumes files already present at $(Build.ArtifactStagingDirectory)/publishFolder/{platform}/
# Step 1: Acquire token only (store secret variable MarketplaceAADToken)
- task: AzureCLI@2
displayName: Acquire Marketplace AAD token
inputs:
azureSubscription: ${{ parameters.azureSubscription }}
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
$resource = "499b84ac-1321-427f-aa17-267ca6975798"
Write-Host "Acquiring AAD token for resource: $resource"
az rest -u https://app.vssps.visualstudio.com/_apis/profile/profiles/me --resource $resource | Out-Null
$aadToken = az account get-access-token --query accessToken --resource $resource -o tsv
if (-not $aadToken) { Write-Error 'Failed to acquire AAD token.'; exit 1 }
Write-Host "##vso[task.setvariable variable=MarketplaceAADToken;isSecret=true]$aadToken"
Write-Host "Token stored in secret variable MarketplaceAADToken"
# Step 2: Publish each platform
- ${{ each platform in parameters.buildPlatforms }}:
- task: PowerShell@2
displayName: "Publish extension (${{ coalesce(platform.vsceTarget, 'universal') }})"
env:
EnabledApiProposalsJson: ${{ parameters.enabledApiProposalsJson }}
inputs:
targetType: inline
script: |
$aadToken = "$(MarketplaceAADToken)"
if (-not $aadToken) { Write-Error 'MarketplaceAADToken is empty (token acquisition failed).'; exit 1 }
$platformFolder = "${{ coalesce(platform.vsceTarget, 'universal') }}"
$root = "$(Build.ArtifactStagingDirectory)/${{ parameters.publishFolder }}/$platformFolder"
Write-Host "Publishing platform: $platformFolder"
Write-Host "Artifact folder: $root"
if (-not (Test-Path $root)) { Write-Error "Platform folder not found: $root"; exit 1 }
# Find VSIX file dynamically
$vsixFile = Get-ChildItem -Path $root -Filter "*.vsix" | Select-Object -First 1
if (-not $vsixFile) { Write-Error "No VSIX file found in: $root"; exit 1 }
$vsixPath = $vsixFile.FullName
$manifestPath = Join-Path $root "${{ parameters.manifestName }}"
$signaturePath = Join-Path $root "${{ parameters.signatureName }}"
Write-Host "VSIX Path: $vsixPath"
Write-Host "Manifest Path: $manifestPath"
Write-Host "Signature Path: $signaturePath"
if (-not (Test-Path $manifestPath)) { Write-Error "Manifest file not found: $manifestPath"; exit 1 }
if (-not (Test-Path $signaturePath)) { Write-Error "Signature file not found: $signaturePath"; exit 1 }
Write-Host "Listing platform folder contents:"
Get-ChildItem $root | Select-Object Name,Length | Format-Table -AutoSize
# If the extension uses proposed APIs, vsce requires explicitly allowing them.
# We expect EnabledApiProposalsJson to be set by an earlier step (e.g. publish-extension.yml).
$allowProposedApisArgs = @()
$enabledApiProposalsJson = $env:EnabledApiProposalsJson
if ([string]::IsNullOrWhiteSpace($enabledApiProposalsJson)) {
Write-Host "EnabledApiProposalsJson is not set; publishing without --allow-proposed-apis."
} else {
try {
$parsedEnabledApiProposals = ConvertFrom-Json -InputObject $enabledApiProposalsJson
$enabledApiProposals = @()
if ($null -ne $parsedEnabledApiProposals) {
foreach ($proposal in @($parsedEnabledApiProposals)) {
if (-not [string]::IsNullOrWhiteSpace([string]$proposal)) {
$enabledApiProposals += [string]$proposal
}
}
}
if ($enabledApiProposals.Count -gt 0) {
Write-Host ("enabledApiProposals (from EnabledApiProposalsJson): " + ($enabledApiProposals -join ', '))
$allowProposedApisArgs = @('--allow-proposed-apis') + $enabledApiProposals
} else {
Write-Host "EnabledApiProposalsJson parsed as empty; no proposed API allowlist flags needed."
}
} catch {
Write-Host "EnabledApiProposalsJson was set but could not be parsed; publishing without --allow-proposed-apis."
}
}
$allowProposedApisDisplay = ($allowProposedApisArgs -join ' ')
if ('${{ parameters.preRelease }}' -eq 'True') {
Write-Host 'Publishing as pre-release'
$displayCmd = "Executing: npx @vscode/vsce@latest publish --pat *** --packagePath $vsixPath --manifestPath $manifestPath --signaturePath $signaturePath"
if ($allowProposedApisDisplay) { $displayCmd += " $allowProposedApisDisplay" }
$displayCmd += ' --pre-release'
Write-Host $displayCmd
npx @vscode/vsce@latest publish --pat $aadToken --packagePath $vsixPath --manifestPath $manifestPath --signaturePath $signaturePath $allowProposedApisArgs --pre-release
} else {
Write-Host 'Publishing as stable release'
$displayCmd = "Executing: npx @vscode/vsce@latest publish --pat *** --packagePath $vsixPath --manifestPath $manifestPath --signaturePath $signaturePath"
if ($allowProposedApisDisplay) { $displayCmd += " $allowProposedApisDisplay" }
Write-Host $displayCmd
npx @vscode/vsce@latest publish --pat $aadToken --packagePath $vsixPath --manifestPath $manifestPath --signaturePath $signaturePath $allowProposedApisArgs
}
if ($LASTEXITCODE -ne 0) {
Write-Error "vsce publish failed for $platformFolder with exit code $LASTEXITCODE"
exit $LASTEXITCODE
}
Write-Host "Successfully published $platformFolder"
# Step 3: Post-publish summary
- task: PowerShell@2
displayName: Post-publish summary
inputs:
targetType: inline
script: |
Write-Host 'Published extension artifacts by platform:'
$root = "$(Build.ArtifactStagingDirectory)/${{ parameters.publishFolder }}"
Get-ChildItem $root -Directory | ForEach-Object {
Write-Host "`nPlatform: $($_.Name)"
Get-ChildItem $_.FullName -File | Select-Object Name,Length | Format-Table -AutoSize
}
Write-Host "`nPre-release parameter: ${{ parameters.preRelease }}"