Skip to content

Commit 620c3bf

Browse files
committed
.azure-pipelines/release.yml: add macOS builds
Add macOS release build definitions on Azure Pipelines. Signed-off-by: Matthew John Cheetham <[email protected]>
1 parent 19a6078 commit 620c3bf

File tree

1 file changed

+286
-0
lines changed

1 file changed

+286
-0
lines changed

.azure-pipelines/release.yml

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,27 @@ parameters:
3030
image: win-x86_64-ado1es
3131
os: windows
3232

33+
- name: macos_matrix
34+
type: object
35+
default:
36+
- id: macos_x64
37+
jobName: 'macOS (x64)'
38+
runtime: osx-x64
39+
pool: 'Azure Pipelines'
40+
image: macOS-latest
41+
os: macos
42+
- id: macos_arm64
43+
jobName: 'macOS (ARM64)'
44+
runtime: osx-arm64
45+
pool: 'Azure Pipelines'
46+
image: macOS-latest
47+
os: macos
48+
3349
variables:
3450
- name: 'esrpAppConnectionName'
3551
value: '1ESGitClient-ESRP-App'
52+
- name: 'esrpMIConnectionName'
53+
value: '1ESGitClient-ESRP-MI'
3654
# ESRP signing variables set in the pipeline settings:
3755
# - esrpEndpointUrl
3856
# - esrpClientId
@@ -204,3 +222,271 @@ extends:
204222
Copy-Item "$(Build.ArtifactStagingDirectory)\installers\*.zip" -Destination "$(Build.ArtifactStagingDirectory)\_final"
205223
Copy-Item "$(Build.ArtifactStagingDirectory)\symbols\*.zip" -Destination "$(Build.ArtifactStagingDirectory)\_final"
206224
Copy-Item "$(Build.ArtifactStagingDirectory)\payload" -Destination "$(Build.ArtifactStagingDirectory)\_final" -Recurse
225+
226+
#
227+
# macOS build jobs
228+
#
229+
- ${{ each dim in parameters.macos_matrix }}:
230+
- job: ${{ dim.id }}
231+
displayName: ${{ dim.jobName }}
232+
pool:
233+
name: ${{ dim.pool }}
234+
image: ${{ dim.image }}
235+
os: ${{ dim.os }}
236+
templateContext:
237+
outputs:
238+
- output: pipelineArtifact
239+
targetPath: '$(Build.ArtifactStagingDirectory)/_final'
240+
artifactName: '${{ dim.runtime }}'
241+
steps:
242+
- checkout: self
243+
- task: Bash@3
244+
displayName: 'Read version file'
245+
inputs:
246+
targetType: inline
247+
script: |
248+
echo "##vso[task.setvariable variable=version;isReadOnly=true]$(cat ./VERSION | sed -E 's/.[0-9]+$//')"
249+
- task: UseDotNet@2
250+
displayName: 'Use .NET 8 SDK'
251+
inputs:
252+
packageType: sdk
253+
version: '8.x'
254+
- task: Bash@3
255+
displayName: 'Build payload'
256+
inputs:
257+
targetType: filePath
258+
filePath: './src/osx/Installer.Mac/layout.sh'
259+
arguments: |
260+
--runtime="${{ dim.runtime }}" \
261+
--configuration="Release" \
262+
--output="$(Build.ArtifactStagingDirectory)/payload" \
263+
--symbol-output="$(Build.ArtifactStagingDirectory)/symbols_raw"
264+
- task: ArchiveFiles@2
265+
displayName: 'Archive symbols'
266+
inputs:
267+
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/symbols_raw'
268+
includeRootFolder: false
269+
archiveType: tar
270+
tarCompression: gz
271+
archiveFile: '$(Build.ArtifactStagingDirectory)/symbols/gcm-${{ dim.runtime }}-$(version)-symbols.tar.gz'
272+
- task: AzureKeyVault@2
273+
displayName: 'Download developer certificate'
274+
inputs:
275+
azureSubscription: '$(esrpMIConnectionName)'
276+
keyVaultName: '$(esrpKeyVaultName)'
277+
secretsFilter: 'mac-developer-certificate,mac-developer-certificate-password,mac-developer-certificate-identity'
278+
- task: Bash@3
279+
displayName: 'Import developer certificate'
280+
inputs:
281+
targetType: inline
282+
script: |
283+
# Create and unlock a keychain for the developer certificate
284+
security create-keychain -p pwd $(Agent.TempDirectory)/buildagent.keychain
285+
security default-keychain -s $(Agent.TempDirectory)/buildagent.keychain
286+
security unlock-keychain -p pwd $(Agent.TempDirectory)/buildagent.keychain
287+
288+
echo $(mac-developer-certificate) | base64 -D > $(Agent.TempDirectory)/cert.p12
289+
echo $(mac-developer-certificate-password) > $(Agent.TempDirectory)/cert.password
290+
291+
# Import the developer certificate
292+
security import $(Agent.TempDirectory)/cert.p12 \
293+
-k $(Agent.TempDirectory)/buildagent.keychain \
294+
-P "$(mac-developer-certificate-password)" \
295+
-T /usr/bin/codesign
296+
297+
# Clean up the cert file immediately after import
298+
rm $(Agent.TempDirectory)/cert.p12
299+
300+
# Set ACLs to allow codesign to access the private key
301+
security set-key-partition-list \
302+
-S apple-tool:,apple:,codesign: \
303+
-s -k pwd \
304+
$(Agent.TempDirectory)/buildagent.keychain
305+
- task: Bash@3
306+
displayName: 'Developer sign payload files'
307+
inputs:
308+
targetType: inline
309+
script: |
310+
mkdir -p $(Build.ArtifactStagingDirectory)/tosign/payload
311+
312+
# Copy the files that need signing (Mach-o executables and dylibs)
313+
pushd $(Build.ArtifactStagingDirectory)/payload
314+
find . -type f -exec file --mime {} + \
315+
| sed -n '/mach/s/: .*//p' \
316+
| while IFS= read -r f; do
317+
rel="${f#./}"
318+
tgt="$(Build.ArtifactStagingDirectory)/tosign/payload/$rel"
319+
mkdir -p "$(dirname "$tgt")"
320+
cp -- "$f" "$tgt"
321+
done
322+
popd
323+
324+
# Developer sign the files
325+
./src/osx/Installer.Mac/codesign.sh \
326+
"$(Build.ArtifactStagingDirectory)/tosign/payload" \
327+
"$(mac-developer-certificate-identity)" \
328+
"$PWD/src/osx/Installer.Mac/entitlements.xml"
329+
# ESRP code signing for macOS requires the files be packaged in a zip file for submission
330+
- task: ArchiveFiles@2
331+
displayName: 'Archive files for signing'
332+
inputs:
333+
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/tosign/payload'
334+
includeRootFolder: false
335+
archiveType: zip
336+
archiveFile: '$(Build.ArtifactStagingDirectory)/tosign/payload.zip'
337+
- task: EsrpCodeSigning@5
338+
condition: and(succeeded(), eq('${{ parameters.esrp }}', true))
339+
displayName: 'Sign payload'
340+
inputs:
341+
connectedServiceName: '$(esrpAppConnectionName)'
342+
useMSIAuthentication: true
343+
appRegistrationClientId: '$(esrpClientId)'
344+
appRegistrationTenantId: '$(esrpTenantId)'
345+
authAkvName: '$(esrpKeyVaultName)'
346+
authSignCertName: '$(esrpSignReqCertName)'
347+
serviceEndpointUrl: '$(esrpEndpointUrl)'
348+
folderPath: '$(Build.ArtifactStagingDirectory)/tosign'
349+
pattern: 'payload.zip'
350+
useMinimatch: true
351+
signConfigType: inlineSignParams
352+
inlineOperation: |
353+
[
354+
{
355+
"KeyCode": "CP-401337-Apple",
356+
"OperationCode": "MacAppDeveloperSign",
357+
"ToolName": "sign",
358+
"ToolVersion": "1.0",
359+
"Parameters": {
360+
"Hardening": "Enable"
361+
}
362+
}
363+
]
364+
# Extract signed files, overwriting the unsigned files, ready for packaging
365+
- task: Bash@3
366+
displayName: 'Extract signed payload files'
367+
inputs:
368+
targetType: inline
369+
script: |
370+
unzip -uo $(Build.ArtifactStagingDirectory)/tosign/payload.zip -d $(Build.ArtifactStagingDirectory)/payload
371+
- task: Bash@3
372+
displayName: 'Build component package'
373+
inputs:
374+
targetType: filePath
375+
filePath: './src/osx/Installer.Mac/pack.sh'
376+
arguments: |
377+
--version="$(version)" \
378+
--payload="$(Build.ArtifactStagingDirectory)/payload" \
379+
--output="$(Build.ArtifactStagingDirectory)/pkg/com.microsoft.gitcredentialmanager.component.pkg"
380+
- task: Bash@3
381+
displayName: 'Build installer package'
382+
inputs:
383+
targetType: filePath
384+
filePath: './src/osx/Installer.Mac/dist.sh'
385+
arguments: |
386+
--version="$(version)" \
387+
--runtime="${{ dim.runtime }}" \
388+
--package-path="$(Build.ArtifactStagingDirectory)/pkg" \
389+
--output="$(Build.ArtifactStagingDirectory)/installers-presign/gcm-${{ dim.runtime }}-$(version).pkg"
390+
# ESRP code signing for macOS requires the files be packaged in a zip file first
391+
- task: Bash@3
392+
displayName: 'Prepare installer package for signing'
393+
inputs:
394+
targetType: inline
395+
script: |
396+
mkdir -p $(Build.ArtifactStagingDirectory)/tosign
397+
cd $(Build.ArtifactStagingDirectory)/installers-presign
398+
zip -rX $(Build.ArtifactStagingDirectory)/tosign/installers-presign.zip *.pkg
399+
- task: EsrpCodeSigning@5
400+
condition: and(succeeded(), eq('${{ parameters.esrp }}', true))
401+
displayName: 'Sign installer package'
402+
inputs:
403+
connectedServiceName: '$(esrpAppConnectionName)'
404+
useMSIAuthentication: true
405+
appRegistrationClientId: '$(esrpClientId)'
406+
appRegistrationTenantId: '$(esrpTenantId)'
407+
authAkvName: '$(esrpKeyVaultName)'
408+
authSignCertName: '$(esrpSignReqCertName)'
409+
serviceEndpointUrl: '$(esrpEndpointUrl)'
410+
folderPath: '$(Build.ArtifactStagingDirectory)/tosign'
411+
pattern: 'installers-presign.zip'
412+
useMinimatch: true
413+
signConfigType: inlineSignParams
414+
inlineOperation: |
415+
[
416+
{
417+
"KeyCode": "CP-401337-Apple",
418+
"OperationCode": "MacAppDeveloperSign",
419+
"ToolName": "sign",
420+
"ToolVersion": "1.0",
421+
"Parameters": {
422+
"Hardening": "Enable"
423+
}
424+
}
425+
]
426+
# Extract signed installer, overwriting the unsigned installer
427+
- task: Bash@3
428+
displayName: 'Extract signed installer package'
429+
inputs:
430+
targetType: inline
431+
script: |
432+
unzip -uo $(Build.ArtifactStagingDirectory)/tosign/installers-presign.zip -d $(Build.ArtifactStagingDirectory)/installers
433+
- task: Bash@3
434+
displayName: 'Prepare installer package for notarization'
435+
inputs:
436+
targetType: inline
437+
script: |
438+
mkdir -p $(Build.ArtifactStagingDirectory)/tosign
439+
cd $(Build.ArtifactStagingDirectory)/installers
440+
zip -rX $(Build.ArtifactStagingDirectory)/tosign/installers.zip *.pkg
441+
- task: EsrpCodeSigning@5
442+
condition: and(succeeded(), eq('${{ parameters.esrp }}', true))
443+
displayName: 'Notarize installer package'
444+
inputs:
445+
connectedServiceName: '$(esrpAppConnectionName)'
446+
useMSIAuthentication: true
447+
appRegistrationClientId: '$(esrpClientId)'
448+
appRegistrationTenantId: '$(esrpTenantId)'
449+
authAkvName: '$(esrpKeyVaultName)'
450+
authSignCertName: '$(esrpSignReqCertName)'
451+
serviceEndpointUrl: '$(esrpEndpointUrl)'
452+
folderPath: '$(Build.ArtifactStagingDirectory)/tosign'
453+
pattern: 'installers.zip'
454+
useMinimatch: true
455+
signConfigType: inlineSignParams
456+
inlineOperation: |
457+
[
458+
{
459+
"KeyCode": "CP-401337-Apple",
460+
"OperationCode": "MacAppNotarize",
461+
"ToolName": "sign",
462+
"ToolVersion": "1.0",
463+
"Parameters": {
464+
"BundleId": "com.microsoft.gitcredentialmanager"
465+
}
466+
}
467+
]
468+
# Extract signed and notarized installer pkg files, overwriting the unsigned files, ready for upload
469+
- task: Bash@3
470+
displayName: 'Extract signed and notarized installer package'
471+
inputs:
472+
targetType: inline
473+
script: |
474+
unzip -uo $(Build.ArtifactStagingDirectory)/tosign/installers.zip -d $(Build.ArtifactStagingDirectory)/installers
475+
- task: ArchiveFiles@2
476+
displayName: 'Archive signed payload'
477+
inputs:
478+
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/payload'
479+
includeRootFolder: false
480+
archiveType: tar
481+
tarCompression: gz
482+
archiveFile: '$(Build.ArtifactStagingDirectory)/installers/gcm-${{ dim.runtime }}-$(version).tar.gz'
483+
- task: Bash@3
484+
displayName: 'Collect artifacts for publishing'
485+
inputs:
486+
targetType: inline
487+
script: |
488+
mkdir -p $(Build.ArtifactStagingDirectory)/_final
489+
cp $(Build.ArtifactStagingDirectory)/installers/*.pkg $(Build.ArtifactStagingDirectory)/_final
490+
cp $(Build.ArtifactStagingDirectory)/installers/*.tar.gz $(Build.ArtifactStagingDirectory)/_final
491+
cp $(Build.ArtifactStagingDirectory)/symbols/*.tar.gz $(Build.ArtifactStagingDirectory)/_final
492+
cp -r $(Build.ArtifactStagingDirectory)/payload $(Build.ArtifactStagingDirectory)/_final

0 commit comments

Comments
 (0)