1+ <#
2+ The script downloads signed build artifacts to a local machine and uploads them to the specified release.
3+
4+ Note: Non-MSFT users do not have permissions to execute this script successfully.
5+
6+ Prerequisites:
7+ - GitHub CLI installed on the machine
8+ - Azure CLI installed on the machine
9+ - The azure-devops extension for Azure CLI installed
10+ - Completed login procecures for both Azure CLI and GH CLI
11+
12+ Parameters:
13+ - WorkingDir - Directory used for temporary work. Contents will be deleted.
14+ - TagName - The tag name of the GitHub release release.
15+ - BuildId - Set it to a DevOps build ID to use a specific signed build instead of the latest.
16+
17+ #>
18+ [CmdletBinding ()]
19+ param (
20+ [Parameter (Mandatory = $true )]
21+ [string ] $WorkingDir ,
22+
23+ [Parameter (Mandatory = $true )]
24+ [string ] $TagName ,
25+
26+ [Parameter (Mandatory = $false )]
27+ [int ] $BuildId
28+ )
29+
30+ $ErrorActionPreference = ' Stop' ;
31+
32+ $org = ' https://dev.azure.com/msazure/' ;
33+ $project = ' One' ;
34+ $pipelineName = ' BicepMirror-Official'
35+
36+ $artifacts = @ (
37+ @ {
38+ buildArtifactName = ' drop_build_bicep_linux' ;
39+ assets = @ (
40+ @ {
41+ assetName = ' bicep-linux-x64' ;
42+ relativePath = ' bicep-Release-linux-x64/bicep' ;
43+ }
44+ );
45+ },
46+ @ {
47+ buildArtifactName = ' drop_build_bicep_osx' ;
48+ assets = @ (
49+ @ {
50+ assetName = ' bicep-osx-x64' ;
51+ relativePath = ' bicep-Release-osx-x64/bicep' ;
52+ }
53+ );
54+ },
55+ @ {
56+ buildArtifactName = ' drop_build_bicep_windows' ;
57+ assets = @ (
58+ @ {
59+ assetName = ' bicep-setup-win-x64.exe' ;
60+ relativePath = ' bicep-setup-win-x64/bicep-setup-win-x64.exe' ;
61+ },
62+ @ {
63+ assetName = ' bicep-win-x64.exe' ;
64+ relativePath = ' bicep-Release-win-x64/bicep.exe' ;
65+ }
66+ );
67+ zipAssets = @ (
68+ @ {
69+ assetName = ' bicep-langserver.zip' ;
70+
71+ # trailing asterisk prevents the bicep.LangServer from becoming the root directory in the generated .zip file
72+ relativePath = ' bicep.LangServer/*' ;
73+ }
74+ )
75+ },
76+ @ {
77+ buildArtifactName = ' drop_build_vsix' ;
78+ assets = @ (
79+ @ {
80+ assetName = ' vscode-bicep.vsix' ;
81+ relativePath = ' vscode-bicep\vscode-bicep.vsix' ;
82+ }
83+ );
84+ }
85+ )
86+
87+ Write-Output " Removing working dir..." ;
88+ if (Test-Path - Path $WorkingDir )
89+ {
90+ Remove-Item - Path $WorkingDir - Recurse - Force
91+ }
92+
93+ Write-Output " Creating working dir..." ;
94+ New-Item - ItemType Directory - Path $WorkingDir - Force;
95+
96+ Write-Output " Creating asset dir..." ;
97+ $assetDir = Join-Path - Path $WorkingDir - ChildPath ' __assets' ;
98+ New-Item - ItemType Directory - Path $assetDir - Force;
99+
100+ Write-Output " Resolving build definition..." ;
101+ $buildDefinition = az pipelines show -- org $org -- project $project -- name $pipelineName | ConvertFrom-Json ;
102+
103+ if ($BuildId )
104+ {
105+ # TODO we can probably make this better by searching for a specific version instead of build ID
106+ # get specific build
107+ Write-Output " Resolving build by ID..." ;
108+ $build = az pipelines runs show -- org $org -- project $project -- id $BuildId | ConvertFrom-Json ;
109+
110+ # the build could be for any pipeline
111+ if ($build.definition.id -ne $buildDefinition.id ) {
112+ Write-Error " The specified Build ID '$BuildId ' belongs to build definition '$ ( $build.definition.name ) '. Expected the '$ ( $buildDefinition.name ) ' build definition instead." ;
113+ }
114+ }
115+ else
116+ {
117+ # get latest build
118+ Write-Output " Resolving latest build..." ;
119+ $build = (az pipelines runs list -- org $org -- project $project -- pipeline- ids $buildDefinition.id -- top 1 | ConvertFrom-Json )[0 ];
120+ }
121+
122+ Write-Output " Getting artifact URLs..." ;
123+ $buildArtifacts = az pipelines runs artifact list -- org $org -- project $project -- run- id $build.id | ConvertFrom-Json ;
124+
125+ foreach ($artifact in $artifacts )
126+ {
127+ Write-Output " Processing artifact $ ( $artifact.buildArtifactName ) ..." ;
128+
129+ $artifactDownloadPath = Join-Path - Path $WorkingDir - ChildPath $artifact.buildArtifactName ;
130+ $buildArtifact = $buildArtifacts | Where-Object { $_.name -eq $artifact.buildArtifactName };
131+
132+ if ($buildArtifact )
133+ {
134+ # downloads and unzips to the specified directory
135+ az pipelines runs artifact download -- org $org -- project $project -- artifact- name $artifact.buildArtifactName -- path $artifactDownloadPath -- run- id $build.id
136+
137+ foreach ($asset in $artifact.assets ) {
138+ Write-Output " Processing file asset $ ( $asset.assetName ) ..." ;
139+
140+ # we need to rename the files before uploading to the release (we have multiple files called "bicep", for example)
141+ $assetFilePath = Join-Path $artifactDownloadPath - ChildPath $asset.relativePath ;
142+ $assetUploadPath = Join-Path - Path $assetDir - ChildPath $asset.assetName ;
143+ Copy-Item - Path $assetFilePath - Destination $assetUploadPath ;
144+
145+ gh release upload $TagName $assetUploadPath -- clobber
146+ }
147+
148+ foreach ($zipAsset in $artifact.zipAssets )
149+ {
150+ Write-Output " Processing zip asset $ ( $zipAsset.assetName ) ..." ;
151+
152+ # directories need to be compressed into zip files before upload
153+ $archiveSource = Join-Path - Path $artifactDownloadPath - ChildPath $zipAsset.relativePath ;
154+ $assetUploadPath = Join-Path - Path $assetDir - ChildPath $zipAsset.assetName ;
155+ Compress-Archive - Path $archiveSource - DestinationPath $assetUploadPath - CompressionLevel Optimal;
156+
157+ gh release upload $TagName $assetUploadPath -- clobber
158+ }
159+ }
160+ else
161+ {
162+ Write-Warning " The artifact '$ ( $artifact.buildArtifactName ) ' is not present in the specified build." ;
163+ }
164+ }
0 commit comments