GoogleApisForiOSComponents/.ci/build.yml

382 строки
20 KiB
YAML

parameters:
# job parameters
name: 'build' # the name of the build job for dependency purposes
displayName: 'Build' # the human name of the job
timeoutInMinutes: 60 # the timeout in minutes
dependsOn: [] # any jobs this job depends on
masterBranchName: 'main' # the "master" branch that should be used - can be something other than "master"
installAppleCertificates: 'true' # whether or not to install the Apple certificates and provisioning profiles
areaPath: '' # the areaPath to log any issues
runChecks: 'true'
continueOnError: 'false'
publishJob: '' # the job to use as the source of the 'nuget' artifact: '', 'windows', 'macos', 'linux'
publishOutputSuffix: '' # the artifact suffix to use when publishing the output folder
signListPath: 'SignList.xml' # the path to the SignList.xml to copy into the nuget artifact for signing
# job software version parameters
macosImage: 'macOS-12' # the name of the macOS VM image
# 20211121
# macOS-latest = macOS-10.15
# macOS-11 required for XCode 13.1
mono: 'Latest' # the version of mono to use
xcode: '14.0.1' # the version of Xcode to use
cake: '0.33.0' # the version of Cake to use
apiTools: '1.3.4' # the version of the api-tools CLI to use
xharness: '1.0.0-prerelease.20602.1'
tools: [] # a list of any additional .NET Core tools needed
cakeTemplatesBranch: 'main' # the branch of XamarinComponents that has the templates
# build parameters
buildType: 'basic' # the type of build: 'basic', 'manifest', 'directories', 'none'
steps: [] # the steps to use when building, typically for 'none'
verbosity: 'normal' # the build verbosity: 'minimal', 'normal', 'diagnostic'
configuration: 'Release' # the build configuration: 'Debug', 'Release'
validPackagePrefixes: [ 'Xamarin', 'Mono' ] # any NuGet prefixes that should pass validation
artifactsPath: 'output' # the path to the NuGet packages that need to be signed, verified and published
# basic cake build parameters
cakeTarget: 'ci' # [basic] the Cake target to run (defaults to 'ci')
cakeFile: 'build.cake' # [basic] the path to the build.cake file (can be any filename)
cakeExtraArgs: '' # [basic] any additional cake CLI arguments
# manifest-based build parameters
forceBuild: 'false' # [manifest, directories] whether or not to force the build
namesFilter: '' # [manifest, directories] the names of the items to build
targetsFilter: 'ci' # [manifest, directories] the targets of the items to build
runCodeQL: 'false'
tsaOptionsPath: '$(Build.SourcesDirectory)/.ci/tsaoptions.json'
jobs:
- job: ${{ parameters.name }}
displayName: ${{ parameters.displayName }}
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
continueOnError: ${{ eq(parameters.continueOnError, 'true') }}
dependsOn: ${{ parameters.dependsOn }}
variables:
Codeql.Enabled: ${{ parameters.runCodeQL }}
Codeql.TSAEnabled: true
Codeql.TSAOptionsPath: ${{ parameters.tsaOptionsPath }}
pool:
vmImage: ${{ parameters.macosImage }}
steps:
- checkout: self
# before the build starts, make sure the tooling is as expected
- bash: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh ${{ parameters.mono }}
displayName: 'Switch to the latest Xamarin SDK'
- bash: echo '##vso[task.setvariable variable=MD_APPLE_SDK_ROOT;]'/Applications/Xcode_${{ parameters.xcode }}.app;sudo xcode-select --switch /Applications/Xcode_${{ parameters.xcode }}.app/Contents/Developer
displayName: 'Switch to the latest Xcode'
- ${{ if eq(parameters.installAppleCertificates, 'true') }}:
- task: InstallAppleProvisioningProfile@1
displayName: 'Install the iOS provisioning profile'
inputs:
provProfileSecureFile: 'Components iOS Provisioning.mobileprovision'
- task: InstallAppleProvisioningProfile@1
displayName: 'Install the macOS provisioning profile'
inputs:
provProfileSecureFile: 'Components Mac Provisioning.mobileprovision'
- task: InstallAppleProvisioningProfile@1
displayName: 'Install the tvOS provisioning profile'
inputs:
provProfileSecureFile: 'Components tvOS Provisioning.mobileprovision'
- task: InstallAppleCertificate@2
displayName: 'Install the iOS certificate'
inputs:
certSecureFile: 'Components iOS Certificate.p12'
- task: InstallAppleCertificate@2
displayName: 'Install the macOS certificate'
inputs:
certSecureFile: 'Components Mac Certificate.p12'
- bash: echo '##vso[task.setvariable variable=PATH;]'$PATH:$HOME/.dotnet/tools
displayName: 'Add ~/.dotnet/tools to the PATH environment variable'
# Cake v0.33.0 uses this version
- task: UseDotNet@2
displayName: Install .NET 2.1.818
inputs:
version: '2.1.818'
- task: UseDotNet@2
displayName: Install .NET $(DotNetVersion)
inputs:
version: $(DotNetVersion)
- pwsh: |
dotnet workload install ios --verbosity diag --from-rollback-file https://maui.blob.core.windows.net/metadata/rollbacks/6.0.4xx.json --source $(Dotnet6Source) --source $(NuGetOrgSource)
displayName: Install .NET 6 iOS Workload
- pwsh: |
dotnet tool update -g api-tools --version ${{ parameters.apiTools }}
dotnet tool update -g cake.tool --version ${{ parameters.cake }}
dotnet tool update -g Microsoft.DotNet.XHarness.CLI --version ${{ parameters.xharness }} --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json
displayName: 'Install required .NET Core global tools'
- ${{ each tool in parameters.tools }}:
- ${{ each pair in tool }}:
- pwsh: dotnet tool update -g ${{ pair.key }} --version ${{ pair.value }}
displayName: 'Install additional .NET Core global tool: ${{ pair.key }}'
- task: NuGetToolInstaller@1
inputs:
checkLatest: true
displayName: 'Download the latest nuget.exe'
- pwsh: |
$branch = "${{ parameters.cakeTemplatesBranch }}"
if (("$(Build.Repository.Id)" -eq "xamarin/XamarinComponents") -and ("$(System.PullRequest.IsFork)" -eq "False") -and ("$env:FORCE_MASTER_TEMPLATES" -ne "True")) {
if ("$env:SYSTEM_PULLREQUEST_SOURCEBRANCH") {
$branch = "$env:SYSTEM_PULLREQUEST_SOURCEBRANCH"
} else {
$branch = "$(Build.SourceBranch)"
}
}
if ($branch.StartsWith("refs/heads/")) {
$branch = $branch.Substring(11)
}
if ($branch.StartsWith("refs/tags/")) {
$branch = $branch.Substring(10)
}
$root = "https://raw.githubusercontent.com/xamarin/XamarinComponents/$branch/.ci"
Write-Host "##vso[task.setvariable variable=TemplateRootUri]$root"
Write-Host "URL root for templates: $root"
displayName: 'Resolve the cake templates URL'
- pwsh: |
$uri = "$(TemplateRootUri)/validation.cake"
Write-Host "Downloading script from $uri..."
Invoke-WebRequest -Uri $uri -OutFile "validation.cake"
displayName: 'Download the cake script to validate NuGet packages'
- pwsh: |
$uri = "$(TemplateRootUri)/nuget-diff.cake"
Write-Host "Downloading script from $uri..."
Invoke-WebRequest -Uri $uri -OutFile "nuget-diff.cake"
displayName: 'Download the cake script to diff NuGet packages'
# determine the last successful build for "master" branch
- pwsh: |
# determine the "master" branch
$masterBranch = "${{ parameters.masterBranchName }}"
$encodedBranch = [Uri]::EscapeDataString("refs/heads/$masterBranch")
Write-Host "Master branch: $masterBranch"
# determine the "current" branch
$branch = "$(Build.SourceBranch)"
if ("$env:SYSTEM_PULLREQUEST_TARGETBRANCH") {
$branch = "$env:SYSTEM_PULLREQUEST_TARGETBRANCH"
}
if ($branch.StartsWith("refs/heads/")) {
$branch = $branch.Substring(11)
Write-Host "Current branch: $branch"
}
if ($branch.StartsWith("refs/tags/")) {
$branch = $branch.Substring(10)
Write-Host "Current tag: $branch"
}
if (($branch -eq $masterBranch) -and ("$(System.PullRequest.IsFork)" -eq "False")) {
Write-Host "Branch is master, fetching last successful build commit..."
$url = "$(System.TeamFoundationCollectionUri)$(System.TeamProjectId)/_apis/build/builds/?definitions=$(System.DefinitionId)&branchName=$encodedBranch&statusFilter=completed&resultFilter=succeeded&api-version=5.0"
Write-Host "URL for last successful master build: $url"
$json = Invoke-RestMethod -Uri $url -Headers @{
Authorization = "Bearer $(System.AccessToken)"
}
Write-Host "JSON response:"
Write-Host "$json"
$lastSuccessfulBuildCommit = try { $json.value[0].sourceVersion; } catch { $null }
}
if ($lastSuccessfulBuildCommit) {
Write-Host "Last successful commit found: $lastSuccessfulBuildCommit"
} else {
$lastSuccessfulBuildCommit = "origin/$masterBranch"
Write-Host "No previously successful build found, using $lastSuccessfulBuildCommit."
}
Write-Host "##vso[task.setvariable variable=GitLastSuccessfulCommit]$lastSuccessfulBuildCommit"
displayName: 'Find the last successful commit'
# the basic build
- ${{ if eq(parameters.buildType, 'basic') }}:
- pwsh: |
Get-Content $MyInvocation.MyCommand.Definition
dotnet cake ${{ parameters.cakeFile }} ${{ parameters.cakeExtraArgs }} `
--gitpreviouscommit="$(GitLastSuccessfulCommit)" `
--gitcommit="$(Build.SourceVersion)" `
--gitbranch="$(Build.SourceBranch)" `
--target="${{ parameters.cakeTarget }}" `
--configuration="${{ parameters.configuration }}" `
--verbosity="${{ parameters.verbosity }}"
displayName: 'Run basic build'
env:
JavaSdkDirectory: $(JAVA_HOME)
RepositoryCommit: $(Build.SourceVersion)
RepositoryBranch: $(Build.SourceBranchName)
RepositoryUrl: $(Build.Repository.Uri)
RepositoryType: "git"
# the directory-based build
- ${{ if eq(parameters.buildType, 'directories') }}:
- pwsh: |
$uri = "$(TemplateRootUri)/build-directories.cake"
Write-Host "Downloading script from $uri..."
Invoke-WebRequest -Uri $uri -OutFile "build-directories.cake"
displayName: 'Download the cake script to build directory-based repositories'
- pwsh: |
Get-Content $MyInvocation.MyCommand.Definition
$force = if ("$env:FORCEBUILD") { "$env:FORCEBUILD" } else { "${{ parameters.forceBuild }}" }
$names = if ("$env:BUILDDIRECTORYNAMES") { "$env:BUILDDIRECTORYNAMES" } else { "${{ parameters.namesFilter }}" }
$targets = if ("$env:BUILDDIRECTORYTARGETS") { "$env:BUILDDIRECTORYTARGETS" } else { "${{ parameters.targetsFilter }}" }
dotnet cake build-directories.cake `
--gitpreviouscommit="$(GitLastSuccessfulCommit)" `
--gitcommit="$(Build.SourceVersion)" `
--gitbranch="$(Build.SourceBranch)" `
--forcebuild="$force" `
--names "$names" `
--targets="$targets" `
--copyoutputtoroot=true `
--configuration="${{ parameters.configuration }}" `
--verbosity="${{ parameters.verbosity }}"
displayName: 'Run directory build'
env:
JavaSdkDirectory: $(JAVA_HOME)
RepositoryCommit: $(Build.SourceVersion)
RepositoryBranch: $(Build.SourceBranchName)
RepositoryUrl: $(Build.Repository.Uri)
RepositoryType: "git"
# the manifest-based build
- ${{ if eq(parameters.buildType, 'manifest') }}:
- pwsh: |
$uri = "$(TemplateRootUri)/build-manifest.cake"
Write-Host "Downloading script from $uri..."
Invoke-WebRequest -Uri $uri -OutFile "build-manifest.cake"
displayName: 'Download the cake script to build manifest-based repositories'
- pwsh: |
Get-Content $MyInvocation.MyCommand.Definition
$force = if ("$env:FORCEBUILD") { "$env:FORCEBUILD" } else { "${{ parameters.forceBuild }}" }
$names = if ("$env:BUILDMANIFESTNAMES") { "$env:BUILDMANIFESTNAMES" } else { "${{ parameters.namesFilter }}" }
$targets = if ("$env:BUILDMANIFESTTARGETS") { "$env:BUILDMANIFESTTARGETS" } else { "${{ parameters.targetsFilter }}" }
dotnet cake build-manifest.cake `
--gitpreviouscommit="$(GitLastSuccessfulCommit)" `
--gitcommit="$(Build.SourceVersion)" `
--gitbranch="$(Build.SourceBranch)" `
--forcebuild="$force" `
--names "$names" `
--targets="$targets" `
--copyoutputtoroot=true `
--configuration="${{ parameters.configuration }}" `
--verbosity="${{ parameters.verbosity }}"
displayName: 'Run manifest build'
env:
JavaSdkDirectory: $(JAVA_HOME)
RepositoryCommit: $(Build.SourceVersion)
RepositoryBranch: $(Build.SourceBranchName)
RepositoryUrl: $(Build.Repository.Uri)
RepositoryType: "git"
# the build steps, typically for 'none' builds
- ${{ parameters.steps }}
- task: PublishTestResults@2
displayName: Publish the test results (xUnit)
condition: always()
inputs:
testResultsFormat: xUnit
testResultsFiles: 'output/**/*TestResults.xml'
testRunTitle: 'xUnit Test results for $(System.JobName)'
- task: PublishTestResults@2
displayName: Publish the test results (NUnit)
condition: always()
inputs:
testResultsFormat: NUnit
testResultsFiles: 'output/**/*TestResults.xml'
testRunTitle: 'NUnit Test results for $(System.JobName)'
- task: PublishTestResults@2
displayName: Publish the test results (VSTest)
condition: always()
inputs:
testResultsFormat: VSTest
testResultsFiles: 'output/**/*.trx'
testRunTitle: 'VS Test results for $(System.JobName)'
# post-build steps
- pwsh: |
dotnet cake validation.cake `
--namespaces="${{ join(',', parameters.validPackagePrefixes) }}" `
--verbosity="${{ parameters.verbosity }}"
displayName: 'Run NuGet package validation'
- pwsh: |
dotnet cake nuget-diff.cake `
--artifacts="${{ parameters.artifactsPath }}" `
--output="${{ parameters.artifactsPath }}/api-diff" `
--cache="$(Agent.TempDirectory)/api-diff" `
--verbosity="${{ parameters.verbosity }}"
displayName: 'Generate API diff'
# after the build is complete
- pwsh: |
$srcExists = (Test-Path "${{ parameters.signListPath }}")
$dstExists = (Test-Path "${{ parameters.artifactsPath }}\SignList.xml")
if ($srcExists -and !$dstExists) {
Copy-Item "${{ parameters.signListPath }}" "${{ parameters.artifactsPath }}\SignList.xml"
Write-Host "Copied ${{ parameters.signListPath }} to ${{ parameters.artifactsPath }}\SignList.xml"
} elseif (!$srcExists) {
Write-Host "${{ parameters.signListPath }} did not exist, nothing copied."
} elseif ($dstExists) {
Write-Host "${{ parameters.artifactsPath }}\SignList.xml already existed, nothing copied."
}
displayName: 'Copy SignList.xml to the nuget artifact'
- task: PublishBuildArtifacts@1
displayName: 'Publish artifacts'
condition: or(eq('${{ parameters.publishJob }}', ''), eq('${{ parameters.publishJob }}', variables['System.JobName']))
inputs:
PathToPublish: ${{ parameters.artifactsPath }}
ArtifactName: nuget
- task: PublishBuildArtifacts@1
displayName: 'Publish platform artifacts'
condition: always()
inputs:
PathToPublish: output
ArtifactName: output-$(System.JobName)${{ parameters.publishOutputSuffix }}
# run any required checks
- ${{ if eq(variables['System.TeamProject'], 'devdiv') }}:
- task: ComponentGovernanceComponentDetection@0
displayName: 'Run component detection'
condition: and(always(), eq('refs/heads/${{ parameters.masterBranchName }}', variables['Build.SourceBranch']))
inputs:
scanType: 'Register'
verbosity: 'Verbose'
alertWarningLevel: 'High'
- ${{ if and(eq(parameters.runChecks, 'true'), eq(variables['System.TeamProject'], 'devdiv')) }}:
- job: ${{ parameters.name }}_checks
displayName: 'Run required code checks'
condition: or(eq('refs/heads/${{ parameters.masterBranchName }}', variables['Build.SourceBranch']), eq('refs/heads/update-codecheck-tasks', variables['Build.SourceBranch']))
pool:
name: 'Hosted Windows 2019 with VS2019'
steps:
- task: CredScan@3
displayName: 'Analyze source for credentials'
- task: PoliCheck@2
inputs:
targetType: F
targetArgument: '$(Build.SourcesDirectory)'
- task: SdtReport@2
displayName: 'Create security analysis report'
inputs:
GdnExportAllTools: false
GdnExportGdnToolApiScan: false
GdnExportGdnToolArmory: false
GdnExportGdnToolBandit: false
GdnExportGdnToolBinSkim: false
GdnExportGdnToolCodesignValidation: false
GdnExportGdnToolCredScan: true
GdnExportGdnToolCredScanSeverity: 'Default'
GdnExportGdnToolCSRF: false
GdnExportGdnToolDetekt: false
GdnExportGdnToolESLint: false
GdnExportGdnToolFlawfinder: false
GdnExportGdnToolFortifySca: false
GdnExportGdnToolFxCop: false
GdnExportGdnToolGosec: false
GdnExportGdnToolModernCop: false
GdnExportGdnToolPoliCheck: true
GdnExportGdnToolPoliCheckSeverity: 'Default'
GdnExportGdnToolRoslynAnalyzers: false
GdnExportGdnToolPSScriptAnalyzer: false
GdnExportGdnToolSDLNativeRules: false
GdnExportGdnToolSemmle: false
GdnExportGdnToolSpotBugs: false
GdnExportGdnToolTSLint: false
- task: PublishSecurityAnalysisLogs@3
displayName: 'Publish security analysis logs'
- task: TSAUpload@2
continueOnError: true
inputs:
GdnPublishTsaOnboard: true
GdnPublishTsaConfigFile: ${{ parameters.tsaOptionsPath }}
GdnPublishTsaExportedResultsPublishable: true