Skip to content

Commit d8bd489

Browse files
committed
.azure-pipelines/release.yml: add macOS builds
Add macOS release build definitions on Azure Pipelines. Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
1 parent ca73c15 commit d8bd489

1 file changed

Lines changed: 246 additions & 0 deletions

File tree

.azure-pipelines/release.yml

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,34 @@ 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
3957
# - esrpTenantId
4058
# - esrpKeyVaultName
4159
# - esrpSignReqCertName
60+
# - appleTeamId
4261

4362
extends:
4463
template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelines
@@ -210,3 +229,230 @@ extends:
210229
}
211230
]
212231
232+
#
233+
# macOS build jobs
234+
#
235+
- ${{ each dim in parameters.macos_matrix }}:
236+
- job: ${{ dim.id }}
237+
displayName: ${{ dim.jobName }}
238+
pool:
239+
name: ${{ dim.pool }}
240+
image: ${{ dim.image }}
241+
os: ${{ dim.os }}
242+
variables:
243+
version: $[stageDependencies.prebuild.vars.outputs['version.value']]
244+
templateContext:
245+
outputs:
246+
- output: pipelineArtifact
247+
targetPath: '$(Build.ArtifactStagingDirectory)/payload'
248+
artifactName: '${{ dim.runtime }}_payload'
249+
- output: pipelineArtifact
250+
targetPath: '$(Build.ArtifactStagingDirectory)/symbols'
251+
artifactName: '${{ dim.runtime }}_symbols'
252+
- output: pipelineArtifact
253+
targetPath: '$(Build.ArtifactStagingDirectory)/installers'
254+
artifactName: '${{ dim.runtime }}_installers'
255+
steps:
256+
- checkout: self
257+
- task: UseDotNet@2
258+
displayName: 'Use .NET 8 SDK'
259+
inputs:
260+
packageType: sdk
261+
version: '8.x'
262+
- task: Bash@3
263+
displayName: 'Build payload'
264+
inputs:
265+
targetType: filePath
266+
filePath: './src/osx/Installer.Mac/layout.sh'
267+
arguments: |
268+
--runtime="${{ dim.runtime }}" \
269+
--configuration="Release" \
270+
--output="$(Build.ArtifactStagingDirectory)/payload" \
271+
--symbol-output="$(Build.ArtifactStagingDirectory)/symbols_raw"
272+
- task: ArchiveFiles@2
273+
displayName: 'Archive symbols'
274+
inputs:
275+
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/symbols_raw'
276+
includeRootFolder: false
277+
archiveType: tar
278+
tarCompression: gz
279+
archiveFile: '$(Build.ArtifactStagingDirectory)/symbols/gcm-${{ dim.runtime }}-$(version)-symbols.tar.gz'
280+
- task: AzureKeyVault@2
281+
displayName: 'Download developer certificate'
282+
inputs:
283+
azureSubscription: '$(esrpMIConnectionName)'
284+
keyVaultName: '$(esrpKeyVaultName)'
285+
secretsFilter: 'mac-developer-certificate,mac-developer-certificate-password'
286+
- task: Bash@3
287+
displayName: 'Import developer certificate'
288+
inputs:
289+
targetType: inline
290+
script: |
291+
# Create and unlock a keychain for the developer certificate
292+
security create-keychain -p pwd $(Agent.TempDirectory)/buildagent.keychain
293+
security default-keychain -s $(Agent.TempDirectory)/buildagent.keychain
294+
security unlock-keychain -p pwd $(Agent.TempDirectory)/buildagent.keychain
295+
296+
echo $(mac-developer-certificate) | base64 -D > $(Agent.TempDirectory)/cert.p12
297+
echo $(mac-developer-certificate-password) > $(Agent.TempDirectory)/cert.password
298+
299+
# Import the developer certificate
300+
security import $(Agent.TempDirectory)/cert.p12 \
301+
-k $(Agent.TempDirectory)/buildagent.keychain \
302+
-P "$(mac-developer-certificate-password)" \
303+
-T /usr/bin/codesign
304+
305+
# Clean up the cert file immediately after import
306+
rm $(Agent.TempDirectory)/cert.p12
307+
308+
# Set ACLs to allow codesign to access the private key
309+
security set-key-partition-list \
310+
-S apple-tool:,apple:,codesign: \
311+
-s -k pwd \
312+
$(Agent.TempDirectory)/buildagent.keychain
313+
- task: Bash@3
314+
displayName: 'Developer sign payload files'
315+
inputs:
316+
targetType: inline
317+
script: |
318+
mkdir -p $(Build.ArtifactStagingDirectory)/tosign/payload
319+
320+
# Copy the files that need signing
321+
pushd $(Build.ArtifactStagingDirectory)/payload
322+
cp ./git-credential-manager *.dylib $(Build.ArtifactStagingDirectory)/tosign/payload
323+
popd
324+
325+
# Developer sign the files
326+
./src/osx/Installer.Mac/codesign.sh \
327+
"$(Build.ArtifactStagingDirectory)/tosign/payload" \
328+
"$(appleTeamId)" \
329+
"./src/osx/Installer.Mac/entitlements.xml"
330+
# ESRP code signing for macOS requires the files be packaged in a zip file for submission
331+
- task: ArchiveFiles@2
332+
displayName: 'Archive files for signing'
333+
inputs:
334+
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/tosign/payload'
335+
includeRootFolder: false
336+
archiveType: zip
337+
archiveFile: '$(Build.ArtifactStagingDirectory)/tosign/payload.zip'
338+
- task: EsrpCodeSigning@5
339+
condition: and(succeeded(), eq('${{ parameters.esrp }}', true))
340+
displayName: 'Sign payload'
341+
inputs:
342+
connectedServiceName: '$(esrpAppConnectionName)'
343+
useMSIAuthentication: true
344+
appRegistrationClientId: '$(esrpClientId)'
345+
appRegistrationTenantId: '$(esrpTenantId)'
346+
authAkvName: '$(esrpKeyVaultName)'
347+
authSignCertName: '$(esrpSignReqCertName)'
348+
serviceEndpointUrl: '$(esrpEndpointUrl)'
349+
folderPath: '$(Build.ArtifactStagingDirectory)/tosign'
350+
pattern: 'payload.zip'
351+
useMinimatch: true
352+
signConfigType: inlineSignParams
353+
inlineOperation: |
354+
[
355+
{
356+
"KeyCode": "CP-401337-Apple",
357+
"OperationCode": "MacAppDeveloperSign",
358+
"ToolName": "sign",
359+
"ToolVersion": "1.0",
360+
"Parameters": {
361+
"Hardening": "Enable"
362+
}
363+
}
364+
]
365+
# Extract signed files, overwriting the unsigned files, ready for packaging
366+
- task: Bash@3
367+
displayName: 'Extract signed payload files'
368+
inputs:
369+
targetType: inline
370+
script: |
371+
unzip -uo $(Build.ArtifactStagingDirectory)/tosign/payload.zip -d $(Build.ArtifactStagingDirectory)/payload
372+
- task: Bash@3
373+
displayName: 'Build component package'
374+
inputs:
375+
targetType: filePath
376+
filePath: './src/osx/Installer.Mac/pack.sh'
377+
arguments: |
378+
--version="$(version)" \
379+
--payload="$(Build.ArtifactStagingDirectory)/payload" \
380+
--output="$(Build.ArtifactStagingDirectory)/pkg/com.microsoft.gitcredentialmanager.component.pkg"
381+
- task: Bash@3
382+
displayName: 'Build installer package'
383+
inputs:
384+
targetType: filePath
385+
filePath: './src/osx/Installer.Mac/dist.sh'
386+
arguments: |
387+
--version="$(version)" \
388+
--runtime="${{ dim.runtime }}" \
389+
--package-path="$(Build.ArtifactStagingDirectory)/pkg" \
390+
--output="$(Build.ArtifactStagingDirectory)/installers/gcm-${{ dim.runtime }}-$(version).pkg"
391+
# ESRP code signing for macOS requires the files be packaged in a zip file first
392+
- task: Bash@3
393+
displayName: 'Prepare installer package for signing'
394+
inputs:
395+
targetType: inline
396+
script: |
397+
mkdir -p $(Build.ArtifactStagingDirectory)/tosign
398+
cd $(Build.ArtifactStagingDirectory)/installers
399+
zip -rX $(Build.ArtifactStagingDirectory)/tosign/installers.zip *.pkg
400+
- task: EsrpCodeSigning@5
401+
condition: and(succeeded(), eq('${{ parameters.esrp }}', true))
402+
displayName: 'Sign installer package'
403+
inputs:
404+
connectedServiceName: '$(esrpAppConnectionName)'
405+
useMSIAuthentication: true
406+
appRegistrationClientId: '$(esrpClientId)'
407+
appRegistrationTenantId: '$(esrpTenantId)'
408+
authAkvName: '$(esrpKeyVaultName)'
409+
authSignCertName: '$(esrpSignReqCertName)'
410+
serviceEndpointUrl: '$(esrpEndpointUrl)'
411+
folderPath: '$(Build.ArtifactStagingDirectory)/tosign'
412+
pattern: 'installers.zip'
413+
useMinimatch: true
414+
signConfigType: inlineSignParams
415+
inlineOperation: |
416+
[
417+
{
418+
"KeyCode": "CP-401337-Apple",
419+
"OperationCode": "MacAppDeveloperSign",
420+
"ToolName": "sign",
421+
"ToolVersion": "1.0",
422+
"Parameters": {}
423+
}
424+
]
425+
- task: EsrpCodeSigning@5
426+
condition: and(succeeded(), eq('${{ parameters.esrp }}', true))
427+
displayName: 'Notarize installer package'
428+
inputs:
429+
connectedServiceName: '$(esrpAppConnectionName)'
430+
useMSIAuthentication: true
431+
appRegistrationClientId: '$(esrpClientId)'
432+
appRegistrationTenantId: '$(esrpTenantId)'
433+
authAkvName: '$(esrpKeyVaultName)'
434+
authSignCertName: '$(esrpSignReqCertName)'
435+
serviceEndpointUrl: '$(esrpEndpointUrl)'
436+
folderPath: '$(Build.ArtifactStagingDirectory)/tosign'
437+
pattern: 'installers.zip'
438+
useMinimatch: true
439+
signConfigType: inlineSignParams
440+
inlineOperation: |
441+
[
442+
{
443+
"KeyCode": "CP-401337-Apple",
444+
"OperationCode": "MacAppNotarize",
445+
"ToolName": "sign",
446+
"ToolVersion": "1.0",
447+
"Parameters": {
448+
"BundleId": "com.microsoft.gitcredentialmanager"
449+
}
450+
}
451+
]
452+
# Extract signed and notarized installer pkg files, overwriting the unsigned files, ready for upload
453+
- task: Bash@3
454+
displayName: 'Extract signed installer package'
455+
inputs:
456+
targetType: inline
457+
script: |
458+
unzip -uo $(Build.ArtifactStagingDirectory)/tosign/installers.zip -d $(Build.ArtifactStagingDirectory)/installers

0 commit comments

Comments
 (0)