@@ -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+
3349variables :
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
4362extends :
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